Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cognito): add SAML user pool identity provider #21879

Merged
merged 12 commits into from
Sep 9, 2022

Conversation

ktfleming
Copy link
Contributor

Adds a construct for a SAML user pool identity provider.

I based much of this off of #20241, as the OIDC and SAML identity pool providers share e.g. the length limitations on provider names.

For the integration test, you have to specify a valid SAML metadata URL or XML document, or the stack won't be created. I used a sample URL from the samling project, but this could be changed if anyone has a better suggestion.


All Submissions:

Adding new Unconventional Dependencies:

  • This PR adds new unconventional dependencies following the process described here

New Features

  • Have you added the new feature to an integration test?
    • Did you use yarn integ to deploy the infrastructure and generate the snapshot (i.e. yarn integ without --dry-run)?

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

@gitpod-io
Copy link

gitpod-io bot commented Sep 1, 2022

@github-actions github-actions bot added the p2 label Sep 1, 2022
@aws-cdk-automation aws-cdk-automation requested a review from a team September 1, 2022 16:57
@ktfleming ktfleming changed the title feat(cognito): SAML user pool identity provider feat(cognito): add SAML user pool identity provider Sep 1, 2022
Copy link
Contributor

@TheRealAmazonKendra TheRealAmazonKendra left a comment

Choose a reason for hiding this comment

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

Thanks so much for the contribution! I have a few comments inline.

Comment on lines 84 to 101
private getProviderName(name?: string): string {
if (name) {
if (!Token.isUnresolved(name) && (name.length < 3 || name.length > 32)) {
throw new Error(`Expected provider name to be between 3 and 32 characters, received ${name} (${name.length} characters)`);
}
return name;
}

const uniqueId = Names.uniqueId(this);

if (uniqueId.length < 3) {
return `${uniqueId}saml`;
}

if (uniqueId.length > 32) {
return uniqueId.substring(0, 16) + uniqueId.substring(uniqueId.length - 16);
}
return uniqueId;
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of this, `Names.uniqueResourceName() should be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed Names.uniqueId to Names.uniqueResourceName, and used the maxLength option to avoid having to truncate it down to 32 characters.

Comment on lines 59 to 61
if (props.name && !Token.isUnresolved(props.name) && (props.name.length < 3 || props.name.length > 32)) {
throw new Error(`Expected provider name to be between 3 and 32 characters, received ${props.name} (${props.name.length} characters)`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You're doing this check multiple times. Let's remove the redundancy.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why is 3-32 the correct length required here? Also, your validation doesn't allow for it to be 3 characters or 32 so the error message is slightly misleading.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored into a validateName function.

Why is 3-32 the correct length required here?

That restriction appears in this page, under the "ProviderName" description.

your validation doesn't allow for it to be 3 characters or 32 so the error message is slightly misleading.

Hmm, I'm not sure about this, it only throws an error on props.name.length < 3 || props.name.length > 32, so I believe lengths of exactly 3 or 32 should still be allowed through.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oof. My tired brain reversed the logic in that. I was definitely wrong.

Comment on lines 11 to 15
/**
* The name of the provider.
*
* @default - the unique ID of the construct
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

If the length needs to be restricted, it should be added to the docstring so the first place the user encounters the information isn't in an error message.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this information to the docstring.

Comment on lines 28 to 39
* The SAML metadata file content.
*
* @default - no file content specified
*/
readonly metadataFile?: string;

/**
* The SAML metadata URL.
*
* @default - no URL specified
*/
readonly metadataUrl?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of having these be mutually exclusive and optional, let's have just one field that is required that can be of either type that we translate into the right field.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good -- I replaced these with metadataType and metadataContent props, both required. The former is an enum that determines how the latter should be interpreted (as a URL, or as XML content). This removes the need for the mutually-exclusive validation. Is that what you had in mind?

Copy link
Contributor

Choose a reason for hiding this comment

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

What I meant here was more along the lines of how we handle the different types of input that we turn into Schedule. I think that same conceptual approach can be used here. My apologies for not providing further context and that link here in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see! Trying to follow the example of Schedule, I've reworked it now to just have one field of type UserPoolIdentityProviderSamlMetadata, which can only be created by one of two methods, url and file. Using the appropriate one should ensure that the providerDetails in the CloudFormation resource are set correctly (translated to MetadataURL and MetadataFile respectively).

@mergify mergify bot dismissed TheRealAmazonKendra’s stale review September 2, 2022 13:48

Pull request has been modified.

@ktfleming
Copy link
Contributor Author

Thanks for the feedback @TheRealAmazonKendra! I've made changes and replied/explained in each of your comments.

Copy link
Contributor

@TheRealAmazonKendra TheRealAmazonKendra left a comment

Choose a reason for hiding this comment

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

In addition to the comment inline, please see my response to your comments from the last review. Besides those comments, however, I just want to say that the overall quality of this PR is excellent. Thank you for all your work on this!


this.validateName(props.name);

const providerDetails: Record<string, string | boolean> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm pretty sure this will run afoul of jsii. The union operator doesn't translate well in most cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the rework of how metadata is provided in 36965e7, this union operator has gone away.

@mergify mergify bot dismissed TheRealAmazonKendra’s stale review September 3, 2022 09:55

Pull request has been modified.

@ktfleming
Copy link
Contributor Author

In addition to the comment inline, please see my response to your comments from the last review. Besides those comments, however, I just want to say that the overall quality of this PR is excellent. Thank you for all your work on this!

Thank you! I tried a rework of the metadata part to bring it closer to the example that you showed me.

@mergify
Copy link
Contributor

mergify bot commented Sep 9, 2022

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: af574c0
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot merged commit 76d446b into aws:main Sep 9, 2022
@mergify
Copy link
Contributor

mergify bot commented Sep 9, 2022

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

Kruspe pushed a commit to DavidSchwarz2/aws-cdk that referenced this pull request Sep 13, 2022
Adds a construct for a SAML user pool identity provider.

I based much of this off of aws#20241, as the OIDC and SAML identity pool providers share e.g. the length limitations on provider names.

For the integration test, you have to specify a valid SAML metadata URL or XML document, or the stack won't be created. I used a sample URL from the [samling](https://fujifish.github.io/samling/samling.html) project, but this could be changed if anyone has a better suggestion.

----

### All Submissions:

* [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [X] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [X] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants