From 71d5769edfa6ce4e6e73cb4b7f71efeffae14454 Mon Sep 17 00:00:00 2001 From: Steve Kuznetsov Date: Thu, 1 Feb 2024 10:53:05 -0700 Subject: [PATCH 1/2] rosa: load identity dynamically Instead of requiring users to provide their account IDs and ARNs in the spec of their hosted control planes, we can refer to AWS credentials like the other managed control plane controllers do in this provider. Signed-off-by: Steve Kuznetsov --- Makefile | 3 +- ...ne.cluster.x-k8s.io_rosacontrolplanes.yaml | 29 ++++++--- controllers/rosacluster_controller.go | 2 + controlplane/rosa/api/v1beta2/defaults.go | 13 ++++ .../api/v1beta2/rosacontrolplane_types.go | 8 ++- .../rosa/api/v1beta2/zz_generated.deepcopy.go | 16 ++--- .../rosa/api/v1beta2/zz_generated.defaults.go | 38 +++++++++++ .../rosacontrolplane_controller.go | 8 ++- exp/controllers/rosamachinepool_controller.go | 1 + main.go | 3 + pkg/cloud/interfaces.go | 12 ++++ pkg/cloud/scope/rosacontrolplane.go | 64 +++++++++++++++++-- pkg/cloud/scope/session.go | 16 ++--- pkg/rosa/clusters.go | 2 +- 14 files changed, 177 insertions(+), 38 deletions(-) create mode 100644 controlplane/rosa/api/v1beta2/defaults.go create mode 100644 controlplane/rosa/api/v1beta2/zz_generated.defaults.go diff --git a/Makefile b/Makefile index b43f76940c..070b0970a1 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ DOCKER_BUILDKIT=1 export ACK_GINKGO_DEPRECATIONS := 1.16.4 # Set --output-base for conversion-gen if we are not within GOPATH -ifneq ($(abspath $(REPO_ROOT)),$(shell go env GOPATH)/src/sigs.k8s.io/cluster-api-provider-aws) +ifneq ($(abspath $(REPO_ROOT)),$(abspath $(shell go env GOPATH)/src/sigs.k8s.io/cluster-api-provider-aws)) GEN_OUTPUT_BASE := --output-base=$(REPO_ROOT) else export GOPATH := $(shell go env GOPATH) @@ -190,6 +190,7 @@ defaulters: $(DEFAULTER_GEN) ## Generate all Go types $(DEFAULTER_GEN) \ --input-dirs=./api/v1beta2 \ --input-dirs=./$(EXP_DIR)/api/v1beta2 \ + --input-dirs=./controlplane/rosa/api/v1beta2 \ --input-dirs=./cmd/clusterawsadm/api/bootstrap/v1beta1 \ --input-dirs=./cmd/clusterawsadm/api/bootstrap/v1alpha1 \ --extra-peer-dirs=sigs.k8s.io/cluster-api/api/v1beta1 \ diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml index db89c2c86b..c63450b327 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml @@ -45,10 +45,6 @@ spec: type: object spec: properties: - accountID: - description: 'TODO: these are to satisfy ocm sdk. Explore how to drop - them.' - type: string availabilityZones: description: AWS AvailabilityZones of the worker nodes should match the AvailabilityZones of the Subnets. @@ -70,8 +66,6 @@ spec: - host - port type: object - creatorARN: - type: string credentialsSecretRef: description: 'CredentialsSecretRef references a secret with necessary credentials to connect to the OCM API. The secret should contain @@ -84,7 +78,28 @@ spec: type: string type: object x-kubernetes-map-type: atomic + identityRef: + description: IdentityRef is a reference to an identity to be used + when reconciling the managed control plane. + properties: + kind: + description: Kind of the identity. + enum: + - AWSClusterControllerIdentity + - AWSClusterRoleIdentity + - AWSClusterStaticIdentity + type: string + name: + description: Name of the identity. + minLength: 1 + type: string + required: + - kind + - name + type: object installerRoleARN: + description: 'TODO: these are to satisfy ocm sdk. Explore how to drop + them.' type: string machineCIDR: description: Block of IP addresses used by OpenShift while installing @@ -276,9 +291,7 @@ spec: workerRoleARN: type: string required: - - accountID - availabilityZones - - creatorARN - installerRoleARN - machineCIDR - oidcID diff --git a/controllers/rosacluster_controller.go b/controllers/rosacluster_controller.go index 7e92841e07..e57cb7402a 100644 --- a/controllers/rosacluster_controller.go +++ b/controllers/rosacluster_controller.go @@ -35,6 +35,7 @@ import ( infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" rosacontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/rosa/api/v1beta2" expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2" + "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope" "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/util" @@ -48,6 +49,7 @@ type ROSAClusterReconciler struct { client.Client Recorder record.EventRecorder WatchFilterValue string + Endpoints []scope.ServiceEndpoint } // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=rosaclusters,verbs=get;list;watch;update;patch;delete diff --git a/controlplane/rosa/api/v1beta2/defaults.go b/controlplane/rosa/api/v1beta2/defaults.go new file mode 100644 index 0000000000..a2006137c1 --- /dev/null +++ b/controlplane/rosa/api/v1beta2/defaults.go @@ -0,0 +1,13 @@ +package v1beta2 + +import "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" + +// SetDefaults_RosaControlPlaneSpec is used by defaulter-gen. +func SetDefaults_RosaControlPlaneSpec(s *RosaControlPlaneSpec) { //nolint:golint,stylecheck + if s.IdentityRef == nil { + s.IdentityRef = &v1beta2.AWSIdentityReference{ + Kind: v1beta2.ControllerIdentityKind, + Name: v1beta2.AWSClusterControllerIdentityName, + } + } +} diff --git a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go index 185aa3a9fe..a5c46f85de 100644 --- a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go +++ b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go @@ -20,6 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ) @@ -64,8 +65,6 @@ type RosaControlPlaneSpec struct { //nolint: maligned OIDCID *string `json:"oidcID"` // TODO: these are to satisfy ocm sdk. Explore how to drop them. - AccountID *string `json:"accountID"` - CreatorARN *string `json:"creatorARN"` InstallerRoleARN *string `json:"installerRoleARN"` SupportRoleARN *string `json:"supportRoleARN"` WorkerRoleARN *string `json:"workerRoleARN"` @@ -76,6 +75,10 @@ type RosaControlPlaneSpec struct { //nolint: maligned // - ocmApiUrl: Optional, defaults to 'https://api.openshift.com' // +optional CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // +optional + IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"` } // AWSRolesRef contains references to various AWS IAM roles required for operators to make calls against the AWS API. @@ -489,6 +492,7 @@ type RosaControlPlaneStatus struct { // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this RosaControl belongs" // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="Control plane infrastructure is ready for worker nodes" +// +k8s:defaulter-gen=true type ROSAControlPlane struct { metav1.TypeMeta `json:",inline"` diff --git a/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go b/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go index 017f4f60dd..bfb980ac14 100644 --- a/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go +++ b/controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go @@ -23,6 +23,7 @@ package v1beta2 import ( "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" + apiv1beta2 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" "sigs.k8s.io/cluster-api/api/v1beta1" ) @@ -130,16 +131,6 @@ func (in *RosaControlPlaneSpec) DeepCopyInto(out *RosaControlPlaneSpec) { *out = new(string) **out = **in } - if in.AccountID != nil { - in, out := &in.AccountID, &out.AccountID - *out = new(string) - **out = **in - } - if in.CreatorARN != nil { - in, out := &in.CreatorARN, &out.CreatorARN - *out = new(string) - **out = **in - } if in.InstallerRoleARN != nil { in, out := &in.InstallerRoleARN, &out.InstallerRoleARN *out = new(string) @@ -160,6 +151,11 @@ func (in *RosaControlPlaneSpec) DeepCopyInto(out *RosaControlPlaneSpec) { *out = new(v1.LocalObjectReference) **out = **in } + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(apiv1beta2.AWSIdentityReference) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RosaControlPlaneSpec. diff --git a/controlplane/rosa/api/v1beta2/zz_generated.defaults.go b/controlplane/rosa/api/v1beta2/zz_generated.defaults.go new file mode 100644 index 0000000000..510687638d --- /dev/null +++ b/controlplane/rosa/api/v1beta2/zz_generated.defaults.go @@ -0,0 +1,38 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1beta2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&ROSAControlPlane{}, func(obj interface{}) { SetObjectDefaults_ROSAControlPlane(obj.(*ROSAControlPlane)) }) + return nil +} + +func SetObjectDefaults_ROSAControlPlane(in *ROSAControlPlane) { + SetDefaults_RosaControlPlaneSpec(&in.Spec) +} diff --git a/controlplane/rosa/controllers/rosacontrolplane_controller.go b/controlplane/rosa/controllers/rosacontrolplane_controller.go index a01289587d..00476fb538 100644 --- a/controlplane/rosa/controllers/rosacontrolplane_controller.go +++ b/controlplane/rosa/controllers/rosacontrolplane_controller.go @@ -68,6 +68,7 @@ type ROSAControlPlaneReconciler struct { client.Client WatchFilterValue string WaitInfraPeriod time.Duration + Endpoints []scope.ServiceEndpoint } // SetupWithManager is used to setup the controller. @@ -148,6 +149,7 @@ func (r *ROSAControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Req Cluster: cluster, ControlPlane: rosaControlPlane, ControllerName: strings.ToLower(rosaControlPlaneKind), + Endpoints: r.Endpoints, Logger: log, }) if err != nil { @@ -344,8 +346,8 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc stsBuilder.AutoMode(true) awsBuilder := cmv1.NewAWS(). - AccountID(*rosaScope.ControlPlane.Spec.AccountID). - BillingAccountID(*rosaScope.ControlPlane.Spec.AccountID). + AccountID(*rosaScope.Identity.Account). + BillingAccountID(*rosaScope.Identity.Account). SubnetIDs(rosaScope.ControlPlane.Spec.Subnets...). STS(stsBuilder) clusterBuilder = clusterBuilder.AWS(awsBuilder) @@ -355,7 +357,7 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc clusterBuilder = clusterBuilder.Nodes(clusterNodesBuilder) clusterProperties := map[string]string{} - clusterProperties[rosaCreatorArnProperty] = *rosaScope.ControlPlane.Spec.CreatorARN + clusterProperties[rosaCreatorArnProperty] = *rosaScope.Identity.Arn clusterBuilder = clusterBuilder.Properties(clusterProperties) clusterSpec, err := clusterBuilder.Build() diff --git a/exp/controllers/rosamachinepool_controller.go b/exp/controllers/rosamachinepool_controller.go index 38a63f1b51..0bc668e4a8 100644 --- a/exp/controllers/rosamachinepool_controller.go +++ b/exp/controllers/rosamachinepool_controller.go @@ -37,6 +37,7 @@ type ROSAMachinePoolReconciler struct { client.Client Recorder record.EventRecorder WatchFilterValue string + Endpoints []scope.ServiceEndpoint } // SetupWithManager is used to setup the controller. diff --git a/main.go b/main.go index b27fa4ea11..32954e6dfd 100644 --- a/main.go +++ b/main.go @@ -227,6 +227,7 @@ func main() { Client: mgr.GetClient(), WatchFilterValue: watchFilterValue, WaitInfraPeriod: waitInfraPeriod, + Endpoints: awsServiceEndpoints, }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: awsClusterConcurrency, RecoverPanic: ptr.To[bool](true)}); err != nil { setupLog.Error(err, "unable to create controller", "controller", "ROSAControlPlane") os.Exit(1) @@ -237,6 +238,7 @@ func main() { Client: mgr.GetClient(), Recorder: mgr.GetEventRecorderFor("rosacluster-controller"), WatchFilterValue: watchFilterValue, + Endpoints: awsServiceEndpoints, }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: awsClusterConcurrency, RecoverPanic: ptr.To[bool](true)}); err != nil { setupLog.Error(err, "unable to create controller", "controller", "ROSACluster") os.Exit(1) @@ -247,6 +249,7 @@ func main() { Client: mgr.GetClient(), Recorder: mgr.GetEventRecorderFor("rosamachinepool-controller"), WatchFilterValue: watchFilterValue, + Endpoints: awsServiceEndpoints, }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: awsClusterConcurrency, RecoverPanic: ptr.To[bool](true)}); err != nil { setupLog.Error(err, "unable to create controller", "controller", "ROSAMachinePool") os.Exit(1) diff --git a/pkg/cloud/interfaces.go b/pkg/cloud/interfaces.go index a7f6609bdc..7d6115d429 100644 --- a/pkg/cloud/interfaces.go +++ b/pkg/cloud/interfaces.go @@ -84,3 +84,15 @@ type ClusterScoper interface { // Close closes the current scope persisting the cluster configuration and status. Close() error } + +// SessionMetadata knows how to extract the information for managing AWS sessions for a resource. +type SessionMetadata interface { + // Namespace returns the cluster namespace. + Namespace() string + // InfraClusterName returns the AWS infrastructure cluster name. + InfraClusterName() string + // InfraCluster returns the AWS infrastructure cluster object. + InfraCluster() ClusterObject + // IdentityRef returns the AWS infrastructure cluster identityRef. + IdentityRef() *infrav1.AWSIdentityReference +} diff --git a/pkg/cloud/scope/rosacontrolplane.go b/pkg/cloud/scope/rosacontrolplane.go index 5d2ee972f8..da4c36cb13 100644 --- a/pkg/cloud/scope/rosacontrolplane.go +++ b/pkg/cloud/scope/rosacontrolplane.go @@ -20,13 +20,18 @@ import ( "context" "fmt" + awsclient "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/service/sts" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" + infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" rosacontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/rosa/api/v1beta2" + "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud" + "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/throttle" "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/util/patch" @@ -38,6 +43,7 @@ type ROSAControlPlaneScopeParams struct { Cluster *clusterv1.Cluster ControlPlane *rosacontrolplanev1.ROSAControlPlane ControllerName string + Endpoints []ServiceEndpoint } func NewROSAControlPlaneScope(params ROSAControlPlaneScopeParams) (*ROSAControlPlaneScope, error) { @@ -53,11 +59,17 @@ func NewROSAControlPlaneScope(params ROSAControlPlaneScopeParams) (*ROSAControlP } managedScope := &ROSAControlPlaneScope{ - Logger: *params.Logger, - Client: params.Client, - Cluster: params.Cluster, - ControlPlane: params.ControlPlane, - patchHelper: nil, + Logger: *params.Logger, + Client: params.Client, + Cluster: params.Cluster, + ControlPlane: params.ControlPlane, + patchHelper: nil, + controllerName: params.ControllerName, + } + + session, serviceLimiters, err := sessionForClusterWithRegion(params.Client, managedScope, *params.ControlPlane.Spec.Region, params.Endpoints, params.Logger) + if err != nil { + return nil, errors.Errorf("failed to create aws session: %v", err) } helper, err := patch.NewHelper(params.ControlPlane, params.Client) @@ -66,6 +78,16 @@ func NewROSAControlPlaneScope(params ROSAControlPlaneScopeParams) (*ROSAControlP } managedScope.patchHelper = helper + managedScope.session = session + managedScope.serviceLimiters = serviceLimiters + + stsClient := NewSTSClient(managedScope, managedScope, managedScope, managedScope.ControlPlane) + identity, err := stsClient.GetCallerIdentity(&sts.GetCallerIdentityInput{}) + if err != nil { + return nil, fmt.Errorf("failed to identify the AWS caller: %w", err) + } + managedScope.Identity = identity + return managedScope, nil } @@ -77,8 +99,40 @@ type ROSAControlPlaneScope struct { Cluster *clusterv1.Cluster ControlPlane *rosacontrolplanev1.ROSAControlPlane + + session awsclient.ConfigProvider + serviceLimiters throttle.ServiceLimiters + controllerName string + Identity *sts.GetCallerIdentityOutput +} + +func (s *ROSAControlPlaneScope) InfraCluster() cloud.ClusterObject { + return s.ControlPlane } +func (s *ROSAControlPlaneScope) IdentityRef() *infrav1.AWSIdentityReference { + return s.ControlPlane.Spec.IdentityRef +} + +func (s *ROSAControlPlaneScope) Session() awsclient.ConfigProvider { + return s.session +} + +func (s *ROSAControlPlaneScope) ServiceLimiter(service string) *throttle.ServiceLimiter { + if sl, ok := s.serviceLimiters[service]; ok { + return sl + } + return nil +} + +func (s *ROSAControlPlaneScope) ControllerName() string { + return s.controllerName +} + +var _ cloud.ScopeUsage = (*ROSAControlPlaneScope)(nil) +var _ cloud.Session = (*ROSAControlPlaneScope)(nil) +var _ cloud.SessionMetadata = (*ROSAControlPlaneScope)(nil) + // Name returns the CAPI cluster name. func (s *ROSAControlPlaneScope) Name() string { return s.Cluster.Name diff --git a/pkg/cloud/scope/session.go b/pkg/cloud/scope/session.go index acf3fa3ab8..cda46352f5 100644 --- a/pkg/cloud/scope/session.go +++ b/pkg/cloud/scope/session.go @@ -104,7 +104,7 @@ func sessionForRegion(region string, endpoint []ServiceEndpoint) (*session.Sessi return ns, sl, nil } -func sessionForClusterWithRegion(k8sClient client.Client, clusterScoper cloud.ClusterScoper, region string, endpoint []ServiceEndpoint, log logger.Wrapper) (*session.Session, throttle.ServiceLimiters, error) { +func sessionForClusterWithRegion(k8sClient client.Client, clusterScoper cloud.SessionMetadata, region string, endpoint []ServiceEndpoint, log logger.Wrapper) (*session.Session, throttle.ServiceLimiters, error) { log = log.WithName("identity") log.Trace("Creating an AWS Session") @@ -186,7 +186,7 @@ func sessionForClusterWithRegion(k8sClient client.Client, clusterScoper cloud.Cl return ns, sl, nil } -func getSessionName(region string, clusterScoper cloud.ClusterScoper) string { +func getSessionName(region string, clusterScoper cloud.SessionMetadata) string { return fmt.Sprintf("%s-%s-%s", region, clusterScoper.InfraClusterName(), clusterScoper.Namespace()) } @@ -254,7 +254,7 @@ func buildProvidersForRef( ctx context.Context, providers []identity.AWSPrincipalTypeProvider, k8sClient client.Client, - clusterScoper cloud.ClusterScoper, + clusterScoper cloud.SessionMetadata, ref *infrav1.AWSIdentityReference, log logger.Wrapper) ([]identity.AWSPrincipalTypeProvider, error) { if ref == nil { @@ -326,11 +326,11 @@ func buildProvidersForRef( return providers, nil } -func setPrincipalUsageAllowedCondition(clusterScoper cloud.ClusterScoper) { +func setPrincipalUsageAllowedCondition(clusterScoper cloud.SessionMetadata) { conditions.MarkTrue(clusterScoper.InfraCluster(), infrav1.PrincipalUsageAllowedCondition) } -func setPrincipalUsageNotAllowedCondition(kind infrav1.AWSIdentityKind, identityObjectKey client.ObjectKey, clusterScoper cloud.ClusterScoper) { +func setPrincipalUsageNotAllowedCondition(kind infrav1.AWSIdentityKind, identityObjectKey client.ObjectKey, clusterScoper cloud.SessionMetadata) { errMsg := fmt.Sprintf(notPermittedError, kind, identityObjectKey.Name) if clusterScoper.IdentityRef().Name == identityObjectKey.Name { @@ -340,7 +340,7 @@ func setPrincipalUsageNotAllowedCondition(kind infrav1.AWSIdentityKind, identity } } -func buildAWSClusterStaticIdentity(ctx context.Context, identityObjectKey client.ObjectKey, k8sClient client.Client, clusterScoper cloud.ClusterScoper) (*identity.AWSStaticPrincipalTypeProvider, error) { +func buildAWSClusterStaticIdentity(ctx context.Context, identityObjectKey client.ObjectKey, k8sClient client.Client, clusterScoper cloud.SessionMetadata) (*identity.AWSStaticPrincipalTypeProvider, error) { staticPrincipal := &infrav1.AWSClusterStaticIdentity{} err := k8sClient.Get(ctx, identityObjectKey, staticPrincipal) if err != nil { @@ -382,7 +382,7 @@ func buildAWSClusterStaticIdentity(ctx context.Context, identityObjectKey client return identity.NewAWSStaticPrincipalTypeProvider(staticPrincipal, secret), nil } -func buildAWSClusterControllerIdentity(ctx context.Context, identityObjectKey client.ObjectKey, k8sClient client.Client, clusterScoper cloud.ClusterScoper) error { +func buildAWSClusterControllerIdentity(ctx context.Context, identityObjectKey client.ObjectKey, k8sClient client.Client, clusterScoper cloud.SessionMetadata) error { controllerIdentity := &infrav1.AWSClusterControllerIdentity{} controllerIdentity.Kind = string(infrav1.ControllerIdentityKind) @@ -408,7 +408,7 @@ func buildAWSClusterControllerIdentity(ctx context.Context, identityObjectKey cl return nil } -func getProvidersForCluster(ctx context.Context, k8sClient client.Client, clusterScoper cloud.ClusterScoper, log logger.Wrapper) ([]identity.AWSPrincipalTypeProvider, error) { +func getProvidersForCluster(ctx context.Context, k8sClient client.Client, clusterScoper cloud.SessionMetadata, log logger.Wrapper) ([]identity.AWSPrincipalTypeProvider, error) { providers := make([]identity.AWSPrincipalTypeProvider, 0) providers, err := buildProvidersForRef(ctx, providers, k8sClient, clusterScoper, clusterScoper.IdentityRef(), log) if err != nil { diff --git a/pkg/rosa/clusters.go b/pkg/rosa/clusters.go index 1b6605245a..98dc0c5d2c 100644 --- a/pkg/rosa/clusters.go +++ b/pkg/rosa/clusters.go @@ -42,7 +42,7 @@ func (c *RosaClient) DeleteCluster(clusterID string) error { func (c *RosaClient) GetCluster() (*cmv1.Cluster, error) { clusterKey := c.rosaScope.RosaClusterName() query := fmt.Sprintf("%s AND (id = '%s' OR name = '%s' OR external_id = '%s')", - getClusterFilter(c.rosaScope.ControlPlane.Spec.CreatorARN), + getClusterFilter(c.rosaScope.Identity.Arn), clusterKey, clusterKey, clusterKey, ) response, err := c.ocm.ClustersMgmt().V1().Clusters().List(). From 1e11e57c78a7f7dcf4d0a3951a25136a3e988022 Mon Sep 17 00:00:00 2001 From: Steve Kuznetsov Date: Thu, 8 Feb 2024 07:58:48 -0700 Subject: [PATCH 2/2] *: clarify the defaults for identity references Signed-off-by: Steve Kuznetsov --- api/v1beta1/awscluster_types.go | 4 +++- api/v1beta2/awscluster_types.go | 4 +++- ...ane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml | 10 ++++++---- ...trolplane.cluster.x-k8s.io_rosacontrolplanes.yaml | 3 ++- .../infrastructure.cluster.x-k8s.io_awsclusters.yaml | 10 ++++++---- ...ructure.cluster.x-k8s.io_awsclustertemplates.yaml | 12 ++++++++---- .../eks/api/v1beta1/awsmanagedcontrolplane_types.go | 4 +++- .../eks/api/v1beta2/awsmanagedcontrolplane_types.go | 4 +++- .../rosa/api/v1beta2/rosacontrolplane_types.go | 4 +++- 9 files changed, 37 insertions(+), 18 deletions(-) diff --git a/api/v1beta1/awscluster_types.go b/api/v1beta1/awscluster_types.go index e19ec12335..9bcb009579 100644 --- a/api/v1beta1/awscluster_types.go +++ b/api/v1beta1/awscluster_types.go @@ -87,8 +87,10 @@ type AWSClusterSpec struct { // +optional Bastion Bastion `json:"bastion"` - // IdentityRef is a reference to a identity to be used when reconciling this cluster // +optional + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // If no identity is specified, the default identity for this controller will be used. IdentityRef *AWSIdentityReference `json:"identityRef,omitempty"` // S3Bucket contains options to configure a supporting S3 bucket for this diff --git a/api/v1beta2/awscluster_types.go b/api/v1beta2/awscluster_types.go index 0a1bdafbfc..49c8236e2c 100644 --- a/api/v1beta2/awscluster_types.go +++ b/api/v1beta2/awscluster_types.go @@ -91,8 +91,10 @@ type AWSClusterSpec struct { // +optional Bastion Bastion `json:"bastion"` - // IdentityRef is a reference to a identity to be used when reconciling this cluster // +optional + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // If no identity is specified, the default identity for this controller will be used. IdentityRef *AWSIdentityReference `json:"identityRef,omitempty"` // S3Bucket contains options to configure a supporting S3 bucket for this diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml index f5990b28fa..1a6546d102 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml @@ -258,8 +258,9 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling the managed control plane. + description: IdentityRef is a reference to an identity to be used + when reconciling the managed control plane. If no identity is specified, + the default identity for this controller will be used. properties: kind: description: Kind of the identity. @@ -1887,8 +1888,9 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling the managed control plane. + description: IdentityRef is a reference to an identity to be used + when reconciling the managed control plane. If no identity is specified, + the default identity for this controller will be used. properties: kind: description: Kind of the identity. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml index c63450b327..629a1d09d0 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml @@ -80,7 +80,8 @@ spec: x-kubernetes-map-type: atomic identityRef: description: IdentityRef is a reference to an identity to be used - when reconciling the managed control plane. + when reconciling the managed control plane. If no identity is specified, + the default identity for this controller will be used. properties: kind: description: Kind of the identity. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml index a534305d72..a2abf7ff0c 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml @@ -167,8 +167,9 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this cluster + description: IdentityRef is a reference to an identity to be used + when reconciling the managed control plane. If no identity is specified, + the default identity for this controller will be used. properties: kind: description: Kind of the identity. @@ -1141,8 +1142,9 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this cluster + description: IdentityRef is a reference to an identity to be used + when reconciling the managed control plane. If no identity is specified, + the default identity for this controller will be used. properties: kind: description: Kind of the identity. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml index 230bfe115a..c94a4d1e68 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml @@ -183,8 +183,10 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster + description: IdentityRef is a reference to an identity to + be used when reconciling the managed control plane. If no + identity is specified, the default identity for this controller + will be used. properties: kind: description: Kind of the identity. @@ -741,8 +743,10 @@ spec: type: array type: object identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster + description: IdentityRef is a reference to an identity to + be used when reconciling the managed control plane. If no + identity is specified, the default identity for this controller + will be used. properties: kind: description: Kind of the identity. diff --git a/controlplane/eks/api/v1beta1/awsmanagedcontrolplane_types.go b/controlplane/eks/api/v1beta1/awsmanagedcontrolplane_types.go index adbff4c3e5..4b7a280f8f 100644 --- a/controlplane/eks/api/v1beta1/awsmanagedcontrolplane_types.go +++ b/controlplane/eks/api/v1beta1/awsmanagedcontrolplane_types.go @@ -40,8 +40,10 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned // +optional EKSClusterName string `json:"eksClusterName,omitempty"` - // IdentityRef is a reference to a identity to be used when reconciling the managed control plane. // +optional + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // If no identity is specified, the default identity for this controller will be used. IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"` // NetworkSpec encapsulates all things related to AWS network. diff --git a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go index 3ca8ded16f..89d5e8bc2b 100644 --- a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go +++ b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go @@ -40,8 +40,10 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned // +optional EKSClusterName string `json:"eksClusterName,omitempty"` - // IdentityRef is a reference to a identity to be used when reconciling the managed control plane. // +optional + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // If no identity is specified, the default identity for this controller will be used. IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"` // NetworkSpec encapsulates all things related to AWS network. diff --git a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go index a5c46f85de..831adeaa90 100644 --- a/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go +++ b/controlplane/rosa/api/v1beta2/rosacontrolplane_types.go @@ -76,8 +76,10 @@ type RosaControlPlaneSpec struct { //nolint: maligned // +optional CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` - // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. // +optional + + // IdentityRef is a reference to an identity to be used when reconciling the managed control plane. + // If no identity is specified, the default identity for this controller will be used. IdentityRef *infrav1.AWSIdentityReference `json:"identityRef,omitempty"` }