Skip to content

Commit e7a2ca9

Browse files
authored
Merge branch 'main' into corymhall/lambda-sources/fix-queue
2 parents e1764b2 + 79c9ca1 commit e7a2ca9

182 files changed

Lines changed: 16117 additions & 1051 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/@aws-cdk/aws-cognito/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ The following third-party identity providers are currently supported in the CDK
528528
- [Google Login](https://developers.google.com/identity/sign-in/web/sign-in)
529529
- [Sign In With Apple](https://developer.apple.com/sign-in-with-apple/get-started/)
530530
- [OpenID Connect](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-oidc-idp.html)
531+
- [SAML](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp.html)
531532

532533
The following code configures a user pool to federate with the third party provider, 'Login with Amazon'. The identity
533534
provider needs to be configured with a set of credentials that the Cognito backend can use to federate with the

packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * from './amazon';
44
export * from './facebook';
55
export * from './google';
66
export * from './oidc';
7+
export * from './saml';
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { Names, Token } from '@aws-cdk/core';
2+
import { Construct } from 'constructs';
3+
import { CfnUserPoolIdentityProvider } from '../cognito.generated';
4+
import { UserPoolIdentityProviderProps } from './base';
5+
import { UserPoolIdentityProviderBase } from './private/user-pool-idp-base';
6+
7+
/**
8+
* Properties to initialize UserPoolIdentityProviderSaml.
9+
*/
10+
export interface UserPoolIdentityProviderSamlProps extends UserPoolIdentityProviderProps {
11+
/**
12+
* The name of the provider. Must be between 3 and 32 characters.
13+
*
14+
* @default - the unique ID of the construct
15+
*/
16+
readonly name?: string;
17+
18+
/**
19+
* Identifiers
20+
*
21+
* Identifiers can be used to redirect users to the correct IdP in multitenant apps.
22+
*
23+
* @default - no identifiers used
24+
*/
25+
readonly identifiers?: string[]
26+
27+
/**
28+
* The SAML metadata.
29+
*/
30+
readonly metadata: UserPoolIdentityProviderSamlMetadata;
31+
32+
/**
33+
* Whether to enable the "Sign-out flow" feature.
34+
*
35+
* @default - false
36+
*/
37+
readonly idpSignout?: boolean;
38+
}
39+
40+
/**
41+
* Metadata types that can be used for a SAML user pool identity provider.
42+
*/
43+
export enum UserPoolIdentityProviderSamlMetadataType {
44+
/** Metadata provided via a URL. */
45+
URL = 'url',
46+
47+
/** Metadata provided via the contents of a file. */
48+
FILE = 'file',
49+
}
50+
51+
/**
52+
* Metadata for a SAML user pool identity provider.
53+
*/
54+
export class UserPoolIdentityProviderSamlMetadata {
55+
56+
/**
57+
* Specify SAML metadata via a URL.
58+
*/
59+
public static url(url: string): UserPoolIdentityProviderSamlMetadata {
60+
return new UserPoolIdentityProviderSamlMetadata(url, UserPoolIdentityProviderSamlMetadataType.URL);
61+
}
62+
63+
/**
64+
* Specify SAML metadata via the contents of a file.
65+
*/
66+
public static file(fileContent: string): UserPoolIdentityProviderSamlMetadata {
67+
return new UserPoolIdentityProviderSamlMetadata(fileContent, UserPoolIdentityProviderSamlMetadataType.FILE);
68+
}
69+
70+
/**
71+
* Construct the metadata for a SAML identity provider.
72+
*
73+
* @param metadataContent A URL hosting SAML metadata, or the content of a file containing SAML metadata.
74+
* @param metadataType The type of metadata, either a URL or file content.
75+
*/
76+
private constructor(public readonly metadataContent: string, public readonly metadataType: UserPoolIdentityProviderSamlMetadataType) {
77+
}
78+
}
79+
80+
/**
81+
* Represents a identity provider that integrates with SAML.
82+
* @resource AWS::Cognito::UserPoolIdentityProvider
83+
*/
84+
export class UserPoolIdentityProviderSaml extends UserPoolIdentityProviderBase {
85+
public readonly providerName: string;
86+
87+
constructor(scope: Construct, id: string, props: UserPoolIdentityProviderSamlProps) {
88+
super(scope, id, props);
89+
90+
this.validateName(props.name);
91+
92+
const { metadataType, metadataContent } = props.metadata;
93+
94+
const resource = new CfnUserPoolIdentityProvider(this, 'Resource', {
95+
userPoolId: props.userPool.userPoolId,
96+
providerName: this.getProviderName(props.name),
97+
providerType: 'SAML',
98+
providerDetails: {
99+
IDPSignout: props.idpSignout ?? false,
100+
MetadataURL: metadataType === UserPoolIdentityProviderSamlMetadataType.URL ? metadataContent : undefined,
101+
MetadataFile: metadataType === UserPoolIdentityProviderSamlMetadataType.FILE ? metadataContent : undefined,
102+
},
103+
idpIdentifiers: props.identifiers,
104+
attributeMapping: super.configureAttributeMapping(),
105+
});
106+
107+
this.providerName = super.getResourceNameAttribute(resource.ref);
108+
}
109+
110+
private getProviderName(name?: string): string {
111+
if (name) {
112+
this.validateName(name);
113+
return name;
114+
}
115+
116+
const uniqueName = Names.uniqueResourceName(this, {
117+
maxLength: 32,
118+
});
119+
120+
if (uniqueName.length < 3) {
121+
return `${uniqueName}saml`;
122+
}
123+
124+
return uniqueName;
125+
}
126+
127+
private validateName(name?: string) {
128+
if (name && !Token.isUnresolved(name) && (name.length < 3 || name.length > 32)) {
129+
throw new Error(`Expected provider name to be between 3 and 32 characters, received ${name} (${name.length} characters)`);
130+
}
131+
}
132+
}

packages/@aws-cdk/aws-cognito/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"@aws-cdk/assertions": "0.0.0",
8484
"@aws-cdk/cdk-build-tools": "0.0.0",
8585
"@aws-cdk/integ-runner": "0.0.0",
86+
"@aws-cdk/integ-tests": "0.0.0",
8687
"@aws-cdk/cfn2ts": "0.0.0",
8788
"@aws-cdk/pkglint": "0.0.0",
8889
"@types/jest": "^27.5.2",
@@ -126,7 +127,8 @@
126127
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAmazonProps",
127128
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderGoogleProps",
128129
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAppleProps",
129-
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderOidcProps"
130+
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderOidcProps",
131+
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderSamlProps"
130132
]
131133
},
132134
"stability": "stable",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { App, CfnOutput, RemovalPolicy, Stack } from '@aws-cdk/core';
2+
import { IntegTest } from '@aws-cdk/integ-tests';
3+
import { Construct } from 'constructs';
4+
import { UserPool, UserPoolIdentityProviderSaml, UserPoolIdentityProviderSamlMetadata } from '../lib';
5+
6+
class TestStack extends Stack {
7+
constructor(scope: Construct, id: string) {
8+
super(scope, id);
9+
const userpool = new UserPool(this, 'pool', {
10+
removalPolicy: RemovalPolicy.DESTROY,
11+
});
12+
13+
new UserPoolIdentityProviderSaml(this, 'cdk', {
14+
userPool: userpool,
15+
name: 'cdk',
16+
metadata: UserPoolIdentityProviderSamlMetadata.url('https://fujifish.github.io/samling/public/metadata.xml'),
17+
});
18+
19+
const client = userpool.addClient('client');
20+
21+
const domain = userpool.addDomain('domain', {
22+
cognitoDomain: {
23+
domainPrefix: 'cdk-test-pool',
24+
},
25+
});
26+
27+
new CfnOutput(this, 'SignInLink', {
28+
value: domain.signInUrl(client, {
29+
redirectUri: 'https://example.com',
30+
}),
31+
});
32+
}
33+
}
34+
35+
const app = new App();
36+
const testCase = new TestStack(app, 'integ-user-pool-identity-provider-saml-stack');
37+
38+
new IntegTest(app, 'integ-user-pool-identity-provider-saml-test', {
39+
testCases: [testCase],
40+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version":"21.0.0"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"6f6f07786415216f13b738979cec5ad81dbab3283fae83b99324965935cc1d60": {
5+
"source": {
6+
"path": "integ-user-pool-identity-provider-saml-stack.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "6f6f07786415216f13b738979cec5ad81dbab3283fae83b99324965935cc1d60.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
{
2+
"Resources": {
3+
"pool056F3F7E": {
4+
"Type": "AWS::Cognito::UserPool",
5+
"Properties": {
6+
"AccountRecoverySetting": {
7+
"RecoveryMechanisms": [
8+
{
9+
"Name": "verified_phone_number",
10+
"Priority": 1
11+
},
12+
{
13+
"Name": "verified_email",
14+
"Priority": 2
15+
}
16+
]
17+
},
18+
"AdminCreateUserConfig": {
19+
"AllowAdminCreateUserOnly": true
20+
},
21+
"EmailVerificationMessage": "The verification code to your new account is {####}",
22+
"EmailVerificationSubject": "Verify your new account",
23+
"SmsVerificationMessage": "The verification code to your new account is {####}",
24+
"VerificationMessageTemplate": {
25+
"DefaultEmailOption": "CONFIRM_WITH_CODE",
26+
"EmailMessage": "The verification code to your new account is {####}",
27+
"EmailSubject": "Verify your new account",
28+
"SmsMessage": "The verification code to your new account is {####}"
29+
}
30+
},
31+
"UpdateReplacePolicy": "Delete",
32+
"DeletionPolicy": "Delete"
33+
},
34+
"poolclient2623294C": {
35+
"Type": "AWS::Cognito::UserPoolClient",
36+
"Properties": {
37+
"UserPoolId": {
38+
"Ref": "pool056F3F7E"
39+
},
40+
"AllowedOAuthFlows": [
41+
"implicit",
42+
"code"
43+
],
44+
"AllowedOAuthFlowsUserPoolClient": true,
45+
"AllowedOAuthScopes": [
46+
"profile",
47+
"phone",
48+
"email",
49+
"openid",
50+
"aws.cognito.signin.user.admin"
51+
],
52+
"CallbackURLs": [
53+
"https://example.com"
54+
],
55+
"SupportedIdentityProviders": [
56+
{
57+
"Ref": "cdk52888317"
58+
},
59+
"COGNITO"
60+
]
61+
}
62+
},
63+
"pooldomain430FA744": {
64+
"Type": "AWS::Cognito::UserPoolDomain",
65+
"Properties": {
66+
"Domain": "cdk-test-pool",
67+
"UserPoolId": {
68+
"Ref": "pool056F3F7E"
69+
}
70+
}
71+
},
72+
"cdk52888317": {
73+
"Type": "AWS::Cognito::UserPoolIdentityProvider",
74+
"Properties": {
75+
"ProviderName": "cdk",
76+
"ProviderType": "SAML",
77+
"UserPoolId": {
78+
"Ref": "pool056F3F7E"
79+
},
80+
"ProviderDetails": {
81+
"IDPSignout": false,
82+
"MetadataURL": "https://fujifish.github.io/samling/public/metadata.xml"
83+
}
84+
}
85+
}
86+
},
87+
"Outputs": {
88+
"SignInLink": {
89+
"Value": {
90+
"Fn::Join": [
91+
"",
92+
[
93+
"https://",
94+
{
95+
"Ref": "pooldomain430FA744"
96+
},
97+
".auth.",
98+
{
99+
"Ref": "AWS::Region"
100+
},
101+
".amazoncognito.com/login?client_id=",
102+
{
103+
"Ref": "poolclient2623294C"
104+
},
105+
"&response_type=code&redirect_uri=https://example.com"
106+
]
107+
]
108+
}
109+
}
110+
},
111+
"Parameters": {
112+
"BootstrapVersion": {
113+
"Type": "AWS::SSM::Parameter::Value<String>",
114+
"Default": "/cdk-bootstrap/hnb659fds/version",
115+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
116+
}
117+
},
118+
"Rules": {
119+
"CheckBootstrapVersion": {
120+
"Assertions": [
121+
{
122+
"Assert": {
123+
"Fn::Not": [
124+
{
125+
"Fn::Contains": [
126+
[
127+
"1",
128+
"2",
129+
"3",
130+
"4",
131+
"5"
132+
],
133+
{
134+
"Ref": "BootstrapVersion"
135+
}
136+
]
137+
}
138+
]
139+
},
140+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
141+
}
142+
]
143+
}
144+
}
145+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "21.0.0",
3+
"testCases": {
4+
"integ-user-pool-identity-provider-saml-test/DefaultTest": {
5+
"stacks": [
6+
"integ-user-pool-identity-provider-saml-stack"
7+
],
8+
"assertionStack": "integ-user-pool-identity-provider-saml-test/DefaultTest/DeployAssert",
9+
"assertionStackName": "integuserpoolidentityprovidersamltestDefaultTestDeployAssert97F09C26"
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)