diff --git a/packages/@aws-cdk/aws-cloudfront/README.md b/packages/@aws-cdk/aws-cloudfront/README.md index 1355d7a64d31d..46ecd1044dd2b 100644 --- a/packages/@aws-cdk/aws-cloudfront/README.md +++ b/packages/@aws-cdk/aws-cloudfront/README.md @@ -542,15 +542,25 @@ Note: Don't forget to copy/paste the contents of `public_key.pem` file including Example: ```ts - new cloudfront.KeyGroup(stack, 'MyKeyGroup', { - items: [ - new cloudfront.PublicKey(stack, 'MyPublicKey', { - encodedKey: '...', // contents of public_key.pem file - // comment: 'Key is expiring on ...', - }), - ], - // comment: 'Key group containing public keys ...', - }); +new cloudfront.KeyGroup(stack, 'MyKeyGroup', { + items: [ + new cloudfront.PublicKey(stack, 'InlinePublicKey', { + encodedKey: Key.fromInline('...'), // contents of public_key.pem file + // comment: 'Key is expiring on ...', + }), + ], + // comment: 'Key group containing public keys ...', +}); + +new cloudfront.KeyGroup(stack, 'MyKeyGroup', { + items: [ + new cloudfront.PublicKey(stack, 'FilePublicKey', { + encodedKey: Key.fromFile(path.join(__dirname, 'public_key.pem')), // path to public_key.pem file + // comment: 'Key is expiring on ...', + }), + ], + // comment: 'Key group containing public keys ...', +}); ``` See: diff --git a/packages/@aws-cdk/aws-cloudfront/lib/public-key.ts b/packages/@aws-cdk/aws-cloudfront/lib/public-key.ts index e2c2b6e044cdb..e20d00b14220d 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/public-key.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/public-key.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs'; import { IResource, Names, Resource, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnPublicKey } from './cloudfront.generated'; @@ -31,11 +32,12 @@ export interface PublicKeyProps { /** * The public key that you can use with signed URLs and signed cookies, or with field-level encryption. - * The `encodedKey` parameter must include `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` lines. + * The `encodedKey` parameter can be either an inline key or from filesystem. If it's inline it must include + * `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` lines. * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/field-level-encryption.html */ - readonly encodedKey: string; + readonly encodedKey: Key; } /** @@ -57,15 +59,13 @@ export class PublicKey extends Resource implements IPublicKey { constructor(scope: Construct, id: string, props: PublicKeyProps) { super(scope, id); - if (!Token.isUnresolved(props.encodedKey) && !/^-----BEGIN PUBLIC KEY-----/.test(props.encodedKey)) { - throw new Error(`Public key must be in PEM format (with the BEGIN/END PUBLIC KEY lines); got ${props.encodedKey}`); - } + const encodedKey = props.encodedKey.bind(this); const resource = new CfnPublicKey(this, 'Resource', { publicKeyConfig: { name: props.publicKeyName ?? this.generateName(), callerReference: this.node.addr, - encodedKey: props.encodedKey, + encodedKey: this.publicKeyValue(encodedKey), comment: props.comment, }, }); @@ -80,4 +80,110 @@ export class PublicKey extends Resource implements IPublicKey { } return name; } -} \ No newline at end of file + + private publicKeyValue(key: KeyConfig): string { + return key.value; + } +} + +/** + * Represents the Public Key handler. + */ +export abstract class Key { + /** + * Inline value for Public Key + * @returns contents of an inline public key. + * @param key Inline public key + */ + public static fromInline(key: string): InlineKey { + return new InlineKey(key); + } + + /** + * Loads the public key from a local disk path. + * @returns contents of a .pem key. + * @param path Path to a .pem file + */ + public static fromFile(path: string/*, options: {}*/): FileKey { + return new FileKey(path/*,options*/); + } + + /** + * Called when the public key is initialized to allow this object to bind + * to the stack, add resources and have fun. + * + * @param scope The binding scope. Don't be smart about trying to down-cast or + * assume it's initialized. You may just use it as a construct scope. + */ + public abstract bind(scope: Construct): KeyConfig; +} + +/** + * Result of binding `Key` into `PublicKey`. + */ +export interface KeyConfig { + /** + * Public Key value. + * @default - contents of a public key + */ + readonly value: string; +} + +/** + * Public Key from an inline string. + */ +export class InlineKey extends Key { + constructor(private key: string) { + super(); + + if (key.length === 0) { + throw new Error('Encoded key inline value cannot be empty'); + } + + if (key.length > 4096) { + throw new Error('Encoded key inline value is too large, must be <= 4096 but is ' + key.length); + } + + if (!Token.isUnresolved(key) && !/^-----BEGIN PUBLIC KEY-----/.test(key)) { + throw new Error(`Public key must be in PEM format (with the BEGIN/END PUBLIC KEY lines); got ${key}`); + } + } + + public bind(_scope: Construct): KeyConfig { + return { + value: this.key, + }; + } + + /** + * Content of a public key. + */ + public content(): string { + return this.key; + } +} + +/** + * Public key from a local directory. + */ +export class FileKey extends Key { + private readonly key: string; + /** + * @param path The path to the asset file or directory. + */ + constructor(public readonly path: string) { + super(); + + const encodedKey = fs.readFileSync(path).toString(); + if (!encodedKey) { + throw new Error('Something went wrong with loading the public key.'); + } + this.key = new InlineKey(encodedKey).content(); + } + + public bind(_scope: Construct): KeyConfig { + return { + value: this.key, + }; + } +} diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.expected.json b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.expected.json index 45191bad86cff..02fa2f8acc15c 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.expected.json +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.expected.json @@ -1,25 +1,48 @@ { "Resources": { - "AwesomePublicKeyED3E7F55": { + "AwesomePublicKeyInline1A6EDCE6": { "Type": "AWS::CloudFront::PublicKey", "Properties": { "PublicKeyConfig": { - "CallerReference": "c88e460888c5762c9c47ac0cdc669370d787fb2d9f", - "EncodedKey": "-----BEGIN PUBLIC KEY-----\n MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS\n JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa\n dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj\n 6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e\n 0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD\n /3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx\n NQIDAQAB\n -----END PUBLIC KEY-----\n ", - "Name": "awscdkcloudfrontcustomAwesomePublicKey0E83393B" + "CallerReference": "c84ece92b360f4192c0c049980669b0afe70b5f955", + "EncodedKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS\nJAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa\ndlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj\n6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e\n0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD\n/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx\nNQIDAQAB\n-----END PUBLIC KEY-----", + "Name": "awscdkcloudfrontcustomAwesomePublicKeyInlineB6223952" } } }, - "AwesomeKeyGroup3EF8348B": { + "AwesomeKeyGroupInline15125FEB": { "Type": "AWS::CloudFront::KeyGroup", "Properties": { "KeyGroupConfig": { "Items": [ { - "Ref": "AwesomePublicKeyED3E7F55" + "Ref": "AwesomePublicKeyInline1A6EDCE6" } ], - "Name": "awscdkcloudfrontcustomAwesomeKeyGroup73FD4DCA" + "Name": "awscdkcloudfrontcustomAwesomeKeyGroupInline80E48054" + } + } + }, + "AwesomePublicKeyFromFile047B5107": { + "Type": "AWS::CloudFront::PublicKey", + "Properties": { + "PublicKeyConfig": { + "CallerReference": "c827b081d326a5957b0a49ee91095b8f41987fe2d6", + "EncodedKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS\nJAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa\ndlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj\n6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e\n0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD\n/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx\nNQIDAQAB\n-----END PUBLIC KEY-----", + "Name": "awscdkcloudfrontcustomAwesomePublicKeyFromFile95419BD0" + } + } + }, + "AwesomeKeyGroupFromFileCF6B49D4": { + "Type": "AWS::CloudFront::KeyGroup", + "Properties": { + "KeyGroupConfig": { + "Items": [ + { + "Ref": "AwesomePublicKeyFromFile047B5107" + } + ], + "Name": "awscdkcloudfrontcustomAwesomeKeyGroupFromFileC5F179C4" } } } diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.ts b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.ts index 7bfdbbe645446..5ffebdb7c47ca 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-key-group.ts @@ -1,3 +1,4 @@ +import * as path from 'path'; import * as cdk from '@aws-cdk/core'; import * as cloudfront from '../lib'; @@ -5,19 +6,28 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-custom'); -new cloudfront.KeyGroup(stack, 'AwesomeKeyGroup', { +const publicKey = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS +JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa +dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj +6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e +0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD +/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx +NQIDAQAB +-----END PUBLIC KEY-----`; + +new cloudfront.KeyGroup(stack, 'AwesomeKeyGroupInline', { + items: [ + new cloudfront.PublicKey(stack, 'AwesomePublicKeyInline', { + encodedKey: cloudfront.Key.fromInline(publicKey), + }), + ], +}); + +new cloudfront.KeyGroup(stack, 'AwesomeKeyGroupFromFile', { items: [ - new cloudfront.PublicKey(stack, 'AwesomePublicKey', { - encodedKey: `-----BEGIN PUBLIC KEY----- - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS - JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa - dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj - 6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e - 0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD - /3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx - NQIDAQAB - -----END PUBLIC KEY----- - `, + new cloudfront.PublicKey(stack, 'AwesomePublicKeyFromFile', { + encodedKey: cloudfront.Key.fromFile(path.join(__dirname, './pem/pubkey-good.test.pem')), }), ], }); diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.expected.json b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.expected.json new file mode 100644 index 0000000000000..42ef751c1663f --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.expected.json @@ -0,0 +1,24 @@ +{ + "Resources": { + "AwesomePublicKeyInline1A6EDCE6": { + "Type": "AWS::CloudFront::PublicKey", + "Properties": { + "PublicKeyConfig": { + "CallerReference": "c84ece92b360f4192c0c049980669b0afe70b5f955", + "EncodedKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS\nJAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa\ndlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj\n6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e\n0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD\n/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx\nNQIDAQAB\n-----END PUBLIC KEY-----", + "Name": "awscdkcloudfrontcustomAwesomePublicKeyInlineB6223952" + } + } + }, + "AwesomePublicKeyFromFile047B5107": { + "Type": "AWS::CloudFront::PublicKey", + "Properties": { + "PublicKeyConfig": { + "CallerReference": "c827b081d326a5957b0a49ee91095b8f41987fe2d6", + "EncodedKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS\nJAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa\ndlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj\n6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e\n0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD\n/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx\nNQIDAQAB\n-----END PUBLIC KEY-----", + "Name": "awscdkcloudfrontcustomAwesomePublicKeyFromFile95419BD0" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.ts b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.ts new file mode 100644 index 0000000000000..c05b45e42c341 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-public-key.ts @@ -0,0 +1,27 @@ +import * as path from 'path'; +import * as cdk from '@aws-cdk/core'; +import * as cloudfront from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-custom'); + +const publicKey = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS +JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa +dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj +6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e +0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD +/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx +NQIDAQAB +-----END PUBLIC KEY-----`; + +new cloudfront.PublicKey(stack, 'AwesomePublicKeyInline', { + encodedKey: cloudfront.Key.fromInline(publicKey), +}); + +new cloudfront.PublicKey(stack, 'AwesomePublicKeyFromFile', { + encodedKey: cloudfront.Key.fromFile(path.join(__dirname, './pem/pubkey-good.test.pem')), +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-cloudfront/test/key-group.test.ts b/packages/@aws-cdk/aws-cloudfront/test/key-group.test.ts index f5a0ae43c0855..d4477f04cf048 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/key-group.test.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/key-group.test.ts @@ -1,7 +1,7 @@ import '@aws-cdk/assert/jest'; import { expect as expectStack } from '@aws-cdk/assert'; import { App, Stack } from '@aws-cdk/core'; -import { KeyGroup, PublicKey } from '../lib'; +import { Key, KeyGroup, PublicKey } from '../lib'; const publicKey1 = `-----BEGIN PUBLIC KEY----- FIRST_KEYgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS @@ -44,7 +44,7 @@ describe('KeyGroup', () => { new KeyGroup(stack, 'MyKeyGroup', { items: [ new PublicKey(stack, 'MyPublicKey', { - encodedKey: publicKey1, + encodedKey: Key.fromInline(publicKey1), }), ], }); @@ -85,7 +85,7 @@ describe('KeyGroup', () => { items: [ new PublicKey(stack, 'MyPublicKey', { publicKeyName: 'pub-key', - encodedKey: publicKey1, + encodedKey: Key.fromInline(publicKey1), comment: 'Key expiring on 1/1/1984', }), ], @@ -129,12 +129,12 @@ describe('KeyGroup', () => { items: [ new PublicKey(stack, 'BingoKey', { publicKeyName: 'Bingo-Key', - encodedKey: publicKey1, + encodedKey: Key.fromInline(publicKey1), comment: 'Key expiring on 1/1/1984', }), new PublicKey(stack, 'RollyKey', { publicKeyName: 'Rolly-Key', - encodedKey: publicKey2, + encodedKey: Key.fromInline(publicKey2), comment: 'Key expiring on 1/1/1984', }), ], diff --git a/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-bad.test.pem b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-bad.test.pem new file mode 100644 index 0000000000000..4406053f40996 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-bad.test.pem @@ -0,0 +1,7 @@ +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS +JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa +dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj +6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e +0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD +/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx +NQIDAQAB \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-good.test.pem b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-good.test.pem new file mode 100644 index 0000000000000..a4c2b0f7cf73b --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-good.test.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS +JAyxd/kGTbJfQNg9YhInb7TSm0dGu0yx8yZ3fnpmxuRPqJIlaVr+fT4YRl71gEYa +dlhHmnVegyPNjP9dNqZ7zwNqMEPOPnS/NOHbJj1KYKpn1f8pPNycQ5MQCntKGnSj +6fc+nbcC0joDvGz80xuy1W4hLV9oC9c3GT26xfZb2jy9MVtA3cppNuTwqrFi3t6e +0iGpraxZlT5wewjZLpQkngqYr6s3aucPAZVsGTEYPo4nD5mswmtZOm+tgcOrivtD +/3sD/qZLQ6c5siqyS8aTraD6y+VXugujfarTU65IeZ6QAUbLMsWuZOIi5Jn8zAwx +NQIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-large.test.pem b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-large.test.pem new file mode 100644 index 0000000000000..fae3bc036fab5 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/pem/pubkey-large.test.pem @@ -0,0 +1,111 @@ +-----BEGIN PUBLIC KEY----- +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 +NQIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/test/public-key.test.ts b/packages/@aws-cdk/aws-cloudfront/test/public-key.test.ts index 934b1a9dc8107..b58aec243b4fa 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/public-key.test.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/public-key.test.ts @@ -1,7 +1,8 @@ +import * as path from 'path'; import '@aws-cdk/assert/jest'; import { expect as expectStack } from '@aws-cdk/assert'; import { App, Stack } from '@aws-cdk/core'; -import { PublicKey } from '../lib'; +import { Key, PublicKey } from '../lib'; const publicKey = `-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudf8/iNkQgdvjEdm6xYS @@ -30,9 +31,21 @@ describe('PublicKey', () => { expect(pubKey.publicKeyId).toEqual(publicKeyId); }); + test('inline key', () => { + new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromInline(publicKey), + }); + }); + + test('key from filesystem', () => { + new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromFile(path.join(__dirname, 'pem/pubkey-good.test.pem')), + }); + }); + test('minimal example', () => { new PublicKey(stack, 'MyPublicKey', { - encodedKey: publicKey, + encodedKey: Key.fromInline(publicKey), }); expectStack(stack).toMatch({ @@ -54,7 +67,7 @@ describe('PublicKey', () => { test('maximum example', () => { new PublicKey(stack, 'MyPublicKey', { publicKeyName: 'pub-key', - encodedKey: publicKey, + encodedKey: Key.fromInline(publicKey), comment: 'Key expiring on 1/1/1984', }); @@ -78,8 +91,47 @@ describe('PublicKey', () => { test('bad key example', () => { expect(() => new PublicKey(stack, 'MyPublicKey', { publicKeyName: 'pub-key', - encodedKey: 'bad-key', + encodedKey: Key.fromInline('bad-key'), comment: 'Key expiring on 1/1/1984', })).toThrow(/Public key must be in PEM format [(]with the BEGIN\/END PUBLIC KEY lines[)]; got (.*?)/); }); + + test('good public key example', () => { + new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromFile(path.join(__dirname, 'pem/pubkey-good.test.pem')), + }); + + expectStack(stack).toMatch({ + Resources: { + MyPublicKey78071F3D: { + Type: 'AWS::CloudFront::PublicKey', + Properties: { + PublicKeyConfig: { + CallerReference: 'c872d91ae0d2943aad25d4b31f1304d0a62c658ace', + EncodedKey: publicKey, + Name: 'StackMyPublicKey36EDA6AB', + }, + }, + }, + }, + }); + }); + + test('bad public key example', () => { + expect(() => new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromFile(path.join(__dirname, 'pem/pubkey-bad.test.pem')), + })).toThrow(/Public key must be in PEM format [(]with the BEGIN\/END PUBLIC KEY lines[)]; got (.*?)/); + }); + + test('empty key example', () => { + expect(() => new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromInline(''), + })).toThrow(/Encoded key inline value cannot be empty/); + }); + + test('large key example', () => { + expect(() => new PublicKey(stack, 'MyPublicKey', { + encodedKey: Key.fromFile(path.join(__dirname, 'pem/pubkey-large.test.pem')), + })).toThrow(/Encoded key inline value is too large, must be <= 4096 but is (.*?)/); + }); }); \ No newline at end of file