Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions packages/@aws-cdk/aws-glue-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,32 +497,29 @@ See [Adding a Connection to Your Data Store](https://docs.aws.amazon.com/glue/la

A `SecurityConfiguration` is a set of security properties that can be used by AWS Glue to encrypt data at rest.

Each encryption config is built with a factory that pairs the encryption mode
with its key, so illegal combinations (such as an S3-managed encryption carrying
a KMS key) cannot be expressed:

```ts
new glue.SecurityConfiguration(this, 'MySecurityConfiguration', {
cloudWatchEncryption: {
mode: glue.CloudWatchEncryptionMode.KMS,
},
jobBookmarksEncryption: {
mode: glue.JobBookmarksEncryptionMode.CLIENT_SIDE_KMS,
},
s3Encryption: {
mode: glue.S3EncryptionMode.KMS,
},
cloudWatchEncryption: glue.CloudWatchEncryption.kms(),
jobBookmarksEncryption: glue.JobBookmarksEncryption.clientSideKms(),
s3Encryption: glue.S3Encryption.kms(),
});
```

By default, a shared KMS key is created for use with the encryption configurations that require one. You can also supply your own key for each encryption config, for example, for CloudWatch encryption:
By default, a shared KMS key is created for use with the encryption configurations that require one. You can also supply your own key to any factory, for example, for CloudWatch encryption:

```ts
declare const key: kms.Key;
new glue.SecurityConfiguration(this, 'MySecurityConfiguration', {
cloudWatchEncryption: {
mode: glue.CloudWatchEncryptionMode.KMS,
kmsKey: key,
},
cloudWatchEncryption: glue.CloudWatchEncryption.kms(key),
});
```

Use `glue.S3Encryption.s3Managed()` for S3-managed (SSE-S3) encryption, which takes no key.

See [documentation](https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html) for more info for Glue encrypting data written by Crawlers, Jobs, and Development Endpoints.

## Catalog
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-glue-alpha/awslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"interface-extends-ref:@aws-cdk/aws-glue-alpha.ISecurityConfiguration",
"interface-extends-ref:@aws-cdk/aws-glue-alpha.ITable",
"interface-extends-ref:@aws-cdk/aws-glue-alpha.IWorkflow",
"prefer-ref-interface:@aws-cdk/aws-glue-alpha.DatabaseProps.catalog"
"prefer-ref-interface:@aws-cdk/aws-glue-alpha.DatabaseProps.catalog",
"no-unused-type:@aws-cdk/aws-glue-alpha.S3EncryptionMode"
]
}
130 changes: 73 additions & 57 deletions packages/@aws-cdk/aws-glue-alpha/lib/security-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,78 +38,94 @@ export enum S3EncryptionMode {
KMS = 'SSE-KMS',
}

// CloudWatch Logs support only SSE-KMS; Job Bookmarks support only CSE-KMS.
const CLOUD_WATCH_ENCRYPTION_MODE = 'SSE-KMS';
const JOB_BOOKMARKS_ENCRYPTION_MODE = 'CSE-KMS';

/**
* Encryption mode for CloudWatch Logs.
* @see https://docs.aws.amazon.com/glue/latest/webapi/API_CloudWatchEncryption.html#Glue-Type-CloudWatchEncryption-CloudWatchEncryptionMode
* S3 encryption configuration for a `SecurityConfiguration`.
*
* Use {@link S3Encryption.s3Managed} for SSE-S3 or {@link S3Encryption.kms} for
* SSE-KMS. Because these are separate factories, a KMS key can never be paired
* with S3-managed encryption.
*/
export enum CloudWatchEncryptionMode {
export class S3Encryption {
/**
* Server-side encryption (SSE) with an AWS KMS key managed by the account owner.
* Server-side encryption (SSE) with an Amazon S3-managed key.
*
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html
*/
KMS = 'SSE-KMS',
}
public static s3Managed(): S3Encryption {
return new S3Encryption(S3EncryptionMode.S3_MANAGED, undefined);
}

/**
* Encryption mode for Job Bookmarks.
* @see https://docs.aws.amazon.com/glue/latest/webapi/API_JobBookmarksEncryption.html#Glue-Type-JobBookmarksEncryption-JobBookmarksEncryptionMode
*/
export enum JobBookmarksEncryptionMode {
/**
* Client-side encryption (CSE) with an AWS KMS key managed by the account owner.
* Server-side encryption (SSE) with an AWS KMS key managed by the account owner.
*
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html
* @param kmsKey the KMS key used to encrypt the data. A key is created if one is not provided.
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
*/
CLIENT_SIDE_KMS = 'CSE-KMS',
}
public static kms(kmsKey?: kms.IKeyRef): S3Encryption {
return new S3Encryption(S3EncryptionMode.KMS, kmsKey);
}

/**
* S3 encryption configuration.
*/
export interface S3Encryption {
/**
* Encryption mode.
*/
readonly mode: S3EncryptionMode;
/** @internal */
public readonly _mode: S3EncryptionMode;

/**
* The KMS key to be used to encrypt the data.
* @default no kms key if mode = S3_MANAGED. A key will be created if one is not provided and mode = KMS.
*/
readonly kmsKey?: kms.IKeyRef;
/** @internal */
public readonly _kmsKey?: kms.IKeyRef;

private constructor(mode: S3EncryptionMode, kmsKey?: kms.IKeyRef) {
this._mode = mode;
this._kmsKey = kmsKey;
}
}

/**
* CloudWatch Logs encryption configuration.
* CloudWatch Logs encryption configuration for a `SecurityConfiguration`.
*
* CloudWatch Logs support only server-side encryption with a KMS key.
*/
export interface CloudWatchEncryption {
export class CloudWatchEncryption {
/**
* Encryption mode
* Server-side encryption (SSE) with an AWS KMS key managed by the account owner.
*
* @param kmsKey the KMS key used to encrypt the data. A key is created if one is not provided.
*/
readonly mode: CloudWatchEncryptionMode;
public static kms(kmsKey?: kms.IKeyRef): CloudWatchEncryption {
return new CloudWatchEncryption(kmsKey);
}

/**
* The KMS key to be used to encrypt the data.
* @default A key will be created if one is not provided.
*/
readonly kmsKey?: kms.IKeyRef;
/** @internal */
public readonly _kmsKey?: kms.IKeyRef;

private constructor(kmsKey?: kms.IKeyRef) {
this._kmsKey = kmsKey;
}
}

/**
* Job bookmarks encryption configuration.
* Job bookmarks encryption configuration for a `SecurityConfiguration`.
*
* Job bookmarks support only client-side encryption with a KMS key.
*/
export interface JobBookmarksEncryption {
export class JobBookmarksEncryption {
/**
* Encryption mode.
* Client-side encryption (CSE) with an AWS KMS key managed by the account owner.
*
* @param kmsKey the KMS key used to encrypt the data. A key is created if one is not provided.
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html
*/
readonly mode: JobBookmarksEncryptionMode;
public static clientSideKms(kmsKey?: kms.IKeyRef): JobBookmarksEncryption {
return new JobBookmarksEncryption(kmsKey);
}

/**
* The KMS key to be used to encrypt the data.
* @default A key will be created if one is not provided.
*/
readonly kmsKey?: kms.IKeyRef;
/** @internal */
public readonly _kmsKey?: kms.IKeyRef;

private constructor(kmsKey?: kms.IKeyRef) {
this._kmsKey = kmsKey;
}
}

/**
Expand Down Expand Up @@ -210,37 +226,37 @@ export class SecurityConfiguration extends cdk.Resource implements ISecurityConf
}

const kmsKeyCreationRequired =
(props.s3Encryption && props.s3Encryption.mode === S3EncryptionMode.KMS && !props.s3Encryption.kmsKey) ||
(props.cloudWatchEncryption && !props.cloudWatchEncryption.kmsKey) ||
(props.jobBookmarksEncryption && !props.jobBookmarksEncryption.kmsKey);
(props.s3Encryption && props.s3Encryption._mode === S3EncryptionMode.KMS && !props.s3Encryption._kmsKey) ||
(props.cloudWatchEncryption && !props.cloudWatchEncryption._kmsKey) ||
(props.jobBookmarksEncryption && !props.jobBookmarksEncryption._kmsKey);
const autoCreatedKmsKey = kmsKeyCreationRequired ? new kms.Key(this, 'Key', { enableKeyRotation: true }) : undefined;

let cloudWatchEncryption;
if (props.cloudWatchEncryption) {
this.cloudWatchEncryptionKey = props.cloudWatchEncryption.kmsKey || autoCreatedKmsKey;
this.cloudWatchEncryptionKey = props.cloudWatchEncryption._kmsKey || autoCreatedKmsKey;
cloudWatchEncryption = {
cloudWatchEncryptionMode: props.cloudWatchEncryption.mode,
cloudWatchEncryptionMode: CLOUD_WATCH_ENCRYPTION_MODE,
kmsKeyArn: this.cloudWatchEncryptionKey?.keyRef.keyArn,
};
}

let jobBookmarksEncryption;
if (props.jobBookmarksEncryption) {
this.jobBookmarksEncryptionKey = props.jobBookmarksEncryption.kmsKey || autoCreatedKmsKey;
this.jobBookmarksEncryptionKey = props.jobBookmarksEncryption._kmsKey || autoCreatedKmsKey;
jobBookmarksEncryption = {
jobBookmarksEncryptionMode: props.jobBookmarksEncryption.mode,
jobBookmarksEncryptionMode: JOB_BOOKMARKS_ENCRYPTION_MODE,
kmsKeyArn: this.jobBookmarksEncryptionKey?.keyRef.keyArn,
};
}

let s3Encryptions;
if (props.s3Encryption) {
if (props.s3Encryption.mode === S3EncryptionMode.KMS) {
this.s3EncryptionKey = props.s3Encryption.kmsKey || autoCreatedKmsKey;
if (props.s3Encryption._mode === S3EncryptionMode.KMS) {
this.s3EncryptionKey = props.s3Encryption._kmsKey || autoCreatedKmsKey;
}
// NOTE: CloudFormations errors out if array is of length > 1. That's why the props don't expose an array
s3Encryptions = [{
s3EncryptionMode: props.s3Encryption.mode,
s3EncryptionMode: props.s3Encryption._mode,
kmsKeyArn: this.s3EncryptionKey?.keyRef.keyArn,
}];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,23 @@ const key = new kms.Key(stack, 'Key');
// SecurityConfiguration for all 3 (s3, cloudwatch and job bookmarks) in modes requiring kms keys
new glue.SecurityConfiguration(stack, 'KeyedSC', {
securityConfigurationName: 'KeyedSC',
jobBookmarksEncryption: {
mode: glue.JobBookmarksEncryptionMode.CLIENT_SIDE_KMS,
kmsKey: key,
},
cloudWatchEncryption: {
mode: glue.CloudWatchEncryptionMode.KMS,
kmsKey: key,
},
s3Encryption: {
mode: glue.S3EncryptionMode.KMS,
kmsKey: key,
},
jobBookmarksEncryption: glue.JobBookmarksEncryption.clientSideKms(key),
cloudWatchEncryption: glue.CloudWatchEncryption.kms(key),
s3Encryption: glue.S3Encryption.kms(key),
});

// SecurityConfiguration for all 3 (s3, cloudwatch and job bookmarks) in modes requiring kms keys without one provided
new glue.SecurityConfiguration(stack, 'KeylessSC', {
securityConfigurationName: 'KeylessSC',
jobBookmarksEncryption: {
mode: glue.JobBookmarksEncryptionMode.CLIENT_SIDE_KMS,
},
cloudWatchEncryption: {
mode: glue.CloudWatchEncryptionMode.KMS,
},
s3Encryption: {
mode: glue.S3EncryptionMode.KMS,
},
jobBookmarksEncryption: glue.JobBookmarksEncryption.clientSideKms(),
cloudWatchEncryption: glue.CloudWatchEncryption.kms(),
s3Encryption: glue.S3Encryption.kms(),
});

// SecurityConfiguration for s3 not requiring kms key
new glue.SecurityConfiguration(stack, 'S3SC', {
securityConfigurationName: 'S3SC',
s3Encryption: {
mode: glue.S3EncryptionMode.S3_MANAGED,
},
s3Encryption: glue.S3Encryption.s3Managed(),
});

app.synth();
Loading
Loading