Integrasi dan pengiriman berkelanjutan (CI/CD) menggunakan CDK Pipelines - AWS Cloud Development Kit (AWS CDK) v2

Ini adalah Panduan Pengembang AWS CDK v2. CDK v1 yang lebih lama memasuki pemeliharaan pada 1 Juni 2022 dan mengakhiri dukungan pada 1 Juni 2023.

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Integrasi dan pengiriman berkelanjutan (CI/CD) menggunakan CDK Pipelines

Gunakan modul CDK Pipelines dari AWS Construct Library untuk mengonfigurasi pengiriman aplikasi yang berkelanjutan. AWS CDK Saat Anda memasukkan kode sumber aplikasi CDK ke AWS CodeCommit,, atau GitHub AWS CodeStar, CDK Pipelines dapat secara otomatis membuat, menguji, dan menerapkan versi baru Anda.

CDK Pipelines diperbarui sendiri. Jika Anda menambahkan tahapan atau tumpukan aplikasi, pipeline secara otomatis mengkonfigurasi ulang dirinya sendiri untuk menerapkan tahapan atau tumpukan baru tersebut.

catatan

CDK Pipelines mendukung dua API. Salah satunya adalah API asli yang tersedia di Pratinjau Pengembang CDK Pipelines. Yang lainnya adalah API modern yang menggabungkan umpan balik dari pelanggan CDK yang diterima selama fase pratinjau. Contoh dalam topik ini menggunakan API modern. Untuk detail tentang perbedaan antara dua API yang didukung, lihat API asli CDK Pipelines di repositori aws-cdk. GitHub

Bootstrap AWS lingkungan Anda

Sebelum Anda dapat menggunakan CDK Pipelines, Anda harus mem-bootstrap lingkungan AWS tempat Anda akan menyebarkan tumpukan Anda.

Pipeline CDK melibatkan setidaknya dua lingkungan. Lingkungan pertama adalah tempat pipa disediakan. Lingkungan kedua adalah tempat Anda ingin menyebarkan tumpukan atau tahapan aplikasi (tahapan adalah grup tumpukan terkait). Lingkungan ini bisa sama, tetapi rekomendasi praktik terbaik adalah mengisolasi tahapan satu sama lain di lingkungan yang berbeda.

catatan

Lihat Bootstrapping untuk informasi lebih lanjut tentang jenis sumber daya yang dibuat oleh bootstrap dan cara menyesuaikan tumpukan bootstrap.

Penerapan berkelanjutan dengan CDK Pipelines memerlukan hal-hal berikut untuk disertakan dalam tumpukan CDK Toolkit:

  • Bucket Amazon Simple Storage Service (Amazon S3).

  • Repositori Amazon ECR.

  • IAM berperan untuk memberikan berbagai bagian pipa izin yang mereka butuhkan.

CDK Toolkit akan memutakhirkan tumpukan bootstrap yang ada atau membuat yang baru jika perlu.

Untuk mem-bootstrap lingkungan yang dapat menyediakan AWS CDK pipeline, panggil cdk bootstrap seperti yang ditunjukkan pada contoh berikut. Memanggil AWS CDK Toolkit melalui npx perintah untuk sementara menginstalnya jika perlu. Ini juga akan menggunakan versi Toolkit yang diinstal dalam proyek saat ini, jika ada.

--cloudformation-execution-policiesmenentukan ARN dari kebijakan di mana penerapan CDK Pipelines masa depan akan dijalankan. AdministratorAccessKebijakan default memastikan bahwa pipeline Anda dapat menerapkan setiap jenis AWS sumber daya. Jika Anda menggunakan kebijakan ini, pastikan Anda mempercayai semua kode dan dependensi yang membentuk aplikasi Anda AWS CDK .

Sebagian besar organisasi mengamanatkan kontrol yang lebih ketat pada jenis sumber daya apa yang dapat digunakan oleh otomatisasi. Periksa dengan departemen yang sesuai dalam organisasi Anda untuk menentukan kebijakan yang harus digunakan pipeline Anda.

Anda dapat menghilangkan --profile opsi jika AWS profil default Anda berisi konfigurasi otentikasi yang diperlukan dan. Wilayah AWS

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

Untuk mem-bootstrap lingkungan tambahan di mana AWS CDK aplikasi akan digunakan oleh pipeline, gunakan perintah berikut sebagai gantinya. --trustOpsi ini menunjukkan akun lain mana yang harus memiliki izin untuk menyebarkan AWS CDK aplikasi ke lingkungan ini. Untuk opsi ini, tentukan ID AWS akun pipeline.

Sekali lagi, Anda dapat menghilangkan --profile opsi jika AWS profil default Anda berisi konfigurasi otentikasi yang diperlukan dan. Wilayah AWS

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
Tip

Gunakan kredensi administratif hanya untuk bootstrap dan untuk menyediakan pipeline awal. Setelah itu, gunakan pipeline itu sendiri, bukan mesin lokal Anda, untuk menyebarkan perubahan.

Jika Anda memutakhirkan lingkungan bootstrapped lama, bucket Amazon S3 sebelumnya menjadi yatim piatu saat bucket baru dibuat. Hapus secara manual dengan menggunakan konsol Amazon S3.

Melindungi tumpukan bootstrap Anda dari penghapusan

Jika tumpukan bootstrap dihapus, AWS sumber daya yang awalnya disediakan di lingkungan untuk mendukung penerapan CDK juga akan dihapus. Ini akan menyebabkan pipa berhenti bekerja. Jika ini terjadi, tidak ada solusi umum untuk pemulihan.

Setelah lingkungan Anda di-bootstrap, jangan hapus dan buat ulang tumpukan bootstrap lingkungan. Sebagai gantinya, coba perbarui tumpukan bootstrap ke versi baru dengan menjalankan cdk bootstrap perintah lagi.

Untuk melindungi dari penghapusan tumpukan bootstrap Anda secara tidak sengaja, kami sarankan Anda memberikan --termination-protection opsi dengan cdk bootstrap perintah untuk mengaktifkan perlindungan terminasi. Anda dapat mengaktifkan perlindungan terminasi pada tumpukan bootstrap baru atau yang sudah ada. Untuk mempelajari lebih lanjut tentang opsi ini, lihat--termination-protection.

Setelah mengaktifkan perlindungan penghentian, Anda dapat menggunakan CloudFormation konsol AWS CLI atau untuk memverifikasi.

Untuk mengaktifkan perlindungan terminasi
  1. Jalankan perintah berikut untuk mengaktifkan perlindungan terminasi pada tumpukan bootstrap baru atau yang sudah ada:

    $ cdk bootstrap --termination-protection
  2. Gunakan CloudFormation konsol AWS CLI atau untuk memverifikasi. Berikut ini adalah contoh, menggunakan AWS CLI. Jika Anda memodifikasi nama stack bootstrap Anda, ganti CDKToolkit dengan nama tumpukan Anda:

    $ aws cloudformation describe-stacks --stack-name CDKToolkit --query "Stacks[0].EnableTerminationProtection" true

Inisialisasi proyek

Buat GitHub proyek baru yang kosong dan kloning ke workstation Anda di direktori. my-pipeline (Contoh kode kami dalam topik ini digunakan GitHub. Anda juga dapat menggunakan AWS CodeStar atau AWS CodeCommit.)

git clone GITHUB-CLONE-URL my-pipeline cd my-pipeline
catatan

Anda dapat menggunakan nama selain my-pipeline untuk direktori utama aplikasi Anda. Namun, jika Anda melakukannya, Anda harus mengubah file dan nama kelas nanti dalam topik ini. Ini karena AWS CDK Toolkit mendasarkan beberapa nama file dan kelas pada nama direktori utama.

Setelah kloning, inisialisasi proyek seperti biasa.

TypeScript
$ cdk init app --language typescript
JavaScript
$ cdk init app --language javascript
Python
$ cdk init app --language python

Setelah aplikasi dibuat, masukkan juga dua perintah berikut. Ini mengaktifkan lingkungan virtual Python aplikasi dan menginstal dependensi AWS CDK inti.

$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead $ python -m pip install -r requirements.txt
Java
$ cdk init app --language java

Jika Anda menggunakan IDE, Anda sekarang dapat membuka atau mengimpor proyek. Di Eclipse, misalnya, pilih File > Import > Maven > Existing Maven Projects. Pastikan bahwa pengaturan proyek diatur untuk menggunakan Java 8 (1.8).

C#
$ cdk init app --language csharp

Jika Anda menggunakan Visual Studio, buka file solusi di src direktori.

Go
$ cdk init app --language go

Setelah aplikasi dibuat, masukkan juga perintah berikut untuk menginstal modul AWS Construct Library yang dibutuhkan aplikasi.

$ go get
penting

Pastikan untuk memasukkan file cdk.json dan cdk.context.json file Anda ke kontrol sumber. Informasi konteks (seperti flag fitur dan nilai cache yang diambil dari AWS akun Anda) adalah bagian dari status proyek Anda. Nilainya mungkin berbeda di lingkungan lain, yang dapat menyebabkan perubahan tak terduga pada hasil Anda. Untuk informasi selengkapnya, lihat Konteks runtime.

Tentukan pipa

Aplikasi CDK Pipelines Anda akan menyertakan setidaknya dua tumpukan: satu yang mewakili pipeline itu sendiri, dan satu atau lebih tumpukan yang mewakili aplikasi yang digunakan melaluinya. Tumpukan juga dapat dikelompokkan ke dalam beberapa tahap, yang dapat Anda gunakan untuk menyebarkan salinan tumpukan infrastruktur ke lingkungan yang berbeda. Untuk saat ini, kami akan mempertimbangkan pipeline, dan kemudian menyelidiki aplikasi yang akan disebarkan.

Konstruk CodePipelineadalah konstruksi yang mewakili Pipeline CDK yang digunakan AWS CodePipeline sebagai mesin penyebarannya. Saat membuat instance CodePipeline dalam tumpukan, Anda menentukan lokasi sumber untuk pipeline (seperti GitHub repositori). Anda juga menentukan perintah untuk membangun aplikasi.

Misalnya, berikut ini mendefinisikan pipa yang sumbernya disimpan dalam GitHub repositori. Ini juga mencakup langkah membangun untuk aplikasi TypeScript CDK. Isi informasi tentang GitHub repo Anda di mana ditunjukkan.

catatan

Secara default, pipeline mengautentikasi GitHub menggunakan token akses pribadi yang disimpan di Secrets Manager dengan nama github-token tersebut.

Anda juga perlu memperbarui instantiasi tumpukan pipeline untuk menentukan AWS akun dan Wilayah.

TypeScript

Dalam lib/my-pipeline-stack.ts (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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'] }) }); } }

Dalam bin/my-pipeline.ts (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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

Dalam lib/my-pipeline-stack.js (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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 }

Dalam bin/my-pipeline.js (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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

Dalam my-pipeline/my-pipeline-stack.py (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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"] ) )

Dalam 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

Dalam src/main/java/com/myorg/MyPipelineStack.java (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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(); } }

Dalam src/main/java/com/myorg/MyPipelineApp.java (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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#

Dalam src/MyPipeline/MyPipelineStack.cs (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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" } }) }); } } }

Dalam src/MyPipeline/Program.cs (dapat bervariasi jika folder proyek Anda tidak diberi namamy-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")), } }

Anda harus menggunakan pipeline secara manual sekali. Setelah itu, pipeline tetap up to date dari repositori kode sumber. Jadi pastikan bahwa kode dalam repo adalah kode yang ingin Anda gunakan. Periksa perubahan Anda dan dorong ke GitHub, lalu terapkan:

git add --all git commit -m "initial commit" git push cdk deploy
Tip

Sekarang setelah Anda melakukan penerapan awal, AWS akun lokal Anda tidak lagi memerlukan akses administratif. Ini karena semua perubahan pada aplikasi Anda akan diterapkan melalui pipeline. Yang perlu Anda lakukan hanyalah mendorong GitHub.

Tahapan aplikasi

Untuk menentukan AWS aplikasi multi-stack yang dapat ditambahkan ke pipeline sekaligus, tentukan subclass dari. Stage (Ini berbeda dengan modul CdkStage CDK Pipelines.)

Panggung berisi tumpukan yang membentuk aplikasi Anda. Jika ada dependensi antara tumpukan, tumpukan secara otomatis ditambahkan ke pipa dalam urutan yang benar. Tumpukan yang tidak bergantung satu sama lain digunakan secara paralel. Anda dapat menambahkan hubungan ketergantungan antar tumpukan dengan menelepon. stack1.addDependency(stack2)

Tahapan menerima env argumen default, yang menjadi lingkungan default untuk tumpukan di dalamnya. (Tumpukan masih dapat memiliki lingkungannya sendiri yang ditentukan.).

Aplikasi ditambahkan ke pipeline dengan menelepon addStage() dengan instance. Stage Sebuah tahap dapat dipakai dan ditambahkan ke pipeline beberapa kali untuk menentukan tahapan yang berbeda dari pipeline aplikasi DTAP atau Multi-region Anda.

Kami akan membuat tumpukan yang berisi fungsi Lambda sederhana dan menempatkan tumpukan itu di panggung. Kemudian kita akan menambahkan stage ke pipeline sehingga bisa dikerahkan.

TypeScript

Buat file baru lib/my-pipeline-lambda-stack.ts untuk menampung tumpukan aplikasi kami yang berisi fungsi 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";') }); } }

Buat file baru lib/my-pipeline-app-stage.ts untuk menahan panggung kami.

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

Edit lib/my-pipeline-stack.ts untuk menambahkan panggung ke pipeline kami.

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

Buat file baru lib/my-pipeline-lambda-stack.js untuk menampung tumpukan aplikasi kami yang berisi fungsi 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 }

Buat file baru lib/my-pipeline-app-stage.js untuk menahan panggung kami.

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

Edit lib/my-pipeline-stack.ts untuk menambahkan panggung ke pipeline kami.

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

Buat file baru my_pipeline/my_pipeline_lambda_stack.py untuk menampung tumpukan aplikasi kami yang berisi fungsi 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';") )

Buat file baru my_pipeline/my_pipeline_app_stage.py untuk menahan panggung kami.

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

Edit my_pipeline/my-pipeline-stack.py untuk menambahkan panggung ke pipeline kami.

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

Buat file baru src/main/java/com.myorg/MyPipelineLambdaStack.java untuk menampung tumpukan aplikasi kami yang berisi fungsi 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(); } }

Buat file baru src/main/java/com.myorg/MyPipelineAppStage.java untuk menahan panggung kami.

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

Edit src/main/java/com.myorg/MyPipelineStack.java untuk menambahkan panggung ke pipeline kami.

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#

Buat file baru src/MyPipeline/MyPipelineLambdaStack.cs untuk menampung tumpukan aplikasi kami yang berisi fungsi 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';") }); } } }

Buat file baru src/MyPipeline/MyPipelineAppStage.cs untuk menahan panggung kami.

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

Edit src/MyPipeline/MyPipelineStack.cs untuk menambahkan panggung ke pipeline kami.

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

Setiap tahap aplikasi yang ditambahkan oleh addStage() hasil penambahan tahap pipeline yang sesuai, diwakili oleh StageDeploymentinstance yang dikembalikan oleh addStage() panggilan. Anda dapat menambahkan tindakan pra-penerapan atau pasca-penerapan ke panggung dengan memanggil metodenya atau. addPre() 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"));

Anda dapat menambahkan tahapan ke Wave untuk menerapkannya secara paralel, misalnya saat menerapkan tahapan ke beberapa akun atau Wilayah.

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

Pengujian penerapan

Anda dapat menambahkan langkah-langkah ke Pipeline CDK untuk memvalidasi penerapan yang sedang Anda lakukan. Misalnya, Anda dapat menggunakan perpustakaan CDK Pipeline ShellStep untuk melakukan tugas-tugas seperti berikut:

  • Mencoba mengakses Amazon API Gateway yang baru diterapkan yang didukung oleh fungsi Lambda

  • Memeriksa pengaturan sumber daya yang digunakan dengan mengeluarkan perintah AWS CLI

Dalam bentuknya yang paling sederhana, menambahkan tindakan validasi terlihat seperti ini:

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

Banyak AWS CloudFormation penerapan menghasilkan generasi sumber daya dengan nama yang tidak dapat diprediksi. Karena itu, CDK Pipelines menyediakan cara untuk AWS CloudFormation membaca output setelah penerapan. Ini memungkinkan untuk meneruskan (misalnya) URL yang dihasilkan dari penyeimbang beban ke tindakan pengujian.

Untuk menggunakan output, paparkan CfnOutput objek yang Anda minati. Kemudian, berikan dalam envFromCfnOutputs properti langkah untuk membuatnya tersedia sebagai variabel lingkungan dalam langkah itu.

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

Anda dapat menulis tes validasi sederhana tepat diShellStep, tetapi pendekatan ini menjadi berat ketika tes lebih dari beberapa baris. Untuk pengujian yang lebih kompleks, Anda dapat membawa file tambahan (seperti skrip shell lengkap, atau program dalam bahasa lain) ke dalam inputs properti ShellStep via. Input dapat berupa langkah apa pun yang memiliki output, termasuk sumber (seperti GitHub repo) atau lainnya. ShellStep

Membawa file dari repositori sumber sesuai jika file langsung dapat digunakan dalam pengujian (misalnya, jika file itu sendiri dapat dieksekusi). Dalam contoh ini, kami mendeklarasikan GitHub repo kami sebagai source (daripada membuat instance sebaris sebagai bagian dari). CodePipeline Kemudian, kami meneruskan fileset ini ke pipeline dan uji validasi.

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

Mendapatkan file tambahan dari langkah synth sesuai jika pengujian Anda perlu dikompilasi, yang dilakukan sebagai bagian dari sintesis.

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

Catatan keamanan

Segala bentuk pengiriman berkelanjutan memiliki risiko keamanan yang melekat. Di bawah Model Tanggung Jawab AWS Bersama, Anda bertanggung jawab atas keamanan informasi Anda di AWS Cloud. Pustaka CDK Pipelines memberi Anda awal yang baik dengan menggabungkan default aman dan praktik terbaik pemodelan.

Namun, pada dasarnya, perpustakaan yang membutuhkan akses tingkat tinggi untuk memenuhi tujuan yang dimaksudkan tidak dapat menjamin keamanan yang lengkap. Ada banyak vektor serangan di luar AWS dan organisasi Anda.

Secara khusus, perlu diingat hal-hal berikut:

  • Berhati-hatilah dengan perangkat lunak yang Anda andalkan. Periksa semua perangkat lunak pihak ketiga yang Anda jalankan di pipeline Anda, karena dapat mengubah infrastruktur yang akan digunakan.

  • Gunakan penguncian ketergantungan untuk mencegah peningkatan yang tidak disengaja. CDK Pipelines package-lock.json menghormati yarn.lock dan memastikan bahwa dependensi Anda adalah yang Anda harapkan.

  • CDK Pipelines berjalan pada sumber daya yang dibuat di akun Anda sendiri, dan konfigurasi sumber daya tersebut dikendalikan oleh pengembang yang mengirimkan kode melalui pipeline. Oleh karena itu, CDK Pipelines dengan sendirinya tidak dapat melindungi dari pengembang jahat yang mencoba melewati pemeriksaan kepatuhan. Jika model ancaman Anda menyertakan pengembang yang menulis kode CDK, Anda harus memiliki mekanisme kepatuhan eksternal seperti AWS CloudFormation Hooks (preventif) atau AWS Config (reaktif) yang Peran AWS CloudFormation Eksekusi tidak memiliki izin untuk dinonaktifkan.

  • Kredensi untuk lingkungan produksi harus berumur pendek. Setelah bootstrap dan penyediaan awal, pengembang tidak perlu memiliki kredensyal akun sama sekali. Perubahan dapat diterapkan melalui pipa. Kurangi kemungkinan kredensil bocor dengan tidak membutuhkannya sejak awal.

Pemecahan Masalah

Masalah berikut biasanya ditemui saat memulai dengan CDK Pipelines.

Pipa: Kegagalan Internal
CREATE_FAILED  | AWS::CodePipeline::Pipeline | Pipeline/Pipeline
Internal Failure

Periksa token GitHub akses Anda. Mungkin hilang, atau mungkin tidak memiliki izin untuk mengakses repositori.

Kunci: Kebijakan berisi pernyataan dengan satu atau beberapa prinsip yang tidak valid
CREATE_FAILED | AWS::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey
Policy contains a statement with one or more invalid principals.

Salah satu lingkungan target belum di-bootstrap dengan tumpukan bootstrap baru. Pastikan semua lingkungan target Anda di-bootstrap.

Stack dalam status ROLLBACK_COMPLETE dan tidak dapat diperbarui.
Stack STACK_NAME is in ROLLBACK_COMPLETE state and can not be updated. (Service:
AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request
ID: ...)

Tumpukan gagal penerapan sebelumnya dan dalam keadaan tidak dapat dicoba ulang. Hapus tumpukan dari AWS CloudFormation konsol dan coba lagi penerapan.