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.
As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Integração e entrega contínuas (CI/CD) usando CDK Pipelines
Use o módulo CDK Pipelines da Biblioteca de Constructos da AWS para configurar a entrega contínua de aplicações do AWS CDK. Quando você confirma o código-fonte da sua aplicação do CDK no AWS CodeCommit, no GitHub ou no AWS CodeStar, o CDK Pipelines pode compilar, testar e implantar automaticamente sua nova versão.
O CDK Pipelines é atualizado automaticamente. Se você adicionar estágios ou pilhas de aplicações, o pipeline se reconfigura automaticamente para implantar esses novos estágios ou pilhas.
O CDK Pipelines oferece suporte a duas APIs. Uma delas é a API original que foi disponibilizada na Demonstração para desenvolvedores do CDK Pipelines. A outra é uma API moderna que incorpora o feedback dos clientes do CDK recebido durante a fase de pré-visualização. Os exemplos deste tópico usam a API moderna. Para obter detalhes sobre as diferenças entre as duas APIs com suporte, consulte API original do CDK Pipelines no repositório aws-cdk do GitHub.
Fazer bootstrapping em seus ambientes da AWS
Antes de usar o CDK Pipelines, você deve inicializar o ambiente da AWS no qual implantará suas pilhas.
Um CDK Pipeline envolve pelo menos dois ambientes. O primeiro ambiente é onde o pipeline é provisionado. O segundo ambiente é onde você deseja implantar as pilhas ou estágios da aplicação (os estágios são grupos de pilhas relacionadas). Esses ambientes podem ser os mesmos, mas uma é uma prática recomendada isolar os estágios uns dos outros em ambientes diferentes.
Consulte Bootstrapping do AWS CDK para obter mais informações sobre os tipos de recursos criados pelo bootstrapping e como personalizar a pilha de bootstrapping.
A implantação contínua com o CDK Pipelines exige que o seguinte seja incluído na pilha do Kit de Ferramentas CDK:
-
Um bucket do Amazon Simple Storage Service (Amazon S3).
-
Um repositório do Amazon ECR.
-
Perfis do IAM para dar às várias partes de um pipeline as permissões de que elas precisam.
O Kit de Ferramentas CDK atualizará sua pilha de bootstrapping existente ou criará uma nova, se necessário.
Para fazer o bootstrapping em um ambiente que possa provisionar um pipeline do AWS CDK, invoque cdk bootstrap conforme mostrado no exemplo a seguir. Invocar o Kit de Ferramentas CDK da AWS por meio do comando npx o instalará temporariamente, se necessário. Ele também usará a versão do Kit de Ferramentas instalada no projeto atual, se houver.
--cloudformation-execution-policies especifica o ARN de uma política sob a qual as futuras implantações do CDK Pipelines serão executadas. A política AdministratorAccess padrão garante que seu pipeline possa implantar todo tipo de recurso da AWS. Se você usar essa política, certifique-se de confiar em todos os códigos e dependências que compõem sua aplicação do AWS CDK.
A maioria das organizações exige controles mais rígidos sobre quais tipos de recursos podem ser implantados pela automação. Consulte o departamento apropriado da sua organização para determinar a política que seu pipeline deve usar.
É possível omitir a opção --profile se seu perfil da AWS padrão contiver a configuração de autenticação e a região da AWS necessárias.
- macOS/Linux
-
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
- Windows
-
npx cdk bootstrap aws://<ACCOUNT-NUMBER></REGION> --profile< ADMIN-PROFILE> ^
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
Para fazer o bootstrapping em ambientes adicionais nos quais as aplicações do AWS CDK serão implantados pelo pipeline, use os comandos a seguir. A opção --trust indica qual outra conta deve ter permissões para implantar aplicações do AWS CDK nesse ambiente. Para essa opção, especifique o ID da conta da AWS do pipeline.
Novamente, é possível omitir a opção --profile se seu perfil da AWS padrão contiver a configuração de autenticação e a região da AWS necessárias.
- macOS/Linux
-
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
--trust <PIPELINE-ACCOUNT-NUMBER>
- Windows
-
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> ^
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^
--trust <PIPELINE-ACCOUNT-NUMBER>
Use credenciais administrativas somente para fazer o bootstrapping e provisionar o pipeline inicial. Depois, use o próprio pipeline, não sua máquina local, para implantar as alterações.
Se você estiver atualizando um ambiente legado em que foi feito o bootstrapping, o bucket anterior do Amazon S3 ficará órfão quando o novo bucket for criado. Exclua-o manualmente usando o console do Amazon S3.
Proteger sua pilha de bootstrapping contra exclusão
Se uma pilha de bootstrapping for excluída, os recursos da AWS que foram originalmente provisionados no ambiente para oferecer suporte a implantações do CDK também serão excluídos. Isso fará com que o pipeline pare de funcionar. Se isso acontecer, não há solução geral para recuperação.
Depois que seu ambiente receber o bootstrapping, não exclua e recrie a pilha de bootstrapping do ambiente. Em vez disso, tente atualizar a pilha de bootstrapping para uma nova versão executando o comando cdk bootstrap novamente.
Para se proteger contra a exclusão acidental de sua pilha de bootstrapping, recomendamos que você forneça a opção --termination-protection com o comando cdk bootstrap para ativar a proteção contra encerramento. É possível ativar a proteção contra encerramento em pilhas de bootstrapping novas ou existentes. Para saber mais sobre essa opção, consulte
--termination-protection
.
Depois de ativar a proteção contra encerramento, será possível usar a AWS CLI ou o console do CloudFormation para verificar.
-
Execute o comando a seguir para ativar a proteção contra encerramento em uma pilha de bootstrapping nova ou existente:
$ cdk bootstrap --termination-protection
-
Use a AWS CLI ou o console do CloudFormation para verificar. Veja a seguir um exemplo usando a AWS CLI. Se você modificou o nome da pilha de bootstrapping, substitua CDKToolkit pelo nome da pilha:
$ aws cloudformation describe-stacks --stack-name <CDKToolkit> --query "Stacks[0].EnableTerminationProtection"
true
Inicializar um projeto
Crie um novo projeto vazio do GitHub e clone-o em sua estação de trabalho no diretório my-pipeline. (Nossos exemplos de código neste tópico usam o GitHub. Você também pode usar o AWS CodeStar ou o AWS CodeCommit.)
git clone <GITHUB-CLONE-URL> my-pipeline
cd my-pipeline
É possível usar um nome diferente de my-pipeline no diretório principal da aplicação. No entanto, se você fizer isso, precisará ajustar os nomes dos arquivos e das classes posteriormente neste tópico. Isso ocorre porque o Kit de Ferramentas CDK da AWS baseia alguns nomes de arquivos e classes no nome do diretório principal.
Após a clonagem, inicialize o projeto normalmente.
- TypeScript
-
$ cdk init app --language typescript
- JavaScript
-
$ cdk init app --language javascript
- Python
-
$ cdk init app --language python
Depois que a aplicação for criado, insira também os dois comandos a seguir. Eles ativam o ambiente virtual Python da aplicação e instalam as dependências principais do AWS CDK.
$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead
$ python -m pip install -r requirements.txt
- Java
-
$ cdk init app --language java
Se você estiver usando um IDE, agora pode abrir ou importar o projeto. No Eclipse, por exemplo, escolha Arquivo > Importar > Maven > Projetos existentes do Maven. Certifique-se de que as configurações do projeto estejam definidas para usar o Java 8 (1.8).
- C#
-
$ cdk init app --language csharp
Se você estiver usando o Visual Studio, abra o arquivo da solução no diretório src.
- Go
-
$ cdk init app --language go
Depois que a aplicação for criado, insira também o comando a seguir para instalar os módulos da Biblioteca de Constructos da AWS que a aplicação exige.
$ go get
Envie seus arquivos cdk.json e cdk.context.json para o controle de origem. As informações de contexto (como sinalizadores de atributos e valores armazenados em cache recuperados da sua conta da AWS) fazem parte do estado do seu projeto. Os valores podem ser diferentes em outro ambiente, o que pode causar alterações inesperadas nos resultados. Para obter mais informações, consulte Valores de contexto e o AWS CDK.
Definir um pipeline
Seu aplicação do CDK Pipelines incluirá pelo menos duas pilhas: uma que representa o próprio pipeline e uma ou mais pilhas que representam a aplicação implantado por meio dele. As pilhas também podem ser agrupadas em estágios, que você pode usar para implantar cópias das pilhas de infraestrutura em diferentes ambientes. Por enquanto, consideraremos o pipeline e, posteriormente, nos aprofundaremos na aplicação que ele implantará.
O constructo
CodePipeline
é o constructo que representa um CDK Pipeline que o AWS CodePipeline usa como mecanismo de implantação. Ao instanciar CodePipeline em uma pilha, você define o local de origem do pipeline (como um repositório do GitHub). Você também define os comandos para compilar a aplicação.
Por exemplo, o seguinte define um pipeline cuja fonte está armazenada em um repositório do GitHub. Também inclui uma etapa de criação para uma aplicação do TypeScript CDK. Preencha as informações sobre seu repositório do GitHub onde indicado.
Por padrão, o pipeline se autentica no GitHub usando um token de acesso pessoal armazenado no Secrets Manager sob o nome github-token.
Você também precisará atualizar a instanciação da pilha do pipeline para especificar a conta e a região da AWS.
- TypeScript
-
Em lib/my-pipeline-stack.ts (pode variar se o nome da pasta do seu projeto não for my-pipeline):
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
export class MyPipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
}
}
Em bin/my-pipeline.ts (pode variar se o nome da pasta do seu projeto não for my-pipeline):
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { MyPipelineStack } from '../lib/my-pipeline-stack';
const app = new cdk.App();
new MyPipelineStack(app, 'MyPipelineStack', {
env: {
account: '111111111111',
region: 'eu-west-1',
}
});
app.synth();
- JavaScript
-
Em lib/my-pipeline-stack.js (pode variar se o nome da pasta do seu projeto não for my-pipeline):
const cdk = require('aws-cdk-lib');
const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines');
class MyPipelineStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
}
}
module.exports = { MyPipelineStack }
Em bin/my-pipeline.js (pode variar se o nome da pasta do seu projeto não for my-pipeline):
#!/usr/bin/env node
const cdk = require('aws-cdk-lib');
const { MyPipelineStack } = require('../lib/my-pipeline-stack');
const app = new cdk.App();
new MyPipelineStack(app, 'MyPipelineStack', {
env: {
account: '111111111111',
region: 'eu-west-1',
}
});
app.synth();
- Python
-
Em my-pipeline/my-pipeline-stack.py (pode variar se o nome da pasta do seu projeto não for my-pipeline):
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep
class MyPipelineStack(cdk.Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
pipeline = CodePipeline(self, "Pipeline",
pipeline_name="MyPipeline",
synth=ShellStep("Synth",
input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
commands=["npm install -g aws-cdk",
"python -m pip install -r requirements.txt",
"cdk synth"]
)
)
Em app.py:
#!/usr/bin/env python3
import aws_cdk as cdk
from my_pipeline.my_pipeline_stack import MyPipelineStack
app = cdk.App()
MyPipelineStack(app, "MyPipelineStack",
env=cdk.Environment(account="111111111111", region="eu-west-1")
)
app.synth()
- Java
-
Em src/main/java/com/myorg/MyPipelineStack.java (pode variar se o nome da pasta do seu projeto não for my-pipeline):
package com.myorg;
import java.util.Arrays;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.pipelines.CodePipeline;
import software.amazon.awscdk.pipelines.CodePipelineSource;
import software.amazon.awscdk.pipelines.ShellStep;
public class MyPipelineStack extends Stack {
public MyPipelineStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyPipelineStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
.pipelineName("MyPipeline")
.synth(ShellStep.Builder.create("Synth")
.input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
.commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
.build())
.build();
}
}
Em src/main/java/com/myorg/MyPipelineApp.java (pode variar se o nome da pasta do seu projeto não for my-pipeline):
package com.myorg;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;
public class MyPipelineApp {
public static void main(final String[] args) {
App app = new App();
new MyPipelineStack(app, "PipelineStack", StackProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build());
app.synth();
}
}
- C#
-
Em src/MyPipeline/MyPipelineStack.cs (pode variar se o nome da pasta do seu projeto não for my-pipeline):
using Amazon.CDK;
using Amazon.CDK.Pipelines;
namespace MyPipeline
{
public class MyPipelineStack : Stack
{
internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
PipelineName = "MyPipeline",
Synth = new ShellStep("Synth", new ShellStepProps
{
Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
})
});
}
}
}
Em src/MyPipeline/Program.cs (pode variar se o nome da pasta do seu projeto não for my-pipeline):
using Amazon.CDK;
namespace MyPipeline
{
sealed class Program
{
public static void Main(string[] args)
{
var app = new App();
new MyPipelineStack(app, "MyPipelineStack", new StackProps
{
Env = new Amazon.CDK.Environment {
Account = "111111111111", Region = "eu-west-1" }
});
app.Synth();
}
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
codebuild "github.com/aws/aws-cdk-go/awscdk/v2/awscodebuild"
ssm "github.com/aws/aws-cdk-go/awscdk/v2/awsssm"
pipeline "github.com/aws/aws-cdk-go/awscdk/v2/pipelines"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
"os"
)
// my CDK Stack with resources
func NewCdkStack(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack {
stack := awscdk.NewStack(scope, id, props)
// create an example ssm parameter
_ = ssm.NewStringParameter(stack, jsii.String("ssm-test-param"), &ssm.StringParameterProps{
ParameterName: jsii.String("/testparam"),
Description: jsii.String("ssm parameter for demo"),
StringValue: jsii.String("my test param"),
})
return stack
}
// my CDK Application
func NewCdkApplication(scope constructs.Construct, id *string, props *awscdk.StageProps) awscdk.Stage {
stage := awscdk.NewStage(scope, id, props)
_ = NewCdkStack(stage, jsii.String("cdk-stack"), &awscdk.StackProps{Env: props.Env})
return stage
}
// my CDK Pipeline
func NewCdkPipeline(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack {
stack := awscdk.NewStack(scope, id, props)
// GitHub repo with owner and repository name
githubRepo := pipeline.CodePipelineSource_GitHub(jsii.String("owner/repo"), jsii.String("main"), &pipeline.GitHubSourceOptions{
Authentication: awscdk.SecretValue_SecretsManager(jsii.String("my-github-token"), nil),
})
// self mutating pipeline
myPipeline := pipeline.NewCodePipeline(stack, jsii.String("cdkPipeline"), &pipeline.CodePipelineProps{
PipelineName: jsii.String("CdkPipeline"),
// self mutation true - pipeline changes itself before application deployment
SelfMutation: jsii.Bool(true),
CodeBuildDefaults: &pipeline.CodeBuildOptions{
BuildEnvironment: &codebuild.BuildEnvironment{
// image version 6.0 recommended for newer go version
BuildImage: codebuild.LinuxBuildImage_FromCodeBuildImageId(jsii.String("aws/codebuild/standard:6.0")),
},
},
Synth: pipeline.NewCodeBuildStep(jsii.String("Synth"), &pipeline.CodeBuildStepProps{
Input: githubRepo,
Commands: &[]*string{
jsii.String("npm install -g aws-cdk"),
jsii.String("cdk synth"),
},
}),
})
// deployment of actual CDK application
myPipeline.AddStage(NewCdkApplication(stack, jsii.String("MyApplication"), &awscdk.StageProps{
Env: targetAccountEnv(),
}), &pipeline.AddStageOpts{
Post: &[]pipeline.Step{
pipeline.NewCodeBuildStep(jsii.String("Manual Steps"), &pipeline.CodeBuildStepProps{
Commands: &[]*string{
jsii.String("echo \"My CDK App deployed, manual steps go here ... \""),
},
}),
},
})
return stack
}
// main app
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
// call CDK Pipeline
NewCdkPipeline(app, jsii.String("CdkPipelineStack"), &awscdk.StackProps{
Env: pipelineEnv(),
})
app.Synth(nil)
}
// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func pipelineEnv() *awscdk.Environment {
return &awscdk.Environment{
Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
}
}
func targetAccountEnv() *awscdk.Environment {
return &awscdk.Environment{
Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
}
}
É necessário implantar um pipeline manualmente uma vez. Depois disso, o pipeline se mantém atualizado a partir do repositório do código-fonte. Portanto, verifique se o código no repositório é o código que você deseja implantar. Verifique suas alterações, envie para o GitHub e, em seguida, implante:
git add --all
git commit -m "initial commit"
git push
cdk deploy
Agora que você fez a implantação inicial, sua conta da AWS local não precisará mais de acesso administrativo. Isso ocorre porque todas as alterações em sua aplicação serão implantadas por meio do pipeline. Tudo o que você precisa fazer é enviar para o GitHub.
Estágios de aplicações
Para definir uma aplicação da AWS de várias pilhas que possa ser adicionado ao pipeline de uma só vez, defina uma subclasse de
Stage
. (Isso é diferente de CdkStage no módulo do CDK Pipelines.)
O estágio contém as pilhas do que compõem a aplicação. Se houver dependências entre as pilhas, as pilhas serão adicionadas automaticamente ao pipeline na ordem correta. As pilhas que não dependam umas das outras são implantadas paralelamente. É possível adicionar uma relação de dependência entre as pilhas chamando stack1.addDependency(stack2).
Os estágios aceitam um argumento env padrão, que se torna o ambiente padrão para as pilhas dentro dele. (As pilhas ainda podem ter seu próprio ambiente especificado.)
Um aplicação é adicionada ao pipeline chamando
addStage()
com instâncias de Stage. Um estágio pode ser instanciado e adicionado ao pipeline várias vezes para definir diferentes estágios do seu pipeline de aplicações multirregional ou DTAP.
Criaremos uma pilha contendo uma função do Lambda simples e colocaremos essa pilha em um estágio. Em seguida, adicionaremos o estágio ao pipeline para que ele possa ser implantado.
- TypeScript
-
Crie o novo arquivo lib/my-pipeline-lambda-stack.ts para armazenar nossa pilha de aplicações contendo uma função do Lambda.
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda';
export class MyLambdaStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new Function(this, 'LambdaFunction', {
runtime: Runtime.NODEJS_18_X,
handler: 'index.handler',
code: new InlineCode('exports.handler = _ => "Hello, CDK";')
});
}
}
Crie o novo arquivo lib/my-pipeline-app-stage.ts para manter nosso estágio.
import * as cdk from 'aws-cdk-lib';
import { Construct } from "constructs";
import { MyLambdaStack } from './my-pipeline-lambda-stack';
export class MyPipelineAppStage extends cdk.Stage {
constructor(scope: Construct, id: string, props?: cdk.StageProps) {
super(scope, id, props);
const lambdaStack = new MyLambdaStack(this, 'LambdaStack');
}
}
Edite lib/my-pipeline-stack.ts para adicionar o estágio ao nosso pipeline.
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
import { MyPipelineAppStage } from './my-pipeline-app-stage';
export class MyPipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
pipeline.addStage(new MyPipelineAppStage(this, "test", {
env: { account: "111111111111", region: "eu-west-1" }
}));
}
}
- JavaScript
-
Crie o novo arquivo lib/my-pipeline-lambda-stack.js para armazenar nossa pilha de aplicações contendo uma função do Lambda.
const cdk = require('aws-cdk-lib');
const { Function, InlineCode, Runtime } = require('aws-cdk-lib/aws-lambda');
class MyLambdaStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
new Function(this, 'LambdaFunction', {
runtime: Runtime.NODEJS_18_X,
handler: 'index.handler',
code: new InlineCode('exports.handler = _ => "Hello, CDK";')
});
}
}
module.exports = { MyLambdaStack }
Crie o novo arquivo lib/my-pipeline-app-stage.js para manter nosso estágio.
const cdk = require('aws-cdk-lib');
const { MyLambdaStack } = require('./my-pipeline-lambda-stack');
class MyPipelineAppStage extends cdk.Stage {
constructor(scope, id, props) {
super(scope, id, props);
const lambdaStack = new MyLambdaStack(this, 'LambdaStack');
}
}
module.exports = { MyPipelineAppStage };
Edite lib/my-pipeline-stack.ts para adicionar o estágio ao nosso pipeline.
const cdk = require('aws-cdk-lib');
const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines');
const { MyPipelineAppStage } = require('./my-pipeline-app-stage');
class MyPipelineStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
pipeline.addStage(new MyPipelineAppStage(this, "test", {
env: { account: "111111111111", region: "eu-west-1" }
}));
}
}
module.exports = { MyPipelineStack }
- Python
-
Crie o novo arquivo my_pipeline/my_pipeline_lambda_stack.py para armazenar nossa pilha de aplicações contendo uma função do Lambda.
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.aws_lambda import Function, InlineCode, Runtime
class MyLambdaStack(cdk.Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
Function(self, "LambdaFunction",
runtime=Runtime.NODEJS_18_X,
handler="index.handler",
code=InlineCode("exports.handler = _ => 'Hello, CDK';")
)
Crie o novo arquivo my_pipeline/my_pipeline_app_stage.py para manter nosso estágio.
import aws_cdk as cdk
from constructs import Construct
from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack
class MyPipelineAppStage(cdk.Stage):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
lambdaStack = MyLambdaStack(self, "LambdaStack")
Edite my_pipeline/my-pipeline-stack.py para adicionar o estágio ao nosso pipeline.
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep
from my_pipeline.my_pipeline_app_stage import MyPipelineAppStage
class MyPipelineStack(cdk.Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
pipeline = CodePipeline(self, "Pipeline",
pipeline_name="MyPipeline",
synth=ShellStep("Synth",
input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
commands=["npm install -g aws-cdk",
"python -m pip install -r requirements.txt",
"cdk synth"]))
pipeline.add_stage(MyPipelineAppStage(self, "test",
env=cdk.Environment(account="111111111111", region="eu-west-1")))
- Java
-
Crie o novo arquivo src/main/java/com.myorg/MyPipelineLambdaStack.java para armazenar nossa pilha de aplicações contendo uma função do Lambda.
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.lambda.InlineCode;
public class MyPipelineLambdaStack extends Stack {
public MyPipelineLambdaStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyPipelineLambdaStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
Function.Builder.create(this, "LambdaFunction")
.runtime(Runtime.NODEJS_18_X)
.handler("index.handler")
.code(new InlineCode("exports.handler = _ => 'Hello, CDK';"))
.build();
}
}
Crie o novo arquivo src/main/java/com.myorg/MyPipelineAppStage.java para manter nosso estágio.
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.Stage;
import software.amazon.awscdk.StageProps;
public class MyPipelineAppStage extends Stage {
public MyPipelineAppStage(final Construct scope, final String id) {
this(scope, id, null);
}
public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) {
super(scope, id, props);
Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack");
}
}
Edite src/main/java/com.myorg/MyPipelineStack.java para adicionar o estágio ao nosso pipeline.
package com.myorg;
import java.util.Arrays;
import software.constructs.Construct;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.StageProps;
import software.amazon.awscdk.pipelines.CodePipeline;
import software.amazon.awscdk.pipelines.CodePipelineSource;
import software.amazon.awscdk.pipelines.ShellStep;
public class MyPipelineStack extends Stack {
public MyPipelineStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyPipelineStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
.pipelineName("MyPipeline")
.synth(ShellStep.Builder.create("Synth")
.input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
.commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
.build())
.build();
pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build()));
}
}
- C#
-
Crie o novo arquivo src/MyPipeline/MyPipelineLambdaStack.cs para armazenar nossa pilha de aplicações contendo uma função do Lambda.
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.Lambda;
namespace MyPipeline
{
class MyPipelineLambdaStack : Stack
{
public MyPipelineLambdaStack(Construct scope, string id, StackProps props=null) : base(scope, id, props)
{
new Function(this, "LambdaFunction", new FunctionProps
{
Runtime = Runtime.NODEJS_18_X,
Handler = "index.handler",
Code = new InlineCode("exports.handler = _ => 'Hello, CDK';")
});
}
}
}
Crie o novo arquivo src/MyPipeline/MyPipelineAppStage.cs para manter nosso estágio.
using Amazon.CDK;
using Constructs;
namespace MyPipeline
{
class MyPipelineAppStage : Stage
{
public MyPipelineAppStage(Construct scope, string id, StageProps props=null) : base(scope, id, props)
{
Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack");
}
}
}
Edite src/MyPipeline/MyPipelineStack.cs para adicionar o estágio ao nosso pipeline.
using Amazon.CDK;
using Constructs;
using Amazon.CDK.Pipelines;
namespace MyPipeline
{
public class MyPipelineStack : Stack
{
internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
PipelineName = "MyPipeline",
Synth = new ShellStep("Synth", new ShellStepProps
{
Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
})
});
pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "eu-west-1"
}
}));
}
}
}
Cada estágio da aplicação adicionado por addStage() resulta na adição de um estágio de pipeline correspondente, representado por uma instância
StageDeployment
retornada pela chamada addStage(). É possível adicionar ações de pré-implantação ou pós-implantação ao estágio chamando seu método addPre() ou addPost().
- TypeScript
-
// import { ManualApprovalStep } from 'aws-cdk-lib/pipelines';
const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
testingStage.addPost(new ManualApprovalStep('approval'));
- JavaScript
-
// const { ManualApprovalStep } = require('aws-cdk-lib/pipelines');
const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
testingStage.addPost(new ManualApprovalStep('approval'));
- Python
-
# from aws_cdk.pipelines import ManualApprovalStep
testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing",
env=cdk.Environment(account="111111111111", region="eu-west-1")))
testing_stage.add_post(ManualApprovalStep('approval'))
- Java
-
// import software.amazon.awscdk.pipelines.StageDeployment;
// import software.amazon.awscdk.pipelines.ManualApprovalStep;
StageDeployment testingStage =
pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build()));
testingStage.addPost(new ManualApprovalStep("approval"));
- C#
-
var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "eu-west-1"
}
}));
testingStage.AddPost(new ManualApprovalStep("approval"));
É possível adicionar estágios a uma
Wave
para implantá-los paralelamente, por exemplo, ao implantar um estágio em várias contas ou regiões.
- TypeScript
-
const wave = pipeline.addWave('wave');
wave.addStage(new MyApplicationStage(this, 'MyAppEU', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
wave.addStage(new MyApplicationStage(this, 'MyAppUS', {
env: { account: '111111111111', region: 'us-west-1' }
}));
- JavaScript
-
const wave = pipeline.addWave('wave');
wave.addStage(new MyApplicationStage(this, 'MyAppEU', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
wave.addStage(new MyApplicationStage(this, 'MyAppUS', {
env: { account: '111111111111', region: 'us-west-1' }
}));
- Python
-
wave = pipeline.add_wave("wave")
wave.add_stage(MyApplicationStage(self, "MyAppEU",
env=cdk.Environment(account="111111111111", region="eu-west-1")))
wave.add_stage(MyApplicationStage(self, "MyAppUS",
env=cdk.Environment(account="111111111111", region="us-west-1")))
- Java
-
// import software.amazon.awscdk.pipelines.Wave;
final Wave wave = pipeline.addWave("wave");
wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build()));
wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("us-west-1")
.build())
.build()));
- C#
-
var wave = pipeline.AddWave("wave");
wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "eu-west-1"
}
}));
wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "us-west-1"
}
}));
Teste de implantações
É possível adicionar etapas a um CDK Pipeline para validar as implantações que você está realizando. Por exemplo, é possível usar o
ShellStep
da biblioteca do CDK Pipelines para realizar tarefas como as seguintes:
Em sua forma mais simples, adicionar ações de validação tem a seguinte aparência:
- TypeScript
-
// stage was returned by pipeline.addStage
stage.addPost(new ShellStep("validate", {
commands: ['../tests/validate.sh'],
}));
- JavaScript
-
// stage was returned by pipeline.addStage
stage.addPost(new ShellStep("validate", {
commands: ['../tests/validate.sh'],
}));
- Python
-
# stage was returned by pipeline.add_stage
stage.add_post(ShellStep("validate",
commands=[''../tests/validate.sh'']
))
- Java
-
// stage was returned by pipeline.addStage
stage.addPost(ShellStep.Builder.create("validate")
.commands(Arrays.asList("'../tests/validate.sh'"))
.build());
- C#
-
// stage was returned by pipeline.addStage
stage.AddPost(new ShellStep("validate", new ShellStepProps
{
Commands = new string[] { "'../tests/validate.sh'" }
}));
Muitas implantações do AWS CloudFormation resultam na geração de recursos com nomes imprevisíveis. Por esse motivo, o CDK Pipelines fornece uma maneira de ler as saídas do AWS CloudFormation após uma implantação. Isso possibilita passar (por exemplo) o URL gerado de um balanceador de carga para uma ação de teste.
Para usar as saídas, exponha o objeto CfnOutput no qual você tem interesse. Em seguida, passe-o na propriedade envFromCfnOutputs de uma etapa para disponibilizá-lo como uma variável de ambiente nessa etapa.
- TypeScript
-
// given a stack lbStack that exposes a load balancer construct as loadBalancer
this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', {
value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/`
});
// pass the load balancer address to a shell step
stage.addPost(new ShellStep("lbaddr", {
envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress},
commands: ['echo $lb_addr']
}));
- JavaScript
-
// given a stack lbStack that exposes a load balancer construct as loadBalancer
this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', {
value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/`
});
// pass the load balancer address to a shell step
stage.addPost(new ShellStep("lbaddr", {
envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress},
commands: ['echo $lb_addr']
}));
- Python
-
# given a stack lb_stack that exposes a load balancer construct as load_balancer
self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress",
value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/")
# pass the load balancer address to a shell step
stage.add_post(ShellStep("lbaddr",
env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address}
commands=["echo $lb_addr"]))
- Java
-
// given a stack lbStack that exposes a load balancer construct as loadBalancer
loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress")
.value(String.format("https://%s/",
lbStack.loadBalancer.loadBalancerDnsName))
.build();
stage.addPost(ShellStep.Builder.create("lbaddr")
.envFromCfnOutputs( // Map.of requires Java 9 or later
java.util.Map.of("lbAddr", loadBalancerAddress))
.commands(Arrays.asList("echo $lbAddr"))
.build());
- C#
-
// given a stack lbStack that exposes a load balancer construct as loadBalancer
loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps
{
Value = string.Format("https://{0}/", lbStack.loadBalancer.LoadBalancerDnsName)
});
stage.AddPost(new ShellStep("lbaddr", new ShellStepProps
{
EnvFromCfnOutputs = new Dictionary<string, CfnOutput>
{
{ "lbAddr", loadBalancerAddress }
},
Commands = new string[] { "echo $lbAddr" }
}));
É possível escrever testes de validação simples diretamente no ShellStep, mas essa abordagem se torna complicada quando o teste tem mais do que algumas linhas. Para testes mais complexos, você pode trazer arquivos adicionais (como scripts de shell completos ou programas em outras linguagens) para a propriedade ShellStep por meio da propriedade inputs. As entradas podem ser qualquer etapa que tenha uma saída, incluindo uma fonte (como um repositório do GitHub) ou outro ShellStep.
Trazer arquivos do repositório de origem é apropriado se os arquivos puderem ser usados diretamente no teste (por exemplo, se eles próprios forem executáveis). Neste exemplo, declaramos nosso repositório do GitHub como source (em vez de instanciá-lo em linha como parte do CodePipeline). Em seguida, passamos esse conjunto de arquivos para o pipeline e para o teste de validação.
- TypeScript
-
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main');
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: source,
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
stage.addPost(new ShellStep('validate', {
input: source,
commands: ['sh ../tests/validate.sh']
}));
- JavaScript
-
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main');
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: source,
commands: ['npm ci', 'npm run build', 'npx cdk synth']
})
});
const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
stage.addPost(new ShellStep('validate', {
input: source,
commands: ['sh ../tests/validate.sh']
}));
- Python
-
source = CodePipelineSource.git_hub("OWNER/REPO", "main")
pipeline = CodePipeline(self, "Pipeline",
pipeline_name="MyPipeline",
synth=ShellStep("Synth",
input=source,
commands=["npm install -g aws-cdk",
"python -m pip install -r requirements.txt",
"cdk synth"]))
stage = pipeline.add_stage(MyApplicationStage(self, "test",
env=cdk.Environment(account="111111111111", region="eu-west-1")))
stage.add_post(ShellStep("validate", input=source,
commands=["sh ../tests/validate.sh"],
))
- Java
-
final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main");
final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
.pipelineName("MyPipeline")
.synth(ShellStep.Builder.create("Synth")
.input(source)
.commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
.build())
.build();
final StageDeployment stage =
pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build()));
stage.addPost(ShellStep.Builder.create("validate")
.input(source)
.commands(Arrays.asList("sh ../tests/validate.sh"))
.build());
- C#
-
var source = CodePipelineSource.GitHub("OWNER/REPO", "main");
var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
PipelineName = "MyPipeline",
Synth = new ShellStep("Synth", new ShellStepProps
{
Input = source,
Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
})
});
var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "eu-west-1"
}
}));
stage.AddPost(new ShellStep("validate", new ShellStepProps
{
Input = source,
Commands = new string[] { "sh ../tests/validate.sh" }
}));
Obter os arquivos adicionais da etapa de sintetização é apropriado se seus testes precisarem ser compilados, o que é feito como parte da síntese.
- TypeScript
-
const synthStep = new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth'],
});
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: synthStep
});
const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
env: { account: '111111111111', region: 'eu-west-1' }
}));
// run a script that was transpiled from TypeScript during synthesis
stage.addPost(new ShellStep('validate', {
input: synthStep,
commands: ['node tests/validate.js']
}));
- JavaScript
-
const synthStep = new ShellStep('Synth', {
input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth'],
});
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: synthStep
});
const stage = pipeline.addStage(new MyPipelineAppStage(this, "test", {
env: { account: "111111111111", region: "eu-west-1" }
}));
// run a script that was transpiled from TypeScript during synthesis
stage.addPost(new ShellStep('validate', {
input: synthStep,
commands: ['node tests/validate.js']
}));
- Python
-
synth_step = ShellStep("Synth",
input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
commands=["npm install -g aws-cdk",
"python -m pip install -r requirements.txt",
"cdk synth"])
pipeline = CodePipeline(self, "Pipeline",
pipeline_name="MyPipeline",
synth=synth_step)
stage = pipeline.add_stage(MyApplicationStage(self, "test",
env=cdk.Environment(account="111111111111", region="eu-west-1")))
# run a script that was compiled during synthesis
stage.add_post(ShellStep("validate",
input=synth_step,
commands=["node test/validate.js"],
))
- Java
-
final ShellStep synth = ShellStep.Builder.create("Synth")
.input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
.commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
.build();
final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
.pipelineName("MyPipeline")
.synth(synth)
.build();
final StageDeployment stage =
pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
.env(Environment.builder()
.account("111111111111")
.region("eu-west-1")
.build())
.build()));
stage.addPost(ShellStep.Builder.create("validate")
.input(synth)
.commands(Arrays.asList("node ./tests/validate.js"))
.build());
- C#
-
var synth = new ShellStep("Synth", new ShellStepProps
{
Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
});
var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
PipelineName = "MyPipeline",
Synth = synth
});
var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
Env = new Environment
{
Account = "111111111111", Region = "eu-west-1"
}
}));
stage.AddPost(new ShellStep("validate", new ShellStepProps
{
Input = synth,
Commands = new string[] { "node ./tests/validate.js" }
}));
Observações de segurança
Qualquer forma de entrega contínua tem riscos de segurança inerentes. De acordo com o Modelo de Responsabilidade Compartilhada da AWS, você é responsável pela segurança de suas informações na Nuvem AWS. A biblioteca do CDK Pipelines oferece uma vantagem inicial ao incorporar padrões seguros e práticas recomendadas de modelagem.
No entanto, por sua própria natureza, uma biblioteca que precisa de um alto nível de acesso para cumprir a finalidade pretendida não pode garantir segurança total. Há muitos vetores de ataque fora da sua organização da AWS.
Em especial, considere o seguinte:
-
Leve em consideração o software do qual você depende. Verifique todos os softwares de terceiros que você executa em seu pipeline, pois eles podem mudar a infraestrutura que é implantada.
-
Use o bloqueio de dependências para evitar atualizações acidentais. O CDK Pipelines respeita package-lock.json e yarn.lock para garantir que suas dependências sejam as que você espera.
-
O CDK Pipelines é executado em recursos criados em sua própria conta, e a configuração desses recursos é controlada pelos desenvolvedores que enviam o código pelo pipeline. Portanto, o CDK Pipelines por si só não pode se proteger contra desenvolvedores mal-intencionados que tentam burlar as verificações de conformidade. Se seu modelo de ameaça incluir desenvolvedores que escrevem código do CDK, é necessário ter mecanismos externos de conformidade, como Hooks do AWS CloudFormation (preventivos) ou AWS Config (reativos), que o perfil de execução do AWS não tenha permissão para desabilitar.
-
As credenciais para ambientes de produção devem durar pouco. Após o bootstrapping e o provisionamento inicial, não é necessário que os desenvolvedores tenham as credenciais da conta. As mudanças podem ser implantadas por meio do pipeline. Reduza a possibilidade de vazamento de credenciais ao não precisar delas em primeiro lugar.
Solução de problemas
Os problemas a seguir são comumente encontrados ao começar a usar o CDK Pipelines.
- Pipeline: falha interna
-
CREATE_FAILED | {aws}::CodePipeline::Pipeline | Pipeline/Pipeline
Internal Failure
Verifique o token de acesso do GitHub. Ele pode estar ausente ou pode não ter as permissões para acessar o repositório.
- Chave: a política contém uma declaração com uma ou mais entidades principais inválidas
-
CREATE_FAILED | {aws}::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey
Policy contains a statement with one or more invalid principals.
Um dos ambientes de destino não foi inicializado com a nova pilha de bootstrap. Certifique-se de fazer o bootstrapping em todos os seus ambientes de destino.
- A pilha está no estado ROLLBACK_COMPLETE e não pode ser atualizada
-
Stack <STACK_NAME> is in ROLLBACK_COMPLETE state and cannot be updated. (Service:
AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request
ID: ...)
A pilha falhou em sua implantação anterior e está em um estado que não pode ser repetido. Exclua a pilha do console do AWS CloudFormation e repita a implantação.