Skip to content

Commit 5746097

Browse files
author
Naadir Jeewa
committed
Update multitenancy proposal
1 parent 69cf50c commit 5746097

File tree

1 file changed

+56
-56
lines changed

1 file changed

+56
-56
lines changed

docs/proposal/20200506-single-controller-multitenancy.md

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ superseded-by: []
4848
- [Controller Changes](#controller-changes)
4949
- [Clusterctl changes](#clusterctl-changes)
5050
- [Validating webhook changes](#validating-webhook-changes)
51-
- [Principal Type Credential Provider Behaviour](#principal-type-credential-provider-behaviour)
51+
- [Identity Type Credential Provider Behaviour](#identity-type-credential-provider-behaviour)
5252
- [Security Model](#security-model)
5353
- [Roles](#roles)
5454
- [RBAC](#rbac)
@@ -57,7 +57,7 @@ superseded-by: []
5757
- [CAPA Controller Requirements](#capa-controller-requirements)
5858
- [Alternative Approaches Considered](#alternative-approaches-considered)
5959
- [Using only secrets or RoleARN field on AWSCluster](#using-only-secrets-or-rolearn-field-on-awscluster)
60-
- [1:1 mapping one namespace to one AWSPrincipal](#11-mapping-one-namespace-to-one-awsprincipal)
60+
- [1:1 mapping one namespace to one AWSIdentity](#11-mapping-one-namespace-to-one-awsidentity)
6161
- [Risks and Mitigations](#risks-and-mitigations)
6262
- [Network assumptions are made explicit](#network-assumptions-are-made-explicit)
6363
- [Caching and handling refresh of credentials](#caching-and-handling-refresh-of-credentials)
@@ -74,7 +74,7 @@ superseded-by: []
7474

7575
## Glossary
7676

77-
* Principal Type - One of several ways to provide a form of identity that is ultimately resolved to an AWS access key ID,
77+
* Identity Type - One of several ways to provide a form of identity that is ultimately resolved to an AWS access key ID,
7878
secret access key and optional session token tuple.
7979
* Credential Provider - An implementation of the interface specified in the [AWS SDK for
8080
Go][aws-sdk-go-credential-provider].
@@ -108,8 +108,8 @@ the existing behavior with no changes to user configuration required.
108108
For large organizations, especially highly-regulated organizations, there is a need to be able to perform separate
109109
duties at various levels of infrastructure - permissions, networks and accounts. VPC sharing is a model which provides
110110
separation at the AWS account level. Within this model it is appropriate for tooling running within the 'management' account
111-
to manage infrastructure within the 'workload' accounts, which requires a principal in the management account which can
112-
assume a principal within a workload account. For CAPA to be most useful within these organizations it will need to
111+
to manage infrastructure within the 'workload' accounts, which requires a identity in the management account which can
112+
assume a identity within a workload account. For CAPA to be most useful within these organizations it will need to
113113
support multi-account models.
114114

115115
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.
155155
The current configuration exists: AWS Account 'management':
156156
* Vpc, subnets shared with 'workload' AWS Account
157157
* EC2 instance profile linked to the IAM role 'ClusterAPI-Mgmt'
158-
* A management Kubernetes cluster running Cluster API Provider AWS controllers using the 'ClusterAPI-Owner' IAM principal.
158+
* A management Kubernetes cluster running Cluster API Provider AWS controllers using the 'ClusterAPI-Owner' IAM identity.
159159

160160
AWS Account 'workload':
161161
* Vpc and subnets provided by 'Owner' AWS Account
@@ -197,9 +197,9 @@ a single instance of CAPA to cover multiple organisations.
197197
<a name="FR4">FR4.</a> CAPA MUST prevent privilege escalation allowing users to create clusters in AWS accounts they should
198198
not be able to.
199199

200-
<a name="FR5">FR5.</a> CAPA SHOULD support credential refreshing when principal data is modified.
200+
<a name="FR5">FR5.</a> CAPA SHOULD support credential refreshing when identity data is modified.
201201

202-
<a name="FR6">FR6.</a> CAPA SHOULD provide validation for principal data submitted by users.
202+
<a name="FR6">FR6.</a> CAPA SHOULD provide validation for identity data submitted by users.
203203

204204
<a name="FR7">FR7.</a> CAPA COULD support role assumption using OIDC projected volume service account tokens.
205205

@@ -279,21 +279,21 @@ AWS accounts whilst preventing privilege escalation as per [FR4](#FR4). Reasons
279279

280280
<em>Namespace scoped resources</em>
281281

282-
* `AWSServiceAccountPrincipal` represents the use of a Kubernetes service account for access
282+
* `AWSServiceAccountIdentity` represents the use of a Kubernetes service account for access
283283
to AWS using federated identity.
284284

285285
<strong><em>Changes to AWSCluster</em></strong>
286286

287-
A new field is added to the `AWSClusterSpec` to reference a principal. We intend to use `corev1.LocalObjectReference` in
287+
A new field is added to the `AWSClusterSpec` to reference a identity. We intend to use `corev1.LocalObjectReference` in
288288
order to ensure that the only objects that can be references are either in the same namespace or are scoped to the
289289
entire cluster.
290290

291291
```go
292-
// AWSPrincipalKind defines allowed AWS principal types
293-
type AWSPrincipalKind string
292+
// AWSIdentityKind defines allowed AWS identity types
293+
type AWSIdentityKind string
294294

295295
type AWSIdentityRef struct {
296-
Kind AWSPrincipalKind `json:"kind"`
296+
Kind AWSIdentityKind `json:"kind"`
297297
Name string `json:"name"`
298298
}
299299

@@ -333,35 +333,35 @@ The `IdentityRef` field will be mutable in order to support `clusterctl move`
333333
scenarios where a user instantiates a cluster on their laptop and then makes
334334
the cluster self-managed.
335335
336-
<strong><em>Principal CRDs</em></strong>
336+
<strong><em>Identity CRDs</em></strong>
337337
338338
<em>Common elements</em>
339339
340-
All AWSCluster*Principal types will have Spec structs with an `AllowedNamespaces`
340+
All AWSCluster*Identity types will have Spec structs with an `AllowedNamespaces`
341341
field as follows:
342342
343343
```go
344344

345345
type AWSClusterIdentitySpec struct {
346-
// AllowedNamespaces is used to identify which namespaces are allowed to use the principal from.
346+
// AllowedNamespaces is used to identify which namespaces are allowed to use the identity from.
347347
// Namespaces can be selected either using an array of namespaces or with label selector.
348-
// An empty allowedNamespaces object indicates that AWSClusters can use this principal from any namespace.
348+
// An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace.
349349
// If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided)
350-
// A namespace should be either in the NamespaceList or match with Selector to use the principal.
350+
// A namespace should be either in the NamespaceList or match with Selector to use the identity.
351351
//
352352
// +optional
353353
AllowedNamespaces *AllowedNamespaces `json:"allowedNamespaces"`
354354
}
355355

356356
type AllowedNamespaces struct {
357-
// An nil or empty list indicates that AWSClusters cannot use the principal from any namespace.
357+
// An nil or empty list indicates that AWSClusters cannot use the identity from any namespace.
358358
//
359359
// +optional
360360
// +nullable
361361
NamespaceList []string `json:"list"`
362362

363363
// AllowedNamespaces is a selector of namespaces that AWSClusters can
364-
// use this ClusterPrincipal from. This is a standard Kubernetes LabelSelector,
364+
// use this ClusterIdentity from. This is a standard Kubernetes LabelSelector,
365365
// a label query over a set of resources. The result of matchLabels and
366366
// matchExpressions are ANDed.
367367
//
@@ -542,8 +542,8 @@ type AWSClusterRoleIdentity struct {
542542
Spec AWSClusterRoleIdentitySpec `json:"spec,omitempty""`
543543
}
544544

545-
// AWSClusterIdentityKind defines allowed cluster-scoped AWS principal types
546-
type AWSClusterIdentityKind AWSPrincipalKind
545+
// AWSClusterIdentityKind defines allowed cluster-scoped AWS identity types
546+
type AWSClusterIdentityKind AWSIdentityKind
547547

548548
type AWSClusterIdentityReference struct {
549549
Kind AWSClusterIdentityKind `json:"kind"`
@@ -566,7 +566,7 @@ type AWSClusterRoleIdentitySpec struct {
566566
// +kubebuilder:validation:Pattern:=[\w+=,.@:\/-]*
567567
ExternalID *string `json:"externalID,omitempty"`
568568

569-
// SourceIdentityRef is a reference to another principal which will be chained to do
569+
// SourceIdentityRef is a reference to another identity which will be chained to do
570570
// role assumption.
571571
SourceIdentityRef AWSClusterIdentityReference `json:"sourceIdentityRef,omitempty"`
572572
}
@@ -596,7 +596,7 @@ metadata:
596596
name: "test-account-role"
597597
spec:
598598
allowedNamespaces:
599-
list: # allows only "test" namespace to use this principal
599+
list: # allows only "test" namespace to use this identity
600600
"test"
601601
roleARN: "arn:aws:iam::123456789:role/CAPARole"
602602
# Optional settings
@@ -611,23 +611,23 @@ spec:
611611
name: test-account-creds
612612
```
613613
614-
<em>Future implementation: AWSServiceAccountPrincipal</em>
614+
<em>Future implementation: AWSServiceAccountIdentity</em>
615615
616616
This would not be implemented in the first instance, but opens the possibility to use Kubernetes service accounts
617617
together with `STS::AssumeRoleWithWebIdentity`, supporting [FR7](#FR7).
618618
619619
Definition:
620620
621621
```go
622-
type AWSServiceAccountPrincipal struct {
622+
type AWSServiceAccountIdentity struct {
623623
metav1.TypeMeta `json:",inline"`
624624
metav1.ObjectMeta `json:"metadata,omitempty"`
625625

626-
// Spec for this AWSServiceAccountPrincipal.
627-
Spec AWSServiceAccountPrincipalSpec `json:"spec,omitempty""`
626+
// Spec for this AWSServiceAccountIdentity.
627+
Spec AWSServiceAccountIdentitySpec `json:"spec,omitempty""`
628628
}
629629

630-
type AWSServiceAccountPrincipalSpec struct {
630+
type AWSServiceAccountIdentitySpec struct {
631631
AWSRoleSpec
632632

633633
// 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
659659
"Statement": [
660660
{
661661
"Effect": "Allow",
662-
"Principal": {
662+
"Identity": {
663663
"Federated": "<Provider ARN for the management cluster OIDC configuration>"
664664
},
665665
"Action": "sts:AssumeRoleWithWebIdentity",
@@ -686,11 +686,11 @@ metadata:
686686
spec:
687687
region: "eu-west-1"
688688
identityRef:
689-
kind: AWSServiceAccountPrincipal
689+
kind: AWSServiceAccountIdentity
690690
name: test-service-account
691691
---
692692
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
693-
kind: AWSServiceAccountPrincipal
693+
kind: AWSServiceAccountIdentity
694694
metadata:
695695
name: "test-service-account"
696696
namespace: "test"
@@ -706,10 +706,10 @@ with the requisite parameters and receive a new JWT token to use with `STS::Assu
706706
707707
### Controller Changes
708708
709-
* If identityRef is specified, the CRD is fetched and unmarshalled into a AWS SDK credential.Provider for the principal type.
709+
* If identityRef is specified, the CRD is fetched and unmarshalled into a AWS SDK credential.Provider for the identity type.
710710
* The controller will compare the hash of the credential provider against the same secret’s provider in a cache ([NFR 8](#NFR8)).
711711
* The controller will take the newer of the two and instantiate AWSClients with the selected credential provider.
712-
* The controller will set an the principal resource as one of the OwnerReferences of the AWSCluster.
712+
* The controller will set an the identity resource as one of the OwnerReferences of the AWSCluster.
713713
* The controller and defaulting webhook will default `nil` `identityRef` field in AWSClusters to `AWSClusterControllerIdentity`.
714714
715715
This flow is shown below:
@@ -721,20 +721,20 @@ This flow is shown below:
721721
Today, `clusterctl move` operates by tracking objectreferences within the same namespace, since we are now proposing to
722722
use cluster-scoped resources, we will need to add requisite support to clusterctl's object graph to track ownerReferences
723723
pointing at cluster-scoped resources, and ensure they are moved. We will naively not delete cluster-scoped resources
724-
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
725-
principal after one move, and being copied again.
724+
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
725+
identity after one move, and being copied again.
726726
727727
728728
#### Validating webhook changes
729729
730730
A validating webhook could potentially handle some of the cross-resource validation necessary for the [security
731731
model](#security-model) and provide more immediate feedback to end users. However, it would be imperfect. For example, a
732-
change to a `AWSCluster*Principal` could affect the validity of corresponding AWSCluster.
732+
change to a `AWSCluster*Identity` could affect the validity of corresponding AWSCluster.
733733
The singleton `AWSClusterControllerIdentity` resource will be immutable to avoid any unwanted overrides to the allowed namespaces, especially during upgrading clusters.
734734
735-
#### Principal Type Credential Provider Behaviour
735+
#### Identity Type Credential Provider Behaviour
736736
737-
Implementations for all principal types will implement the `credentials.Provider` interface in the AWS SDK to support [FR5](#FR5) as well as an
737+
Implementations for all identity types will implement the `credentials.Provider` interface in the AWS SDK to support [FR5](#FR5) as well as an
738738
additional function signature to support caching:
739739
740740
```go
@@ -748,10 +748,10 @@ type Provider interface {
748748
IsExpired() bool
749749
}
750750

751-
type AWSPrincipalTypeProvider interface {
751+
type AWSIdentityTypeProvider interface {
752752
credentials.Provider
753753
// Hash returns a unique hash of the data forming the credentials
754-
// for this principal
754+
// for this identity
755755
Hash() (string, error)
756756
}
757757
```
@@ -771,7 +771,7 @@ forcing a refresh.
771771
772772
The authors have implemented a similar mechanism [based on the Ruby AWS SDK][aws-assume-role].
773773
774-
This could be further optimised by having the controller maintain a watch on all Secrets matching the principal types.
774+
This could be further optimised by having the controller maintain a watch on all Secrets matching the identity types.
775775
Upon receiving an update event, the controller will update lookup the key in the cache and update the relevant provider.
776776
This may be implemented as its own interface. Mutexes will ensure in-flight updates are completed prior to SDK calls are
777777
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
805805
readable by most roles, so instead we'll focus on write access for this model.
806806
807807
##### Write Permissions
808-
| | AWSCluster*Principal | AWSServiceAccountPrincipal | AWS IAM API | Cluster |
809-
| ---------------------------- | -------------------- | -------------------------- | ----------- | ------- |
810-
| Infrastructure Provider | Yes | Yes | Yes | Yes |
811-
| Management Cluster Operators | Yes | Yes | Yes | Yes |
812-
| Workload Cluster Operator | No | Yes | No | Yes |
808+
| | AWSCluster*Identity | AWSServiceAccountIdentity | AWS IAM API | Cluster |
809+
| ---------------------------- | ------------------- | ------------------------- | ----------- | ------- |
810+
| Infrastructure Provider | Yes | Yes | Yes | Yes |
811+
| Management Cluster Operators | Yes | Yes | Yes | Yes |
812+
| Workload Cluster Operator | No | Yes | No | Yes |
813813
814814
Because Kubernetes service accounts necessarily encode the namespace into the JWT subject, we can allow workload cluster
815815
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,
821821
they will be controlled with configuration fields on GatewayClasses:
822822
823823
* **allowedNamespaces**: This field is a selector of namespaces that
824-
Gateways can use this `AWSCluster*Principal` from. This is a standard Kubernetes
824+
Gateways can use this `AWSCluster*Identity` from. This is a standard Kubernetes
825825
LabelSelector, a label query over a set of resources. The result of
826826
matchLabels and matchExpressions are ANDed. CAPA will not support
827827
AWSClusters in namespaces outside this selector. An empty selector (default)
828-
indicates that AWSCluster can use this `AWSCluster*Principal` from any namespace. This
828+
indicates that AWSCluster can use this `AWSCluster*Identity` from any namespace. This
829829
field is intentionally not a pointer because the nil behavior (no namespaces)
830830
is undesirable here.
831831
@@ -834,10 +834,10 @@ they will be controlled with configuration fields on GatewayClasses:
834834
The CAPA controller will need to:
835835
836836
* Populate condition fields on AWSClusters and indicate if it is
837-
compatible with `AWS*Principal`.
838-
* Not implement invalid configuration. Fore example, if a `AWSCluster*Principal` is referenced in
837+
compatible with `AWS*Identity`.
838+
* Not implement invalid configuration. Fore example, if a `AWSCluster*Identity` is referenced in
839839
an invalid namespace for it, it should be ignored.
840-
* Respond to changes in `AWS*Principal` configuration that may change.
840+
* Respond to changes in `AWS*Identity` configuration that may change.
841841
842842
### Alternative Approaches Considered
843843
@@ -862,13 +862,13 @@ API server KMS.
862862
863863
**Downsides**
864864
865-
By allowing workload cluster operators to create the various principals, or referencing them directly in the
865+
By allowing workload cluster operators to create the various identitys, or referencing them directly in the
866866
AWSCluster as a field they could potentially escalate privilege when assuming role across AWS accounts as the CAPA
867867
controller itself may be running with privileged trust.
868868
869-
#### 1:1 mapping one namespace to one AWSPrincipal
869+
#### 1:1 mapping one namespace to one AWSIdentity
870870
871-
The mapping of a singular AWSPrincipal to a single namespace such that there is a 1:1 mapping
871+
The mapping of a singular AWSIdentity to a single namespace such that there is a 1:1 mapping
872872
was considered, via either some implicitly named secret or other metadata on the namespace.
873873
874874
**Benefits**
@@ -923,7 +923,7 @@ The data changes are additive and optional, except `AWSClusterControllerIdentity
923923
`AWSClusterControllerIdentity` singleton instance restricts the usage of controller credentials only from `allowedNamespaces`.
924924
AWSClusters that do not have an assigned `IdentityRef` is defaulted to use `AWSClusterControllerIdentity`, hence existing clusters needs to have
925925
`AWSClusterControllerIdentity` instance. In order to make existing AWSClusters to continue to reconcile as before, a new controller is added as experimental feature
926-
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.
926+
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.
927927
During v1alpha4 releases, since breaking changes will be allowed, this feature will become obsolete.
928928
929929
## Additional Details

0 commit comments

Comments
 (0)