Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/ISSUE_TEMPLATE/testplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,16 @@ connectors are accepted, invalid are rejected with sensible error messages.
- [ ] EC2 Join method in IoT mode with node and auth in different AWS accounts
- [ ] IAM Join method in IoT mode with node and auth in different AWS accounts

### Kubernetes Node Joining
- [ ] Join a Teleport node running in the same Kubernetes cluster via a Kubernetes ProvisionToken

### Cloud Labels
- [ ] Create an EC2 instance with [tags in instance metadata enabled](https://goteleport.com/docs/management/guides/ec2-tags/)
and with tag `foo`: `bar`. Verify that a node running on the instance has label
`aws/foo=bar`.
- [ ] Create an Azure VM with tag `foo`: `bar`. Verify that a node running on the
instance has label `azure/foo=bar`.

### Passwordless

Passwordless requires `tsh` compiled with libfido2 for most operations (apart
Expand Down
21 changes: 21 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1109,8 +1109,12 @@ message ProvisionTokenSpecV2 {
(gogoproto.jsontag) = "suggested_agent_matcher_labels,omitempty",
(gogoproto.customtype) = "Labels"
];
// Kubernetes allows the configuration of options specific to the "kubernetes" join method.
ProvisionTokenSpecV2Kubernetes Kubernetes = 10 [(gogoproto.jsontag) = "kubernetes,omitempty"];
}

// ProvisionTokenSpecV2Github contains the GitHub-specific part of the
// ProvisionTokenSpecV2
message ProvisionTokenSpecV2GitHub {
// Rule includes fields mapped from `lib/githubactions.IDToken`
// Not all fields should be included, only ones that we expect to be useful
Expand Down Expand Up @@ -1151,6 +1155,8 @@ message ProvisionTokenSpecV2GitHub {
string EnterpriseServerHost = 2 [(gogoproto.jsontag) = "enterprise_server_host,omitempty"];
}

// ProvisionTokenSpecV2CircleCI contains the CircleCI-specific part of the
// ProvisionTokenSpecV2
message ProvisionTokenSpecV2CircleCI {
message Rule {
string ProjectID = 1 [(gogoproto.jsontag) = "project_id,omitempty"];
Expand All @@ -1162,6 +1168,21 @@ message ProvisionTokenSpecV2CircleCI {
string OrganizationID = 2 [(gogoproto.jsontag) = "organization_id,omitempty"];
}

// ProvisionTokenSpecV2Kubernetes contains the Kubernetes-specific part of the
// ProvisionTokenSpecV2
message ProvisionTokenSpecV2Kubernetes {
// Rule is a set of properties the Kubernetes-issued token might have to be
// allowed to use this ProvisionToken
message Rule {
// ServiceAccount is the namespaced name of the Kubernetes service account.
// Its format is "namespace:service-account".
string ServiceAccount = 1 [(gogoproto.jsontag) = "service_account,omitempty"];
}
// Allow is a list of Rules, nodes using this token must match one
// allow rule to use this token.
repeated Rule Allow = 1 [(gogoproto.jsontag) = "allow,omitempty"];
}

// StaticTokensV2 implements the StaticTokens interface.
message StaticTokensV2 {
option (gogoproto.goproto_stringer) = false;
Expand Down
41 changes: 41 additions & 0 deletions api/types/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const (
// join method. Documentation regarding the implementation of this can be
// found in lib/circleci
JoinMethodCircleCI JoinMethod = "circleci"
// JoinMethodKubernetes indicates that the node will join with the
// Kubernetes join method. Documentation regarding implementation can be
// found in lib/kubernetestoken
JoinMethodKubernetes JoinMethod = "kubernetes"
)

var JoinMethods = []JoinMethod{
Expand All @@ -55,6 +59,7 @@ var JoinMethods = []JoinMethod{
JoinMethodIAM,
JoinMethodGitHub,
JoinMethodCircleCI,
JoinMethodKubernetes,
}

func ValidateJoinMethod(method JoinMethod) error {
Expand Down Expand Up @@ -235,6 +240,17 @@ func (p *ProvisionTokenV2) CheckAndSetDefaults() error {
if err := providerCfg.checkAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
case JoinMethodKubernetes:
providerCfg := p.Spec.Kubernetes
if providerCfg == nil {
return trace.BadParameter(
`"kubernetes" configuration must be provided for the join method %q`,
JoinMethodKubernetes,
)
}
if err := providerCfg.checkAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
default:
return trace.BadParameter("unknown join method %q", p.Spec.JoinMethod)
}
Expand Down Expand Up @@ -492,3 +508,28 @@ func (a *ProvisionTokenSpecV2CircleCI) checkAndSetDefaults() error {
}
return nil
}

func (a *ProvisionTokenSpecV2Kubernetes) checkAndSetDefaults() error {
if len(a.Allow) == 0 {
return trace.BadParameter(
"the %q join method requires defined kubernetes allow rules",
JoinMethodKubernetes,
)
}
for _, allowRule := range a.Allow {
if allowRule.ServiceAccount == "" {
return trace.BadParameter(
"the %q join method requires kubernetes allow rules with non-empty service account name",
JoinMethodKubernetes,
)
}
if len(strings.Split(allowRule.ServiceAccount, ":")) != 2 {
return trace.BadParameter(
`the %q join method service account rule format is "namespace:service_account", got %q instead`,
JoinMethodKubernetes,
allowRule.ServiceAccount,
)
}
}
return nil
}
57 changes: 57 additions & 0 deletions api/types/provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,63 @@ func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) {
},
expectedErr: &trace.BadParameterError{},
},
{
desc: "kubernetes valid",
token: &ProvisionTokenV2{
Metadata: Metadata{
Name: "test",
},
Spec: ProvisionTokenSpecV2{
Roles: []SystemRole{RoleNode},
JoinMethod: JoinMethodKubernetes,
Kubernetes: &ProvisionTokenSpecV2Kubernetes{
Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{
{
ServiceAccount: "namespace:my-service-account",
},
},
},
},
},
},
{
desc: "kubernetes wrong service account name",
token: &ProvisionTokenV2{
Metadata: Metadata{
Name: "test",
},
Spec: ProvisionTokenSpecV2{
Roles: []SystemRole{RoleNode},
JoinMethod: JoinMethodKubernetes,
Kubernetes: &ProvisionTokenSpecV2Kubernetes{
Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{
{
ServiceAccount: "my-service-account",
},
},
},
},
},
expectedErr: &trace.BadParameterError{},
},
{
desc: "kubernetes allow rule blank",
token: &ProvisionTokenV2{
Metadata: Metadata{
Name: "test",
},
Spec: ProvisionTokenSpecV2{
Roles: []SystemRole{RoleNode},
JoinMethod: JoinMethodKubernetes,
Kubernetes: &ProvisionTokenSpecV2Kubernetes{
Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{
{},
},
},
},
},
expectedErr: &trace.BadParameterError{},
},
}

for _, tc := range testcases {
Expand Down
Loading