Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(certificatemanager): key algorithm support for PrivateCertificate and Certificate #28597

Merged
merged 14 commits into from
Jan 9, 2024
Merged
1 change: 1 addition & 0 deletions packages/aws-cdk-lib/aws-certificatemanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ new acm.PrivateCertificate(this, 'PrivateCertificate', {
subjectAlternativeNames: ['cool.example.com', 'test.example.net'], // optional
certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(this, 'CA',
'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'),
keyAlgorithm: acm.KeyAlgorithm.RSA_2048 // optional, default algorithm is RSA_2048
longtv2222 marked this conversation as resolved.
Show resolved Hide resolved
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
});
```

Expand Down
30 changes: 30 additions & 0 deletions packages/aws-cdk-lib/aws-certificatemanager/lib/certificate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,36 @@ export interface CertificateProps {
readonly certificateName?: string
}

/**
* Certificate Manager key algorithm
*
* If you need to use an algorithm that doesn't exist as a static member, you
* can instantiate a `KeyAlgorithm` object, e.g: `new KeyAlgorithm('RSA_2048')`.
*/
export class KeyAlgorithm {
Copy link
Contributor Author

@longtv2222 longtv2222 Jan 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowed values are: RSA_1024 | RSA_2048 | RSA_3072 | RSA_4096 | EC_prime256v1 | EC_secp384r1 | EC_secp521r1 but I only included RSA_2048 | EC_prime256v1 | EC_secp384r1 since imported certificate does not exist in CloudFormation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I feel like that's the right thing to do for now too. Having the ability to create additional values probably makes up for any edge cases that could come up.

/**
* RSA_2048 algorithm
*/
public static readonly RSA_2048 = new KeyAlgorithm("RSA_2048");

/**
* EC_prime256v1 algorithm
*/
public static readonly EC_PRIME256V1 = new KeyAlgorithm("EC_prime256v1");

/**
* EC_secp384r1 algorithm
*/
public static readonly EC_SECP384R1 = new KeyAlgorithm("EC_secp384r1");

constructor(
/**
* The name of the algorithm
*/
public readonly name: string
) { };
}

/**
* Properties for certificate validation
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Construct } from 'constructs';
import { ICertificate } from './certificate';
import { ICertificate, KeyAlgorithm } from './certificate';
import { CertificateBase } from './certificate-base';
import { CfnCertificate } from './certificatemanager.generated';
import * as acmpca from '../../aws-acmpca';
Expand Down Expand Up @@ -28,6 +28,13 @@ export interface PrivateCertificateProps {
* Private certificate authority (CA) that will be used to issue the certificate.
*/
readonly certificateAuthority: acmpca.ICertificateAuthority;

/**
* Specifies the algorithm of the public and private key pair that your certificate uses to encrypt data.
*
longtv2222 marked this conversation as resolved.
Show resolved Hide resolved
* @default KeyAlgorithm.RSA_2048
Copy link
Contributor Author

@longtv2222 longtv2222 Jan 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If keyAlgorithm is undefined, then the default algorithm is RSA_2048 according to doc

*/
readonly keyAlgorithm?: KeyAlgorithm;
}

/**
Expand Down Expand Up @@ -59,6 +66,7 @@ export class PrivateCertificate extends CertificateBase implements ICertificate
domainName: props.domainName,
subjectAlternativeNames: props.subjectAlternativeNames,
certificateAuthorityArn: props.certificateAuthority.certificateAuthorityArn,
keyAlgorithm: props.keyAlgorithm?.name,
});

this.certificateArn = cert.ref;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Template } from '../../assertions';
import { Match, Template } from '../../assertions';
import * as acmpca from '../../aws-acmpca';
import { Duration, Lazy, Stack } from '../../core';
import { PrivateCertificate } from '../lib';
import { KeyAlgorithm, PrivateCertificate } from '../lib';

test('private certificate authority', () => {
const stack = new Stack();
Expand Down Expand Up @@ -100,3 +100,49 @@ test('metricDaysToExpiry', () => {
renderingProperties: expect.anything(),
});
});

describe('Key Algorithm', () => {
test('key algorithm is undefined if not provided', () => {
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'),
});

Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', {
KeyAlgorithm: Match.absent(),
});
});

test('Can specify algorithm', () => {
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'),
keyAlgorithm: KeyAlgorithm.EC_SECP384R1
});

Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', {
KeyAlgorithm: 'EC_secp384r1',
});
});

test('Can specify any arbitrary algorithm', () => {
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'),
keyAlgorithm: new KeyAlgorithm("any value"),
});

Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', {
KeyAlgorithm: 'any value',
});
});
});
Loading