Skip to content

Commit

Permalink
Merge branch 'master' into njlynch/hierarchical-ls-long
Browse files Browse the repository at this point in the history
  • Loading branch information
iliapolo authored Nov 2, 2021
2 parents 42b8e71 + 1ab9b26 commit 918e617
Show file tree
Hide file tree
Showing 25 changed files with 540 additions and 60 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/auto-approve.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ on:

jobs:
auto-approve:
if: >
github.event.pull_request.user.login == 'dependabot[bot]'
|| github.event.pull_request.user.login == 'dependabot-preview[bot]'
|| (contains(github.event.pull_request.labels.*.name, 'pr/auto-approve')
&& github.event.pull_request.user.login == 'aws-cdk-automation')
if: contains(github.event.pull_request.labels.*.name, 'pr/auto-approve')
runs-on: ubuntu-latest
permissions:
pull-requests: write
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Apply various labels on PRs

name: pr-labeler
on:
pull_request:
types: [ opened ]

jobs:
auto-approve:
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'dependabot-preview[bot]'
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- run: gh pr edit ${{ github.event.pull_request.number }} --add-label "pr/auto-approve" -R ${{ github.repository }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
15 changes: 15 additions & 0 deletions packages/@aws-cdk/aws-certificatemanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ new acm.DnsValidatedCertificate(this, 'CrossRegionCertificate', {
});
```

## Requesting private certificates

AWS Certificate Manager can create [private certificates](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-private.html) issued by [Private Certificate Authority (PCA)](https://docs.aws.amazon.com/acm-pca/latest/userguide/PcaWelcome.html). Validation of private certificates is not necessary.

```ts
import * as acmpca from '@aws-cdk/aws-acmpca';

new acm.PrivateCertificate(stack, 'PrivateCertificate', {
domainName: 'test.example.com',
subjectAlternativeNames: ['cool.example.com', 'test.example.net'], // optional
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
});
```

## Importing

If you want to import an existing certificate, you can do so from its ARN:
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-certificatemanager/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './certificate';
export * from './dns-validated-certificate';
export * from './private-certificate';
export * from './util';

// AWS::CertificateManager CloudFormation Resources:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as acmpca from '@aws-cdk/aws-acmpca';
import { Construct } from 'constructs';
import { ICertificate } from './certificate';
import { CertificateBase } from './certificate-base';
import { CfnCertificate } from './certificatemanager.generated';

/**
* Properties for your private certificate
*/
export interface PrivateCertificateProps {
/**
* Fully-qualified domain name to request a private certificate for.
*
* May contain wildcards, such as ``*.domain.com``.
*/
readonly domainName: string;

/**
* Alternative domain names on your private certificate.
*
* Use this to register alternative domain names that represent the same site.
*
* @default - No additional FQDNs will be included as alternative domain names.
*/
readonly subjectAlternativeNames?: string[];

/**
* Private certificate authority (CA) that will be used to issue the certificate.
*/
readonly certificateAuthority: acmpca.ICertificateAuthority;
}

/**
* A private certificate managed by AWS Certificate Manager
*
* @resource AWS::CertificateManager::Certificate
*/
export class PrivateCertificate extends CertificateBase implements ICertificate {
/**
* Import a certificate
*/
public static fromCertificateArn(scope: Construct, id: string, certificateArn: string): ICertificate {
class Import extends CertificateBase {
public readonly certificateArn = certificateArn;
}

return new Import(scope, id);
}

/**
* The certificate's ARN
*/
public readonly certificateArn: string;

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

const cert = new CfnCertificate(this, 'Resource', {
domainName: props.domainName,
subjectAlternativeNames: props.subjectAlternativeNames,
certificateAuthorityArn: props.certificateAuthority.certificateAuthorityArn,
});

this.certificateArn = cert.ref;
}
}
5 changes: 4 additions & 1 deletion packages/@aws-cdk/aws-certificatemanager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"@types/jest": "^26.0.24"
},
"dependencies": {
"@aws-cdk/aws-acmpca": "0.0.0",
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
Expand All @@ -88,6 +89,7 @@
},
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-acmpca": "0.0.0",
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
Expand All @@ -101,7 +103,8 @@
"awslint": {
"exclude": [
"props-physical-name:@aws-cdk/aws-certificatemanager.CertificateProps",
"props-physical-name:@aws-cdk/aws-certificatemanager.DnsValidatedCertificateProps"
"props-physical-name:@aws-cdk/aws-certificatemanager.DnsValidatedCertificateProps",
"props-physical-name:@aws-cdk/aws-certificatemanager.PrivateCertificateProps"
]
},
"stability": "stable",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import '@aws-cdk/assert-internal/jest';
import * as acmpca from '@aws-cdk/aws-acmpca';
import { Duration, Lazy, Stack } from '@aws-cdk/core';
import { PrivateCertificate } from '../lib';

test('private certificate authority', () => {
const stack = new Stack();

new PrivateCertificate(stack, 'Certificate', {
domainName: 'test.example.com',
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
});

expect(stack).toHaveResource('AWS::CertificateManager::Certificate', {
DomainName: 'test.example.com',
CertificateAuthorityArn: 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77',
});
});

test('private certificate authority with subjectAlternativeNames', () => {
const stack = new Stack();

new PrivateCertificate(stack, 'Certificate', {
domainName: 'test.example.com',
subjectAlternativeNames: ['extra.example.com'],
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
});

expect(stack).toHaveResource('AWS::CertificateManager::Certificate', {
DomainName: 'test.example.com',
SubjectAlternativeNames: ['extra.example.com'],
CertificateAuthorityArn: 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77',
});
});

test('private certificate authority with multiple subjectAlternativeNames', () => {
const stack = new Stack();

new PrivateCertificate(stack, 'Certificate', {
domainName: 'test.example.com',
subjectAlternativeNames: ['*.test.example.com', '*.foo.test.example.com', 'bar.test.example.com'],
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
});

expect(stack).toHaveResource('AWS::CertificateManager::Certificate', {
DomainName: 'test.example.com',
SubjectAlternativeNames: ['*.test.example.com', '*.foo.test.example.com', 'bar.test.example.com'],
CertificateAuthorityArn: 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77',
});
});

test('private certificate authority with tokens', () => {
const stack = new Stack();

const certificateAuthority = Lazy.string({
produce: () => 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77',
});

const domainName = Lazy.string({
produce: () => 'test.example.com',
});

const domainNameAlternative = Lazy.string({
produce: () => 'extra.example.com',
});

new PrivateCertificate(stack, 'Certificate', {
domainName,
subjectAlternativeNames: [domainNameAlternative],
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA', certificateAuthority),
});

expect(stack).toHaveResource('AWS::CertificateManager::Certificate', {
DomainName: 'test.example.com',
SubjectAlternativeNames: ['extra.example.com'],
CertificateAuthorityArn: 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77',
});
});

test('metricDaysToExpiry', () => {
const stack = new Stack();

const certificate = new PrivateCertificate(stack, 'Certificate', {
domainName: 'test.example.com',
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
});

expect(stack.resolve(certificate.metricDaysToExpiry().toMetricConfig())).toEqual({
metricStat: {
dimensions: [{ name: 'CertificateArn', value: stack.resolve(certificate.certificateArn) }],
metricName: 'DaysToExpiry',
namespace: 'AWS/CertificateManager',
period: Duration.days(1),
statistic: 'Minimum',
},
renderingProperties: expect.anything(),
});
});
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-docdb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ your instances will be launched privately or publicly:
const cluster = new DatabaseCluster(this, 'Database', {
masterUser: {
username: 'myuser' // NOTE: 'admin' is reserved by DocumentDB
excludeCharacters: '\"@/:', // optional, defaults to the set "\"@/"
},
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE),
vpcSubnets: {
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-docdb/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ export class DatabaseCluster extends DatabaseClusterBase {
secret = new DatabaseSecret(this, 'Secret', {
username: props.masterUser.username,
encryptionKey: props.masterUser.kmsKey,
excludeCharacters: props.masterUser.excludeCharacters,
});
}

Expand Down
9 changes: 8 additions & 1 deletion packages/@aws-cdk/aws-docdb/lib/database-secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export interface DatabaseSecretProps {
* @default - no master secret information will be included
*/
readonly masterSecret?: ISecret;

/**
* Characters to not include in the generated password.
*
* @default "\"@/"
*/
readonly excludeCharacters?: string;
}

/**
Expand Down Expand Up @@ -61,7 +68,7 @@ export class DatabaseSecret extends Secret {
masterarn: props.masterSecret?.secretArn,
}),
generateStringKey: 'password',
excludeCharacters: '"@/',
excludeCharacters: props.excludeCharacters ?? '"@/',
},
});
}
Expand Down
7 changes: 7 additions & 0 deletions packages/@aws-cdk/aws-docdb/lib/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ export interface Login {
* @default default master key
*/
readonly kmsKey?: kms.IKey;

/**
* Specifies characters to not include in generated passwords.
*
* @default "\"@/"
*/
readonly excludeCharacters?: string;
}

/**
Expand Down
25 changes: 24 additions & 1 deletion packages/@aws-cdk/aws-docdb/test/cluster.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect as expectCDK, haveResource, ResourcePart, arrayWith } from '@aws-cdk/assert-internal';
import { expect as expectCDK, haveResource, ResourcePart, arrayWith, haveResourceLike, objectLike } from '@aws-cdk/assert-internal';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as kms from '@aws-cdk/aws-kms';
import * as cdk from '@aws-cdk/core';
Expand Down Expand Up @@ -293,6 +293,29 @@ describe('DatabaseCluster', () => {
}));
});

test('creates a secret with excludeCharacters', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');

// WHEN
new DatabaseCluster(stack, 'Database', {
masterUser: {
username: 'admin',
excludeCharacters: '"@/()[]',
},
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL),
vpc,
});

// THEN
expectCDK(stack).to(haveResourceLike('AWS::SecretsManager::Secret', {
GenerateSecretString: objectLike({
ExcludeCharacters: '\"@/()[]',
}),
}));
});

test('create an encrypted cluster with custom KMS key', () => {
// GIVEN
const stack = testStack();
Expand Down
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/instance-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ export enum InstanceClass {
*/
C5 = 'c5',

/**
* Compute optimized instances, 6th generation
*/
COMPUTE6_INTEL = 'c6i',

/**
* Compute optimized instances, 6th generation
*/
C6I = 'c6i',

/**
* Compute optimized instances with local NVME drive, 5th generation
*/
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-iot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const func = new lambda.Function(this, 'MyFunction', {
});

new iot.TopicRule(this, 'TopicRule', {
topicRuleName: 'MyTopicRule', // optional
description: 'invokes the lambda finction', // optional
sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp FROM 'device/+/data'"),
actions: [new actions.LambdaFunctionAction(func)],
});
Expand All @@ -72,3 +74,12 @@ const topicRule = new iot.TopicRule(this, 'TopicRule', {
});
topicRule.addAction(new actions.LambdaFunctionAction(func))
```

If you wanna make the topic rule disable, add property `enabled: false` as following:

```ts
new iot.TopicRule(this, 'TopicRule', {
sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp FROM 'device/+/data'"),
enabled: false,
});
```
Loading

0 comments on commit 918e617

Please sign in to comment.