cdk-rds-sql 7.3.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +16 -16
- package/README.md +36 -11
- package/lib/database.js +1 -1
- package/lib/handler/handler.js +28 -21
- package/lib/iam-grant.d.ts +0 -1
- package/lib/iam-grant.js +2 -12
- package/lib/provider.js +1 -1
- package/lib/role.d.ts +10 -4
- package/lib/role.js +56 -53
- package/lib/schema.js +1 -1
- package/lib/sql.js +1 -1
- package/package.json +1 -1
- package/lambda/engine.abstract.ts +0 -114
- package/lambda/engine.dsql.ts +0 -391
- package/lambda/engine.factory.ts +0 -23
- package/lambda/engine.mysql.test.ts +0 -228
- package/lambda/engine.mysql.ts +0 -249
- package/lambda/engine.postgresql.test.ts +0 -151
- package/lambda/engine.postgresql.ts +0 -329
- package/lambda/handler.mysql.test.ts +0 -349
- package/lambda/handler.postgresql.test.ts +0 -338
- package/lambda/handler.test.ts +0 -164
- package/lambda/handler.ts +0 -388
- package/lambda/types.ts +0 -86
- package/lambda/util.ts +0 -186
package/.jsii
CHANGED
|
@@ -4080,7 +4080,7 @@
|
|
|
4080
4080
|
},
|
|
4081
4081
|
"name": "cdk-rds-sql",
|
|
4082
4082
|
"readme": {
|
|
4083
|
-
"markdown": "# About\n\nThis CDK construct library makes it possible to create databases,\nschemas, and roles in an Aurora Serverless v2, RDS Database Cluster,\nDatabase Instance, or AWS DSQL clusters. PostgreSQL, MySQL, and DSQL\ndatabases are supported.\n\nThis construct library is intended to be used in enterprise\nenvironments, and works in isolated subnets.\n\n<p align=\"left\">\n <a href=\"https://github.com/semantic-release/semantic-release\"><img src=\"https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release\" alt=semantic-release: angular\"></a>\n <a href=\"https://github.com/berenddeboer/cdk-rds-sql/actions/workflows/release.yml\"><img src=\"https://github.com/berenddeboer/cdk-rds-sql/actions/workflows/release.yml/badge.svg\" alt=\"Release badge\"></a>\n</p>\n\n# Requirements\n\n- CDK v2.\n\n# Installation\n\n npm i cdk-rds-sql\n\n# Usage\n\n## Provider\n\nFirst setup your VPC and create your cluster:\n\n```ts\nimport { Duration, RemovalPolicy } from \"aws-cdk-lib\"\nimport * as ec2 from \"aws-cdk-lib/aws-ec2\"\nimport * as rds from \"aws-cdk-lib/aws-rds\"\n\nconst vpc = ec2.Vpc.fromLookup(this, \"Vpc\", {\n vpcId: this.node.tryGetContext(\"vpc-id\"),\n})\n\nconst cluster = new rds.ServerlessCluster(this, \"Cluster\", {\n vpc: vpc,\n vpcSubnets: {\n subnetType: ec2.SubnetType.PRIVATE_ISOLATED,\n },\n engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL,\n parameterGroup: rds.ParameterGroup.fromParameterGroupName(\n this,\n \"ParameterGroup\",\n \"default.aurora-postgresql11\"\n ),\n removalPolicy: RemovalPolicy.DESTROY,\n scaling: {\n autoPause: Duration.minutes(60),\n minCapacity: rds.AuroraCapacityUnit.ACU_2,\n maxCapacity: rds.AuroraCapacityUnit.ACU_2,\n },\n})\n```\n\nThen create a provider which will connect to your database. For a cluster:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n cluster: cluster,\n secret: cluster.secret!,\n})\n```\n\nFor an instance:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n instance: instance,\n secret: cluster.secret!,\n})\n```\n\nThe provider will setup a lambda, which normally lives in the same VPC\nas the database. You can give a different VPC, as long as that VPC has\naccess to the VPC of the database. Only the provider lambda will talk\nto your database.\n\nThe provider will by default use the private isolated subnet of the\nVPC. Your isolated network must have a VPC endpoint to AWS Secrets Manager\nand possibly KMS as well. If you want to use a subnet with egress\naccess in case you have no such VPC endpoints, specify the subnet as\nfollows:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n vpcSubnets: {\n subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,\n },\n cluster: cluster,\n secret: cluster.secret!,\n})\n```\n\n## Roles\n\nCreate a postgres role (or mysql user) for a cluster as follows:\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n databaseName: \"mydb\",\n})\n```\n\nThis will automatically create a secret just like `ServerlessCluster`\ndoes, with all the connection info needed for this user. It's secret\nvalue is a JSON like:\n\n```json\n{\n \"dbClusterIdentifier\": \"teststack-clustereb1186t9-sh4wpqfdyfvu\",\n \"password\": \"very-long-and-boring\",\n \"dbname\": \"mydb\",\n \"engine\": \"postgres\",\n \"port\": 5432,\n \"host\": \"teststack-clustereb1186t9-sh4wpqfdyfvu.cluster-cgudolabssna.us-east-1.rds.amazonaws.com\",\n \"username\": \"myrole\"\n}\n```\n\nYou can access the secret via `role.secret`.\n\nInstead of `databaseName` you can also specify `database` to reference\nan existing database. The role will not be created until the database\nhas been created.\n\nIf you want to make the role the owner of a new database, just specify\nthe `databaseName` here, and create the database later.\n\n### IAM Authentication\n\nInstead of password-based authentication, you can create roles that\nuse AWS IAM database authentication. This eliminates the need to store\ndatabase passwords and provides enhanced security through AWS IAM\npolicies.\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst iamRole = new Role(this, \"IamRole\", {\n provider: provider,\n roleName: \"myiamrole\",\n databaseName: \"mydb\",\n enableIamAuth: true,\n})\n```\n\nFor IAM-authenticated roles, the secret will not contain a password field:\n\n```json\n{\n \"dbClusterIdentifier\": \"teststack-clustereb1186t9-sh4wpqfdyfvu\",\n \"dbname\": \"mydb\",\n \"engine\": \"postgres\",\n \"port\": 5432,\n \"host\": \"teststack-clustereb1186t9-sh4wpqfdyfvu.cluster-cgudolabssna.us-east-1.rds.amazonaws.com\",\n \"username\": \"myiamrole\"\n}\n```\n\n**Requirements for IAM Authentication:**\n\n- SSL connections are required (enabled by default in this library)\n- Your application must have IAM permissions to connect to the database\n- The database user/role name must match the IAM identity\n\n**IAM Policy Example:**\n\nYour application will need an IAM policy like this to connect:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\"rds-db:connect\"],\n \"Resource\": [\n \"arn:aws:rds-db:region:account-id:dbuser:cluster-resource-id/myiamrole\"\n ]\n }\n ]\n}\n```\n\nBoth PostgreSQL and MySQL databases support IAM authentication. For more details, see the [AWS RDS IAM Database Authentication documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html).\n\n### MySQL support\n\nIn MySQL users are created with '%' as value for the host. It is hard\nto do this better:\n\n- Determine the CIDR blocks used by a VPC is not trivial.\n- For imported VPCs you cannot specify the IPv6 CIDR.\n- CIDRs might change without the system knowing, meaning applications\n could lose access to the database at random times, such as when a\n container is restarted.\n\n## Database\n\nCreate a database as follows:\n\n```ts\nimport { Database } from \"cdk-rds-sql\"\n\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n})\n```\n\nYou can provide an owner, which makes it easy to create database owned\nby a new user:\n\n```ts\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n owner: role,\n})\n```\n\n## Schema\n\nCreate a schema in the default database as follows:\n\n```ts\nimport { Schema } from \"cdk-rds-sql\"\n\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n})\n```\n\nOr in another database:\n\n```ts\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n})\n\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n databaseName: database.databaseName,\n})\n```\n\nOne may need a role permitted for using schema:\n\n```ts\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n databaseName: database.databaseName,\n role: role,\n})\n```\n\n## Sql\n\nYou can insert arbitrary SQL into your database with the `Sql` construct:\n\n```ts\nimport { Sql } from \"cdk-rds-sql\"\n\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: \"create table t (i int)\",\n})\n```\n\nCreate a table if it does not exist, and grant a role privileges:\n\n```ts\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: `\ncreate table if not exists t (i int);\ngrant select on t to myrole;\n`,\n})\n```\n\nRollback sql on stack deletion:\n\n```ts\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: `\ncreate table if not exists t (i int);\ngrant select on t to myrole;\n`,\n rollback: `\nDO $$BEGIN\n IF EXISTS (select from pg_database WHERE datname = 't') THEN\n IF EXISTS (select from pg_catalog.pg_roles WHERE rolname = 'myrole') THEN\n revoke select t from myrole;\n END IF;\n drop table t;\n END IF;\nEND$$;\n`,\n})\n```\n\nNote that there is no synchronisation between various `Sql`\nconstructs, in particular the order in your code does not determine\nthe order in which your SQL is executed. This happens in parallel,\nunless you specify an explicit dependency via `sql.node.addDepency()`.\n\nThere are a lot of concerns when using `Sql`:\n\n- When you update your Sql, your previous Sql is not \"rolled back\",\n the new Sql is simply executed again.\n- When you delete your `Sql` construct the rollback is executed if specified\n- When permission are granted via `Sql` they must be removed via\n rollback to succesfully remove the role\n- Currently the `Sql` constructs has less than 5 minutes to execute\n its work.\n- It is unknown how large your SQL can be.\n\n# Parameters\n\nSome lambda constructs, in particular [Bref](https://bref.sh/), do not\nsupport secrets out of the box. Use the `parameterPrefix` property to\ncreate SSM parameters in addition to a secret:\n\n```ts\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n databaseName: \"mydb\",\n parameterPrefix: \"/my-app/\",\n})\n```\n\nThis will create `/my-app/username`, `/my-app/password` and such.\n\nTo access parameters you will need IAM permissions such as:\n\n```ts\ninitialPolicy: [\n new iam.PolicyStatement({\n\tactions: [\"ssm:GetParameter\", \"ssm:GetParameters\"],\n\tresources: [\n\t // Grant access to all parameters under the base path\n\t `arn:aws:ssm:${this.region}:${this.account}:parameter/my-app/*`,\n\t],\n\teffect: iam.Effect.ALLOW,\n })\n],\n```\n\nNote that your VPC will need an SSM Parameters interface endpoint to support this.\n\n# AWS DSQL Support\n\nThis construct also supports AWS DSQL. DSQL is a great number of\nlimitations around it's postgresql support, so there is some learing\ncurve. This library supports creating roles, schemas, and executing\nSQL on DSQL clusters. Creating databases is not supported by DSQL.\n\n## DSQL Provider Setup\n\nDSQL clusters don't require a VPC or secrets since they use IAM authentication:\n\n```ts\nimport * as dsql from \"aws-cdk-lib/aws-dsql\"\nimport { Provider } from \"cdk-rds-sql\"\n\nconst dsqlCluster = new dsql.CfnCluster(this, \"DsqlCluster\", {\n deletionProtectionEnabled: false,\n})\n\nconst provider = new Provider(this, \"Provider\", {\n cluster: dsqlCluster,\n // No VPC or secret needed for DSQL\n})\n```\n\nYou can access DSQL from within a VPC, but cdk-rds-sql has not been\nspecifically tested with that scenario.\n\n## DSQL Roles\n\nDSQL always uses IAM authentication, so the `enableIamAuth` property is ignored:\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n})\n```\n\n## Using DSQL\n\nConnecting to DSQL requires a couple of things:\n\n1. Your IAM role needs the `dsql:DbConnect` IAM permission to connect to the cluster.\n2. You probably want a normal postgres role (not \"admin\") to use from your apps.\n3. Your IAM role needs to be connected to your postgres role: use the `IamGrant` construct for that:\n\n ```ts\n new IamGrant(this, \"LambdaIamGrant\", {\n provider: provider,\n roleName: role.roleName,\n resourceArn: queryLambda.role!.roleArn,\n })\n ```\n\n4. From your code use the Dsql signer to create the password:\n\n ```ts\n import { DsqlSigner } from \"@aws-sdk/dsql-signer\"\n import { Client } from \"pg\"\n\n const region =\n process.env[\"AWS_REGION\"] || process.env[\"AWS_DEFAULT_REGION\"] || \"us-west-2\"\n\n // Generate DSQL auth token using AWS SDK\n const signer = new DsqlSigner({\n hostname: host,\n region,\n })\n\n const authToken = await signer.getDbConnectAuthToken()\n\n const client = new Client({\n host,\n port: 5432,\n user: dbUser,\n database: dbName,\n password: authToken,\n ssl: { rejectUnauthorized: false },\n })\n\n await client.connect()\n ```\n\n# IPv6\n\nIf you use the provider in an IPv6 subnet you probably need these settings:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n ...\n functionProps: {\n\tipv6AllowedForDualStack: true,\n\tallowAllIpv6Outbound: true,\n },\n}\n```\n\n# Disabling SSL\n\nThe default connection to RDS is ssl enabled. You can disable ssl by\nsetting the `ssl` option to `false`:\n\n```ts\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n instance: instance,\n secret: cluster.secret!,\n ssl: false, // default is true\n})\n```\n\n# Working on this code\n\nThis code is managed by\n[projen](https://github.com/projen/projen/blob/main/README.md). In\naddition [pre-commit](https://pre-commit.com/) is used.\n\nSo after git clone and `npm ci` you would do:\n\n```\npre-commit install --install-hooks --hook-type commit-msg --hook-type pre-commit\n```\n\nto install the pre-commit hooks.\n\n## Testing\n\nTest code via projen with:\n\n npx projen test\n\nYou can run the sample stack with:\n\n npx projen integ:deploy:serverless\n\nIf you want to use an existing vpc:\n\n npx cdk deploy --context vpc-id=vpc-0123456789 TestServerlessV2Stack\n\nYou can also test DSQL support with:\n\n npx projen integ:deploy:dsql\n\n# To do\n\n- Update role: will not revoke connect to previous database if database name has changed.\n"
|
|
4083
|
+
"markdown": "# About\n\nThis CDK construct library makes it possible to create databases,\nschemas, and roles in an Aurora Serverless v2, RDS Database Cluster,\nDatabase Instance, or AWS DSQL clusters. PostgreSQL, MySQL, and DSQL\ndatabases are supported.\n\nThis construct library is intended to be used in enterprise\nenvironments, and works in isolated subnets.\n\n<p align=\"left\">\n <a href=\"https://github.com/semantic-release/semantic-release\"><img src=\"https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release\" alt=semantic-release: angular\"></a>\n <a href=\"https://github.com/berenddeboer/cdk-rds-sql/actions/workflows/release.yml\"><img src=\"https://github.com/berenddeboer/cdk-rds-sql/actions/workflows/release.yml/badge.svg\" alt=\"Release badge\"></a>\n</p>\n\n# Requirements\n\n- CDK v2.\n\n# Installation\n\n npm i cdk-rds-sql\n\n# Usage\n\n## Provider\n\nFirst setup your VPC and create your cluster:\n\n```ts\nimport { Duration, RemovalPolicy } from \"aws-cdk-lib\"\nimport * as ec2 from \"aws-cdk-lib/aws-ec2\"\nimport * as rds from \"aws-cdk-lib/aws-rds\"\n\nconst vpc = ec2.Vpc.fromLookup(this, \"Vpc\", {\n vpcId: this.node.tryGetContext(\"vpc-id\"),\n})\n\nconst cluster = new rds.ServerlessCluster(this, \"Cluster\", {\n vpc: vpc,\n vpcSubnets: {\n subnetType: ec2.SubnetType.PRIVATE_ISOLATED,\n },\n engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL,\n parameterGroup: rds.ParameterGroup.fromParameterGroupName(\n this,\n \"ParameterGroup\",\n \"default.aurora-postgresql11\"\n ),\n removalPolicy: RemovalPolicy.DESTROY,\n scaling: {\n autoPause: Duration.minutes(60),\n minCapacity: rds.AuroraCapacityUnit.ACU_2,\n maxCapacity: rds.AuroraCapacityUnit.ACU_2,\n },\n})\n```\n\nThen create a provider which will connect to your database. For a cluster:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n cluster: cluster,\n secret: cluster.secret!,\n})\n```\n\nFor an instance:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n instance: instance,\n secret: cluster.secret!,\n})\n```\n\nThe provider will setup a lambda, which normally lives in the same VPC\nas the database. You can give a different VPC, as long as that VPC has\naccess to the VPC of the database. Only the provider lambda will talk\nto your database.\n\nThe provider will by default use the private isolated subnet of the\nVPC. Your isolated network must have a VPC endpoint to AWS Secrets Manager\nand possibly KMS as well. If you want to use a subnet with egress\naccess in case you have no such VPC endpoints, specify the subnet as\nfollows:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n vpcSubnets: {\n subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,\n },\n cluster: cluster,\n secret: cluster.secret!,\n})\n```\n\n## Roles\n\nCreate a postgres role (or mysql user) for a cluster as follows:\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n databaseName: \"mydb\",\n})\n```\n\nThis will automatically create a secret just like `ServerlessCluster`\ndoes, with all the connection info needed for this user. It's secret\nvalue is a JSON like:\n\n```json\n{\n \"dbClusterIdentifier\": \"teststack-clustereb1186t9-sh4wpqfdyfvu\",\n \"password\": \"very-long-and-boring\",\n \"dbname\": \"mydb\",\n \"engine\": \"postgres\",\n \"port\": 5432,\n \"host\": \"teststack-clustereb1186t9-sh4wpqfdyfvu.cluster-cgudolabssna.us-east-1.rds.amazonaws.com\",\n \"username\": \"myrole\"\n}\n```\n\nYou can access the secret via `role.secret`.\n\nInstead of `databaseName` you can also specify `database` to reference\nan existing database. The role will not be created until the database\nhas been created.\n\nIf you want to make the role the owner of a new database, just specify\nthe `databaseName` here, and create the database later.\n\n### IAM Authentication\n\nInstead of password-based authentication, you can create roles that\nuse AWS IAM database authentication. This eliminates the need to store\ndatabase passwords and provides enhanced security through AWS IAM\npolicies.\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst iamRole = new Role(this, \"IamRole\", {\n provider: provider,\n roleName: \"myiamrole\",\n databaseName: \"mydb\",\n enableIamAuth: true,\n})\n```\n\nWhen `enableIamAuth` is set to `true`:\n\n- **No secret is created** - the `role.secret` property will be `undefined`\n- The database role is created without a password\n- Your application must generate an IAM authentication token at runtime\n\nThis is the same behavior as DSQL clusters, which always use IAM authentication.\n\n**Requirements for IAM Authentication:**\n\n- SSL connections are required (enabled by default in this library)\n- Your application must have IAM permissions to connect to the database\n- The database user/role name must match the IAM identity\n\n**IAM Policy Example:**\n\nYour application will need an IAM policy like this to connect:\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\"rds-db:connect\"],\n \"Resource\": [\n \"arn:aws:rds-db:region:account-id:dbuser:cluster-resource-id/myiamrole\"\n ]\n }\n ]\n}\n```\n\n**Generating an IAM Authentication Token:**\n\nAt runtime, your application needs to generate an authentication token\nusing the AWS SDK. Here's an example using the AWS SDK for JavaScript:\n\n```ts\nimport { Signer } from \"@aws-sdk/rds-signer\"\nimport { Client } from \"pg\"\n\nconst signer = new Signer({\n hostname: \"your-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com\",\n port: 5432,\n username: \"myiamrole\",\n region: \"us-east-1\",\n})\n\nconst token = await signer.getAuthToken()\n\nconst client = new Client({\n host: \"your-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com\",\n port: 5432,\n user: \"myiamrole\",\n database: \"mydb\",\n password: token,\n ssl: { rejectUnauthorized: true },\n})\n\nawait client.connect()\n```\n\nBoth PostgreSQL and MySQL databases support IAM authentication. For more details, see the [AWS RDS IAM Database Authentication documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html).\n\n### MySQL support\n\nIn MySQL users are created with '%' as value for the host. It is hard\nto do this better:\n\n- Determine the CIDR blocks used by a VPC is not trivial.\n- For imported VPCs you cannot specify the IPv6 CIDR.\n- CIDRs might change without the system knowing, meaning applications\n could lose access to the database at random times, such as when a\n container is restarted.\n\n## Database\n\nCreate a database as follows:\n\n```ts\nimport { Database } from \"cdk-rds-sql\"\n\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n})\n```\n\nYou can provide an owner, which makes it easy to create database owned\nby a new user:\n\n```ts\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n owner: role,\n})\n```\n\n## Schema\n\nCreate a schema in the default database as follows:\n\n```ts\nimport { Schema } from \"cdk-rds-sql\"\n\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n})\n```\n\nOr in another database:\n\n```ts\nconst database = new Database(this, \"Database\", {\n provider: provider,\n databaseName: \"mydb\",\n})\n\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n databaseName: database.databaseName,\n})\n```\n\nOne may need a role permitted for using schema:\n\n```ts\nnew Schema(this, \"Schema\", {\n provider: provider,\n schemaName: \"myschema\",\n databaseName: database.databaseName,\n role: role,\n})\n```\n\n## Sql\n\nYou can insert arbitrary SQL into your database with the `Sql` construct:\n\n```ts\nimport { Sql } from \"cdk-rds-sql\"\n\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: \"create table t (i int)\",\n})\n```\n\nCreate a table if it does not exist, and grant a role privileges:\n\n```ts\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: `\ncreate table if not exists t (i int);\ngrant select on t to myrole;\n`,\n})\n```\n\nRollback sql on stack deletion:\n\n```ts\nconst sql = new Sql(this, \"Sql\", {\n provider: provider,\n database: database,\n statement: `\ncreate table if not exists t (i int);\ngrant select on t to myrole;\n`,\n rollback: `\nDO $$BEGIN\n IF EXISTS (select from pg_database WHERE datname = 't') THEN\n IF EXISTS (select from pg_catalog.pg_roles WHERE rolname = 'myrole') THEN\n revoke select t from myrole;\n END IF;\n drop table t;\n END IF;\nEND$$;\n`,\n})\n```\n\nNote that there is no synchronisation between various `Sql`\nconstructs, in particular the order in your code does not determine\nthe order in which your SQL is executed. This happens in parallel,\nunless you specify an explicit dependency via `sql.node.addDepency()`.\n\nThere are a lot of concerns when using `Sql`:\n\n- When you update your Sql, your previous Sql is not \"rolled back\",\n the new Sql is simply executed again.\n- When you delete your `Sql` construct the rollback is executed if specified\n- When permission are granted via `Sql` they must be removed via\n rollback to succesfully remove the role\n- Currently the `Sql` constructs has less than 5 minutes to execute\n its work.\n- It is unknown how large your SQL can be.\n\n# Parameters\n\nSome lambda constructs, in particular [Bref](https://bref.sh/), do not\nsupport secrets out of the box. Use the `parameterPrefix` property to\ncreate SSM parameters in addition to a secret:\n\n```ts\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n databaseName: \"mydb\",\n parameterPrefix: \"/my-app/\",\n})\n```\n\nThis will create `/my-app/username`, `/my-app/password` and such.\n\nTo access parameters you will need IAM permissions such as:\n\n```ts\ninitialPolicy: [\n new iam.PolicyStatement({\n\tactions: [\"ssm:GetParameter\", \"ssm:GetParameters\"],\n\tresources: [\n\t // Grant access to all parameters under the base path\n\t `arn:aws:ssm:${this.region}:${this.account}:parameter/my-app/*`,\n\t],\n\teffect: iam.Effect.ALLOW,\n })\n],\n```\n\nNote that your VPC will need an SSM Parameters interface endpoint to support this.\n\n# AWS DSQL Support\n\nThis construct also supports AWS DSQL. DSQL is a great number of\nlimitations around it's postgresql support, so there is some learing\ncurve. This library supports creating roles, schemas, and executing\nSQL on DSQL clusters. Creating databases is not supported by DSQL.\n\n## DSQL Provider Setup\n\nDSQL clusters don't require a VPC or secrets since they use IAM authentication:\n\n```ts\nimport * as dsql from \"aws-cdk-lib/aws-dsql\"\nimport { Provider } from \"cdk-rds-sql\"\n\nconst dsqlCluster = new dsql.CfnCluster(this, \"DsqlCluster\", {\n deletionProtectionEnabled: false,\n})\n\nconst provider = new Provider(this, \"Provider\", {\n cluster: dsqlCluster,\n // No VPC or secret needed for DSQL\n})\n```\n\nYou can access DSQL from within a VPC, but cdk-rds-sql has not been\nspecifically tested with that scenario.\n\n## DSQL Roles\n\nDSQL always uses IAM authentication, so the `enableIamAuth` property is ignored:\n\n```ts\nimport { Role } from \"cdk-rds-sql\"\n\nconst role = new Role(this, \"Role\", {\n provider: provider,\n roleName: \"myrole\",\n})\n```\n\n## Using DSQL\n\nConnecting to DSQL requires a couple of things:\n\n1. Your IAM role needs the `dsql:DbConnect` IAM permission to connect to the cluster.\n2. You probably want a normal postgres role (not \"admin\") to use from your apps.\n3. Your IAM role needs to be connected to your postgres role: use the `IamGrant` construct for that:\n\n ```ts\n new IamGrant(this, \"LambdaIamGrant\", {\n provider: provider,\n roleName: role.roleName,\n resourceArn: queryLambda.role!.roleArn,\n })\n ```\n\n4. From your code use the Dsql signer to create the password:\n\n ```ts\n import { DsqlSigner } from \"@aws-sdk/dsql-signer\"\n import { Client } from \"pg\"\n\n const region =\n process.env[\"AWS_REGION\"] || process.env[\"AWS_DEFAULT_REGION\"] || \"us-west-2\"\n\n // Generate DSQL auth token using AWS SDK\n const signer = new DsqlSigner({\n hostname: host,\n region,\n })\n\n const authToken = await signer.getDbConnectAuthToken()\n\n const client = new Client({\n host,\n port: 5432,\n user: dbUser,\n database: dbName,\n password: authToken,\n ssl: { rejectUnauthorized: false },\n })\n\n await client.connect()\n ```\n\n# IPv6\n\nIf you use the provider in an IPv6 subnet you probably need these settings:\n\n```ts\nimport { Provider } from \"cdk-rds-sql\"\n\nconst provider = new Provider(this, \"Provider\", {\n ...\n functionProps: {\n\tipv6AllowedForDualStack: true,\n\tallowAllIpv6Outbound: true,\n },\n}\n```\n\n# Disabling SSL\n\nThe default connection to RDS is ssl enabled. You can disable ssl by\nsetting the `ssl` option to `false`:\n\n```ts\nconst provider = new Provider(this, \"Provider\", {\n vpc: vpc,\n instance: instance,\n secret: cluster.secret!,\n ssl: false, // default is true\n})\n```\n\n# Working on this code\n\nThis code is managed by\n[projen](https://github.com/projen/projen/blob/main/README.md). In\naddition [pre-commit](https://pre-commit.com/) is used.\n\nSo after git clone and `npm ci` you would do:\n\n```\npre-commit install --install-hooks --hook-type commit-msg --hook-type pre-commit\n```\n\nto install the pre-commit hooks.\n\n## Testing\n\nTest code via projen with:\n\n npx projen test\n\nYou can run the sample stack with:\n\n npx projen integ:deploy:serverless\n\nIf you want to use an existing vpc:\n\n npx cdk deploy --context vpc-id=vpc-0123456789 TestServerlessV2Stack\n\nYou can also test DSQL support with:\n\n npx projen integ:deploy:dsql\n\n# To do\n\n- Update role: will not revoke connect to previous database if database name has changed.\n"
|
|
4084
4084
|
},
|
|
4085
4085
|
"repository": {
|
|
4086
4086
|
"type": "git",
|
|
@@ -4447,7 +4447,7 @@
|
|
|
4447
4447
|
},
|
|
4448
4448
|
"locationInModule": {
|
|
4449
4449
|
"filename": "src/iam-grant.ts",
|
|
4450
|
-
"line":
|
|
4450
|
+
"line": 24
|
|
4451
4451
|
},
|
|
4452
4452
|
"parameters": [
|
|
4453
4453
|
{
|
|
@@ -4473,7 +4473,7 @@
|
|
|
4473
4473
|
"kind": "class",
|
|
4474
4474
|
"locationInModule": {
|
|
4475
4475
|
"filename": "src/iam-grant.ts",
|
|
4476
|
-
"line":
|
|
4476
|
+
"line": 23
|
|
4477
4477
|
},
|
|
4478
4478
|
"name": "IamGrant",
|
|
4479
4479
|
"symbolId": "src/iam-grant:IamGrant"
|
|
@@ -4488,7 +4488,7 @@
|
|
|
4488
4488
|
"kind": "interface",
|
|
4489
4489
|
"locationInModule": {
|
|
4490
4490
|
"filename": "src/iam-grant.ts",
|
|
4491
|
-
"line":
|
|
4491
|
+
"line": 6
|
|
4492
4492
|
},
|
|
4493
4493
|
"name": "IamGrantProps",
|
|
4494
4494
|
"properties": [
|
|
@@ -4501,7 +4501,7 @@
|
|
|
4501
4501
|
"immutable": true,
|
|
4502
4502
|
"locationInModule": {
|
|
4503
4503
|
"filename": "src/iam-grant.ts",
|
|
4504
|
-
"line":
|
|
4504
|
+
"line": 10
|
|
4505
4505
|
},
|
|
4506
4506
|
"name": "provider",
|
|
4507
4507
|
"type": {
|
|
@@ -4517,7 +4517,7 @@
|
|
|
4517
4517
|
"immutable": true,
|
|
4518
4518
|
"locationInModule": {
|
|
4519
4519
|
"filename": "src/iam-grant.ts",
|
|
4520
|
-
"line":
|
|
4520
|
+
"line": 20
|
|
4521
4521
|
},
|
|
4522
4522
|
"name": "resourceArn",
|
|
4523
4523
|
"type": {
|
|
@@ -4533,7 +4533,7 @@
|
|
|
4533
4533
|
"immutable": true,
|
|
4534
4534
|
"locationInModule": {
|
|
4535
4535
|
"filename": "src/iam-grant.ts",
|
|
4536
|
-
"line":
|
|
4536
|
+
"line": 15
|
|
4537
4537
|
},
|
|
4538
4538
|
"name": "roleName",
|
|
4539
4539
|
"type": {
|
|
@@ -5095,7 +5095,7 @@
|
|
|
5095
5095
|
},
|
|
5096
5096
|
"locationInModule": {
|
|
5097
5097
|
"filename": "src/role.ts",
|
|
5098
|
-
"line":
|
|
5098
|
+
"line": 165
|
|
5099
5099
|
},
|
|
5100
5100
|
"parameters": [
|
|
5101
5101
|
{
|
|
@@ -5121,7 +5121,7 @@
|
|
|
5121
5121
|
"kind": "class",
|
|
5122
5122
|
"locationInModule": {
|
|
5123
5123
|
"filename": "src/role.ts",
|
|
5124
|
-
"line":
|
|
5124
|
+
"line": 147
|
|
5125
5125
|
},
|
|
5126
5126
|
"name": "Role",
|
|
5127
5127
|
"properties": [
|
|
@@ -5133,7 +5133,7 @@
|
|
|
5133
5133
|
"immutable": true,
|
|
5134
5134
|
"locationInModule": {
|
|
5135
5135
|
"filename": "src/role.ts",
|
|
5136
|
-
"line":
|
|
5136
|
+
"line": 151
|
|
5137
5137
|
},
|
|
5138
5138
|
"name": "roleName",
|
|
5139
5139
|
"type": {
|
|
@@ -5142,14 +5142,14 @@
|
|
|
5142
5142
|
},
|
|
5143
5143
|
{
|
|
5144
5144
|
"docs": {
|
|
5145
|
-
"remarks": "
|
|
5145
|
+
"remarks": "This is only available when:\n- The provider is not a DSQL cluster (DSQL uses IAM authentication)\n- `enableIamAuth` is not set to `true`\n\nWhen using IAM authentication, no secret is created as the password\nis generated dynamically using IAM credentials.",
|
|
5146
5146
|
"stability": "stable",
|
|
5147
|
-
"summary": "The generated secret."
|
|
5147
|
+
"summary": "The generated secret containing connection information and password."
|
|
5148
5148
|
},
|
|
5149
5149
|
"immutable": true,
|
|
5150
5150
|
"locationInModule": {
|
|
5151
5151
|
"filename": "src/role.ts",
|
|
5152
|
-
"line":
|
|
5152
|
+
"line": 163
|
|
5153
5153
|
},
|
|
5154
5154
|
"name": "secret",
|
|
5155
5155
|
"optional": true,
|
|
@@ -5246,7 +5246,7 @@
|
|
|
5246
5246
|
"abstract": true,
|
|
5247
5247
|
"docs": {
|
|
5248
5248
|
"default": "false - use password authentication",
|
|
5249
|
-
"remarks": "When enabled, the role will be created without a password and\nconfigured for AWS IAM database authentication.
|
|
5249
|
+
"remarks": "When enabled, the role will be created without a password and\nconfigured for AWS IAM database authentication. No secret will\nbe created for this role.\n\nNote: For DSQL clusters, this property is ignored as DSQL always\nuses IAM authentication.",
|
|
5250
5250
|
"stability": "stable",
|
|
5251
5251
|
"summary": "Enable IAM authentication for this role."
|
|
5252
5252
|
},
|
|
@@ -5594,6 +5594,6 @@
|
|
|
5594
5594
|
"symbolId": "src/sql:SqlProps"
|
|
5595
5595
|
}
|
|
5596
5596
|
},
|
|
5597
|
-
"version": "
|
|
5598
|
-
"fingerprint": "
|
|
5597
|
+
"version": "8.0.0",
|
|
5598
|
+
"fingerprint": "nObbSYqIUQCnw0PeMMkzqtNsYFp8MurtEPxO/8iirFo="
|
|
5599
5599
|
}
|
package/README.md
CHANGED
|
@@ -161,18 +161,13 @@ const iamRole = new Role(this, "IamRole", {
|
|
|
161
161
|
})
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
When `enableIamAuth` is set to `true`:
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
"port": 5432,
|
|
172
|
-
"host": "teststack-clustereb1186t9-sh4wpqfdyfvu.cluster-cgudolabssna.us-east-1.rds.amazonaws.com",
|
|
173
|
-
"username": "myiamrole"
|
|
174
|
-
}
|
|
175
|
-
```
|
|
166
|
+
- **No secret is created** - the `role.secret` property will be `undefined`
|
|
167
|
+
- The database role is created without a password
|
|
168
|
+
- Your application must generate an IAM authentication token at runtime
|
|
169
|
+
|
|
170
|
+
This is the same behavior as DSQL clusters, which always use IAM authentication.
|
|
176
171
|
|
|
177
172
|
**Requirements for IAM Authentication:**
|
|
178
173
|
|
|
@@ -199,6 +194,36 @@ Your application will need an IAM policy like this to connect:
|
|
|
199
194
|
}
|
|
200
195
|
```
|
|
201
196
|
|
|
197
|
+
**Generating an IAM Authentication Token:**
|
|
198
|
+
|
|
199
|
+
At runtime, your application needs to generate an authentication token
|
|
200
|
+
using the AWS SDK. Here's an example using the AWS SDK for JavaScript:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import { Signer } from "@aws-sdk/rds-signer"
|
|
204
|
+
import { Client } from "pg"
|
|
205
|
+
|
|
206
|
+
const signer = new Signer({
|
|
207
|
+
hostname: "your-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com",
|
|
208
|
+
port: 5432,
|
|
209
|
+
username: "myiamrole",
|
|
210
|
+
region: "us-east-1",
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
const token = await signer.getAuthToken()
|
|
214
|
+
|
|
215
|
+
const client = new Client({
|
|
216
|
+
host: "your-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com",
|
|
217
|
+
port: 5432,
|
|
218
|
+
user: "myiamrole",
|
|
219
|
+
database: "mydb",
|
|
220
|
+
password: token,
|
|
221
|
+
ssl: { rejectUnauthorized: true },
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
await client.connect()
|
|
225
|
+
```
|
|
226
|
+
|
|
202
227
|
Both PostgreSQL and MySQL databases support IAM authentication. For more details, see the [AWS RDS IAM Database Authentication documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html).
|
|
203
228
|
|
|
204
229
|
### MySQL support
|
package/lib/database.js
CHANGED
|
@@ -45,5 +45,5 @@ class Database extends aws_cdk_lib_1.CustomResource {
|
|
|
45
45
|
}
|
|
46
46
|
exports.Database = Database;
|
|
47
47
|
_a = JSII_RTTI_SYMBOL_1;
|
|
48
|
-
Database[_a] = { fqn: "cdk-rds-sql.Database", version: "
|
|
48
|
+
Database[_a] = { fqn: "cdk-rds-sql.Database", version: "8.0.0" };
|
|
49
49
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZGF0YWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBNEM7QUFDNUMsMkNBQXNDO0FBQ3RDLGlDQUF1QztBQUN2Qyx5Q0FBc0Q7QUEwQnRELE1BQU0sZ0JBQWlCLFNBQVEsc0JBQVM7SUFHdEMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF5QjtRQUNqRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBQ2hCLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQTtJQUN4QyxDQUFDO0NBQ0Y7QUFFRCxNQUFhLFFBQVMsU0FBUSw0QkFBYztJQUMxQzs7T0FFRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFnQixFQUFFLEVBQVUsRUFBRSxZQUFvQjtRQUN4RSxPQUFPLElBQUksZ0JBQWdCLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNyQyxZQUFZLEVBQUUsWUFBWTtTQUMzQixDQUFDLENBQUE7SUFDSixDQUFDO0lBSUQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFvQjtRQUM1RCw0REFBNEQ7UUFDNUQsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyx5QkFBYyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2xELE1BQU0sSUFBSSxLQUFLLENBQ2IscUZBQXFGLENBQ3RGLENBQUE7UUFDSCxDQUFDO1FBRUQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixZQUFZLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFZO1lBQ3pDLFVBQVUsRUFBRTtnQkFDVixRQUFRLEVBQUUscUJBQWMsQ0FBQyxRQUFRO2dCQUNqQyxVQUFVLEVBQUUsS0FBSyxDQUFDLFlBQVk7Z0JBQzlCLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDaEYsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsUUFBUTthQUM3QjtTQUNGLENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUN2QyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUE7UUFDdEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ3RDLENBQUM7SUFDSCxDQUFDOztBQWxDSCw0QkFtQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXN0b21SZXNvdXJjZSB9IGZyb20gXCJhd3MtY2RrLWxpYlwiXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiXG5pbXBvcnQgeyBSZHNTcWxSZXNvdXJjZSB9IGZyb20gXCIuL2VudW1cIlxuaW1wb3J0IHsgSVByb3ZpZGVyLCBEYXRhYmFzZUVuZ2luZSB9IGZyb20gXCIuL3Byb3ZpZGVyXCJcbmltcG9ydCB7IFJvbGUgfSBmcm9tIFwiLi9yb2xlXCJcblxuaW50ZXJmYWNlIERhdGFiYXNlQXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIGRhdGFiYXNlIHRvIGNyZWF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGFiYXNlTmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGRhdGFiYXNlIG93bmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgb3duZXI/OiBSb2xlXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YWJhc2VQcm9wcyBleHRlbmRzIERhdGFiYXNlQXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBQcm92aWRlci5cbiAgICovXG4gIHJlYWRvbmx5IHByb3ZpZGVyOiBJUHJvdmlkZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRGF0YWJhc2Uge1xuICByZWFkb25seSBkYXRhYmFzZU5hbWU6IHN0cmluZ1xufVxuXG5jbGFzcyBJbXBvcnRlZERhdGFiYXNlIGV4dGVuZHMgQ29uc3RydWN0IGltcGxlbWVudHMgSURhdGFiYXNlIHtcbiAgcHVibGljIHJlYWRvbmx5IGRhdGFiYXNlTmFtZTogc3RyaW5nXG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IERhdGFiYXNlQXR0cmlidXRlcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZClcbiAgICB0aGlzLmRhdGFiYXNlTmFtZSA9IHByb3BzLmRhdGFiYXNlTmFtZVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBEYXRhYmFzZSBleHRlbmRzIEN1c3RvbVJlc291cmNlIGltcGxlbWVudHMgSURhdGFiYXNlIHtcbiAgLyoqXG4gICAqIFJldHVybiBhIERhdGFiYXNlIGJhc2VkIHVwb24gbmFtZSBvbmx5LiBVc2UgZm9yIGltcG9ydGluZyBleGlzdGluZyBkYXRhYmFzZXMuXG4gICAqL1xuICBzdGF0aWMgZnJvbURhdGFiYXNlTmFtZShzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBkYXRhYmFzZU5hbWU6IHN0cmluZyk6IElEYXRhYmFzZSB7XG4gICAgcmV0dXJuIG5ldyBJbXBvcnRlZERhdGFiYXNlKHNjb3BlLCBpZCwge1xuICAgICAgZGF0YWJhc2VOYW1lOiBkYXRhYmFzZU5hbWUsXG4gICAgfSlcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBkYXRhYmFzZU5hbWU6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEYXRhYmFzZVByb3BzKSB7XG4gICAgLy8gQ2hlY2sgaWYgdXNpbmcgRFNRTCBwcm92aWRlciBhbmQgZm9yYmlkIGRhdGFiYXNlIGNyZWF0aW9uXG4gICAgaWYgKHByb3BzLnByb3ZpZGVyLmVuZ2luZSA9PT0gRGF0YWJhc2VFbmdpbmUuRFNRTCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIkRhdGFiYXNlIGNyZWF0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aCBEU1FMLiBEU1FMIGFsd2F5cyB1c2VzICdwb3N0Z3JlcycgZGF0YWJhc2UuXCJcbiAgICAgIClcbiAgICB9XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogcHJvcHMucHJvdmlkZXIuc2VydmljZVRva2VuLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBSZXNvdXJjZTogUmRzU3FsUmVzb3VyY2UuREFUQUJBU0UsXG4gICAgICAgIFJlc291cmNlSWQ6IHByb3BzLmRhdGFiYXNlTmFtZSxcbiAgICAgICAgLi4uKHByb3BzLnByb3ZpZGVyLnNlY3JldCA/IHsgU2VjcmV0QXJuOiBwcm9wcy5wcm92aWRlci5zZWNyZXQuc2VjcmV0QXJuIH0gOiB7fSksXG4gICAgICAgIE93bmVyOiBwcm9wcy5vd25lcj8ucm9sZU5hbWUsXG4gICAgICB9LFxuICAgIH0pXG4gICAgdGhpcy5ub2RlLmFkZERlcGVuZGVuY3kocHJvcHMucHJvdmlkZXIpXG4gICAgdGhpcy5kYXRhYmFzZU5hbWUgPSBwcm9wcy5kYXRhYmFzZU5hbWVcbiAgICBpZiAocHJvcHMub3duZXIpIHtcbiAgICAgIHRoaXMubm9kZS5hZGREZXBlbmRlbmN5KHByb3BzLm93bmVyKVxuICAgIH1cbiAgfVxufVxuIl19
|
package/lib/handler/handler.js
CHANGED
|
@@ -2336,7 +2336,7 @@ var require_cert_signatures = __commonJS({
|
|
|
2336
2336
|
var require_sasl = __commonJS({
|
|
2337
2337
|
"node_modules/pg/lib/crypto/sasl.js"(exports2, module2) {
|
|
2338
2338
|
"use strict";
|
|
2339
|
-
var
|
|
2339
|
+
var crypto2 = require_utils2();
|
|
2340
2340
|
var { signatureAlgorithmHashFromCertificate } = require_cert_signatures();
|
|
2341
2341
|
function startSession(mechanisms, stream) {
|
|
2342
2342
|
const candidates = ["SCRAM-SHA-256"];
|
|
@@ -2348,7 +2348,7 @@ var require_sasl = __commonJS({
|
|
|
2348
2348
|
if (mechanism === "SCRAM-SHA-256-PLUS" && typeof stream.getPeerCertificate !== "function") {
|
|
2349
2349
|
throw new Error("SASL: Mechanism SCRAM-SHA-256-PLUS requires a certificate");
|
|
2350
2350
|
}
|
|
2351
|
-
const clientNonce =
|
|
2351
|
+
const clientNonce = crypto2.randomBytes(18).toString("base64");
|
|
2352
2352
|
const gs2Header = mechanism === "SCRAM-SHA-256-PLUS" ? "p=tls-server-end-point" : stream ? "y" : "n";
|
|
2353
2353
|
return {
|
|
2354
2354
|
mechanism,
|
|
@@ -2383,20 +2383,20 @@ var require_sasl = __commonJS({
|
|
|
2383
2383
|
const peerCert = stream.getPeerCertificate().raw;
|
|
2384
2384
|
let hashName = signatureAlgorithmHashFromCertificate(peerCert);
|
|
2385
2385
|
if (hashName === "MD5" || hashName === "SHA-1") hashName = "SHA-256";
|
|
2386
|
-
const certHash = await
|
|
2386
|
+
const certHash = await crypto2.hashByName(hashName, peerCert);
|
|
2387
2387
|
const bindingData = Buffer.concat([Buffer.from("p=tls-server-end-point,,"), Buffer.from(certHash)]);
|
|
2388
2388
|
channelBinding = bindingData.toString("base64");
|
|
2389
2389
|
}
|
|
2390
2390
|
const clientFinalMessageWithoutProof = "c=" + channelBinding + ",r=" + sv.nonce;
|
|
2391
2391
|
const authMessage = clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
|
|
2392
2392
|
const saltBytes = Buffer.from(sv.salt, "base64");
|
|
2393
|
-
const saltedPassword = await
|
|
2394
|
-
const clientKey = await
|
|
2395
|
-
const storedKey = await
|
|
2396
|
-
const clientSignature = await
|
|
2393
|
+
const saltedPassword = await crypto2.deriveKey(password, saltBytes, sv.iteration);
|
|
2394
|
+
const clientKey = await crypto2.hmacSha256(saltedPassword, "Client Key");
|
|
2395
|
+
const storedKey = await crypto2.sha256(clientKey);
|
|
2396
|
+
const clientSignature = await crypto2.hmacSha256(storedKey, authMessage);
|
|
2397
2397
|
const clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString("base64");
|
|
2398
|
-
const serverKey = await
|
|
2399
|
-
const serverSignatureBytes = await
|
|
2398
|
+
const serverKey = await crypto2.hmacSha256(saltedPassword, "Server Key");
|
|
2399
|
+
const serverSignatureBytes = await crypto2.hmacSha256(serverKey, authMessage);
|
|
2400
2400
|
session.message = "SASLResponse";
|
|
2401
2401
|
session.serverSignature = Buffer.from(serverSignatureBytes).toString("base64");
|
|
2402
2402
|
session.response = clientFinalMessageWithoutProof + ",p=" + clientProof;
|
|
@@ -4532,7 +4532,7 @@ var require_client = __commonJS({
|
|
|
4532
4532
|
var Query2 = require_query();
|
|
4533
4533
|
var defaults2 = require_defaults();
|
|
4534
4534
|
var Connection2 = require_connection();
|
|
4535
|
-
var
|
|
4535
|
+
var crypto2 = require_utils2();
|
|
4536
4536
|
var Client2 = class extends EventEmitter {
|
|
4537
4537
|
constructor(config) {
|
|
4538
4538
|
super();
|
|
@@ -4727,7 +4727,7 @@ var require_client = __commonJS({
|
|
|
4727
4727
|
_handleAuthMD5Password(msg) {
|
|
4728
4728
|
this._checkPgPass(async () => {
|
|
4729
4729
|
try {
|
|
4730
|
-
const hashedPassword = await
|
|
4730
|
+
const hashedPassword = await crypto2.postgresMd5PasswordHash(this.user, this.password, msg.salt);
|
|
4731
4731
|
this.connection.password(hashedPassword);
|
|
4732
4732
|
} catch (e) {
|
|
4733
4733
|
this.emit("error", e);
|
|
@@ -16834,9 +16834,9 @@ var require_client3 = __commonJS({
|
|
|
16834
16834
|
var require_auth_41 = __commonJS({
|
|
16835
16835
|
"node_modules/mysql2/lib/auth_41.js"(exports2) {
|
|
16836
16836
|
"use strict";
|
|
16837
|
-
var
|
|
16837
|
+
var crypto2 = require("crypto");
|
|
16838
16838
|
function sha1(msg, msg1, msg2) {
|
|
16839
|
-
const hash =
|
|
16839
|
+
const hash = crypto2.createHash("sha1");
|
|
16840
16840
|
hash.update(msg);
|
|
16841
16841
|
if (msg1) {
|
|
16842
16842
|
hash.update(msg1);
|
|
@@ -18585,7 +18585,7 @@ var require_sha256_password = __commonJS({
|
|
|
18585
18585
|
"node_modules/mysql2/lib/auth_plugins/sha256_password.js"(exports2, module2) {
|
|
18586
18586
|
"use strict";
|
|
18587
18587
|
var PLUGIN_NAME = "sha256_password";
|
|
18588
|
-
var
|
|
18588
|
+
var crypto2 = require("crypto");
|
|
18589
18589
|
var { xorRotating } = require_auth_41();
|
|
18590
18590
|
var REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);
|
|
18591
18591
|
var STATE_INITIAL = 0;
|
|
@@ -18593,7 +18593,7 @@ var require_sha256_password = __commonJS({
|
|
|
18593
18593
|
var STATE_FINAL = -1;
|
|
18594
18594
|
function encrypt(password, scramble, key) {
|
|
18595
18595
|
const stage1 = xorRotating(Buffer.from(`${password}\0`, "utf8"), scramble);
|
|
18596
|
-
return
|
|
18596
|
+
return crypto2.publicEncrypt(key, stage1);
|
|
18597
18597
|
}
|
|
18598
18598
|
module2.exports = (pluginOptions = {}) => ({ connection }) => {
|
|
18599
18599
|
let state = 0;
|
|
@@ -18636,7 +18636,7 @@ var require_caching_sha2_password = __commonJS({
|
|
|
18636
18636
|
"node_modules/mysql2/lib/auth_plugins/caching_sha2_password.js"(exports2, module2) {
|
|
18637
18637
|
"use strict";
|
|
18638
18638
|
var PLUGIN_NAME = "caching_sha2_password";
|
|
18639
|
-
var
|
|
18639
|
+
var crypto2 = require("crypto");
|
|
18640
18640
|
var { xor, xorRotating } = require_auth_41();
|
|
18641
18641
|
var REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
|
|
18642
18642
|
var FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
|
|
@@ -18646,7 +18646,7 @@ var require_caching_sha2_password = __commonJS({
|
|
|
18646
18646
|
var STATE_WAIT_SERVER_KEY = 2;
|
|
18647
18647
|
var STATE_FINAL = -1;
|
|
18648
18648
|
function sha256(msg) {
|
|
18649
|
-
const hash =
|
|
18649
|
+
const hash = crypto2.createHash("sha256");
|
|
18650
18650
|
hash.update(msg);
|
|
18651
18651
|
return hash.digest();
|
|
18652
18652
|
}
|
|
@@ -18661,10 +18661,10 @@ var require_caching_sha2_password = __commonJS({
|
|
|
18661
18661
|
}
|
|
18662
18662
|
function encrypt(password, scramble, key) {
|
|
18663
18663
|
const stage1 = xorRotating(Buffer.from(`${password}\0`, "utf8"), scramble);
|
|
18664
|
-
return
|
|
18664
|
+
return crypto2.publicEncrypt(
|
|
18665
18665
|
{
|
|
18666
18666
|
key,
|
|
18667
|
-
padding:
|
|
18667
|
+
padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
|
|
18668
18668
|
},
|
|
18669
18669
|
stage1
|
|
18670
18670
|
);
|
|
@@ -25383,6 +25383,7 @@ __export(handler_exports, {
|
|
|
25383
25383
|
handler: () => handler
|
|
25384
25384
|
});
|
|
25385
25385
|
module.exports = __toCommonJS(handler_exports);
|
|
25386
|
+
var crypto = __toESM(require("crypto"));
|
|
25386
25387
|
var import_client_secrets_manager2 = require("@aws-sdk/client-secrets-manager");
|
|
25387
25388
|
var import_client_ssm = require("@aws-sdk/client-ssm");
|
|
25388
25389
|
var import_exponential_backoff = __toESM(require_backoff());
|
|
@@ -26208,7 +26209,7 @@ var handler = async (event) => {
|
|
|
26208
26209
|
log(event);
|
|
26209
26210
|
const requestType = event.RequestType;
|
|
26210
26211
|
const resource = event.ResourceProperties.Resource;
|
|
26211
|
-
const resourceId = event.ResourceProperties.ResourceId;
|
|
26212
|
+
const resourceId = event.ResourceProperties.ResourceId ?? "";
|
|
26212
26213
|
const databaseName = event.ResourceProperties.DatabaseName;
|
|
26213
26214
|
if (!Object.values(RdsSqlResource).includes(resource)) {
|
|
26214
26215
|
throw `Resource type '${resource}' not recognised.`;
|
|
@@ -26408,8 +26409,14 @@ var handler = async (event) => {
|
|
|
26408
26409
|
}
|
|
26409
26410
|
}
|
|
26410
26411
|
let response = {};
|
|
26411
|
-
if (
|
|
26412
|
+
if (resourceId) {
|
|
26412
26413
|
response.PhysicalResourceId = resourceId;
|
|
26414
|
+
} else {
|
|
26415
|
+
if (resource === "iam_grant" /* IAM_GRANT */) {
|
|
26416
|
+
const iamProps = toIamGrantEngineProps(event.ResourceProperties);
|
|
26417
|
+
const hash = crypto.createHash("sha256").update(iamProps.ResourceArn).digest("hex").substring(0, 8);
|
|
26418
|
+
response.PhysicalResourceId = `${iamProps.RoleName}:${hash}`;
|
|
26419
|
+
}
|
|
26413
26420
|
}
|
|
26414
26421
|
return response;
|
|
26415
26422
|
};
|
package/lib/iam-grant.d.ts
CHANGED
package/lib/iam-grant.js
CHANGED
|
@@ -3,19 +3,10 @@ var _a;
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.IamGrant = void 0;
|
|
5
5
|
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
-
const crypto = require("crypto");
|
|
7
6
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
8
7
|
const enum_1 = require("./enum");
|
|
9
8
|
const provider_1 = require("./provider");
|
|
10
9
|
class IamGrant extends aws_cdk_lib_1.CustomResource {
|
|
11
|
-
static createUniqueResourceId(roleName, resourceArn) {
|
|
12
|
-
const hash = crypto
|
|
13
|
-
.createHash("sha256")
|
|
14
|
-
.update(resourceArn)
|
|
15
|
-
.digest("hex")
|
|
16
|
-
.substring(0, 8);
|
|
17
|
-
return `${roleName}:${hash}`;
|
|
18
|
-
}
|
|
19
10
|
constructor(scope, id, props) {
|
|
20
11
|
// IAM grants are only supported on DSQL
|
|
21
12
|
if (props.provider.engine !== provider_1.DatabaseEngine.DSQL) {
|
|
@@ -26,7 +17,6 @@ class IamGrant extends aws_cdk_lib_1.CustomResource {
|
|
|
26
17
|
resourceType: "Custom::DsqlIamGrant",
|
|
27
18
|
properties: {
|
|
28
19
|
Resource: enum_1.RdsSqlResource.IAM_GRANT,
|
|
29
|
-
ResourceId: IamGrant.createUniqueResourceId(props.roleName, props.resourceArn),
|
|
30
20
|
RoleName: props.roleName,
|
|
31
21
|
ResourceArn: props.resourceArn,
|
|
32
22
|
},
|
|
@@ -36,5 +26,5 @@ class IamGrant extends aws_cdk_lib_1.CustomResource {
|
|
|
36
26
|
}
|
|
37
27
|
exports.IamGrant = IamGrant;
|
|
38
28
|
_a = JSII_RTTI_SYMBOL_1;
|
|
39
|
-
IamGrant[_a] = { fqn: "cdk-rds-sql.IamGrant", version: "
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
29
|
+
IamGrant[_a] = { fqn: "cdk-rds-sql.IamGrant", version: "8.0.0" };
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWFtLWdyYW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2lhbS1ncmFudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUE0QztBQUU1QyxpQ0FBdUM7QUFDdkMseUNBQXNEO0FBbUJ0RCxNQUFhLFFBQVMsU0FBUSw0QkFBYztJQUMxQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQW9CO1FBQzVELHdDQUF3QztRQUN4QyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLHlCQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEQsTUFBTSxJQUFJLEtBQUssQ0FDYixnSEFBZ0gsQ0FDakgsQ0FBQTtRQUNILENBQUM7UUFFRCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFlBQVksRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVk7WUFDekMsWUFBWSxFQUFFLHNCQUFzQjtZQUNwQyxVQUFVLEVBQUU7Z0JBQ1YsUUFBUSxFQUFFLHFCQUFjLENBQUMsU0FBUztnQkFDbEMsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO2dCQUN4QixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7YUFDL0I7U0FDRixDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDekMsQ0FBQzs7QUFuQkgsNEJBb0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ3VzdG9tUmVzb3VyY2UgfSBmcm9tIFwiYXdzLWNkay1saWJcIlxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIlxuaW1wb3J0IHsgUmRzU3FsUmVzb3VyY2UgfSBmcm9tIFwiLi9lbnVtXCJcbmltcG9ydCB7IElQcm92aWRlciwgRGF0YWJhc2VFbmdpbmUgfSBmcm9tIFwiLi9wcm92aWRlclwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgSWFtR3JhbnRQcm9wcyB7XG4gIC8qKlxuICAgKiBQcm92aWRlci5cbiAgICovXG4gIHJlYWRvbmx5IHByb3ZpZGVyOiBJUHJvdmlkZXJcblxuICAvKipcbiAgICogRGF0YWJhc2Ugcm9sZSBuYW1lIHRvIGdyYW50IElBTSBhY2Nlc3MgdG8uXG4gICAqL1xuICByZWFkb25seSByb2xlTmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIElBTSByZXNvdXJjZSBBUk4gKHJvbGUsIHVzZXIsIG9yIG90aGVyIElBTSBwcmluY2lwYWwpLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VBcm46IHN0cmluZ1xufVxuXG5leHBvcnQgY2xhc3MgSWFtR3JhbnQgZXh0ZW5kcyBDdXN0b21SZXNvdXJjZSB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBJYW1HcmFudFByb3BzKSB7XG4gICAgLy8gSUFNIGdyYW50cyBhcmUgb25seSBzdXBwb3J0ZWQgb24gRFNRTFxuICAgIGlmIChwcm9wcy5wcm92aWRlci5lbmdpbmUgIT09IERhdGFiYXNlRW5naW5lLkRTUUwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJJQU0gZ3JhbnRzIGFyZSBvbmx5IHN1cHBvcnRlZCB3aXRoIERTUUwgY2x1c3RlcnMuIFVzZSByZWd1bGFyIGRhdGFiYXNlIGF1dGhlbnRpY2F0aW9uIGZvciBSRFMvQXVyb3JhIGNsdXN0ZXJzLlwiXG4gICAgICApXG4gICAgfVxuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3BzLnByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHJlc291cmNlVHlwZTogXCJDdXN0b206OkRzcWxJYW1HcmFudFwiLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBSZXNvdXJjZTogUmRzU3FsUmVzb3VyY2UuSUFNX0dSQU5ULFxuICAgICAgICBSb2xlTmFtZTogcHJvcHMucm9sZU5hbWUsXG4gICAgICAgIFJlc291cmNlQXJuOiBwcm9wcy5yZXNvdXJjZUFybixcbiAgICAgIH0sXG4gICAgfSlcbiAgICB0aGlzLm5vZGUuYWRkRGVwZW5kZW5jeShwcm9wcy5wcm92aWRlcilcbiAgfVxufVxuIl19
|
package/lib/provider.js
CHANGED
|
@@ -209,7 +209,7 @@ class Provider extends constructs_1.Construct {
|
|
|
209
209
|
}
|
|
210
210
|
exports.Provider = Provider;
|
|
211
211
|
_a = JSII_RTTI_SYMBOL_1;
|
|
212
|
-
Provider[_a] = { fqn: "cdk-rds-sql.Provider", version: "
|
|
212
|
+
Provider[_a] = { fqn: "cdk-rds-sql.Provider", version: "8.0.0" };
|
|
213
213
|
class ImportedProvider extends constructs_1.Construct {
|
|
214
214
|
constructor(scope, id, attrs) {
|
|
215
215
|
super(scope, id);
|
package/lib/role.d.ts
CHANGED
|
@@ -62,8 +62,8 @@ export interface RoleProps {
|
|
|
62
62
|
* Enable IAM authentication for this role.
|
|
63
63
|
*
|
|
64
64
|
* When enabled, the role will be created without a password and
|
|
65
|
-
* configured for AWS IAM database authentication.
|
|
66
|
-
*
|
|
65
|
+
* configured for AWS IAM database authentication. No secret will
|
|
66
|
+
* be created for this role.
|
|
67
67
|
*
|
|
68
68
|
* Note: For DSQL clusters, this property is ignored as DSQL always
|
|
69
69
|
* uses IAM authentication.
|
|
@@ -78,8 +78,14 @@ export declare class Role extends Construct {
|
|
|
78
78
|
*/
|
|
79
79
|
readonly roleName: string;
|
|
80
80
|
/**
|
|
81
|
-
* The generated secret.
|
|
82
|
-
*
|
|
81
|
+
* The generated secret containing connection information and password.
|
|
82
|
+
*
|
|
83
|
+
* This is only available when:
|
|
84
|
+
* - The provider is not a DSQL cluster (DSQL uses IAM authentication)
|
|
85
|
+
* - `enableIamAuth` is not set to `true`
|
|
86
|
+
*
|
|
87
|
+
* When using IAM authentication, no secret is created as the password
|
|
88
|
+
* is generated dynamically using IAM credentials.
|
|
83
89
|
*/
|
|
84
90
|
readonly secret?: ISecret;
|
|
85
91
|
constructor(scope: Construct, id: string, props: RoleProps);
|