software.amazon.awscdk.services.redshift.package-info Maven / Gradle / Ivy
Show all versions of redshift Show documentation
/**
* Amazon Redshift Construct Library
*
* ---
*
*
*
*
*
* All classes with the Cfn
prefix in this module (CFN Resources) are always stable and safe to use.
*
*
*
*
*
*
*
* 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 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.
*
*
*
*
*
*
*
*
Starting a Redshift Cluster Database
*
* To set up a Redshift cluster, define a Cluster
. It will be launched in a VPC.
* You can specify a VPC, otherwise one will be created. The nodes are always launched in private subnets and are encrypted by default.
*
*
* import software.amazon.awscdk.services.ec2.*;
*
*
* Vpc vpc = new Vpc(this, "Vpc");
* Cluster cluster = Cluster.Builder.create(this, "Redshift")
* .masterUser(Login.builder()
* .masterUsername("admin")
* .build())
* .vpc(vpc)
* .build();
*
*
* By default, the master password will be generated and stored in AWS Secrets Manager.
*
* A default database named default_db
will be created in the cluster. To change the name of this database set the defaultDatabaseName
attribute in the constructor properties.
*
* By default, the cluster will not be publicly accessible.
* Depending on your use case, you can make the cluster publicly accessible with the publiclyAccessible
property.
*
*
Connecting
*
* To control who can access the cluster, use the .connections
attribute. Redshift Clusters have
* a default port, so you don't need to specify the port:
*
*
* cluster.connections.allowDefaultPortFromAnyIpv4("Open to the world");
*
*
* The endpoint to access your database cluster will be available as the .clusterEndpoint
attribute:
*
*
* cluster.getClusterEndpoint().getSocketAddress();
*
*
*
Database Resources
*
* This module allows for the creation of non-CloudFormation database resources such as users
* and tables. This allows you to manage identities, permissions, and stateful resources
* within your Redshift cluster from your CDK application.
*
* Because these resources are not available in CloudFormation, this library leverages
* custom
* resources
* to manage them. In addition to the IAM permissions required to make Redshift service
* calls, the execution role for the custom resource handler requires database credentials to
* create resources within the cluster.
*
* These database credentials can be supplied explicitly through the adminUser
properties
* of the various database resource constructs. Alternatively, the credentials can be
* automatically pulled from the Redshift cluster's default administrator
* credentials. However, this option is only available if the password for the credentials
* was generated by the CDK application (ie., no value vas provided for the masterPassword
* property
* of
* Cluster.masterUser
).
*
*
Creating Users
*
* Create a user within a Redshift cluster database by instantiating a User
construct. This
* will generate a username and password, store the credentials in a AWS Secrets Manager
* Secret
,
* and make a query to the Redshift cluster to create a new database user with the
* credentials.
*
*
* User.Builder.create(this, "User")
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
*
*
* By default, the user credentials are encrypted with your AWS account's default Secrets
* Manager encryption key. You can specify the encryption key used for this purpose by
* supplying a key in the encryptionKey
property.
*
*
* import software.amazon.awscdk.services.kms.*;
*
*
* Key encryptionKey = new Key(this, "Key");
* User.Builder.create(this, "User")
* .encryptionKey(encryptionKey)
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
*
*
* By default, a username is automatically generated from the user construct ID and its path
* in the construct tree. You can specify a particular username by providing a value for the
* username
property. Usernames must be valid identifiers; see: Names and
* identifiers in the Amazon
* Redshift Database Developer Guide.
*
*
* User.Builder.create(this, "User")
* .username("myuser")
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
*
*
* The user password is generated by AWS Secrets Manager using the default configuration
* found in
* secretsmanager.SecretStringGenerator
,
* except with password length 30
and some SQL-incompliant characters excluded. The
* plaintext for the password will never be present in the CDK application; instead, a
* CloudFormation Dynamic
* Reference
* will be used wherever the password value is required.
*
*
Creating Tables
*
* Create a table within a Redshift cluster database by instantiating a Table
* construct. This will make a query to the Redshift cluster to create a new database table
* with the supplied schema.
*
*
* Table.Builder.create(this, "Table")
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").build(), Column.builder().name("col2").dataType("float").build()))
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
*
*
* The table can be configured to have distStyle attribute and a distKey column:
*
*
* Table.Builder.create(this, "Table")
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").distKey(true).build(), Column.builder().name("col2").dataType("float").build()))
* .cluster(cluster)
* .databaseName("databaseName")
* .distStyle(TableDistStyle.KEY)
* .build();
*
*
* The table can also be configured to have sortStyle attribute and sortKey columns:
*
*
* Table.Builder.create(this, "Table")
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").sortKey(true).build(), Column.builder().name("col2").dataType("float").sortKey(true).build()))
* .cluster(cluster)
* .databaseName("databaseName")
* .sortStyle(TableSortStyle.COMPOUND)
* .build();
*
*
*
Granting Privileges
*
* You can give a user privileges to perform certain actions on a table by using the
* Table.grant()
method.
*
*
* User user = User.Builder.create(this, "User")
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
* Table table = Table.Builder.create(this, "Table")
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").build(), Column.builder().name("col2").dataType("float").build()))
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
*
* table.grant(user, TableAction.DROP, TableAction.SELECT);
*
*
* Take care when managing privileges via the CDK, as attempting to manage a user's
* privileges on the same table in multiple CDK applications could lead to accidentally
* overriding these permissions. Consider the following two CDK applications which both refer
* to the same user and table. In application 1, the resources are created and the user is
* given INSERT
permissions on the table:
*
*
* String databaseName = "databaseName";
* String username = "myuser";
* String tableName = "mytable";
*
* User user = User.Builder.create(this, "User")
* .username(username)
* .cluster(cluster)
* .databaseName(databaseName)
* .build();
* Table table = Table.Builder.create(this, "Table")
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").build(), Column.builder().name("col2").dataType("float").build()))
* .cluster(cluster)
* .databaseName(databaseName)
* .build();
* table.grant(user, TableAction.INSERT);
*
*
* In application 2, the resources are imported and the user is given INSERT
permissions on
* the table:
*
*
* String databaseName = "databaseName";
* String username = "myuser";
* String tableName = "mytable";
*
* IUser user = User.fromUserAttributes(this, "User", UserAttributes.builder()
* .username(username)
* .password(SecretValue.unsafePlainText("NOT_FOR_PRODUCTION"))
* .cluster(cluster)
* .databaseName(databaseName)
* .build());
* ITable table = Table.fromTableAttributes(this, "Table", TableAttributes.builder()
* .tableName(tableName)
* .tableColumns(List.of(Column.builder().name("col1").dataType("varchar(4)").build(), Column.builder().name("col2").dataType("float").build()))
* .cluster(cluster)
* .databaseName("databaseName")
* .build());
* table.grant(user, TableAction.INSERT);
*
*
* Both applications attempt to grant the user the appropriate privilege on the table by
* submitting a GRANT USER
SQL query to the Redshift cluster. Note that the latter of these
* two calls will have no effect since the user has already been granted the privilege.
*
* Now, if application 1 were to remove the call to grant
, a REVOKE USER
SQL query is
* submitted to the Redshift cluster. In general, application 1 does not know that
* application 2 has also granted this permission and thus cannot decide not to issue the
* revocation. This leads to the undesirable state where application 2 still contains the
* call to grant
but the user does not have the specified permission.
*
* Note that this does not occur when duplicate privileges are granted within the same
* application, as such privileges are de-duplicated before any SQL query is submitted.
*
*
Rotating credentials
*
* When the master password is generated and stored in AWS Secrets Manager, it can be rotated automatically:
*
*
* cluster.addRotationSingleUser();
*
*
* The multi user rotation scheme is also available:
*
*
* User user = User.Builder.create(this, "User")
* .cluster(cluster)
* .databaseName("databaseName")
* .build();
* cluster.addRotationMultiUser("MultiUserRotation", RotationMultiUserOptions.builder()
* .secret(user.getSecret())
* .build());
*
*/
@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
package software.amazon.awscdk.services.redshift;