From 69cf50ca1ce11e8a656f8f05dffe28594d1e3ac2 Mon Sep 17 00:00:00 2001 From: Sedef Date: Mon, 22 Mar 2021 01:09:29 -0700 Subject: [PATCH 1/2] Add multitenancy docs --- docs/book/src/SUMMARY_PREFIX.md | 1 + docs/book/src/topics/multitenancy.md | 271 +++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 docs/book/src/topics/multitenancy.md diff --git a/docs/book/src/SUMMARY_PREFIX.md b/docs/book/src/SUMMARY_PREFIX.md index ee20c02d7f..73848dd8bf 100644 --- a/docs/book/src/SUMMARY_PREFIX.md +++ b/docs/book/src/SUMMARY_PREFIX.md @@ -7,6 +7,7 @@ - [Using clusterawsadm to fulfill prerequisites](./topics/using-clusterawsadm-to-fulfill-prerequisites.md) - [Accessing EC2 instances](./topics/accessing-ec2-instances.md) - [Machine Pools](./topics/machinepools.md) + - [Multi-tenancy](./topics/multitenancy.md) - [EKS Support](./topics/eks/index.md) - [Prerequisites](./topics/eks/prerequisites.md) - [Enabling EKS Support](./topics/eks/enabling.md) diff --git a/docs/book/src/topics/multitenancy.md b/docs/book/src/topics/multitenancy.md new file mode 100644 index 0000000000..bc17e6a04a --- /dev/null +++ b/docs/book/src/topics/multitenancy.md @@ -0,0 +1,271 @@ +# Multi-tenancy + +Starting from v0.6.5, single controller multi-tenancy is supported that allows using a different AWS Identity for each workload cluster. +For details, see the [multi-tenancy proposal](https://github.com/kubernetes-sigs/cluster-api-provider-aws/blob/master/docs/proposal/20200506-single-controller-multitenancy.md). + + +For multi-tenancy support, a reference field (`identityRef`) is added to `AWSCluster`, which describes the identity to be used when reconciling the cluster. + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSCluster +metadata: + name: "test" + namespace: "test" +spec: + region: "eu-west-1" + identityRef: + kind: + name: +``` + +Identity resources are used to describe IAM identities that will be used during reconciliation. +There are three identity types: AWSClusterControllerIdentity, AWSClusterStaticIdentity, and AWSClusterRoleIdentity. +Once an IAM identity is created in AWS, the corresponding values should be used to create a identity resource. + +## AWSClusterControllerIdentity + +Before multi-tenancy support, all AWSClusters were being reconciled using the credentials that are used by Cluster API Provider AWS Controllers. +`AWSClusterControllerIdentity` is used to restrict the usage of controller credentials only to AWSClusters that are in `allowedNamespaces`. +Since CAPA controllers use a single set of credentials, `AWSClusterControllerIdentity` is a singleton, and can only be created with `name: default`. + +For backward compatibility, `AutoControllerIdentityCreator` experimental feature is added, which is responsible to create the `AWSClusterControllerIdentity` singleton if it does not exist. +- **Feature status:** Experimental +- **Feature gate:** AutoControllerIdentityCreator=true +`AutoControllerIdentityCreator` creates `AWSClusterControllerIdentity` singleton with empty `allowedNamespaces` (allowedNamespaces: {}) to grant access to the `AWSClusterControllerIdentity` from all namespaces. + +Example: +```yaml +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSCluster +metadata: + name: "test" + namespace: "test" +spec: + region: "eu-west-1" + identityRef: + kind: AWSClusterControllerIdentity + name: default +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterControllerIdentity +metadata: + name: "default" +spec: + allowedNamespaces:{} # matches all namespaces +``` +`AWSClusterControllerIdentity` is immutable to avoid any unwanted overrides to the allowed namespaces, especially during upgrading clusters. + +## AWSClusterIdentityIdentity +`AWSClusterIdentityIdentity` represents static AWS credentials, which are stored in a `Secret`. + +Example: Below, an `AWSClusterIdentityIdentity` is created that allows access to the `AWSClusters` that are in "test" namespace. +The identity credentials that will be used by "test" AWSCluster are stored in "test-account-creds" secret. + + +```yaml +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSCluster +metadata: + name: "test" + namespace: "test" +spec: + region: "eu-west-1" + identityRef: + kind: AWSClusterIdentityIdentity + name: test-account +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterIdentityIdentity +metadata: + name: "test-account" +spec: + secretRef: + name: test-account-creds + namespace: capa-system + allowedNamespaces: + selector: + matchLabels: + ns: "testlabel" +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + cluster.x-k8s.io/ns: "testlabel" + name: "test" +--- +apiVersion: v1 +kind: Secret +metadata: + name: "test-account-creds" + namespace: capa-system +stringData: + accessKeyID: AKIAIOSFODNN7EXAMPLE + secretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY +``` + +## AWSClusterRoleIdentity +`AWSClusterRoleIdentity` allows CAPA to assume a role either in the same or another AWS account, using the STS::AssumeRole API. +The assumed role could be used by the AWSClusters that is in the `allowedNamespaces`. + +Example: +Below, an `AWSClusterRoleIdentity` instance, which will be used by AWSCluster "test", is created. +This role will be assumed by the source identity at runtime. Source identity can be of any identity type. +Role is assumed in the beginning once and after, whenever the assumed role's credentials are expired. + +```yaml +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSCluster +metadata: + name: "test" + namespace: "test" +spec: + region: "eu-west-1" + identityRef: + kind: AWSClusterRoleIdentity + name: test-account-role +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterRoleIdentity +metadata: + name: "test-account-role" +spec: + allowedNamespaces: + list: # allows only "test" namespace to use this identity + "test" + roleARN: "arn:aws:iam::123456789:role/CAPARole" + sourceIdentityRef: + kind: AWSClusterIdentityIdentity + name: test-account-creds +``` + +Nested role assumption is also supported. +Example: Below, "multi-tenancy-nested-role" will be assumed by "multi-tenancy-role", which will be assumed by the "default" `AWSClusterControllerIdentity` + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterRoleIdentity +metadata: + name: multi-tenancy-role +spec: + allowedNamespaces: + list: [] + durationSeconds: 900 # default and min value is 900 seconds + roleARN: arn:aws:iam::11122233344:role/multi-tenancy-role + sessionName: multi-tenancy-role-session + sourceidentityRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: AWSClusterControllerIdentity + name: default +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterRoleIdentity +metadata: + name: multi-tenancy-nested-role +spec: + allowedNamespaces: + list: [] + roleARN: arn:aws:iam::11122233355:role/multi-tenancy-nested-role + sessionName: multi-tenancy-nested-role-session + sourceidentityRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: AWSClusterRoleIdentity + name: multi-tenancy-role +``` + +## Secure Access to Identitys +`allowedNamespaces` field is used to grant access to the namespaces to use Identitys. +Only AWSClusters that are created in one of the Identity's allowed namespaces can use that Identity. +`allowedNamespaces` are defined by providing either a list of namespaces or label selector to select namespaces. + +### Examples + +An empty `allowedNamespaces` indicates that the Identity can be used by all namespaces. + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterControllerIdentity +spec: + allowedNamespaces:{} # matches all namespaces +``` + +Having a nil `list` and a nil `selector` is the same with having an empty `allowedNamespaces` (Identity can be used by all namespaces). + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterControllerIdentity +spec: + allowedNamespaces: + list: nil + selector: nil +``` + +A nil `allowedNamespaces` indicates that the Identity cannot be used from any namespace. + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterControllerIdentity +spec: + allowedNamespaces: # this is same with not providing the field at all or allowedNamespaces: null +``` + +The union of namespaces that are matched by `selector` and the namespaces that are in the `list` is granted access to the identity. +The namespaces that are not in the list and not matching the selector will not have access. + +Nil or empty `list` matches no namespaces. Nil or empty `selector` matches no namespaces. +If `list` is nil and `selector` is empty OR `list` is empty and `selector` is nil, Identity cannot be used from any namespace. +Because in this case, `allowedNamespaces` is not empty or nil, and neither `list` nor `selector` allows any namespaces, so the union is empty. + +```yaml +# Matches no namespaces +allowedNamespaces: + list: [] +``` +```yaml +# Matches no namespaces +allowedNamespaces: + selector: {} +``` +```yaml +# Matches no namespaces +allowedNamespaces: + list: null + selector: {} +``` +```yaml +# Matches no namespaces +allowedNamespaces: + list: [] + selector: {} +``` + +**Important** The default behaviour of an empty label selector is to match all objects, however here we do not follow that behavior to avoid unintended access to the identitys. +This is consistent with core cluster API selectors, e.g., Machine and ClusterResourceSet selectors. The result of matchLabels and matchExpressions are ANDed. + + +In Kubernetes selectors, `matchLabels` and `matchExpressions` are ANDed. +In the example below, list is empty/nil, so does not allow any namespaces and selector matches with only `default` namespace. +Since `list` and `selector` results are ORed, `default` namespace can use this identity. + +```yaml +kind: namespace +metadata: + name: default + labels: + environment: dev +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AWSClusterControllerIdentity +spec: + allowedNamespaces: + list: null # or [] + selector: + matchLabels: + namespace: default + matchExpressions: + - {key: environment, operator: In, values: [dev]} +``` From 5746097b034251e143f90f7a3bc9b7812afb2606 Mon Sep 17 00:00:00 2001 From: Naadir Jeewa Date: Tue, 13 Apr 2021 17:48:24 +0100 Subject: [PATCH 2/2] Update multitenancy proposal --- ...20200506-single-controller-multitenancy.md | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/docs/proposal/20200506-single-controller-multitenancy.md b/docs/proposal/20200506-single-controller-multitenancy.md index 87f0e36d19..3417b35ea5 100644 --- a/docs/proposal/20200506-single-controller-multitenancy.md +++ b/docs/proposal/20200506-single-controller-multitenancy.md @@ -48,7 +48,7 @@ superseded-by: [] - [Controller Changes](#controller-changes) - [Clusterctl changes](#clusterctl-changes) - [Validating webhook changes](#validating-webhook-changes) - - [Principal Type Credential Provider Behaviour](#principal-type-credential-provider-behaviour) + - [Identity Type Credential Provider Behaviour](#identity-type-credential-provider-behaviour) - [Security Model](#security-model) - [Roles](#roles) - [RBAC](#rbac) @@ -57,7 +57,7 @@ superseded-by: [] - [CAPA Controller Requirements](#capa-controller-requirements) - [Alternative Approaches Considered](#alternative-approaches-considered) - [Using only secrets or RoleARN field on AWSCluster](#using-only-secrets-or-rolearn-field-on-awscluster) - - [1:1 mapping one namespace to one AWSPrincipal](#11-mapping-one-namespace-to-one-awsprincipal) + - [1:1 mapping one namespace to one AWSIdentity](#11-mapping-one-namespace-to-one-awsidentity) - [Risks and Mitigations](#risks-and-mitigations) - [Network assumptions are made explicit](#network-assumptions-are-made-explicit) - [Caching and handling refresh of credentials](#caching-and-handling-refresh-of-credentials) @@ -74,7 +74,7 @@ superseded-by: [] ## Glossary -* Principal Type - One of several ways to provide a form of identity that is ultimately resolved to an AWS access key ID, +* Identity Type - One of several ways to provide a form of identity that is ultimately resolved to an AWS access key ID, secret access key and optional session token tuple. * Credential Provider - An implementation of the interface specified in the [AWS SDK for Go][aws-sdk-go-credential-provider]. @@ -108,8 +108,8 @@ the existing behavior with no changes to user configuration required. For large organizations, especially highly-regulated organizations, there is a need to be able to perform separate duties at various levels of infrastructure - permissions, networks and accounts. VPC sharing is a model which provides separation at the AWS account level. Within this model it is appropriate for tooling running within the 'management' account -to manage infrastructure within the 'workload' accounts, which requires a principal in the management account which can -assume a principal within a workload account. For CAPA to be most useful within these organizations it will need to +to manage infrastructure within the 'workload' accounts, which requires a identity in the management account which can +assume a identity within a workload account. For CAPA to be most useful within these organizations it will need to support multi-account models. Some organizations may also delegate the management of clusters to another third-party. In that case, the boundary @@ -155,7 +155,7 @@ clusters in dedicated AWS accounts. The current configuration exists: AWS Account 'management': * Vpc, subnets shared with 'workload' AWS Account * EC2 instance profile linked to the IAM role 'ClusterAPI-Mgmt' -* A management Kubernetes cluster running Cluster API Provider AWS controllers using the 'ClusterAPI-Owner' IAM principal. +* A management Kubernetes cluster running Cluster API Provider AWS controllers using the 'ClusterAPI-Owner' IAM identity. AWS Account 'workload': * Vpc and subnets provided by 'Owner' AWS Account @@ -197,9 +197,9 @@ a single instance of CAPA to cover multiple organisations. FR4. CAPA MUST prevent privilege escalation allowing users to create clusters in AWS accounts they should not be able to. -FR5. CAPA SHOULD support credential refreshing when principal data is modified. +FR5. CAPA SHOULD support credential refreshing when identity data is modified. -FR6. CAPA SHOULD provide validation for principal data submitted by users. +FR6. CAPA SHOULD provide validation for identity data submitted by users. FR7. CAPA COULD support role assumption using OIDC projected volume service account tokens. @@ -279,21 +279,21 @@ AWS accounts whilst preventing privilege escalation as per [FR4](#FR4). Reasons Namespace scoped resources -* `AWSServiceAccountPrincipal` represents the use of a Kubernetes service account for access +* `AWSServiceAccountIdentity` represents the use of a Kubernetes service account for access to AWS using federated identity. Changes to AWSCluster -A new field is added to the `AWSClusterSpec` to reference a principal. We intend to use `corev1.LocalObjectReference` in +A new field is added to the `AWSClusterSpec` to reference a identity. We intend to use `corev1.LocalObjectReference` in order to ensure that the only objects that can be references are either in the same namespace or are scoped to the entire cluster. ```go -// AWSPrincipalKind defines allowed AWS principal types -type AWSPrincipalKind string +// AWSIdentityKind defines allowed AWS identity types +type AWSIdentityKind string type AWSIdentityRef struct { - Kind AWSPrincipalKind `json:"kind"` + Kind AWSIdentityKind `json:"kind"` Name string `json:"name"` } @@ -333,35 +333,35 @@ The `IdentityRef` field will be mutable in order to support `clusterctl move` scenarios where a user instantiates a cluster on their laptop and then makes the cluster self-managed. -Principal CRDs +Identity CRDs Common elements -All AWSCluster*Principal types will have Spec structs with an `AllowedNamespaces` +All AWSCluster*Identity types will have Spec structs with an `AllowedNamespaces` field as follows: ```go type AWSClusterIdentitySpec struct { -// AllowedNamespaces is used to identify which namespaces are allowed to use the principal from. +// AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. // Namespaces can be selected either using an array of namespaces or with label selector. -// An empty allowedNamespaces object indicates that AWSClusters can use this principal from any namespace. +// An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. // If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) -// A namespace should be either in the NamespaceList or match with Selector to use the principal. +// A namespace should be either in the NamespaceList or match with Selector to use the identity. // // +optional AllowedNamespaces *AllowedNamespaces `json:"allowedNamespaces"` } type AllowedNamespaces struct { -// An nil or empty list indicates that AWSClusters cannot use the principal from any namespace. +// An nil or empty list indicates that AWSClusters cannot use the identity from any namespace. // // +optional // +nullable NamespaceList []string `json:"list"` // AllowedNamespaces is a selector of namespaces that AWSClusters can -// use this ClusterPrincipal from. This is a standard Kubernetes LabelSelector, +// use this ClusterIdentity from. This is a standard Kubernetes LabelSelector, // a label query over a set of resources. The result of matchLabels and // matchExpressions are ANDed. // @@ -542,8 +542,8 @@ type AWSClusterRoleIdentity struct { Spec AWSClusterRoleIdentitySpec `json:"spec,omitempty""` } -// AWSClusterIdentityKind defines allowed cluster-scoped AWS principal types -type AWSClusterIdentityKind AWSPrincipalKind +// AWSClusterIdentityKind defines allowed cluster-scoped AWS identity types +type AWSClusterIdentityKind AWSIdentityKind type AWSClusterIdentityReference struct { Kind AWSClusterIdentityKind `json:"kind"` @@ -566,7 +566,7 @@ type AWSClusterRoleIdentitySpec struct { // +kubebuilder:validation:Pattern:=[\w+=,.@:\/-]* ExternalID *string `json:"externalID,omitempty"` - // SourceIdentityRef is a reference to another principal which will be chained to do + // SourceIdentityRef is a reference to another identity which will be chained to do // role assumption. SourceIdentityRef AWSClusterIdentityReference `json:"sourceIdentityRef,omitempty"` } @@ -596,7 +596,7 @@ metadata: name: "test-account-role" spec: allowedNamespaces: - list: # allows only "test" namespace to use this principal + list: # allows only "test" namespace to use this identity "test" roleARN: "arn:aws:iam::123456789:role/CAPARole" # Optional settings @@ -611,7 +611,7 @@ spec: name: test-account-creds ``` -Future implementation: AWSServiceAccountPrincipal +Future implementation: AWSServiceAccountIdentity This would not be implemented in the first instance, but opens the possibility to use Kubernetes service accounts together with `STS::AssumeRoleWithWebIdentity`, supporting [FR7](#FR7). @@ -619,15 +619,15 @@ together with `STS::AssumeRoleWithWebIdentity`, supporting [FR7](#FR7). Definition: ```go -type AWSServiceAccountPrincipal struct { +type AWSServiceAccountIdentity struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // Spec for this AWSServiceAccountPrincipal. - Spec AWSServiceAccountPrincipalSpec `json:"spec,omitempty""` + // Spec for this AWSServiceAccountIdentity. + Spec AWSServiceAccountIdentitySpec `json:"spec,omitempty""` } -type AWSServiceAccountPrincipalSpec struct { +type AWSServiceAccountIdentitySpec struct { AWSRoleSpec // Audience is the intended audience of the token. A recipient of a token @@ -659,7 +659,7 @@ The account owner would be expected to set up an appropriate IAM role with the f "Statement": [ { "Effect": "Allow", - "Principal": { + "Identity": { "Federated": "" }, "Action": "sts:AssumeRoleWithWebIdentity", @@ -686,11 +686,11 @@ metadata: spec: region: "eu-west-1" identityRef: - kind: AWSServiceAccountPrincipal + kind: AWSServiceAccountIdentity name: test-service-account --- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 -kind: AWSServiceAccountPrincipal +kind: AWSServiceAccountIdentity metadata: name: "test-service-account" namespace: "test" @@ -706,10 +706,10 @@ with the requisite parameters and receive a new JWT token to use with `STS::Assu ### Controller Changes -* If identityRef is specified, the CRD is fetched and unmarshalled into a AWS SDK credential.Provider for the principal type. +* If identityRef is specified, the CRD is fetched and unmarshalled into a AWS SDK credential.Provider for the identity type. * The controller will compare the hash of the credential provider against the same secret’s provider in a cache ([NFR 8](#NFR8)). * The controller will take the newer of the two and instantiate AWSClients with the selected credential provider. -* The controller will set an the principal resource as one of the OwnerReferences of the AWSCluster. +* The controller will set an the identity resource as one of the OwnerReferences of the AWSCluster. * The controller and defaulting webhook will default `nil` `identityRef` field in AWSClusters to `AWSClusterControllerIdentity`. This flow is shown below: @@ -721,20 +721,20 @@ This flow is shown below: Today, `clusterctl move` operates by tracking objectreferences within the same namespace, since we are now proposing to use cluster-scoped resources, we will need to add requisite support to clusterctl's object graph to track ownerReferences pointing at cluster-scoped resources, and ensure they are moved. We will naively not delete cluster-scoped resources -during a move, as they maybe referenced across namespaces. Because we will be tracking the AWS Account ID for a given principal, it is expected, that for this proposal, this provides sufficient protection against the possibility of a cluster-scoped -principal after one move, and being copied again. +during a move, as they maybe referenced across namespaces. Because we will be tracking the AWS Account ID for a given identity, it is expected, that for this proposal, this provides sufficient protection against the possibility of a cluster-scoped +identity after one move, and being copied again. #### Validating webhook changes A validating webhook could potentially handle some of the cross-resource validation necessary for the [security model](#security-model) and provide more immediate feedback to end users. However, it would be imperfect. For example, a -change to a `AWSCluster*Principal` could affect the validity of corresponding AWSCluster. +change to a `AWSCluster*Identity` could affect the validity of corresponding AWSCluster. The singleton `AWSClusterControllerIdentity` resource will be immutable to avoid any unwanted overrides to the allowed namespaces, especially during upgrading clusters. -#### Principal Type Credential Provider Behaviour +#### Identity Type Credential Provider Behaviour -Implementations for all principal types will implement the `credentials.Provider` interface in the AWS SDK to support [FR5](#FR5) as well as an +Implementations for all identity types will implement the `credentials.Provider` interface in the AWS SDK to support [FR5](#FR5) as well as an additional function signature to support caching: ```go @@ -748,10 +748,10 @@ type Provider interface { IsExpired() bool } -type AWSPrincipalTypeProvider interface { +type AWSIdentityTypeProvider interface { credentials.Provider // Hash returns a unique hash of the data forming the credentials - // for this principal + // for this identity Hash() (string, error) } ``` @@ -771,7 +771,7 @@ forcing a refresh. The authors have implemented a similar mechanism [based on the Ruby AWS SDK][aws-assume-role]. -This could be further optimised by having the controller maintain a watch on all Secrets matching the principal types. +This could be further optimised by having the controller maintain a watch on all Secrets matching the identity types. Upon receiving an update event, the controller will update lookup the key in the cache and update the relevant provider. This may be implemented as its own interface. Mutexes will ensure in-flight updates are completed prior to SDK calls are made. This would require changes to RBAC, and maintaining a watch on secrets of a specific type will require further @@ -805,11 +805,11 @@ defined above. In most cases, it will be desirable to have all resources be readable by most roles, so instead we'll focus on write access for this model. ##### Write Permissions -| | AWSCluster*Principal | AWSServiceAccountPrincipal | AWS IAM API | Cluster | -| ---------------------------- | -------------------- | -------------------------- | ----------- | ------- | -| Infrastructure Provider | Yes | Yes | Yes | Yes | -| Management Cluster Operators | Yes | Yes | Yes | Yes | -| Workload Cluster Operator | No | Yes | No | Yes | +| | AWSCluster*Identity | AWSServiceAccountIdentity | AWS IAM API | Cluster | +| ---------------------------- | ------------------- | ------------------------- | ----------- | ------- | +| Infrastructure Provider | Yes | Yes | Yes | Yes | +| Management Cluster Operators | Yes | Yes | Yes | Yes | +| Workload Cluster Operator | No | Yes | No | Yes | Because Kubernetes service accounts necessarily encode the namespace into the JWT subject, we can allow workload cluster operators to create their own `AWSServiceAccountIdentities`. Whether they have actual permissions on AWS IAM to set up @@ -821,11 +821,11 @@ The extra configuration options are not possible to control with RBAC. Instead, they will be controlled with configuration fields on GatewayClasses: * **allowedNamespaces**: This field is a selector of namespaces that - Gateways can use this `AWSCluster*Principal` from. This is a standard Kubernetes + Gateways can use this `AWSCluster*Identity` from. This is a standard Kubernetes LabelSelector, a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. CAPA will not support AWSClusters in namespaces outside this selector. An empty selector (default) - indicates that AWSCluster can use this `AWSCluster*Principal` from any namespace. This + indicates that AWSCluster can use this `AWSCluster*Identity` from any namespace. This field is intentionally not a pointer because the nil behavior (no namespaces) is undesirable here. @@ -834,10 +834,10 @@ they will be controlled with configuration fields on GatewayClasses: The CAPA controller will need to: * Populate condition fields on AWSClusters and indicate if it is - compatible with `AWS*Principal`. -* Not implement invalid configuration. Fore example, if a `AWSCluster*Principal` is referenced in + compatible with `AWS*Identity`. +* Not implement invalid configuration. Fore example, if a `AWSCluster*Identity` is referenced in an invalid namespace for it, it should be ignored. -* Respond to changes in `AWS*Principal` configuration that may change. +* Respond to changes in `AWS*Identity` configuration that may change. ### Alternative Approaches Considered @@ -862,13 +862,13 @@ API server KMS. **Downsides** -By allowing workload cluster operators to create the various principals, or referencing them directly in the +By allowing workload cluster operators to create the various identitys, or referencing them directly in the AWSCluster as a field they could potentially escalate privilege when assuming role across AWS accounts as the CAPA controller itself may be running with privileged trust. -#### 1:1 mapping one namespace to one AWSPrincipal +#### 1:1 mapping one namespace to one AWSIdentity -The mapping of a singular AWSPrincipal to a single namespace such that there is a 1:1 mapping +The mapping of a singular AWSIdentity to a single namespace such that there is a 1:1 mapping was considered, via either some implicitly named secret or other metadata on the namespace. **Benefits** @@ -923,7 +923,7 @@ The data changes are additive and optional, except `AWSClusterControllerIdentity `AWSClusterControllerIdentity` singleton instance restricts the usage of controller credentials only from `allowedNamespaces`. AWSClusters that do not have an assigned `IdentityRef` is defaulted to use `AWSClusterControllerIdentity`, hence existing clusters needs to have `AWSClusterControllerIdentity` instance. In order to make existing AWSClusters to continue to reconcile as before, a new controller is added as experimental feature -and gated with **Feature gate:** AutoControllerPrincipalCreator=true. By default, this feature is enabled. This controller creates `AWSClusterControllerIdentity` singleton instance (if missing) that allows all namespaces to use the principal. +and gated with **Feature gate:** AutoControllerIdentityCreator=true. By default, this feature is enabled. This controller creates `AWSClusterControllerIdentity` singleton instance (if missing) that allows all namespaces to use the identity. During v1alpha4 releases, since breaking changes will be allowed, this feature will become obsolete. ## Additional Details