@aws-cdk/aws-glue-alpha 2.262.2-alpha.0 → 2.264.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.jsii +1331 -183
  2. package/.jsii.tabl.json.gz +0 -0
  3. package/.warnings.jsii.js +23 -1
  4. package/README.md +154 -0
  5. package/awslint.json +2 -1
  6. package/custom-resource-handlers/dist/aws-glue-alpha/partition-index-handler/index.js +1 -0
  7. package/custom-resource-handlers/dist/aws-glue-alpha/partition-index-provider.generated.d.ts +8 -0
  8. package/custom-resource-handlers/dist/aws-glue-alpha/partition-index-provider.generated.js +68 -0
  9. package/lib/catalog.d.ts +259 -0
  10. package/lib/catalog.js +424 -0
  11. package/lib/code.js +3 -3
  12. package/lib/connection.js +2 -2
  13. package/lib/data-format.js +5 -5
  14. package/lib/data-quality-ruleset.js +2 -2
  15. package/lib/database.d.ts +17 -14
  16. package/lib/database.js +43 -24
  17. package/lib/external-table.js +3 -3
  18. package/lib/index.d.ts +1 -0
  19. package/lib/index.js +2 -1
  20. package/lib/jobs/job.js +2 -2
  21. package/lib/jobs/pyspark-etl-job.js +1 -1
  22. package/lib/jobs/pyspark-flex-etl-job.js +1 -1
  23. package/lib/jobs/pyspark-streaming-job.js +1 -1
  24. package/lib/jobs/python-shell-job.js +1 -1
  25. package/lib/jobs/ray-job.js +1 -1
  26. package/lib/jobs/scala-spark-etl-job.js +1 -1
  27. package/lib/jobs/scala-spark-flex-etl-job.js +1 -1
  28. package/lib/jobs/scala-spark-streaming-job.js +1 -1
  29. package/lib/jobs/spark-job.js +1 -1
  30. package/lib/partition-projection.js +1 -1
  31. package/lib/s3-table.js +11 -4
  32. package/lib/schema.js +1 -1
  33. package/lib/security-configuration.js +3 -3
  34. package/lib/storage-parameter.js +1 -1
  35. package/lib/table-base.d.ts +1 -1
  36. package/lib/table-base.js +126 -31
  37. package/lib/table-deprecated.js +1 -1
  38. package/lib/triggers/trigger-options.js +1 -1
  39. package/lib/triggers/workflow.js +2 -2
  40. package/package.json +11 -7
  41. package/scripts/airlift-custom-resource-handlers.sh +44 -0
Binary file
package/.warnings.jsii.js CHANGED
@@ -1,4 +1,26 @@
1
- const VALIDATORS = { _aws_cdk_aws_glue_alpha_ConnectionOptions: function _aws_cdk_aws_glue_alpha_ConnectionOptions(p) {
1
+ const VALIDATORS = { _aws_cdk_aws_glue_alpha_CatalogEncryptionOptions: function _aws_cdk_aws_glue_alpha_CatalogEncryptionOptions(p) {
2
+ if (p == null)
3
+ return;
4
+ visitedObjects.add(p);
5
+ try {
6
+ if (!visitedObjects.has(p.connectionPasswordEncryption))
7
+ module.exports._aws_cdk_aws_glue_alpha_ConnectionPasswordEncryption(p.connectionPasswordEncryption);
8
+ }
9
+ finally {
10
+ visitedObjects.delete(p);
11
+ }
12
+ }, _aws_cdk_aws_glue_alpha_CatalogProps: function _aws_cdk_aws_glue_alpha_CatalogProps(p) {
13
+ if (p == null)
14
+ return;
15
+ visitedObjects.add(p);
16
+ try {
17
+ if (!visitedObjects.has(p.connectionPasswordEncryption))
18
+ module.exports._aws_cdk_aws_glue_alpha_ConnectionPasswordEncryption(p.connectionPasswordEncryption);
19
+ }
20
+ finally {
21
+ visitedObjects.delete(p);
22
+ }
23
+ }, _aws_cdk_aws_glue_alpha_ConnectionOptions: function _aws_cdk_aws_glue_alpha_ConnectionOptions(p) {
2
24
  if (p == null)
3
25
  return;
4
26
  visitedObjects.add(p);
package/README.md CHANGED
@@ -494,6 +494,158 @@ new glue.SecurityConfiguration(this, 'MySecurityConfiguration', {
494
494
 
495
495
  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.
496
496
 
497
+ ## Catalog
498
+
499
+ The Glue Data Catalog is a persistent metadata store for your data assets. Every
500
+ account has an implicit, account-wide catalog that always exists, and you can also
501
+ create additional catalogs as `AWS::Glue::Catalog` resources (for example, to
502
+ federate to another metastore).
503
+
504
+ A catalog's encryption is fixed when the catalog is created: a catalog either
505
+ carries encryption settings or it does not. This keeps its configuration easy to
506
+ reason about — there are no mutation methods that change encryption after the fact.
507
+
508
+ ### The account-wide catalog
509
+
510
+ Use `Catalog.forAccount(scope)` to obtain the implicit account catalog. It is not
511
+ a CloudFormation resource — it always exists. Repeated calls within the same stack
512
+ return the same instance:
513
+
514
+ ```ts
515
+ const catalog = glue.Catalog.forAccount(this);
516
+ ```
517
+
518
+ To configure Data Catalog encryption for the account, use
519
+ `Catalog.encryptAccount(scope, options)`:
520
+
521
+ ```ts
522
+ declare const key: kms.Key;
523
+ glue.Catalog.encryptAccount(this, {
524
+ encryptionAtRest: glue.DataCatalogEncryptionAtRest.kms(key),
525
+ });
526
+ ```
527
+
528
+ Because encryption is fixed at construction, `encryptAccount` must be called
529
+ *before* the account catalog is first used in the stack — before any
530
+ `Catalog.forAccount(this)` call, and before any `Database` that uses the account
531
+ catalog. Calling it after the account catalog has been materialized throws.
532
+
533
+ The account catalog's encryption is an account- and region-wide setting, managed
534
+ through the singleton `PutDataCatalogEncryptionSettings` API. Configure it in
535
+ exactly one stack. Configuring it from multiple stacks in the same account and
536
+ region makes those stacks overwrite one another at deploy time, and the result is
537
+ order-dependent. Unlike duplicate settings within a single stack (which
538
+ CloudFormation rejects), this cross-stack conflict is not caught at synthesis
539
+ time, because each stack synthesizes to its own template.
540
+
541
+ ### Creating a catalog
542
+
543
+ To create a new catalog resource, use the `Catalog` constructor. Encryption is
544
+ configured through the `encryptionAtRest` and `connectionPasswordEncryption` props:
545
+
546
+ ```ts
547
+ new glue.Catalog(this, 'MyCatalog', {
548
+ catalogName: 'my-catalog',
549
+ description: 'my catalog description',
550
+ });
551
+ ```
552
+
553
+ ### Encryption at rest
554
+
555
+ Configure Data Catalog encryption at rest through the `encryptionAtRest` option
556
+ (on `Catalog.encryptAccount`, the `Catalog` constructor, or the import factories).
557
+ It accepts a `DataCatalogEncryptionAtRest` describing the mode:
558
+
559
+ ```ts
560
+ declare const key: kms.Key;
561
+
562
+ // SSE-KMS with a customer-managed key
563
+ glue.Catalog.encryptAccount(this, {
564
+ encryptionAtRest: glue.DataCatalogEncryptionAtRest.kms(key),
565
+ });
566
+
567
+ // SSE-KMS with an AWS-managed key (omit the key)
568
+ new glue.Catalog(this, 'ManagedKeyCatalog', {
569
+ catalogName: 'managed-key-catalog',
570
+ encryptionAtRest: glue.DataCatalogEncryptionAtRest.kms(),
571
+ });
572
+
573
+ // Disable encryption at rest
574
+ new glue.Catalog(this, 'PlaintextCatalog', {
575
+ catalogName: 'plaintext-catalog',
576
+ encryptionAtRest: glue.DataCatalogEncryptionAtRest.disabled(),
577
+ });
578
+ ```
579
+
580
+ When you use `SSE-KMS-WITH-SERVICE-ROLE`, AWS Glue accesses the KMS key through a
581
+ service role you provide. If you pass a customer-managed key, the role is
582
+ automatically granted the permissions it needs to encrypt and decrypt catalog data:
583
+
584
+ ```ts
585
+ import * as iam from 'aws-cdk-lib/aws-iam';
586
+ declare const key: kms.Key;
587
+ declare const role: iam.IRole;
588
+ glue.Catalog.encryptAccount(this, {
589
+ encryptionAtRest: glue.DataCatalogEncryptionAtRest.kmsWithServiceRole(role, key),
590
+ });
591
+ ```
592
+
593
+ The customer-managed key, when configured, is exposed on the catalog as
594
+ `encryptionKey` (and the connection-password key as `connectionPasswordKey`), so
595
+ you can reference it to grant additional access. It is undefined when encryption is
596
+ disabled or an AWS-managed key is used.
597
+
598
+ ### Connection password encryption
599
+
600
+ Independently from encryption at rest, the Data Catalog can encrypt the passwords
601
+ stored in connection properties. Configure it through the
602
+ `connectionPasswordEncryption` option:
603
+
604
+ ```ts
605
+ declare const key: kms.Key;
606
+ glue.Catalog.encryptAccount(this, {
607
+ connectionPasswordEncryption: {
608
+ kmsKey: key,
609
+ // Whether GetConnection/GetConnections return the password encrypted (default: true)
610
+ returnConnectionPasswordEncrypted: true,
611
+ },
612
+ });
613
+ ```
614
+
615
+ The two encryption blocks are independent: enabling one does not require the other,
616
+ and each may use a different KMS key. The customer-managed key for connection
617
+ passwords is exposed as `connectionPasswordKey`.
618
+
619
+ ### Importing a catalog
620
+
621
+ You can import an existing catalog by ARN or by id. An imported catalog is a pure
622
+ identity handle — it emits no resources and does not manage the catalog's
623
+ encryption:
624
+
625
+ ```ts
626
+ const byId = glue.Catalog.fromCatalogId(this, 'ById', 'my-catalog-id');
627
+ const byArn = glue.Catalog.fromCatalogArn(this, 'ByArn', 'arn:aws:glue:us-east-1:123456789012:catalog/my-catalog-id');
628
+ ```
629
+
630
+ To manage the Data Catalog encryption of a catalog you did not create in this
631
+ stack, add a `CfnDataCatalogEncryptionSettings` resource targeting its id
632
+ directly. Do this from exactly one stack: like the account catalog, a catalog has
633
+ a single encryption configuration, so two settings resources targeting the same id
634
+ race to overwrite one another at deploy time. Within a single stack this is caught
635
+ by CloudFormation template validation (E3019, duplicate primary identifiers);
636
+ across stacks it is not, since each stack synthesizes to its own template.
637
+
638
+ ```ts
639
+ import { CfnDataCatalogEncryptionSettings } from 'aws-cdk-lib/aws-glue';
640
+
641
+ new CfnDataCatalogEncryptionSettings(this, 'Encryption', {
642
+ catalogId: 'my-catalog-id',
643
+ dataCatalogEncryptionSettings: {
644
+ encryptionAtRest: { catalogEncryptionMode: 'SSE-KMS' },
645
+ },
646
+ });
647
+ ```
648
+
497
649
  ## Database
498
650
 
499
651
  A `Database` is a logical grouping of `Tables` in the Glue Catalog.
@@ -877,6 +1029,8 @@ new glue.ExternalTable(this, 'MyTable', {
877
1029
 
878
1030
  ## [Encryption](https://docs.aws.amazon.com/athena/latest/ug/encryption.html)
879
1031
 
1032
+ When the table creates its own S3 bucket (i.e. you do not pass an explicit `bucket`), that bucket enforces SSL: a bucket policy denies any request made over plain HTTP. If you provide your own bucket, enabling `enforceSSL` on it is your responsibility.
1033
+
880
1034
  You can enable encryption on a Table's data:
881
1035
 
882
1036
  * [S3Managed](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html) - (default) Server side encryption (`SSE-S3`) with an Amazon S3-managed key.
package/awslint.json CHANGED
@@ -108,6 +108,7 @@
108
108
  "interface-extends-ref:@aws-cdk/aws-glue-alpha.IJob",
109
109
  "interface-extends-ref:@aws-cdk/aws-glue-alpha.ISecurityConfiguration",
110
110
  "interface-extends-ref:@aws-cdk/aws-glue-alpha.ITable",
111
- "interface-extends-ref:@aws-cdk/aws-glue-alpha.IWorkflow"
111
+ "interface-extends-ref:@aws-cdk/aws-glue-alpha.IWorkflow",
112
+ "prefer-ref-interface:@aws-cdk/aws-glue-alpha.DatabaseProps.catalog"
112
113
  ]
113
114
  }
@@ -0,0 +1 @@
1
+ "use strict";var f=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var C=(t,e)=>{for(var i in e)f(t,i,{get:e[i],enumerable:!0})},P=(t,e,i,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of h(e))!w.call(t,r)&&r!==i&&f(t,r,{get:()=>e[r],enumerable:!(s=I(e,r))||s.enumerable});return t};var E=t=>P(f({},"__esModule",{value:!0}),t);var b={};C(b,{isComplete:()=>S,onEvent:()=>R});module.exports=E(b);var o=require("@aws-sdk/client-glue"),y=class extends Error{constructor(e){super(e),this.name="PartitionIndexError"}},u=new o.GlueClient({});async function m(t,e,i){return((await u.send(new o.GetPartitionIndexesCommand({DatabaseName:t,TableName:e}))).PartitionIndexDescriptorList||[]).find(r=>r.IndexName?.toLowerCase()===i.toLowerCase())}function x(t,e,i,s){return u.send(new o.CreatePartitionIndexCommand({DatabaseName:t,TableName:e,PartitionIndex:{IndexName:i,Keys:s}}))}async function R(t){let{DatabaseName:e,TableName:i,IndexName:s,Keys:r}=t.ResourceProperties;if(t.RequestType==="Create"){try{await x(e,i,s,r)}catch(n){if(n.name==="AlreadyExistsException"||n.name==="ResourceNumberLimitExceededException"){let a=await m(e,i,s),d=a?.Keys?.map(c=>c.Name);if(!a||JSON.stringify(d)!==JSON.stringify(r))throw new y(`Partition index ${s} already exists on ${e}.${i} with different or reordered keys (existing: ${JSON.stringify(d)}, requested: ${JSON.stringify(r)}). Delete the existing index first.`);console.log(`Partition index ${s} already exists with matching keys - reusing`)}else throw n}return{PhysicalResourceId:s}}else if(t.RequestType==="Update"){let n=t.OldResourceProperties??{},a=n.DatabaseName!==e||n.TableName!==i,d=JSON.stringify(n.Keys)!==JSON.stringify(r);if(!a&&!d)return{PhysicalResourceId:s};if(a)return{PhysicalResourceId:s};try{await u.send(new o.DeletePartitionIndexCommand({DatabaseName:e,TableName:i,IndexName:s}))}catch(c){if(c.name!=="EntityNotFoundException")throw c}return{PhysicalResourceId:s}}else if(t.RequestType==="Delete")try{await u.send(new o.DeletePartitionIndexCommand({DatabaseName:e,TableName:i,IndexName:s}))}catch(n){if(n.name==="EntityNotFoundException")console.log(`Partition index ${s} not found on ${e}.${i} - may have been deleted out-of-band`);else throw n}return{}}async function S(t){let{DatabaseName:e,TableName:i,IndexName:s,Keys:r}=t.ResourceProperties,n=await m(e,i,s);if(t.RequestType==="Delete")return{IsComplete:!n};let a=t.OldResourceProperties??{},d=t.RequestType==="Update"&&(a.DatabaseName!==e||a.TableName!==i),c=t.RequestType==="Update"&&JSON.stringify(a.Keys)!==JSON.stringify(r);if(d||c){let g=n?.Keys?.map(l=>l.Name),N=n!==void 0&&JSON.stringify(g)===JSON.stringify(r);if(!n){try{await x(e,i,s,r)}catch(l){if(l.name!=="AlreadyExistsException")throw l}return{IsComplete:!1}}if(!N)return{IsComplete:!1}}if(!n)return{IsComplete:!1};if(n.IndexStatus==="ACTIVE")return{IsComplete:!0};if(n.IndexStatus==="CREATING")return{IsComplete:!1};if(n.IndexStatus==="DELETING")return{IsComplete:!1};let p=n.BackfillErrors?.length?` Backfill errors: ${JSON.stringify(n.BackfillErrors)}`:"";throw new y(`Partition index ${s} in unexpected state: ${n.IndexStatus}.${p}`)}0&&(module.exports={isComplete,onEvent});
@@ -0,0 +1,8 @@
1
+ import { Construct } from "constructs";
2
+ import * as lambda from "aws-cdk-lib/aws-lambda";
3
+ export declare class PartitionIndexOnEventFunction extends lambda.Function {
4
+ constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
5
+ }
6
+ export declare class PartitionIndexIsCompleteFunction extends lambda.Function {
7
+ constructor(scope: Construct, id: string, props?: lambda.FunctionOptions);
8
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PartitionIndexIsCompleteFunction = exports.PartitionIndexOnEventFunction = void 0;
37
+ /* eslint-disable prettier/prettier, @stylistic/max-len */
38
+ const path = __importStar(require("path"));
39
+ const lambda = __importStar(require("aws-cdk-lib/aws-lambda"));
40
+ class PartitionIndexOnEventFunction extends lambda.Function {
41
+ constructor(scope, id, props) {
42
+ super(scope, id, {
43
+ ...props,
44
+ code: lambda.Code.fromAsset(path.join(__dirname, 'partition-index-handler'), {
45
+ assetHash: "028d94f2a9d516b362cd4e21d696c452c79a04b5023274979ba12affc803bfb9"
46
+ }),
47
+ handler: "index.onEvent",
48
+ runtime: lambda.determineLatestNodeRuntime(scope)
49
+ });
50
+ this.node.addMetadata('aws:cdk:is-custom-resource-handler-runtime-family', this.runtime.family);
51
+ }
52
+ }
53
+ exports.PartitionIndexOnEventFunction = PartitionIndexOnEventFunction;
54
+ class PartitionIndexIsCompleteFunction extends lambda.Function {
55
+ constructor(scope, id, props) {
56
+ super(scope, id, {
57
+ ...props,
58
+ code: lambda.Code.fromAsset(path.join(__dirname, 'partition-index-handler'), {
59
+ assetHash: "028d94f2a9d516b362cd4e21d696c452c79a04b5023274979ba12affc803bfb9"
60
+ }),
61
+ handler: "index.isComplete",
62
+ runtime: lambda.determineLatestNodeRuntime(scope)
63
+ });
64
+ this.node.addMetadata('aws:cdk:is-custom-resource-handler-runtime-family', this.runtime.family);
65
+ }
66
+ }
67
+ exports.PartitionIndexIsCompleteFunction = PartitionIndexIsCompleteFunction;
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFydGl0aW9uLWluZGV4LXByb3ZpZGVyLmdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBhcnRpdGlvbi1pbmRleC1wcm92aWRlci5nZW5lcmF0ZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMERBQTBEO0FBQzFELDJDQUE2QjtBQUU3QiwrREFBaUQ7QUFFakQsTUFBYSw2QkFBOEIsU0FBUSxNQUFNLENBQUMsUUFBUTtJQUNoRSxZQUFtQixLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE4QjtRQUM3RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLEdBQUcsS0FBSztZQUNSLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSx5QkFBeUIsQ0FBQyxFQUFFO2dCQUMzRSxTQUFTLEVBQUUsa0VBQWtFO2FBQzlFLENBQUM7WUFDRixPQUFPLEVBQUUsZUFBZTtZQUN4QixPQUFPLEVBQUUsTUFBTSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQztTQUNsRCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtREFBbUQsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQ2pHO0NBQ0Y7QUFaRCxzRUFZQztBQUVELE1BQWEsZ0NBQWlDLFNBQVEsTUFBTSxDQUFDLFFBQVE7SUFDbkUsWUFBbUIsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBOEI7UUFDN0UsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixHQUFHLEtBQUs7WUFDUixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUseUJBQXlCLENBQUMsRUFBRTtnQkFDM0UsU0FBUyxFQUFFLGtFQUFrRTthQUM5RSxDQUFDO1lBQ0YsT0FBTyxFQUFFLGtCQUFrQjtZQUMzQixPQUFPLEVBQUUsTUFBTSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQztTQUNsRCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtREFBbUQsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQ2pHO0NBQ0Y7QUFaRCw0RUFZQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyLCBAc3R5bGlzdGljL21heC1sZW4gKi9cbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIjtcblxuZXhwb3J0IGNsYXNzIFBhcnRpdGlvbkluZGV4T25FdmVudEZ1bmN0aW9uIGV4dGVuZHMgbGFtYmRhLkZ1bmN0aW9uIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzPzogbGFtYmRhLkZ1bmN0aW9uT3B0aW9ucykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJ3BhcnRpdGlvbi1pbmRleC1oYW5kbGVyJyksIHtcbiAgICAgICAgYXNzZXRIYXNoOiBcIjAyOGQ5NGYyYTlkNTE2YjM2MmNkNGUyMWQ2OTZjNDUyYzc5YTA0YjUwMjMyNzQ5NzliYTEyYWZmYzgwM2JmYjlcIlxuICAgICAgfSksXG4gICAgICBoYW5kbGVyOiBcImluZGV4Lm9uRXZlbnRcIixcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5kZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZShzY29wZSlcbiAgICB9KTtcbiAgICB0aGlzLm5vZGUuYWRkTWV0YWRhdGEoJ2F3czpjZGs6aXMtY3VzdG9tLXJlc291cmNlLWhhbmRsZXItcnVudGltZS1mYW1pbHknLCB0aGlzLnJ1bnRpbWUuZmFtaWx5KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGFydGl0aW9uSW5kZXhJc0NvbXBsZXRlRnVuY3Rpb24gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge1xuICBwdWJsaWMgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM/OiBsYW1iZGEuRnVuY3Rpb25PcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAncGFydGl0aW9uLWluZGV4LWhhbmRsZXInKSwge1xuICAgICAgICBhc3NldEhhc2g6IFwiMDI4ZDk0ZjJhOWQ1MTZiMzYyY2Q0ZTIxZDY5NmM0NTJjNzlhMDRiNTAyMzI3NDk3OWJhMTJhZmZjODAzYmZiOVwiXG4gICAgICB9KSxcbiAgICAgIGhhbmRsZXI6IFwiaW5kZXguaXNDb21wbGV0ZVwiLFxuICAgICAgcnVudGltZTogbGFtYmRhLmRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lKHNjb3BlKVxuICAgIH0pO1xuICAgIHRoaXMubm9kZS5hZGRNZXRhZGF0YSgnYXdzOmNkazppcy1jdXN0b20tcmVzb3VyY2UtaGFuZGxlci1ydW50aW1lLWZhbWlseScsIHRoaXMucnVudGltZS5mYW1pbHkpO1xuICB9XG59Il19
@@ -0,0 +1,259 @@
1
+ import type { CatalogReference, ICatalogRef } from 'aws-cdk-lib/aws-glue';
2
+ import type * as iam from 'aws-cdk-lib/aws-iam';
3
+ import type * as kms from 'aws-cdk-lib/aws-kms';
4
+ import type { IResource } from 'aws-cdk-lib/core';
5
+ import { Resource } from 'aws-cdk-lib/core';
6
+ import type { Construct } from 'constructs';
7
+ /**
8
+ * The encryption-at-rest mode for a Glue Data Catalog.
9
+ *
10
+ * @see https://docs.aws.amazon.com/glue/latest/webapi/API_EncryptionAtRest.html#Glue-Type-EncryptionAtRest-CatalogEncryptionMode
11
+ */
12
+ export declare enum CatalogEncryptionMode {
13
+ /**
14
+ * Encryption at rest is disabled.
15
+ */
16
+ DISABLED = "DISABLED",
17
+ /**
18
+ * Server-side encryption (SSE) with an AWS KMS key.
19
+ */
20
+ SSE_KMS = "SSE-KMS",
21
+ /**
22
+ * Server-side encryption (SSE) with an AWS KMS key, using a service role that
23
+ * AWS Glue assumes to access the key on your behalf.
24
+ */
25
+ SSE_KMS_WITH_SERVICE_ROLE = "SSE-KMS-WITH-SERVICE-ROLE"
26
+ }
27
+ /**
28
+ * Encryption-at-rest configuration for a Glue Data Catalog.
29
+ *
30
+ * The Data Catalog encryption at rest and the connection password encryption
31
+ * are independent: enabling one does not require the other, and each may use a
32
+ * different KMS key.
33
+ *
34
+ * @see https://docs.aws.amazon.com/glue/latest/webapi/API_EncryptionAtRest.html
35
+ */
36
+ export declare class DataCatalogEncryptionAtRest {
37
+ /**
38
+ * Disable encryption at rest for the Data Catalog.
39
+ */
40
+ static disabled(): DataCatalogEncryptionAtRest;
41
+ /**
42
+ * Encrypt the Data Catalog at rest with an AWS KMS key.
43
+ *
44
+ * @param key the KMS key to use. If omitted, an AWS-managed key is used and
45
+ * the key is not exposed as a grantable resource.
46
+ */
47
+ static kms(key?: kms.IKey): DataCatalogEncryptionAtRest;
48
+ /**
49
+ * Encrypt the Data Catalog at rest with an AWS KMS key, accessed through a
50
+ * service role that AWS Glue assumes on your behalf.
51
+ *
52
+ * When a customer-managed `key` is provided, the `role` is automatically
53
+ * granted `kms:Encrypt`/`kms:Decrypt`/`kms:GenerateDataKey*` on it.
54
+ *
55
+ * @param role the service role that AWS Glue assumes to access the key.
56
+ * @param key the KMS key to use. If omitted, an AWS-managed key is used and
57
+ * the key is not exposed as a grantable resource.
58
+ */
59
+ static kmsWithServiceRole(role: iam.IRole, key?: kms.IKey): DataCatalogEncryptionAtRest;
60
+ /**
61
+ * The encryption mode.
62
+ */
63
+ readonly mode: CatalogEncryptionMode;
64
+ /**
65
+ * The customer-managed KMS key used for encryption at rest, if any.
66
+ */
67
+ readonly kmsKey?: kms.IKeyRef;
68
+ /**
69
+ * The service role that AWS Glue assumes to access the KMS key, if any.
70
+ */
71
+ readonly serviceRole?: iam.IRole;
72
+ private constructor();
73
+ }
74
+ /**
75
+ * Connection-password encryption configuration for a Glue Data Catalog.
76
+ *
77
+ * When enabled, the Data Catalog encrypts the password as part of
78
+ * `CreateConnection` or `UpdateConnection` and stores it in the
79
+ * `ENCRYPTED_PASSWORD` field of the connection properties. This is independent
80
+ * from catalog encryption at rest, and may use a different KMS key.
81
+ *
82
+ * @see https://docs.aws.amazon.com/glue/latest/webapi/API_ConnectionPasswordEncryption.html
83
+ */
84
+ export interface ConnectionPasswordEncryption {
85
+ /**
86
+ * The KMS key used to encrypt connection passwords.
87
+ *
88
+ * @default - an AWS-managed key is used and the key is not exposed as a grantable resource.
89
+ */
90
+ readonly kmsKey?: kms.IKeyRef;
91
+ /**
92
+ * Whether passwords remain encrypted in the responses of `GetConnection` and
93
+ * `GetConnections`. This takes effect independently from catalog encryption.
94
+ *
95
+ * @default true
96
+ */
97
+ readonly returnConnectionPasswordEncrypted?: boolean;
98
+ }
99
+ /**
100
+ * Encryption configuration for a Glue Data Catalog.
101
+ *
102
+ * Encryption is fixed at construction: a catalog either carries encryption
103
+ * settings or it does not, which keeps its configuration easy to reason about
104
+ * and avoids order-dependent mutation after the catalog is created.
105
+ */
106
+ export interface CatalogEncryptionOptions {
107
+ /**
108
+ * Encryption-at-rest configuration for the catalog.
109
+ *
110
+ * @default - encryption at rest is not managed by CDK (the catalog default applies)
111
+ */
112
+ readonly encryptionAtRest?: DataCatalogEncryptionAtRest;
113
+ /**
114
+ * Connection-password encryption configuration for the catalog.
115
+ *
116
+ * @default - connection-password encryption is not managed by CDK
117
+ */
118
+ readonly connectionPasswordEncryption?: ConnectionPasswordEncryption;
119
+ }
120
+ /**
121
+ * A Glue Data Catalog, either the implicit account-wide catalog or one created
122
+ * as an `AWS::Glue::Catalog` resource.
123
+ */
124
+ export interface ICatalog extends IResource, ICatalogRef {
125
+ /**
126
+ * The id of the catalog (for the account-wide catalog, the AWS account id).
127
+ * @attribute
128
+ */
129
+ readonly catalogId: string;
130
+ /**
131
+ * The ARN of the catalog.
132
+ * @attribute
133
+ */
134
+ readonly catalogArn: string;
135
+ /**
136
+ * The customer-managed KMS key used for the catalog's encryption at rest, if
137
+ * one was configured.
138
+ *
139
+ * Undefined when encryption is disabled or an AWS-managed key is used. Grant
140
+ * access to it via `KeyGrants`, e.g.
141
+ * `if (catalog.encryptionKey) { KeyGrants.fromKey(catalog.encryptionKey).encrypt(grantee); }`.
142
+ */
143
+ readonly encryptionKey?: kms.IKeyRef;
144
+ /**
145
+ * The customer-managed KMS key used to encrypt connection passwords, if one
146
+ * was configured.
147
+ *
148
+ * Undefined when password encryption uses an AWS-managed key or is not
149
+ * configured. Grant access to it via `KeyGrants`, e.g.
150
+ * `if (catalog.connectionPasswordKey) { KeyGrants.fromKey(catalog.connectionPasswordKey).encrypt(grantee); }`.
151
+ */
152
+ readonly connectionPasswordKey?: kms.IKeyRef;
153
+ }
154
+ /**
155
+ * Base class for all `ICatalog` implementations. Materializes the single
156
+ * `CfnDataCatalogEncryptionSettings` resource (targeting its own `catalogId`)
157
+ * from the encryption options supplied at construction. Encryption is fixed at
158
+ * construction, so a catalog either carries settings or it does not.
159
+ */
160
+ export declare abstract class CatalogBase extends Resource implements ICatalog {
161
+ abstract readonly catalogId: string;
162
+ abstract readonly catalogArn: string;
163
+ private _encryptionKey?;
164
+ private _connectionPasswordKey?;
165
+ get encryptionKey(): kms.IKeyRef | undefined;
166
+ get connectionPasswordKey(): kms.IKeyRef | undefined;
167
+ get catalogRef(): CatalogReference;
168
+ /**
169
+ * Emit the catalog's encryption settings from the options fixed at
170
+ * construction. Subclasses call this once, after `catalogId`/`catalogArn` are
171
+ * assigned. When neither block is configured, no resource is emitted, avoiding
172
+ * an empty settings resource that would reset the catalog on deploy.
173
+ */
174
+ protected configureEncryption(options: CatalogEncryptionOptions): void;
175
+ }
176
+ /**
177
+ * Construction properties for a `Catalog`.
178
+ */
179
+ export interface CatalogProps extends CatalogEncryptionOptions {
180
+ /**
181
+ * The name of the catalog.
182
+ */
183
+ readonly catalogName: string;
184
+ /**
185
+ * A description of the catalog.
186
+ *
187
+ * @default - no description
188
+ */
189
+ readonly description?: string;
190
+ }
191
+ /**
192
+ * A Glue Data Catalog.
193
+ *
194
+ * Use `Catalog.forAccount(scope)` to obtain the implicit account-wide catalog,
195
+ * `Catalog.encryptAccount(scope, options)` to configure its Data Catalog
196
+ * encryption, or `new Catalog(...)` to create an `AWS::Glue::Catalog` resource.
197
+ */
198
+ export declare class Catalog extends CatalogBase {
199
+ /** Uniquely identifies this class. */
200
+ static readonly PROPERTY_INJECTION_ID: string;
201
+ /**
202
+ * Obtain the implicit, account-wide Data Catalog.
203
+ *
204
+ * The account catalog is not a CloudFormation resource; it always exists. This
205
+ * returns a stack-scoped singleton, so repeated calls within the same stack
206
+ * return the same instance.
207
+ *
208
+ * This returns the account catalog without managing its encryption. To
209
+ * configure Data Catalog encryption for the account, use
210
+ * `Catalog.encryptAccount(scope, options)` instead - it must be called before
211
+ * the account catalog is first used in the stack.
212
+ */
213
+ static forAccount(scope: Construct): ICatalog;
214
+ /**
215
+ * Configure Data Catalog encryption for the implicit, account-wide catalog and
216
+ * return it.
217
+ *
218
+ * The account catalog's encryption is an account/region-wide setting, managed
219
+ * through the singleton `PutDataCatalogEncryptionSettings` API. Because
220
+ * encryption is fixed at construction, it must be configured before the
221
+ * account catalog is first used in the stack: calling this after the account
222
+ * catalog has already been materialized (for example by `Catalog.forAccount`,
223
+ * or by a `Database` that uses the account catalog) throws.
224
+ *
225
+ * Configure it in exactly one stack. Configuring it from multiple stacks in the
226
+ * same account and region makes those stacks overwrite one another at deploy
227
+ * time, and the result is order-dependent. Unlike duplicate settings within a
228
+ * single stack (which CloudFormation rejects), this cross-stack conflict is not
229
+ * caught at synthesis time, because each stack synthesizes to its own template.
230
+ */
231
+ static encryptAccount(scope: Construct, options: CatalogEncryptionOptions): ICatalog;
232
+ /**
233
+ * Import an existing catalog by its ARN.
234
+ *
235
+ * The ARN must be a Glue catalog ARN, either the account-wide catalog
236
+ * (`arn:aws:glue:<region>:<account>:catalog`, whose id is the account) or a
237
+ * named catalog (`arn:aws:glue:<region>:<account>:catalog/<name>`, whose id is
238
+ * the name).
239
+ *
240
+ * The imported catalog is a pure identity handle and does not manage the
241
+ * catalog's encryption. To manage an existing catalog's Data Catalog
242
+ * encryption, add a `CfnDataCatalogEncryptionSettings` resource targeting its
243
+ * id.
244
+ */
245
+ static fromCatalogArn(scope: Construct, id: string, catalogArn: string): ICatalog;
246
+ /**
247
+ * Import an existing catalog by its id.
248
+ *
249
+ * The imported catalog is a pure identity handle and does not manage the
250
+ * catalog's encryption. To manage an existing catalog's Data Catalog
251
+ * encryption, add a `CfnDataCatalogEncryptionSettings` resource targeting its
252
+ * id.
253
+ */
254
+ static fromCatalogId(scope: Construct, id: string, catalogId: string): ICatalog;
255
+ readonly catalogId: string;
256
+ readonly catalogArn: string;
257
+ private readonly resource;
258
+ constructor(scope: Construct, id: string, props: CatalogProps);
259
+ }