diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/.eslintrc.js b/packages/@aws-cdk/aws-s3vectors-alpha/.eslintrc.js new file mode 100644 index 0000000000000..73d2505a85a7f --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/.eslintrc.js @@ -0,0 +1,4 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +baseConfig.rules['import/order'] = 'off'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/.gitignore b/packages/@aws-cdk/aws-s3vectors-alpha/.gitignore new file mode 100644 index 0000000000000..60f323886f8db --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/.gitignore @@ -0,0 +1,22 @@ +*.js +*.js.map +*.d.ts +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml +!**/*.snapshot/**/asset.*/*.js +!**/*.snapshot/**/asset.*/*.d.ts + +!**/*.snapshot/**/asset.*/** diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/.jsiirc.json b/packages/@aws-cdk/aws-s3vectors-alpha/.jsiirc.json new file mode 100644 index 0000000000000..c2abedeeb3195 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "java": { + "package": "software.amazon.awscdk.services.s3vectors.alpha" + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.S3Vectors.Alpha" + }, + "python": { + "module": "aws_cdk.aws_s3vectors_alpha" + } + } +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/.npmignore b/packages/@aws-cdk/aws-s3vectors-alpha/.npmignore new file mode 100644 index 0000000000000..7369a31e261be --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/.npmignore @@ -0,0 +1,33 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +tsconfig.json + +# Include .jsii +!.jsii + +# Include .js files +!*.js + +# Exclude jsii outdir +dist + +# Exclude test files +test/ +jest.config.js +*.integ.snapshot/ + +# Exclude build artifacts +*.tsbuildinfo + +# exclude cdk artifacts +**/cdk.out +.LAST_PACKAGE +.LAST_BUILD +*.snk +junit.xml +!*.lit.ts +coverage +.nyc_output +*.tgz +.eslintrc.js \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/LICENSE b/packages/@aws-cdk/aws-s3vectors-alpha/LICENSE new file mode 100644 index 0000000000000..5ccf0c6780bab --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/NOTICE b/packages/@aws-cdk/aws-s3vectors-alpha/NOTICE new file mode 100644 index 0000000000000..cd0946c1cf193 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/README.md b/packages/@aws-cdk/aws-s3vectors-alpha/README.md new file mode 100644 index 0000000000000..6ef28e700c460 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/README.md @@ -0,0 +1,41 @@ +# AWS S3 Vectors Construct Library (Alpha) + + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +Amazon S3 Vectors delivers purpose-built, cost-optimized vector storage for semantic search and AI applications. + +## Installation + +Install the module: + +```sh +npm install @aws-cdk/aws-s3vectors-alpha +``` + +## Usage + +Documentation and examples will be added during implementation. + +## Contributing + +See [CONTRIBUTING](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) for more information. + +## License + +This project is licensed under the Apache-2.0 License. diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/awslint.json b/packages/@aws-cdk/aws-s3vectors-alpha/awslint.json new file mode 100644 index 0000000000000..624531244a1b5 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/awslint.json @@ -0,0 +1,7 @@ +{ + "exclude": [ + "props-physical-name:@aws-cdk/aws-s3vectors-alpha.VectorBucketPolicyProps", + "attribute-tag:@aws-cdk/aws-s3vectors-alpha.VectorBucket.vectorBucketPolicy", + "attribute-readonly:@aws-cdk/aws-s3vectors-alpha.VectorBucket.vectorBucketPolicy" + ] +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/jest.config.js b/packages/@aws-cdk/aws-s3vectors-alpha/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/lib/index-construct.ts b/packages/@aws-cdk/aws-s3vectors-alpha/lib/index-construct.ts new file mode 100644 index 0000000000000..477956a89557c --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/lib/index-construct.ts @@ -0,0 +1,289 @@ +import { Fn, IResource, Resource, ResourceProps, Token } from 'aws-cdk-lib'; +import { CfnIndex } from 'aws-cdk-lib/aws-s3vectors'; +import { UnscopedValidationError } from 'aws-cdk-lib/core/lib/errors'; +import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; +import { Construct } from 'constructs'; +import { IVectorBucket } from './vector-bucket'; + +/** + * Represents a Vector Index + */ +export interface IIndex extends IResource { + /** + * The ARN of the vector index + * + * @attribute + */ + readonly indexArn: string; + + /** + * The name of the vector index + * + * @attribute + */ + readonly indexName: string; +} + +/** + * Distance metric for similarity search + */ +export enum DistanceMetric { + /** + * Cosine distance - measures the cosine of the angle between vectors + * + * Best for normalized vectors and when direction matters more than magnitude + */ + COSINE = 'cosine', + + /** + * Euclidean distance - measures the straight-line distance between vectors + * + * Best when both direction and magnitude are important + */ + EUCLIDEAN = 'euclidean', +} + +/** + * Data type for vectors + */ +export enum DataType { + /** + * 32-bit floating point + */ + FLOAT32 = 'float32', +} + +/** + * Properties for defining a Vector Index + */ +export interface IndexProps extends ResourceProps { + /** + * The vector bucket that will contain this index + */ + readonly vectorBucket: IVectorBucket; + + /** + * The name of the vector index + * + * Must be unique within the vector bucket, between 3 and 63 characters long, + * and begin and end with a letter or number + * + * @default - Automatically generated name + */ + readonly indexName?: string; + + /** + * The number of dimensions in the vectors + * + * All vectors added to the index must have exactly this number of values. + * Must be an integer between 1 and 4096. + */ + readonly dimension: number; + + /** + * The distance metric to use for similarity search + * + * Choose your embedding model's recommended distance metric for more accurate results. + * + * @default DistanceMetric.COSINE + */ + readonly distanceMetric?: DistanceMetric; + + /** + * The data type of the vectors + * + * @default DataType.FLOAT32 + */ + readonly dataType?: DataType; + + /** + * Metadata keys that should not be filterable + * + * These keys can be retrieved but cannot be used as query filters. + * Useful for storing additional context like original text, URLs, or timestamps + * that you want to retrieve with search results but don't need for filtering. + * + * Must be unique within the vector index, 1 to 63 characters long. + * Up to 10 non-filterable metadata keys are supported per index. + * + * @default - All metadata is filterable + */ + readonly nonFilterableMetadataKeys?: string[]; +} + +/** + * A Vector Index for organizing and querying vector data + * + * @resource AWS::S3Vectors::Index + */ +@propertyInjectable +export class Index extends Resource implements IIndex { + /** + * Property injection ID for Index + */ + public static readonly PROPERTY_INJECTION_ID: string = '@aws-cdk.aws-s3vectors-alpha.Index'; + + /** + * Import an existing vector index by ARN + * + * @param scope The parent construct + * @param id The construct ID + * @param indexArn The ARN of the index + */ + public static fromIndexArn(scope: Construct, id: string, indexArn: string): IIndex { + // ARN format: arn:partition:s3vectors:region:account:bucket/bucket-name/index/index-name + // Extract index name using Fn.split and Fn.select (index 3 = last part) + const indexName = Fn.select(3, Fn.split('/', indexArn)); + + class Import extends Resource implements IIndex { + public readonly indexArn = indexArn; + public readonly indexName = indexName; + } + + return new Import(scope, id); + } + + /** + * The ARN of the vector index + * @attribute + */ + public readonly indexArn: string; + + /** + * The name of the vector index + * @attribute + */ + public readonly indexName: string; + + /** + * The vector bucket that contains this index + */ + public readonly vectorBucket: IVectorBucket; + + /** + * The number of dimensions in the vectors + */ + public readonly dimension: number; + + /** + * The distance metric used for similarity search + */ + public readonly distanceMetric: DistanceMetric; + + /** + * The data type of the vectors + */ + public readonly dataType: DataType; + + constructor(scope: Construct, id: string, props: IndexProps) { + super(scope, id, { + physicalName: props.indexName, + }); + + // Validate configuration + this.validateIndexName(props.indexName); + this.validateDimension(props.dimension); + this.validateNonFilterableMetadataKeys(props.nonFilterableMetadataKeys); + + this.vectorBucket = props.vectorBucket; + this.dimension = props.dimension; + this.distanceMetric = props.distanceMetric ?? DistanceMetric.COSINE; + this.dataType = props.dataType ?? DataType.FLOAT32; + + const metadataConfiguration = props.nonFilterableMetadataKeys + ? { nonFilterableMetadataKeys: props.nonFilterableMetadataKeys } + : undefined; + + const resource = new CfnIndex(this, 'Resource', { + vectorBucketArn: props.vectorBucket.vectorBucketArn, + indexName: props.indexName, + dimension: this.dimension, + distanceMetric: this.distanceMetric, + dataType: this.dataType, + metadataConfiguration, + }); + + this.indexArn = resource.attrIndexArn; + this.indexName = Fn.select(3, Fn.split('/', this.indexArn)); + } + + /** + * Validate index name + * + * @param indexName The index name to validate + */ + private validateIndexName(indexName: string | undefined): void { + if (indexName == undefined || Token.isUnresolved(indexName)) { + return; // Skip validation for tokens + } + + const errors: string[] = []; + + // Length check: 3-63 characters + if (indexName.length < 3 || indexName.length > 63) { + errors.push('Index name must be between 3 and 63 characters'); + } + + // Character set check: lowercase, numbers, hyphens, dots + const illegalCharsetRegEx = /[^a-z0-9-.]/; + if (illegalCharsetRegEx.test(indexName)) { + errors.push('Index name must only contain lowercase characters, numbers, hyphens (-), and dots (.)'); + } + + // Start/end character check: lowercase or number + const allowedEdgeCharsetRegEx = /[a-z0-9]/; + if (!allowedEdgeCharsetRegEx.test(indexName.charAt(0))) { + errors.push('Index name must start with a lowercase letter or number'); + } + if (!allowedEdgeCharsetRegEx.test(indexName.charAt(indexName.length - 1))) { + errors.push('Index name must end with a lowercase letter or number'); + } + + if (errors.length > 0) { + throw new UnscopedValidationError(`Invalid index name (value: ${indexName})\n${errors.join('\n')}`); + } + } + + /** + * Validate dimension value + * + * @param dimension The dimension value to validate + */ + private validateDimension(dimension: number): void { + if (dimension < 1 || dimension > 4096) { + throw new UnscopedValidationError( + `Dimension must be between 1 and 4096, got ${dimension}. ` + + 'Choose a dimension that matches your embedding model output.', + ); + } + } + + /** + * Validate non-filterable metadata keys + * + * @param keys The non-filterable metadata keys to validate + */ + private validateNonFilterableMetadataKeys(keys: string[] | undefined): void { + if (!keys || keys.length === 0) { + return; + } + + const errors: string[] = []; + + // Maximum 10 keys + if (keys.length > 10) { + errors.push(`Maximum 10 non-filterable metadata keys are supported, got ${keys.length}`); + } + + // Each key must be 1-63 characters + keys.forEach((key, index) => { + if (key.length < 1 || key.length > 63) { + errors.push(`Non-filterable metadata key at index ${index} must be between 1 and 63 characters, got "${key}" with length ${key.length}`); + } + }); + + if (errors.length > 0) { + throw new UnscopedValidationError(`Invalid non-filterable metadata keys:\n${errors.join('\n')}`); + } + } +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/lib/index.ts b/packages/@aws-cdk/aws-s3vectors-alpha/lib/index.ts new file mode 100644 index 0000000000000..96c4ed7b5019f --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/lib/index.ts @@ -0,0 +1,7 @@ +// AWS::S3Vectors Alpha Constructs +// This module is experimental and subject to change + +export * from './vector-bucket'; +export * from './vector-bucket-policy'; +export * from './index-construct'; +export * from './permissions'; diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/lib/permissions.ts b/packages/@aws-cdk/aws-s3vectors-alpha/lib/permissions.ts new file mode 100644 index 0000000000000..6dd4ef44341a2 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/lib/permissions.ts @@ -0,0 +1,69 @@ +/** + * IAM actions for reading from vector buckets + */ +export const VECTOR_BUCKET_READ_ACCESS = [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', +]; + +/** + * IAM actions for writing to vector buckets + */ +export const VECTOR_BUCKET_WRITE_ACCESS = [ + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', + 's3vectors:CreateIndex', + 's3vectors:DeleteIndex', +]; + +/** + * IAM actions for read/write access to vector buckets + */ +export const VECTOR_BUCKET_READ_WRITE_ACCESS = [...new Set([ + ...VECTOR_BUCKET_READ_ACCESS, + ...VECTOR_BUCKET_WRITE_ACCESS, +])]; + +/** + * IAM actions for reading from vector indexes + */ +export const INDEX_READ_ACCESS = [ + 's3vectors:GetVectors', + 's3vectors:QueryVectors', +]; + +/** + * IAM actions for writing to vector indexes + */ +export const INDEX_WRITE_ACCESS = [ + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', +]; + +/** + * IAM actions for read/write access to vector indexes + */ +export const INDEX_READ_WRITE_ACCESS = [...new Set([ + ...INDEX_READ_ACCESS, + ...INDEX_WRITE_ACCESS, +])]; + +/** + * KMS actions required for reading encrypted vectors + */ +export const KEY_READ_ACCESS = ['kms:Decrypt']; + +/** + * KMS actions required for writing encrypted vectors + */ +export const KEY_WRITE_ACCESS = ['kms:Decrypt', 'kms:GenerateDataKey*']; + +/** + * KMS actions required for read/write access to encrypted vectors + */ +export const KEY_READ_WRITE_ACCESS = [...new Set([ + ...KEY_READ_ACCESS, + ...KEY_WRITE_ACCESS, +])]; diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket-policy.ts b/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket-policy.ts new file mode 100644 index 0000000000000..c8cd4b3b5df91 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket-policy.ts @@ -0,0 +1,69 @@ +import { Construct } from 'constructs'; +import { CfnVectorBucketPolicy } from 'aws-cdk-lib/aws-s3vectors'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { RemovalPolicy, Resource } from 'aws-cdk-lib/core'; +import { IVectorBucket } from './vector-bucket'; +import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource'; +import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; + +/** + * Parameters for constructing a VectorBucketPolicy + */ +export interface VectorBucketPolicyProps { + /** + * The associated vector bucket + */ + readonly vectorBucket: IVectorBucket; + /** + * The policy document for the vector bucket's resource policy + * @default undefined An empty iam.PolicyDocument will be initialized + */ + readonly resourcePolicy?: iam.PolicyDocument; + /** + * Policy to apply when the policy is removed from this stack. + * + * @default - RemovalPolicy.DESTROY. + */ + readonly removalPolicy?: RemovalPolicy; +} + +/** + * A Policy for S3 Vector Buckets. + * + * You will almost never need to use this construct directly. + * Instead, VectorBucket.addToResourcePolicy can be used to add more policies to your vector bucket directly + */ +@propertyInjectable +export class VectorBucketPolicy extends Resource { + /** Uniquely identifies this class. */ + public static readonly PROPERTY_INJECTION_ID: string = '@aws-cdk.aws-s3vectors-alpha.VectorBucketPolicy'; + /** + * The IAM PolicyDocument containing permissions represented by this policy. + */ + public readonly document: iam.PolicyDocument; + /** + * @internal The underlying policy resource. + */ + private readonly _resource: CfnVectorBucketPolicy; + + constructor(scope: Construct, id: string, props: VectorBucketPolicyProps) { + super(scope, id); + // Enhanced CDK Analytics Telemetry + addConstructMetadata(this, props); + + // Use default policy if not provided with props + this.document = props.resourcePolicy || new iam.PolicyDocument({}); + + // Use vectorBucketArn for the policy + // Note: CloudFormation accepts either vectorBucketArn or vectorBucketName, + // but using ARN is preferred for CDK constructs + this._resource = new CfnVectorBucketPolicy(this, id, { + vectorBucketArn: props.vectorBucket.vectorBucketArn, + policy: this.document, + }); + + if (props.removalPolicy) { + this._resource.applyRemovalPolicy(props.removalPolicy); + } + } +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket.ts b/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket.ts new file mode 100644 index 0000000000000..c0edc3b026cce --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/lib/vector-bucket.ts @@ -0,0 +1,460 @@ +import { ArnFormat, IResource, Resource, ResourceProps, RemovalPolicy, Stack, Token, Fn } from 'aws-cdk-lib'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import { CfnVectorBucket } from 'aws-cdk-lib/aws-s3vectors'; +import { UnscopedValidationError } from 'aws-cdk-lib/core/lib/errors'; +import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; +import { Construct } from 'constructs'; +import { + VECTOR_BUCKET_READ_ACCESS, + VECTOR_BUCKET_WRITE_ACCESS, + VECTOR_BUCKET_READ_WRITE_ACCESS, + KEY_READ_ACCESS, + KEY_WRITE_ACCESS, + KEY_READ_WRITE_ACCESS, +} from './permissions'; +import { VectorBucketPolicy } from './vector-bucket-policy'; + +/** + * Represents a Vector Bucket + */ +export interface IVectorBucket extends IResource { + /** + * The ARN of the vector bucket + * + * @attribute + */ + readonly vectorBucketArn: string; + + /** + * The name of the vector bucket + * + * @attribute + */ + readonly vectorBucketName: string; + + /** + * Optional KMS encryption key associated with this vector bucket + */ + readonly encryptionKey?: kms.IKey; + + /** + * Adds a statement to the resource policy for a principal to perform actions on this vector bucket + * + * @param permission the policy statement to be added + * @returns metadata about the execution of this method + */ + addToResourcePolicy(permission: iam.PolicyStatement): iam.AddToResourcePolicyResult; + + /** + * Grant read permissions for this vector bucket to an IAM principal + * + * If encryption is used, permission to use the key to decrypt the contents + * of the bucket will also be granted to the same principal. + * + * @param identity The principal + * @param indexId Allow the permissions to all indexes using '*' or to single index by its name + */ + grantRead(identity: iam.IGrantable, indexId: string): iam.Grant; + + /** + * Grant write permissions for this vector bucket to an IAM principal + * + * If encryption is used, permission to use the key to encrypt the contents + * of the bucket will also be granted to the same principal. + * + * @param identity The principal + * @param indexId Allow the permissions to all indexes using '*' or to single index by its name + */ + grantWrite(identity: iam.IGrantable, indexId: string): iam.Grant; + + /** + * Grant read/write permissions for this vector bucket to an IAM principal + * + * If encryption is used, permission to use the key to encrypt/decrypt the contents + * of the bucket will also be granted to the same principal. + * + * @param identity The principal + * @param indexId Allow the permissions to all indexes using '*' or to single index by its name + */ + grantReadWrite(identity: iam.IGrantable, indexId: string): iam.Grant; +} + +/** + * Encryption type for S3 Vector Bucket + */ +export enum VectorBucketEncryption { + /** + * Server-side encryption with Amazon S3 managed keys (SSE-S3) + */ + S3_MANAGED = 'AES256', + + /** + * Server-side encryption with AWS KMS managed keys (SSE-KMS) + */ + KMS = 'aws:kms', +} + +/** + * Properties for defining a Vector Bucket + */ +export interface VectorBucketProps extends ResourceProps { + /** + * The name of the vector bucket + * + * If not specified, a unique name will be generated + * + * @default - Automatically generated name + */ + readonly vectorBucketName?: string; + + /** + * The type of server-side encryption to apply to this bucket + * + * @default - VectorBucketEncryption.S3_MANAGED + */ + readonly encryption?: VectorBucketEncryption; + + /** + * External KMS key to use for bucket encryption + * + * The encryption property must be KMS for this to have any effect + * + * @default - If encryption is set to KMS and this property is undefined, + * a new KMS key will be created and associated with this bucket + */ + readonly encryptionKey?: kms.IKey; + + /** + * Policy to apply when the bucket is removed from this stack + * + * @default - The bucket will be orphaned + */ + readonly removalPolicy?: RemovalPolicy; +} + +/** + * Attributes for importing an existing Vector Bucket + */ +export interface VectorBucketAttributes { + /** + * The ARN of the vector bucket + */ + readonly vectorBucketArn: string; + + /** + * The encryption key associated with this bucket + * + * @default - No encryption key + */ + readonly encryptionKey?: kms.IKey; +} + +/** + * Base class for Vector Bucket + */ +abstract class VectorBucketBase extends Resource implements IVectorBucket { + public abstract readonly vectorBucketArn: string; + public abstract readonly vectorBucketName: string; + public abstract readonly encryptionKey?: kms.IKey; + + /** + * The resource policy associated with this vector bucket. + * + * If `autoCreatePolicy` is true, a `VectorBucketPolicy` will be created upon the + * first call to addToResourcePolicy. + */ + public abstract vectorBucketPolicy?: VectorBucketPolicy; + + /** + * Indicates if a vector bucket resource policy should automatically be created upon + * the first call to `addToResourcePolicy`. + */ + protected abstract autoCreatePolicy: boolean; + + public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult { + if (!this.vectorBucketPolicy && this.autoCreatePolicy) { + this.vectorBucketPolicy = new VectorBucketPolicy(this, 'DefaultPolicy', { + vectorBucket: this, + }); + } + + if (this.vectorBucketPolicy) { + this.vectorBucketPolicy.document.addStatements(statement); + return { statementAdded: true, policyDependable: this.vectorBucketPolicy }; + } + + return { statementAdded: false }; + } + + public grantRead(identity: iam.IGrantable, indexId: string): iam.Grant { + return this.grant( + identity, + VECTOR_BUCKET_READ_ACCESS, + KEY_READ_ACCESS, + this.vectorBucketArn, + `${this.vectorBucketArn}/index/${indexId}`, + ); + } + + public grantWrite(identity: iam.IGrantable, indexId: string): iam.Grant { + return this.grant( + identity, + VECTOR_BUCKET_WRITE_ACCESS, + KEY_WRITE_ACCESS, + this.vectorBucketArn, + `${this.vectorBucketArn}/index/${indexId}`, + ); + } + + public grantReadWrite(identity: iam.IGrantable, indexId: string): iam.Grant { + return this.grant( + identity, + VECTOR_BUCKET_READ_WRITE_ACCESS, + KEY_READ_WRITE_ACCESS, + this.vectorBucketArn, + `${this.vectorBucketArn}/index/${indexId}`, + ); + } + + private grant( + grantee: iam.IGrantable, + bucketActions: string[], + keyActions: string[], + resourceArn: string, + ...otherResourceArns: (string | undefined)[] + ): iam.Grant { + const resources = [resourceArn, ...otherResourceArns].filter((arn): arn is string => arn != undefined); + + const grant = iam.Grant.addToPrincipalOrResource({ + grantee, + actions: bucketActions, + resourceArns: resources, + resource: this, + }); + + if (this.encryptionKey && keyActions && keyActions.length !== 0) { + this.encryptionKey.grant(grantee, ...keyActions); + } + + return grant; + } +} + +/** + * An S3 Vector Bucket for storing and querying vector data + * + * @resource AWS::S3Vectors::VectorBucket + */ +@propertyInjectable +export class VectorBucket extends VectorBucketBase { + /** + * Property injection ID for VectorBucket + */ + public static readonly PROPERTY_INJECTION_ID: string = '@aws-cdk.aws-s3vectors-alpha.VectorBucket'; + + /** + * Import an existing vector bucket by ARN + * + * @param scope The parent construct + * @param id The construct ID + * @param vectorBucketArn The ARN of the vector bucket + */ + public static fromVectorBucketArn(scope: Construct, id: string, vectorBucketArn: string): IVectorBucket { + return VectorBucket.fromVectorBucketAttributes(scope, id, { vectorBucketArn }); + } + + /** + * Import an existing vector bucket by name + * + * @param scope The parent construct + * @param id The construct ID + * @param vectorBucketName The name of the vector bucket + */ + public static fromVectorBucketName(scope: Construct, id: string, vectorBucketName: string): IVectorBucket { + const stack = Stack.of(scope); + const vectorBucketArn = stack.formatArn({ + service: 's3vectors', + resource: 'bucket', + resourceName: vectorBucketName, + }); + + class Import extends VectorBucketBase { + public readonly vectorBucketArn = vectorBucketArn; + public readonly vectorBucketName = vectorBucketName; + public readonly encryptionKey = undefined; + public readonly vectorBucketPolicy?: VectorBucketPolicy; + protected autoCreatePolicy: boolean = false; + } + + return new Import(scope, id); + } + + /** + * Import an existing vector bucket using attributes + * + * @param scope The parent construct + * @param id The construct ID + * @param attrs The attributes of the vector bucket + */ + public static fromVectorBucketAttributes(scope: Construct, id: string, attrs: VectorBucketAttributes): IVectorBucket { + const stack = Stack.of(scope); + const arnComponents = stack.splitArn(attrs.vectorBucketArn, ArnFormat.SLASH_RESOURCE_NAME); + const bucketName = arnComponents.resourceName; + + if (!bucketName) { + throw new UnscopedValidationError(`Cannot extract bucket name from ARN: ${attrs.vectorBucketArn}`); + } + + class Import extends VectorBucketBase { + public readonly vectorBucketArn = attrs.vectorBucketArn; + public readonly vectorBucketName = bucketName!; + public readonly encryptionKey = attrs.encryptionKey; + public readonly vectorBucketPolicy?: VectorBucketPolicy; + protected autoCreatePolicy: boolean = false; + } + + return new Import(scope, id); + } + + public readonly vectorBucketArn: string; + public readonly vectorBucketName: string; + public readonly encryptionKey?: kms.IKey; + + /** + * The resource policy associated with this vector bucket. + * + * If `autoCreatePolicy` is true, a `VectorBucketPolicy` will be created upon the + * first call to addToResourcePolicy. + */ + public vectorBucketPolicy?: VectorBucketPolicy; + + /** + * Indicates if a vector bucket resource policy should automatically be created upon + * the first call to `addToResourcePolicy`. + */ + protected autoCreatePolicy: boolean = true; + + constructor(scope: Construct, id: string, props: VectorBucketProps = {}) { + super(scope, id, { + physicalName: props.vectorBucketName, + }); + + // Validate bucket name + this.validateVectorBucketName(props.vectorBucketName); + + // Parse encryption configuration + const { bucketEncryption, encryptionKey } = this.parseEncryption(props); + this.encryptionKey = encryptionKey; + + // Create the vector bucket + const resource = new CfnVectorBucket(this, 'Resource', { + vectorBucketName: props.vectorBucketName, + encryptionConfiguration: bucketEncryption, + }); + + if (props.removalPolicy) { + resource.applyRemovalPolicy(props.removalPolicy); + } + + this.vectorBucketArn = resource.attrVectorBucketArn; + this.vectorBucketName = Fn.select(1, Fn.split('/', this.vectorBucketArn)); + } + + private parseEncryption(props: VectorBucketProps): { + bucketEncryption?: CfnVectorBucket.EncryptionConfigurationProperty; + encryptionKey?: kms.IKey; + } { + const encryptionType = props.encryption; + let key = props.encryptionKey; + + // If encryption is undefined + if (encryptionType === undefined) { + if (key === undefined) { + // No encryption specified, use default S3 managed + return { bucketEncryption: undefined, encryptionKey: undefined }; + } else { + // Key provided without encryption type, use KMS + return { + bucketEncryption: { + sseType: VectorBucketEncryption.KMS, + kmsKeyArn: key.keyArn, + }, + encryptionKey: key, + }; + } + } + + // KMS encryption + if (encryptionType === VectorBucketEncryption.KMS) { + if (key === undefined) { + // Create a new key + key = new kms.Key(this, 'Key', { + description: `Created by ${this.node.path}`, + enableKeyRotation: true, + }); + } + return { + bucketEncryption: { + sseType: VectorBucketEncryption.KMS, + kmsKeyArn: key.keyArn, + }, + encryptionKey: key, + }; + } + + // S3 managed encryption + if (encryptionType === VectorBucketEncryption.S3_MANAGED) { + if (key !== undefined) { + throw new UnscopedValidationError( + 'Expected encryption = VectorBucketEncryption.KMS with user provided encryption key. ' + + 'Use VectorBucketEncryption.KMS or remove the encryptionKey property.', + ); + } + return { + bucketEncryption: { + sseType: VectorBucketEncryption.S3_MANAGED, + }, + }; + } + + return { bucketEncryption: undefined }; + } + + /** + * Validate vector bucket name + * + * @param bucketName The bucket name to validate + */ + private validateVectorBucketName(bucketName: string | undefined): void { + if (bucketName == undefined || Token.isUnresolved(bucketName)) { + return; // Skip validation for tokens + } + + const errors: string[] = []; + + // Length check: 3-63 characters + if (bucketName.length < 3 || bucketName.length > 63) { + errors.push('Bucket name must be at least 3 and no more than 63 characters'); + } + + // Character set check: lowercase, numbers, hyphens only + const illegalCharsetRegEx = /[^a-z0-9-]/; + if (illegalCharsetRegEx.test(bucketName)) { + errors.push('Bucket name must only contain lowercase characters, numbers, and hyphens (-)'); + } + + // Start/end character check: lowercase or number + const allowedEdgeCharsetRegEx = /[a-z0-9]/; + if (!allowedEdgeCharsetRegEx.test(bucketName.charAt(0))) { + errors.push('Bucket name must start with a lowercase letter or number'); + } + if (!allowedEdgeCharsetRegEx.test(bucketName.charAt(bucketName.length - 1))) { + errors.push('Bucket name must end with a lowercase letter or number'); + } + + if (errors.length > 0) { + throw new UnscopedValidationError(`Invalid S3 vector bucket name (value: ${bucketName})\n${errors.join('\n')}`); + } + } +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/package.json b/packages/@aws-cdk/aws-s3vectors-alpha/package.json new file mode 100644 index 0000000000000..58f87c5545d5f --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/package.json @@ -0,0 +1,107 @@ +{ + "name": "@aws-cdk/aws-s3vectors-alpha", + "version": "0.0.0", + "private": false, + "description": "The CDK Construct Library for AWS::S3Vectors", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.s3vectors.alpha", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "s3vectors-alpha" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.S3Vectors.Alpha", + "packageId": "Amazon.CDK.AWS.S3Vectors.Alpha", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-s3vectors-alpha", + "module": "aws_cdk.aws_s3vectors_alpha", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ] + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + }, + "tsconfig": "tsconfig.json", + "validateTsconfig": "minimal" + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-s3vectors-alpha" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "integ-runner", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "s3vectors", + "vector", + "alpha" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/integ-tests-alpha": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^29.5.14", + "jest": "^29.7.0", + "aws-cdk-lib": "0.0.0", + "constructs": "^10.0.0" + }, + "peerDependencies": { + "aws-cdk-lib": "^0.0.0", + "constructs": "^10.0.0" + }, + "engines": { + "node": ">= 18.0.0" + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + }, + "homepage": "https://github.com/aws/aws-cdk" +} diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/index.test.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/index.test.ts new file mode 100644 index 0000000000000..9771110af7ccc --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/index.test.ts @@ -0,0 +1,233 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as cdk from 'aws-cdk-lib'; +import { Stack } from 'aws-cdk-lib/core'; +import * as s3vectors from '../lib'; + +describe('Index', () => { + let stack: Stack; + let vectorBucket: s3vectors.VectorBucket; + + beforeEach(() => { + stack = new Stack(); + vectorBucket = new s3vectors.VectorBucket(stack, 'MyVectorBucket'); + }); + + describe('Basic functionality', () => { + test('creates an Index with required properties', () => { + // WHEN + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + }); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::S3Vectors::Index', 1); + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::Index', { + Dimension: 1536, + DistanceMetric: 'cosine', + DataType: 'float32', + }); + }); + + test('creates an Index with Euclidean distance metric', () => { + // WHEN + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 768, + distanceMetric: s3vectors.DistanceMetric.EUCLIDEAN, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::Index', { + Dimension: 768, + DistanceMetric: 'euclidean', + }); + }); + + test('creates an Index with non-filterable metadata keys', () => { + // WHEN + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1024, + nonFilterableMetadataKeys: ['original-text', 'source-url'], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::Index', { + MetadataConfiguration: { + NonFilterableMetadataKeys: ['original-text', 'source-url'], + }, + }); + }); + + test('can import from ARN', () => { + // WHEN + const imported = s3vectors.Index.fromIndexArn( + stack, + 'ImportedIndex', + 'arn:aws:s3vectors:us-east-1:123456789012:bucket/my-bucket/index/my-index', + ); + + // THEN + expect(imported.indexArn).toBe('arn:aws:s3vectors:us-east-1:123456789012:bucket/my-bucket/index/my-index'); + expect(imported.indexName).toBe('my-index'); + }); + }); + + describe('Validation', () => { + test('validates dimension range', () => { + // THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 0, + }); + }).toThrow(/Dimension must be between 1 and 4096/); + + expect(() => { + new s3vectors.Index(stack, 'MyIndex2', { + vectorBucket, + dimension: 5000, + }); + }).toThrow(/Dimension must be between 1 and 4096/); + }); + + test('accepts minimum dimension value', () => { + // WHEN/THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1, + }); + }).not.toThrow(); + }); + + test('accepts maximum dimension value', () => { + // WHEN/THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 4096, + }); + }).not.toThrow(); + }); + + test('rejects negative dimension', () => { + // WHEN/THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: -1, + }); + }).toThrow(/Dimension must be between 1 and 4096/); + }); + + test('validates non-filterable metadata keys count', () => { + // THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + nonFilterableMetadataKeys: Array.from({ length: 11 }, (_, i) => `key${i}`), + }); + }).toThrow(/Maximum 10 non-filterable metadata keys/); + }); + + test('allows exactly 10 non-filterable metadata keys', () => { + // WHEN/THEN - exactly 10 keys should be valid + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + nonFilterableMetadataKeys: Array.from({ length: 10 }, (_, i) => `key${i}`), + }); + }).not.toThrow(); + }); + + test('validates non-filterable metadata key length', () => { + // WHEN/THEN - empty key + expect(() => { + new s3vectors.Index(stack, 'Index1', { + vectorBucket, + dimension: 1536, + nonFilterableMetadataKeys: [''], + }); + }).toThrow(/must be between 1 and 63 characters/); + + // WHEN/THEN - key too long (64 characters) + expect(() => { + new s3vectors.Index(stack, 'Index2', { + vectorBucket, + dimension: 1536, + nonFilterableMetadataKeys: ['a'.repeat(64)], + }); + }).toThrow(/must be between 1 and 63 characters/); + + // WHEN/THEN - valid key (63 characters) + expect(() => { + new s3vectors.Index(stack, 'Index3', { + vectorBucket, + dimension: 1536, + nonFilterableMetadataKeys: ['a'.repeat(63)], + }); + }).not.toThrow(); + }); + + test('validates index name with dots and hyphens', () => { + // WHEN/THEN - valid names with dots and hyphens + expect(() => { + new s3vectors.Index(stack, 'Index1', { + vectorBucket, + dimension: 1536, + indexName: 'my-index.v1', + }); + }).not.toThrow(); + + expect(() => { + new s3vectors.Index(stack, 'Index2', { + vectorBucket, + dimension: 1536, + indexName: 'my.index-v2', + }); + }).not.toThrow(); + }); + + test('rejects index name starting with dot', () => { + // WHEN/THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + indexName: '.invalid', + }); + }).toThrow(/must start with a lowercase letter or number/); + }); + + test('rejects index name ending with hyphen', () => { + // WHEN/THEN + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + indexName: 'invalid-', + }); + }).toThrow(/must end with a lowercase letter or number/); + }); + + test('handles token values in index name validation', () => { + // GIVEN + const tokenName = new cdk.CfnParameter(stack, 'IndexNameParameter', { + type: 'String', + }).valueAsString; + + // WHEN/THEN - should not throw + expect(() => { + new s3vectors.Index(stack, 'MyIndex', { + vectorBucket, + dimension: 1536, + indexName: tokenName, + }); + }).not.toThrow(); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.assets.json new file mode 100644 index 0000000000000..5acd2d186804b --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "1c023e895f9444cad8fcdecb0992a1fdac01168b02fec17918a482297e90e63c": { + "displayName": "KeyWithKMSEncryptionTypeTest Template", + "source": { + "path": "KeyWithKMSEncryptionTypeTest.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-80b4ad64": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "1c023e895f9444cad8fcdecb0992a1fdac01168b02fec17918a482297e90e63c.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.template.json new file mode 100644 index 0000000000000..11a11092539e3 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/KeyWithKMSEncryptionTypeTest.template.json @@ -0,0 +1,90 @@ +{ + "Resources": { + "Key961B73FD": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "Properties": { + "EncryptionConfiguration": { + "KmsKeyArn": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + }, + "SseType": "aws:kms" + }, + "VectorBucketName": "integ-vb-key-with-type" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.assets.json new file mode 100644 index 0000000000000..73b95ad3760e6 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "3530cdeada3de03e1adf12769d88d98a3b3fa615827dd98ee319ef51c2e1f89c": { + "displayName": "OnlyEncryptionKeyTest Template", + "source": { + "path": "OnlyEncryptionKeyTest.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-dcde71dd": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3530cdeada3de03e1adf12769d88d98a3b3fa615827dd98ee319ef51c2e1f89c.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.template.json new file mode 100644 index 0000000000000..df2971a29703b --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyEncryptionKeyTest.template.json @@ -0,0 +1,90 @@ +{ + "Resources": { + "Key961B73FD": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "Properties": { + "EncryptionConfiguration": { + "KmsKeyArn": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + }, + "SseType": "aws:kms" + }, + "VectorBucketName": "integ-vb-key-only" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.assets.json new file mode 100644 index 0000000000000..a85391ee196a9 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "d613259e9a63ac7dbc3c4f1cd227063131f7d95765ad3bf2a3fad8a68e3a385a": { + "displayName": "OnlyKMSEncryptionTypeTest Template", + "source": { + "path": "OnlyKMSEncryptionTypeTest.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-f01ef860": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "d613259e9a63ac7dbc3c4f1cd227063131f7d95765ad3bf2a3fad8a68e3a385a.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.template.json new file mode 100644 index 0000000000000..11fd34a82088d --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyKMSEncryptionTypeTest.template.json @@ -0,0 +1,92 @@ +{ + "Resources": { + "VectorBucketKey1279B8EA": { + "Type": "AWS::KMS::Key", + "Properties": { + "Description": "Created by OnlyKMSEncryptionTypeTest/VectorBucket", + "EnableKeyRotation": true, + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "Properties": { + "EncryptionConfiguration": { + "KmsKeyArn": { + "Fn::GetAtt": [ + "VectorBucketKey1279B8EA", + "Arn" + ] + }, + "SseType": "aws:kms" + }, + "VectorBucketName": "integ-vb-kms-encryption-type-only" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.assets.json new file mode 100644 index 0000000000000..10b6371cd98a7 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "538abcb3639517e6b5a0fe558bf6fa37768693d6b624b802930f90272162a1a8": { + "displayName": "OnlyS3ManagedEncryptionTest Template", + "source": { + "path": "OnlyS3ManagedEncryptionTest.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-c6d76a7f": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "538abcb3639517e6b5a0fe558bf6fa37768693d6b624b802930f90272162a1a8.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.template.json new file mode 100644 index 0000000000000..80954cb597f65 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/OnlyS3ManagedEncryptionTest.template.json @@ -0,0 +1,49 @@ +{ + "Resources": { + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "Properties": { + "EncryptionConfiguration": { + "SseType": "AES256" + }, + "VectorBucketName": "integ-vb-s3-managed-encryption-type-only" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets.json new file mode 100644 index 0000000000000..fa0251a4b9a41 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A Template", + "source": { + "path": "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/integ.json new file mode 100644 index 0000000000000..0e4eabfab4b75 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/integ.json @@ -0,0 +1,16 @@ +{ + "version": "48.0.0", + "testCases": { + "VectorBucketEncryptionIntegTest/DefaultTest": { + "stacks": [ + "OnlyEncryptionKeyTest", + "OnlyKMSEncryptionTypeTest", + "KeyWithKMSEncryptionTypeTest", + "OnlyS3ManagedEncryptionTest" + ], + "assertionStack": "VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert", + "assertionStackName": "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/manifest.json new file mode 100644 index 0000000000000..2b93614ae0fab --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/manifest.json @@ -0,0 +1,808 @@ +{ + "version": "48.0.0", + "artifacts": { + "OnlyEncryptionKeyTest.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "OnlyEncryptionKeyTest.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "OnlyEncryptionKeyTest": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "OnlyEncryptionKeyTest.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3530cdeada3de03e1adf12769d88d98a3b3fa615827dd98ee319ef51c2e1f89c.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "OnlyEncryptionKeyTest.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "OnlyEncryptionKeyTest.assets" + ], + "metadata": { + "/OnlyEncryptionKeyTest/Key": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/OnlyEncryptionKeyTest/Key/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Key961B73FD" + } + ], + "/OnlyEncryptionKeyTest/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/OnlyEncryptionKeyTest/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/OnlyEncryptionKeyTest/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "OnlyEncryptionKeyTest" + }, + "OnlyKMSEncryptionTypeTest.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "OnlyKMSEncryptionTypeTest.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "OnlyKMSEncryptionTypeTest": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "OnlyKMSEncryptionTypeTest.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d613259e9a63ac7dbc3c4f1cd227063131f7d95765ad3bf2a3fad8a68e3a385a.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "OnlyKMSEncryptionTypeTest.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "OnlyKMSEncryptionTypeTest.assets" + ], + "metadata": { + "/OnlyKMSEncryptionTypeTest/VectorBucket/Key": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "description": "*", + "enableKeyRotation": true + } + } + ], + "/OnlyKMSEncryptionTypeTest/VectorBucket/Key/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucketKey1279B8EA" + } + ], + "/OnlyKMSEncryptionTypeTest/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/OnlyKMSEncryptionTypeTest/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/OnlyKMSEncryptionTypeTest/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "OnlyKMSEncryptionTypeTest" + }, + "KeyWithKMSEncryptionTypeTest.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "KeyWithKMSEncryptionTypeTest.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "KeyWithKMSEncryptionTypeTest": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "KeyWithKMSEncryptionTypeTest.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1c023e895f9444cad8fcdecb0992a1fdac01168b02fec17918a482297e90e63c.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "KeyWithKMSEncryptionTypeTest.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "KeyWithKMSEncryptionTypeTest.assets" + ], + "metadata": { + "/KeyWithKMSEncryptionTypeTest/Key": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/KeyWithKMSEncryptionTypeTest/Key/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Key961B73FD" + } + ], + "/KeyWithKMSEncryptionTypeTest/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/KeyWithKMSEncryptionTypeTest/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/KeyWithKMSEncryptionTypeTest/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "KeyWithKMSEncryptionTypeTest" + }, + "OnlyS3ManagedEncryptionTest.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "OnlyS3ManagedEncryptionTest.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "OnlyS3ManagedEncryptionTest": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "OnlyS3ManagedEncryptionTest.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/538abcb3639517e6b5a0fe558bf6fa37768693d6b624b802930f90272162a1a8.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "OnlyS3ManagedEncryptionTest.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "OnlyS3ManagedEncryptionTest.assets" + ], + "metadata": { + "/OnlyS3ManagedEncryptionTest/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/OnlyS3ManagedEncryptionTest/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/OnlyS3ManagedEncryptionTest/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "OnlyS3ManagedEncryptionTest" + }, + "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "VectorBucketEncryptionIntegTestDefaultTestDeployAssert7860388A.assets" + ], + "metadata": { + "/VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/tree.json new file mode 100644 index 0000000000000..522e72e99e202 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"OnlyEncryptionKeyTest":{"id":"OnlyEncryptionKeyTest","path":"OnlyEncryptionKeyTest","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Key":{"id":"Key","path":"OnlyEncryptionKeyTest/Key","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.Key","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"OnlyEncryptionKeyTest/Key/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.CfnKey","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::KMS::Key","aws:cdk:cloudformation:props":{"keyPolicy":{"Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::",{"Ref":"AWS::AccountId"},":root"]]}},"Resource":"*"}],"Version":"2012-10-17"}}}}}},"VectorBucket":{"id":"VectorBucket","path":"OnlyEncryptionKeyTest/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"OnlyEncryptionKeyTest/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{"encryptionConfiguration":{"sseType":"aws:kms","kmsKeyArn":{"Fn::GetAtt":["Key961B73FD","Arn"]}},"vectorBucketName":"integ-vb-key-only"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"OnlyEncryptionKeyTest/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"OnlyEncryptionKeyTest/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"OnlyKMSEncryptionTypeTest":{"id":"OnlyKMSEncryptionTypeTest","path":"OnlyKMSEncryptionTypeTest","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VectorBucket":{"id":"VectorBucket","path":"OnlyKMSEncryptionTypeTest/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Key":{"id":"Key","path":"OnlyKMSEncryptionTypeTest/VectorBucket/Key","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.Key","version":"0.0.0","metadata":[{"description":"*","enableKeyRotation":true}]},"children":{"Resource":{"id":"Resource","path":"OnlyKMSEncryptionTypeTest/VectorBucket/Key/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.CfnKey","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::KMS::Key","aws:cdk:cloudformation:props":{"description":"Created by OnlyKMSEncryptionTypeTest/VectorBucket","enableKeyRotation":true,"keyPolicy":{"Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::",{"Ref":"AWS::AccountId"},":root"]]}},"Resource":"*"}],"Version":"2012-10-17"}}}}}},"Resource":{"id":"Resource","path":"OnlyKMSEncryptionTypeTest/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{"encryptionConfiguration":{"sseType":"aws:kms","kmsKeyArn":{"Fn::GetAtt":["VectorBucketKey1279B8EA","Arn"]}},"vectorBucketName":"integ-vb-kms-encryption-type-only"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"OnlyKMSEncryptionTypeTest/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"OnlyKMSEncryptionTypeTest/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"KeyWithKMSEncryptionTypeTest":{"id":"KeyWithKMSEncryptionTypeTest","path":"KeyWithKMSEncryptionTypeTest","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Key":{"id":"Key","path":"KeyWithKMSEncryptionTypeTest/Key","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.Key","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"KeyWithKMSEncryptionTypeTest/Key/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_kms.CfnKey","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::KMS::Key","aws:cdk:cloudformation:props":{"keyPolicy":{"Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::",{"Ref":"AWS::AccountId"},":root"]]}},"Resource":"*"}],"Version":"2012-10-17"}}}}}},"VectorBucket":{"id":"VectorBucket","path":"KeyWithKMSEncryptionTypeTest/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"KeyWithKMSEncryptionTypeTest/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{"encryptionConfiguration":{"sseType":"aws:kms","kmsKeyArn":{"Fn::GetAtt":["Key961B73FD","Arn"]}},"vectorBucketName":"integ-vb-key-with-type"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"KeyWithKMSEncryptionTypeTest/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"KeyWithKMSEncryptionTypeTest/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"OnlyS3ManagedEncryptionTest":{"id":"OnlyS3ManagedEncryptionTest","path":"OnlyS3ManagedEncryptionTest","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VectorBucket":{"id":"VectorBucket","path":"OnlyS3ManagedEncryptionTest/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"OnlyS3ManagedEncryptionTest/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{"encryptionConfiguration":{"sseType":"AES256"},"vectorBucketName":"integ-vb-s3-managed-encryption-type-only"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"OnlyS3ManagedEncryptionTest/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"OnlyS3ManagedEncryptionTest/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"VectorBucketEncryptionIntegTest":{"id":"VectorBucketEncryptionIntegTest","path":"VectorBucketEncryptionIntegTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"VectorBucketEncryptionIntegTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"VectorBucketEncryptionIntegTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"VectorBucketEncryptionIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.ts new file mode 100644 index 0000000000000..d75b3111426d1 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-encryption.ts @@ -0,0 +1,84 @@ +import * as core from 'aws-cdk-lib/core'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as s3vectors from '../lib'; +import { Construct } from 'constructs'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +/** + * Test cases for vector bucket encryption: + * + * | props.encryption | props.encryptionKey | bucketEncryption (expected) | encryptionKey (expected) | + * |------------------|---------------------|-----------------------------|-------------------------------| + * | undefined | k | aws:kms | k | + * | KMS | undefined | aws:kms | new key (auto-generated) | + * | KMS | k | aws:kms | k | + * | S3_MANAGED | undefined | AES256 | undefined | + */ + +class OnlyEncryptionKeyTest extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + public readonly key: kms.IKey; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + this.key = new kms.Key(this, 'Key', {}); + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + vectorBucketName: 'integ-vb-key-only', + encryptionKey: this.key, + removalPolicy: core.RemovalPolicy.DESTROY, + }); + } +} + +class OnlyKMSEncryptionTypeTest extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + vectorBucketName: 'integ-vb-kms-encryption-type-only', + encryption: s3vectors.VectorBucketEncryption.KMS, + removalPolicy: core.RemovalPolicy.DESTROY, + }); + } +} + +class KeyWithKMSEncryptionTypeTest extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + public readonly key: kms.IKey; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + this.key = new kms.Key(this, 'Key', {}); + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + vectorBucketName: 'integ-vb-key-with-type', + encryption: s3vectors.VectorBucketEncryption.KMS, + encryptionKey: this.key, + removalPolicy: core.RemovalPolicy.DESTROY, + }); + } +} + +class OnlyS3ManagedEncryptionTest extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + vectorBucketName: 'integ-vb-s3-managed-encryption-type-only', + encryption: s3vectors.VectorBucketEncryption.S3_MANAGED, + removalPolicy: core.RemovalPolicy.DESTROY, + }); + } +} + +const app = new core.App(); + +const testCases = [ + new OnlyEncryptionKeyTest(app, 'OnlyEncryptionKeyTest'), + new OnlyKMSEncryptionTypeTest(app, 'OnlyKMSEncryptionTypeTest'), + new KeyWithKMSEncryptionTypeTest(app, 'KeyWithKMSEncryptionTypeTest'), + new OnlyS3ManagedEncryptionTest(app, 'OnlyS3ManagedEncryptionTest'), +]; + +new IntegTest(app, 'VectorBucketEncryptionIntegTest', { testCases }); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets.json new file mode 100644 index 0000000000000..3e4dc8963c86d --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197 Template", + "source": { + "path": "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.assets.json new file mode 100644 index 0000000000000..dc72afd32a3da --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "6549d68acadecaf0fc61d877bdff8052d9434c439b20730ce6a1c66e96f24df5": { + "displayName": "VectorBucketWithGrantsTestStack Template", + "source": { + "path": "VectorBucketWithGrantsTestStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-16f7d907": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6549d68acadecaf0fc61d877bdff8052d9434c439b20730ce6a1c66e96f24df5.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.template.json new file mode 100644 index 0000000000000..712de4217f396 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/VectorBucketWithGrantsTestStack.template.json @@ -0,0 +1,274 @@ +{ + "Resources": { + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "Properties": { + "VectorBucketName": "vector-bucket-with-grants" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Index4A79713B": { + "Type": "AWS::S3Vectors::Index", + "Properties": { + "DataType": "float32", + "Dimension": 1536, + "DistanceMetric": "cosine", + "IndexName": "test-index", + "VectorBucketArn": { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + } + } + }, + "ReadRoleF724156F": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Description": "Role with read permissions to vector bucket" + } + }, + "ReadRoleDefaultPolicy8F6E34EE": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3vectors:GetIndex", + "s3vectors:GetVectors", + "s3vectors:ListIndexes", + "s3vectors:ListVectors" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + "/index/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + "/index/test-index" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ReadRoleDefaultPolicy8F6E34EE", + "Roles": [ + { + "Ref": "ReadRoleF724156F" + } + ] + } + }, + "WriteRoleDF5CC624": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Description": "Role with write permissions to vector bucket" + } + }, + "WriteRoleDefaultPolicy7F8B4A73": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3vectors:CreateIndex", + "s3vectors:DeleteIndex", + "s3vectors:DeleteVectors", + "s3vectors:PutVectors" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + "/index/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "WriteRoleDefaultPolicy7F8B4A73", + "Roles": [ + { + "Ref": "WriteRoleDF5CC624" + } + ] + } + }, + "ReadWriteRole39A63897": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Description": "Role with read/write permissions to vector bucket" + } + }, + "ReadWriteRoleDefaultPolicy82ECA137": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3vectors:CreateIndex", + "s3vectors:DeleteIndex", + "s3vectors:DeleteVectors", + "s3vectors:GetIndex", + "s3vectors:GetVectors", + "s3vectors:ListIndexes", + "s3vectors:ListVectors", + "s3vectors:PutVectors" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + "/index/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ReadWriteRoleDefaultPolicy82ECA137", + "Roles": [ + { + "Ref": "ReadWriteRole39A63897" + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/integ.json new file mode 100644 index 0000000000000..30e6dc87078dc --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "VectorBucketWithGrantsIntegTest/DefaultTest": { + "stacks": [ + "VectorBucketWithGrantsTestStack" + ], + "assertionStack": "VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert", + "assertionStackName": "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/manifest.json new file mode 100644 index 0000000000000..51c0ea7534276 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/manifest.json @@ -0,0 +1,881 @@ +{ + "version": "48.0.0", + "artifacts": { + "VectorBucketWithGrantsTestStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "VectorBucketWithGrantsTestStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "VectorBucketWithGrantsTestStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "VectorBucketWithGrantsTestStack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6549d68acadecaf0fc61d877bdff8052d9434c439b20730ce6a1c66e96f24df5.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "VectorBucketWithGrantsTestStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "VectorBucketWithGrantsTestStack.assets" + ], + "metadata": { + "/VectorBucketWithGrantsTestStack/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/VectorBucketWithGrantsTestStack/Index/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Index4A79713B" + } + ], + "/VectorBucketWithGrantsTestStack/ReadRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + }, + "description": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/ReadRole/ImportReadRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/VectorBucketWithGrantsTestStack/ReadRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ReadRoleF724156F" + } + ], + "/VectorBucketWithGrantsTestStack/ReadRole/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/ReadRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ReadRoleDefaultPolicy8F6E34EE" + } + ], + "/VectorBucketWithGrantsTestStack/WriteRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + }, + "description": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/WriteRole/ImportWriteRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/VectorBucketWithGrantsTestStack/WriteRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WriteRoleDF5CC624" + } + ], + "/VectorBucketWithGrantsTestStack/WriteRole/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/WriteRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WriteRoleDefaultPolicy7F8B4A73" + } + ], + "/VectorBucketWithGrantsTestStack/ReadWriteRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + }, + "description": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/ReadWriteRole/ImportReadWriteRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/VectorBucketWithGrantsTestStack/ReadWriteRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ReadWriteRole39A63897" + } + ], + "/VectorBucketWithGrantsTestStack/ReadWriteRole/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + } + ], + "/VectorBucketWithGrantsTestStack/ReadWriteRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ReadWriteRoleDefaultPolicy82ECA137" + } + ], + "/VectorBucketWithGrantsTestStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/VectorBucketWithGrantsTestStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "VectorBucketWithGrantsTestStack" + }, + "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "VectorBucketWithGrantsIntegTestDefaultTestDeployAssert84C30197.assets" + ], + "metadata": { + "/VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/tree.json new file mode 100644 index 0000000000000..783cfcdaa7597 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"VectorBucketWithGrantsTestStack":{"id":"VectorBucketWithGrantsTestStack","path":"VectorBucketWithGrantsTestStack","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VectorBucket":{"id":"VectorBucket","path":"VectorBucketWithGrantsTestStack/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{"vectorBucketName":"vector-bucket-with-grants"}}}}},"Index":{"id":"Index","path":"VectorBucketWithGrantsTestStack/Index","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.Index","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/Index/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnIndex","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::Index","aws:cdk:cloudformation:props":{"dataType":"float32","dimension":1536,"distanceMetric":"cosine","indexName":"test-index","vectorBucketArn":{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]}}}}}},"ReadRole":{"id":"ReadRole","path":"VectorBucketWithGrantsTestStack/ReadRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"description":"*"},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportReadRole":{"id":"ImportReadRole","path":"VectorBucketWithGrantsTestStack/ReadRole/ImportReadRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/ReadRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"description":"Role with read permissions to vector bucket"}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"VectorBucketWithGrantsTestStack/ReadRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/ReadRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["s3vectors:GetIndex","s3vectors:GetVectors","s3vectors:ListIndexes","s3vectors:ListVectors"],"Effect":"Allow","Resource":[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},{"Fn::Join":["",[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},"/index/*"]]},{"Fn::Join":["",[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},"/index/test-index"]]}]}],"Version":"2012-10-17"},"policyName":"ReadRoleDefaultPolicy8F6E34EE","roles":[{"Ref":"ReadRoleF724156F"}]}}}}}}},"WriteRole":{"id":"WriteRole","path":"VectorBucketWithGrantsTestStack/WriteRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"description":"*"},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportWriteRole":{"id":"ImportWriteRole","path":"VectorBucketWithGrantsTestStack/WriteRole/ImportWriteRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/WriteRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"description":"Role with write permissions to vector bucket"}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"VectorBucketWithGrantsTestStack/WriteRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/WriteRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["s3vectors:CreateIndex","s3vectors:DeleteIndex","s3vectors:DeleteVectors","s3vectors:PutVectors"],"Effect":"Allow","Resource":[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},{"Fn::Join":["",[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},"/index/*"]]}]}],"Version":"2012-10-17"},"policyName":"WriteRoleDefaultPolicy7F8B4A73","roles":[{"Ref":"WriteRoleDF5CC624"}]}}}}}}},"ReadWriteRole":{"id":"ReadWriteRole","path":"VectorBucketWithGrantsTestStack/ReadWriteRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"description":"*"},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportReadWriteRole":{"id":"ImportReadWriteRole","path":"VectorBucketWithGrantsTestStack/ReadWriteRole/ImportReadWriteRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/ReadWriteRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"description":"Role with read/write permissions to vector bucket"}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"VectorBucketWithGrantsTestStack/ReadWriteRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"VectorBucketWithGrantsTestStack/ReadWriteRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["s3vectors:CreateIndex","s3vectors:DeleteIndex","s3vectors:DeleteVectors","s3vectors:GetIndex","s3vectors:GetVectors","s3vectors:ListIndexes","s3vectors:ListVectors","s3vectors:PutVectors"],"Effect":"Allow","Resource":[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},{"Fn::Join":["",[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},"/index/*"]]}]}],"Version":"2012-10-17"},"policyName":"ReadWriteRoleDefaultPolicy82ECA137","roles":[{"Ref":"ReadWriteRole39A63897"}]}}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"VectorBucketWithGrantsTestStack/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"VectorBucketWithGrantsTestStack/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"VectorBucketWithGrantsIntegTest":{"id":"VectorBucketWithGrantsIntegTest","path":"VectorBucketWithGrantsIntegTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"VectorBucketWithGrantsIntegTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"VectorBucketWithGrantsIntegTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"VectorBucketWithGrantsIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.ts new file mode 100644 index 0000000000000..39a2c77d06a77 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket-with-grants.ts @@ -0,0 +1,64 @@ +import * as core from 'aws-cdk-lib/core'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as s3vectors from '../lib'; +import { Construct } from 'constructs'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +/** + * Snapshot test for vector bucket with IAM grants + */ +class VectorBucketWithGrantsTestStack extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + public readonly index: s3vectors.Index; + public readonly readRole: iam.Role; + public readonly writeRole: iam.Role; + public readonly readWriteRole: iam.Role; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + vectorBucketName: 'vector-bucket-with-grants', + removalPolicy: core.RemovalPolicy.DESTROY, + }); + + this.index = new s3vectors.Index(this, 'Index', { + vectorBucket: this.vectorBucket, + indexName: 'test-index', + dimension: 1536, + distanceMetric: s3vectors.DistanceMetric.COSINE, + }); + + // Create roles for testing grants + this.readRole = new iam.Role(this, 'ReadRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + description: 'Role with read permissions to vector bucket', + }); + + this.writeRole = new iam.Role(this, 'WriteRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + description: 'Role with write permissions to vector bucket', + }); + + this.readWriteRole = new iam.Role(this, 'ReadWriteRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + description: 'Role with read/write permissions to vector bucket', + }); + + // Grant permissions + this.vectorBucket.grantRead(this.readRole, '*'); + this.vectorBucket.grantWrite(this.writeRole, '*'); + this.vectorBucket.grantReadWrite(this.readWriteRole, '*'); + + // Grant permissions to specific index + this.vectorBucket.grantRead(this.readRole, 'test-index'); + } +} + +const app = new core.App(); + +const vectorBucketWithGrantsTest = new VectorBucketWithGrantsTestStack(app, 'VectorBucketWithGrantsTestStack'); + +new IntegTest(app, 'VectorBucketWithGrantsIntegTest', { + testCases: [vectorBucketWithGrantsTest], +}); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets.json new file mode 100644 index 0000000000000..4188858a9b7bd --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "VectorBucketIntegTestDefaultTestDeployAssert10C18705 Template", + "source": { + "path": "VectorBucketIntegTestDefaultTestDeployAssert10C18705.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestDefaultTestDeployAssert10C18705.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.assets.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.assets.json new file mode 100644 index 0000000000000..b2f5ed4310ef3 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "df172e13413720c087d0ab32d28f943b3dc5b068d59c3dad9cde3f7ea4e6dfe4": { + "displayName": "VectorBucketIntegTestStack Template", + "source": { + "path": "VectorBucketIntegTestStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-0f4ff85e": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "df172e13413720c087d0ab32d28f943b3dc5b068d59c3dad9cde3f7ea4e6dfe4.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.template.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.template.json new file mode 100644 index 0000000000000..037834972a579 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/VectorBucketIntegTestStack.template.json @@ -0,0 +1,178 @@ +{ + "Resources": { + "VectorBucket7AA37AC5": { + "Type": "AWS::S3Vectors::VectorBucket", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Index4A79713B": { + "Type": "AWS::S3Vectors::Index", + "Properties": { + "DataType": "float32", + "Dimension": 1536, + "DistanceMetric": "cosine", + "VectorBucketArn": { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + } + } + }, + "PolicyF0963E5B": { + "Type": "AWS::S3Vectors::VectorBucketPolicy", + "Properties": { + "Policy": { + "Statement": [ + { + "Action": [ + "s3vectors:GetVector", + "s3vectors:QueryVectors" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "VectorBucketArn": { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + } + } + } + }, + "Outputs": { + "VectorBucketNameOutput": { + "Description": "The name of the vector bucket", + "Value": { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "/", + { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + } + ] + } + ] + } + }, + "VectorBucketArnOutput": { + "Description": "The ARN of the vector bucket", + "Value": { + "Fn::GetAtt": [ + "VectorBucket7AA37AC5", + "VectorBucketArn" + ] + } + }, + "IndexNameOutput": { + "Description": "The name of the index", + "Value": { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + "/", + { + "Fn::GetAtt": [ + "Index4A79713B", + "IndexArn" + ] + } + ] + } + ] + } + }, + "IndexArnOutput": { + "Description": "The ARN of the index", + "Value": { + "Fn::GetAtt": [ + "Index4A79713B", + "IndexArn" + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/integ.json new file mode 100644 index 0000000000000..7663c6127a252 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "VectorBucketIntegTest/DefaultTest": { + "stacks": [ + "VectorBucketIntegTestStack" + ], + "assertionStack": "VectorBucketIntegTest/DefaultTest/DeployAssert", + "assertionStackName": "VectorBucketIntegTestDefaultTestDeployAssert10C18705" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/manifest.json new file mode 100644 index 0000000000000..26c331e560b36 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/manifest.json @@ -0,0 +1,649 @@ +{ + "version": "48.0.0", + "artifacts": { + "VectorBucketIntegTestStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "VectorBucketIntegTestStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "VectorBucketIntegTestStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "VectorBucketIntegTestStack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/df172e13413720c087d0ab32d28f943b3dc5b068d59c3dad9cde3f7ea4e6dfe4.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "VectorBucketIntegTestStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "VectorBucketIntegTestStack.assets" + ], + "metadata": { + "/VectorBucketIntegTestStack/VectorBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucket7AA37AC5" + } + ], + "/VectorBucketIntegTestStack/Index/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Index4A79713B" + } + ], + "/VectorBucketIntegTestStack/Policy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/VectorBucketIntegTestStack/Policy/Policy": [ + { + "type": "aws:cdk:logicalId", + "data": "PolicyF0963E5B" + } + ], + "/VectorBucketIntegTestStack/VectorBucketNameOutput": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucketNameOutput" + } + ], + "/VectorBucketIntegTestStack/VectorBucketArnOutput": [ + { + "type": "aws:cdk:logicalId", + "data": "VectorBucketArnOutput" + } + ], + "/VectorBucketIntegTestStack/IndexNameOutput": [ + { + "type": "aws:cdk:logicalId", + "data": "IndexNameOutput" + } + ], + "/VectorBucketIntegTestStack/IndexArnOutput": [ + { + "type": "aws:cdk:logicalId", + "data": "IndexArnOutput" + } + ], + "/VectorBucketIntegTestStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/VectorBucketIntegTestStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "VectorBucketIntegTestStack" + }, + "VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "VectorBucketIntegTestDefaultTestDeployAssert10C18705": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "VectorBucketIntegTestDefaultTestDeployAssert10C18705.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "VectorBucketIntegTestDefaultTestDeployAssert10C18705.assets" + ], + "metadata": { + "/VectorBucketIntegTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/VectorBucketIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "VectorBucketIntegTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/tree.json new file mode 100644 index 0000000000000..aa01c4d60fc08 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"VectorBucketIntegTestStack":{"id":"VectorBucketIntegTestStack","path":"VectorBucketIntegTestStack","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VectorBucket":{"id":"VectorBucket","path":"VectorBucketIntegTestStack/VectorBucket","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucket","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"VectorBucketIntegTestStack/VectorBucket/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucket","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucket","aws:cdk:cloudformation:props":{}}}}},"Index":{"id":"Index","path":"VectorBucketIntegTestStack/Index","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.Index","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"VectorBucketIntegTestStack/Index/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnIndex","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::Index","aws:cdk:cloudformation:props":{"dataType":"float32","dimension":1536,"distanceMetric":"cosine","vectorBucketArn":{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]}}}}}},"Policy":{"id":"Policy","path":"VectorBucketIntegTestStack/Policy","constructInfo":{"fqn":"@aws-cdk/aws-s3vectors-alpha.VectorBucketPolicy","version":"0.0.0","metadata":["*"]},"children":{"Policy":{"id":"Policy","path":"VectorBucketIntegTestStack/Policy/Policy","constructInfo":{"fqn":"aws-cdk-lib.aws_s3vectors.CfnVectorBucketPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::S3Vectors::VectorBucketPolicy","aws:cdk:cloudformation:props":{"policy":{"Statement":[{"Action":["s3vectors:GetVector","s3vectors:QueryVectors"],"Effect":"Allow","Principal":{"AWS":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::",{"Ref":"AWS::AccountId"},":root"]]}},"Resource":[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},{"Fn::Join":["",[{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]},"/*"]]}]}],"Version":"2012-10-17"},"vectorBucketArn":{"Fn::GetAtt":["VectorBucket7AA37AC5","VectorBucketArn"]}}}}}},"VectorBucketNameOutput":{"id":"VectorBucketNameOutput","path":"VectorBucketIntegTestStack/VectorBucketNameOutput","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"VectorBucketArnOutput":{"id":"VectorBucketArnOutput","path":"VectorBucketIntegTestStack/VectorBucketArnOutput","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"IndexNameOutput":{"id":"IndexNameOutput","path":"VectorBucketIntegTestStack/IndexNameOutput","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"IndexArnOutput":{"id":"IndexArnOutput","path":"VectorBucketIntegTestStack/IndexArnOutput","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"VectorBucketIntegTestStack/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"VectorBucketIntegTestStack/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"VectorBucketIntegTest":{"id":"VectorBucketIntegTest","path":"VectorBucketIntegTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"VectorBucketIntegTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"VectorBucketIntegTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"VectorBucketIntegTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"VectorBucketIntegTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"VectorBucketIntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.ts new file mode 100644 index 0000000000000..b7672f74f9d32 --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/integ.vector-bucket.ts @@ -0,0 +1,77 @@ +import * as core from 'aws-cdk-lib/core'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as s3vectors from '../lib'; +import { Construct } from 'constructs'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +/** + * Integration test for S3 Vectors - tests VectorBucket, Index, and VectorBucketPolicy + */ +class VectorBucketIntegTestStack extends core.Stack { + public readonly vectorBucket: s3vectors.VectorBucket; + public readonly index: s3vectors.Index; + public readonly vectorBucketPolicy: s3vectors.VectorBucketPolicy; + + constructor(scope: Construct, id: string, props?: core.StackProps) { + super(scope, id, props); + + // Create a vector bucket + this.vectorBucket = new s3vectors.VectorBucket(this, 'VectorBucket', { + removalPolicy: core.RemovalPolicy.DESTROY, + }); + + // Create an index in the vector bucket + this.index = new s3vectors.Index(this, 'Index', { + vectorBucket: this.vectorBucket, + dimension: 1536, + distanceMetric: s3vectors.DistanceMetric.COSINE, + }); + + // Create a vector bucket policy + this.vectorBucketPolicy = new s3vectors.VectorBucketPolicy(this, 'Policy', { + vectorBucket: this.vectorBucket, + }); + + // Add a policy statement to allow read access from the current account + this.vectorBucketPolicy.document.addStatements( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + principals: [new iam.AccountRootPrincipal()], + actions: ['s3vectors:GetVector', 's3vectors:QueryVectors'], + resources: [ + this.vectorBucket.vectorBucketArn, + `${this.vectorBucket.vectorBucketArn}/*`, + ], + }), + ); + + // Output the bucket name to see what Ref returns + new core.CfnOutput(this, 'VectorBucketNameOutput', { + value: this.vectorBucket.vectorBucketName, + description: 'The name of the vector bucket', + }); + + new core.CfnOutput(this, 'VectorBucketArnOutput', { + value: this.vectorBucket.vectorBucketArn, + description: 'The ARN of the vector bucket', + }); + + new core.CfnOutput(this, 'IndexNameOutput', { + value: this.index.indexName, + description: 'The name of the index', + }); + + new core.CfnOutput(this, 'IndexArnOutput', { + value: this.index.indexArn, + description: 'The ARN of the index', + }); + } +} + +const app = new core.App(); + +const testStack = new VectorBucketIntegTestStack(app, 'VectorBucketIntegTestStack'); + +new IntegTest(app, 'VectorBucketIntegTest', { + testCases: [testStack], +}); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket-policy.test.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket-policy.test.ts new file mode 100644 index 0000000000000..6c188b3e00fba --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket-policy.test.ts @@ -0,0 +1,138 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { RemovalPolicy, Stack } from 'aws-cdk-lib'; +import { VectorBucket, VectorBucketPolicy } from '../lib'; + +describe('VectorBucketPolicy', () => { + let stack: Stack; + + beforeEach(() => { + stack = new Stack(); + }); + + test('creates a vector bucket policy', () => { + // GIVEN + const vectorBucket = new VectorBucket(stack, 'VectorBucket'); + + // WHEN + new VectorBucketPolicy(stack, 'Policy', { + vectorBucket, + resourcePolicy: new iam.PolicyDocument({ + statements: [ + new iam.PolicyStatement({ + actions: ['s3vectors:QueryVectors'], + principals: [new iam.AccountRootPrincipal()], + resources: [vectorBucket.vectorBucketArn], + }), + ], + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucketPolicy', { + Policy: { + Statement: [ + { + Action: 's3vectors:QueryVectors', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::', + { Ref: 'AWS::AccountId' }, + ':root', + ], + ], + }, + }, + Resource: { + 'Fn::GetAtt': ['VectorBucket7AA37AC5', 'VectorBucketArn'], + }, + }, + ], + Version: '2012-10-17', + }, + }); + }); + + test('creates policy with removal policy', () => { + // GIVEN + const vectorBucket = new VectorBucket(stack, 'VectorBucket'); + + // WHEN + new VectorBucketPolicy(stack, 'Policy', { + vectorBucket, + resourcePolicy: new iam.PolicyDocument({ + statements: [ + new iam.PolicyStatement({ + actions: ['s3vectors:*'], + principals: [new iam.AccountRootPrincipal()], + resources: [vectorBucket.vectorBucketArn], + }), + ], + }), + removalPolicy: RemovalPolicy.RETAIN, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::S3Vectors::VectorBucketPolicy', { + DeletionPolicy: 'Retain', + }); + }); + + test('addToResourcePolicy creates policy automatically', () => { + // GIVEN + const vectorBucket = new VectorBucket(stack, 'VectorBucket'); + + // WHEN + vectorBucket.addToResourcePolicy( + new iam.PolicyStatement({ + actions: ['s3vectors:PutVectors'], + principals: [new iam.AccountRootPrincipal()], + resources: [`${vectorBucket.vectorBucketArn}/index/*`], + }), + ); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucketPolicy', { + Policy: { + Statement: [ + { + Action: 's3vectors:PutVectors', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::', + { Ref: 'AWS::AccountId' }, + ':root', + ], + ], + }, + }, + Resource: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['VectorBucket7AA37AC5', 'VectorBucketArn'], + }, + '/index/*', + ], + ], + }, + }, + ], + Version: '2012-10-17', + }, + }); + }); +}); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket.test.ts b/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket.test.ts new file mode 100644 index 0000000000000..d28cbc669c6be --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/test/vector-bucket.test.ts @@ -0,0 +1,536 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as cdk from 'aws-cdk-lib'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import { Stack } from 'aws-cdk-lib/core'; +import * as s3vectors from '../lib'; + +describe('VectorBucket', () => { + let stack: Stack; + + beforeEach(() => { + stack = new Stack(); + }); + + describe('Basic functionality', () => { + test('creates a VectorBucket with default properties', () => { + // WHEN + new s3vectors.VectorBucket(stack, 'MyVectorBucket'); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::S3Vectors::VectorBucket', 1); + }); + + test('creates a VectorBucket with specified name', () => { + // WHEN + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'test-bucket', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucket', { + VectorBucketName: 'test-bucket', + }); + }); + + test('can import from ARN', () => { + // WHEN + const imported = s3vectors.VectorBucket.fromVectorBucketArn( + stack, + 'ImportedBucket', + 'arn:aws:s3vectors:us-east-1:123456789012:bucket/my-bucket', + ); + + // THEN + expect(imported.vectorBucketArn).toBe('arn:aws:s3vectors:us-east-1:123456789012:bucket/my-bucket'); + expect(imported.vectorBucketName).toBe('my-bucket'); + }); + + test('can import from name', () => { + // WHEN + const imported = s3vectors.VectorBucket.fromVectorBucketName( + stack, + 'ImportedBucket', + 'my-bucket', + ); + + // THEN + expect(imported.vectorBucketName).toBe('my-bucket'); + }); + }); + + describe('Validation', () => { + test('validates bucket name', () => { + // THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'Invalid-Name!', + }); + }).toThrow(/must only contain lowercase/); + }); + + test('validates bucket name length', () => { + // THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'ab', + }); + }).toThrow(/at least 3 and no more than 63 characters/); + }); + + test('rejects bucket name with uppercase letters', () => { + // WHEN/THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'MyBucket', + }); + }).toThrow(/must only contain lowercase/); + }); + + test('accepts bucket name with numbers', () => { + // WHEN/THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'my-bucket-123', + }); + }).not.toThrow(); + }); + + test('accepts minimum length bucket name', () => { + // WHEN/THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'abc', + }); + }).not.toThrow(); + }); + + test('accepts maximum length bucket name', () => { + // WHEN/THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: 'a'.repeat(63), + }); + }).not.toThrow(); + }); + + test('handles token values in bucket name validation', () => { + // GIVEN + const tokenName = new cdk.CfnParameter(stack, 'BucketNameParameter', { + type: 'String', + }).valueAsString; + + // WHEN/THEN - should not throw + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + vectorBucketName: tokenName, + }); + }).not.toThrow(); + }); + }); + + describe('Encryption', () => { + test('creates a VectorBucket with S3 managed encryption', () => { + // WHEN + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryption: s3vectors.VectorBucketEncryption.S3_MANAGED, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucket', { + EncryptionConfiguration: { + SseType: 'AES256', + }, + }); + }); + + test('creates with KMS encryption and provided key', () => { + // GIVEN + const key = new kms.Key(stack, 'MyKey'); + + // WHEN + const bucket = new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + encryptionKey: key, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucket', { + EncryptionConfiguration: { + SseType: 'aws:kms', + KmsKeyArn: { + 'Fn::GetAtt': ['MyKey6AB29FA6', 'Arn'], + }, + }, + }); + expect(bucket.encryptionKey).toBe(key); + }); + + test('creates with KMS encryption and auto-generated key', () => { + // WHEN + const bucket = new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucket', { + EncryptionConfiguration: { + SseType: 'aws:kms', + KmsKeyArn: { + 'Fn::GetAtt': ['MyVectorBucketKey7ACA85A8', 'Arn'], + }, + }, + }); + expect(bucket.encryptionKey).toBeDefined(); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); + }); + + test('throws error when S3_MANAGED encryption with provided key', () => { + // GIVEN + const key = new kms.Key(stack, 'MyKey'); + + // THEN + expect(() => { + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryption: s3vectors.VectorBucketEncryption.S3_MANAGED, + encryptionKey: key, + }); + }).toThrow(/Expected encryption = VectorBucketEncryption.KMS/); + }); + + test('uses KMS when only key is provided without encryption type', () => { + // GIVEN + const key = new kms.Key(stack, 'MyKey'); + + // WHEN + const bucket = new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryptionKey: key, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3Vectors::VectorBucket', { + EncryptionConfiguration: { + SseType: 'aws:kms', + KmsKeyArn: { + 'Fn::GetAtt': ['MyKey6AB29FA6', 'Arn'], + }, + }, + }); + expect(bucket.encryptionKey).toBe(key); + }); + + test('creates without encryption configuration when neither encryption nor key specified', () => { + // WHEN + const bucket = new s3vectors.VectorBucket(stack, 'MyVectorBucket'); + + // THEN + const template = Template.fromStack(stack); + const resources = template.findResources('AWS::S3Vectors::VectorBucket'); + const bucketResource = Object.values(resources)[0]; + expect(bucketResource?.Properties?.EncryptionConfiguration).toBeUndefined(); + expect(bucket.encryptionKey).toBeUndefined(); + }); + + test('auto-generated KMS key has key rotation enabled', () => { + // WHEN + new s3vectors.VectorBucket(stack, 'MyVectorBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { + EnableKeyRotation: true, + }); + }); + }); + + describe('Permissions', () => { + let permStack: Stack; + let bucket: s3vectors.VectorBucket; + let role: iam.Role; + + beforeEach(() => { + permStack = new Stack(); + bucket = new s3vectors.VectorBucket(permStack, 'MyVectorBucket', { + vectorBucketName: 'test-bucket', + }); + role = new iam.Role(permStack, 'TestRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + }); + + test('grantRead adds correct IAM permissions for all indexes', () => { + // WHEN + bucket.grantRead(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + '/index/*', + ], + ], + }, + ], + }, + ], + }, + }); + }); + + test('grantWrite adds correct IAM permissions for all indexes', () => { + // WHEN + bucket.grantWrite(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', + 's3vectors:CreateIndex', + 's3vectors:DeleteIndex', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + '/index/*', + ], + ], + }, + ], + }, + ], + }, + }); + }); + + test('grantReadWrite adds correct IAM permissions for all indexes', () => { + // WHEN + bucket.grantReadWrite(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', + 's3vectors:CreateIndex', + 's3vectors:DeleteIndex', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + '/index/*', + ], + ], + }, + ], + }, + ], + }, + }); + }); + + test('grantRead with indexId scopes permissions correctly', () => { + // WHEN + bucket.grantRead(role, 'my-index'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['MyVectorBucket4697D5BD', 'VectorBucketArn'], + }, + '/index/my-index', + ], + ], + }, + ], + }, + ], + }, + }); + }); + + test('grant methods add KMS permissions when encrypted', () => { + // GIVEN + const key = new kms.Key(permStack, 'MyKey'); + const encryptedBucket = new s3vectors.VectorBucket(permStack, 'EncryptedBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + encryptionKey: key, + }); + + // WHEN + encryptedBucket.grantRead(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', + ], + Effect: 'Allow', + }, + { + Action: 'kms:Decrypt', + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': ['MyKey6AB29FA6', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('grantWrite adds KMS GenerateDataKey permission when encrypted', () => { + // GIVEN + const key = new kms.Key(permStack, 'MyKey'); + const encryptedBucket = new s3vectors.VectorBucket(permStack, 'EncryptedBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + encryptionKey: key, + }); + + // WHEN + encryptedBucket.grantWrite(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', + 's3vectors:CreateIndex', + 's3vectors:DeleteIndex', + ], + Effect: 'Allow', + }, + { + Action: [ + 'kms:Decrypt', + 'kms:GenerateDataKey*', + ], + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': ['MyKey6AB29FA6', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('grantReadWrite adds comprehensive KMS permissions when encrypted', () => { + // GIVEN + const key = new kms.Key(permStack, 'MyKey'); + const encryptedBucket = new s3vectors.VectorBucket(permStack, 'EncryptedBucket', { + encryption: s3vectors.VectorBucketEncryption.KMS, + encryptionKey: key, + }); + + // WHEN + encryptedBucket.grantReadWrite(role, '*'); + + // THEN + Template.fromStack(permStack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3vectors:GetVectors', + 's3vectors:ListVectors', + 's3vectors:ListIndexes', + 's3vectors:GetIndex', + 's3vectors:PutVectors', + 's3vectors:DeleteVectors', + 's3vectors:CreateIndex', + 's3vectors:DeleteIndex', + ], + Effect: 'Allow', + }, + { + Action: [ + 'kms:Decrypt', + 'kms:GenerateDataKey*', + ], + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': ['MyKey6AB29FA6', 'Arn'], + }, + }, + ], + }, + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-s3vectors-alpha/tsconfig.json b/packages/@aws-cdk/aws-s3vectors-alpha/tsconfig.json new file mode 100644 index 0000000000000..2b326e452cfbc --- /dev/null +++ b/packages/@aws-cdk/aws-s3vectors-alpha/tsconfig.json @@ -0,0 +1,51 @@ +{ + "compilerOptions": { + "declarationMap": false, + "inlineSourceMap": true, + "inlineSources": true, + "alwaysStrict": true, + "declaration": true, + "incremental": true, + "lib": [ + "es2022" + ], + "module": "commonjs", + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": false, + "target": "es2022", + "composite": true, + "tsBuildInfoFile": "tsconfig.tsbuildinfo", + "esModuleInterop": false + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules" + ], + "references": [ + { + "path": "../../aws-cdk-lib" + }, + { + "path": "../../../tools/@aws-cdk/cdk-build-tools" + }, + { + "path": "../../../tools/@aws-cdk/pkglint" + }, + { + "path": "../integ-tests-alpha" + } + ] +}