Skip to content

Conversation

@joris-de
Copy link

@joris-de joris-de commented Aug 20, 2025

Issue #20460

Closes #20460

Reason for this change

OpenIdConnectProvider creates a custom resource, which includes a lambda function. Currently, users cannot provide their own IAM role for this lambda function, it is auto generated. This limits users who need to use pre-existing roles due to organizational policies or specific permission requirements.

Description of changes

Added an optional role property to OpenIdConnectProviderProps that allows users to provide their own IAM role for the custom resource's lambda function. When a custom role is provided:

  • The custom resource provider uses the provided role instead of creating a new one
  • Users are responsible for ensuring the role has the required IAM permissions
  • The addToRolePolicy method throws an error if called when using a custom role

I have tried to automatically add the required IAM permissions to the custom role, but converting the JSON policy statements using PolicyStatement.fromJson() was not possible because it created a circular dependency. I did not find a good way to implement this functionality. Please let me know if you know how to do this.

Describe any new or updated permissions being added

No new permissions are added by this change. When users provide a custom role, they must manually add the required IAM permissions:

  • 'iam:CreateOpenIDConnectProvider'
  • 'iam:DeleteOpenIDConnectProvider'
  • 'iam:UpdateOpenIDConnectProviderThumbprint'
  • 'iam:AddClientIDToOpenIDConnectProvider'
  • 'iam:RemoveClientIDFromOpenIDConnectProvider'

Description of how you validated changes

I added unit tests for the OpenIdConnectProvider and CustomResourceProvider to verify:

  • Custom roles are properly used when provided
  • No automatic IAM role is created when a custom role is provided
  • The lambda function references the custom role ARN
  • addToRolePolicy throws an error when using custom roles
  • Existing functionality remains unchanged when no custom role is provided

I also added an integration test where the OpenIDConnectProvider is created with a custom role.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@joris-de joris-de requested a review from a team as a code owner August 20, 2025 11:21
@aws-cdk-automation aws-cdk-automation requested a review from a team August 20, 2025 11:21
@github-actions github-actions bot added beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK p2 labels Aug 20, 2025
Copy link
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This review is outdated)

@joris-de joris-de changed the title feat(iam): Custom Role Support for OpenIdConnectProvider feat(iam): custom role support for OpenIdConnectProvider Aug 20, 2025
@aws-cdk-automation aws-cdk-automation dismissed their stale review August 20, 2025 11:25

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

Copy link
Contributor

@iankhou iankhou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test coverage, left a couple of comments on typing. Thanks for working on this!

*
* @default - No role, will be created automatically with the required permissions.
*/
readonly role?: any;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we type this as IRole here?

@@ -1,3 +1,4 @@
// import { IRole } from '../../../aws-iam';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented out code, why don't we use this for the optionally-provided role?

Copy link
Author

@joris-de joris-de Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comments! I missed removing this. Added your suggestions.
Do you have any opinions if the permissions for the custom role should be added automatically in CustomResourceProviderBaseor should it be the responsibility of the user? If they should be added automatically, how can I fix TypeError: Class extends value undefined is not a constructor or null when importing
import { PolicyStatement } from '../../../aws-iam'; in aws-cdk/packages/aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider-base.ts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a custom role is being passed in, we should make it clear what the role needs to look like—I see you do this in the documentation. We can do one of the following:

  1. Have checks to ensure the role has the right permissions, and fail synth if not
  2. We add the permissions in CDK
  3. Synth without checks, and fail at deploy time if permissions are wrong

1 and 2 require us to maintain parity with the service's permission requirements, whereas the service should already have these checks. For 2, we would also need to handle failures in adding permissions.

3 will allow synthing of a potentially errant template, but only from the service perspective. Generally we follow this approach, to reduce duplication of validation that the service should do anyway, and pass through the error from the service.

Curious on @mrgrain's thoughts on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Synth without checks, and fail at deploy time if permissions are wrong

This wouldn't happen at deploy time, but at runtime (when the provider is used). It's the worst option.

  1. We add the permissions in CDK

This is what we usually do. There should be no difference to the role being user provided or created automatically by the CDK. It should really just be this:

this.role = props.role ?? new iam.Role(...);

@iankhou iankhou self-assigned this Aug 21, 2025
@iankhou iankhou added p1 and removed p2 labels Aug 21, 2025
Comment on lines +182 to +184
if (this.customRole) {
throw new ValidationError('Cannot call addToRolePolicy() when using a custom role. Add the required policies to your role directly.', this);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something we would usually do.

@iankhou
Copy link
Contributor

iankhou commented Aug 22, 2025

Hey, looks like OpenIdConnectProvider is replaced by OidcProviderNative, but the former cannot be deprecated yet due to EKS still using it.

However, we generally should not be updating OpenIdConnectProvider unless it's for critical security issues, or something that affects existing functionality. Apologies, it's not super clear in the docs, since OpenIdConnectProvider is not actually deprecated...

See the discussion here: #28634 (comment)

@iankhou iankhou closed this Aug 22, 2025
@github-actions
Copy link
Contributor

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 22, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK p1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants