Recursos y el AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

Esta es la segunda versión de la Guía para desarrolladores de AWS CDK. La primera versión del CDK pasó a la etapa de mantenimiento el 1.° de junio de 2022 y no cuenta con soporte desde el 1.° de junio de 2023.

Recursos y el AWS CDK

Los recursos son lo que se configura para usar los Servicios de AWS en las aplicaciones. Los recursos son una característica de AWS CloudFormation. Al configurar los recursos y sus propiedades en una plantilla de AWS CloudFormation, puede implementarlos en AWS CloudFormation para aprovisionar sus recursos. Con el AWS Cloud Development Kit (AWS CDK), puede configurar los recursos mediante constructos. A continuación, debe implementar su aplicación CDK, lo que implica sintetizar una plantilla de AWS CloudFormation e implementarla en AWS CloudFormation para aprovisionar sus recursos.

Configuración de recursos mediante constructos

Como se describe en Constructos AWS CDK, el AWS CDK proporciona una amplia biblioteca de clases de constructos, denominada constructos de AWS, que representan todos los recursos de AWS.

Para crear una instancia de un recurso utilizando su constructo correspondiente, introduzca el ámbito como primer argumento, el identificador lógico del constructo y un conjunto de propiedades de configuración (props). Por ejemplo, aquí se explica cómo crear una cola de Amazon SQS con cifrado AWS KMS mediante el constructo SQS.Queue de la Biblioteca de constructos de AWS.

TypeScript
import * as sqs from '@aws-cdk/aws-sqs'; new sqs.Queue(this, 'MyQueue', { encryption: sqs.QueueEncryption.KMS_MANAGED });
JavaScript
const sqs = require('@aws-cdk/aws-sqs'); new sqs.Queue(this, 'MyQueue', { encryption: sqs.QueueEncryption.KMS_MANAGED });
Python
import aws_cdk.aws_sqs as sqs sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED)
Java
import software.amazon.awscdk.services.sqs.*; Queue.Builder.create(this, "MyQueue").encryption( QueueEncryption.KMS_MANAGED).build();
C#
using Amazon.CDK.AWS.SQS; new Queue(this, "MyQueue", new QueueProps { Encryption = QueueEncryption.KMS_MANAGED });
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" ) sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{ Encryption: sqs.QueueEncryption_KMS_MANAGED, })

Algunos props de configuración son opcionales y, en muchos casos, tienen valores predeterminados. En algunos casos, todos los props son opcionales y el último argumento se puede omitir por completo.

Atributos de recursos

La mayoría de los recursos de la Biblioteca de constructos de AWS se muestran los atributos, que se resuelven en el momento de la implementación mediante AWS CloudFormation. Los atributos se exponen en forma de propiedades en las clases de recursos con el nombre del tipo como prefijo. En el siguiente ejemplo de código se muestra cómo obtener la URL de una cola de Amazon SQS usando la propiedad queueUrl (Python: queue_url).

TypeScript
import * as sqs from '@aws-cdk/aws-sqs'; const queue = new sqs.Queue(this, 'MyQueue'); const url = queue.queueUrl; // => A string representing a deploy-time value
JavaScript
const sqs = require('@aws-cdk/aws-sqs'); const queue = new sqs.Queue(this, 'MyQueue'); const url = queue.queueUrl; // => A string representing a deploy-time value
Python
import aws_cdk.aws_sqs as sqs queue = sqs.Queue(self, "MyQueue") url = queue.queue_url # => A string representing a deploy-time value
Java
Queue queue = new Queue(this, "MyQueue"); String url = queue.getQueueUrl(); // => A string representing a deploy-time value
C#
var queue = new Queue(this, "MyQueue"); var url = queue.QueueUrl; // => A string representing a deploy-time value
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" ) queue := sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{}) url := queue.QueueUrl() // => A string representing a deploy-time value

Consulte Token y AWS CDK para obtener información sobre cómo el AWS CDK codifica los atributos de tiempo de implementación como cadenas.

Recursos de referencia

Al configurar los recursos, a menudo tendrá que hacer referencia a las propiedades de otro recurso. A continuación se muestran algunos ejemplos:

  • Un recurso de Amazon Elastic Container Service (Amazon ECS) requiere una referencia al clúster en el que se ejecuta.

  • Una distribución de Amazon CloudFront requiere una referencia al bucket de Amazon Simple Storage Service (Amazon S3) que contiene el código fuente.

Puede hacer referencia a recursos en algunas de las siguientes maneras:

  • Transfiriendo un recurso definido en su aplicación de CDK, ya sea en la misma pila o en una diferente.

  • Al pasar un objeto proxy que hace referencia a un recurso definido en su cuenta de AWS, creado a partir de un identificador único del recurso (como un ARN)

Si la propiedad de un constructo representa un constructo de otro recurso, su tipo es el del tipo de interfaz del constructo. Por ejemplo, el constructo Amazon ECS toma una propiedad cluster de tipo ecs.ICluster. Otro ejemplo es el constructo de distribución de CloudFront que toma una propiedad sourceBucket (Python: source_bucket) de tipo s3.IBucket.

Puede pasar directamente cualquier objeto de recurso del tipo adecuado definido en la misma aplicación de AWS CDK. En el siguiente ejemplo se define un clúster de Amazon ECS y, a continuación, se utiliza para definir un servicio de Amazon ECS.

TypeScript
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
JavaScript
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ }); const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
Python
cluster = ecs.Cluster(self, "Cluster") service = ecs.Ec2Service(self, "Service", cluster=cluster)
Java
Cluster cluster = new Cluster(this, "Cluster"); Ec2Service service = new Ec2Service(this, "Service", new Ec2ServiceProps.Builder().cluster(cluster).build());
C#
var cluster = new Cluster(this, "Cluster"); var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster });
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" ecs "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" ) cluster := ecs.NewCluster(stack, jsii.String("MyCluster"), &ecs.ClusterProps{}) service := ecs.NewEc2Service(stack, jsii.String("MyService"), &ecs.Ec2ServiceProps{ Cluster: cluster, })

Referencia de recursos en una pila diferente

Puede hacer referencia a los recursos de una pila diferente siempre que estén definidos en la misma aplicación y en el mismo entorno de AWS. Generalmente, se utiliza el siguiente patrón:

  • Guarde una referencia al constructo como atributo de la pila que produce el recurso. (Para obtener una referencia a la pila del constructo actual, utilice Stack.of(this).)

  • Pase esta referencia al constructor de la pila que consume el recurso como parámetro o propiedad. Luego, la pila consumidora la pasa como una propiedad a cualquier constructo que la necesite.

En el ejemplo siguiente se define una pila stack1. Esta pila define un bucket de Amazon S3 y almacena una referencia al constructo del bucket como atributo de la pila. A continuación, la aplicación define una segunda pila, stack2, que acepta un bucket en la instanciación. stack2 podría, por ejemplo, definir una table AWS Glue que utilice el depósito para el almacenamiento de datos.

TypeScript
const prod = { account: '123456789012', region: 'us-east-1' }; const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); // stack2 will take a property { bucket: IBucket } const stack2 = new StackThatExpectsABucket(app, 'Stack2', { bucket: stack1.bucket, env: prod });
JavaScript
const prod = { account: '123456789012', region: 'us-east-1' }; const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod }); // stack2 will take a property { bucket: IBucket } const stack2 = new StackThatExpectsABucket(app, 'Stack2', { bucket: stack1.bucket, env: prod });
Python
prod = core.Environment(account="123456789012", region="us-east-1") stack1 = StackThatProvidesABucket(app, "Stack1", env=prod) # stack2 will take a property "bucket" stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod)
Java
// Helper method to build an environment static Environment makeEnv(String account, String region) { return Environment.builder().account(account).region(region) .build(); } App app = new App(); Environment prod = makeEnv("123456789012", "us-east-1"); StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1", StackProps.builder().env(prod).build()); // stack2 will take an argument "bucket" StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,", StackProps.builder().env(prod).build(), stack1.bucket);
C#
Amazon.CDK.Environment makeEnv(string account, string region) { return new Amazon.CDK.Environment { Account = account, Region = region }; } var prod = makeEnv(account: "123456789012", region: "us-east-1"); var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod }); // stack2 will take a property "bucket" var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod, bucket = stack1.Bucket});

Si el AWS CDK determina que el recurso se encuentra en el mismo entorno, pero en una pila diferente, sintetiza automáticamente las exportaciones de AWS CloudFormation en la pila de producción y un Fn::ImportValue en la pila consumidora para transferir esa información de una pila a otra.

Resolución de interbloqueos de dependencia

Al hacer referencia a un recurso de una pila en una pila diferente, se crea una dependencia entre las dos pilas. Esto garantiza que se implementen en el orden correcto. Una vez implementadas las pilas, esta dependencia es concreta. Después de eso, eliminar el uso del recurso compartido de la pila que lo consume puede provocar un error de implementación inesperado. Esto ocurre si existe otra dependencia entre las dos pilas que obligue a implementarlas en el mismo orden. También puede ocurrir sin una dependencia si el kit de herramientas de CDK simplemente elige la pila de producción para implementarla primero. La exportación AWS CloudFormation se elimina de la pila de producción porque ya no es necesaria, pero el recurso exportado se sigue utilizando en la pila consumidora porque su actualización aún no se ha implementado. Por lo tanto, se produce un error al implementar la pila de productores.

Para salir de este bloqueo, elimine el uso del recurso compartido de la pila que lo consume. (Esto elimina la exportación automática de la pila de producción). A continuación, agregue manualmente la misma exportación a la pila de producción utilizando exactamente el mismo identificador lógico que la exportación generada automáticamente. Elimine el uso del recurso compartido en la pila consumidora e implemente ambas pilas. A continuación, elimine la exportación manual (y el recurso compartido si ya no es necesario) y vuelva a implementar ambas pilas. El método exportValue() de la pila es una forma cómoda de crear la exportación manual para este propósito. (Consulte el ejemplo en la referencia del método vinculado).

Referencia de recursos en su cuenta de AWS

Supongamos que quiere usar un recurso que ya está disponible en su cuenta de AWS en la aplicación del AWS CDK. Puede ser un recurso que se definió a través de la consola, un SDK de AWS, directamente con AWS CloudFormation, o en una aplicación de AWS CDK diferente. Puede convertir el ARN del recurso (u otro atributo de identificación o grupo de atributos) en un objeto proxy. El objeto proxy sirve como referencia al recurso al llamar a un método de fábrica estático de la clase del recurso.

Al crear un proxy de este tipo, el recurso externo no pasa a formar parte de la aplicación de AWS CDK. Por lo tanto, los cambios que realice en el proxy de su aplicación de AWS CDK no afectan al recurso implementado. Sin embargo, el proxy se puede pasar a cualquier método de AWS CDK que requiera un recurso de ese tipo.

El siguiente ejemplo muestra cómo hacer referencia a un bucket basado en un bucket existente con el ARN arn:aws:s3: ::amzn-s3-demo-bucket1 y una nube virtual privada (VPC) de Amazon basada en una VPC existente con un identificador específico.

TypeScript
// Construct a proxy for a bucket by its name (must be same account) s3.Bucket.fromBucketName(this, 'amzn-s3-demo-bucket', 'amzn-s3-demo-bucket1'); // Construct a proxy for a bucket by its full ARN (can be another account) s3.Bucket.fromBucketArn(this, 'amzn-s3-demo-bucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); // Construct a proxy for an existing VPC from its attribute(s) ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { vpcId: 'vpc-1234567890abcde', });
JavaScript
// Construct a proxy for a bucket by its name (must be same account) s3.Bucket.fromBucketName(this, 'amzn-s3-demo-bucket', 'amzn-s3-demo-bucket1'); // Construct a proxy for a bucket by its full ARN (can be another account) s3.Bucket.fromBucketArn(this, 'amzn-s3-demo-bucket', 'arn:aws:s3:::amzn-s3-demo-bucket1'); // Construct a proxy for an existing VPC from its attribute(s) ec2.Vpc.fromVpcAttributes(this, 'MyVpc', { vpcId: 'vpc-1234567890abcde' });
Python
# Construct a proxy for a bucket by its name (must be same account) s3.Bucket.from_bucket_name(self, "amzn-s3-demo-bucket", "amzn-s3-demo-bucket1") # Construct a proxy for a bucket by its full ARN (can be another account) s3.Bucket.from_bucket_arn(self, "amzn-s3-demo-bucket", "arn:aws:s3:::amzn-s3-demo-bucket1") # Construct a proxy for an existing VPC from its attribute(s) ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef")
Java
// Construct a proxy for a bucket by its name (must be same account) Bucket.fromBucketName(this, "amzn-s3-demo-bucket", "amzn-s3-demo-bucket1"); // Construct a proxy for a bucket by its full ARN (can be another account) Bucket.fromBucketArn(this, "amzn-s3-demo-bucket", "arn:aws:s3:::amzn-s3-demo-bucket1"); // Construct a proxy for an existing VPC from its attribute(s) Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder() .vpcId("vpc-1234567890abcdef").build());
C#
// Construct a proxy for a bucket by its name (must be same account) Bucket.FromBucketName(this, "amzn-s3-demo-bucket", "amzn-s3-demo-bucket1"); // Construct a proxy for a bucket by its full ARN (can be another account) Bucket.FromBucketArn(this, "amzn-s3-demo-bucket", "arn:aws:s3:::amzn-s3-demo-bucket1"); // Construct a proxy for an existing VPC from its attribute(s) Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes { VpcId = "vpc-1234567890abcdef" });
Go
// Define a proxy for a bucket by its name (must be same account) s3.Bucket_FromBucketName(stack, jsii.String("amzn-s3-demo-bucket"), jsii.String("amzn-s3-demo-bucket1")) // Define a proxy for a bucket by its full ARN (can be another account) s3.Bucket_FromBucketArn(stack, jsii.String("amzn-s3-demo-bucket"), jsii.String("arn:aws:s3:::amzn-s3-demo-bucket1")) // Define a proxy for an existing VPC from its attributes ec2.Vpc_FromVpcAttributes(stack, jsii.String("MyVpc"), &ec2.VpcAttributes{ VpcId: jsii.String("vpc-1234567890abcde"), })

Echemos un vistazo más de cerca al método Vpc.fromLookup(). Como el constructo ec2.Vpc es complejo, hay muchas maneras de seleccionar la VPC que se va a usar con la aplicación de CDK. Para solucionar este problema, el constructo de VPC tiene un método estático fromLookup (Python: from_lookup) que le permite buscar la VPC de Amazon deseada consultando su cuenta de AWS en el momento de la síntesis.

Para utilizar Vpc.fromLookup(), el sistema que sintetiza la pila debe tener acceso a la cuenta propietaria de la VPC de Amazon. Esto se debe a que el kit de herramientas de CDK consulta la cuenta para encontrar la VPC de Amazon adecuada en el momento de la síntesis.

Además, Vpc.fromLookup() solo funciona en pilas definidas con una cuenta y una región explícitas (consulte Entornos para AWS CDK). Si AWS CDK intenta buscar una VPC de Amazon desde una pila independiente del entorno, el kit de herramientas de CDK no sabrá qué entorno consultar para encontrar la VPC.

Debe proporcionar atributos Vpc.fromLookup() suficientes para identificar de forma exclusiva una VPC en su cuenta de AWS. Por ejemplo, solo puede haber una VPC predeterminada, por lo que basta con especificar la VPC como predeterminada.

TypeScript
ec2.Vpc.fromLookup(this, 'DefaultVpc', { isDefault: true });
JavaScript
ec2.Vpc.fromLookup(this, 'DefaultVpc', { isDefault: true });
Python
ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True)
Java
Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder() .isDefault(true).build());
C#
Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true });
Go
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ IsDefault: jsii.Bool(true), })

También puede utilizar la propiedad tags para consultar VPC por etiqueta. Puede agregar etiquetas a la VPC de Amazon en el momento de su creación utilizando AWS CloudFormation o el AWS CDK. Puede editar las etiquetas en cualquier momento después de crearlas mediante la AWS Management Console, la AWS CLI, o un SDK de AWS. Además de las etiquetas que agregue usted mismo, AWS CDK agrega automáticamente las siguientes etiquetas a todas las VPC que cree.

  • Nombre: nombre de la VPC.

  • aws-cdk:subnet-name: nombre de la subred.

  • aws-cdk:subnet-type: tipo de subred: pública, privada o aislada.

TypeScript
ec2.Vpc.fromLookup(this, 'PublicVpc', {tags: {'aws-cdk:subnet-type': "Public"}});
JavaScript
ec2.Vpc.fromLookup(this, 'PublicVpc', {tags: {'aws-cdk:subnet-type': "Public"}});
Python
ec2.Vpc.from_lookup(self, "PublicVpc", tags={"aws-cdk:subnet-type": "Public"})
Java
Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder() .tags(java.util.Map.of("aws-cdk:subnet-type", "Public")) // Java 9 or later .build());
C#
Vpc.FromLookup(this, id = "PublicVpc", new VpcLookupOptions { Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" });
Go
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{ Tags: &map[string]*string{"aws-cdk:subnet-type": jsii.String("Public")}, })

Los resultados de Vpc.fromLookup() se almacenan en caché en el archivo cdk.context.json del proyecto. (Consulte Valores de contexto y AWS CDK). Confirme este archivo al control de versiones para que la aplicación siga haciendo referencia a la misma VPC de Amazon. Esto funciona incluso si más adelante cambia los atributos de sus VPC de forma que se seleccione una VPC diferente. Esto es especialmente importante si va a implementar la pila en un entorno que no tiene acceso a la cuenta de AWS que define la VPC, como CDK Pipelines.

Si bien puede usar un recurso externo en cualquier lugar en el que utilice un recurso similar definido en la aplicación de AWS CDK, no puede modificarlo. Por ejemplo, llamar a addToResourcePolicy (Python: add_to_resource_policy) en un s3.Bucket externo no hace nada.

Nombres físicos de los recursos

Los nombres lógicos de los recursos en AWS CloudFormation son diferentes de los nombres de los recursos que aparecen en la AWS Management Console después de su implementación en AWS CloudFormation. El AWS CDK llama a estos nombres finales nombres físicos.

Por ejemplo, AWS CloudFormation podría crear el bucket de Amazon S3 con el identificador lógico Stack2amzn-s3-demo-bucket4DD88B4F del ejemplo anterior con el nombre físico stack2amzn-s3-demo-bucket4dd88b4f-iuv1rbv9z3to.

Puede especificar un nombre físico al crear constructo que representen recursos mediante la propiedad<resourceType>Name. En el siguiente ejemplo se crea un bucket de Amazon S3 con el nombre físico amzn-s3-demo-bucket.

TypeScript
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { bucketName: 'amzn-s3-demo-bucket', });
JavaScript
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { bucketName: 'amzn-s3-demo-bucket' });
Python
bucket = s3.Bucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket")
Java
Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") .bucketName("amzn-s3-demo-bucket").build();
C#
var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { BucketName = "amzn-s3-demo-bucket" });
Go
bucket := s3.NewBucket(this, jsii.String("amzn-s3-demo-bucket"), &s3.BucketProps{ BucketName: jsii.String("amzn-s3-demo-bucket"), })

La asignación de nombres físicos a los recursos presenta algunas desventajas en AWS CloudFormation. Y lo que es más importante, cualquier cambio en los recursos implementados que requiera la sustitución de un recurso, como los cambios en las propiedades de un recurso que sean inmutables tras su creación, fallará si a un recurso se le ha asignado un nombre físico. Si termina en ese estado, la única solución es eliminar la pila AWS CloudFormation y volver a implementar la aplicación de AWS CDK. Consulte la documentación de AWS CloudFormation para obtener más detalles.

En algunos casos, como cuando se crea una aplicación de AWS CDK con referencias a varios entornos, se requieren nombres físicos para que el AWS CDK funcione correctamente. En esos casos, si no quiere molestarse en crear un nombre físico usted mismo, puede dejar que el AWS CDK lo haga por usted. Para ello, use el valor especial PhysicalName.GENERATE_IF_NEEDED, de la siguiente manera.

TypeScript
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { bucketName: core.PhysicalName.GENERATE_IF_NEEDED, });
JavaScript
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', { bucketName: core.PhysicalName.GENERATE_IF_NEEDED });
Python
bucket = s3.Bucket(self, "amzn-s3-demo-bucket", bucket_name=core.PhysicalName.GENERATE_IF_NEEDED)
Java
Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket") .bucketName(PhysicalName.GENERATE_IF_NEEDED).build();
C#
var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps { BucketName = PhysicalName.GENERATE_IF_NEEDED });
Go
bucket := s3.NewBucket(this, jsii.String("amzn-s3-demo-bucket"), &s3.BucketProps{ BucketName: awscdk.PhysicalName_GENERATE_IF_NEEDED(), })

Pasar identificadores de recursos únicos

Siempre que sea posible, debe pasar recursos por referencia, como se describe en la sección anterior. Sin embargo, hay casos en los que no tiene otra opción que hacer referencia a un recurso por uno de sus atributos. Algunos ejemplos de casos de uso incluyen lo siguiente:

  • Cuando se utilizan recursos AWS CloudFormation de bajo nivel.

  • Cuando necesita exponer los recursos a los componentes de tiempo de ejecución de una aplicación de AWS CDK, como cuando se hace referencia a las funciones de Lambda a través de variables de entorno.

Estos identificadores están disponibles como atributos en los recursos, como los siguientes.

TypeScript
bucket.bucketName lambdaFunc.functionArn securityGroup.groupArn
JavaScript
bucket.bucketName lambdaFunc.functionArn securityGroup.groupArn
Python
bucket.bucket_name lambda_func.function_arn security_group_arn
Java

El enlace de AWS CDK de Java utiliza métodos de captación para los atributos.

bucket.getBucketName() lambdaFunc.getFunctionArn() securityGroup.getGroupArn()
C#
bucket.BucketName lambdaFunc.FunctionArn securityGroup.GroupArn
Go
bucket.BucketName() fn.FunctionArn()

En el siguiente ejemplo se muestra cómo pasar un nombre de bucket generado a una función de AWS Lambda.

TypeScript
const bucket = new s3.Bucket(this, 'Bucket'); new lambda.Function(this, 'MyLambda', { // ... environment: { BUCKET_NAME: bucket.bucketName, }, });
JavaScript
const bucket = new s3.Bucket(this, 'Bucket'); new lambda.Function(this, 'MyLambda', { // ... environment: { BUCKET_NAME: bucket.bucketName } });
Python
bucket = s3.Bucket(self, "Bucket") lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name))
Java
final Bucket bucket = new Bucket(this, "Bucket"); Function.Builder.create(this, "MyLambda") .environment(java.util.Map.of( // Java 9 or later "BUCKET_NAME", bucket.getBucketName())) .build();
C#
var bucket = new Bucket(this, "Bucket"); new Function(this, "MyLambda", new FunctionProps { Environment = new Dictionary<string, string> { ["BUCKET_NAME"] = bucket.BucketName } });
Go
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{ Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()}, })

Otorgar permisos entre recursos

Los constructos de nivel superior permiten obtener permisos con privilegios mínimos al ofrecer API sencillas y basadas en la intención para expresar los requisitos de permisos. Por ejemplo, muchos constructos de nivel 2 ofrecen métodos de concesión que se pueden utilizar para conceder a una entidad (por ejemplo, un rol o un usuario de IAM) permiso para trabajar con el recurso, sin tener que crear manualmente las declaraciones de permiso de IAM.

El siguiente ejemplo crea los permisos para permitir que el rol de ejecución de una función de Lambda lea y escriba objetos en un bucket de Amazon S3 concreto. Si el bucket de Amazon S3 está cifrado con una clave AWS KMS, este método también concede permisos al rol de ejecución de la función de Lambda para descifrar con la clave.

TypeScript
if (bucket.grantReadWrite(func).success) { // ... }
JavaScript
if ( bucket.grantReadWrite(func).success) { // ... }
Python
if bucket.grant_read_write(func).success: # ...
Java
if (bucket.grantReadWrite(func).getSuccess()) { // ... }
C#
if (bucket.GrantReadWrite(func).Success) { // ... }
Go
if *bucket.GrantReadWrite(function, nil).Success() { // ... }

Los métodos de concesión devuelven un objeto iam.Grant. Utilice el atributo success del objeto Grant para determinar si la subvención se aplicó de manera efectiva (por ejemplo, es posible que no se haya aplicado a recursos externos). También puede usar el método assertSuccess (Python: assert_success) del objeto Grant para garantizar que la concesión se haya aplicado correctamente.

Si un método de concesión específico no está disponible para un caso de uso concreto, puede usar un método de concesión genérico para definir una nueva concesión con una lista de acciones específica.

En el siguiente ejemplo se muestra cómo conceder acceso a una función de Lambda al CreateBackup de Amazon DynamoDB.

TypeScript
table.grant(func, 'dynamodb:CreateBackup');
JavaScript
table.grant(func, 'dynamodb:CreateBackup');
Python
table.grant(func, "dynamodb:CreateBackup")
Java
table.grant(func, "dynamodb:CreateBackup");
C#
table.Grant(func, "dynamodb:CreateBackup");
Go
table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{}) table.Grant(function, jsii.String("dynamodb:CreateBackup"))

Muchos recursos, como las funciones de Lambda, requieren que se asuma un rol al ejecutar el código. Una propiedad de configuración le permite especificar un iam.IRole. Si no se especifica ningún rol, la función crea automáticamente un rol específico para este uso. A continuación, puede utilizar métodos de concesión en los recursos para agregar declaraciones al rol.

Los métodos de concesión se crean con la API de nivel inferior para administrarlos con las políticas de IAM. Las políticas se modelan como objetos PolicyDocument. Agregue instrucciones directamente a los roles (o al rol adjunto de un constructo) mediante el método addToRolePolicy (Python: add_to_role_policy) o a la política de un recurso (como una política Bucket) mediante el método addToResourcePolicy (Python: add_to_resource_policy).

Métricas de recursos y alarmas

Muchos recursos emiten métricas de CloudWatch que se pueden usar para configurar paneles y alarmas de monitoreo. Los constructos de nivel superior tienen métodos métricos que permiten acceder a las métricas sin tener que buscar el nombre correcto que se va a utilizar.

El siguiente ejemplo muestra cómo definir una alarma cuando el ApproximateNumberOfMessagesNotVisible de Amazon SQS supera 100.

TypeScript
import * as cw from '@aws-cdk/aws-cloudwatch'; import * as sqs from '@aws-cdk/aws-sqs'; import { Duration } from '@aws-cdk/core'; const queue = new sqs.Queue(this, 'MyQueue'); const metric = queue.metricApproximateNumberOfMessagesNotVisible({ label: 'Messages Visible (Approx)', period: Duration.minutes(5), // ... }); metric.createAlarm(this, 'TooManyMessagesAlarm', { comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, threshold: 100, // ... });
JavaScript
const cw = require('@aws-cdk/aws-cloudwatch'); const sqs = require('@aws-cdk/aws-sqs'); const { Duration } = require('@aws-cdk/core'); const queue = new sqs.Queue(this, 'MyQueue'); const metric = queue.metricApproximateNumberOfMessagesNotVisible({ label: 'Messages Visible (Approx)', period: Duration.minutes(5) // ... }); metric.createAlarm(this, 'TooManyMessagesAlarm', { comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD, threshold: 100 // ... });
Python
import aws_cdk.aws_cloudwatch as cw import aws_cdk.aws_sqs as sqs from aws_cdk.core import Duration queue = sqs.Queue(self, "MyQueue") metric = queue.metric_approximate_number_of_messages_not_visible( label="Messages Visible (Approx)", period=Duration.minutes(5), # ... ) metric.create_alarm(self, "TooManyMessagesAlarm", comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD, threshold=100, # ... )
Java
import software.amazon.awscdk.core.Duration; import software.amazon.awscdk.services.sqs.Queue; import software.amazon.awscdk.services.cloudwatch.Metric; import software.amazon.awscdk.services.cloudwatch.MetricOptions; import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions; import software.amazon.awscdk.services.cloudwatch.ComparisonOperator; Queue queue = new Queue(this, "MyQueue"); Metric metric = queue .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder() .label("Messages Visible (Approx)") .period(Duration.minutes(5)).build()); metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder() .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) .threshold(100) // ... .build());
C#
using cdk = Amazon.CDK; using cw = Amazon.CDK.AWS.CloudWatch; using sqs = Amazon.CDK.AWS.SQS; var queue = new sqs.Queue(this, "MyQueue"); var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions { Label = "Messages Visible (Approx)", Period = cdk.Duration.Minutes(5), // ... }); metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions { ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD, Threshold = 100, // .. });
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" cw "github.com/aws/aws-cdk-go/awscdk/v2/awscloudwatch" sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" ) queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{}) metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{ Label: jsii.String("Messages Visible (Approx)"), Period: awscdk.Duration_Minutes(jsii.Number(5)), }) metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{ ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD, Threshold: jsii.Number(100), })

Si no hay ningún método para una métrica en particular, puede utilizar el método de métrica general para especificar el nombre de la métrica manualmente.

Puede agregar estas métricas a los paneles de CloudWatch. Consulte CloudWatch.

Tráfico de red

En muchos casos, debe habilitar los permisos en una red para que una aplicación funcione, por ejemplo, cuando la infraestructura informática necesita acceder a la capa de persistencia. Los recursos que establecen o detectan las conexiones exponen métodos que permiten los flujos de tráfico, como el establecimiento de reglas de grupos de seguridad o ACL de red.

Los recursos de iConnectable tienen una propiedad connections que es la puerta de enlace a la configuración de las reglas de tráfico de la red.

Para permitir que los datos fluyan en una ruta de red determinada, se utilizan métodos allow. El siguiente ejemplo habilita las conexiones HTTPS a la web y las conexiones entrantes desde el grupo Amazon EC2 Auto Scaling fleet2.

TypeScript
import * as asg from '@aws-cdk/aws-autoscaling'; import * as ec2 from '@aws-cdk/aws-ec2'; const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); // Allow surfing the (secure) web fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/); fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
JavaScript
const asg = require('@aws-cdk/aws-autoscaling'); const ec2 = require('@aws-cdk/aws-ec2'); const fleet1 = asg.AutoScalingGroup(); // Allow surfing the (secure) web fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 })); const fleet2 = asg.AutoScalingGroup(); fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
Python
import aws_cdk.aws_autoscaling as asg import aws_cdk.aws_ec2 as ec2 fleet1 = asg.AutoScalingGroup( ... ) # Allow surfing the (secure) web fleet1.connections.allow_to(ec2.Peer.any_ipv4(), ec2.Port(PortProps(from_port=443, to_port=443))) fleet2 = asg.AutoScalingGroup( ... ) fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic())
Java
import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; import software.amazon.awscdk.services.ec2.Peer; import software.amazon.awscdk.services.ec2.Port; AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet") /* ... */.build(); // Allow surfing the (secure) Web fleet1.getConnections().allowTo(Peer.anyIpv4(), Port.Builder.create().fromPort(443).toPort(443).build()); AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2") /* ... */.build(); fleet1.getConnections().allowFrom(fleet2, Port.allTraffic());
C#
using cdk = Amazon.CDK; using asg = Amazon.CDK.AWS.AutoScaling; using ec2 = Amazon.CDK.AWS.EC2; // Allow surfing the (secure) Web var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ }); fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps { FromPort = 443, ToPort = 443 }); var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ }); fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic());
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling" ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" ) fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{}) fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web")) fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{}) fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic"))

Algunos recursos tienen puertos predeterminados asociados. Los ejemplos incluyen el oyente de un equilibrador de carga en el puerto público y los puertos en los que el motor de base de datos acepta conexiones para instancias de una base de datos de Amazon RDS. En estos casos, puede imponer un control estricto de la red sin tener que especificar el puerto manualmente. Para hacerlo, utilice los métodos allowDefaultPortFrom y allowToDefaultPort (Python: allow_default_port_from, allow_to_default_port).

El siguiente ejemplo muestra cómo habilitar las conexiones desde cualquier dirección IPV4 y una conexión desde un grupo de escalado automático para acceder a una base de datos.

TypeScript
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
JavaScript
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access'); fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
Python
listener.connections.allow_default_port_from_any_ipv4("Allow public access") fleet.connections.allow_to_default_port(rds_database, "Fleet can access database")
Java
listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access"); fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database");
C#
listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access"); fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database");
Go
listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access")) fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database"))

Control de eventos

Algunos recursos pueden actuar como fuentes de eventos. Utilice el método addEventNotification (Python: add_event_notification) para registrar un objetivo de evento en un tipo de evento concreto emitido por el recurso. Además, los métodos addXxxNotification ofrecen una forma sencilla de registrar un controlador para los tipos de eventos más comunes.

En el siguiente ejemplo se muestra cómo activar una función de Lambda cuando se agrega un objeto a un bucket de Amazon S3.

TypeScript
import * as s3nots from '@aws-cdk/aws-s3-notifications'; const handler = new lambda.Function(this, 'Handler', { /*…*/ }); const bucket = new s3.Bucket(this, 'Bucket'); bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
JavaScript
const s3nots = require('@aws-cdk/aws-s3-notifications'); const handler = new lambda.Function(this, 'Handler', { /*…*/ }); const bucket = new s3.Bucket(this, 'Bucket'); bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
Python
import aws_cdk.aws_s3_notifications as s3_nots handler = lambda_.Function(self, "Handler", ...) bucket = s3.Bucket(self, "Bucket") bucket.add_object_created_notification(s3_nots.LambdaDestination(handler))
Java
import software.amazon.awscdk.services.s3.Bucket; import software.amazon.awscdk.services.lambda.Function; import software.amazon.awscdk.services.s3.notifications.LambdaDestination; Function handler = Function.Builder.create(this, "Handler")/* ... */.build(); Bucket bucket = new Bucket(this, "Bucket"); bucket.addObjectCreatedNotification(new LambdaDestination(handler));
C#
using lambda = Amazon.CDK.AWS.Lambda; using s3 = Amazon.CDK.AWS.S3; using s3Nots = Amazon.CDK.AWS.S3.Notifications; var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. }); var bucket = new s3.Bucket(this, "Bucket"); bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler));
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" s3nots "github.com/aws/aws-cdk-go/awscdk/v2/awss3notifications" ) handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{}) bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{}) bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil)

Políticas de eliminación

Los recursos que mantienen datos persistentes, como las bases de datos, los buckets de Amazon S3 y los registros de Amazon ECR, tienen una política de eliminación. La política de eliminación indica si se deben eliminar los objetos persistentes cuando se destruya la pila de AWS CDK que los contiene. Los valores que especifican la política de eliminación están disponibles en la enumeración de la RemovalPolicy del módulo core de AWS CDK.

nota

Los recursos, además de los que almacenan datos de forma persistente, también pueden tener una removalPolicy que se utilice para un propósito diferente. Por ejemplo, una versión de una función de Lambda usa un atributo removalPolicy para determinar si una versión determinada se conserva cuando se implementa una nueva versión. Tienen significados y valores predeterminados diferentes en comparación con la política de eliminación de un bucket de Amazon S3 o tabla de DynamoDB.

Valor Significado

RemovalPolicy.RETAIN

Conserve el contenido del recurso al destruir la pila (opción predeterminada). El recurso queda huérfano de la pila y se debe eliminar manualmente. Si intenta volver a implementar la pila mientras el recurso aún existe, recibirá un mensaje de error debido a un conflicto de nombres.

RemovalPolicy.DESTROY

El recurso se destruirá junto con la pila.

AWS CloudFormation no elimina los buckets de Amazon S3 que contienen archivos, incluso si su política de eliminación está establecida en DESTROY. Intentar realizar una de estas operaciones es un error de AWS CloudFormation. Para que AWS CDK elimine todos los archivos del bucket antes de destruirlo, defina la propiedad autoDeleteObjects del depósito en true.

A continuación, se muestra un ejemplo de cómo crear un bucket de Amazon S3 con la RemovalPolicy de DESTROY y autoDeleteOjbects establecido en true.

TypeScript
import * as cdk from '@aws-cdk/core'; import * as s3 from '@aws-cdk/aws-s3'; export class CdkTestStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const bucket = new s3.Bucket(this, 'Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true }); } }
JavaScript
const cdk = require('@aws-cdk/core'); const s3 = require('@aws-cdk/aws-s3'); class CdkTestStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); const bucket = new s3.Bucket(this, 'Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true }); } } module.exports = { CdkTestStack }
Python
import aws_cdk.core as cdk import aws_cdk.aws_s3 as s3 class CdkTestStack(cdk.stack): def __init__(self, scope: cdk.Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) bucket = s3.Bucket(self, "Bucket", removal_policy=cdk.RemovalPolicy.DESTROY, auto_delete_objects=True)
Java
software.amazon.awscdk.core.*; import software.amazon.awscdk.services.s3.*; public class CdkTestStack extends Stack { public CdkTestStack(final Construct scope, final String id) { this(scope, id, null); } public CdkTestStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Bucket.Builder.create(this, "Bucket") .removalPolicy(RemovalPolicy.DESTROY) .autoDeleteObjects(true).build(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.S3; public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) { new Bucket(this, "Bucket", new BucketProps { RemovalPolicy = RemovalPolicy.DESTROY, AutoDeleteObjects = true }); }
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/jsii-runtime-go" s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3" ) s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{ RemovalPolicy: awscdk.RemovalPolicy_DESTROY, AutoDeleteObjects: jsii.Bool(true), })

También puede aplicar una política de eliminación directamente al recurso AWS CloudFormation subyacente mediante el método applyRemovalPolicy(). Este método está disponible en algunos recursos con estado que no tienen una propiedad removalPolicy en los props de sus recursos de nivel 2. Algunos ejemplos son los siguientes:

  • Pilas de AWS CloudFormation

  • Grupos de usuarios de Amazon Cognito

  • Instancias de base de datos de Amazon DocumentDB

  • Volúmenes de Amazon EC2

  • Dominios de Amazon OpenSearch Service

  • Sistemas de archivos de Amazon FSx

  • Colas de Amazon SQS

TypeScript
const resource = bucket.node.findChild('Resource') as cdk.CfnResource; resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
JavaScript
const resource = bucket.node.findChild('Resource'); resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
Python
resource = bucket.node.find_child('Resource') resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY);
Java
CfnResource resource = (CfnResource)bucket.node.findChild("Resource"); resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
C#
var resource = (CfnResource)bucket.node.findChild('Resource'); resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
nota

Las RemovalPolicy del AWS CDK se traducen como DeletionPolicy de AWS CloudFormation. Sin embargo, la entrada predeterminada en AWS CDK es conservar los datos, que es lo contrario del AWS CloudFormation predeterminado.