From cad6e2aff21ace528fde4f263c62554635096152 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Wed, 11 Jun 2025 21:45:55 +0000 Subject: [PATCH 01/25] attempt by Q --- README.md | 39 ++++ pkg/actions/podidentityassociation/creator.go | 12 ++ .../podidentityassociation/creator_test.go | 28 +++ .../iam_role_creator.go | 23 ++ .../podidentityassociation_suite_test.go | 2 +- pkg/actions/podidentityassociation/tasks.go | 24 ++- pkg/actions/podidentityassociation/updater.go | 33 ++- .../podidentityassociation/updater_test.go | 203 ++++++++++-------- .../podidentityassociation/validation.go | 91 ++++++++ pkg/apis/eksctl.io/v1alpha5/iam.go | 9 + pkg/apis/eksctl.io/v1alpha5/validation.go | 48 +++++ .../eksctl.io/v1alpha5/validation_test.go | 65 ++++++ pkg/cfn/builder/iam.go | 47 ++++ 13 files changed, 530 insertions(+), 94 deletions(-) create mode 100644 pkg/actions/podidentityassociation/validation.go diff --git a/README.md b/README.md index f552ee3f53..90a308a1bf 100644 --- a/README.md +++ b/README.md @@ -261,3 +261,42 @@ Do not open security related issues in the open source project. > **_Logo Credits_** > > _Original Gophers drawn by [Ashley McNamara](https://twitter.com/ashleymcnamara), unique E, K, S, C, T & L Gopher identities had been produced with [Gopherize.me](https://github.com/matryer/gopherize.me/)._ + +## Cross-Account Pod Identity Support + +Starting with version X.Y.Z, eksctl supports EKS Pod Identity cross-account access. This feature allows pods running in your EKS cluster to access AWS resources in a different AWS account. + +### Usage + +To create a pod identity association with cross-account access: + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig +metadata: + name: my-cluster + region: us-west-2 + +podIdentityAssociations: +- namespace: default + serviceAccountName: my-service-account + # The source role in the same account as the cluster + roleName: my-source-role + # The target role in a different account + targetRoleARN: arn:aws:iam::123456789012:role/my-target-role + # Optional: Disable session tags + disableSessionTags: false +``` + +### Required IAM Setup + +1. **Source Role (in the cluster account):** + - Must trust the EKS Pod Identity service + - Must have permission to assume the target role + +2. **Target Role (in the target account):** + - Must trust the source role + - Should include an external ID condition in the format: `region/account-id/cluster-name/namespace/service-account-name` + - Must have the necessary permissions to access the target resources + +For more information, see the [EKS Pod Identity documentation](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). diff --git a/pkg/actions/podidentityassociation/creator.go b/pkg/actions/podidentityassociation/creator.go index ef43fb3ce7..2dc770f25f 100644 --- a/pkg/actions/podidentityassociation/creator.go +++ b/pkg/actions/podidentityassociation/creator.go @@ -47,6 +47,18 @@ func (c *Creator) CreateTasks(ctx context.Context, podIdentityAssociations []api } for _, pia := range podIdentityAssociations { pia := pia + + // Validate the pod identity association configuration + if err := api.ValidatePodIdentityAssociation(&pia); err != nil { + taskTree.Append(&tasks.GenericTask{ + Description: fmt.Sprintf("validate pod identity association for service account %q", pia.NameString()), + Doer: func() error { + return fmt.Errorf("invalid pod identity association configuration: %w", err) + }, + }) + continue + } + piaCreationTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, diff --git a/pkg/actions/podidentityassociation/creator_test.go b/pkg/actions/podidentityassociation/creator_test.go index e67a3d2449..0cb3296030 100644 --- a/pkg/actions/podidentityassociation/creator_test.go +++ b/pkg/actions/podidentityassociation/creator_test.go @@ -140,6 +140,34 @@ var _ = Describe("Create", func() { expectedErr: "creating pod identity association", }), + Entry("creates a pod identity association with cross-account access", createPodIdentityAssociationEntry{ + toBeCreated: []api.PodIdentityAssociation{ + { + Namespace: namespace, + ServiceAccountName: serviceAccountName1, + RoleARN: roleARN, + TargetRoleARN: "arn:aws:iam::444455556666:role/TargetRole", + DisableSessionTags: true, + }, + }, + mockEKS: func(provider *mockprovider.MockProvider) { + mockProvider.MockEKS(). + On("CreatePodIdentityAssociation", mock.Anything, mock.Anything). + Run(func(args mock.Arguments) { + Expect(args).To(HaveLen(2)) + input := args[1].(*awseks.CreatePodIdentityAssociationInput) + Expect(*input.ClusterName).To(Equal(clusterName)) + Expect(*input.Namespace).To(Equal(namespace)) + Expect(*input.ServiceAccount).To(Equal(serviceAccountName1)) + Expect(*input.RoleArn).To(Equal(roleARN)) + // Note: TargetRoleArn and DisableSessionTags will be added when AWS SDK is updated + }). + Return(&awseks.CreatePodIdentityAssociationOutput{}, nil). + Once() + }, + expectedCreateStackCalls: 0, + }), + Entry("creates all expected roles and associations successfully", createPodIdentityAssociationEntry{ toBeCreated: []api.PodIdentityAssociation{ { diff --git a/pkg/actions/podidentityassociation/iam_role_creator.go b/pkg/actions/podidentityassociation/iam_role_creator.go index 950a415d81..73e4291052 100644 --- a/pkg/actions/podidentityassociation/iam_role_creator.go +++ b/pkg/actions/podidentityassociation/iam_role_creator.go @@ -3,6 +3,7 @@ package podidentityassociation import ( "context" "fmt" + "strings" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" @@ -29,6 +30,28 @@ func (r *IAMRoleCreator) Create(ctx context.Context, podIdentityAssociation *api ServiceAccountName: podIdentityAssociation.ServiceAccountName, }.IDString() + // If a target role ARN is specified for cross-account access, we need to: + // 1. Add permission to assume the target role + // 2. Configure the external ID for the target role trust relationship + if podIdentityAssociation.TargetRoleARN != "" { + // Extract account ID and role name from the target role ARN + // ARN format: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME + targetRoleARNParts := strings.Split(podIdentityAssociation.TargetRoleARN, ":") + if len(targetRoleARNParts) >= 5 { + targetAccountID := targetRoleARNParts[4] + targetRoleName := strings.TrimPrefix(targetRoleARNParts[5], "role/") + + // Add permission to assume the target role + // This will be added to the role's permission policy + rs.AddAssumeRolePermission(podIdentityAssociation.TargetRoleARN) + + // Add a tag to indicate this role is configured for cross-account access + podIdentityAssociation.Tags["eksctl.io/cross-account-role"] = "true" + podIdentityAssociation.Tags["eksctl.io/target-account-id"] = targetAccountID + podIdentityAssociation.Tags["eksctl.io/target-role-name"] = targetRoleName + } + } + var stackName string if addonName != "" { podIdentityAssociation.Tags[api.AddonNameTag] = addonName diff --git a/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go b/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go index 7fd20eadac..fb9bc49cdb 100644 --- a/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go +++ b/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go @@ -9,5 +9,5 @@ import ( func TestPodIdentityAssociation(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Pod Identity Association Suite") + RunSpecs(t, "PodIdentityAssociation Suite") } diff --git a/pkg/actions/podidentityassociation/tasks.go b/pkg/actions/podidentityassociation/tasks.go index 1b1094b4ed..26c504f4d8 100644 --- a/pkg/actions/podidentityassociation/tasks.go +++ b/pkg/actions/podidentityassociation/tasks.go @@ -43,13 +43,33 @@ func (t *createPodIdentityAssociationTask) Describe() string { func (t *createPodIdentityAssociationTask) Do(errorCh chan error) error { defer close(errorCh) - if _, err := t.eksAPI.CreatePodIdentityAssociation(t.ctx, &awseks.CreatePodIdentityAssociationInput{ + input := &awseks.CreatePodIdentityAssociationInput{ ClusterName: &t.clusterName, Namespace: &t.podIdentityAssociation.Namespace, RoleArn: &t.podIdentityAssociation.RoleARN, ServiceAccount: &t.podIdentityAssociation.ServiceAccountName, Tags: t.podIdentityAssociation.Tags, - }); err != nil { + } + + // Add target role ARN if specified (for cross-account access) + if t.podIdentityAssociation.TargetRoleARN != "" { + // Note: This field will be available in a future AWS SDK update + // For now, we're adding the field to prepare for when the SDK is updated + logger.Info("Target role ARN %q specified for cross-account access", t.podIdentityAssociation.TargetRoleARN) + // TODO: Uncomment when AWS SDK is updated + // input.TargetRoleArn = &t.podIdentityAssociation.TargetRoleARN + } + + // Add disable session tags if specified + if t.podIdentityAssociation.DisableSessionTags { + // Note: This field will be available in a future AWS SDK update + // For now, we're adding the field to prepare for when the SDK is updated + logger.Info("Session tags will be disabled for this pod identity association") + // TODO: Uncomment when AWS SDK is updated + // input.DisableSessionTags = t.podIdentityAssociation.DisableSessionTags + } + + if _, err := t.eksAPI.CreatePodIdentityAssociation(t.ctx, input); err != nil { if t.ignorePodIdentityExistsErr { var inUseErr *ekstypes.ResourceInUseException if errors.As(err, &inUseErr) { diff --git a/pkg/actions/podidentityassociation/updater.go b/pkg/actions/podidentityassociation/updater.go index 967451a415..dc23dc34f3 100644 --- a/pkg/actions/podidentityassociation/updater.go +++ b/pkg/actions/podidentityassociation/updater.go @@ -106,11 +106,31 @@ func (u *Updater) update(ctx context.Context, updateConfig *UpdateConfig, podIde } func (u *Updater) updatePodIdentityAssociation(ctx context.Context, roleARN string, updateConfig *UpdateConfig, podIdentityAssociationID string) error { - if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, &eks.UpdatePodIdentityAssociationInput{ + input := &eks.UpdatePodIdentityAssociationInput{ AssociationId: aws.String(updateConfig.AssociationID), ClusterName: aws.String(u.ClusterName), RoleArn: aws.String(roleARN), - }); err != nil { + } + + // Add target role ARN if specified (for cross-account access) + if updateConfig.PodIdentityAssociation.TargetRoleARN != "" { + // Note: This field will be available in a future AWS SDK update + // For now, we're adding the field to prepare for when the SDK is updated + logger.Info("Target role ARN %q specified for cross-account access", updateConfig.PodIdentityAssociation.TargetRoleARN) + // TODO: Uncomment when AWS SDK is updated + // input.TargetRoleArn = &updateConfig.PodIdentityAssociation.TargetRoleARN + } + + // Add disable session tags if specified + if updateConfig.PodIdentityAssociation.DisableSessionTags { + // Note: This field will be available in a future AWS SDK update + // For now, we're adding the field to prepare for when the SDK is updated + logger.Info("Session tags will be disabled for this pod identity association") + // TODO: Uncomment when AWS SDK is updated + // input.DisableSessionTags = updateConfig.PodIdentityAssociation.DisableSessionTags + } + + if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, input); err != nil { return fmt.Errorf("(associationID: %s, roleARN: %s): %w", updateConfig.AssociationID, roleARN, err) } logger.Info("updated role ARN %q for pod identity association %q", roleARN, podIdentityAssociationID) @@ -185,12 +205,17 @@ func (r *RoleUpdateValidator) ValidateRoleUpdate(pia api.PodIdentityAssociation, if pia.RoleARN == "" { return errors.New("podIdentityAssociation.roleARN is required since the role was not created by eksctl") } - podIDWithRoleARN := api.PodIdentityAssociation{ + + // For cross-account access, we need to allow targetRoleARN and disableSessionTags + podIDWithCrossAccountFields := api.PodIdentityAssociation{ Namespace: pia.Namespace, ServiceAccountName: pia.ServiceAccountName, RoleARN: pia.RoleARN, + TargetRoleARN: pia.TargetRoleARN, + DisableSessionTags: pia.DisableSessionTags, } - if !reflect.DeepEqual(pia, podIDWithRoleARN) { + + if !reflect.DeepEqual(pia, podIDWithCrossAccountFields) { return errors.New("only namespace, serviceAccountName and roleARN can be specified if the role was not created by eksctl") } } diff --git a/pkg/actions/podidentityassociation/updater_test.go b/pkg/actions/podidentityassociation/updater_test.go index 635fd9ff4d..93f0c03083 100644 --- a/pkg/actions/podidentityassociation/updater_test.go +++ b/pkg/actions/podidentityassociation/updater_test.go @@ -184,12 +184,14 @@ var _ = Describe("Pod Identity Update", func() { expectedErr: `error updating pod identity association "default/default": cannot change podIdentityAssociation.roleARN since the role was created by eksctl`, }), - Entry("role ARN specified when the IAM resources were not created by eksctl", updateEntry{ + Entry("update pod identity association with cross-account access", updateEntry{ podIdentityAssociations: []api.PodIdentityAssociation{ { Namespace: "default", ServiceAccountName: "default", - RoleARN: "arn:aws:iam::00000000:role/new-role", + RoleARN: "arn:aws:iam::00000000:role/source-role", + TargetRoleARN: "arn:aws:iam::11111111:role/target-role", + DisableSessionTags: true, }, }, mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { @@ -199,7 +201,7 @@ var _ = Describe("Pod Identity Update", func() { Namespace: "default", ServiceAccountName: "default", }, - updateRoleARN: "arn:aws:iam::00000000:role/new-role", + updateRoleARN: "arn:aws:iam::00000000:role/source-role", }) }, @@ -211,105 +213,29 @@ var _ = Describe("Pod Identity Update", func() { }, }), - Entry("pod identity association has changes", updateEntry{ - podIdentityAssociations: []api.PodIdentityAssociation{ - { - Namespace: "default", - ServiceAccountName: "default", - }, - { - Namespace: "kube-system", - ServiceAccountName: "aws-node", - }, - }, - mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { - podIdentifiers := []podidentityassociation.Identifier{ - { - Namespace: "default", - ServiceAccountName: "default", - }, - { - Namespace: "kube-system", - ServiceAccountName: "aws-node", - }, - } - mockListStackNamesWithIRSAv1(stackManager, podIdentifiers[:1], podIdentifiers[1:]) - describeStackOutputs := []cfntypes.Output{ - { - OutputKey: aws.String(outputs.IAMServiceAccountRoleName), - OutputValue: aws.String("arn:aws:iam::1234567:role/Role"), - }, - } - for _, options := range []mockOptions{ - { - podIdentifier: podIdentifiers[0], - updateRoleARN: "arn:aws:iam::1234567:role/Role", - describeStackOutputs: describeStackOutputs, - makeStackName: makeIRSAv1StackName, - }, - { - podIdentifier: podIdentifiers[1], - updateRoleARN: "arn:aws:iam::1234567:role/Role", - describeStackOutputs: describeStackOutputs, - }, - } { - mockCalls(stackManager, eksAPI, options) - } - - stackManager.MustUpdateStackReturns(nil) - }, - - expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { - Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) - Expect(stackManager.DescribeStackCallCount()).To(Equal(4)) - Expect(stackManager.MustUpdateStackCallCount()).To(Equal(2)) - eksAPI.AssertExpectations(GinkgoT()) - }, - }), - - Entry("pod identity association has no changes", updateEntry{ + Entry("role ARN specified when the IAM resources were not created by eksctl", updateEntry{ podIdentityAssociations: []api.PodIdentityAssociation{ { Namespace: "default", ServiceAccountName: "default", - }, - { - Namespace: "kube-system", - ServiceAccountName: "aws-node", + RoleARN: "arn:aws:iam::00000000:role/new-role", }, }, mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { - podIdentifiers := []podidentityassociation.Identifier{ - { + mockListStackNames(stackManager, nil) + mockCalls(stackManager, eksAPI, mockOptions{ + podIdentifier: podidentityassociation.Identifier{ Namespace: "default", ServiceAccountName: "default", }, - { - Namespace: "kube-system", - ServiceAccountName: "aws-node", - }, - } - mockListStackNames(stackManager, podIdentifiers) - for _, options := range []mockOptions{ - { - podIdentifier: podIdentifiers[0], - }, - { - podIdentifier: podIdentifiers[1], - }, - } { - mockCalls(stackManager, eksAPI, options) - } - - stackManager.MustUpdateStackReturns(&manager.NoChangeError{ - Msg: "no changes found", + updateRoleARN: "arn:aws:iam::00000000:role/new-role", }) }, expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) - Expect(stackManager.DescribeStackCallCount()).To(Equal(2)) - Expect(stackManager.MustUpdateStackCallCount()).To(Equal(2)) + Expect(stackManager.DescribeStackCallCount()).To(Equal(0)) + Expect(stackManager.MustUpdateStackCallCount()).To(Equal(0)) eksAPI.AssertExpectations(GinkgoT()) }, }), @@ -433,6 +359,109 @@ var _ = Describe("Pod Identity Update", func() { eksAPI.AssertExpectations(GinkgoT()) }, }), + + Entry("pod identity association has changes", updateEntry{ + podIdentityAssociations: []api.PodIdentityAssociation{ + { + Namespace: "default", + ServiceAccountName: "default", + }, + { + Namespace: "kube-system", + ServiceAccountName: "aws-node", + }, + }, + mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + podIdentifiers := []podidentityassociation.Identifier{ + { + Namespace: "default", + ServiceAccountName: "default", + }, + { + Namespace: "kube-system", + ServiceAccountName: "aws-node", + }, + } + mockListStackNamesWithIRSAv1(stackManager, podIdentifiers[:1], podIdentifiers[1:]) + describeStackOutputs := []cfntypes.Output{ + { + OutputKey: aws.String(outputs.IAMServiceAccountRoleName), + OutputValue: aws.String("arn:aws:iam::1234567:role/Role"), + }, + } + for _, options := range []mockOptions{ + { + podIdentifier: podIdentifiers[0], + updateRoleARN: "arn:aws:iam::1234567:role/Role", + describeStackOutputs: describeStackOutputs, + makeStackName: makeIRSAv1StackName, + }, + { + podIdentifier: podIdentifiers[1], + updateRoleARN: "arn:aws:iam::1234567:role/Role", + describeStackOutputs: describeStackOutputs, + }, + } { + mockCalls(stackManager, eksAPI, options) + } + + stackManager.MustUpdateStackReturns(nil) + }, + + expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) + Expect(stackManager.DescribeStackCallCount()).To(Equal(4)) + Expect(stackManager.MustUpdateStackCallCount()).To(Equal(2)) + eksAPI.AssertExpectations(GinkgoT()) + }, + }), + + Entry("pod identity association has no changes", updateEntry{ + podIdentityAssociations: []api.PodIdentityAssociation{ + { + Namespace: "default", + ServiceAccountName: "default", + }, + { + Namespace: "kube-system", + ServiceAccountName: "aws-node", + }, + }, + mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + podIdentifiers := []podidentityassociation.Identifier{ + { + Namespace: "default", + ServiceAccountName: "default", + }, + { + Namespace: "kube-system", + ServiceAccountName: "aws-node", + }, + } + mockListStackNames(stackManager, podIdentifiers) + for _, options := range []mockOptions{ + { + podIdentifier: podIdentifiers[0], + }, + { + podIdentifier: podIdentifiers[1], + }, + } { + mockCalls(stackManager, eksAPI, options) + } + + stackManager.MustUpdateStackReturns(&manager.NoChangeError{ + Msg: "no changes found", + }) + }, + + expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) + Expect(stackManager.DescribeStackCallCount()).To(Equal(2)) + Expect(stackManager.MustUpdateStackCallCount()).To(Equal(2)) + eksAPI.AssertExpectations(GinkgoT()) + }, + }), ) }) diff --git a/pkg/actions/podidentityassociation/validation.go b/pkg/actions/podidentityassociation/validation.go new file mode 100644 index 0000000000..b8b40f0046 --- /dev/null +++ b/pkg/actions/podidentityassociation/validation.go @@ -0,0 +1,91 @@ +package podidentityassociation + +import ( + "errors" + "fmt" + "strings" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" +) + +// ValidatePodIdentityAssociation validates a pod identity association configuration. +func ValidatePodIdentityAssociation(pia *api.PodIdentityAssociation) error { + if pia.Namespace == "" { + return errors.New("namespace cannot be empty") + } + + if pia.ServiceAccountName == "" { + return errors.New("serviceAccountName cannot be empty") + } + + // If targetRoleARN is specified, validate it + if pia.TargetRoleARN != "" { + if err := validateRoleARN(pia.TargetRoleARN); err != nil { + return fmt.Errorf("invalid targetRoleARN: %w", err) + } + + // If roleARN is empty but targetRoleARN is specified, we need to create a source role + if pia.RoleARN == "" && pia.RoleName == "" { + // This is fine, we'll create a source role + } else if pia.RoleARN != "" { + // Validate that the source role is in the same account as the cluster + sourceAccountID, err := getAccountIDFromARN(pia.RoleARN) + if err != nil { + return fmt.Errorf("invalid roleARN: %w", err) + } + + targetAccountID, err := getAccountIDFromARN(pia.TargetRoleARN) + if err != nil { + return fmt.Errorf("invalid targetRoleARN: %w", err) + } + + if sourceAccountID == targetAccountID { + return errors.New("targetRoleARN must be in a different account than roleARN for cross-account access") + } + } + } + + return nil +} + +// validateRoleARN validates that the provided string is a valid IAM role ARN. +func validateRoleARN(arn string) error { + if !strings.HasPrefix(arn, "arn:aws:iam::") { + return errors.New("ARN must start with 'arn:aws:iam::'") + } + + parts := strings.Split(arn, ":") + if len(parts) != 6 { + return errors.New("ARN must have 6 parts separated by colons") + } + + if parts[5] == "" || !strings.HasPrefix(parts[5], "role/") { + return errors.New("ARN must end with 'role/ROLE_NAME'") + } + + accountID := parts[4] + if len(accountID) != 12 || !isNumeric(accountID) { + return errors.New("account ID in ARN must be a 12-digit number") + } + + return nil +} + +// getAccountIDFromARN extracts the account ID from an IAM role ARN. +func getAccountIDFromARN(arn string) (string, error) { + parts := strings.Split(arn, ":") + if len(parts) != 6 { + return "", errors.New("ARN must have 6 parts separated by colons") + } + return parts[4], nil +} + +// isNumeric checks if a string contains only digits. +func isNumeric(s string) bool { + for _, c := range s { + if c < '0' || c > '9' { + return false + } + } + return true +} diff --git a/pkg/apis/eksctl.io/v1alpha5/iam.go b/pkg/apis/eksctl.io/v1alpha5/iam.go index 1a446dd5e5..ff6a05e5ce 100644 --- a/pkg/apis/eksctl.io/v1alpha5/iam.go +++ b/pkg/apis/eksctl.io/v1alpha5/iam.go @@ -194,6 +194,15 @@ type PodIdentityAssociation struct { // +optional Tags map[string]string `json:"tags,omitempty"` + + // +optional + // TargetRoleARN is the Amazon Resource Name (ARN) of the IAM role to be chained to the IAM role specified as RoleARN. + // This enables cross-account access where the RoleARN is in the same account as the cluster and TargetRoleARN is in a different account. + TargetRoleARN string `json:"targetRoleARN,omitempty"` + + // +optional + // DisableSessionTags disables the tags that are automatically added to role session by Amazon EKS. + DisableSessionTags bool `json:"disableSessionTags,omitempty"` } func (p PodIdentityAssociation) NameString() string { diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 99693c7b2b..d2b8b726b3 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -1822,3 +1822,51 @@ func validateAddonPodIdentityAssociations(addons []*Addon) error { } return nil } +// ValidatePodIdentityAssociation validates a pod identity association configuration. +func ValidatePodIdentityAssociation(pia *PodIdentityAssociation) error { + if pia.Namespace == "" { + return errors.New("namespace cannot be empty") + } + + if pia.ServiceAccountName == "" { + return errors.New("serviceAccountName cannot be empty") + } + + // If targetRoleARN is specified, validate it + if pia.TargetRoleARN != "" { + if !arn.IsARN(pia.TargetRoleARN) { + return fmt.Errorf("targetRoleARN %q is not a valid ARN", pia.TargetRoleARN) + } + + parsedARN, err := arn.Parse(pia.TargetRoleARN) + if err != nil { + return fmt.Errorf("failed to parse targetRoleARN: %w", err) + } + + if parsedARN.Service != "iam" { + return fmt.Errorf("targetRoleARN must be an IAM role ARN") + } + + if !strings.HasPrefix(parsedARN.Resource, "role/") { + return fmt.Errorf("targetRoleARN must be an IAM role ARN (resource must start with 'role/')") + } + + // If roleARN is specified, validate that the source and target roles are in different accounts + if pia.RoleARN != "" { + if !arn.IsARN(pia.RoleARN) { + return fmt.Errorf("roleARN %q is not a valid ARN", pia.RoleARN) + } + + sourceARN, err := arn.Parse(pia.RoleARN) + if err != nil { + return fmt.Errorf("failed to parse roleARN: %w", err) + } + + if sourceARN.AccountID == parsedARN.AccountID { + return fmt.Errorf("targetRoleARN must be in a different account than roleARN for cross-account access") + } + } + } + + return nil +} diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 6f5cc763e2..37c1c38a36 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -2803,3 +2803,68 @@ func newNodeGroup() *api.NodeGroup { NodeGroupBase: &api.NodeGroupBase{}, } } +var _ = Describe("PodIdentityAssociation validation", func() { + Describe("ValidatePodIdentityAssociation", func() { + It("should pass for a valid pod identity association", func() { + pia := &api.PodIdentityAssociation{ + Namespace: "default", + ServiceAccountName: "my-service-account", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should fail if namespace is empty", func() { + pia := &api.PodIdentityAssociation{ + ServiceAccountName: "my-service-account", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).To(MatchError("namespace cannot be empty")) + }) + + It("should fail if serviceAccountName is empty", func() { + pia := &api.PodIdentityAssociation{ + Namespace: "default", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).To(MatchError("serviceAccountName cannot be empty")) + }) + + It("should pass for a valid cross-account pod identity association", func() { + pia := &api.PodIdentityAssociation{ + Namespace: "default", + ServiceAccountName: "my-service-account", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + TargetRoleARN: "arn:aws:iam::987654321098:role/target-role", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should fail if targetRoleARN is not a valid ARN", func() { + pia := &api.PodIdentityAssociation{ + Namespace: "default", + ServiceAccountName: "my-service-account", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + TargetRoleARN: "not-an-arn", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).To(MatchError(ContainSubstring("targetRoleARN"))) + Expect(err).To(MatchError(ContainSubstring("not a valid ARN"))) + }) + + It("should fail if source and target roles are in the same account", func() { + pia := &api.PodIdentityAssociation{ + Namespace: "default", + ServiceAccountName: "my-service-account", + RoleARN: "arn:aws:iam::123456789012:role/my-role", + TargetRoleARN: "arn:aws:iam::123456789012:role/target-role", + } + err := api.ValidatePodIdentityAssociation(pia) + Expect(err).To(MatchError(ContainSubstring("targetRoleARN must be in a different account than roleARN"))) + }) + }) +}) diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index 2af2858f73..bc6b4df0c0 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -506,6 +506,53 @@ func toMapOfInterfaces(old []api.IAMStatement) []cft.MapOfInterfaces { return new } +// AddAssumeRolePermission adds permission to assume a target role +func (rs *IAMRoleResourceSet) AddAssumeRolePermission(targetRoleARN string) { + if rs.attachPolicy == nil { + rs.attachPolicy = api.InlineDocument{} + } + + // Create or update the policy to include permission to assume the target role + assumeRolePolicy := api.InlineDocument{ + "Version": "2012-10-17", + "Statement": []api.IAMStatement{ + { + Effect: "Allow", + Action: []string{ + "sts:AssumeRole", + "sts:TagSession", + }, + Resource: []string{targetRoleARN}, + }, + }, + } + + // If there's an existing policy, merge the statements + if existingPolicy, ok := rs.attachPolicy["Statement"]; ok { + if statements, ok := existingPolicy.([]interface{}); ok { + newStatements := assumeRolePolicy["Statement"].([]api.IAMStatement) + for _, stmt := range statements { + if stmtMap, ok := stmt.(map[string]interface{}); ok { + // Skip if this is already an AssumeRole statement for the same resource + if action, hasAction := stmtMap["Action"]; hasAction { + if resource, hasResource := stmtMap["Resource"]; hasResource { + if strings.Contains(fmt.Sprintf("%v", action), "AssumeRole") && + strings.Contains(fmt.Sprintf("%v", resource), targetRoleARN) { + return // Statement already exists + } + } + } + } + } + + // Add the new statement + rs.attachPolicy["Statement"] = append(statements, newStatements[0]) + } + } else { + // No existing statements, use the new policy + rs.attachPolicy = assumeRolePolicy + } +} // RenderJSON will render iamserviceaccount stack as JSON func (rs *IAMRoleResourceSet) RenderJSON() ([]byte, error) { return rs.template.RenderJSON() From dbcf34fc940d2497b84dcb0eb15e009df8834a67 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 16 Jun 2025 22:50:30 +0000 Subject: [PATCH 02/25] enable new field in api calls; update tests --- examples/39-pod-identity-association.yaml | 21 ++++++++++----- go.mod | 12 ++++----- go.sum | 24 ++++++++--------- .../podidentityassociation/creator_test.go | 3 ++- pkg/actions/podidentityassociation/tasks.go | 10 ++----- pkg/actions/podidentityassociation/updater.go | 14 +++------- .../podidentityassociation/updater_test.go | 26 +++++++++++++++++-- .../eksctl.io/v1alpha5/assets/schema.json | 15 ++++++++++- 8 files changed, 79 insertions(+), 46 deletions(-) diff --git a/examples/39-pod-identity-association.yaml b/examples/39-pod-identity-association.yaml index 8b8e3c7333..e9f6c278da 100644 --- a/examples/39-pod-identity-association.yaml +++ b/examples/39-pod-identity-association.yaml @@ -15,16 +15,25 @@ addons: tags: team: eks -iam: - podIdentityAssociations: - # roleARN is given, eksctl will only create the pod identity association +iam: + podIdentityAssociations: + # roleARN is given, eksctl will only create the pod identity association - namespace: default serviceAccountName: s3-reader createServiceAccount: true # default is false - roleARN: arn:aws:iam::111122223333:role/role-1 + roleARN: arn:aws:iam::111122223333:role/role-1 + + # Cross-account access example: roleARN is in the same account as the cluster, + # targetRoleARN is in a different account. The pod will get credentials for the target role. + - namespace: default + serviceAccountName: cross-account-s3-reader + createServiceAccount: true + roleARN: arn:aws:iam::111122223333:role/role-a # Role in the same account as the cluster + targetRoleARN: arn:aws:iam::444455556666:role/role-b # Role in a different account + disableSessionTags: true # Optional: disable session tags added by EKS Pod Identity # roleARN is not given, eksctl will first create an IAM role with given roleName using: - # permissionPolicyARNs, wellKnownPolicies and permissionsBoundaryARN + # permissionPolicyARNs, wellKnownPolicies and permissionsBoundaryARN - namespace: dev serviceAccountName: app-cache-access roleName: pod-identity-role-app-cache @@ -50,4 +59,4 @@ iam: - "autoscaling:SetDesiredCapacity" - "autoscaling:TerminateInstanceInAutoScalingGroup" - "ec2:DescribeLaunchTemplateVersions" - Resource: '*' \ No newline at end of file + Resource: '*' diff --git a/go.mod b/go.mod index 3778822cd4..c75fb84725 100644 --- a/go.mod +++ b/go.mod @@ -8,16 +8,16 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b44c2 github.com/aws/aws-sdk-go v1.55.7 - github.com/aws/aws-sdk-go-v2 v1.36.3 + github.com/aws/aws-sdk-go-v2 v1.36.4 github.com/aws/aws-sdk-go-v2/config v1.29.14 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.0 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2 github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.0 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 - github.com/aws/aws-sdk-go-v2/service/eks v1.65.0 + github.com/aws/aws-sdk-go-v2/service/eks v1.66.0 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2 github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 @@ -130,8 +130,8 @@ require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 // indirect github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12 // indirect diff --git a/go.sum b/go.sum index 0e4d285ae1..273bf04fb1 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,8 @@ github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b4 github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b44c2/go.mod h1:RU/lVVsYHNN7Bwr2UmCw5z2aWPcNIHADY49bj082oYM= github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= -github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E= +github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= @@ -116,28 +116,28 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9 github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 h1:/frG8aV09yhCVSOEC2pzktflJJO48NwY3xntHBwxHiA= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33/go.mod h1:8vwASlAcV366M+qxZnjNzCjeastk1Rt1bpSRaGZanGU= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.0 h1:uYhWKm7FhOKF5chyd2QSVXWqchI+ikht+aIkDJUIg9U= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.0/go.mod h1:CDqMoc3KRdZJ8qziW96J35lKH01Wq3B2aihtHj2JbRs= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2 h1:NPslW0T7NPQxKQEwZYA1S0exrPfWqCXO5QyY/kZNUIQ= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2/go.mod h1:bR598CXWah8FyPjkeYvhGM9cdiuDpiyILNCHuviv6aU= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2 h1:o9cuZdZlI9VWMqsNa2mnf2IRsFAROHnaYA1BW3lHGuY= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2/go.mod h1:penaZKzGmqHGZId4EUCBIW/f9l4Y7hQ5NKd45yoCYuI= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0 h1:RaAAMoGAns9TPioFYyvZBvMnNjw4fZCoAlud3MEWHv8= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0/go.mod h1:/BibEr5ksr34abqBTQN213GrNG6GCKCB6WG7CH4zH2w= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.0 h1:t/xT0VNZUj9oQmzQjq7qoQYlX9Mz6a37O3PG0STymFM= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.0/go.mod h1:uo14VBn5cNk/BPGTPz3kyLBxgpgOObgO8lmz+H7Z4Ck= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2 h1:3/bbtfzzGkbhzMUBCwX4BcfBx7YDDjENC2sZvIySKa0= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2/go.mod h1:Wd99awP91azT7t59fylEjtBYazJvNAneRveTthS7g/0= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 h1:4U9dpQZTvJ0Mi1qn8L1hRJ4igFCQYEjwUuOmYkWM5tE= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3/go.mod h1:ygltZT++6Wn2uG4+tqE0NW1MkdEtb5W2O/CFc0xJX/g= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 h1:+4A9SDduLZFlDeXWRmfQ6r8kyEJZQfK6lcg+KwdvWrI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1/go.mod h1:ouvGEfHbLaIlWwpDpOVWPWR+YwO0HDv3vm5tYLq8ImY= -github.com/aws/aws-sdk-go-v2/service/eks v1.65.0 h1:6sbu1/Us6jfguajqZGCSZXPylbs68RSfLWjjUPRAvOI= -github.com/aws/aws-sdk-go-v2/service/eks v1.65.0/go.mod h1:v1xXy6ea0PHtWkjFUvAUh6B/5wv7UF909Nru0dOIJDk= +github.com/aws/aws-sdk-go-v2/service/eks v1.66.0 h1:t3F1y6P7ytAoeOVPVgwHv8XKK88nLBHF/qnsRsTGmhc= +github.com/aws/aws-sdk-go-v2/service/eks v1.66.0/go.mod h1:P2bS5zLBmp8vYlFnKqI2uy7nSw/al941zXYxlcVfuhw= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3 h1:DpyV8LeDf0y7iDaGZ3h1Y+Nh5IaBOR+xj44vVgEEegY= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3/go.mod h1:H232HdqVlSUoqy0cMJYW1TKjcxvGFGFZ20xQG8fOAPw= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2 h1:vX70Z4lNSr7XsioU0uJq5yvxgI50sB66MvD+V/3buS4= diff --git a/pkg/actions/podidentityassociation/creator_test.go b/pkg/actions/podidentityassociation/creator_test.go index 0cb3296030..fc99b21c86 100644 --- a/pkg/actions/podidentityassociation/creator_test.go +++ b/pkg/actions/podidentityassociation/creator_test.go @@ -160,7 +160,8 @@ var _ = Describe("Create", func() { Expect(*input.Namespace).To(Equal(namespace)) Expect(*input.ServiceAccount).To(Equal(serviceAccountName1)) Expect(*input.RoleArn).To(Equal(roleARN)) - // Note: TargetRoleArn and DisableSessionTags will be added when AWS SDK is updated + Expect(*input.TargetRoleArn).To(Equal("arn:aws:iam::444455556666:role/TargetRole")) + Expect(*input.DisableSessionTags).To(BeTrue()) }). Return(&awseks.CreatePodIdentityAssociationOutput{}, nil). Once() diff --git a/pkg/actions/podidentityassociation/tasks.go b/pkg/actions/podidentityassociation/tasks.go index 26c504f4d8..51bad5c01f 100644 --- a/pkg/actions/podidentityassociation/tasks.go +++ b/pkg/actions/podidentityassociation/tasks.go @@ -53,20 +53,14 @@ func (t *createPodIdentityAssociationTask) Do(errorCh chan error) error { // Add target role ARN if specified (for cross-account access) if t.podIdentityAssociation.TargetRoleARN != "" { - // Note: This field will be available in a future AWS SDK update - // For now, we're adding the field to prepare for when the SDK is updated logger.Info("Target role ARN %q specified for cross-account access", t.podIdentityAssociation.TargetRoleARN) - // TODO: Uncomment when AWS SDK is updated - // input.TargetRoleArn = &t.podIdentityAssociation.TargetRoleARN + input.TargetRoleArn = &t.podIdentityAssociation.TargetRoleARN } // Add disable session tags if specified if t.podIdentityAssociation.DisableSessionTags { - // Note: This field will be available in a future AWS SDK update - // For now, we're adding the field to prepare for when the SDK is updated logger.Info("Session tags will be disabled for this pod identity association") - // TODO: Uncomment when AWS SDK is updated - // input.DisableSessionTags = t.podIdentityAssociation.DisableSessionTags + input.DisableSessionTags = &t.podIdentityAssociation.DisableSessionTags } if _, err := t.eksAPI.CreatePodIdentityAssociation(t.ctx, input); err != nil { diff --git a/pkg/actions/podidentityassociation/updater.go b/pkg/actions/podidentityassociation/updater.go index dc23dc34f3..1c31d3518d 100644 --- a/pkg/actions/podidentityassociation/updater.go +++ b/pkg/actions/podidentityassociation/updater.go @@ -114,20 +114,14 @@ func (u *Updater) updatePodIdentityAssociation(ctx context.Context, roleARN stri // Add target role ARN if specified (for cross-account access) if updateConfig.PodIdentityAssociation.TargetRoleARN != "" { - // Note: This field will be available in a future AWS SDK update - // For now, we're adding the field to prepare for when the SDK is updated logger.Info("Target role ARN %q specified for cross-account access", updateConfig.PodIdentityAssociation.TargetRoleARN) - // TODO: Uncomment when AWS SDK is updated - // input.TargetRoleArn = &updateConfig.PodIdentityAssociation.TargetRoleARN + input.TargetRoleArn = &updateConfig.PodIdentityAssociation.TargetRoleARN } // Add disable session tags if specified if updateConfig.PodIdentityAssociation.DisableSessionTags { - // Note: This field will be available in a future AWS SDK update - // For now, we're adding the field to prepare for when the SDK is updated logger.Info("Session tags will be disabled for this pod identity association") - // TODO: Uncomment when AWS SDK is updated - // input.DisableSessionTags = updateConfig.PodIdentityAssociation.DisableSessionTags + input.DisableSessionTags = &updateConfig.PodIdentityAssociation.DisableSessionTags } if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, input); err != nil { @@ -205,7 +199,7 @@ func (r *RoleUpdateValidator) ValidateRoleUpdate(pia api.PodIdentityAssociation, if pia.RoleARN == "" { return errors.New("podIdentityAssociation.roleARN is required since the role was not created by eksctl") } - + // For cross-account access, we need to allow targetRoleARN and disableSessionTags podIDWithCrossAccountFields := api.PodIdentityAssociation{ Namespace: pia.Namespace, @@ -214,7 +208,7 @@ func (r *RoleUpdateValidator) ValidateRoleUpdate(pia api.PodIdentityAssociation, TargetRoleARN: pia.TargetRoleARN, DisableSessionTags: pia.DisableSessionTags, } - + if !reflect.DeepEqual(pia, podIDWithCrossAccountFields) { return errors.New("only namespace, serviceAccountName and roleARN can be specified if the role was not created by eksctl") } diff --git a/pkg/actions/podidentityassociation/updater_test.go b/pkg/actions/podidentityassociation/updater_test.go index 93f0c03083..c21ee6f12b 100644 --- a/pkg/actions/podidentityassociation/updater_test.go +++ b/pkg/actions/podidentityassociation/updater_test.go @@ -70,11 +70,33 @@ var _ = Describe("Pod Identity Update", func() { }, }, nil) if o.updateRoleARN != "" { - eksAPI.On("UpdatePodIdentityAssociation", mock.Anything, &eks.UpdatePodIdentityAssociationInput{ + input := &eks.UpdatePodIdentityAssociationInput{ AssociationId: aws.String(associationID), ClusterName: aws.String(clusterName), RoleArn: aws.String(o.updateRoleARN), - }).Return(&eks.UpdatePodIdentityAssociationOutput{}, nil) + } + + // For the cross-account access test case + if o.podIdentifier.Namespace == "default" && o.podIdentifier.ServiceAccountName == "default" && o.updateRoleARN == "arn:aws:iam::00000000:role/source-role" { + for _, pia := range []api.PodIdentityAssociation{ + { + Namespace: "default", + ServiceAccountName: "default", + RoleARN: "arn:aws:iam::00000000:role/source-role", + TargetRoleARN: "arn:aws:iam::11111111:role/target-role", + DisableSessionTags: true, + }, + } { + if pia.TargetRoleARN != "" { + input.TargetRoleArn = &pia.TargetRoleARN + } + if pia.DisableSessionTags { + input.DisableSessionTags = &pia.DisableSessionTags + } + } + } + + eksAPI.On("UpdatePodIdentityAssociation", mock.Anything, input).Return(&eks.UpdatePodIdentityAssociationOutput{}, nil) } mockStackManager(stackManager, stackName, o.describeStackOutputs, o.describeStackCapabilities) } diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 217d514667..2033caa1d4 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -2513,6 +2513,12 @@ "type": "boolean", "default": "false" }, + "disableSessionTags": { + "type": "boolean", + "description": "disables the tags that are automatically added to role session by Amazon EKS.", + "x-intellij-html-description": "disables the tags that are automatically added to role session by Amazon EKS.", + "default": "false" + }, "namespace": { "type": "string" }, @@ -2544,6 +2550,11 @@ "type": "object", "default": "{}" }, + "targetRoleARN": { + "type": "string", + "description": "Amazon Resource Name (ARN) of the IAM role to be chained to the IAM role specified as RoleARN. This enables cross-account access where the RoleARN is in the same account as the cluster and TargetRoleARN is in a different account.", + "x-intellij-html-description": "Amazon Resource Name (ARN) of the IAM role to be chained to the IAM role specified as RoleARN. This enables cross-account access where the RoleARN is in the same account as the cluster and TargetRoleARN is in a different account." + }, "wellKnownPolicies": { "$ref": "#/definitions/WellKnownPolicies" } @@ -2558,7 +2569,9 @@ "permissionPolicyARNs", "permissionPolicy", "wellKnownPolicies", - "tags" + "tags", + "targetRoleARN", + "disableSessionTags" ], "additionalProperties": false }, From 06ebae54ba1b05a9750246babafa1c365c42c063 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 16 Jun 2025 23:47:10 +0000 Subject: [PATCH 03/25] clean up docs --- examples/39-pod-identity-association.yaml | 18 +++++----- .../src/usage/pod-identity-associations.md | 36 ++++++++++++++++++- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/examples/39-pod-identity-association.yaml b/examples/39-pod-identity-association.yaml index e9f6c278da..0f4ccd6652 100644 --- a/examples/39-pod-identity-association.yaml +++ b/examples/39-pod-identity-association.yaml @@ -23,15 +23,6 @@ iam: createServiceAccount: true # default is false roleARN: arn:aws:iam::111122223333:role/role-1 - # Cross-account access example: roleARN is in the same account as the cluster, - # targetRoleARN is in a different account. The pod will get credentials for the target role. - - namespace: default - serviceAccountName: cross-account-s3-reader - createServiceAccount: true - roleARN: arn:aws:iam::111122223333:role/role-a # Role in the same account as the cluster - targetRoleARN: arn:aws:iam::444455556666:role/role-b # Role in a different account - disableSessionTags: true # Optional: disable session tags added by EKS Pod Identity - # roleARN is not given, eksctl will first create an IAM role with given roleName using: # permissionPolicyARNs, wellKnownPolicies and permissionsBoundaryARN - namespace: dev @@ -60,3 +51,12 @@ iam: - "autoscaling:TerminateInstanceInAutoScalingGroup" - "ec2:DescribeLaunchTemplateVersions" Resource: '*' + + # Cross-account access example: roleARN is in the same account as the cluster, + # targetRoleARN is in a different account. The pod will get credentials for the target role. + - namespace: default + serviceAccountName: cross-account-s3-reader + createServiceAccount: true + roleARN: arn:aws:iam::111122223333:role/role-a # Role in the same account as the cluster + targetRoleARN: arn:aws:iam::444455556666:role/role-b # Role in a different account + disableSessionTags: true # Optional: disable session tags added by EKS Pod Identity diff --git a/userdocs/src/usage/pod-identity-associations.md b/userdocs/src/usage/pod-identity-associations.md index f4645e5fe7..241cd4e253 100644 --- a/userdocs/src/usage/pod-identity-associations.md +++ b/userdocs/src/usage/pod-identity-associations.md @@ -2,7 +2,7 @@ ## Introduction -AWS EKS has introduced a new enhanced mechanism called Pod Identity Association for cluster administrators to configure Kubernetes applications to receive IAM permissions required to connect with AWS services outside of the cluster. Pod Identity Association leverages IRSA, however, it makes it configurable directly through EKS API, eliminating the need for using IAM API altogether. +AWS EKS has introduced a new enhanced mechanism called Pod Identity Association for cluster administrators to configure Kubernetes applications to receive IAM permissions required to connect with AWS services outside of the cluster. Pod Identity Association leverages IRSA, however, it makes it configurable directly through the EKS API, eliminating the need for using IAM API altogether. As a result, IAM roles no longer need to reference an [OIDC provider](/usage/iamserviceaccounts/#how-it-works) and hence won't be tied to a single cluster anymore. This means, IAM roles can now be used across multiple EKS clusters without the need to update the role trust policy each time a new cluster is created. This in turn, eliminates the need for role duplication and simplifies the process of automating IRSA altogether. @@ -412,6 +412,40 @@ The existing OIDC provider trust relationship is always being removed from IAM R eksctl utils migrate-to-pod-identity --cluster my-cluster --approve --remove-oidc-provider-trust-relationship ``` + +## Cross Account Pod Identity Support + +eksctl supports [EKS Pod Identity cross-account access](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html). This feature allows pods running in your EKS cluster to access AWS resources in a different AWS account. + +### Usage + +To create a pod identity association with cross-account access: + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig +metadata: + name: my-cluster + region: us-west-2 + +podIdentityAssociations: +- namespace: default + serviceAccountName: my-service-account + # The source role in the same account as the cluster + roleName: my-source-role + # The target role in a different account + targetRoleARN: arn:aws:iam::123456789012:role/my-target-role + # Optional: Disable session tags + disableSessionTags: false +``` + +### Permissions + +Cross account access requires permissions to be configured on both the source and target accounts, either via roles or resource-based policies. + +For more information, see the [AWS Identity and Access Management documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html). + + ## Further references [Official AWS Userdocs for EKS Add-ons support for pod identities](https://docs.aws.amazon.com/eks/latest/userguide/add-ons-iam.html) From 067f5734f41fd21a79973e354291d0626dc637aa Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 16 Jun 2025 23:47:53 +0000 Subject: [PATCH 04/25] rm dup docs --- README.md | 49 +++++-------------------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 90a308a1bf..336c5425a5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ _Need help? Join [Eksctl Slack][slackjoin]._ ## New: EKS Auto Mode Support -`eksctl` now supports EKS Auto Mode! EKS Auto Mode automates routine tasks for cluster compute, storage, and networking. +`eksctl` now supports EKS Auto Mode! EKS Auto Mode automates routine tasks for cluster compute, storage, and networking. * Learn how to [create an EKS Auto Mode Cluster with eksctl](https://docs.aws.amazon.com/eks/latest/userguide/automode-get-started-eksctl.html). * Review the [eksctl docs](https://github.com/eksctl-io/eksctl/blob/main/userdocs/src/usage/auto-mode.md) for EKS Auto Mode. @@ -196,12 +196,12 @@ Example output: [ℹ] Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "attractive-sculpture-1685534556" in "eu-west-2" [ℹ] CloudWatch logging will not be enabled for cluster "attractive-sculpture-1685534556" in "eu-west-2" [ℹ] you can enable it with 'eksctl utils update-cluster-logging --enable-types={SPECIFY-YOUR-LOG-TYPES-HERE (e.g. all)} --region=eu-west-2 --cluster=attractive-sculpture-1685534556' -[ℹ] -2 sequential tasks: { create cluster control plane "attractive-sculpture-1685534556", - 2 sequential sub-tasks: { +[ℹ] +2 sequential tasks: { create cluster control plane "attractive-sculpture-1685534556", + 2 sequential sub-tasks: { wait for control plane to become ready, create managed nodegroup "ng-ac4c787c", - } + } } [ℹ] building cluster stack "eksctl-attractive-sculpture-1685534556-cluster" [ℹ] deploying stack "eksctl-attractive-sculpture-1685534556-cluster" @@ -261,42 +261,3 @@ Do not open security related issues in the open source project. > **_Logo Credits_** > > _Original Gophers drawn by [Ashley McNamara](https://twitter.com/ashleymcnamara), unique E, K, S, C, T & L Gopher identities had been produced with [Gopherize.me](https://github.com/matryer/gopherize.me/)._ - -## Cross-Account Pod Identity Support - -Starting with version X.Y.Z, eksctl supports EKS Pod Identity cross-account access. This feature allows pods running in your EKS cluster to access AWS resources in a different AWS account. - -### Usage - -To create a pod identity association with cross-account access: - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig -metadata: - name: my-cluster - region: us-west-2 - -podIdentityAssociations: -- namespace: default - serviceAccountName: my-service-account - # The source role in the same account as the cluster - roleName: my-source-role - # The target role in a different account - targetRoleARN: arn:aws:iam::123456789012:role/my-target-role - # Optional: Disable session tags - disableSessionTags: false -``` - -### Required IAM Setup - -1. **Source Role (in the cluster account):** - - Must trust the EKS Pod Identity service - - Must have permission to assume the target role - -2. **Target Role (in the target account):** - - Must trust the source role - - Should include an external ID condition in the format: `region/account-id/cluster-name/namespace/service-account-name` - - Must have the necessary permissions to access the target resources - -For more information, see the [EKS Pod Identity documentation](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). From f6ddde1aff03767998521817717b71f18b6072cf Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 16 Jun 2025 23:53:57 +0000 Subject: [PATCH 05/25] assert type --- pkg/actions/podidentityassociation/creator_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/actions/podidentityassociation/creator_test.go b/pkg/actions/podidentityassociation/creator_test.go index fc99b21c86..316557674f 100644 --- a/pkg/actions/podidentityassociation/creator_test.go +++ b/pkg/actions/podidentityassociation/creator_test.go @@ -155,6 +155,7 @@ var _ = Describe("Create", func() { On("CreatePodIdentityAssociation", mock.Anything, mock.Anything). Run(func(args mock.Arguments) { Expect(args).To(HaveLen(2)) + Expect(args[1]).To(BeAssignableToTypeOf(&awseks.CreatePodIdentityAssociationInput{})) input := args[1].(*awseks.CreatePodIdentityAssociationInput) Expect(*input.ClusterName).To(Equal(clusterName)) Expect(*input.Namespace).To(Equal(namespace)) From 4b24c0f92f04dc39b358c0891cfc8bf6b6bed1ed Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Fri, 20 Jun 2025 18:52:19 +0000 Subject: [PATCH 06/25] update go.mod and generated mocks files --- go.mod | 30 ++++----- go.sum | 30 +++++++++ pkg/actions/addon/mocks/IAMRoleCreator.go | 2 +- pkg/actions/addon/mocks/IAMRoleUpdater.go | 2 +- .../addon/mocks/PodIdentityIAMUpdater.go | 2 +- .../automode/mocks/cluster_role_manager.go | 2 +- .../automode/mocks/node_group_drainer.go | 2 +- pkg/actions/automode/mocks/role_manager.go | 2 +- .../cluster/mocks/auto_mode_deleter.go | 2 +- .../mocks/RoleMigrator.go | 2 +- .../mocks/StackDeleter.go | 2 +- pkg/automode/mocks/stack_creator.go | 2 +- pkg/automode/mocks/stack_deleter.go | 2 +- pkg/awsapi/cloudwatchlogs.go | 22 ++++--- pkg/awsapi/eks.go | 62 +++++++++++++++---- pkg/cfn/manager/mocks/NodeGroupResourceSet.go | 2 +- .../manager/mocks/NodeGroupStackManager.go | 2 +- pkg/ctl/utils/mocks/VPCConfigUpdater.go | 2 +- pkg/eks/mocks/ConfigProvider.go | 2 +- pkg/eks/mocks/KubeNodeGroup.go | 2 +- pkg/eks/mocksv2/ASG.go | 2 +- pkg/eks/mocksv2/CloudFormation.go | 2 +- pkg/eks/mocksv2/CloudTrail.go | 2 +- pkg/eks/mocksv2/CloudWatchLogs.go | 2 +- pkg/eks/mocksv2/CredentialsProvider.go | 2 +- pkg/eks/mocksv2/EC2.go | 2 +- pkg/eks/mocksv2/EKS.go | 2 +- pkg/eks/mocksv2/ELB.go | 2 +- pkg/eks/mocksv2/ELBV2.go | 2 +- pkg/eks/mocksv2/IAM.go | 2 +- pkg/eks/mocksv2/Outposts.go | 2 +- pkg/eks/mocksv2/SSM.go | 2 +- pkg/eks/mocksv2/STS.go | 2 +- 33 files changed, 136 insertions(+), 66 deletions(-) diff --git a/go.mod b/go.mod index c75fb84725..72bb6ba3cf 100644 --- a/go.mod +++ b/go.mod @@ -8,24 +8,24 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b44c2 github.com/aws/aws-sdk-go v1.55.7 - github.com/aws/aws-sdk-go-v2 v1.36.4 + github.com/aws/aws-sdk-go-v2 v1.36.5 github.com/aws/aws-sdk-go-v2/config v1.29.14 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2 - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2 - github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3 + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 - github.com/aws/aws-sdk-go-v2/service/eks v1.66.0 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2 - github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 + github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5 + github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 - github.com/aws/aws-sdk-go-v2/service/outposts v1.50.1 - github.com/aws/aws-sdk-go-v2/service/ssm v1.59.0 + github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3 + github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3 github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 - github.com/aws/smithy-go v1.22.3 + github.com/aws/smithy-go v1.22.4 github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20250219002025-c3b5cd3d2fd9 github.com/benjamintf1/unmarshalledmatchers v1.0.0 github.com/blang/semver/v4 v4.0.0 @@ -128,10 +128,10 @@ require ( github.com/ashanbrown/forbidigo v1.6.0 // indirect github.com/ashanbrown/makezero v1.2.0 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 // indirect github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12 // indirect diff --git a/go.sum b/go.sum index 273bf04fb1..abc0bfb03f 100644 --- a/go.sum +++ b/go.sum @@ -108,8 +108,12 @@ github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E= github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= +github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= @@ -118,34 +122,54 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mln github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 h1:/frG8aV09yhCVSOEC2pzktflJJO48NwY3xntHBwxHiA= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33/go.mod h1:8vwASlAcV366M+qxZnjNzCjeastk1Rt1bpSRaGZanGU= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2 h1:NPslW0T7NPQxKQEwZYA1S0exrPfWqCXO5QyY/kZNUIQ= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2/go.mod h1:bR598CXWah8FyPjkeYvhGM9cdiuDpiyILNCHuviv6aU= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 h1:0BmpSm5x2rpB9D2K2OAoOc1cZTUJpw1OiQj86ZT8RTg= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0/go.mod h1:6U/Xm5bBkZGCTxH3NE9+hPKEpCFCothGn/gwytsr1Mk= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2 h1:o9cuZdZlI9VWMqsNa2mnf2IRsFAROHnaYA1BW3lHGuY= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2/go.mod h1:penaZKzGmqHGZId4EUCBIW/f9l4Y7hQ5NKd45yoCYuI= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3 h1:aic9qcLAqsmeYCfXElUnZOB/GRBIV2lFd1pQeJs9sVY= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3/go.mod h1:xU79X14UC0F8sEJCRTWwINzlQ4jacpEFpRESLHRHfoY= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0 h1:RaAAMoGAns9TPioFYyvZBvMnNjw4fZCoAlud3MEWHv8= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0/go.mod h1:/BibEr5ksr34abqBTQN213GrNG6GCKCB6WG7CH4zH2w= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 h1:wSQwBOXa1EV81WiVWLZ8fCrJ7wlwcfqSexEiv9OjPrA= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3/go.mod h1:5N4LfimBXTCtqKr0tZKfcte5UswFb7SJZV+LiQUZsGk= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2 h1:3/bbtfzzGkbhzMUBCwX4BcfBx7YDDjENC2sZvIySKa0= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2/go.mod h1:Wd99awP91azT7t59fylEjtBYazJvNAneRveTthS7g/0= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 h1:e5cbPZYTIY2nUEFieZUfVdINOiCTvChOMPfdLnmiLzs= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0/go.mod h1:UseIHRfrm7PqeZo6fcTb6FUCXzCnh1KJbQbmOfxArGM= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 h1:4U9dpQZTvJ0Mi1qn8L1hRJ4igFCQYEjwUuOmYkWM5tE= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3/go.mod h1:ygltZT++6Wn2uG4+tqE0NW1MkdEtb5W2O/CFc0xJX/g= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 h1:+4A9SDduLZFlDeXWRmfQ6r8kyEJZQfK6lcg+KwdvWrI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1/go.mod h1:ouvGEfHbLaIlWwpDpOVWPWR+YwO0HDv3vm5tYLq8ImY= github.com/aws/aws-sdk-go-v2/service/eks v1.66.0 h1:t3F1y6P7ytAoeOVPVgwHv8XKK88nLBHF/qnsRsTGmhc= github.com/aws/aws-sdk-go-v2/service/eks v1.66.0/go.mod h1:P2bS5zLBmp8vYlFnKqI2uy7nSw/al941zXYxlcVfuhw= +github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 h1:sD1y3G4WXw1GjK95L5dBXPFXNWl/O8GMradUojUYqCg= +github.com/aws/aws-sdk-go-v2/service/eks v1.66.1/go.mod h1:Qj90srO2HigGG5x8Ro6RxixxqiSjZjF91WTEVpnsjAs= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3 h1:DpyV8LeDf0y7iDaGZ3h1Y+Nh5IaBOR+xj44vVgEEegY= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3/go.mod h1:H232HdqVlSUoqy0cMJYW1TKjcxvGFGFZ20xQG8fOAPw= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6 h1:9grU/+HRwLXJV8XUjEPThJj/H+0oHkeNBFpSSfZekeg= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6/go.mod h1:N4fs285CsnBHlAkzBpQapefR/noggTyF09fWs72EzB4= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2 h1:vX70Z4lNSr7XsioU0uJq5yvxgI50sB66MvD+V/3buS4= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2/go.mod h1:xnCC3vFBfOKpU6PcsCKL2ktgBTZfOwTGxj6V8/X3IS4= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5 h1:5BOPLqErxakBnKKKbFkuICL3ZXueX2x5aGQgFfIWnj8= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5/go.mod h1:E+At5Cto6ntT+qaNs3RpJKsx1GaFaNB3zzNUFhHL8DE= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12 h1:uH6GOnGSvVN9MCk6o3+HvZFpdqL7AzJKNOTM/6l+3/s= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12/go.mod h1:6qtp53AQg7KEeYrsp430PNlmVVO9qK0Xw8nddE1y+ow= github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 h1:G6+UzGvubaet9QOh0664E9JeT+b6Zvop3AChozRqkrA= github.com/aws/aws-sdk-go-v2/service/iam v1.42.0/go.mod h1:mPJkGQzeCoPs82ElNILor2JzZgYENr4UaSKUT8K27+c= +github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 h1:IrauIGCnD90jXDFpAKYzCgrbagk/Yta4L+zxcVLOA58= +github.com/aws/aws-sdk-go-v2/service/iam v1.42.2/go.mod h1:QRtwvoAGc59uxv4vQHPKr75SLzhYCRSoETxAA98r6O4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.6.1 h1:7SuukGpyIgF5EiAbf1dZRxP+xSnY1WjiHBjL08fjJeE= @@ -158,6 +182,8 @@ github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 h1:RivOtUH3eEu6SWnUMFHKAW4MqDOz github.com/aws/aws-sdk-go-v2/service/kms v1.38.3/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk= github.com/aws/aws-sdk-go-v2/service/outposts v1.50.1 h1:G86crad1x3w4G/6fQUrYODmeGB0ptErRTLCxB1EMnlE= github.com/aws/aws-sdk-go-v2/service/outposts v1.50.1/go.mod h1:2V3R0VgqiX+jSmn3dNq0yglSf1YuwxCJjsO6ME3XYxs= +github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3 h1:WjXG23ryEdlCLl2vSoEuGHYfbgxQ/ilZuDhfTHqMwm0= +github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3/go.mod h1:XiGs3zv9ejL2VLM77wccs1qBnsmyAFnWs5Fs6iptvWY= github.com/aws/aws-sdk-go-v2/service/pricing v1.32.17 h1:EtZFyL/uhaXlHjIwHW0KSJvppg+Ie1fzQ3wEXLEUj0I= github.com/aws/aws-sdk-go-v2/service/pricing v1.32.17/go.mod h1:l7bufyRvU+8mY0Z1BNWbWvjr59dlj9YrLKmeiz5CJ30= github.com/aws/aws-sdk-go-v2/service/route53 v1.48.8 h1:abeu0IVRqYXSts7Tl1Yoi/BxC59xdXYX0uVSN0fbPOk= @@ -168,6 +194,8 @@ github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15 h1:KRXf9/NWjoRgj2WJbX13GNjBPQ1 github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15/go.mod h1:1CY54O4jz8BzgH2d6KyrzKWr2bAoqKsqUv2YZUGwMLE= github.com/aws/aws-sdk-go-v2/service/ssm v1.59.0 h1:KWArCwA/WkuHWKfygkNz0B6YS6OvdgoJUaJHX0Qby1s= github.com/aws/aws-sdk-go-v2/service/ssm v1.59.0/go.mod h1:PUWUl5MDiYNQkUHN9Pyd9kgtA/YhbxnSnHP+yQqzrM8= +github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3 h1:LU+VzAtElJqi84EBkMSGq6hhIMO3fuCDKRItQpaHBlw= +github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3/go.mod h1:IyVabkWrs8SNdOEZLyFFcW9bUltV4G6OQS0s6H20PHg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= @@ -176,6 +204,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/Xv github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20250219002025-c3b5cd3d2fd9 h1:fopAsvwV3w+MGIX3oWqq0YmwL+lr/ik+wXt0gyDaEEY= github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20250219002025-c3b5cd3d2fd9/go.mod h1:0pDSM0ZubQLD0W2The2kS55orAFDZb0ETrtYOq2iCqI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= diff --git a/pkg/actions/addon/mocks/IAMRoleCreator.go b/pkg/actions/addon/mocks/IAMRoleCreator.go index dba9484d73..75c29510ca 100644 --- a/pkg/actions/addon/mocks/IAMRoleCreator.go +++ b/pkg/actions/addon/mocks/IAMRoleCreator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/addon/mocks/IAMRoleUpdater.go b/pkg/actions/addon/mocks/IAMRoleUpdater.go index 47f8003a96..aaec853800 100644 --- a/pkg/actions/addon/mocks/IAMRoleUpdater.go +++ b/pkg/actions/addon/mocks/IAMRoleUpdater.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/addon/mocks/PodIdentityIAMUpdater.go b/pkg/actions/addon/mocks/PodIdentityIAMUpdater.go index d27a115845..620d851593 100644 --- a/pkg/actions/addon/mocks/PodIdentityIAMUpdater.go +++ b/pkg/actions/addon/mocks/PodIdentityIAMUpdater.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/automode/mocks/cluster_role_manager.go b/pkg/actions/automode/mocks/cluster_role_manager.go index 3fc3419fd6..9085a3b62c 100644 --- a/pkg/actions/automode/mocks/cluster_role_manager.go +++ b/pkg/actions/automode/mocks/cluster_role_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/automode/mocks/node_group_drainer.go b/pkg/actions/automode/mocks/node_group_drainer.go index 5e81788eeb..1b23dc8ee5 100644 --- a/pkg/actions/automode/mocks/node_group_drainer.go +++ b/pkg/actions/automode/mocks/node_group_drainer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/automode/mocks/role_manager.go b/pkg/actions/automode/mocks/role_manager.go index 0bc8791ff9..0f7d07fc81 100644 --- a/pkg/actions/automode/mocks/role_manager.go +++ b/pkg/actions/automode/mocks/role_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/cluster/mocks/auto_mode_deleter.go b/pkg/actions/cluster/mocks/auto_mode_deleter.go index cf1e6aad1d..7427695620 100644 --- a/pkg/actions/cluster/mocks/auto_mode_deleter.go +++ b/pkg/actions/cluster/mocks/auto_mode_deleter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/podidentityassociation/mocks/RoleMigrator.go b/pkg/actions/podidentityassociation/mocks/RoleMigrator.go index 37072d6deb..f2d060dbfc 100644 --- a/pkg/actions/podidentityassociation/mocks/RoleMigrator.go +++ b/pkg/actions/podidentityassociation/mocks/RoleMigrator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/actions/podidentityassociation/mocks/StackDeleter.go b/pkg/actions/podidentityassociation/mocks/StackDeleter.go index ad94a864f8..c0d3b05006 100644 --- a/pkg/actions/podidentityassociation/mocks/StackDeleter.go +++ b/pkg/actions/podidentityassociation/mocks/StackDeleter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/automode/mocks/stack_creator.go b/pkg/automode/mocks/stack_creator.go index 4a9d912604..bf610a1b9d 100644 --- a/pkg/automode/mocks/stack_creator.go +++ b/pkg/automode/mocks/stack_creator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/automode/mocks/stack_deleter.go b/pkg/automode/mocks/stack_deleter.go index 8bdf5c9ddd..408a666ae2 100644 --- a/pkg/automode/mocks/stack_deleter.go +++ b/pkg/automode/mocks/stack_deleter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/awsapi/cloudwatchlogs.go b/pkg/awsapi/cloudwatchlogs.go index 02bfcdbc77..5740aacbe6 100644 --- a/pkg/awsapi/cloudwatchlogs.go +++ b/pkg/awsapi/cloudwatchlogs.go @@ -1135,11 +1135,11 @@ type CloudWatchLogs interface { // - The maximum batch size is 1,048,576 bytes. This size is calculated as the // sum of all event messages in UTF-8, plus 26 bytes for each log event. // - // - None of the log events in the batch can be more than 2 hours in the future. + // - Events more than 2 hours in the future are rejected while processing + // remaining valid events. // - // - None of the log events in the batch can be more than 14 days in the past. - // Also, none of the log events can be from earlier than the retention period of - // the log group. + // - Events older than 14 days or preceding the log group's retention period are + // rejected while processing remaining valid events. // // - The log events in the batch must be in chronological order by their // timestamp. The timestamp is the time that the event occurred, expressed as the @@ -1148,17 +1148,21 @@ type CloudWatchLogs interface { // timestamp is specified in .NET format: yyyy-mm-ddThh:mm:ss . For example, // 2017-09-15T13:45:30 .) // - // - A batch of log events in a single request cannot span more than 24 hours. + // - A batch of log events in a single request must be in a chronological order. // Otherwise, the operation fails. // // - Each log event can be no larger than 1 MB. // // - The maximum number of log events in a batch is 10,000. // - // - The quota of five requests per second per log stream has been removed. - // Instead, PutLogEvents actions are throttled based on a per-second per-account - // quota. You can request an increase to the per-second throttling quota by using - // the Service Quotas service. + // - For valid events (within 14 days in the past to 2 hours in future), the + // time span in a single batch cannot exceed 24 hours. Otherwise, the operation + // fails. + // + // The quota of five requests per second per log stream has been removed. Instead, + // PutLogEvents actions are throttled based on a per-second per-account quota. You + // can request an increase to the per-second throttling quota by using the Service + // Quotas service. // // If a call to PutLogEvents returns "UnrecognizedClientException" the most likely // cause is a non-valid Amazon Web Services access key ID or secret key. diff --git a/pkg/awsapi/eks.go b/pkg/awsapi/eks.go index df5def3362..4539bd7c73 100644 --- a/pkg/awsapi/eks.go +++ b/pkg/awsapi/eks.go @@ -84,7 +84,9 @@ type EKS interface { // You can use the endpointPublicAccess and endpointPrivateAccess parameters to // enable or disable public and private access to your cluster's Kubernetes API // server endpoint. By default, public access is enabled, and private access is - // disabled. For more information, see [Amazon EKS Cluster Endpoint Access Control]in the Amazon EKS User Guide . + // disabled. The endpoint domain name and IP address family depends on the value of + // the ipFamily for the cluster. For more information, see [Amazon EKS Cluster Endpoint Access Control] in the Amazon EKS User + // Guide . // // You can use the logging parameter to enable or disable exporting the Kubernetes // control plane logs for your cluster to CloudWatch Logs. By default, cluster @@ -170,20 +172,36 @@ type EKS interface { CreateNodegroup(ctx context.Context, params *eks.CreateNodegroupInput, optFns ...func(*Options)) (*eks.CreateNodegroupOutput, error) // Creates an EKS Pod Identity association between a service account in an Amazon // EKS cluster and an IAM role with EKS Pod Identity. Use EKS Pod Identity to give - // temporary IAM credentials to pods and the credentials are rotated automatically. + // temporary IAM credentials to Pods and the credentials are rotated automatically. // // Amazon EKS Pod Identity associations provide the ability to manage credentials // for your applications, similar to the way that Amazon EC2 instance profiles // provide credentials to Amazon EC2 instances. // - // If a pod uses a service account that has an association, Amazon EKS sets - // environment variables in the containers of the pod. The environment variables + // If a Pod uses a service account that has an association, Amazon EKS sets + // environment variables in the containers of the Pod. The environment variables // configure the Amazon Web Services SDKs, including the Command Line Interface, to // use the EKS Pod Identity credentials. // - // Pod Identity is a simpler method than IAM roles for service accounts, as this - // method doesn't use OIDC identity providers. Additionally, you can configure a - // role for Pod Identity once, and reuse it across clusters. + // EKS Pod Identity is a simpler method than IAM roles for service accounts, as + // this method doesn't use OIDC identity providers. Additionally, you can configure + // a role for EKS Pod Identity once, and reuse it across clusters. + // + // Similar to Amazon Web Services IAM behavior, EKS Pod Identity associations are + // eventually consistent, and may take several seconds to be effective after the + // initial API call returns successfully. You must design your applications to + // account for these potential delays. We recommend that you don’t include + // association create/updates in the critical, high-availability code paths of your + // application. Instead, make changes in a separate initialization or setup routine + // that you run less frequently. + // + // You can set a target IAM role in the same or a different account for advanced + // scenarios. With a target role, EKS Pod Identity automatically performs two role + // assumptions in sequence: first assuming the role in the association that is in + // this account, then using those credentials to assume the target IAM role. This + // process provides your Pod with temporary credentials that have the permissions + // defined in the target role, allowing secure access to resources in another + // Amazon Web Services account. CreatePodIdentityAssociation(ctx context.Context, params *eks.CreatePodIdentityAssociationInput, optFns ...func(*Options)) (*eks.CreatePodIdentityAssociationOutput, error) // Deletes an access entry. // @@ -394,7 +412,7 @@ type EKS interface { // // - You can also use this API operation to enable or disable public and private // access to your cluster's Kubernetes API server endpoint. By default, public - // access is enabled, and private access is disabled. For more information, see [Amazon EKS cluster endpoint access control] + // access is enabled, and private access is disabled. For more information, see [Cluster API server endpoint] // in the Amazon EKS User Guide . // // - You can also use this API operation to choose different subnets and @@ -421,9 +439,9 @@ type EKS interface { // // [Amazon EKS Cluster control plane logs]: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html // + // [Cluster API server endpoint]: https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html // [CloudWatch Pricing]: http://aws.amazon.com/cloudwatch/pricing/ // [https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html]: https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html - // [Amazon EKS cluster endpoint access control]: https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html UpdateClusterConfig(ctx context.Context, params *eks.UpdateClusterConfigInput, optFns ...func(*Options)) (*eks.UpdateClusterConfigOutput, error) // Updates an Amazon EKS cluster to the specified Kubernetes version. Your cluster // continues to function during the update. The response output includes an update @@ -485,10 +503,28 @@ type EKS interface { // [Amazon EKS optimized Amazon Linux AMI versions]: https://docs.aws.amazon.com/eks/latest/userguide/eks-linux-ami-versions.html // [Amazon EKS optimized Windows AMI versions]: https://docs.aws.amazon.com/eks/latest/userguide/eks-ami-versions-windows.html UpdateNodegroupVersion(ctx context.Context, params *eks.UpdateNodegroupVersionInput, optFns ...func(*Options)) (*eks.UpdateNodegroupVersionOutput, error) - // Updates a EKS Pod Identity association. Only the IAM role can be changed; an - // association can't be moved between clusters, namespaces, or service accounts. If - // you need to edit the namespace or service account, you need to delete the - // association and then create a new association with your desired settings. + // Updates a EKS Pod Identity association. In an update, you can change the IAM + // role, the target IAM role, or disableSessionTags . You must change at least one + // of these in an update. An association can't be moved between clusters, + // namespaces, or service accounts. If you need to edit the namespace or service + // account, you need to delete the association and then create a new association + // with your desired settings. + // + // Similar to Amazon Web Services IAM behavior, EKS Pod Identity associations are + // eventually consistent, and may take several seconds to be effective after the + // initial API call returns successfully. You must design your applications to + // account for these potential delays. We recommend that you don’t include + // association create/updates in the critical, high-availability code paths of your + // application. Instead, make changes in a separate initialization or setup routine + // that you run less frequently. + // + // You can set a target IAM role in the same or a different account for advanced + // scenarios. With a target role, EKS Pod Identity automatically performs two role + // assumptions in sequence: first assuming the role in the association that is in + // this account, then using those credentials to assume the target IAM role. This + // process provides your Pod with temporary credentials that have the permissions + // defined in the target role, allowing secure access to resources in another + // Amazon Web Services account. UpdatePodIdentityAssociation(ctx context.Context, params *eks.UpdatePodIdentityAssociationInput, optFns ...func(*Options)) (*eks.UpdatePodIdentityAssociationOutput, error) } diff --git a/pkg/cfn/manager/mocks/NodeGroupResourceSet.go b/pkg/cfn/manager/mocks/NodeGroupResourceSet.go index f62a8c011d..a68456db15 100644 --- a/pkg/cfn/manager/mocks/NodeGroupResourceSet.go +++ b/pkg/cfn/manager/mocks/NodeGroupResourceSet.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/cfn/manager/mocks/NodeGroupStackManager.go b/pkg/cfn/manager/mocks/NodeGroupStackManager.go index e35f765633..28c046209a 100644 --- a/pkg/cfn/manager/mocks/NodeGroupStackManager.go +++ b/pkg/cfn/manager/mocks/NodeGroupStackManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/ctl/utils/mocks/VPCConfigUpdater.go b/pkg/ctl/utils/mocks/VPCConfigUpdater.go index 1c37f53f12..0796f546a1 100644 --- a/pkg/ctl/utils/mocks/VPCConfigUpdater.go +++ b/pkg/ctl/utils/mocks/VPCConfigUpdater.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/eks/mocks/ConfigProvider.go b/pkg/eks/mocks/ConfigProvider.go index e7cd62e79a..4380123faa 100644 --- a/pkg/eks/mocks/ConfigProvider.go +++ b/pkg/eks/mocks/ConfigProvider.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/eks/mocks/KubeNodeGroup.go b/pkg/eks/mocks/KubeNodeGroup.go index b33faaf9c5..12fac1f5f6 100644 --- a/pkg/eks/mocks/KubeNodeGroup.go +++ b/pkg/eks/mocks/KubeNodeGroup.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks diff --git a/pkg/eks/mocksv2/ASG.go b/pkg/eks/mocksv2/ASG.go index 7927912ebd..07633a19b6 100644 --- a/pkg/eks/mocksv2/ASG.go +++ b/pkg/eks/mocksv2/ASG.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/CloudFormation.go b/pkg/eks/mocksv2/CloudFormation.go index c09bbdadd7..5d22e80642 100644 --- a/pkg/eks/mocksv2/CloudFormation.go +++ b/pkg/eks/mocksv2/CloudFormation.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/CloudTrail.go b/pkg/eks/mocksv2/CloudTrail.go index e903b46e3c..75202ece67 100644 --- a/pkg/eks/mocksv2/CloudTrail.go +++ b/pkg/eks/mocksv2/CloudTrail.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/CloudWatchLogs.go b/pkg/eks/mocksv2/CloudWatchLogs.go index 0d85b07b38..976bec79f9 100644 --- a/pkg/eks/mocksv2/CloudWatchLogs.go +++ b/pkg/eks/mocksv2/CloudWatchLogs.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/CredentialsProvider.go b/pkg/eks/mocksv2/CredentialsProvider.go index abf7af735b..130923f2e2 100644 --- a/pkg/eks/mocksv2/CredentialsProvider.go +++ b/pkg/eks/mocksv2/CredentialsProvider.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/EC2.go b/pkg/eks/mocksv2/EC2.go index d3d4968dc6..1748381eae 100644 --- a/pkg/eks/mocksv2/EC2.go +++ b/pkg/eks/mocksv2/EC2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/EKS.go b/pkg/eks/mocksv2/EKS.go index d6d178b41c..319089da23 100644 --- a/pkg/eks/mocksv2/EKS.go +++ b/pkg/eks/mocksv2/EKS.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/ELB.go b/pkg/eks/mocksv2/ELB.go index 75983c5efa..1373f0b1dc 100644 --- a/pkg/eks/mocksv2/ELB.go +++ b/pkg/eks/mocksv2/ELB.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/ELBV2.go b/pkg/eks/mocksv2/ELBV2.go index d151f03ea8..3f8eda77ad 100644 --- a/pkg/eks/mocksv2/ELBV2.go +++ b/pkg/eks/mocksv2/ELBV2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/IAM.go b/pkg/eks/mocksv2/IAM.go index 580b4a7252..8b7bee80d3 100644 --- a/pkg/eks/mocksv2/IAM.go +++ b/pkg/eks/mocksv2/IAM.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/Outposts.go b/pkg/eks/mocksv2/Outposts.go index 06bca944c5..92faa11f19 100644 --- a/pkg/eks/mocksv2/Outposts.go +++ b/pkg/eks/mocksv2/Outposts.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/SSM.go b/pkg/eks/mocksv2/SSM.go index 8898626ecc..24cf62efd4 100644 --- a/pkg/eks/mocksv2/SSM.go +++ b/pkg/eks/mocksv2/SSM.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 diff --git a/pkg/eks/mocksv2/STS.go b/pkg/eks/mocksv2/STS.go index 714c662e63..eca90152f0 100644 --- a/pkg/eks/mocksv2/STS.go +++ b/pkg/eks/mocksv2/STS.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocksv2 From 5b70b9ceb0a77123c7a2217124b72fcb1153498f Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 23 Jun 2025 06:28:27 +0000 Subject: [PATCH 07/25] update docs to reference tutorial instead of IAM page --- userdocs/src/usage/pod-identity-associations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdocs/src/usage/pod-identity-associations.md b/userdocs/src/usage/pod-identity-associations.md index 241cd4e253..ed5559b6ad 100644 --- a/userdocs/src/usage/pod-identity-associations.md +++ b/userdocs/src/usage/pod-identity-associations.md @@ -443,7 +443,7 @@ podIdentityAssociations: Cross account access requires permissions to be configured on both the source and target accounts, either via roles or resource-based policies. -For more information, see the [AWS Identity and Access Management documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html). +For a walkthrough of setting this up, see ["Amazon EKS Pod Identity streamlines cross account access"](https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-streamlines-cross-account-access/). ## Further references From ebd3d31e10b8fa3c73683cd088b8bdfd8644d924 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 23 Jun 2025 07:14:35 +0000 Subject: [PATCH 08/25] update docs --- .../podidentityassociation/updater_test.go | 58 +++++++++---------- .../src/usage/pod-identity-associations.md | 49 ++++++++++------ 2 files changed, 60 insertions(+), 47 deletions(-) diff --git a/pkg/actions/podidentityassociation/updater_test.go b/pkg/actions/podidentityassociation/updater_test.go index c21ee6f12b..e6dfe5c2bd 100644 --- a/pkg/actions/podidentityassociation/updater_test.go +++ b/pkg/actions/podidentityassociation/updater_test.go @@ -206,35 +206,6 @@ var _ = Describe("Pod Identity Update", func() { expectedErr: `error updating pod identity association "default/default": cannot change podIdentityAssociation.roleARN since the role was created by eksctl`, }), - Entry("update pod identity association with cross-account access", updateEntry{ - podIdentityAssociations: []api.PodIdentityAssociation{ - { - Namespace: "default", - ServiceAccountName: "default", - RoleARN: "arn:aws:iam::00000000:role/source-role", - TargetRoleARN: "arn:aws:iam::11111111:role/target-role", - DisableSessionTags: true, - }, - }, - mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { - mockListStackNames(stackManager, nil) - mockCalls(stackManager, eksAPI, mockOptions{ - podIdentifier: podidentityassociation.Identifier{ - Namespace: "default", - ServiceAccountName: "default", - }, - updateRoleARN: "arn:aws:iam::00000000:role/source-role", - }) - }, - - expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { - Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) - Expect(stackManager.DescribeStackCallCount()).To(Equal(0)) - Expect(stackManager.MustUpdateStackCallCount()).To(Equal(0)) - eksAPI.AssertExpectations(GinkgoT()) - }, - }), - Entry("role ARN specified when the IAM resources were not created by eksctl", updateEntry{ podIdentityAssociations: []api.PodIdentityAssociation{ { @@ -484,6 +455,35 @@ var _ = Describe("Pod Identity Update", func() { eksAPI.AssertExpectations(GinkgoT()) }, }), + + Entry("update pod identity association with cross-account access", updateEntry{ + podIdentityAssociations: []api.PodIdentityAssociation{ + { + Namespace: "default", + ServiceAccountName: "default", + RoleARN: "arn:aws:iam::00000000:role/source-role", + TargetRoleARN: "arn:aws:iam::11111111:role/target-role", + DisableSessionTags: true, + }, + }, + mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + mockListStackNames(stackManager, nil) + mockCalls(stackManager, eksAPI, mockOptions{ + podIdentifier: podidentityassociation.Identifier{ + Namespace: "default", + ServiceAccountName: "default", + }, + updateRoleARN: "arn:aws:iam::00000000:role/source-role", + }) + }, + + expectedCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { + Expect(stackManager.ListPodIdentityStackNamesCallCount()).To(Equal(1)) + Expect(stackManager.DescribeStackCallCount()).To(Equal(0)) + Expect(stackManager.MustUpdateStackCallCount()).To(Equal(0)) + eksAPI.AssertExpectations(GinkgoT()) + }, + }), ) }) diff --git a/userdocs/src/usage/pod-identity-associations.md b/userdocs/src/usage/pod-identity-associations.md index ed5559b6ad..5327dbbf59 100644 --- a/userdocs/src/usage/pod-identity-associations.md +++ b/userdocs/src/usage/pod-identity-associations.md @@ -412,14 +412,15 @@ The existing OIDC provider trust relationship is always being removed from IAM R eksctl utils migrate-to-pod-identity --cluster my-cluster --approve --remove-oidc-provider-trust-relationship ``` - ## Cross Account Pod Identity Support eksctl supports [EKS Pod Identity cross-account access](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html). This feature allows pods running in your EKS cluster to access AWS resources in a different AWS account. ### Usage -To create a pod identity association with cross-account access: +To create a pod identity association with cross-account access, first set up IAM Roles and Policies allowing access from a source AWS account (with the cluster) to a target AWS account (with the resources the cluster can access). For an example of this, see ["Amazon EKS Pod Identity streamlines cross account access."](https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-streamlines-cross-account-access/) + +Once an IAM Role is configured in each account, use eksctl to create the pod identity associations: ```yaml apiVersion: eksctl.io/v1alpha5 @@ -427,24 +428,36 @@ kind: ClusterConfig metadata: name: my-cluster region: us-west-2 + version: "1.32" -podIdentityAssociations: -- namespace: default - serviceAccountName: my-service-account - # The source role in the same account as the cluster - roleName: my-source-role - # The target role in a different account - targetRoleARN: arn:aws:iam::123456789012:role/my-target-role - # Optional: Disable session tags - disableSessionTags: false -``` - -### Permissions - -Cross account access requires permissions to be configured on both the source and target accounts, either via roles or resource-based policies. - -For a walkthrough of setting this up, see ["Amazon EKS Pod Identity streamlines cross account access"](https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-streamlines-cross-account-access/). +addons: + - name: vpc-cni + - name: coredns + - name: kube-proxy + - name: eks-pod-identity-agent +iam: + podIdentityAssociations: + - namespace: default + serviceAccountName: demo-app-sa + createServiceAccount: true + # The source role in the same account as the cluster + roleARN: arn:aws:iam::111122223333:role/account-a-role + # The target role in a different account + targetRoleARN: arn:aws:iam::999988887777:role/account-b-role + # Optional: Disable session tags + disableSessionTags: false + +managedNodeGroups: + - name: my-cluster + instanceType: m6a.large + privateNetworking: true + minSize: 2 + desiredCapacity: 2 + maxSize: 3 +``` + +Update the target role's trust relationship to accept an `sts.ExternalId` matching the service account. ## Further references From 16544d8b139d271bc06ee811f16aada2f7fc11ab Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 23 Jun 2025 07:23:41 +0000 Subject: [PATCH 09/25] adjust ids --- userdocs/src/usage/pod-identity-associations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/userdocs/src/usage/pod-identity-associations.md b/userdocs/src/usage/pod-identity-associations.md index 5327dbbf59..75cc6a9ee5 100644 --- a/userdocs/src/usage/pod-identity-associations.md +++ b/userdocs/src/usage/pod-identity-associations.md @@ -442,9 +442,9 @@ iam: serviceAccountName: demo-app-sa createServiceAccount: true # The source role in the same account as the cluster - roleARN: arn:aws:iam::111122223333:role/account-a-role + roleARN: arn:aws:iam::1111111111:role/account-a-role # The target role in a different account - targetRoleARN: arn:aws:iam::999988887777:role/account-b-role + targetRoleARN: arn:aws:iam::2222222222:role/account-b-role # Optional: Disable session tags disableSessionTags: false From d6a934f9829d4deeb3df90b11d0731bd8a1b56ef Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 23 Jun 2025 07:24:52 +0000 Subject: [PATCH 10/25] update doc --- userdocs/src/usage/pod-identity-associations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/userdocs/src/usage/pod-identity-associations.md b/userdocs/src/usage/pod-identity-associations.md index 75cc6a9ee5..de61f5b040 100644 --- a/userdocs/src/usage/pod-identity-associations.md +++ b/userdocs/src/usage/pod-identity-associations.md @@ -426,6 +426,8 @@ Once an IAM Role is configured in each account, use eksctl to create the pod ide apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: + # The cluster name and service account name should match the target + # account policy's trust relationship. name: my-cluster region: us-west-2 version: "1.32" @@ -457,8 +459,6 @@ managedNodeGroups: maxSize: 3 ``` -Update the target role's trust relationship to accept an `sts.ExternalId` matching the service account. - ## Further references [Official AWS Userdocs for EKS Add-ons support for pod identities](https://docs.aws.amazon.com/eks/latest/userguide/add-ons-iam.html) From 46170a33d0575de1989b9848489826014cceef2a Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Tue, 24 Jun 2025 17:41:47 +0000 Subject: [PATCH 11/25] rm duplicate validation file --- .../podidentityassociation_suite_test.go | 2 +- .../podidentityassociation/validation.go | 91 ------------------- 2 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 pkg/actions/podidentityassociation/validation.go diff --git a/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go b/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go index fb9bc49cdb..7fd20eadac 100644 --- a/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go +++ b/pkg/actions/podidentityassociation/podidentityassociation_suite_test.go @@ -9,5 +9,5 @@ import ( func TestPodIdentityAssociation(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "PodIdentityAssociation Suite") + RunSpecs(t, "Pod Identity Association Suite") } diff --git a/pkg/actions/podidentityassociation/validation.go b/pkg/actions/podidentityassociation/validation.go deleted file mode 100644 index b8b40f0046..0000000000 --- a/pkg/actions/podidentityassociation/validation.go +++ /dev/null @@ -1,91 +0,0 @@ -package podidentityassociation - -import ( - "errors" - "fmt" - "strings" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" -) - -// ValidatePodIdentityAssociation validates a pod identity association configuration. -func ValidatePodIdentityAssociation(pia *api.PodIdentityAssociation) error { - if pia.Namespace == "" { - return errors.New("namespace cannot be empty") - } - - if pia.ServiceAccountName == "" { - return errors.New("serviceAccountName cannot be empty") - } - - // If targetRoleARN is specified, validate it - if pia.TargetRoleARN != "" { - if err := validateRoleARN(pia.TargetRoleARN); err != nil { - return fmt.Errorf("invalid targetRoleARN: %w", err) - } - - // If roleARN is empty but targetRoleARN is specified, we need to create a source role - if pia.RoleARN == "" && pia.RoleName == "" { - // This is fine, we'll create a source role - } else if pia.RoleARN != "" { - // Validate that the source role is in the same account as the cluster - sourceAccountID, err := getAccountIDFromARN(pia.RoleARN) - if err != nil { - return fmt.Errorf("invalid roleARN: %w", err) - } - - targetAccountID, err := getAccountIDFromARN(pia.TargetRoleARN) - if err != nil { - return fmt.Errorf("invalid targetRoleARN: %w", err) - } - - if sourceAccountID == targetAccountID { - return errors.New("targetRoleARN must be in a different account than roleARN for cross-account access") - } - } - } - - return nil -} - -// validateRoleARN validates that the provided string is a valid IAM role ARN. -func validateRoleARN(arn string) error { - if !strings.HasPrefix(arn, "arn:aws:iam::") { - return errors.New("ARN must start with 'arn:aws:iam::'") - } - - parts := strings.Split(arn, ":") - if len(parts) != 6 { - return errors.New("ARN must have 6 parts separated by colons") - } - - if parts[5] == "" || !strings.HasPrefix(parts[5], "role/") { - return errors.New("ARN must end with 'role/ROLE_NAME'") - } - - accountID := parts[4] - if len(accountID) != 12 || !isNumeric(accountID) { - return errors.New("account ID in ARN must be a 12-digit number") - } - - return nil -} - -// getAccountIDFromARN extracts the account ID from an IAM role ARN. -func getAccountIDFromARN(arn string) (string, error) { - parts := strings.Split(arn, ":") - if len(parts) != 6 { - return "", errors.New("ARN must have 6 parts separated by colons") - } - return parts[4], nil -} - -// isNumeric checks if a string contains only digits. -func isNumeric(s string) bool { - for _, c := range s { - if c < '0' || c > '9' { - return false - } - } - return true -} From 12201b653b60df90e065c26dee072d6cb0e7d8d9 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Tue, 24 Jun 2025 17:42:42 +0000 Subject: [PATCH 12/25] rm dup validation --- pkg/actions/podidentityassociation/creator.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pkg/actions/podidentityassociation/creator.go b/pkg/actions/podidentityassociation/creator.go index 2dc770f25f..ef43fb3ce7 100644 --- a/pkg/actions/podidentityassociation/creator.go +++ b/pkg/actions/podidentityassociation/creator.go @@ -47,18 +47,6 @@ func (c *Creator) CreateTasks(ctx context.Context, podIdentityAssociations []api } for _, pia := range podIdentityAssociations { pia := pia - - // Validate the pod identity association configuration - if err := api.ValidatePodIdentityAssociation(&pia); err != nil { - taskTree.Append(&tasks.GenericTask{ - Description: fmt.Sprintf("validate pod identity association for service account %q", pia.NameString()), - Doer: func() error { - return fmt.Errorf("invalid pod identity association configuration: %w", err) - }, - }) - continue - } - piaCreationTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, From dffd6bfc0c94a3b55149d089cd2f4992c208acf8 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Tue, 24 Jun 2025 17:58:46 +0000 Subject: [PATCH 13/25] run tidy --- go.sum | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/go.sum b/go.sum index abc0bfb03f..4cf9ef2a33 100644 --- a/go.sum +++ b/go.sum @@ -106,12 +106,8 @@ github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b4 github.com/aws/amazon-ec2-instance-selector/v3 v3.1.1-0.20250224180552-36eea73b44c2/go.mod h1:RU/lVVsYHNN7Bwr2UmCw5z2aWPcNIHADY49bj082oYM= github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E= -github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= @@ -120,54 +116,34 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9 github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 h1:/frG8aV09yhCVSOEC2pzktflJJO48NwY3xntHBwxHiA= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33/go.mod h1:8vwASlAcV366M+qxZnjNzCjeastk1Rt1bpSRaGZanGU= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2 h1:NPslW0T7NPQxKQEwZYA1S0exrPfWqCXO5QyY/kZNUIQ= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.53.2/go.mod h1:bR598CXWah8FyPjkeYvhGM9cdiuDpiyILNCHuviv6aU= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 h1:0BmpSm5x2rpB9D2K2OAoOc1cZTUJpw1OiQj86ZT8RTg= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0/go.mod h1:6U/Xm5bBkZGCTxH3NE9+hPKEpCFCothGn/gwytsr1Mk= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2 h1:o9cuZdZlI9VWMqsNa2mnf2IRsFAROHnaYA1BW3lHGuY= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.59.2/go.mod h1:penaZKzGmqHGZId4EUCBIW/f9l4Y7hQ5NKd45yoCYuI= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3 h1:aic9qcLAqsmeYCfXElUnZOB/GRBIV2lFd1pQeJs9sVY= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3/go.mod h1:xU79X14UC0F8sEJCRTWwINzlQ4jacpEFpRESLHRHfoY= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0 h1:RaAAMoGAns9TPioFYyvZBvMnNjw4fZCoAlud3MEWHv8= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.0/go.mod h1:/BibEr5ksr34abqBTQN213GrNG6GCKCB6WG7CH4zH2w= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 h1:wSQwBOXa1EV81WiVWLZ8fCrJ7wlwcfqSexEiv9OjPrA= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3/go.mod h1:5N4LfimBXTCtqKr0tZKfcte5UswFb7SJZV+LiQUZsGk= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2 h1:3/bbtfzzGkbhzMUBCwX4BcfBx7YDDjENC2sZvIySKa0= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.50.2/go.mod h1:Wd99awP91azT7t59fylEjtBYazJvNAneRveTthS7g/0= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 h1:e5cbPZYTIY2nUEFieZUfVdINOiCTvChOMPfdLnmiLzs= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0/go.mod h1:UseIHRfrm7PqeZo6fcTb6FUCXzCnh1KJbQbmOfxArGM= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 h1:4U9dpQZTvJ0Mi1qn8L1hRJ4igFCQYEjwUuOmYkWM5tE= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3/go.mod h1:ygltZT++6Wn2uG4+tqE0NW1MkdEtb5W2O/CFc0xJX/g= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 h1:+4A9SDduLZFlDeXWRmfQ6r8kyEJZQfK6lcg+KwdvWrI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1/go.mod h1:ouvGEfHbLaIlWwpDpOVWPWR+YwO0HDv3vm5tYLq8ImY= -github.com/aws/aws-sdk-go-v2/service/eks v1.66.0 h1:t3F1y6P7ytAoeOVPVgwHv8XKK88nLBHF/qnsRsTGmhc= -github.com/aws/aws-sdk-go-v2/service/eks v1.66.0/go.mod h1:P2bS5zLBmp8vYlFnKqI2uy7nSw/al941zXYxlcVfuhw= github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 h1:sD1y3G4WXw1GjK95L5dBXPFXNWl/O8GMradUojUYqCg= github.com/aws/aws-sdk-go-v2/service/eks v1.66.1/go.mod h1:Qj90srO2HigGG5x8Ro6RxixxqiSjZjF91WTEVpnsjAs= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3 h1:DpyV8LeDf0y7iDaGZ3h1Y+Nh5IaBOR+xj44vVgEEegY= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.3/go.mod h1:H232HdqVlSUoqy0cMJYW1TKjcxvGFGFZ20xQG8fOAPw= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6 h1:9grU/+HRwLXJV8XUjEPThJj/H+0oHkeNBFpSSfZekeg= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6/go.mod h1:N4fs285CsnBHlAkzBpQapefR/noggTyF09fWs72EzB4= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2 h1:vX70Z4lNSr7XsioU0uJq5yvxgI50sB66MvD+V/3buS4= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.2/go.mod h1:xnCC3vFBfOKpU6PcsCKL2ktgBTZfOwTGxj6V8/X3IS4= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5 h1:5BOPLqErxakBnKKKbFkuICL3ZXueX2x5aGQgFfIWnj8= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5/go.mod h1:E+At5Cto6ntT+qaNs3RpJKsx1GaFaNB3zzNUFhHL8DE= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12 h1:uH6GOnGSvVN9MCk6o3+HvZFpdqL7AzJKNOTM/6l+3/s= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12/go.mod h1:6qtp53AQg7KEeYrsp430PNlmVVO9qK0Xw8nddE1y+ow= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 h1:G6+UzGvubaet9QOh0664E9JeT+b6Zvop3AChozRqkrA= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.0/go.mod h1:mPJkGQzeCoPs82ElNILor2JzZgYENr4UaSKUT8K27+c= github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 h1:IrauIGCnD90jXDFpAKYzCgrbagk/Yta4L+zxcVLOA58= github.com/aws/aws-sdk-go-v2/service/iam v1.42.2/go.mod h1:QRtwvoAGc59uxv4vQHPKr75SLzhYCRSoETxAA98r6O4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= @@ -180,8 +156,6 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.14 h1:fgdkfsxTehqPc github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.14/go.mod h1:wMxQ3OE8fiM8z2YRAeb2J8DLTTWMvRyYYuQOs26AbTQ= github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 h1:RivOtUH3eEu6SWnUMFHKAW4MqDOzWn1vGQ3S38Y5QMg= github.com/aws/aws-sdk-go-v2/service/kms v1.38.3/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk= -github.com/aws/aws-sdk-go-v2/service/outposts v1.50.1 h1:G86crad1x3w4G/6fQUrYODmeGB0ptErRTLCxB1EMnlE= -github.com/aws/aws-sdk-go-v2/service/outposts v1.50.1/go.mod h1:2V3R0VgqiX+jSmn3dNq0yglSf1YuwxCJjsO6ME3XYxs= github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3 h1:WjXG23ryEdlCLl2vSoEuGHYfbgxQ/ilZuDhfTHqMwm0= github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3/go.mod h1:XiGs3zv9ejL2VLM77wccs1qBnsmyAFnWs5Fs6iptvWY= github.com/aws/aws-sdk-go-v2/service/pricing v1.32.17 h1:EtZFyL/uhaXlHjIwHW0KSJvppg+Ie1fzQ3wEXLEUj0I= @@ -192,8 +166,6 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.77.1 h1:5bI9tJL2Z0FGFtp/LPDv0eyliFBHC github.com/aws/aws-sdk-go-v2/service/s3 v1.77.1/go.mod h1:njj3tSJONkfdLt4y6X8pyqeM6sJLNZxmzctKKV+n1GM= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15 h1:KRXf9/NWjoRgj2WJbX13GNjBPQ1SxUYLnIfXTz08mWs= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15/go.mod h1:1CY54O4jz8BzgH2d6KyrzKWr2bAoqKsqUv2YZUGwMLE= -github.com/aws/aws-sdk-go-v2/service/ssm v1.59.0 h1:KWArCwA/WkuHWKfygkNz0B6YS6OvdgoJUaJHX0Qby1s= -github.com/aws/aws-sdk-go-v2/service/ssm v1.59.0/go.mod h1:PUWUl5MDiYNQkUHN9Pyd9kgtA/YhbxnSnHP+yQqzrM8= github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3 h1:LU+VzAtElJqi84EBkMSGq6hhIMO3fuCDKRItQpaHBlw= github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3/go.mod h1:IyVabkWrs8SNdOEZLyFFcW9bUltV4G6OQS0s6H20PHg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= @@ -202,8 +174,6 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0c github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= -github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= -github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20250219002025-c3b5cd3d2fd9 h1:fopAsvwV3w+MGIX3oWqq0YmwL+lr/ik+wXt0gyDaEEY= From 96e1a25c635ad99c47c34ece1994b0f24a57c885 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Tue, 24 Jun 2025 18:22:04 +0000 Subject: [PATCH 14/25] cleanup comments --- .../podidentityassociation/iam_role_creator.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pkg/actions/podidentityassociation/iam_role_creator.go b/pkg/actions/podidentityassociation/iam_role_creator.go index 73e4291052..eeb1c34c3b 100644 --- a/pkg/actions/podidentityassociation/iam_role_creator.go +++ b/pkg/actions/podidentityassociation/iam_role_creator.go @@ -30,22 +30,15 @@ func (r *IAMRoleCreator) Create(ctx context.Context, podIdentityAssociation *api ServiceAccountName: podIdentityAssociation.ServiceAccountName, }.IDString() - // If a target role ARN is specified for cross-account access, we need to: - // 1. Add permission to assume the target role - // 2. Configure the external ID for the target role trust relationship + // If a target role ARN is specified for cross-account access, we need to add permission to assume the target role if podIdentityAssociation.TargetRoleARN != "" { - // Extract account ID and role name from the target role ARN - // ARN format: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME targetRoleARNParts := strings.Split(podIdentityAssociation.TargetRoleARN, ":") if len(targetRoleARNParts) >= 5 { targetAccountID := targetRoleARNParts[4] targetRoleName := strings.TrimPrefix(targetRoleARNParts[5], "role/") - - // Add permission to assume the target role - // This will be added to the role's permission policy + rs.AddAssumeRolePermission(podIdentityAssociation.TargetRoleARN) - - // Add a tag to indicate this role is configured for cross-account access + podIdentityAssociation.Tags["eksctl.io/cross-account-role"] = "true" podIdentityAssociation.Tags["eksctl.io/target-account-id"] = targetAccountID podIdentityAssociation.Tags["eksctl.io/target-role-name"] = targetRoleName From 0bdd5c633c7e66b2d31e81b04dfc2c9e7e0b13b7 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Wed, 2 Jul 2025 18:34:11 +0000 Subject: [PATCH 15/25] fmt --- pkg/cfn/builder/iam.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index bc6b4df0c0..a46efb8f3a 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -536,15 +536,15 @@ func (rs *IAMRoleResourceSet) AddAssumeRolePermission(targetRoleARN string) { // Skip if this is already an AssumeRole statement for the same resource if action, hasAction := stmtMap["Action"]; hasAction { if resource, hasResource := stmtMap["Resource"]; hasResource { - if strings.Contains(fmt.Sprintf("%v", action), "AssumeRole") && - strings.Contains(fmt.Sprintf("%v", resource), targetRoleARN) { + if strings.Contains(fmt.Sprintf("%v", action), "AssumeRole") && + strings.Contains(fmt.Sprintf("%v", resource), targetRoleARN) { return // Statement already exists } } } } } - + // Add the new statement rs.attachPolicy["Statement"] = append(statements, newStatements[0]) } @@ -553,6 +553,7 @@ func (rs *IAMRoleResourceSet) AddAssumeRolePermission(targetRoleARN string) { rs.attachPolicy = assumeRolePolicy } } + // RenderJSON will render iamserviceaccount stack as JSON func (rs *IAMRoleResourceSet) RenderJSON() ([]byte, error) { return rs.template.RenderJSON() From bf6a520c97c25b807c9f2cbe3d9e487c56d79da2 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Wed, 9 Jul 2025 21:52:10 +0000 Subject: [PATCH 16/25] Do not add permissions to created role: just use policies passed in by user --- examples/39-pod-identity-association.yaml | 13 + go.mod | 10 +- go.sum | 20 +- .../iam_role_creator.go | 16 - pkg/awsapi/cloudformation.go | 59 ++++ pkg/awsapi/elasticloadbalancingv2.go | 35 ++- pkg/awsapi/iam.go | 288 ++++++++++++------ pkg/cfn/builder/iam.go | 48 --- 8 files changed, 303 insertions(+), 186 deletions(-) diff --git a/examples/39-pod-identity-association.yaml b/examples/39-pod-identity-association.yaml index 0f4ccd6652..d5c1da46d9 100644 --- a/examples/39-pod-identity-association.yaml +++ b/examples/39-pod-identity-association.yaml @@ -60,3 +60,16 @@ iam: roleARN: arn:aws:iam::111122223333:role/role-a # Role in the same account as the cluster targetRoleARN: arn:aws:iam::444455556666:role/role-b # Role in a different account disableSessionTags: true # Optional: disable session tags added by EKS Pod Identity + + # Cross-account access example: roleARN is not defined, but instead the customer provides + # the permissionPolicyARNs for the role that will be created. + - namespace: default + serviceAccountName: cross-account-s3-reader-b + createServiceAccount: true + roleName: pod-identity-role-cross-account + targetRoleARN: arn:aws:iam::444455556666:role/role-b + # This permission policy must allow assumption of the targetRoleARN + permissionPolicyARNs: ["arn:aws:iam::111122223333:policy/my-cross-account-permission-policy"] + wellKnownPolicies: + autoScaler: true + externalDNS: true diff --git a/go.mod b/go.mod index 72bb6ba3cf..7f8c127edc 100644 --- a/go.mod +++ b/go.mod @@ -12,18 +12,18 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.29.14 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0 github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5 - github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.46.0 + github.com/aws/aws-sdk-go-v2/service/iam v1.43.0 github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 - github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3 - github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3 + github.com/aws/aws-sdk-go-v2/service/outposts v1.51.0 + github.com/aws/aws-sdk-go-v2/service/ssm v1.60.0 github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 github.com/aws/smithy-go v1.22.4 github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20250219002025-c3b5cd3d2fd9 diff --git a/go.sum b/go.sum index 4cf9ef2a33..20c20811a5 100644 --- a/go.sum +++ b/go.sum @@ -126,8 +126,8 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33 h1:/frG8aV09yhCVSOEC2pzktflJJO github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.33/go.mod h1:8vwASlAcV366M+qxZnjNzCjeastk1Rt1bpSRaGZanGU= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 h1:0BmpSm5x2rpB9D2K2OAoOc1cZTUJpw1OiQj86ZT8RTg= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0/go.mod h1:6U/Xm5bBkZGCTxH3NE9+hPKEpCFCothGn/gwytsr1Mk= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3 h1:aic9qcLAqsmeYCfXElUnZOB/GRBIV2lFd1pQeJs9sVY= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.60.3/go.mod h1:xU79X14UC0F8sEJCRTWwINzlQ4jacpEFpRESLHRHfoY= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0 h1:1nVq2bvAANTPAfipKBOtbP1ebqTpJrOsxNqwb6ybCG8= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0/go.mod h1:xU79X14UC0F8sEJCRTWwINzlQ4jacpEFpRESLHRHfoY= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 h1:wSQwBOXa1EV81WiVWLZ8fCrJ7wlwcfqSexEiv9OjPrA= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3/go.mod h1:5N4LfimBXTCtqKr0tZKfcte5UswFb7SJZV+LiQUZsGk= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 h1:e5cbPZYTIY2nUEFieZUfVdINOiCTvChOMPfdLnmiLzs= @@ -140,12 +140,12 @@ github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 h1:sD1y3G4WXw1GjK95L5dBXPFXNWl/ github.com/aws/aws-sdk-go-v2/service/eks v1.66.1/go.mod h1:Qj90srO2HigGG5x8Ro6RxixxqiSjZjF91WTEVpnsjAs= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6 h1:9grU/+HRwLXJV8XUjEPThJj/H+0oHkeNBFpSSfZekeg= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.29.6/go.mod h1:N4fs285CsnBHlAkzBpQapefR/noggTyF09fWs72EzB4= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5 h1:5BOPLqErxakBnKKKbFkuICL3ZXueX2x5aGQgFfIWnj8= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.45.5/go.mod h1:E+At5Cto6ntT+qaNs3RpJKsx1GaFaNB3zzNUFhHL8DE= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.46.0 h1:3nrkDeiPreARHMoqvS+umxTKcDVkqnRPlz01/kVgG7U= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.46.0/go.mod h1:E+At5Cto6ntT+qaNs3RpJKsx1GaFaNB3zzNUFhHL8DE= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12 h1:uH6GOnGSvVN9MCk6o3+HvZFpdqL7AzJKNOTM/6l+3/s= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.36.12/go.mod h1:6qtp53AQg7KEeYrsp430PNlmVVO9qK0Xw8nddE1y+ow= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 h1:IrauIGCnD90jXDFpAKYzCgrbagk/Yta4L+zxcVLOA58= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.2/go.mod h1:QRtwvoAGc59uxv4vQHPKr75SLzhYCRSoETxAA98r6O4= +github.com/aws/aws-sdk-go-v2/service/iam v1.43.0 h1:/ZZo3N8iU/PLsRSCjjlT/J+n4N8kqfTO7BwW1GE+G50= +github.com/aws/aws-sdk-go-v2/service/iam v1.43.0/go.mod h1:QRtwvoAGc59uxv4vQHPKr75SLzhYCRSoETxAA98r6O4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.6.1 h1:7SuukGpyIgF5EiAbf1dZRxP+xSnY1WjiHBjL08fjJeE= @@ -156,8 +156,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.14 h1:fgdkfsxTehqPc github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.14/go.mod h1:wMxQ3OE8fiM8z2YRAeb2J8DLTTWMvRyYYuQOs26AbTQ= github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 h1:RivOtUH3eEu6SWnUMFHKAW4MqDOzWn1vGQ3S38Y5QMg= github.com/aws/aws-sdk-go-v2/service/kms v1.38.3/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk= -github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3 h1:WjXG23ryEdlCLl2vSoEuGHYfbgxQ/ilZuDhfTHqMwm0= -github.com/aws/aws-sdk-go-v2/service/outposts v1.50.3/go.mod h1:XiGs3zv9ejL2VLM77wccs1qBnsmyAFnWs5Fs6iptvWY= +github.com/aws/aws-sdk-go-v2/service/outposts v1.51.0 h1:HLhXiT+SOlYunW0KlOUSS2jVy2OUQEdo54umLSf1Bmk= +github.com/aws/aws-sdk-go-v2/service/outposts v1.51.0/go.mod h1:XiGs3zv9ejL2VLM77wccs1qBnsmyAFnWs5Fs6iptvWY= github.com/aws/aws-sdk-go-v2/service/pricing v1.32.17 h1:EtZFyL/uhaXlHjIwHW0KSJvppg+Ie1fzQ3wEXLEUj0I= github.com/aws/aws-sdk-go-v2/service/pricing v1.32.17/go.mod h1:l7bufyRvU+8mY0Z1BNWbWvjr59dlj9YrLKmeiz5CJ30= github.com/aws/aws-sdk-go-v2/service/route53 v1.48.8 h1:abeu0IVRqYXSts7Tl1Yoi/BxC59xdXYX0uVSN0fbPOk= @@ -166,8 +166,8 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.77.1 h1:5bI9tJL2Z0FGFtp/LPDv0eyliFBHC github.com/aws/aws-sdk-go-v2/service/s3 v1.77.1/go.mod h1:njj3tSJONkfdLt4y6X8pyqeM6sJLNZxmzctKKV+n1GM= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15 h1:KRXf9/NWjoRgj2WJbX13GNjBPQ1SxUYLnIfXTz08mWs= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.15/go.mod h1:1CY54O4jz8BzgH2d6KyrzKWr2bAoqKsqUv2YZUGwMLE= -github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3 h1:LU+VzAtElJqi84EBkMSGq6hhIMO3fuCDKRItQpaHBlw= -github.com/aws/aws-sdk-go-v2/service/ssm v1.59.3/go.mod h1:IyVabkWrs8SNdOEZLyFFcW9bUltV4G6OQS0s6H20PHg= +github.com/aws/aws-sdk-go-v2/service/ssm v1.60.0 h1:YuMspnzt8uHda7a6A/29WCbjMJygyiyTvq480lnsScQ= +github.com/aws/aws-sdk-go-v2/service/ssm v1.60.0/go.mod h1:IyVabkWrs8SNdOEZLyFFcW9bUltV4G6OQS0s6H20PHg= github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= diff --git a/pkg/actions/podidentityassociation/iam_role_creator.go b/pkg/actions/podidentityassociation/iam_role_creator.go index eeb1c34c3b..950a415d81 100644 --- a/pkg/actions/podidentityassociation/iam_role_creator.go +++ b/pkg/actions/podidentityassociation/iam_role_creator.go @@ -3,7 +3,6 @@ package podidentityassociation import ( "context" "fmt" - "strings" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" @@ -30,21 +29,6 @@ func (r *IAMRoleCreator) Create(ctx context.Context, podIdentityAssociation *api ServiceAccountName: podIdentityAssociation.ServiceAccountName, }.IDString() - // If a target role ARN is specified for cross-account access, we need to add permission to assume the target role - if podIdentityAssociation.TargetRoleARN != "" { - targetRoleARNParts := strings.Split(podIdentityAssociation.TargetRoleARN, ":") - if len(targetRoleARNParts) >= 5 { - targetAccountID := targetRoleARNParts[4] - targetRoleName := strings.TrimPrefix(targetRoleARNParts[5], "role/") - - rs.AddAssumeRolePermission(podIdentityAssociation.TargetRoleARN) - - podIdentityAssociation.Tags["eksctl.io/cross-account-role"] = "true" - podIdentityAssociation.Tags["eksctl.io/target-account-id"] = targetAccountID - podIdentityAssociation.Tags["eksctl.io/target-role-name"] = targetRoleName - } - } - var stackName string if addonName != "" { podIdentityAssociation.Tags[api.AddonNameTag] = addonName diff --git a/pkg/awsapi/cloudformation.go b/pkg/awsapi/cloudformation.go index 4e989be777..15f64bb103 100644 --- a/pkg/awsapi/cloudformation.go +++ b/pkg/awsapi/cloudformation.go @@ -98,6 +98,17 @@ type CloudFormation interface { // Web Services Regions. A stack instance refers to a stack in a specific account // and Region. You must specify at least one value for either Accounts or // DeploymentTargets , and you must specify at least one value for Regions . + // + // The maximum number of organizational unit (OUs) supported by a + // CreateStackInstances operation is 50. + // + // If you need more than 50, consider the following options: + // + // - Batch processing: If you don't want to expose your OU hierarchy, split up + // the operations into multiple calls with less than 50 OUs each. + // + // - Parent OU strategy: If you don't mind exposing the OU hierarchy, target a + // parent OU that contains all desired child OUs. CreateStackInstances(ctx context.Context, params *cloudformation.CreateStackInstancesInput, optFns ...func(*Options)) (*cloudformation.CreateStackInstancesOutput, error) // Creates a refactor across multiple stacks, with the list of stacks and // resources that are affected. @@ -141,6 +152,17 @@ type CloudFormation interface { DeleteStack(ctx context.Context, params *cloudformation.DeleteStackInput, optFns ...func(*Options)) (*cloudformation.DeleteStackOutput, error) // Deletes stack instances for the specified accounts, in the specified Amazon Web // Services Regions. + // + // The maximum number of organizational unit (OUs) supported by a + // DeleteStackInstances operation is 50. + // + // If you need more than 50, consider the following options: + // + // - Batch processing: If you don't want to expose your OU hierarchy, split up + // the operations into multiple calls with less than 50 OUs each. + // + // - Parent OU strategy: If you don't mind exposing the OU hierarchy, target a + // parent OU that contains all desired child OUs. DeleteStackInstances(ctx context.Context, params *cloudformation.DeleteStackInstancesInput, optFns ...func(*Options)) (*cloudformation.DeleteStackInstancesOutput, error) // Deletes a stack set. Before you can delete a stack set, all its member stack // instances must be deleted. For more information about how to complete this, see DeleteStackInstances @@ -280,8 +302,14 @@ type CloudFormation interface { // [CloudFormation User Guide]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/ DescribeStackResources(ctx context.Context, params *cloudformation.DescribeStackResourcesInput, optFns ...func(*Options)) (*cloudformation.DescribeStackResourcesOutput, error) // Returns the description of the specified StackSet. + // + // This API provides strongly consistent reads meaning it will always return the + // most up-to-date data. DescribeStackSet(ctx context.Context, params *cloudformation.DescribeStackSetInput, optFns ...func(*Options)) (*cloudformation.DescribeStackSetOutput, error) // Returns the description of the specified StackSet operation. + // + // This API provides strongly consistent reads meaning it will always return the + // most up-to-date data. DescribeStackSetOperation(ctx context.Context, params *cloudformation.DescribeStackSetOperationInput, optFns ...func(*Options)) (*cloudformation.DescribeStackSetOperationOutput, error) // Returns the description for the specified stack; if no stack name was // specified, then it returns the description for all the stacks created. For more @@ -494,11 +522,20 @@ type CloudFormation interface { // Returns summary information about deployment targets for a stack set. ListStackSetAutoDeploymentTargets(ctx context.Context, params *cloudformation.ListStackSetAutoDeploymentTargetsInput, optFns ...func(*Options)) (*cloudformation.ListStackSetAutoDeploymentTargetsOutput, error) // Returns summary information about the results of a stack set operation. + // + // This API provides eventually consistent reads meaning it may take some time but + // will eventually return the most up-to-date data. ListStackSetOperationResults(ctx context.Context, params *cloudformation.ListStackSetOperationResultsInput, optFns ...func(*Options)) (*cloudformation.ListStackSetOperationResultsOutput, error) // Returns summary information about operations performed on a stack set. + // + // This API provides eventually consistent reads meaning it may take some time but + // will eventually return the most up-to-date data. ListStackSetOperations(ctx context.Context, params *cloudformation.ListStackSetOperationsInput, optFns ...func(*Options)) (*cloudformation.ListStackSetOperationsOutput, error) // Returns summary information about stack sets that are associated with the user. // + // This API provides strongly consistent reads meaning it will always return the + // most up-to-date data. + // // - [Self-managed permissions] If you set the CallAs parameter to SELF while // signed in to your Amazon Web Services account, ListStackSets returns all // self-managed stack sets in your Amazon Web Services account. @@ -700,6 +737,17 @@ type CloudFormation interface { // stack instance has been updated with the new parameter, you can then override // the parameter value using UpdateStackInstances . // + // The maximum number of organizational unit (OUs) supported by a + // UpdateStackInstances operation is 50. + // + // If you need more than 50, consider the following options: + // + // - Batch processing: If you don't want to expose your OU hierarchy, split up + // the operations into multiple calls with less than 50 OUs each. + // + // - Parent OU strategy: If you don't mind exposing the OU hierarchy, target a + // parent OU that contains all desired child OUs. + // // [CreateStackInstances]: https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStackInstances.html // [UpdateStackSet]: https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStackSet.html UpdateStackInstances(ctx context.Context, params *cloudformation.UpdateStackInstancesInput, optFns ...func(*Options)) (*cloudformation.UpdateStackInstancesOutput, error) @@ -710,6 +758,17 @@ type CloudFormation interface { // (completely or partially, below or above a specified failure tolerance), the // stack set is updated with your changes. Subsequent CreateStackInstancescalls on the specified stack // set use the updated stack set. + // + // The maximum number of organizational unit (OUs) supported by a UpdateStackSet + // operation is 50. + // + // If you need more than 50, consider the following options: + // + // - Batch processing: If you don't want to expose your OU hierarchy, split up + // the operations into multiple calls with less than 50 OUs each. + // + // - Parent OU strategy: If you don't mind exposing the OU hierarchy, target a + // parent OU that contains all desired child OUs. UpdateStackSet(ctx context.Context, params *cloudformation.UpdateStackSetInput, optFns ...func(*Options)) (*cloudformation.UpdateStackSetOutput, error) // Updates termination protection for the specified stack. If a user attempts to // delete a stack with termination protection enabled, the operation fails and the diff --git a/pkg/awsapi/elasticloadbalancingv2.go b/pkg/awsapi/elasticloadbalancingv2.go index 01ace66d5a..e84e55ed92 100644 --- a/pkg/awsapi/elasticloadbalancingv2.go +++ b/pkg/awsapi/elasticloadbalancingv2.go @@ -23,11 +23,11 @@ type ELBV2 interface { // If the certificate in already in the certificate list, the call is successful // but the certificate is not added again. // - // For more information, see [HTTPS listeners] in the Application Load Balancers Guide or [TLS listeners] in the + // For more information, see [SSL certificates] in the Application Load Balancers Guide or [Server certificates] in the // Network Load Balancers Guide. // - // [TLS listeners]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-tls-listener.html - // [HTTPS listeners]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html + // [Server certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/tls-listener-certificates.html + // [SSL certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/https-listener-certificates.html AddListenerCertificates(ctx context.Context, params *elasticloadbalancingv2.AddListenerCertificatesInput, optFns ...func(*Options)) (*elasticloadbalancingv2.AddListenerCertificatesOutput, error) // Adds the specified tags to the specified Elastic Load Balancing resource. You // can tag your Application Load Balancers, Network Load Balancers, Gateway Load @@ -107,6 +107,10 @@ type ELBV2 interface { // [Target groups for your Network Load Balancers]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html CreateTargetGroup(ctx context.Context, params *elasticloadbalancingv2.CreateTargetGroupInput, optFns ...func(*Options)) (*elasticloadbalancingv2.CreateTargetGroupOutput, error) // Creates a trust store. + // + // For more information, see [Mutual TLS for Application Load Balancers]. + // + // [Mutual TLS for Application Load Balancers]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html CreateTrustStore(ctx context.Context, params *elasticloadbalancingv2.CreateTrustStoreInput, optFns ...func(*Options)) (*elasticloadbalancingv2.CreateTrustStoreOutput, error) // Deletes the specified listener. // @@ -160,7 +164,7 @@ type ELBV2 interface { // // Note: If the specified target does not exist, the action returns successfully. // - // [Deregistration delay]: https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/target-groups.html#deregistration-delay + // [Deregistration delay]: https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/edit-target-group-attributes.html#deregistration-delay DeregisterTargets(ctx context.Context, params *elasticloadbalancingv2.DeregisterTargetsInput, optFns ...func(*Options)) (*elasticloadbalancingv2.DeregisterTargetsOutput, error) // Describes the current Elastic Load Balancing resource limits for your Amazon // Web Services account. @@ -191,8 +195,8 @@ type ELBV2 interface { // For more information, see [SSL certificates] in the Application Load Balancers Guide or [Server certificates] in the // Network Load Balancers Guide. // - // [Server certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-tls-listener.html#tls-listener-certificate - // [SSL certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#https-listener-certificates + // [Server certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/tls-listener-certificates.html + // [SSL certificates]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/https-listener-certificates.html DescribeListenerCertificates(ctx context.Context, params *elasticloadbalancingv2.DescribeListenerCertificatesInput, optFns ...func(*Options)) (*elasticloadbalancingv2.DescribeListenerCertificatesOutput, error) // Describes the specified listeners or the listeners for the specified // Application Load Balancer, Network Load Balancer, or Gateway Load Balancer. You @@ -221,10 +225,10 @@ type ELBV2 interface { DescribeRules(ctx context.Context, params *elasticloadbalancingv2.DescribeRulesInput, optFns ...func(*Options)) (*elasticloadbalancingv2.DescribeRulesOutput, error) // Describes the specified policies or all policies used for SSL negotiation. // - // For more information, see [Security policies] in the Application Load Balancers Guide or [Security policies] in the + // For more information, see [Security policies] in the Application Load Balancers Guide and [Security policies] in the // Network Load Balancers Guide. // - // [Security policies]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-tls-listener.html#describe-ssl-policies + // [Security policies]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/describe-ssl-policies.html DescribeSSLPolicies(ctx context.Context, params *elasticloadbalancingv2.DescribeSSLPoliciesInput, optFns ...func(*Options)) (*elasticloadbalancingv2.DescribeSSLPoliciesOutput, error) // Describes the tags for the specified Elastic Load Balancing resources. You can // describe the tags for one or more Application Load Balancers, Network Load @@ -321,10 +325,17 @@ type ELBV2 interface { // for a target when you register it. You can register each EC2 instance or IP // address with the same target group multiple times using different ports. // - // With a Network Load Balancer, you can't register instances by instance ID if - // they have the following instance types: C1, CC1, CC2, CG1, CG2, CR1, CS1, G1, - // G2, HI1, HS1, M1, M2, M3, and T1. You can register instances of these types by - // IP address. + // For more information, see the following: + // + // [Register targets for your Application Load Balancer] + // + // [Register targets for your Network Load Balancer] + // + // [Register targets for your Gateway Load Balancer] + // + // [Register targets for your Network Load Balancer]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-register-targets.html + // [Register targets for your Gateway Load Balancer]: https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/target-group-register-targets.html + // [Register targets for your Application Load Balancer]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-register-targets.html RegisterTargets(ctx context.Context, params *elasticloadbalancingv2.RegisterTargetsInput, optFns ...func(*Options)) (*elasticloadbalancingv2.RegisterTargetsOutput, error) // Removes the specified certificate from the certificate list for the specified // HTTPS or TLS listener. diff --git a/pkg/awsapi/iam.go b/pkg/awsapi/iam.go index ef2fddceb2..661fb46771 100644 --- a/pkg/awsapi/iam.go +++ b/pkg/awsapi/iam.go @@ -108,10 +108,11 @@ type IAM interface { // Amazon Web Services account root user password is not affected by this // operation. // - // Use UpdateLoginProfile to use the CLI, the Amazon Web Services API, or the Users page in the IAM + // Use [UpdateLoginProfile] to use the CLI, the Amazon Web Services API, or the Users page in the IAM // console to change the password for any IAM user. For more information about // modifying passwords, see [Managing passwords]in the IAM User Guide. // + // [UpdateLoginProfile]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html // [Managing passwords]: https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingLogins.html ChangePassword(ctx context.Context, params *iam.ChangePasswordInput, optFns ...func(*Options)) (*iam.ChangePasswordOutput, error) // Creates a new Amazon Web Services secret access key and corresponding Amazon @@ -167,12 +168,13 @@ type IAM interface { // Console. // // You can use the CLI, the Amazon Web Services API, or the Users page in the IAM - // console to create a password for any IAM user. Use ChangePasswordto update your own existing + // console to create a password for any IAM user. Use [ChangePassword]to update your own existing // password in the My Security Credentials page in the Amazon Web Services // Management Console. // // For more information about managing passwords, see [Managing passwords] in the IAM User Guide. // + // [ChangePassword]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ChangePassword.html // [Managing passwords]: https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingLogins.html CreateLoginProfile(ctx context.Context, params *iam.CreateLoginProfileInput, optFns ...func(*Options)) (*iam.CreateLoginProfileOutput, error) // Creates an IAM entity to describe an identity provider (IdP) that supports [OpenID Connect (OIDC)]. @@ -208,11 +210,12 @@ type IAM interface { // communication using the thumbprints set in the IdP's configuration. // // The trust for the OIDC provider is derived from the IAM provider that this - // operation creates. Therefore, it is best to limit access to the CreateOpenIDConnectProvideroperation to + // operation creates. Therefore, it is best to limit access to the [CreateOpenIDConnectProvider]operation to // highly privileged users. // // [OpenID Connect (OIDC)]: http://openid.net/connect/ // [Creating a role for web identity or OpenID connect federation]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html + // [CreateOpenIDConnectProvider]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateOpenIDConnectProvider.html CreateOpenIDConnectProvider(ctx context.Context, params *iam.CreateOpenIDConnectProviderInput, optFns ...func(*Options)) (*iam.CreateOpenIDConnectProviderOutput, error) // Creates a new managed policy for your Amazon Web Services account. // @@ -233,7 +236,7 @@ type IAM interface { // Creates a new version of the specified managed policy. To update a managed // policy, you create a new policy version. A managed policy can have up to five // versions. If the policy has five versions, you must delete an existing version - // using DeletePolicyVersionbefore you create a new version. + // using [DeletePolicyVersion]before you create a new version. // // Optionally, you can set the new version as the policy's default version. The // default version is the version that is in effect for the IAM users, groups, and @@ -241,6 +244,7 @@ type IAM interface { // // For more information about managed policy versions, see [Versioning for managed policies] in the IAM User Guide. // + // [DeletePolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeletePolicyVersion.html // [Versioning for managed policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-versions.html CreatePolicyVersion(ctx context.Context, params *iam.CreatePolicyVersionInput, optFns ...func(*Options)) (*iam.CreatePolicyVersionOutput, error) // Creates a new role for your Amazon Web Services account. @@ -296,15 +300,16 @@ type IAM interface { // You can have a maximum of two sets of service-specific credentials for each // supported service per user. // - // You can create service-specific credentials for CodeCommit and Amazon Keyspaces - // (for Apache Cassandra). + // You can create service-specific credentials for Amazon Bedrock, CodeCommit and + // Amazon Keyspaces (for Apache Cassandra). // - // You can reset the password to a new service-generated value by calling ResetServiceSpecificCredential. + // You can reset the password to a new service-generated value by calling [ResetServiceSpecificCredential]. // - // For more information about service-specific credentials, see [Using IAM with CodeCommit: Git credentials, SSH keys, and Amazon Web Services access keys] in the IAM User + // For more information about service-specific credentials, see [Service-specific credentials for IAM users] in the IAM User // Guide. // - // [Using IAM with CodeCommit: Git credentials, SSH keys, and Amazon Web Services access keys]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_ssh-keys.html + // [ResetServiceSpecificCredential]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ResetServiceSpecificCredential.html + // [Service-specific credentials for IAM users]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bedrock.html CreateServiceSpecificCredential(ctx context.Context, params *iam.CreateServiceSpecificCredentialInput, optFns ...func(*Options)) (*iam.CreateServiceSpecificCredentialOutput, error) // Creates a new IAM user for your Amazon Web Services account. // @@ -314,7 +319,7 @@ type IAM interface { // [IAM and STS quotas]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html CreateUser(ctx context.Context, params *iam.CreateUserInput, optFns ...func(*Options)) (*iam.CreateUserOutput, error) // Creates a new virtual MFA device for the Amazon Web Services account. After - // creating the virtual MFA, use EnableMFADeviceto attach the MFA device to an IAM user. For more + // creating the virtual MFA, use [EnableMFADevice]to attach the MFA device to an IAM user. For more // information about creating and working with virtual MFA devices, see [Using a virtual MFA device]in the IAM // User Guide. // @@ -328,6 +333,7 @@ type IAM interface { // information is destroyed following secure procedures. // // [Using a virtual MFA device]: https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_VirtualMFA.html + // [EnableMFADevice]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_EnableMFADevice.html // [IAM and STS quotas]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html CreateVirtualMFADevice(ctx context.Context, params *iam.CreateVirtualMFADeviceInput, optFns ...func(*Options)) (*iam.CreateVirtualMFADeviceOutput, error) // Deactivates the specified MFA device and removes it from association with the @@ -363,9 +369,10 @@ type IAM interface { // Deletes the specified inline policy that is embedded in the specified IAM group. // // A group can also have managed policies attached to it. To detach a managed - // policy from a group, use DetachGroupPolicy. For more information about policies, refer to [Managed policies and inline policies] in + // policy from a group, use [DetachGroupPolicy]. For more information about policies, refer to [Managed policies and inline policies] in // the IAM User Guide. // + // [DetachGroupPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachGroupPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DeleteGroupPolicy(ctx context.Context, params *iam.DeleteGroupPolicyInput, optFns ...func(*Options)) (*iam.DeleteGroupPolicyOutput, error) // Deletes the specified instance profile. The instance profile must not have an @@ -380,19 +387,23 @@ type IAM interface { // // [Using instance profiles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html DeleteInstanceProfile(ctx context.Context, params *iam.DeleteInstanceProfileInput, optFns ...func(*Options)) (*iam.DeleteInstanceProfileOutput, error) - // Deletes the password for the specified IAM user, For more information, see [Managing passwords for IAM users]. + // Deletes the password for the specified IAM user or root user, For more + // information, see [Managing passwords for IAM users]. // // You can use the CLI, the Amazon Web Services API, or the Users page in the IAM - // console to delete a password for any IAM user. You can use ChangePasswordto update, but not + // console to delete a password for any IAM user. You can use [ChangePassword]to update, but not // delete, your own password in the My Security Credentials page in the Amazon Web // Services Management Console. // // Deleting a user's password does not prevent a user from accessing Amazon Web // Services through the command line interface or the API. To prevent all user // access, you must also either make any access keys inactive or delete them. For - // more information about making keys inactive or deleting them, see UpdateAccessKeyand DeleteAccessKey. + // more information about making keys inactive or deleting them, see [UpdateAccessKey]and [DeleteAccessKey]. // + // [ChangePassword]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ChangePassword.html + // [DeleteAccessKey]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html // [Managing passwords for IAM users]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_admin-change-user.html + // [UpdateAccessKey]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html DeleteLoginProfile(ctx context.Context, params *iam.DeleteLoginProfileInput, optFns ...func(*Options)) (*iam.DeleteLoginProfileOutput, error) // Deletes an OpenID Connect identity provider (IdP) resource object in IAM. // @@ -411,11 +422,11 @@ type IAM interface { // deleting a managed policy: // // - Detach the policy from all users, groups, and roles that the policy is - // attached to, using DetachUserPolicy, DetachGroupPolicy, or DetachRolePolicy. To list all the users, groups, and roles that a - // policy is attached to, use ListEntitiesForPolicy. + // attached to, using [DetachUserPolicy], [DetachGroupPolicy], or [DetachRolePolicy]. To list all the users, groups, and roles that a + // policy is attached to, use [ListEntitiesForPolicy]. // - // - Delete all versions of the policy using DeletePolicyVersion. To list the policy's versions, - // use ListPolicyVersions. You cannot use DeletePolicyVersionto delete the version that is marked as the default + // - Delete all versions of the policy using [DeletePolicyVersion]. To list the policy's versions, + // use [ListPolicyVersions]. You cannot use [DeletePolicyVersion]to delete the version that is marked as the default // version. You delete the policy's default version in the next step of the // process. // @@ -424,36 +435,48 @@ type IAM interface { // // For information about managed policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [DetachUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachUserPolicy.html + // [DetachRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html + // [ListEntitiesForPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html + // [DeletePolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeletePolicyVersion.html + // [DetachGroupPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachGroupPolicy.html + // [ListPolicyVersions]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DeletePolicy(ctx context.Context, params *iam.DeletePolicyInput, optFns ...func(*Options)) (*iam.DeletePolicyOutput, error) // Deletes the specified version from the specified managed policy. // // You cannot delete the default version from a policy using this operation. To - // delete the default version from a policy, use DeletePolicy. To find out which version of a - // policy is marked as the default version, use ListPolicyVersions. + // delete the default version from a policy, use [DeletePolicy]. To find out which version of a + // policy is marked as the default version, use [ListPolicyVersions]. // // For information about versions for managed policies, see [Versioning for managed policies] in the IAM User Guide. // + // [DeletePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeletePolicy.html // [Versioning for managed policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-versions.html + // [ListPolicyVersions]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html DeletePolicyVersion(ctx context.Context, params *iam.DeletePolicyVersionInput, optFns ...func(*Options)) (*iam.DeletePolicyVersionOutput, error) // Deletes the specified role. Unlike the Amazon Web Services Management Console, // when you delete a role programmatically, you must delete the items attached to // the role manually, or the deletion fails. For more information, see [Deleting an IAM role]. Before // attempting to delete a role, remove the following attached items: // - // - Inline policies (DeleteRolePolicy ) + // - Inline policies ([DeleteRolePolicy] ) // - // - Attached managed policies (DetachRolePolicy ) + // - Attached managed policies ([DetachRolePolicy] ) // - // - Instance profile (RemoveRoleFromInstanceProfile ) + // - Instance profile ([RemoveRoleFromInstanceProfile] ) // // - Optional – Delete instance profile after detaching from role for resource - // clean up (DeleteInstanceProfile ) + // clean up ([DeleteInstanceProfile] ) // // Make sure that you do not have any Amazon EC2 instances running with the role // you are about to delete. Deleting a role or instance profile that is associated // with a running instance will break any applications running on the instance. // + // [DetachRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html + // [RemoveRoleFromInstanceProfile]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_RemoveRoleFromInstanceProfile.html + // [DeleteRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteRolePolicy.html + // [DeleteInstanceProfile]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteInstanceProfile.html // [Deleting an IAM role]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage_delete.html#roles-managingrole-deleting-cli DeleteRole(ctx context.Context, params *iam.DeleteRoleInput, optFns ...func(*Options)) (*iam.DeleteRoleOutput, error) // Deletes the permissions boundary for the specified IAM role. @@ -467,9 +490,10 @@ type IAM interface { // Deletes the specified inline policy that is embedded in the specified IAM role. // // A role can also have managed policies attached to it. To detach a managed - // policy from a role, use DetachRolePolicy. For more information about policies, refer to [Managed policies and inline policies] in the + // policy from a role, use [DetachRolePolicy]. For more information about policies, refer to [Managed policies and inline policies] in the // IAM User Guide. // + // [DetachRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DeleteRolePolicy(ctx context.Context, params *iam.DeleteRolePolicyInput, optFns ...func(*Options)) (*iam.DeleteRolePolicyOutput, error) // Deletes a SAML provider resource in IAM. @@ -517,7 +541,7 @@ type IAM interface { // not complete, then the DeletionTaskId of the earlier request is returned. // // If you submit a deletion request for a service-linked role whose linked service - // is still accessing a resource, then the deletion task fails. If it fails, the GetServiceLinkedRoleDeletionStatus + // is still accessing a resource, then the deletion task fails. If it fails, the [GetServiceLinkedRoleDeletionStatus] // operation returns the reason for the failure, usually including the resources // that must be deleted. To delete the service-linked role, you must first remove // those resources from the linked service and then submit the deletion request @@ -529,6 +553,7 @@ type IAM interface { // // [Roles terms and concepts: Amazon Web Services service-linked role]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-service-linked-role // [Amazon Web Services documentation]: http://docs.aws.amazon.com/ + // [GetServiceLinkedRoleDeletionStatus]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServiceLinkedRoleDeletionStatus.html DeleteServiceLinkedRole(ctx context.Context, params *iam.DeleteServiceLinkedRoleInput, optFns ...func(*Options)) (*iam.DeleteServiceLinkedRoleOutput, error) // Deletes the specified service-specific credential. DeleteServiceSpecificCredential(ctx context.Context, params *iam.DeleteServiceSpecificCredentialInput, optFns ...func(*Options)) (*iam.DeleteServiceSpecificCredentialOutput, error) @@ -546,25 +571,35 @@ type IAM interface { // attached to the user manually, or the deletion fails. For more information, see [Deleting an IAM user] // . Before attempting to delete a user, remove the following items: // - // - Password (DeleteLoginProfile ) + // - Password ([DeleteLoginProfile] ) // - // - Access keys (DeleteAccessKey ) + // - Access keys ([DeleteAccessKey] ) // - // - Signing certificate (DeleteSigningCertificate ) + // - Signing certificate ([DeleteSigningCertificate] ) // - // - SSH public key (DeleteSSHPublicKey ) + // - SSH public key ([DeleteSSHPublicKey] ) // - // - Git credentials (DeleteServiceSpecificCredential ) + // - Git credentials ([DeleteServiceSpecificCredential] ) // - // - Multi-factor authentication (MFA) device (DeactivateMFADevice , DeleteVirtualMFADevice) + // - Multi-factor authentication (MFA) device ([DeactivateMFADevice] , [DeleteVirtualMFADevice]) // - // - Inline policies (DeleteUserPolicy ) + // - Inline policies ([DeleteUserPolicy] ) // - // - Attached managed policies (DetachUserPolicy ) + // - Attached managed policies ([DetachUserPolicy] ) // - // - Group memberships (RemoveUserFromGroup ) + // - Group memberships ([RemoveUserFromGroup] ) // + // [DetachUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachUserPolicy.html + // [DeleteAccessKey]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html + // [DeleteVirtualMFADevice]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteVirtualMFADevice.html // [Deleting an IAM user]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_manage.html#id_users_deleting_cli + // [DeleteUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUserPolicy.html + // [RemoveUserFromGroup]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_RemoveUserFromGroup.html + // [DeleteLoginProfile]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteLoginProfile.html + // [DeleteServiceSpecificCredential]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteServiceSpecificCredential.html + // [DeleteSigningCertificate]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteSigningCertificate.html + // [DeleteSSHPublicKey]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteSSHPublicKey.html + // [DeactivateMFADevice]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html DeleteUser(ctx context.Context, params *iam.DeleteUserInput, optFns ...func(*Options)) (*iam.DeleteUserOutput, error) // Deletes the permissions boundary for the specified IAM user. // @@ -575,35 +610,41 @@ type IAM interface { // Deletes the specified inline policy that is embedded in the specified IAM user. // // A user can also have managed policies attached to it. To detach a managed - // policy from a user, use DetachUserPolicy. For more information about policies, refer to [Managed policies and inline policies] in the + // policy from a user, use [DetachUserPolicy]. For more information about policies, refer to [Managed policies and inline policies] in the // IAM User Guide. // + // [DetachUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachUserPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DeleteUserPolicy(ctx context.Context, params *iam.DeleteUserPolicyInput, optFns ...func(*Options)) (*iam.DeleteUserPolicyOutput, error) // Deletes a virtual MFA device. // // You must deactivate a user's virtual MFA device before you can delete it. For - // information about deactivating MFA devices, see DeactivateMFADevice. + // information about deactivating MFA devices, see [DeactivateMFADevice]. + // + // [DeactivateMFADevice]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html DeleteVirtualMFADevice(ctx context.Context, params *iam.DeleteVirtualMFADeviceInput, optFns ...func(*Options)) (*iam.DeleteVirtualMFADeviceOutput, error) // Removes the specified managed policy from the specified IAM group. // // A group can also have inline policies embedded with it. To delete an inline - // policy, use DeleteGroupPolicy. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. + // policy, use [DeleteGroupPolicy]. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [DeleteGroupPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteGroupPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DetachGroupPolicy(ctx context.Context, params *iam.DetachGroupPolicyInput, optFns ...func(*Options)) (*iam.DetachGroupPolicyOutput, error) // Removes the specified managed policy from the specified role. // // A role can also have inline policies embedded with it. To delete an inline - // policy, use DeleteRolePolicy. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. + // policy, use [DeleteRolePolicy]. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [DeleteRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteRolePolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DetachRolePolicy(ctx context.Context, params *iam.DetachRolePolicyInput, optFns ...func(*Options)) (*iam.DetachRolePolicyOutput, error) // Removes the specified managed policy from the specified user. // // A user can also have inline policies embedded with it. To delete an inline - // policy, use DeleteUserPolicy. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. + // policy, use [DeleteUserPolicy]. For information about policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [DeleteUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUserPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html DetachUserPolicy(ctx context.Context, params *iam.DetachUserPolicyInput, optFns ...func(*Options)) (*iam.DetachUserPolicyOutput, error) // Disables the management of privileged root user credentials across member @@ -692,9 +733,9 @@ type IAM interface { // authoritative source for information about all API calls and whether they were // successful or denied access. For more information, see [Logging IAM events with CloudTrail]in the IAM User Guide. // - // This operation returns a JobId . Use this parameter in the GetOrganizationsAccessReport operation to check + // This operation returns a JobId . Use this parameter in the [GetOrganizationsAccessReport] operation to check // the status of the report generation. To check the status of this request, use - // the JobId parameter in the GetOrganizationsAccessReport operation and test the JobStatus response + // the JobId parameter in the [GetOrganizationsAccessReport] operation and test the JobStatus response // parameter. When the job is complete, you can retrieve the report. // // To generate a service last accessed data report for entities, specify an entity @@ -769,6 +810,7 @@ type IAM interface { // [Logging IAM events with CloudTrail]: https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html // [Refining permissions using service last accessed data]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html // [Reducing permissions using service last accessed data]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html + // [GetOrganizationsAccessReport]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetOrganizationsAccessReport.html // [Evaluating policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-basics // [Reducing policy scope by viewing user activity]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html GenerateOrganizationsAccessReport(ctx context.Context, params *iam.GenerateOrganizationsAccessReportInput, optFns ...func(*Options)) (*iam.GenerateOrganizationsAccessReportOutput, error) @@ -794,7 +836,7 @@ type IAM interface { // parameter in the following operations to retrieve the following details from // your report: // - // GetServiceLastAccessedDetails + // [GetServiceLastAccessedDetails] // - – Use this operation for users, groups, roles, or policies to list every // Amazon Web Services service that the resource could access using permissions // policies. For each service, the response includes information about the most @@ -805,7 +847,7 @@ type IAM interface { // role within a session, or by the same user when used to call // GetServiceLastAccessedDetail . // - // GetServiceLastAccessedDetailsWithEntities + // [GetServiceLastAccessedDetailsWithEntities] // - – Use this operation for groups and policies to list information about the // associated entities (users or roles) that attempted to access a specific Amazon // Web Services service. @@ -815,7 +857,7 @@ type IAM interface { // parameter. // // For additional information about the permissions policies that allow an - // identity (user, group, or role) to access specific services, use the ListPoliciesGrantingServiceAccessoperation. + // identity (user, group, or role) to access specific services, use the [ListPoliciesGrantingServiceAccess]operation. // // Service last accessed data does not use other policy types when determining // whether a resource could access a service. These other policy types include @@ -828,9 +870,12 @@ type IAM interface { // IAM User Guide. // // [Logging IAM events with CloudTrail]: https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html + // [GetServiceLastAccessedDetails]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServiceLastAccessedDetails.html + // [ListPoliciesGrantingServiceAccess]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPoliciesGrantingServiceAccess.html // [Reducing permissions using service last accessed data]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html // [Regions where data is tracked]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html#access-advisor_tracking-period // [Evaluating policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-basics + // [GetServiceLastAccessedDetailsWithEntities]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServiceLastAccessedDetailsWithEntities.html // [IAM action last accessed information services and actions]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor-action-last-accessed.html GenerateServiceLastAccessedDetails(ctx context.Context, params *iam.GenerateServiceLastAccessedDetailsInput, optFns ...func(*Options)) (*iam.GenerateServiceLastAccessedDetailsOutput, error) // Retrieves information about when the specified access key was last used. The @@ -847,7 +892,7 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // // You can optionally filter the results using the Filter parameter. You can // paginate the results using the MaxItems and Marker parameters. @@ -870,15 +915,18 @@ type IAM interface { GetAccountSummary(ctx context.Context, params *iam.GetAccountSummaryInput, optFns ...func(*Options)) (*iam.GetAccountSummaryOutput, error) // Gets a list of all of the context keys referenced in the input policies. The // policies are supplied as a list of one or more strings. To get the context keys - // from policies associated with an IAM user, group, or role, use GetContextKeysForPrincipalPolicy. + // from policies associated with an IAM user, group, or role, use [GetContextKeysForPrincipalPolicy]. // // Context keys are variables maintained by Amazon Web Services and its services // that provide details about the context of an API query request. Context keys can // be evaluated by testing against a value specified in an IAM policy. Use // GetContextKeysForCustomPolicy to understand what key names and values you must - // supply when you call SimulateCustomPolicy. Note that all parameters are shown in unencoded form + // supply when you call [SimulateCustomPolicy]. Note that all parameters are shown in unencoded form // here for clarity but must be URL encoded to be included as a part of a real HTML // request. + // + // [GetContextKeysForPrincipalPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetContextKeysForPrincipalPolicy.html + // [SimulateCustomPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_SimulateCustomPolicy.html GetContextKeysForCustomPolicy(ctx context.Context, params *iam.GetContextKeysForCustomPolicyInput, optFns ...func(*Options)) (*iam.GetContextKeysForCustomPolicyOutput, error) // Gets a list of all of the context keys referenced in all the IAM policies that // are attached to the specified IAM entity. The entity can be an IAM user, group, @@ -886,17 +934,21 @@ type IAM interface { // policies attached to groups that the user is a member of. // // You can optionally include a list of one or more additional policies, specified - // as strings. If you want to include only a list of policies by string, use GetContextKeysForCustomPolicy + // as strings. If you want to include only a list of policies by string, use [GetContextKeysForCustomPolicy] // instead. // // Note: This operation discloses information about the permissions granted to // other users. If you do not want users to see other user's permissions, then - // consider allowing them to use GetContextKeysForCustomPolicyinstead. + // consider allowing them to use [GetContextKeysForCustomPolicy]instead. // // Context keys are variables maintained by Amazon Web Services and its services // that provide details about the context of an API query request. Context keys can - // be evaluated by testing against a value in an IAM policy. Use GetContextKeysForPrincipalPolicyto understand - // what key names and values you must supply when you call SimulatePrincipalPolicy. + // be evaluated by testing against a value in an IAM policy. Use [GetContextKeysForPrincipalPolicy]to understand + // what key names and values you must supply when you call [SimulatePrincipalPolicy]. + // + // [GetContextKeysForPrincipalPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetContextKeysForPrincipalPolicy.html + // [GetContextKeysForCustomPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetContextKeysForCustomPolicy.html + // [SimulatePrincipalPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_SimulatePrincipalPolicy.html GetContextKeysForPrincipalPolicy(ctx context.Context, params *iam.GetContextKeysForPrincipalPolicyInput, optFns ...func(*Options)) (*iam.GetContextKeysForPrincipalPolicyOutput, error) // Retrieves a credential report for the Amazon Web Services account. For more // @@ -915,15 +967,17 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // // An IAM group can also have managed policies attached to it. To retrieve a - // managed policy document that is attached to a group, use GetPolicyto determine the - // policy's default version, then use GetPolicyVersionto retrieve the policy document. + // managed policy document that is attached to a group, use [GetPolicy]to determine the + // policy's default version, then use [GetPolicyVersion]to retrieve the policy document. // // For more information about policies, see [Managed policies and inline policies] in the IAM User Guide. // // [RFC 3986]: https://tools.ietf.org/html/rfc3986 + // [GetPolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html + // [GetPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html GetGroupPolicy(ctx context.Context, params *iam.GetGroupPolicyInput, optFns ...func(*Options)) (*iam.GetGroupPolicyOutput, error) // Retrieves information about the specified instance profile, including the @@ -953,11 +1007,11 @@ type IAM interface { // object in IAM. GetOpenIDConnectProvider(ctx context.Context, params *iam.GetOpenIDConnectProviderInput, optFns ...func(*Options)) (*iam.GetOpenIDConnectProviderOutput, error) // Retrieves the service last accessed data report for Organizations that was - // previously generated using the GenerateOrganizationsAccessReportoperation. This operation retrieves the status + // previously generated using the [GenerateOrganizationsAccessReport]operation. This operation retrieves the status // of your report job and the report contents. // // Depending on the parameters that you passed when you generated the report, the - // data returned could include different information. For details, see GenerateOrganizationsAccessReport. + // data returned could include different information. For details, see [GenerateOrganizationsAccessReport]. // // To call this operation, you must be signed in to the management account in your // organization. SCPs must be enabled for your organization root. You must have @@ -972,21 +1026,27 @@ type IAM interface { // // By default, the list is sorted by service namespace. // + // [GenerateOrganizationsAccessReport]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GenerateOrganizationsAccessReport.html // [Refining permissions using service last accessed data]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html GetOrganizationsAccessReport(ctx context.Context, params *iam.GetOrganizationsAccessReportInput, optFns ...func(*Options)) (*iam.GetOrganizationsAccessReportOutput, error) // Retrieves information about the specified managed policy, including the // policy's default version and the total number of IAM users, groups, and roles to // which the policy is attached. To retrieve the list of the specific users, - // groups, and roles that the policy is attached to, use ListEntitiesForPolicy. This operation returns + // groups, and roles that the policy is attached to, use [ListEntitiesForPolicy]. This operation returns // metadata about the policy. To retrieve the actual policy document for a specific - // version of the policy, use GetPolicyVersion. + // version of the policy, use [GetPolicyVersion]. // // This operation retrieves information about managed policies. To retrieve // information about an inline policy that is embedded with an IAM user, group, or - // role, use GetUserPolicy, GetGroupPolicy, or GetRolePolicy. + // role, use [GetUserPolicy], [GetGroupPolicy], or [GetRolePolicy]. // // For more information about policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [ListEntitiesForPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html + // [GetRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html + // [GetPolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html + // [GetGroupPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetGroupPolicy.html + // [GetUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUserPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html GetPolicy(ctx context.Context, params *iam.GetPolicyInput, optFns ...func(*Options)) (*iam.GetPolicyOutput, error) // Retrieves information about the specified version of the specified managed @@ -996,20 +1056,24 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // - // To list the available versions for a policy, use ListPolicyVersions. + // To list the available versions for a policy, use [ListPolicyVersions]. // // This operation retrieves information about managed policies. To retrieve // information about an inline policy that is embedded in a user, group, or role, - // use GetUserPolicy, GetGroupPolicy, or GetRolePolicy. + // use [GetUserPolicy], [GetGroupPolicy], or [GetRolePolicy]. // // For more information about the types of policies, see [Managed policies and inline policies] in the IAM User Guide. // // For more information about managed policy versions, see [Versioning for managed policies] in the IAM User Guide. // // [RFC 3986]: https://tools.ietf.org/html/rfc3986 + // [GetRolePolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html + // [GetGroupPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetGroupPolicy.html + // [GetUserPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUserPolicy.html // [Versioning for managed policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-versions.html + // [ListPolicyVersions]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html GetPolicyVersion(ctx context.Context, params *iam.GetPolicyVersionInput, optFns ...func(*Options)) (*iam.GetPolicyVersionOutput, error) // Retrieves information about the specified role, including the role's path, @@ -1020,7 +1084,7 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // // [RFC 3986]: https://tools.ietf.org/html/rfc3986 // [IAM roles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html @@ -1032,11 +1096,11 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // // An IAM role can also have managed policies attached to it. To retrieve a - // managed policy document that is attached to a role, use GetPolicyto determine the - // policy's default version, then use GetPolicyVersionto retrieve the policy document. + // managed policy document that is attached to a role, use [GetPolicy]to determine the + // policy's default version, then use [GetPolicyVersion]to retrieve the policy document. // // For more information about policies, see [Managed policies and inline policies] in the IAM User Guide. // @@ -1044,6 +1108,8 @@ type IAM interface { // // [RFC 3986]: https://tools.ietf.org/html/rfc3986 // [IAM roles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html + // [GetPolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html + // [GetPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html GetRolePolicy(ctx context.Context, params *iam.GetRolePolicyInput, optFns ...func(*Options)) (*iam.GetRolePolicyOutput, error) // Returns the SAML provider metadocument that was uploaded when the IAM SAML @@ -1142,11 +1208,13 @@ type IAM interface { // By default, the list of associated entities is sorted by date, with the most // recent access listed first. GetServiceLastAccessedDetailsWithEntities(ctx context.Context, params *iam.GetServiceLastAccessedDetailsWithEntitiesInput, optFns ...func(*Options)) (*iam.GetServiceLastAccessedDetailsWithEntitiesOutput, error) - // Retrieves the status of your service-linked role deletion. After you use DeleteServiceLinkedRole to + // Retrieves the status of your service-linked role deletion. After you use [DeleteServiceLinkedRole] to // submit a service-linked role for deletion, you can use the DeletionTaskId // parameter in GetServiceLinkedRoleDeletionStatus to check the status of the // deletion. If the deletion fails, this operation returns the reason that it // failed, if that information is returned by the service. + // + // [DeleteServiceLinkedRole]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteServiceLinkedRole.html GetServiceLinkedRoleDeletionStatus(ctx context.Context, params *iam.GetServiceLinkedRoleDeletionStatusInput, optFns ...func(*Options)) (*iam.GetServiceLinkedRoleDeletionStatusOutput, error) // Retrieves information about the specified IAM user, including the user's // creation date, path, unique ID, and ARN. @@ -1162,15 +1230,17 @@ type IAM interface { // use a URL decoding method to convert the policy back to plain JSON text. For // example, if you use Java, you can use the decode method of the // java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs - // provide similar functionality. + // provide similar functionality, and some SDKs do this decoding automatically. // // An IAM user can also have managed policies attached to it. To retrieve a - // managed policy document that is attached to a user, use GetPolicyto determine the - // policy's default version. Then use GetPolicyVersionto retrieve the policy document. + // managed policy document that is attached to a user, use [GetPolicy]to determine the + // policy's default version. Then use [GetPolicyVersion]to retrieve the policy document. // // For more information about policies, see [Managed policies and inline policies] in the IAM User Guide. // // [RFC 3986]: https://tools.ietf.org/html/rfc3986 + // [GetPolicyVersion]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html + // [GetPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html GetUserPolicy(ctx context.Context, params *iam.GetUserPolicyInput, optFns ...func(*Options)) (*iam.GetUserPolicyOutput, error) // Returns information about the access key IDs associated with the specified IAM @@ -1200,7 +1270,7 @@ type IAM interface { // Lists all managed policies that are attached to the specified IAM group. // // An IAM group can also have inline policies embedded with it. To list the inline - // policies for a group, use ListGroupPolicies. For information about policies, see [Managed policies and inline policies] in the IAM + // policies for a group, use [ListGroupPolicies]. For information about policies, see [Managed policies and inline policies] in the IAM // User Guide. // // You can paginate the results using the MaxItems and Marker parameters. You can @@ -1209,12 +1279,13 @@ type IAM interface { // specified group (or none that match the specified path prefix), the operation // returns an empty list. // + // [ListGroupPolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListGroupPolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListAttachedGroupPolicies(ctx context.Context, params *iam.ListAttachedGroupPoliciesInput, optFns ...func(*Options)) (*iam.ListAttachedGroupPoliciesOutput, error) // Lists all managed policies that are attached to the specified IAM role. // // An IAM role can also have inline policies embedded with it. To list the inline - // policies for a role, use ListRolePolicies. For information about policies, see [Managed policies and inline policies] in the IAM User + // policies for a role, use [ListRolePolicies]. For information about policies, see [Managed policies and inline policies] in the IAM User // Guide. // // You can paginate the results using the MaxItems and Marker parameters. You can @@ -1223,12 +1294,13 @@ type IAM interface { // specified role (or none that match the specified path prefix), the operation // returns an empty list. // + // [ListRolePolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListAttachedRolePolicies(ctx context.Context, params *iam.ListAttachedRolePoliciesInput, optFns ...func(*Options)) (*iam.ListAttachedRolePoliciesOutput, error) // Lists all managed policies that are attached to the specified IAM user. // // An IAM user can also have inline policies embedded with it. To list the inline - // policies for a user, use ListUserPolicies. For information about policies, see [Managed policies and inline policies] in the IAM User + // policies for a user, use [ListUserPolicies]. For information about policies, see [Managed policies and inline policies] in the IAM User // Guide. // // You can paginate the results using the MaxItems and Marker parameters. You can @@ -1237,6 +1309,7 @@ type IAM interface { // specified group (or none that match the specified path prefix), the operation // returns an empty list. // + // [ListUserPolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUserPolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListAttachedUserPolicies(ctx context.Context, params *iam.ListAttachedUserPoliciesInput, optFns ...func(*Options)) (*iam.ListAttachedUserPoliciesOutput, error) // Lists all IAM users, groups, and roles that the specified managed policy is @@ -1252,13 +1325,14 @@ type IAM interface { // group. // // An IAM group can also have managed policies attached to it. To list the managed - // policies that are attached to a group, use ListAttachedGroupPolicies. For more information about + // policies that are attached to a group, use [ListAttachedGroupPolicies]. For more information about // policies, see [Managed policies and inline policies]in the IAM User Guide. // // You can paginate the results using the MaxItems and Marker parameters. If there // are no inline policies embedded with the specified group, the operation returns // an empty list. // + // [ListAttachedGroupPolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedGroupPolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListGroupPolicies(ctx context.Context, params *iam.ListGroupPoliciesInput, optFns ...func(*Options)) (*iam.ListGroupPoliciesOutput, error) // Lists the IAM groups that have the specified path prefix. @@ -1282,11 +1356,12 @@ type IAM interface { // IAM resource-listing operations return a subset of the available attributes for // the resource. For example, this operation does not return tags, even though they // are an attribute of the returned object. To view all of the information for an - // instance profile, see GetInstanceProfile. + // instance profile, see [GetInstanceProfile]. // // You can paginate the results using the MaxItems and Marker parameters. // // [Using instance profiles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html + // [GetInstanceProfile]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetInstanceProfile.html ListInstanceProfiles(ctx context.Context, params *iam.ListInstanceProfilesInput, optFns ...func(*Options)) (*iam.ListInstanceProfilesOutput, error) // Lists the instance profiles that have the specified associated IAM role. If // there are none, the operation returns an empty list. For more information about @@ -1325,7 +1400,9 @@ type IAM interface { // IAM resource-listing operations return a subset of the available attributes for // the resource. For example, this operation does not return tags, even though they // are an attribute of the returned object. To view all of the information for an - // OIDC provider, see GetOpenIDConnectProvider. + // OIDC provider, see [GetOpenIDConnectProvider]. + // + // [GetOpenIDConnectProvider]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetOpenIDConnectProvider.html ListOpenIDConnectProviders(ctx context.Context, params *iam.ListOpenIDConnectProvidersInput, optFns ...func(*Options)) (*iam.ListOpenIDConnectProvidersOutput, error) // Lists the centralized root access features enabled for your organization. For // more information, see [Centrally manage root access for member accounts]. @@ -1348,8 +1425,9 @@ type IAM interface { // IAM resource-listing operations return a subset of the available attributes for // the resource. For example, this operation does not return tags, even though they // are an attribute of the returned object. To view all of the information for a - // customer manged policy, see GetPolicy. + // customer manged policy, see [GetPolicy]. // + // [GetPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListPolicies(ctx context.Context, params *iam.ListPoliciesInput, optFns ...func(*Options)) (*iam.ListPoliciesOutput, error) // Retrieves a list of policies that the IAM identity (user, group, or role) can @@ -1382,10 +1460,12 @@ type IAM interface { // // Policies that are attached to users and roles as permissions boundaries are not // returned. To view which managed policy is currently used to set the permissions - // boundary for a user or role, use the GetUseror GetRole operations. + // boundary for a user or role, use the [GetUser]or [GetRole] operations. // + // [GetRole]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html // [Evaluating policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-basics // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html + // [GetUser]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUser.html ListPoliciesGrantingServiceAccess(ctx context.Context, params *iam.ListPoliciesGrantingServiceAccessInput, optFns ...func(*Options)) (*iam.ListPoliciesGrantingServiceAccessOutput, error) // Lists the tags that are attached to the specified IAM customer managed policy. // The returned list of tags is sorted by tag key. For more information about @@ -1404,13 +1484,14 @@ type IAM interface { // role. // // An IAM role can also have managed policies attached to it. To list the managed - // policies that are attached to a role, use ListAttachedRolePolicies. For more information about + // policies that are attached to a role, use [ListAttachedRolePolicies]. For more information about // policies, see [Managed policies and inline policies]in the IAM User Guide. // // You can paginate the results using the MaxItems and Marker parameters. If there // are no inline policies embedded with the specified role, the operation returns // an empty list. // + // [ListAttachedRolePolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListRolePolicies(ctx context.Context, params *iam.ListRolePoliciesInput, optFns ...func(*Options)) (*iam.ListRolePoliciesOutput, error) // Lists the tags that are attached to the specified role. The returned list of @@ -1433,10 +1514,11 @@ type IAM interface { // // - Tags // - // To view all of the information for a role, see GetRole. + // To view all of the information for a role, see [GetRole]. // // You can paginate the results using the MaxItems and Marker parameters. // + // [GetRole]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html // [IAM roles]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html ListRoles(ctx context.Context, params *iam.ListRolesInput, optFns ...func(*Options)) (*iam.ListRolesOutput, error) // Lists the tags that are attached to the specified Security Assertion Markup @@ -1452,11 +1534,12 @@ type IAM interface { // resource-listing operations return a subset of the available attributes for the // resource. For example, this operation does not return tags, even though they are // an attribute of the returned object. To view all of the information for a SAML - // provider, see GetSAMLProvider. + // provider, see [GetSAMLProvider]. // // This operation requires [Signature Version 4]. // // [Signature Version 4]: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html + // [GetSAMLProvider]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetSAMLProvider.html ListSAMLProviders(ctx context.Context, params *iam.ListSAMLProvidersInput, optFns ...func(*Options)) (*iam.ListSAMLProvidersOutput, error) // Returns information about the SSH public keys associated with the specified IAM // user. If none exists, the operation returns an empty list. @@ -1495,8 +1578,9 @@ type IAM interface { // IAM resource-listing operations return a subset of the available attributes for // the resource. For example, this operation does not return tags, even though they // are an attribute of the returned object. To view all of the information for a - // servercertificate, see GetServerCertificate. + // servercertificate, see [GetServerCertificate]. // + // [GetServerCertificate]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServerCertificate.html // [Working with server certificates]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_server-certs.html ListServerCertificates(ctx context.Context, params *iam.ListServerCertificatesInput, optFns ...func(*Options)) (*iam.ListServerCertificatesOutput, error) // Returns information about the service-specific credentials associated with the @@ -1524,13 +1608,14 @@ type IAM interface { // Lists the names of the inline policies embedded in the specified IAM user. // // An IAM user can also have managed policies attached to it. To list the managed - // policies that are attached to a user, use ListAttachedUserPolicies. For more information about + // policies that are attached to a user, use [ListAttachedUserPolicies]. For more information about // policies, see [Managed policies and inline policies]in the IAM User Guide. // // You can paginate the results using the MaxItems and Marker parameters. If there // are no inline policies embedded with the specified user, the operation returns // an empty list. // + // [ListAttachedUserPolicies]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedUserPolicies.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html ListUserPolicies(ctx context.Context, params *iam.ListUserPoliciesInput, optFns ...func(*Options)) (*iam.ListUserPoliciesOutput, error) // Lists the tags that are attached to the specified IAM user. The returned list @@ -1551,9 +1636,11 @@ type IAM interface { // // - Tags // - // To view all of the information for a user, see GetUser. + // To view all of the information for a user, see [GetUser]. // // You can paginate the results using the MaxItems and Marker parameters. + // + // [GetUser]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUser.html ListUsers(ctx context.Context, params *iam.ListUsersInput, optFns ...func(*Options)) (*iam.ListUsersOutput, error) // Lists the virtual MFA devices defined in the Amazon Web Services account by // assignment status. If you do not specify an assignment status, the operation @@ -1563,9 +1650,11 @@ type IAM interface { // IAM resource-listing operations return a subset of the available attributes for // the resource. For example, this operation does not return tags, even though they // are an attribute of the returned object. To view tag information for a virtual - // MFA device, see ListMFADeviceTags. + // MFA device, see [ListMFADeviceTags]. // // You can paginate the results using the MaxItems and Marker parameters. + // + // [ListMFADeviceTags]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADeviceTags.html ListVirtualMFADevices(ctx context.Context, params *iam.ListVirtualMFADevicesInput, optFns ...func(*Options)) (*iam.ListVirtualMFADevicesOutput, error) // Adds or updates an inline policy document that is embedded in the specified IAM // group. @@ -1701,10 +1790,11 @@ type IAM interface { // (operative) version. // // This operation affects all users, groups, and roles that the policy is attached - // to. To list the users, groups, and roles that the policy is attached to, use ListEntitiesForPolicy. + // to. To list the users, groups, and roles that the policy is attached to, use [ListEntitiesForPolicy]. // // For information about managed policies, see [Managed policies and inline policies] in the IAM User Guide. // + // [ListEntitiesForPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html // [Managed policies and inline policies]: https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html SetDefaultPolicyVersion(ctx context.Context, params *iam.SetDefaultPolicyVersionInput, optFns ...func(*Options)) (*iam.SetDefaultPolicyVersionOutput, error) // Sets the specified version of the global endpoint token as the token version @@ -1725,9 +1815,10 @@ type IAM interface { // you temporarily store tokens. For information, see [Activating and deactivating STS in an Amazon Web Services Region]in the IAM User Guide. // // To view the current session token version, see the GlobalEndpointTokenVersion - // entry in the response of the GetAccountSummaryoperation. + // entry in the response of the [GetAccountSummary]operation. // // [Activating and deactivating STS in an Amazon Web Services Region]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html + // [GetAccountSummary]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccountSummary.html // [Security Token Service endpoints and quotas]: https://docs.aws.amazon.com/general/latest/gr/sts.html SetSecurityTokenServicePreferences(ctx context.Context, params *iam.SetSecurityTokenServicePreferencesInput, optFns ...func(*Options)) (*iam.SetSecurityTokenServicePreferencesOutput, error) // Simulate how a set of IAM policies and optionally a resource-based policy works @@ -1739,13 +1830,13 @@ type IAM interface { // operations. You can simulate resources that don't exist in your account. // // If you want to simulate existing policies that are attached to an IAM user, - // group, or role, use SimulatePrincipalPolicyinstead. + // group, or role, use [SimulatePrincipalPolicy]instead. // // Context keys are variables that are maintained by Amazon Web Services and its // services and which provide details about the context of an API query request. // You can use the Condition element of an IAM policy to evaluate context keys. To // get the list of context keys that the policies require for correct simulation, - // use GetContextKeysForCustomPolicy. + // use [GetContextKeysForCustomPolicy]. // // If the output is long, you can use MaxItems and Marker parameters to paginate // the results. @@ -1758,7 +1849,9 @@ type IAM interface { // For more information about using the policy simulator, see [Testing IAM policies with the IAM policy simulator]in the IAM User // Guide. // + // [GetContextKeysForCustomPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetContextKeysForCustomPolicy.html // [Testing IAM policies with the IAM policy simulator]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_testing-policies.html + // [SimulatePrincipalPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_SimulatePrincipalPolicy.html SimulateCustomPolicy(ctx context.Context, params *iam.SimulateCustomPolicyInput, optFns ...func(*Options)) (*iam.SimulateCustomPolicyOutput, error) // Simulate how a set of IAM policies attached to an IAM entity works with a list // of API operations and Amazon Web Services resources to determine the policies' @@ -1769,7 +1862,7 @@ type IAM interface { // // You can optionally include a list of one or more additional policies specified // as strings to include in the simulation. If you want to simulate only policies - // specified as strings, use SimulateCustomPolicyinstead. + // specified as strings, use [SimulateCustomPolicy]instead. // // You can also optionally include one resource-based policy to be evaluated with // each of the resources included in the simulation for IAM users only. @@ -1780,12 +1873,12 @@ type IAM interface { // // Note: This operation discloses information about the permissions granted to // other users. If you do not want users to see other user's permissions, then - // consider allowing them to use SimulateCustomPolicyinstead. + // consider allowing them to use [SimulateCustomPolicy]instead. // // Context keys are variables maintained by Amazon Web Services and its services // that provide details about the context of an API query request. You can use the // Condition element of an IAM policy to evaluate context keys. To get the list of - // context keys that the policies require for correct simulation, use GetContextKeysForPrincipalPolicy. + // context keys that the policies require for correct simulation, use [GetContextKeysForPrincipalPolicy]. // // If the output is long, you can use the MaxItems and Marker parameters to // paginate the results. @@ -1798,7 +1891,9 @@ type IAM interface { // For more information about using the policy simulator, see [Testing IAM policies with the IAM policy simulator]in the IAM User // Guide. // + // [GetContextKeysForPrincipalPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetContextKeysForPrincipalPolicy.html // [Testing IAM policies with the IAM policy simulator]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_testing-policies.html + // [SimulateCustomPolicy]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_SimulateCustomPolicy.html SimulatePrincipalPolicy(ctx context.Context, params *iam.SimulatePrincipalPolicyInput, optFns ...func(*Options)) (*iam.SimulatePrincipalPolicyOutput, error) // Adds one or more tags to an IAM instance profile. If a tag with the same key // name already exists, then that tag is overwritten with the new value. @@ -2147,11 +2242,12 @@ type IAM interface { UpdateGroup(ctx context.Context, params *iam.UpdateGroupInput, optFns ...func(*Options)) (*iam.UpdateGroupOutput, error) // Changes the password for the specified IAM user. You can use the CLI, the // Amazon Web Services API, or the Users page in the IAM console to change the - // password for any IAM user. Use ChangePasswordto change your own password in the My Security + // password for any IAM user. Use [ChangePassword]to change your own password in the My Security // Credentials page in the Amazon Web Services Management Console. // // For more information about modifying passwords, see [Managing passwords] in the IAM User Guide. // + // [ChangePassword]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ChangePassword.html // [Managing passwords]: https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingLogins.html UpdateLoginProfile(ctx context.Context, params *iam.UpdateLoginProfileInput, optFns ...func(*Options)) (*iam.UpdateLoginProfileOutput, error) // Replaces the existing list of server certificate thumbprints associated with an @@ -2177,10 +2273,12 @@ type IAM interface { UpdateOpenIDConnectProviderThumbprint(ctx context.Context, params *iam.UpdateOpenIDConnectProviderThumbprintInput, optFns ...func(*Options)) (*iam.UpdateOpenIDConnectProviderThumbprintOutput, error) // Updates the description or maximum session duration setting of a role. UpdateRole(ctx context.Context, params *iam.UpdateRoleInput, optFns ...func(*Options)) (*iam.UpdateRoleOutput, error) - // Use UpdateRole instead. + // Use [UpdateRole] instead. // // Modifies only the description of a role. This operation performs the same // function as the Description parameter in the UpdateRole operation. + // + // [UpdateRole]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateRole.html UpdateRoleDescription(ctx context.Context, params *iam.UpdateRoleDescriptionInput, optFns ...func(*Options)) (*iam.UpdateRoleDescriptionOutput, error) // Updates the metadata document, SAML encryption settings, and private keys for // an existing SAML provider. To rotate private keys, add your new private key and diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index a46efb8f3a..2af2858f73 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -506,54 +506,6 @@ func toMapOfInterfaces(old []api.IAMStatement) []cft.MapOfInterfaces { return new } -// AddAssumeRolePermission adds permission to assume a target role -func (rs *IAMRoleResourceSet) AddAssumeRolePermission(targetRoleARN string) { - if rs.attachPolicy == nil { - rs.attachPolicy = api.InlineDocument{} - } - - // Create or update the policy to include permission to assume the target role - assumeRolePolicy := api.InlineDocument{ - "Version": "2012-10-17", - "Statement": []api.IAMStatement{ - { - Effect: "Allow", - Action: []string{ - "sts:AssumeRole", - "sts:TagSession", - }, - Resource: []string{targetRoleARN}, - }, - }, - } - - // If there's an existing policy, merge the statements - if existingPolicy, ok := rs.attachPolicy["Statement"]; ok { - if statements, ok := existingPolicy.([]interface{}); ok { - newStatements := assumeRolePolicy["Statement"].([]api.IAMStatement) - for _, stmt := range statements { - if stmtMap, ok := stmt.(map[string]interface{}); ok { - // Skip if this is already an AssumeRole statement for the same resource - if action, hasAction := stmtMap["Action"]; hasAction { - if resource, hasResource := stmtMap["Resource"]; hasResource { - if strings.Contains(fmt.Sprintf("%v", action), "AssumeRole") && - strings.Contains(fmt.Sprintf("%v", resource), targetRoleARN) { - return // Statement already exists - } - } - } - } - } - - // Add the new statement - rs.attachPolicy["Statement"] = append(statements, newStatements[0]) - } - } else { - // No existing statements, use the new policy - rs.attachPolicy = assumeRolePolicy - } -} - // RenderJSON will render iamserviceaccount stack as JSON func (rs *IAMRoleResourceSet) RenderJSON() ([]byte, error) { return rs.template.RenderJSON() From 08eba494717b08ecab27d7167b5b0173626d3514 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Thu, 10 Jul 2025 22:40:02 +0000 Subject: [PATCH 17/25] add new params to UpdatePodIdentityAssociations cli command --- pkg/ctl/cmdutils/pod_identity_association.go | 8 +- pkg/ctl/update/pod_identity_association.go | 5 +- .../update/pod_identity_association_test.go | 139 ++++++++++++++++++ 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 pkg/ctl/update/pod_identity_association_test.go diff --git a/pkg/ctl/cmdutils/pod_identity_association.go b/pkg/ctl/cmdutils/pod_identity_association.go index bf951713c0..a358553326 100644 --- a/pkg/ctl/cmdutils/pod_identity_association.go +++ b/pkg/ctl/cmdutils/pod_identity_association.go @@ -173,12 +173,18 @@ type UpdatePodIdentityAssociationOptions struct { PodIdentityAssociationOptions // RoleARN is the IAM role ARN to be associated with the pod. RoleARN string + // TargetRoleARN is the new target IAM role to associate with the service account. + // This is used for cross-account pod identity access. + TargetRoleARN string + // DisableSessionTags is a boolean flag to enable or disable session tags. + // This is used for cross-account pod identity access. + DisableSessionTags bool } // NewUpdatePodIdentityAssociationLoader will load config or use flags for `eksctl update podidentityassociation`. func NewUpdatePodIdentityAssociationLoader(cmd *Cmd, options UpdatePodIdentityAssociationOptions) ClusterConfigLoader { l := newCommonClusterConfigLoader(cmd) - l.flagsIncompatibleWithConfigFile.Insert("namespace", "service-account-name", "role-arn") + l.flagsIncompatibleWithConfigFile.Insert("namespace", "service-account-name", "role-arn", "target-role-arn", "disable-session-tags") l.validateWithoutConfigFile = func() error { if err := validatePodIdentityAssociation(l, options.PodIdentityAssociationOptions); err != nil { diff --git a/pkg/ctl/update/pod_identity_association.go b/pkg/ctl/update/pod_identity_association.go index e4aa08c39c..d84dfc8c5e 100644 --- a/pkg/ctl/update/pod_identity_association.go +++ b/pkg/ctl/update/pod_identity_association.go @@ -35,7 +35,8 @@ func updatePodIdentityAssociation(cmd *cmdutils.Cmd) { fs.StringVar(&options.Namespace, "namespace", "", "Namespace of the pod identity association") fs.StringVar(&options.ServiceAccountName, "service-account-name", "", "Service account name of the pod identity association") fs.StringVar(&options.RoleARN, "role-arn", "", "ARN of the IAM role to be associated with the service account") - + fs.StringVar(&options.TargetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access") + fs.BoolVar(&options.DisableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") }) cmdutils.AddCommonFlagsForAWS(cmd, &cmd.ProviderConfig, false) @@ -67,6 +68,8 @@ func doUpdatePodIdentityAssociation(cmd *cmdutils.Cmd, options cmdutils.UpdatePo Namespace: options.Namespace, ServiceAccountName: options.ServiceAccountName, RoleARN: options.RoleARN, + TargetRoleARN: options.TargetRoleARN, + DisableSessionTags: options.DisableSessionTags, }, } } diff --git a/pkg/ctl/update/pod_identity_association_test.go b/pkg/ctl/update/pod_identity_association_test.go new file mode 100644 index 0000000000..293e5c42c1 --- /dev/null +++ b/pkg/ctl/update/pod_identity_association_test.go @@ -0,0 +1,139 @@ +package update + +import ( + "context" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/eks" + ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types" + "github.com/spf13/cobra" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/weaveworks/eksctl/pkg/actions/podidentityassociation" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" + "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" +) + +// mockStackManager is a mock implementation of the StackUpdater interface +type mockStackManager struct { + mock.Mock +} + +func (m *mockStackManager) ListPodIdentityStackNames(ctx context.Context) ([]string, error) { + return []string{}, nil +} + +func (m *mockStackManager) MustUpdateStack(ctx context.Context, options manager.UpdateStackOptions) error { + return nil +} + +func (m *mockStackManager) DescribeStack(ctx context.Context, stack *manager.Stack) (*manager.Stack, error) { + return stack, nil +} + +func (m *mockStackManager) GetIAMServiceAccounts(ctx context.Context, namespace, name string) ([]*api.ClusterIAMServiceAccount, error) { + return []*api.ClusterIAMServiceAccount{}, nil +} + +func (m *mockStackManager) GetStackTemplate(ctx context.Context, stackName string) (string, error) { + return "", nil +} + +func TestUpdatePodIdentityAssociationWithCrossAccountAccess(t *testing.T) { + // Create a mock provider + p := mockprovider.NewMockProvider() + mockEKS := p.MockEKS() + + // Set up the expected API calls + mockEKS.On("ListPodIdentityAssociations", mock.Anything, &eks.ListPodIdentityAssociationsInput{ + ClusterName: aws.String("test-cluster"), + Namespace: aws.String("default"), + ServiceAccount: aws.String("test-sa"), + }).Return(&eks.ListPodIdentityAssociationsOutput{ + Associations: []ekstypes.PodIdentityAssociationSummary{ + { + AssociationId: aws.String("test-association-id"), + }, + }, + }, nil) + + mockEKS.On("DescribePodIdentityAssociation", mock.Anything, &eks.DescribePodIdentityAssociationInput{ + ClusterName: aws.String("test-cluster"), + AssociationId: aws.String("test-association-id"), + }).Return(&eks.DescribePodIdentityAssociationOutput{ + Association: &ekstypes.PodIdentityAssociation{ + AssociationId: aws.String("test-association-id"), + RoleArn: aws.String("arn:aws:iam::111122223333:role/old-role"), + }, + }, nil) + + // This is the key part of the test - we're capturing the input to verify the fields + var capturedInput *eks.UpdatePodIdentityAssociationInput + mockEKS.On("UpdatePodIdentityAssociation", mock.Anything, mock.MatchedBy(func(input *eks.UpdatePodIdentityAssociationInput) bool { + capturedInput = input + return true + })).Return(&eks.UpdatePodIdentityAssociationOutput{}, nil) + + // Create a command with a mock implementation of doUpdatePodIdentityAssociation + // that doesn't call NewProviderForExistingCluster + cmd := &cmdutils.Cmd{ + CobraCommand: &cobra.Command{}, + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + } + cmd.ClusterConfig.Metadata.Name = "test-cluster" + cmd.ProviderConfig.Region = "us-west-2" + + // Set up the options with cross-account access fields + options := cmdutils.UpdatePodIdentityAssociationOptions{ + PodIdentityAssociationOptions: cmdutils.PodIdentityAssociationOptions{ + Namespace: "default", + ServiceAccountName: "test-sa", + }, + RoleARN: "arn:aws:iam::111122223333:role/source-role", + TargetRoleARN: "arn:aws:iam::444455556666:role/target-role", + DisableSessionTags: true, + } + + // Create the pod identity association in the cluster config + cmd.ClusterConfig.IAM.PodIdentityAssociations = []api.PodIdentityAssociation{ + { + Namespace: options.Namespace, + ServiceAccountName: options.ServiceAccountName, + RoleARN: options.RoleARN, + TargetRoleARN: options.TargetRoleARN, + DisableSessionTags: options.DisableSessionTags, + }, + } + + // Instead of calling doUpdatePodIdentityAssociation, we'll directly call the updater + // with our mock provider to test the API calls + stackManager := &mockStackManager{} + updater := &podidentityassociation.Updater{ + ClusterName: cmd.ClusterConfig.Metadata.Name, + APIUpdater: p.EKS(), + StackUpdater: stackManager, + } + err := updater.Update(context.Background(), cmd.ClusterConfig.IAM.PodIdentityAssociations) + require.NoError(t, err) + + // Verify that the API was called with the correct parameters + require.NotNil(t, capturedInput) + require.Equal(t, "test-association-id", *capturedInput.AssociationId) + require.Equal(t, "test-cluster", *capturedInput.ClusterName) + require.Equal(t, "arn:aws:iam::111122223333:role/source-role", *capturedInput.RoleArn) + + // Verify the cross-account access fields + require.NotNil(t, capturedInput.TargetRoleArn) + require.Equal(t, "arn:aws:iam::444455556666:role/target-role", *capturedInput.TargetRoleArn) + + require.NotNil(t, capturedInput.DisableSessionTags) + require.True(t, *capturedInput.DisableSessionTags) + + // Verify all expectations were met + mockEKS.AssertExpectations(t) +} From 4c3a8b710e7eb75f3f61455d1ab7308c87d30a82 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Thu, 10 Jul 2025 23:06:57 +0000 Subject: [PATCH 18/25] add support for CreateUpdatePodIdentityAssociation CLI command --- pkg/ctl/cmdutils/pod_identity_association.go | 2 ++ pkg/ctl/create/pod_identity_association.go | 2 ++ pkg/ctl/create/pod_identity_association_test.go | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/pkg/ctl/cmdutils/pod_identity_association.go b/pkg/ctl/cmdutils/pod_identity_association.go index a358553326..09eb96e979 100644 --- a/pkg/ctl/cmdutils/pod_identity_association.go +++ b/pkg/ctl/cmdutils/pod_identity_association.go @@ -20,6 +20,8 @@ var ( "permission-policy-arn", "well-known-policies", "create-service-account", + "target-role-arn", + "disable-session-tags", } ) diff --git a/pkg/ctl/create/pod_identity_association.go b/pkg/ctl/create/pod_identity_association.go index d0bc9e447f..1c8e36ef06 100644 --- a/pkg/ctl/create/pod_identity_association.go +++ b/pkg/ctl/create/pod_identity_association.go @@ -71,6 +71,8 @@ func configureCreatePodIdentityAssociationCmd(cmd *cmdutils.Cmd, pia *api.PodIde fs.StringVar(&pia.RoleARN, "role-arn", "", "ARN of the IAM role to be associated with the service account") fs.StringVar(&pia.RoleName, "role-name", "", "Set a custom name for the created role") fs.StringVar(&pia.PermissionsBoundaryARN, "permission-boundary-arn", "", "ARN of the policy that is used to set the permission boundary for the role") + fs.StringVar(&pia.TargetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access") + fs.BoolVar(&pia.DisableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") fs.BoolVar(&pia.CreateServiceAccount, "create-service-account", false, "instructs eksctl to create the K8s service account") diff --git a/pkg/ctl/create/pod_identity_association_test.go b/pkg/ctl/create/pod_identity_association_test.go index 49a488a569..688c2733f7 100644 --- a/pkg/ctl/create/pod_identity_association_test.go +++ b/pkg/ctl/create/pod_identity_association_test.go @@ -69,5 +69,13 @@ var _ = Describe("create pod identity association", func() { args: append(defaultArgs, "--well-known-policies=invalid"), expectedErr: "invalid wellKnownPolicy", }), + Entry("setting --target-role-arn and --config-file at the same time", createPodIdentityAssociationEntry{ + args: []string{"--target-role-arn", "arn:aws:iam::444455556666:role/target-role", "--config-file", configFile}, + expectedErr: "cannot use --target-role-arn when --config-file/-f is set", + }), + Entry("setting --disable-session-tags and --config-file at the same time", createPodIdentityAssociationEntry{ + args: []string{"--disable-session-tags", "--config-file", configFile}, + expectedErr: "cannot use --disable-session-tags when --config-file/-f is set", + }), ) }) From 9a897e2cf675a109d0986c6425c2f4af57906227 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Fri, 11 Jul 2025 00:09:16 +0000 Subject: [PATCH 19/25] remove unused func --- pkg/apis/eksctl.io/v1alpha5/validation.go | 48 -------------- .../eksctl.io/v1alpha5/validation_test.go | 65 ------------------- 2 files changed, 113 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 3c6b8ff40e..eb7a1181c1 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -1834,51 +1834,3 @@ func validateAddonPodIdentityAssociations(addons []*Addon) error { } return nil } -// ValidatePodIdentityAssociation validates a pod identity association configuration. -func ValidatePodIdentityAssociation(pia *PodIdentityAssociation) error { - if pia.Namespace == "" { - return errors.New("namespace cannot be empty") - } - - if pia.ServiceAccountName == "" { - return errors.New("serviceAccountName cannot be empty") - } - - // If targetRoleARN is specified, validate it - if pia.TargetRoleARN != "" { - if !arn.IsARN(pia.TargetRoleARN) { - return fmt.Errorf("targetRoleARN %q is not a valid ARN", pia.TargetRoleARN) - } - - parsedARN, err := arn.Parse(pia.TargetRoleARN) - if err != nil { - return fmt.Errorf("failed to parse targetRoleARN: %w", err) - } - - if parsedARN.Service != "iam" { - return fmt.Errorf("targetRoleARN must be an IAM role ARN") - } - - if !strings.HasPrefix(parsedARN.Resource, "role/") { - return fmt.Errorf("targetRoleARN must be an IAM role ARN (resource must start with 'role/')") - } - - // If roleARN is specified, validate that the source and target roles are in different accounts - if pia.RoleARN != "" { - if !arn.IsARN(pia.RoleARN) { - return fmt.Errorf("roleARN %q is not a valid ARN", pia.RoleARN) - } - - sourceARN, err := arn.Parse(pia.RoleARN) - if err != nil { - return fmt.Errorf("failed to parse roleARN: %w", err) - } - - if sourceARN.AccountID == parsedARN.AccountID { - return fmt.Errorf("targetRoleARN must be in a different account than roleARN for cross-account access") - } - } - } - - return nil -} diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index a26b4c571a..27e235099b 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -2801,68 +2801,3 @@ func newNodeGroup() *api.NodeGroup { NodeGroupBase: &api.NodeGroupBase{}, } } -var _ = Describe("PodIdentityAssociation validation", func() { - Describe("ValidatePodIdentityAssociation", func() { - It("should pass for a valid pod identity association", func() { - pia := &api.PodIdentityAssociation{ - Namespace: "default", - ServiceAccountName: "my-service-account", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).NotTo(HaveOccurred()) - }) - - It("should fail if namespace is empty", func() { - pia := &api.PodIdentityAssociation{ - ServiceAccountName: "my-service-account", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).To(MatchError("namespace cannot be empty")) - }) - - It("should fail if serviceAccountName is empty", func() { - pia := &api.PodIdentityAssociation{ - Namespace: "default", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).To(MatchError("serviceAccountName cannot be empty")) - }) - - It("should pass for a valid cross-account pod identity association", func() { - pia := &api.PodIdentityAssociation{ - Namespace: "default", - ServiceAccountName: "my-service-account", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - TargetRoleARN: "arn:aws:iam::987654321098:role/target-role", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).NotTo(HaveOccurred()) - }) - - It("should fail if targetRoleARN is not a valid ARN", func() { - pia := &api.PodIdentityAssociation{ - Namespace: "default", - ServiceAccountName: "my-service-account", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - TargetRoleARN: "not-an-arn", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).To(MatchError(ContainSubstring("targetRoleARN"))) - Expect(err).To(MatchError(ContainSubstring("not a valid ARN"))) - }) - - It("should fail if source and target roles are in the same account", func() { - pia := &api.PodIdentityAssociation{ - Namespace: "default", - ServiceAccountName: "my-service-account", - RoleARN: "arn:aws:iam::123456789012:role/my-role", - TargetRoleARN: "arn:aws:iam::123456789012:role/target-role", - } - err := api.ValidatePodIdentityAssociation(pia) - Expect(err).To(MatchError(ContainSubstring("targetRoleARN must be in a different account than roleARN"))) - }) - }) -}) From aac71ca58850ef72c3fa19006cc5e3e6bd8f6c20 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Fri, 11 Jul 2025 17:56:43 +0000 Subject: [PATCH 20/25] use sudo apt update in link checker to fix lib not found issue --- .github/workflows/link-checker.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/link-checker.yaml b/.github/workflows/link-checker.yaml index c76c0e15da..11e1a331cf 100644 --- a/.github/workflows/link-checker.yaml +++ b/.github/workflows/link-checker.yaml @@ -11,6 +11,9 @@ jobs: name: Check site links runs-on: ubuntu-latest steps: + - name: Update package repository + run: sudo apt update + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 - name: Set up Python From b2d384e16025c906080b3fe457976c3937f1e839 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 14 Jul 2025 16:59:50 +0000 Subject: [PATCH 21/25] rm wellKnownPolicies from example --- examples/39-pod-identity-association.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/39-pod-identity-association.yaml b/examples/39-pod-identity-association.yaml index d5c1da46d9..bb08c4e4f5 100644 --- a/examples/39-pod-identity-association.yaml +++ b/examples/39-pod-identity-association.yaml @@ -70,6 +70,3 @@ iam: targetRoleARN: arn:aws:iam::444455556666:role/role-b # This permission policy must allow assumption of the targetRoleARN permissionPolicyARNs: ["arn:aws:iam::111122223333:policy/my-cross-account-permission-policy"] - wellKnownPolicies: - autoScaler: true - externalDNS: true From be20404b85310720f1080a7a6dab036438509e6d Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 14 Jul 2025 18:48:09 +0000 Subject: [PATCH 22/25] handle targetRoleARN and disableSessionTags as pointers to ensure they arent modified when no flag provided --- .../podidentityassociation/creator_test.go | 5 ++-- pkg/actions/podidentityassociation/tasks.go | 8 +++---- pkg/actions/podidentityassociation/updater.go | 23 ++++++++++--------- .../podidentityassociation/updater_test.go | 16 ++++++------- .../eksctl.io/v1alpha5/assets/schema.json | 3 +-- pkg/apis/eksctl.io/v1alpha5/iam.go | 4 ++-- pkg/ctl/cmdutils/pod_identity_association.go | 4 ++-- pkg/ctl/create/pod_identity_association.go | 16 +++++++++++-- pkg/ctl/update/pod_identity_association.go | 14 +++++++++-- .../update/pod_identity_association_test.go | 4 ++-- 10 files changed, 60 insertions(+), 37 deletions(-) diff --git a/pkg/actions/podidentityassociation/creator_test.go b/pkg/actions/podidentityassociation/creator_test.go index 316557674f..526f6d6b90 100644 --- a/pkg/actions/podidentityassociation/creator_test.go +++ b/pkg/actions/podidentityassociation/creator_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/aws/aws-sdk-go-v2/aws" awseks "github.com/aws/aws-sdk-go-v2/service/eks" "k8s.io/apimachinery/pkg/runtime" @@ -146,8 +147,8 @@ var _ = Describe("Create", func() { Namespace: namespace, ServiceAccountName: serviceAccountName1, RoleARN: roleARN, - TargetRoleARN: "arn:aws:iam::444455556666:role/TargetRole", - DisableSessionTags: true, + TargetRoleARN: aws.String("arn:aws:iam::444455556666:role/TargetRole"), + DisableSessionTags: aws.Bool(true), }, }, mockEKS: func(provider *mockprovider.MockProvider) { diff --git a/pkg/actions/podidentityassociation/tasks.go b/pkg/actions/podidentityassociation/tasks.go index 51bad5c01f..be2c1212f0 100644 --- a/pkg/actions/podidentityassociation/tasks.go +++ b/pkg/actions/podidentityassociation/tasks.go @@ -52,15 +52,15 @@ func (t *createPodIdentityAssociationTask) Do(errorCh chan error) error { } // Add target role ARN if specified (for cross-account access) - if t.podIdentityAssociation.TargetRoleARN != "" { + if t.podIdentityAssociation.TargetRoleARN != nil && *t.podIdentityAssociation.TargetRoleARN != "" { logger.Info("Target role ARN %q specified for cross-account access", t.podIdentityAssociation.TargetRoleARN) - input.TargetRoleArn = &t.podIdentityAssociation.TargetRoleARN + input.TargetRoleArn = t.podIdentityAssociation.TargetRoleARN } // Add disable session tags if specified - if t.podIdentityAssociation.DisableSessionTags { + if t.podIdentityAssociation.DisableSessionTags != nil { logger.Info("Session tags will be disabled for this pod identity association") - input.DisableSessionTags = &t.podIdentityAssociation.DisableSessionTags + input.DisableSessionTags = t.podIdentityAssociation.DisableSessionTags } if _, err := t.eksAPI.CreatePodIdentityAssociation(t.ctx, input); err != nil { diff --git a/pkg/actions/podidentityassociation/updater.go b/pkg/actions/podidentityassociation/updater.go index 1c31d3518d..ed6ab78648 100644 --- a/pkg/actions/podidentityassociation/updater.go +++ b/pkg/actions/podidentityassociation/updater.go @@ -97,7 +97,11 @@ func (u *Updater) update(ctx context.Context, updateConfig *UpdateConfig, podIde if err != nil { return err } - if !hasChanged { + + // If there's no change to the IAM role or pod identity association properties, return early + if !hasChanged && + updateConfig.PodIdentityAssociation.TargetRoleARN == nil && + updateConfig.PodIdentityAssociation.DisableSessionTags == nil { return nil } roleARN = newRoleARN @@ -112,21 +116,18 @@ func (u *Updater) updatePodIdentityAssociation(ctx context.Context, roleARN stri RoleArn: aws.String(roleARN), } - // Add target role ARN if specified (for cross-account access) - if updateConfig.PodIdentityAssociation.TargetRoleARN != "" { - logger.Info("Target role ARN %q specified for cross-account access", updateConfig.PodIdentityAssociation.TargetRoleARN) - input.TargetRoleArn = &updateConfig.PodIdentityAssociation.TargetRoleARN + if updateConfig.PodIdentityAssociation.TargetRoleARN != nil { + input.TargetRoleArn = updateConfig.PodIdentityAssociation.TargetRoleARN } - - // Add disable session tags if specified - if updateConfig.PodIdentityAssociation.DisableSessionTags { - logger.Info("Session tags will be disabled for this pod identity association") - input.DisableSessionTags = &updateConfig.PodIdentityAssociation.DisableSessionTags + if updateConfig.PodIdentityAssociation.DisableSessionTags != nil { + input.DisableSessionTags = updateConfig.PodIdentityAssociation.DisableSessionTags } if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, input); err != nil { - return fmt.Errorf("(associationID: %s, roleARN: %s): %w", updateConfig.AssociationID, roleARN, err) + return fmt.Errorf("updating pod identity association (associationID: %s, roleARN: %s): %w", + updateConfig.AssociationID, roleARN, err) } + logger.Info("updated role ARN %q for pod identity association %q", roleARN, podIdentityAssociationID) return nil } diff --git a/pkg/actions/podidentityassociation/updater_test.go b/pkg/actions/podidentityassociation/updater_test.go index e6dfe5c2bd..af03867c26 100644 --- a/pkg/actions/podidentityassociation/updater_test.go +++ b/pkg/actions/podidentityassociation/updater_test.go @@ -83,15 +83,15 @@ var _ = Describe("Pod Identity Update", func() { Namespace: "default", ServiceAccountName: "default", RoleARN: "arn:aws:iam::00000000:role/source-role", - TargetRoleARN: "arn:aws:iam::11111111:role/target-role", - DisableSessionTags: true, + TargetRoleARN: aws.String("arn:aws:iam::11111111:role/target-role"), + DisableSessionTags: aws.Bool(true), }, } { - if pia.TargetRoleARN != "" { - input.TargetRoleArn = &pia.TargetRoleARN + if pia.TargetRoleARN != nil { + input.TargetRoleArn = pia.TargetRoleARN } - if pia.DisableSessionTags { - input.DisableSessionTags = &pia.DisableSessionTags + if pia.DisableSessionTags != nil { + input.DisableSessionTags = pia.DisableSessionTags } } } @@ -462,8 +462,8 @@ var _ = Describe("Pod Identity Update", func() { Namespace: "default", ServiceAccountName: "default", RoleARN: "arn:aws:iam::00000000:role/source-role", - TargetRoleARN: "arn:aws:iam::11111111:role/target-role", - DisableSessionTags: true, + TargetRoleARN: aws.String("arn:aws:iam::11111111:role/target-role"), + DisableSessionTags: aws.Bool(true), }, }, mockCalls: func(stackManager *managerfakes.FakeStackManager, eksAPI *mocksv2.EKS) { diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index e9e82703fa..e3ae66cc4e 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -2516,8 +2516,7 @@ "disableSessionTags": { "type": "boolean", "description": "disables the tags that are automatically added to role session by Amazon EKS.", - "x-intellij-html-description": "disables the tags that are automatically added to role session by Amazon EKS.", - "default": "false" + "x-intellij-html-description": "disables the tags that are automatically added to role session by Amazon EKS." }, "namespace": { "type": "string" diff --git a/pkg/apis/eksctl.io/v1alpha5/iam.go b/pkg/apis/eksctl.io/v1alpha5/iam.go index ff6a05e5ce..3c646916d3 100644 --- a/pkg/apis/eksctl.io/v1alpha5/iam.go +++ b/pkg/apis/eksctl.io/v1alpha5/iam.go @@ -198,11 +198,11 @@ type PodIdentityAssociation struct { // +optional // TargetRoleARN is the Amazon Resource Name (ARN) of the IAM role to be chained to the IAM role specified as RoleARN. // This enables cross-account access where the RoleARN is in the same account as the cluster and TargetRoleARN is in a different account. - TargetRoleARN string `json:"targetRoleARN,omitempty"` + TargetRoleARN *string `json:"targetRoleARN,omitempty"` // +optional // DisableSessionTags disables the tags that are automatically added to role session by Amazon EKS. - DisableSessionTags bool `json:"disableSessionTags,omitempty"` + DisableSessionTags *bool `json:"disableSessionTags,omitempty"` } func (p PodIdentityAssociation) NameString() string { diff --git a/pkg/ctl/cmdutils/pod_identity_association.go b/pkg/ctl/cmdutils/pod_identity_association.go index 09eb96e979..0a3a022ddc 100644 --- a/pkg/ctl/cmdutils/pod_identity_association.go +++ b/pkg/ctl/cmdutils/pod_identity_association.go @@ -177,10 +177,10 @@ type UpdatePodIdentityAssociationOptions struct { RoleARN string // TargetRoleARN is the new target IAM role to associate with the service account. // This is used for cross-account pod identity access. - TargetRoleARN string + TargetRoleARN *string // DisableSessionTags is a boolean flag to enable or disable session tags. // This is used for cross-account pod identity access. - DisableSessionTags bool + DisableSessionTags *bool } // NewUpdatePodIdentityAssociationLoader will load config or use flags for `eksctl update podidentityassociation`. diff --git a/pkg/ctl/create/pod_identity_association.go b/pkg/ctl/create/pod_identity_association.go index 1c8e36ef06..4daa88c3b8 100644 --- a/pkg/ctl/create/pod_identity_association.go +++ b/pkg/ctl/create/pod_identity_association.go @@ -71,8 +71,20 @@ func configureCreatePodIdentityAssociationCmd(cmd *cmdutils.Cmd, pia *api.PodIde fs.StringVar(&pia.RoleARN, "role-arn", "", "ARN of the IAM role to be associated with the service account") fs.StringVar(&pia.RoleName, "role-name", "", "Set a custom name for the created role") fs.StringVar(&pia.PermissionsBoundaryARN, "permission-boundary-arn", "", "ARN of the policy that is used to set the permission boundary for the role") - fs.StringVar(&pia.TargetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access") - fs.BoolVar(&pia.DisableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") + var targetRoleARN string + var disableSessionTags bool + fs.StringVar(&targetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access (default to empty string for no cross-account access)") + fs.BoolVar(&disableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity (default false)") + + // Store the flag values in the struct + cmdutils.AddPreRun(cmd.CobraCommand, func(cobraCmd *cobra.Command, args []string) { + if fs.Changed("target-role-arn") { + pia.TargetRoleARN = &targetRoleARN + } + if fs.Changed("disable-session-tags") { + pia.DisableSessionTags = &disableSessionTags + } + }) fs.BoolVar(&pia.CreateServiceAccount, "create-service-account", false, "instructs eksctl to create the K8s service account") diff --git a/pkg/ctl/update/pod_identity_association.go b/pkg/ctl/update/pod_identity_association.go index d84dfc8c5e..7409c940cc 100644 --- a/pkg/ctl/update/pod_identity_association.go +++ b/pkg/ctl/update/pod_identity_association.go @@ -35,8 +35,18 @@ func updatePodIdentityAssociation(cmd *cmdutils.Cmd) { fs.StringVar(&options.Namespace, "namespace", "", "Namespace of the pod identity association") fs.StringVar(&options.ServiceAccountName, "service-account-name", "", "Service account name of the pod identity association") fs.StringVar(&options.RoleARN, "role-arn", "", "ARN of the IAM role to be associated with the service account") - fs.StringVar(&options.TargetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access") - fs.BoolVar(&options.DisableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") + var targetRoleArn string + var disableSessionTags bool + fs.StringVar(&targetRoleArn, "target-role-arn", "", "ARN of the target IAM role for cross-account access") + fs.BoolVar(&disableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") + cmdutils.AddPreRun(cmd.CobraCommand, func(cobraCmd *cobra.Command, args []string) { + if fs.Changed("target-role-arn") { + options.TargetRoleARN = &targetRoleArn + } + if fs.Changed("disable-session-tags") { + options.DisableSessionTags = &disableSessionTags + } + }) }) cmdutils.AddCommonFlagsForAWS(cmd, &cmd.ProviderConfig, false) diff --git a/pkg/ctl/update/pod_identity_association_test.go b/pkg/ctl/update/pod_identity_association_test.go index 293e5c42c1..e816e8c1a3 100644 --- a/pkg/ctl/update/pod_identity_association_test.go +++ b/pkg/ctl/update/pod_identity_association_test.go @@ -95,8 +95,8 @@ func TestUpdatePodIdentityAssociationWithCrossAccountAccess(t *testing.T) { ServiceAccountName: "test-sa", }, RoleARN: "arn:aws:iam::111122223333:role/source-role", - TargetRoleARN: "arn:aws:iam::444455556666:role/target-role", - DisableSessionTags: true, + TargetRoleARN: aws.String("arn:aws:iam::444455556666:role/target-role"), + DisableSessionTags: aws.Bool(true), } // Create the pod identity association in the cluster config From 27aebd5c723205f9640f70f664165e406981a141 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Mon, 14 Jul 2025 19:11:54 +0000 Subject: [PATCH 23/25] add no-disable-session-tags arg for update --- pkg/ctl/create/pod_identity_association.go | 5 +++-- pkg/ctl/update/pod_identity_association.go | 10 +++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/ctl/create/pod_identity_association.go b/pkg/ctl/create/pod_identity_association.go index 4daa88c3b8..ceb22c4c59 100644 --- a/pkg/ctl/create/pod_identity_association.go +++ b/pkg/ctl/create/pod_identity_association.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -74,7 +75,7 @@ func configureCreatePodIdentityAssociationCmd(cmd *cmdutils.Cmd, pia *api.PodIde var targetRoleARN string var disableSessionTags bool fs.StringVar(&targetRoleARN, "target-role-arn", "", "ARN of the target IAM role for cross-account access (default to empty string for no cross-account access)") - fs.BoolVar(&disableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity (default false)") + fs.BoolVar(&disableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity (if not provided, session tags are enabled by default)") // Store the flag values in the struct cmdutils.AddPreRun(cmd.CobraCommand, func(cobraCmd *cobra.Command, args []string) { @@ -82,7 +83,7 @@ func configureCreatePodIdentityAssociationCmd(cmd *cmdutils.Cmd, pia *api.PodIde pia.TargetRoleARN = &targetRoleARN } if fs.Changed("disable-session-tags") { - pia.DisableSessionTags = &disableSessionTags + pia.DisableSessionTags = aws.Bool(true) } }) diff --git a/pkg/ctl/update/pod_identity_association.go b/pkg/ctl/update/pod_identity_association.go index 7409c940cc..f84532e651 100644 --- a/pkg/ctl/update/pod_identity_association.go +++ b/pkg/ctl/update/pod_identity_association.go @@ -3,6 +3,7 @@ package update import ( "context" + "github.com/aws/aws-sdk-go/aws" "github.com/weaveworks/eksctl/pkg/actions/podidentityassociation" "github.com/spf13/cobra" @@ -36,15 +37,18 @@ func updatePodIdentityAssociation(cmd *cmdutils.Cmd) { fs.StringVar(&options.ServiceAccountName, "service-account-name", "", "Service account name of the pod identity association") fs.StringVar(&options.RoleARN, "role-arn", "", "ARN of the IAM role to be associated with the service account") var targetRoleArn string - var disableSessionTags bool + var disableSessionTags, noDisableSessionTags bool fs.StringVar(&targetRoleArn, "target-role-arn", "", "ARN of the target IAM role for cross-account access") fs.BoolVar(&disableSessionTags, "disable-session-tags", false, "Disable session tags added by EKS Pod Identity") + fs.BoolVar(&noDisableSessionTags, "no-disable-session-tags", false, "Enable session tags added by EKS Pod Identity") cmdutils.AddPreRun(cmd.CobraCommand, func(cobraCmd *cobra.Command, args []string) { if fs.Changed("target-role-arn") { options.TargetRoleARN = &targetRoleArn } - if fs.Changed("disable-session-tags") { - options.DisableSessionTags = &disableSessionTags + if fs.Changed("no-disable-session-tags") { + options.DisableSessionTags = aws.Bool(false) + } else if fs.Changed("disable-session-tags") { + options.DisableSessionTags = aws.Bool(true) } }) }) From 939a2bd1a2c2e5552630dd1a6249c44e79f1d98f Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Thu, 17 Jul 2025 03:54:06 +0000 Subject: [PATCH 24/25] remove link-checker workflow --- .github/workflows/link-checker.yaml | 39 ----------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .github/workflows/link-checker.yaml diff --git a/.github/workflows/link-checker.yaml b/.github/workflows/link-checker.yaml deleted file mode 100644 index 11e1a331cf..0000000000 --- a/.github/workflows/link-checker.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: Link checker - -on: - pull_request: - paths: - - 'userdocs/**' - - '**.md' - -jobs: - link-checker: - name: Check site links - runs-on: ubuntu-latest - steps: - - name: Update package repository - run: sudo apt update - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 - - - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 #v5.6.0 - with: - python-version: 3.12 - - - name: Setup Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 #v5.5.0 - with: - go-version: ~1.24.0 - cache: false - - - name: Install doc dependencies - run: make install-site-deps - - - name: Build docs for link check - run: make build-pages - - - name: Link Checker - uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 #v2.4.1 - with: - args: --exclude-all-private --exclude-mail --exclude-file .github/workflows/exclude-file.txt --exclude-path pkg/goformation --verbose --no-progress './**/*.md' './**/*.html' From 8874637fa107378e0b9b05b16fa97be0e0af2b29 Mon Sep 17 00:00:00 2001 From: Nathan Clonts Date: Thu, 17 Jul 2025 04:11:00 +0000 Subject: [PATCH 25/25] rm unnecessary logs and nil checks --- go.mod | 2 +- go.sum | 4 +-- pkg/actions/podidentityassociation/tasks.go | 18 ++++-------- pkg/actions/podidentityassociation/updater.go | 24 ++++++---------- pkg/awsapi/cloudwatchlogs.go | 28 +++++++++---------- 5 files changed, 30 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index 91cd714778..ed898313a8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/autoscaling v1.54.0 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0 github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.52.0 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 github.com/aws/aws-sdk-go-v2/service/eks v1.66.1 diff --git a/go.sum b/go.sum index 0ae42738d1..6c53636c15 100644 --- a/go.sum +++ b/go.sum @@ -130,8 +130,8 @@ github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0 h1:1nVq2bvAANTPAfipK github.com/aws/aws-sdk-go-v2/service/cloudformation v1.61.0/go.mod h1:xU79X14UC0F8sEJCRTWwINzlQ4jacpEFpRESLHRHfoY= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3 h1:wSQwBOXa1EV81WiVWLZ8fCrJ7wlwcfqSexEiv9OjPrA= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.49.3/go.mod h1:5N4LfimBXTCtqKr0tZKfcte5UswFb7SJZV+LiQUZsGk= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0 h1:e5cbPZYTIY2nUEFieZUfVdINOiCTvChOMPfdLnmiLzs= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.51.0/go.mod h1:UseIHRfrm7PqeZo6fcTb6FUCXzCnh1KJbQbmOfxArGM= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.52.0 h1:m6kVT+00x2NuB5ZEBbEV0rT1RCmf5e5e3yiQ7moWBbQ= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.52.0/go.mod h1:UseIHRfrm7PqeZo6fcTb6FUCXzCnh1KJbQbmOfxArGM= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3 h1:4U9dpQZTvJ0Mi1qn8L1hRJ4igFCQYEjwUuOmYkWM5tE= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.51.3/go.mod h1:ygltZT++6Wn2uG4+tqE0NW1MkdEtb5W2O/CFc0xJX/g= github.com/aws/aws-sdk-go-v2/service/ec2 v1.210.1 h1:+4A9SDduLZFlDeXWRmfQ6r8kyEJZQfK6lcg+KwdvWrI= diff --git a/pkg/actions/podidentityassociation/tasks.go b/pkg/actions/podidentityassociation/tasks.go index be2c1212f0..395d2a6133 100644 --- a/pkg/actions/podidentityassociation/tasks.go +++ b/pkg/actions/podidentityassociation/tasks.go @@ -44,25 +44,19 @@ func (t *createPodIdentityAssociationTask) Do(errorCh chan error) error { defer close(errorCh) input := &awseks.CreatePodIdentityAssociationInput{ - ClusterName: &t.clusterName, - Namespace: &t.podIdentityAssociation.Namespace, - RoleArn: &t.podIdentityAssociation.RoleARN, - ServiceAccount: &t.podIdentityAssociation.ServiceAccountName, - Tags: t.podIdentityAssociation.Tags, + ClusterName: &t.clusterName, + Namespace: &t.podIdentityAssociation.Namespace, + RoleArn: &t.podIdentityAssociation.RoleARN, + ServiceAccount: &t.podIdentityAssociation.ServiceAccountName, + Tags: t.podIdentityAssociation.Tags, + DisableSessionTags: t.podIdentityAssociation.DisableSessionTags, } // Add target role ARN if specified (for cross-account access) if t.podIdentityAssociation.TargetRoleARN != nil && *t.podIdentityAssociation.TargetRoleARN != "" { - logger.Info("Target role ARN %q specified for cross-account access", t.podIdentityAssociation.TargetRoleARN) input.TargetRoleArn = t.podIdentityAssociation.TargetRoleARN } - // Add disable session tags if specified - if t.podIdentityAssociation.DisableSessionTags != nil { - logger.Info("Session tags will be disabled for this pod identity association") - input.DisableSessionTags = t.podIdentityAssociation.DisableSessionTags - } - if _, err := t.eksAPI.CreatePodIdentityAssociation(t.ctx, input); err != nil { if t.ignorePodIdentityExistsErr { var inUseErr *ekstypes.ResourceInUseException diff --git a/pkg/actions/podidentityassociation/updater.go b/pkg/actions/podidentityassociation/updater.go index ed6ab78648..050528ff7d 100644 --- a/pkg/actions/podidentityassociation/updater.go +++ b/pkg/actions/podidentityassociation/updater.go @@ -110,22 +110,14 @@ func (u *Updater) update(ctx context.Context, updateConfig *UpdateConfig, podIde } func (u *Updater) updatePodIdentityAssociation(ctx context.Context, roleARN string, updateConfig *UpdateConfig, podIdentityAssociationID string) error { - input := &eks.UpdatePodIdentityAssociationInput{ - AssociationId: aws.String(updateConfig.AssociationID), - ClusterName: aws.String(u.ClusterName), - RoleArn: aws.String(roleARN), - } - - if updateConfig.PodIdentityAssociation.TargetRoleARN != nil { - input.TargetRoleArn = updateConfig.PodIdentityAssociation.TargetRoleARN - } - if updateConfig.PodIdentityAssociation.DisableSessionTags != nil { - input.DisableSessionTags = updateConfig.PodIdentityAssociation.DisableSessionTags - } - - if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, input); err != nil { - return fmt.Errorf("updating pod identity association (associationID: %s, roleARN: %s): %w", - updateConfig.AssociationID, roleARN, err) + if _, err := u.APIUpdater.UpdatePodIdentityAssociation(ctx, &eks.UpdatePodIdentityAssociationInput{ + AssociationId: aws.String(updateConfig.AssociationID), + ClusterName: aws.String(u.ClusterName), + RoleArn: aws.String(roleARN), + TargetRoleArn: updateConfig.PodIdentityAssociation.TargetRoleARN, + DisableSessionTags: updateConfig.PodIdentityAssociation.DisableSessionTags, + }); err != nil { + return fmt.Errorf("(associationID: %s, roleARN: %s): %w", updateConfig.AssociationID, roleARN, err) } logger.Info("updated role ARN %q for pod identity association %q", roleARN, podIdentityAssociationID) diff --git a/pkg/awsapi/cloudwatchlogs.go b/pkg/awsapi/cloudwatchlogs.go index 5740aacbe6..c559d1cf61 100644 --- a/pkg/awsapi/cloudwatchlogs.go +++ b/pkg/awsapi/cloudwatchlogs.go @@ -86,7 +86,7 @@ type CloudWatchLogs interface { // Permissions] in the table at [Enabling logging from Amazon Web Services services.] // // A delivery destination can represent a log group in CloudWatch Logs, an Amazon - // S3 bucket, or a delivery stream in Firehose. + // S3 bucket, a delivery stream in Firehose, or X-Ray. // // To configure logs delivery between a supported Amazon Web Services service and // a destination, you must do the following: @@ -154,11 +154,10 @@ type CloudWatchLogs interface { // // An anomaly detector can help surface issues by automatically discovering // anomalies in your log event traffic. An anomaly detector uses machine learning - // algorithms to scan log events and find patterns. - // - // A pattern is a shared text structure that recurs among your log fields. - // Patterns provide a useful tool for analyzing large sets of logs because a large - // number of log events can often be compressed into a few patterns. + // algorithms to scan log events and find patterns. A pattern is a shared text + // structure that recurs among your log fields. Patterns provide a useful tool for + // analyzing large sets of logs because a large number of log events can often be + // compressed into a few patterns. // // The anomaly detector uses pattern recognition to find anomalies , which are // unusual log events. It uses the evaluationFrequency to compare current log @@ -166,13 +165,11 @@ type CloudWatchLogs interface { // // Fields within a pattern are called tokens. Fields that vary within a pattern, // such as a request ID or timestamp, are referred to as dynamic tokens and - // represented by <> . + // represented by <*> . // // The following is an example of a pattern: // - // [INFO] Request time: < - // - // > ms + // [INFO] Request time: <*> ms // // This pattern represents log events like [INFO] Request time: 327 ms and other // similar log events that differ only by the number, in this csse 327. When the @@ -384,8 +381,8 @@ type CloudWatchLogs interface { // // A delivery source represents an Amazon Web Services resource that sends logs to // an logs delivery destination. The destination can be CloudWatch Logs, Amazon S3, - // or Firehose. Only some Amazon Web Services services support being configured as - // a delivery source. These services are listed in [Enable logging from Amazon Web Services services.] + // Firehose or X-Ray. Only some Amazon Web Services services support being + // configured as a delivery source. These services are listed in [Enable logging from Amazon Web Services services.] // // [delivery destination]: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutDeliveryDestination.html // [delivery source]: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutDeliverySource.html @@ -735,7 +732,7 @@ type CloudWatchLogs interface { // logs:PutDataProtectionPolicy and logs:PutAccountPolicy permissions. // // - To create a subscription filter policy, you must have the - // logs:PutSubscriptionFilter and logs:PutccountPolicy permissions. + // logs:PutSubscriptionFilter and logs:PutAccountPolicy permissions. // // - To create a transformer policy, you must have the logs:PutTransformer and // logs:PutAccountPolicy permissions. @@ -939,7 +936,7 @@ type CloudWatchLogs interface { // Creates or updates a logical delivery destination. A delivery destination is an // Amazon Web Services resource that represents an Amazon Web Services service that // logs can be sent to. CloudWatch Logs, Amazon S3, and Firehose are supported as - // logs delivery destinations. + // logs delivery destinations and X-Ray as the trace delivery destination. // // To configure logs delivery between a supported Amazon Web Services service and // a destination, you must do the following: @@ -1007,7 +1004,8 @@ type CloudWatchLogs interface { PutDeliveryDestinationPolicy(ctx context.Context, params *cloudwatchlogs.PutDeliveryDestinationPolicyInput, optFns ...func(*Options)) (*cloudwatchlogs.PutDeliveryDestinationPolicyOutput, error) // Creates or updates a logical delivery source. A delivery source represents an // Amazon Web Services resource that sends logs to an logs delivery destination. - // The destination can be CloudWatch Logs, Amazon S3, or Firehose. + // The destination can be CloudWatch Logs, Amazon S3, Firehose or X-Ray for sending + // traces. // // To configure logs delivery between a delivery destination and an Amazon Web // Services service that is supported as a delivery source, you must do the