Skip to content

Commit

Permalink
Merge branch 'master' into nija-at/fix-eslint-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Feb 3, 2021
2 parents 5565d65 + 8d3aaba commit 7244104
Show file tree
Hide file tree
Showing 20 changed files with 712 additions and 101 deletions.
1 change: 0 additions & 1 deletion packages/@aws-cdk/assets/lib/fs/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export interface CopyOptions {
* A strategy for how to handle symlinks.
*
* @default Never
* @deprecated use `followSymlinks` instead
*/
readonly follow?: FollowMode;

Expand Down
44 changes: 44 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,51 @@ export abstract class ResourceBase extends ResourceConstruct implements IResourc
}
}

/**
* Attributes that can be specified when importing a Resource
*/
export interface ResourceAttributes {
/**
* The ID of the resource.
*/
readonly resourceId: string;

/**
* The rest API that this resource is part of.
*/
readonly restApi: IRestApi;

/**
* The full path of this resource.
*/
readonly path: string;
}

export class Resource extends ResourceBase {
/**
* Import an existing resource
*/
public static fromResourceAttributes(scope: Construct, id: string, attrs: ResourceAttributes): IResource {
class Import extends ResourceBase {
public readonly api = attrs.restApi;
public readonly resourceId = attrs.resourceId;
public readonly path = attrs.path;
public readonly defaultIntegration?: Integration = undefined;
public readonly defaultMethodOptions?: MethodOptions = undefined;
public readonly defaultCorsPreflightOptions?: CorsOptions = undefined;

public get parentResource(): IResource {
throw new Error('parentResource is not configured for imported resource.');
}

public get restApi(): RestApi {
throw new Error('restApi is not configured for imported resource.');
}
}

return new Import(scope, id);
}

public readonly parentResource?: IResource;
public readonly api: IRestApi;
public readonly resourceId: string;
Expand Down
21 changes: 21 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/resource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,27 @@ describe('resource', () => {

});

test('fromResourceAttributes()', () => {
// GIVEN
const stack = new Stack();
const resourceId = 'resource-id';
const api = new apigw.RestApi(stack, 'MyRestApi');

// WHEN
const imported = apigw.Resource.fromResourceAttributes(stack, 'imported-resource', {
resourceId,
restApi: api,
path: 'some-path',
});
imported.addMethod('GET');

// THEN
expect(stack).toHaveResource('AWS::ApiGateway::Method', {
HttpMethod: 'GET',
ResourceId: resourceId,
});
});

describe('getResource', () => {

describe('root resource', () => {
Expand Down
37 changes: 37 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -520,3 +520,40 @@ new CloudFrontWebDistribution(stack, 'ADistribution', {
],
});
```

## KeyGroup & PublicKey API

Now you can create a key group to use with CloudFront signed URLs and signed cookies. You can add public keys to use with CloudFront features such as signed URLs, signed cookies, and field-level encryption.

The following example command uses OpenSSL to generate an RSA key pair with a length of 2048 bits and save to the file named `private_key.pem`.

```bash
openssl genrsa -out private_key.pem 2048
```

The resulting file contains both the public and the private key. The following example command extracts the public key from the file named `private_key.pem` and stores it in `public_key.pem`.

```bash
openssl rsa -pubout -in private_key.pem -out public_key.pem
```

Note: Don't forget to copy/paste the contents of `public_key.pem` file including `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` lines into `encodedKey` parameter when creating a `PublicKey`.

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 ...',
});
```

See:

* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html
* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export * from './cache-policy';
export * from './distribution';
export * from './geo-restriction';
export * from './key-group';
export * from './origin';
export * from './origin-access-identity';
export * from './origin-request-policy';
export * from './public-key';
export * from './web-distribution';

export * as experimental from './experimental';
Expand Down
75 changes: 75 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/key-group.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { IResource, Names, Resource } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnKeyGroup } from './cloudfront.generated';
import { IPublicKey } from './public-key';

/**
* Represents a Key Group
*/
export interface IKeyGroup extends IResource {
/**
* The ID of the key group.
* @attribute
*/
readonly keyGroupId: string;
}

/**
* Properties for creating a Public Key
*/
export interface KeyGroupProps {
/**
* A name to identify the key group.
* @default - generated from the `id`
*/
readonly keyGroupName?: string;

/**
* A comment to describe the key group.
* @default - no comment
*/
readonly comment?: string;

/**
* A list of public keys to add to the key group.
*/
readonly items: IPublicKey[];
}

/**
* A Key Group configuration
*
* @resource AWS::CloudFront::KeyGroup
*/
export class KeyGroup extends Resource implements IKeyGroup {

/** Imports a Key Group from its id. */
public static fromKeyGroupId(scope: Construct, id: string, keyGroupId: string): IKeyGroup {
return new class extends Resource implements IKeyGroup {
public readonly keyGroupId = keyGroupId;
}(scope, id);
}
public readonly keyGroupId: string;

constructor(scope: Construct, id: string, props: KeyGroupProps) {
super(scope, id);

const resource = new CfnKeyGroup(this, 'Resource', {
keyGroupConfig: {
name: props.keyGroupName ?? this.generateName(),
comment: props.comment,
items: props.items.map(key => key.publicKeyId),
},
});

this.keyGroupId = resource.ref;
}

private generateName(): string {
const name = Names.uniqueId(this);
if (name.length > 80) {
return name.substring(0, 40) + name.substring(name.length - 40);
}
return name;
}
}
83 changes: 83 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/public-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { IResource, Names, Resource, Token } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnPublicKey } from './cloudfront.generated';

/**
* Represents a Public Key
*/
export interface IPublicKey extends IResource {
/**
* The ID of the key group.
* @attribute
*/
readonly publicKeyId: string;
}

/**
* Properties for creating a Public Key
*/
export interface PublicKeyProps {
/**
* A name to identify the public key.
* @default - generated from the `id`
*/
readonly publicKeyName?: string;

/**
* A comment to describe the public key.
* @default - no comment
*/
readonly comment?: string;

/**
* 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.
* @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;
}

/**
* A Public Key Configuration
*
* @resource AWS::CloudFront::PublicKey
*/
export class PublicKey extends Resource implements IPublicKey {

/** Imports a Public Key from its id. */
public static fromPublicKeyId(scope: Construct, id: string, publicKeyId: string): IPublicKey {
return new class extends Resource implements IPublicKey {
public readonly publicKeyId = publicKeyId;
}(scope, id);
}

public readonly publicKeyId: string;

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 resource = new CfnPublicKey(this, 'Resource', {
publicKeyConfig: {
name: props.publicKeyName ?? this.generateName(),
callerReference: this.node.addr,
encodedKey: props.encodedKey,
comment: props.comment,
},
});

this.publicKeyId = resource.ref;
}

private generateName(): string {
const name = Names.uniqueId(this);
if (name.length > 80) {
return name.substring(0, 40) + name.substring(name.length - 40);
}
return name;
}
}
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-cloudfront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@
"resource-attribute:@aws-cdk/aws-cloudfront.CachePolicy.cachePolicyLastModifiedTime",
"construct-interface-extends-iconstruct:@aws-cdk/aws-cloudfront.IOriginRequestPolicy",
"resource-interface-extends-resource:@aws-cdk/aws-cloudfront.IOriginRequestPolicy",
"resource-attribute:@aws-cdk/aws-cloudfront.OriginRequestPolicy.originRequestPolicyLastModifiedTime"
"resource-attribute:@aws-cdk/aws-cloudfront.OriginRequestPolicy.originRequestPolicyLastModifiedTime",
"resource-attribute:@aws-cdk/aws-cloudfront.KeyGroup.keyGroupLastModifiedTime",
"resource-attribute:@aws-cdk/aws-cloudfront.PublicKey.publicKeyCreatedTime"
]
},
"awscdkio": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"Resources": {
"AwesomePublicKeyED3E7F55": {
"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"
}
}
},
"AwesomeKeyGroup3EF8348B": {
"Type": "AWS::CloudFront::KeyGroup",
"Properties": {
"KeyGroupConfig": {
"Items": [
{
"Ref": "AwesomePublicKeyED3E7F55"
}
],
"Name": "awscdkcloudfrontcustomAwesomeKeyGroup73FD4DCA"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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');

new cloudfront.KeyGroup(stack, 'AwesomeKeyGroup', {
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-----
`,
}),
],
});

app.synth();
Loading

0 comments on commit 7244104

Please sign in to comment.