Skip to content

Commit 7ee183d

Browse files
authored
fix(cognito): deprecate privateKey and add privateKeyValue as typed SecureValue (#31409)
### Issue # (if applicable) Closes #31378 ### Reason for this change 1. `privateKey` was typed `string` which should be `SecureValue` just as [clientSecretValue](https://github.com/aws/aws-cdk/blob/1e203753519e10e19ef0db87e1382377b609bcaa/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts#L28) in Google IdP. This PR deprecates `privateKey` and adds `privateKeyValue` with correct type. 2. `apple.ts` was named by mistake and it won't be unit tested. This PR renames it to `apple.test.ts` so it would be covered. Figured an existing test was failed, just fixed that failed one as well. ### Description of changes - Add `privateKeyValue` property of type SecretValue to UserPoolIdentityProviderAppleProps - Deprecate the existing `privateKey` string property - Implement logic to ensure exactly one of `privateKey` or `privateKeyValue` is provided - Update UserPoolIdentityProviderApple to use the new `privateKeyValue` when available - Rename apple.ts test file to apple.test.ts for consistency - Add new test case to verify mutually exclusive properties Users must now provide either `privateKey` or `privateKeyValue`, but not both. This change enhances security by allowing the use of SecretValue for the Apple IDP private key. ### Description of how you validated changes ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent ff02cca commit 7ee183d

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

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

+17-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Construct } from 'constructs';
22
import { UserPoolIdentityProviderProps } from './base';
33
import { CfnUserPoolIdentityProvider } from '../cognito.generated';
44
import { UserPoolIdentityProviderBase } from './private/user-pool-idp-base';
5+
import { SecretValue } from '../../../core';
56

67
/**
78
* Properties to initialize UserPoolAppleIdentityProvider
@@ -22,8 +23,16 @@ export interface UserPoolIdentityProviderAppleProps extends UserPoolIdentityProv
2223
readonly keyId: string;
2324
/**
2425
* The privateKey content for Apple APIs to authenticate the client.
26+
*
27+
* @deprecated use privateKeyValue
28+
* @default none
2529
*/
26-
readonly privateKey: string;
30+
readonly privateKey?: string;
31+
/**
32+
* The privateKey content for Apple APIs to authenticate the client.
33+
* @default none
34+
*/
35+
readonly privateKeyValue?: SecretValue;
2736
/**
2837
* The list of apple permissions to obtain for getting access to the apple profile
2938
* @see https://developer.apple.com/documentation/sign_in_with_apple/clientconfigi/3230955-scope
@@ -44,6 +53,12 @@ export class UserPoolIdentityProviderApple extends UserPoolIdentityProviderBase
4453

4554
const scopes = props.scopes ?? ['name'];
4655

56+
// Exactly one of the properties must be configured
57+
if ((!props.privateKey && !props.privateKeyValue) ||
58+
(props.privateKey && props.privateKeyValue)) {
59+
throw new Error('Exactly one of "privateKey" or "privateKeyValue" must be configured.');
60+
}
61+
4762
const resource = new CfnUserPoolIdentityProvider(this, 'Resource', {
4863
userPoolId: props.userPool.userPoolId,
4964
providerName: 'SignInWithApple', // must be 'SignInWithApple' when the type is 'SignInWithApple'
@@ -52,7 +67,7 @@ export class UserPoolIdentityProviderApple extends UserPoolIdentityProviderBase
5267
client_id: props.clientId,
5368
team_id: props.teamId,
5469
key_id: props.keyId,
55-
private_key: props.privateKey,
70+
private_key: props.privateKeyValue ? props.privateKeyValue.unsafeUnwrap() : props.privateKey,
5671
authorize_scopes: scopes.join(' '),
5772
},
5873
attributeMapping: super.configureAttributeMapping(),

packages/aws-cdk-lib/aws-cognito/test/user-pool-idps/apple.ts renamed to packages/aws-cdk-lib/aws-cognito/test/user-pool-idps/apple.test.ts

+42-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Template } from '../../../assertions';
2-
import { Stack } from '../../../core';
2+
import { Stack, SecretValue } from '../../../core';
33
import { ProviderAttribute, UserPool, UserPoolIdentityProviderApple } from '../../lib';
44

55
describe('UserPoolIdentityProvider', () => {
@@ -102,12 +102,51 @@ describe('UserPoolIdentityProvider', () => {
102102
// THEN
103103
Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', {
104104
AttributeMapping: {
105-
family_name: 'firstName',
106-
given_name: 'lastName',
105+
family_name: 'lastName',
106+
given_name: 'firstName',
107107
customAttr1: 'email',
108108
customAttr2: 'sub',
109109
},
110110
});
111111
});
112+
113+
// cannot assign both privateKey and privateKeyValue
114+
test('cannot assign both privateKey and privateKeyValue', () => {
115+
// GIVEN
116+
const stack = new Stack();
117+
const pool = new UserPool(stack, 'userpool');
118+
119+
expect(() => {
120+
new UserPoolIdentityProviderApple(stack, 'userpoolidp', {
121+
userPool: pool,
122+
clientId: 'com.amzn.cdk',
123+
teamId: 'CDKTEAMCDK',
124+
keyId: 'XXXXXXXXXX',
125+
privateKey: 'PRIV_KEY_CDK',
126+
privateKeyValue: SecretValue.secretsManager('dummyId'),
127+
});
128+
}).toThrow('Exactly one of "privateKey" or "privateKeyValue" must be configured.');
129+
});
130+
131+
// should support privateKeyValue
132+
test('should support privateKeyValue', () => {
133+
// GIVEN
134+
const stack = new Stack();
135+
const pool = new UserPool(stack, 'userpool');
136+
137+
new UserPoolIdentityProviderApple(stack, 'userpoolidp', {
138+
userPool: pool,
139+
clientId: 'com.amzn.cdk',
140+
teamId: 'CDKTEAMCDK',
141+
keyId: 'XXXXXXXXXX',
142+
privateKeyValue: SecretValue.secretsManager('dummyId'),
143+
});
144+
145+
Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolIdentityProvider', {
146+
ProviderDetails: {
147+
private_key: '{{resolve:secretsmanager:dummyId:SecretString:::}}',
148+
},
149+
});
150+
});
112151
});
113152
});

0 commit comments

Comments
 (0)