Recursos e o AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

Este é o Guia do Desenvolvedor do AWS CDK v2. O CDK v1 antigo entrou em manutenção em 1º de junho de 2022 e encerrou o suporte em 1º de junho de 2023.

Recursos e o AWS CDK

Recursos são o que você configura para usar Serviços da AWS em seus aplicativos. Os recursos são um atributo do AWS CloudFormation. Ao configurar recursos e suas propriedades em um modelo AWS CloudFormation, você pode implantar para o AWS CloudFormation para provisionar seus recursos. Com o AWS Cloud Development Kit (AWS CDK), você pode configurar recursos por meio de constructos. Em seguida, você implanta seu aplicativo CDK, o que envolve sintetizar um modelo AWS CloudFormation e implantá-lo no AWS CloudFormation para provisionar seus recursos.

Configurar recursos usando constructos

Conforme descrito em Constructos do AWS CDK, o AWS CDK fornece uma rica biblioteca de classes de constructos, chamada constructos da AWS, que representam todos os recursos da AWS.

Para criar uma instância de um recurso usando seu constructo correspondente, passe o escopo como o primeiro argumento, o ID lógico do constructo e um conjunto de propriedades de configuração (props). Por exemplo, veja como criar uma fila do Amazon SQS com criptografia AWS KMS usando o constructo sqs.Queue da Biblioteca de Constructos da 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, })

Alguns props de configuração são opcionais e, em muitos casos, têm valores padrão. Em alguns casos, todos os props são opcionais e o último argumento pode ser totalmente omitido.

Atributos de recursos

A maioria dos recursos na Biblioteca de Constructos AWS expõe atributos, que são resolvidos no momento da implantação pelo AWS CloudFormation. Os atributos são expostos na forma de propriedades nas classes de recursos com o nome do tipo como prefixo. O exemplo a seguir mostra como obter o URL de uma fila do Amazon SQS usando a propriedade 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 Tokens e o AWS CDK para obter informações sobre como o AWS CDK codifica atributos de tempo de implantação como strings.

Fazer referência a recursos

Ao configurar recursos, muitas vezes você precisará referenciar propriedades de outro recurso. Veja os exemplos a seguir:

  • Um recurso do Amazon Elastic Container Service (Amazon ECS) requer uma referência ao cluster no qual é executado.

  • Uma distribuição do Amazon CloudFront requer uma referência ao bucket do Amazon Simple Storage Service (Amazon S3) contendo o código-fonte.

É possível fazer referência a recursos de qualquer uma das formas a seguir:

  • Ao passar um recurso definido em seu aplicativo CDK, na mesma pilha ou em uma diferente

  • Ao passar um objeto proxy referenciando um recurso definido em sua conta AWS, criado a partir de um identificador exclusivo do recurso (como um ARN)

Se a propriedade de um constructo representa um constructo para outro recurso, seu tipo é o tipo de interface de constructo. Por exemplo, o constructo do Amazon ECS assume uma propriedade cluster do tipo ecs.ICluster. Outro exemplo é o constructo de distribuição do CloudFront que usa uma propriedade sourceBucket (Python: source_bucket) do tipo s3.IBucket.

Você pode transmitir diretamente qualquer objeto de recurso do tipo adequado definido no mesmo aplicativo AWS CDK. O exemplo a seguir define um cluster do Amazon ECS e o usa para definir um serviço do 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, })

Como fazer referência a recursos em uma pilha diferente

Você pode se referir aos recursos em uma pilha diferente, desde que estejam definidos no mesmo aplicativo e no mesmo ambiente AWS. O seguinte padrão é geralmente usado:

  • Armazene uma referência ao constructo como um atributo da pilha que produz o recurso. (Para obter uma referência à pilha do constructo atual, use Stack.of(this).)

  • Passe essa referência ao construtor da pilha que consome o recurso como parâmetro ou propriedade. A pilha consumidora então a passa como uma propriedade para qualquer constructo que precise dela.

O exemplo a seguir define uma pilha stack1. Essa pilha define um bucket do Amazon S3 e armazena uma referência ao constructo do bucket como um atributo da pilha. Em seguida, o aplicativo define uma segunda pilha, stack2, que aceita um bucket na instanciação. O stack2 pode, por exemplo, definir uma tabela AWS Glue que usa o bucket para armazenamento de dados.

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});

Se o AWS CDK determinar que o recurso está no mesmo ambiente, mas em uma pilha diferente, ele sintetiza automaticamente as exportações AWS CloudFormation na pilha de produção e um Fn::ImportValue na pilha consumidora para transferir essas informações de uma pilha para a outra.

Como resolver os deadlocks de dependência

Fazer referência a um recurso de uma pilha em outra pilha cria uma dependência entre as duas pilhas. Isso garante que eles sejam implantados na ordem correta. Depois que as pilhas são implantadas, essa dependência é concreta. Depois disso, remover o uso do recurso compartilhado da pilha consumidora pode causar uma falha inesperada na implantação. Isso acontece se houver outra dependência entre as duas pilhas que as força a serem implantadas na mesma ordem. Isso também pode acontecer sem dependência se a pilha de produção for simplesmente escolhida pelo CDK Toolkit para ser implantada primeiro. A exportação AWS CloudFormation é removida da pilha de produção porque não é mais necessária, mas o recurso exportado ainda está sendo usado na pilha de consumo porque sua atualização ainda não foi implantada. Portanto, a implantação da pilha do produtor falha.

Para resolver esse impasse, remova o uso do recurso compartilhado da pilha de consumo. (Isso remove a exportação automática da pilha de produção.) Em seguida, adicione manualmente a mesma exportação à pilha de produção usando exatamente o mesmo ID lógico da exportação gerado automaticamente. Remova o uso do recurso compartilhado na pilha de consumo e implante as duas pilhas. Em seguida, remova a exportação manual (e o recurso compartilhado, se não for mais necessário) e implante as duas pilhas novamente. O método exportValue() da pilha é uma maneira conveniente de criar a exportação manual para essa finalidade. (Veja o exemplo na referência do método vinculado.)

Como fazer referência a recursos em sua conta AWS

Suponha que você queira usar um recurso já disponível na sua conta AWS no seu aplicativo AWS CDK. Isso pode ser um recurso definido por meio do console, de um SDK da AWS, diretamente com o AWS CloudFormation ou em um aplicativo AWS CDK diferente. Você pode transformar o ARN do recurso (ou outro atributo de identificação ou grupo de atributos) em um objeto proxy. O objeto proxy serve como referência ao recurso chamando um método estático de fábrica na classe do recurso.

Quando você cria esse proxy, o recurso externo não se torna parte do seu aplicativo AWS CDK. Portanto, as alterações feitas no proxy em seu aplicativo AWS CDK não afetam o recurso implantado. No entanto, o proxy pode ser passado para qualquer método AWS CDK que exija um recurso desse tipo.

O exemplo a seguir mostra como referenciar um bucket baseado em um bucket existente com o ARN arn:aws:s3:::amzn-s3-demo-bucket1 e uma nuvem privada Amazon Virtual com base em uma VPC existente com um ID 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"), })

Vamos examinar com mais cuidado o método Vpc.fromLookup(). Como o ec2.Vpc constructo é complexo, talvez você queira selecionar a VPC de várias maneiras para ser usada com seu aplicativo CDK. Para resolver isso, o constructo da VPC tem um método estático fromLookup (Python: from_lookup) que permite pesquisar a Amazon VPC desejada consultando sua conta AWS no momento da síntese.

Para usar o Vpc.fromLookup(), o sistema que sintetiza a pilha deve ter acesso à conta proprietária da Amazon VPC. Isso ocorre porque o CDK Toolkit consulta a conta para encontrar a Amazon VPC certa no momento da síntese.

Além disso, o Vpc.fromLookup() funciona somente em pilhas definidas com uma conta e uma região explícitas (consulte Ambientes para o AWS CDK). Se o AWS CDK tentar pesquisar uma Amazon VPC a partir de uma pilha independente do ambiente, o CDK Toolkit não sabe qual ambiente consultar para encontrar a VPC.

Você deve fornecer atributos Vpc.fromLookup() suficientes para identificar de forma exclusiva uma VPC em sua conta AWS. Por exemplo, só pode haver uma VPC padrão, então basta especificar a VPC como padrão.

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), })

Você também pode usar a propriedade tags para consultar VPCs por tag. Você pode adicionar tags à Amazon VPC no momento de sua criação usando AWS CloudFormation ou AWS CDK. Você pode editar as tags a qualquer momento após a criação usando o AWS Management Console, o AWS CLI ou um SDK da AWS. Além de todas as tags que você mesmo adiciona, o AWS CDK adiciona automaticamente as seguintes tags a todas as VPCs criadas.

  • Nome – O nome da VPC.

  • aws-cdk:subnet-name – O nome da sub-rede.

  • aws-cdk:subnet-type – O tipo de sub-rede: pública, privada ou isolada.

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")}, })

Os resultados do Vpc.fromLookup() são armazenados em cache no arquivo cdk.context.json do projeto. (Consulte Valores de contexto e o AWS CDK.) Confirme esse arquivo com o controle de versão para que seu aplicativo continue se referindo à mesma Amazon VPC. Isso funciona mesmo se você alterar posteriormente os atributos de suas VPCs de uma forma que resultaria na seleção de uma VPC diferente. Isso é particularmente importante se você estiver implantando a pilha em um ambiente que não tem acesso à conta AWS que define a VPC, como o CDK Pipelines.

Embora você possa usar um recurso externo em qualquer lugar em que usaria um recurso semelhante definido no seu aplicativo AWS CDK, não é possível modificá-lo. Por exemplo, chamar addToResourcePolicy (Python: add_to_resource_policy) em um s3.Bucket externo não faz nada.

Nomes físicos de recursos

Os nomes lógicos dos recursos no AWS CloudFormation são diferentes dos nomes dos recursos que são mostrados no AWS Management Console depois de serem implantados pelo AWS CloudFormation. O AWS CDK chama esses nomes finais de nomes físicos.

Por exemplo, o AWS CloudFormation pode criar o bucket do Amazon S3 com o ID lógico Stack2amzn-s3-demo-bucket4DD88B4F do exemplo anterior com o nome físico stack2amzn-s3-demo-bucket4dd88b4f-iuv1rbv9z3to.

Você pode especificar um nome físico ao criar constructos que representam recursos usando a propriedade <resourceType>Name. O exemplo a seguir cria um bucket do Amazon S3 com o nome 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"), })

A atribuição de nomes físicos aos recursos tem algumas desvantagens no AWS CloudFormation. Mais importante ainda, qualquer alteração nos recursos implantados que exija a substituição de um recurso, como alterações nas propriedades de um recurso que são imutáveis após a criação, falhará se um recurso tiver um nome físico atribuído. Se você acabar nesse estado, a única solução é excluir a pilha AWS CloudFormation e implantar o aplicativo AWS CDK novamente. Consulte a Documentação do AWS CloudFormation para obter detalhes.

Em alguns casos, como ao criar um aplicativo AWS CDK com referências entre ambientes, nomes físicos são necessários para que o AWS CDK funcione corretamente. Nesses casos, se você não quiser se preocupar em criar um nome físico, pode deixar o AWS CDK nomear para você. Para isso, use o valor especial PhysicalName.GENERATE_IF_NEEDED, da forma a seguir.

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(), })

Passando identificadores de recursos exclusivos

Sempre que possível, você deve passar os recursos por referência, conforme descrito na seção anterior. No entanto, há casos em que você não tem outra escolha a não ser se referir a um recurso por meio de um de seus atributos. Alguns casos de uso incluem o seguinte:

  • Quando você está usando recursos AWS CloudFormation de baixo nível.

  • Quando você precisa expor recursos aos componentes de runtime de um aplicativo AWS CDK, como ao se referir às funções do Lambda por meio de variáveis de ambiente.

Esses identificadores estão disponíveis como atributos nos recursos, como os seguintes.

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

A vinculação Java AWS CDK usa métodos getter para atributos.

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

O exemplo a seguir mostra como transmitir um nome de bucket gerado a uma função 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()}, })

Concedendo permissões entre recursos

Constructos de alto nível possibilitam permissões com privilégios mínimos, oferecendo APIs simples e baseadas em intenção para expressar os requisitos de permissão. Por exemplo, muitos constructos de L2 oferecem métodos de concessão que você pode usar para conceder permissão a uma entidade (como um perfil do IAM ou usuário) para trabalhar com o recurso, sem precisar criar manualmente declarações de permissão do IAM.

O exemplo a seguir cria as permissões para permitir que a função de execução de uma função do Lambda leia e grave objetos em um determinado bucket do Amazon S3. Se o bucket do Amazon S3 for criptografado com uma chave AWS KMS, esse método também concederá permissões à função de execução da função do Lambda para decodificar com a chave.

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() { // ... }

Os métodos de concessão retornam um objeto iam.Grant. Use o atributo success do objeto Grant para determinar se a concessão foi efetivamente aplicada (por exemplo, ela pode não ter sido aplicada em recursos externos). Você também pode usar o método assertSuccess (Python: assert_success) do objeto Grant para garantir que a concessão tenha sido aplicada com sucesso.

Se um método de concessão específico não estiver disponível para o caso de uso específico, você poderá usar um método de concessão genérico para definir uma nova concessão com uma lista específica de ações.

O exemplo a seguir mostra como conceder a uma função do Lambda acesso à ação do Amazon DynamoDB CreateBackup.

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"))

Muitos recursos, como as funções do Lambda, exigem que uma função seja assumida ao executar o código. Uma propriedade de configuração permite que você especifique um iam.IRole. Se nenhuma função for especificada, a função criará automaticamente uma função específica para esse uso. Em seguida, você pode usar métodos de concessão nos recursos para adicionar declarações ao perfil.

Os métodos de concessão são criados usando APIs de nível inferior para lidar com as políticas do IAM. As políticas são modeladas como objetos PolicyDocument. Adicione declarações diretamente às funções (ou à função anexada de um constructo) usando o método addToRolePolicy (Python: add_to_role_policy) ou à política de um recurso (como uma política Bucket) usando o método addToResourcePolicy (Python: add_to_resource_policy).

Métricas de recursos e alarmes

Muitos recursos emitem métricas do CloudWatch que podem ser usadas para configurar painéis de monitoramento e alarmes. Constructos de nível superior têm métodos métricos que permitem acessar as métricas sem procurar o nome correto a ser usado.

O exemplo a seguir mostra como definir um alarme quando o ApproximateNumberOfMessagesNotVisible de uma fila do Amazon SQS exceder 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), })

Se não houver um método para uma métrica específica, você poderá usar o método métrico geral para especificar o nome da métrica manualmente.

Métricas também podem ser adicionadas aos painéis do CloudWatch. Consulte CloudWatch.

Tráfego de rede

Em muitos casos, você deve habilitar permissões em uma rede para que um aplicativo funcione, como quando a infraestrutura computacional precisa acessar a camada de persistência. Recursos que estabelecem ou escutam conexões expõem métodos que permitem fluxos de tráfego, incluindo a definição de regras de grupos de segurança ou ACLs de rede.

Os recursos IConnectable têm uma propriedade connections que é o gateway para a configuração das regras de tráfego de rede.

Você permite que os dados fluam em um determinado caminho de rede usando métodos allow. O exemplo a seguir permite conexões HTTPS com a web e conexões de entrada do 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"))

Alguns recursos têm portas padrão associadas a eles. Os exemplos incluem o receptor de um balanceador de carga na porta pública e as portas nas quais o mecanismo de banco de dados aceita conexões para instâncias de um banco de dados do Amazon RDS. Nesses casos, você pode aplicar um controle rígido da rede sem precisar especificar manualmente a porta. Para fazer isso, use os métodos allowDefaultPortFrom e allowToDefaultPort (Python: allow_default_port_from, allow_to_default_port).

O exemplo a seguir mostra como habilitar conexões de qualquer endereço IPV4 e uma conexão de um grupo do Auto Scaling para acessar um banco de dados.

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"))

Processar eventos

Alguns recursos podem atuar como fontes de eventos. Use o método addEventNotification (Python: add_event_notification) para registrar um destino de evento para um determinado tipo de evento emitido pelo recurso. Além disso, os métodos addXxxNotification oferecem uma maneira simples de registrar um manipulador para tipos de eventos comuns.

O exemplo a seguir mostra como acionar uma função do Lambda quando um objeto é adicionado a um bucket do 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 remoção

Recursos que mantêm dados persistentes, como bancos de dados, buckets do Amazon S3 e registros do Amazon ECR, têm uma política de remoção. A política de remoção indica se objetos persistentes devem ser excluídos quando a pilha AWS CDK que os contém for destruída. Os valores que especificam a política de remoção estão disponíveis por meio da enumeração RemovalPolicy no módulo core do AWS CDK.

nota

Recursos além daqueles que armazenam dados de forma persistente também podem ter um removalPolicy que é usado para uma finalidade diferente. Por exemplo, uma versão da função do Lambda usa um atributo removalPolicy para determinar se uma determinada versão é retida quando uma nova versão é implantada. Eles têm significados e padrões diferentes em comparação com a política de remoção em um bucket do Amazon S3 ou uma tabela do DynamoDB.

Valor Significado

RemovalPolicy.RETAIN

Manter o conteúdo do recurso ao destruir a pilha (padrão). O recurso fica órfão da pilha e deve ser excluído manualmente. Se você tentar reimplantar a pilha enquanto o recurso ainda existe, você receberá uma mensagem de erro devido a um conflito de nomes.

RemovalPolicy.DESTROY

O recurso será destruído junto com a pilha.

O AWS CloudFormation não remove buckets do Amazon S3 que contêm arquivos, mesmo que sua política de remoção esteja definida como DESTROY. Qualquer tentativa de fazer isso gerará um erro AWS CloudFormation. Para que o AWS CDK exclua todos os arquivos do bucket antes de destruí-lo, defina a propriedade autoDeleteObjects do bucket como true.

Veja a seguir um exemplo de criação de um bucket do Amazon S3 com RemovalPolicy de DESTROY e autoDeleteOjbects definido como 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), })

Você também pode aplicar uma política de remoção diretamente ao recurso AWS CloudFormation subjacente por meio do método applyRemovalPolicy(). Esse método está disponível em alguns recursos com estado que não têm uma propriedade removalPolicy nas propriedades do recurso L2. Os exemplos incluem:

  • Pilhas do AWS CloudFormation

  • Grupos de usuários do Amazon Cognito

  • Instâncias de banco de dados do Amazon DocumentDB

  • Volumes do Amazon EC2

  • Domínios do Amazon OpenSearch Service

  • Sistemas de arquivos do Amazon FSx

  • Filas do 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

O RemovalPolicy do AWS CDK se traduz em DeletionPolicy do AWS CloudFormation. No entanto, o padrão AWS CDK é reter os dados, o que é o oposto do padrão AWS CloudFormation.