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 21be0fc920..23e4a88ee2 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml @@ -2913,6 +2913,30 @@ spec: and no name is supplied then a role is created. minLength: 2 type: string + rolePath: + description: |- + RolePath sets the path to the role. For more information about paths, see IAM Identifiers + (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + in the IAM User Guide. + + This parameter is optional. If it is not included, it defaults to a slash + (/). + type: string + rolePermissionsBoundary: + description: |- + RolePermissionsBoundary sets the ARN of the managed policy that is used + to set the permissions boundary for the role. + + A permissions boundary policy defines the maximum permissions that identity-based + policies can grant to an entity, but does not grant permissions. Permissions + boundaries do not define the maximum permissions that a resource-based policy + can grant to an entity. To learn more, see Permissions boundaries for IAM + entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + in the IAM User Guide. + + For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + in the IAM User Guide. + type: string secondaryCidrBlock: description: |- SecondaryCidrBlock is the additional CIDR range to use for pod IPs. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsfargateprofiles.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsfargateprofiles.yaml index e2fcb92dd7..9691e01087 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsfargateprofiles.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsfargateprofiles.yaml @@ -264,6 +264,30 @@ spec: and not delete it on deletion. If the EKSEnableIAM feature flag is true and no name is supplied then a role is created. type: string + rolePath: + description: |- + RolePath sets the path to the role. For more information about paths, see IAM Identifiers + (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + in the IAM User Guide. + + This parameter is optional. If it is not included, it defaults to a slash + (/). + type: string + rolePermissionsBoundary: + description: |- + RolePermissionsBoundary sets the ARN of the managed policy that is used + to set the permissions boundary for the role. + + A permissions boundary policy defines the maximum permissions that identity-based + policies can grant to an entity, but does not grant permissions. Permissions + boundaries do not define the maximum permissions that a resource-based policy + can grant to an entity. To learn more, see Permissions boundaries for IAM + entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + in the IAM User Guide. + + For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + in the IAM User Guide. + type: string selectors: description: Selectors specify fargate pod selectors. items: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml index 9ecac67715..8bbe8f3eb7 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml @@ -921,6 +921,30 @@ spec: and not delete it on deletion. If the EKSEnableIAM feature flag is true and no name is supplied then a role is created. type: string + rolePath: + description: |- + RolePath sets the path to the role. For more information about paths, see IAM Identifiers + (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + in the IAM User Guide. + + This parameter is optional. If it is not included, it defaults to a slash + (/). + type: string + rolePermissionsBoundary: + description: |- + RolePermissionsBoundary sets the ARN of the managed policy that is used + to set the permissions boundary for the role. + + A permissions boundary policy defines the maximum permissions that identity-based + policies can grant to an entity, but does not grant permissions. Permissions + boundaries do not define the maximum permissions that a resource-based policy + can grant to an entity. To learn more, see Permissions boundaries for IAM + entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + in the IAM User Guide. + + For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + in the IAM User Guide. + type: string scaling: description: Scaling specifies scaling for the ASG behind this pool properties: diff --git a/controlplane/eks/api/v1beta1/zz_generated.conversion.go b/controlplane/eks/api/v1beta1/zz_generated.conversion.go index 481943f7bd..a900a5fcc8 100644 --- a/controlplane/eks/api/v1beta1/zz_generated.conversion.go +++ b/controlplane/eks/api/v1beta1/zz_generated.conversion.go @@ -384,6 +384,8 @@ func autoConvert_v1beta2_AWSManagedControlPlaneSpec_To_v1beta1_AWSManagedControl out.Version = (*string)(unsafe.Pointer(in.Version)) out.RoleName = (*string)(unsafe.Pointer(in.RoleName)) out.RoleAdditionalPolicies = (*[]string)(unsafe.Pointer(in.RoleAdditionalPolicies)) + // WARNING: in.RolePath requires manual conversion: does not exist in peer-type + // WARNING: in.RolePermissionsBoundary requires manual conversion: does not exist in peer-type out.Logging = (*ControlPlaneLoggingSpec)(unsafe.Pointer(in.Logging)) out.EncryptionConfig = (*EncryptionConfig)(unsafe.Pointer(in.EncryptionConfig)) out.AdditionalTags = *(*apiv1beta2.Tags)(unsafe.Pointer(&in.AdditionalTags)) diff --git a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go index 109752e573..15618ef3b8 100644 --- a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go +++ b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go @@ -88,6 +88,28 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned // +optional RoleAdditionalPolicies *[]string `json:"roleAdditionalPolicies,omitempty"` + // RolePath sets the path to the role. For more information about paths, see IAM Identifiers + // (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + // in the IAM User Guide. + // + // This parameter is optional. If it is not included, it defaults to a slash + // (/). + RolePath *string `json:"rolePath,omitempty"` + + // RolePermissionsBoundary sets the ARN of the managed policy that is used + // to set the permissions boundary for the role. + // + // A permissions boundary policy defines the maximum permissions that identity-based + // policies can grant to an entity, but does not grant permissions. Permissions + // boundaries do not define the maximum permissions that a resource-based policy + // can grant to an entity. To learn more, see Permissions boundaries for IAM + // entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + // in the IAM User Guide. + // + // For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + // in the IAM User Guide. + RolePermissionsBoundary *string `json:"rolePermissionsBoundary,omitempty"` + // Logging specifies which EKS Cluster logs should be enabled. Entries for // each of the enabled logs will be sent to CloudWatch // +optional diff --git a/controlplane/eks/api/v1beta2/zz_generated.deepcopy.go b/controlplane/eks/api/v1beta2/zz_generated.deepcopy.go index 160f556db9..349e23f991 100644 --- a/controlplane/eks/api/v1beta2/zz_generated.deepcopy.go +++ b/controlplane/eks/api/v1beta2/zz_generated.deepcopy.go @@ -124,6 +124,16 @@ func (in *AWSManagedControlPlaneSpec) DeepCopyInto(out *AWSManagedControlPlaneSp copy(*out, *in) } } + if in.RolePath != nil { + in, out := &in.RolePath, &out.RolePath + *out = new(string) + **out = **in + } + if in.RolePermissionsBoundary != nil { + in, out := &in.RolePermissionsBoundary, &out.RolePermissionsBoundary + *out = new(string) + **out = **in + } if in.Logging != nil { in, out := &in.Logging, &out.Logging *out = new(ControlPlaneLoggingSpec) diff --git a/exp/api/v1beta1/zz_generated.conversion.go b/exp/api/v1beta1/zz_generated.conversion.go index 585cbd1504..c962112423 100644 --- a/exp/api/v1beta1/zz_generated.conversion.go +++ b/exp/api/v1beta1/zz_generated.conversion.go @@ -357,7 +357,17 @@ func Convert_v1beta2_AWSFargateProfile_To_v1beta1_AWSFargateProfile(in *v1beta2. func autoConvert_v1beta1_AWSFargateProfileList_To_v1beta2_AWSFargateProfileList(in *AWSFargateProfileList, out *v1beta2.AWSFargateProfileList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1beta2.AWSFargateProfile)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta2.AWSFargateProfile, len(*in)) + for i := range *in { + if err := Convert_v1beta1_AWSFargateProfile_To_v1beta2_AWSFargateProfile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -368,7 +378,17 @@ func Convert_v1beta1_AWSFargateProfileList_To_v1beta2_AWSFargateProfileList(in * func autoConvert_v1beta2_AWSFargateProfileList_To_v1beta1_AWSFargateProfileList(in *v1beta2.AWSFargateProfileList, out *AWSFargateProfileList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]AWSFargateProfile)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AWSFargateProfile, len(*in)) + for i := range *in { + if err := Convert_v1beta2_AWSFargateProfile_To_v1beta1_AWSFargateProfile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -721,6 +741,8 @@ func autoConvert_v1beta2_AWSManagedMachinePoolSpec_To_v1beta1_AWSManagedMachineP out.AdditionalTags = *(*apiv1beta2.Tags)(unsafe.Pointer(&in.AdditionalTags)) out.RoleAdditionalPolicies = *(*[]string)(unsafe.Pointer(&in.RoleAdditionalPolicies)) out.RoleName = in.RoleName + // WARNING: in.RolePath requires manual conversion: does not exist in peer-type + // WARNING: in.RolePermissionsBoundary requires manual conversion: does not exist in peer-type out.AMIVersion = (*string)(unsafe.Pointer(in.AMIVersion)) out.AMIType = (*ManagedMachineAMIType)(unsafe.Pointer(in.AMIType)) out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) @@ -883,15 +905,12 @@ func autoConvert_v1beta2_FargateProfileSpec_To_v1beta1_FargateProfileSpec(in *v1 out.SubnetIDs = *(*[]string)(unsafe.Pointer(&in.SubnetIDs)) out.AdditionalTags = *(*apiv1beta2.Tags)(unsafe.Pointer(&in.AdditionalTags)) out.RoleName = in.RoleName + // WARNING: in.RolePath requires manual conversion: does not exist in peer-type + // WARNING: in.RolePermissionsBoundary requires manual conversion: does not exist in peer-type out.Selectors = *(*[]FargateSelector)(unsafe.Pointer(&in.Selectors)) return nil } -// Convert_v1beta2_FargateProfileSpec_To_v1beta1_FargateProfileSpec is an autogenerated conversion function. -func Convert_v1beta2_FargateProfileSpec_To_v1beta1_FargateProfileSpec(in *v1beta2.FargateProfileSpec, out *FargateProfileSpec, s conversion.Scope) error { - return autoConvert_v1beta2_FargateProfileSpec_To_v1beta1_FargateProfileSpec(in, out, s) -} - func autoConvert_v1beta1_FargateProfileStatus_To_v1beta2_FargateProfileStatus(in *FargateProfileStatus, out *v1beta2.FargateProfileStatus, s conversion.Scope) error { out.Ready = in.Ready out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) diff --git a/exp/api/v1beta2/awsfargateprofile_types.go b/exp/api/v1beta2/awsfargateprofile_types.go index 35317aff52..5278eb661e 100644 --- a/exp/api/v1beta2/awsfargateprofile_types.go +++ b/exp/api/v1beta2/awsfargateprofile_types.go @@ -60,6 +60,28 @@ type FargateProfileSpec struct { // +optional RoleName string `json:"roleName,omitempty"` + // RolePath sets the path to the role. For more information about paths, see IAM Identifiers + // (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + // in the IAM User Guide. + // + // This parameter is optional. If it is not included, it defaults to a slash + // (/). + RolePath string `json:"rolePath,omitempty"` + + // RolePermissionsBoundary sets the ARN of the managed policy that is used + // to set the permissions boundary for the role. + // + // A permissions boundary policy defines the maximum permissions that identity-based + // policies can grant to an entity, but does not grant permissions. Permissions + // boundaries do not define the maximum permissions that a resource-based policy + // can grant to an entity. To learn more, see Permissions boundaries for IAM + // entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + // in the IAM User Guide. + // + // For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + // in the IAM User Guide. + RolePermissionsBoundary string `json:"rolePermissionsBoundary,omitempty"` + // Selectors specify fargate pod selectors. Selectors []FargateSelector `json:"selectors,omitempty"` } diff --git a/exp/api/v1beta2/awsmanagedmachinepool_types.go b/exp/api/v1beta2/awsmanagedmachinepool_types.go index c7e70fcf55..e506f84069 100644 --- a/exp/api/v1beta2/awsmanagedmachinepool_types.go +++ b/exp/api/v1beta2/awsmanagedmachinepool_types.go @@ -100,6 +100,28 @@ type AWSManagedMachinePoolSpec struct { // +optional RoleName string `json:"roleName,omitempty"` + // RolePath sets the path to the role. For more information about paths, see IAM Identifiers + // (https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) + // in the IAM User Guide. + // + // This parameter is optional. If it is not included, it defaults to a slash + // (/). + RolePath string `json:"rolePath,omitempty"` + + // RolePermissionsBoundary sets the ARN of the managed policy that is used + // to set the permissions boundary for the role. + // + // A permissions boundary policy defines the maximum permissions that identity-based + // policies can grant to an entity, but does not grant permissions. Permissions + // boundaries do not define the maximum permissions that a resource-based policy + // can grant to an entity. To learn more, see Permissions boundaries for IAM + // entities (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) + // in the IAM User Guide. + // + // For more information about policy types, see Policy types (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policy-types) + // in the IAM User Guide. + RolePermissionsBoundary string `json:"rolePermissionsBoundary,omitempty"` + // AMIVersion defines the desired AMI release version. If no version number // is supplied then the latest version for the Kubernetes version // will be used diff --git a/pkg/cloud/services/eks/iam/iam.go b/pkg/cloud/services/eks/iam/iam.go index bb4db97670..17bfba658f 100644 --- a/pkg/cloud/services/eks/iam/iam.go +++ b/pkg/cloud/services/eks/iam/iam.go @@ -190,6 +190,8 @@ func (s *IAMService) CreateRole( key string, trustRelationship *iamv1.PolicyDocument, additionalTags infrav1.Tags, + path string, + permissionsBoundary string, ) (*iam.Role, error) { tags := RoleTags(key, additionalTags) @@ -202,6 +204,8 @@ func (s *IAMService) CreateRole( RoleName: aws.String(roleName), Tags: tags, AssumeRolePolicyDocument: aws.String(trustRelationshipJSON), + Path: aws.String(path), + PermissionsBoundary: aws.String(permissionsBoundary), } out, err := s.IAMClient.CreateRole(input) diff --git a/pkg/cloud/services/eks/roles.go b/pkg/cloud/services/eks/roles.go index 7742ace69d..72295acfb9 100644 --- a/pkg/cloud/services/eks/roles.go +++ b/pkg/cloud/services/eks/roles.go @@ -95,7 +95,7 @@ func (s *Service) reconcileControlPlaneIAMRole() error { return fmt.Errorf("getting role %s: %w", *s.scope.ControlPlane.Spec.RoleName, ErrClusterRoleNotFound) } - role, err = s.CreateRole(*s.scope.ControlPlane.Spec.RoleName, s.scope.Name(), eksiam.ControlPlaneTrustRelationship(false), s.scope.AdditionalTags()) + role, err = s.CreateRole(*s.scope.ControlPlane.Spec.RoleName, s.scope.Name(), eksiam.ControlPlaneTrustRelationship(false), s.scope.AdditionalTags(), *s.scope.ControlPlane.Spec.RolePath, *s.scope.ControlPlane.Spec.RolePermissionsBoundary) if err != nil { record.Warnf(s.scope.ControlPlane, "FailedIAMRoleCreation", "Failed to create control plane IAM role %q: %v", *s.scope.ControlPlane.Spec.RoleName, err) @@ -204,7 +204,7 @@ func (s *NodegroupService) reconcileNodegroupIAMRole() error { return ErrNodegroupRoleNotFound } - role, err = s.CreateRole(s.scope.ManagedMachinePool.Spec.RoleName, s.scope.ClusterName(), eksiam.NodegroupTrustRelationship(), s.scope.AdditionalTags()) + role, err = s.CreateRole(s.scope.ManagedMachinePool.Spec.RoleName, s.scope.ClusterName(), eksiam.NodegroupTrustRelationship(), s.scope.AdditionalTags(), s.scope.ManagedMachinePool.Spec.RolePath, s.scope.ManagedMachinePool.Spec.RolePermissionsBoundary) if err != nil { record.Warnf(s.scope.ManagedMachinePool, "FailedIAMRoleCreation", "Failed to create nodegroup IAM role %q: %v", s.scope.RoleName(), err) return err @@ -329,7 +329,7 @@ func (s *FargateService) reconcileFargateIAMRole() (requeue bool, err error) { } createdRole = true - role, err = s.CreateRole(s.scope.RoleName(), s.scope.ClusterName(), eksiam.FargateTrustRelationship(), s.scope.AdditionalTags()) + role, err = s.CreateRole(s.scope.RoleName(), s.scope.ClusterName(), eksiam.FargateTrustRelationship(), s.scope.AdditionalTags(), s.scope.FargateProfile.Spec.RolePath, s.scope.FargateProfile.Spec.RolePermissionsBoundary) if err != nil { record.Warnf(s.scope.FargateProfile, "FailedIAMRoleCreation", "Failed to create fargate IAM role %q: %v", s.scope.RoleName(), err) return false, errors.Wrap(err, "failed to create role")