

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.

# Menyebarkan aplikasi AWS CDK
<a name="deploy"></a>

Penyebaran AWS Cloud Development Kit (AWS CDK) adalah proses penyediaan infrastruktur Anda. AWS

## Cara AWS kerja penerapan CDK
<a name="deploy-how"></a>

 AWS CDK menggunakan AWS CloudFormation layanan untuk melakukan penyebaran. Sebelum Anda menerapkan, Anda mensintesis tumpukan CDK Anda. Ini membuat CloudFormation template dan artefak penerapan untuk setiap tumpukan CDK di aplikasi Anda. Penerapan dimulai dari mesin pengembangan lokal atau dari lingkungan *integrasi berkelanjutan dan pengiriman berkelanjutan (CI/CD*). Selama penerapan, aset diunggah ke sumber daya yang di-bootstrap dan CloudFormation templat dikirimkan untuk CloudFormation menyediakan sumber daya Anda. AWS 

Agar penerapan berhasil, berikut ini diperlukan:
+ Antarmuka Baris Perintah AWS CDK (AWS CDK CLI) harus diberikan izin yang valid.
+  AWS Lingkungan harus di-bootstrap.
+  AWS CDK harus mengetahui sumber daya yang di-bootstrap untuk mengunggah aset ke dalamnya.

## Prasyarat untuk penerapan CDK
<a name="deploy-prerequisites"></a>

Sebelum Anda dapat menerapkan aplikasi AWS CDK, Anda harus menyelesaikan yang berikut ini:
+ Konfigurasikan kredenal keamanan untuk CDK CLI.
+ Bootstrap AWS lingkungan Anda.
+ Konfigurasikan AWS lingkungan untuk setiap tumpukan CDK Anda.
+ Kembangkan aplikasi CDK Anda.<a name="deploy-prerequisites-creds"></a>

 **Konfigurasikan kredensional keamanan**   
Untuk menggunakan CDK CLI untuk AWS berinteraksi, Anda harus mengonfigurasi kredensi keamanan pada mesin lokal Anda. Untuk petunjuknya, lihat [Mengonfigurasi kredenal keamanan untuk AWS CDK CLI](configure-access.md).<a name="deploy-prerequisites-bootstrap"></a>

 **Bootstrap AWS lingkungan Anda**   
Penerapan selalu dikaitkan dengan satu atau lebih AWS [lingkungan](environments.md). Sebelum Anda dapat menerapkan, lingkungan harus [di-bootstrap](bootstrapping.md) terlebih dahulu. Bootstrapping menyediakan sumber daya di lingkungan Anda yang digunakan CDK untuk melakukan dan mengelola penerapan. [Sumber daya ini mencakup bucket Amazon Simple Storage Service (Amazon S3) dan repositori Amazon Elastic Container Registry (Amazon ECR) Registry (Amazon ECR) untuk menyimpan dan mengelola aset.](assets.md) Sumber daya ini juga mencakup peran AWS Identity and Access Management (IAM) and Access Management (IAM) yang digunakan untuk memberikan izin selama pengembangan dan penyebaran.  
Kami menyarankan Anda menggunakan perintah AWS CDK Command Line Interface (AWS CDK CLI) `cdk bootstrap` untuk mem-bootstrap lingkungan Anda. Anda dapat menyesuaikan bootstrap atau membuat sumber daya ini secara manual di lingkungan Anda jika perlu. Untuk petunjuk, lihat [Bootstrap lingkungan Anda untuk digunakan dengan AWS CDK](bootstrapping-env.md).<a name="deploy-prerequisites-env"></a>

 **Konfigurasikan AWS lingkungan**   
Setiap tumpukan CDK harus dikaitkan dengan lingkungan untuk menentukan ke mana tumpukan tersebut digunakan. Untuk petunjuk, lihat [Mengkonfigurasi lingkungan yang akan digunakan dengan AWS CDK](configure-env.md).<a name="deploy-prerequisites-develop"></a>

 **Kembangkan aplikasi CDK Anda**   
Dalam [proyek](projects.md) CDK, Anda membuat dan mengembangkan aplikasi CDK Anda. Dalam aplikasi Anda, Anda membuat satu atau beberapa [tumpukan](stacks.md) CDK. Dalam tumpukan Anda, Anda mengimpor dan menggunakan [konstruksi dari AWS Construct](constructs.md) Library untuk menentukan infrastruktur Anda. Sebelum Anda dapat menerapkan, aplikasi CDK Anda harus berisi setidaknya satu tumpukan.

## Sintesis aplikasi CDK
<a name="deploy-how-synth"></a>

Untuk melakukan sintesis, kami sarankan Anda menggunakan perintah CDK `cdk synth` CLI. `cdk deploy`Perintah juga akan melakukan sintesis sebelum memulai penerapan. Namun, dengan menggunakan`cdk synth`, Anda dapat memvalidasi aplikasi CDK dan menangkap kesalahan sebelum memulai penerapan.

Perilaku sintesis ditentukan oleh [stack synthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers) yang Anda konfigurasikan untuk tumpukan CDK Anda. Jika Anda tidak mengkonfigurasi synthesizer, ` [DefaultStackSynthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html) ` akan digunakan. Anda juga dapat mengkonfigurasi dan menyesuaikan sintesis untuk memenuhi kebutuhan Anda. Untuk petunjuk, lihat [Mengkonfigurasi dan melakukan sintesis tumpukan CDK](configure-synth.md).

Agar CloudFormation template yang disintesis Anda berhasil diterapkan ke lingkungan Anda, itu harus kompatibel dengan bagaimana lingkungan Anda di-bootstrap. Misalnya, CloudFormation template Anda harus menentukan bucket Amazon S3 yang benar untuk menerapkan aset. Jika Anda menggunakan metode default bootstrapping lingkungan Anda, synthesizer stack default akan berfungsi. Jika Anda menyesuaikan perilaku CDK, seperti menyesuaikan bootstrap atau sintesis, perilaku penerapan CDK dapat bervariasi.<a name="deploy-how-synth-app"></a>

 **Siklus hidup aplikasi**   
Saat Anda melakukan sintesis, aplikasi CDK dijalankan melalui fase berikut, yang dikenal sebagai siklus *hidup aplikasi*:    
 **Konstruksi (atau Inisialisasi)**   
Kode Anda membuat instance semua konstruksi yang ditentukan dan kemudian menautkannya bersama-sama. Pada tahap ini, semua konstruksi (aplikasi, tumpukan, dan konstruksi anak mereka) dipakai dan rantai konstruktor dijalankan. Sebagian besar kode aplikasi Anda dijalankan pada tahap ini.  
 **Persiapan**   
Semua konstruksi yang telah menerapkan `prepare` metode berpartisipasi dalam putaran akhir modifikasi, untuk mengatur status akhir mereka. Fase persiapan terjadi secara otomatis. Sebagai pengguna, Anda tidak melihat umpan balik dari fase ini. Jarang perlu menggunakan kait “siapkan”, dan umumnya tidak disarankan. Berhati-hatilah saat memutasi pohon konstruksi selama fase ini, karena urutan operasi dapat memengaruhi perilaku.  
Selama fase ini, setelah pohon konstruksi dibangun, [aspek](aspects.md) apa pun yang telah Anda konfigurasikan juga diterapkan.  
 **Validasi**   
Semua konstruksi yang telah menerapkan `validate` metode dapat memvalidasi diri mereka sendiri untuk memastikan bahwa mereka berada dalam keadaan yang akan diterapkan dengan benar. Anda akan mendapatkan pemberitahuan tentang kegagalan validasi yang terjadi selama fase ini. Umumnya, kami merekomendasikan untuk melakukan validasi sesegera mungkin (biasanya segera setelah Anda mendapatkan beberapa masukan) dan melempar pengecualian sedini mungkin. Melakukan validasi lebih awal meningkatkan keandalan karena jejak tumpukan akan lebih akurat, dan memastikan bahwa kode Anda dapat terus dijalankan dengan aman.  
 **Sintesis**   
Ini adalah tahap akhir menjalankan aplikasi CDK Anda. Ini dipicu oleh panggilan ke`app.synth()`, dan melintasi pohon konstruksi dan memanggil `synthesize` metode pada semua konstruksi. Konstruksi yang mengimplementasikan `synthesize` dapat berpartisipasi dalam sintesis dan menghasilkan artefak penyebaran ke perakitan cloud yang dihasilkan. Artefak ini termasuk CloudFormation template, bundel aplikasi AWS Lambda, file dan aset gambar Docker, dan artefak penyebaran lainnya. Dalam kebanyakan kasus, Anda tidak perlu menerapkan `synthesize` metode ini.<a name="deploy-how-synth-run"></a>

 **Menjalankan aplikasi Anda**   
CDK CLI perlu tahu cara menjalankan aplikasi CDK Anda. Jika Anda membuat project dari template menggunakan `cdk init` perintah, `cdk.json` file aplikasi Anda menyertakan `app` kunci. Kunci ini menentukan perintah yang diperlukan untuk bahasa yang digunakan aplikasi. Jika bahasa Anda memerlukan kompilasi, baris perintah akan melakukan langkah ini sebelum menjalankan aplikasi secara otomatis.  

**Example**  

```
{
  "app": "npx ts-node --prefer-ts-exts bin/my-app.ts"
}
```

```
{
  "app": "node bin/my-app.js"
}
```

```
{
    "app": "python app.py"
}
```

```
{
  "app": "mvn -e -q compile exec:java"
}
```

```
{
  "app": "dotnet run -p src/MyApp/MyApp.csproj"
}
```

```
{
  "app": "go mod download && go run my-app.go"
}
```
Jika Anda tidak membuat proyek menggunakan CDK CLI, atau jika Anda ingin mengganti baris perintah yang diberikan`cdk.json`, Anda dapat memberikan ` --app ` opsi saat menjalankan perintah. `cdk`

```
$ cdk --app '<executable>' <cdk-command> ...
```

`<executable>`Bagian dari perintah menunjukkan perintah yang harus dijalankan untuk menjalankan aplikasi CDK Anda. Gunakan tanda kutip seperti yang ditunjukkan, karena perintah tersebut berisi spasi. `<cdk-command>`Ini adalah subperintah seperti `synth` atau `deploy` yang memberi tahu CDK CLI apa yang ingin Anda lakukan dengan aplikasi Anda. Ikuti ini dengan opsi tambahan apa pun yang diperlukan untuk subperintah itu.

CDK CLI juga dapat berinteraksi langsung dengan rakitan cloud yang sudah disintesis. Untuk melakukan itu, lewati direktori tempat perakitan cloud disimpan`--app`. Contoh berikut mencantumkan tumpukan yang ditentukan dalam perakitan cloud yang disimpan di bawah`./my-cloud-assembly`.

```
$ cdk --app <./my-cloud-assembly> ls
```<a name="deploy-how-synth-assemblies"></a>

 **Rakitan awan**   
Panggilan ke `app.synth()` inilah yang memberi tahu AWS CDK untuk mensintesis rakitan cloud dari sebuah aplikasi. Biasanya Anda tidak berinteraksi langsung dengan rakitan cloud. Mereka adalah file yang menyertakan semua yang diperlukan untuk menerapkan aplikasi Anda ke lingkungan cloud. Misalnya, ini menyertakan AWS CloudFormation template untuk setiap tumpukan di aplikasi Anda. Ini juga menyertakan salinan aset file atau gambar Docker apa pun yang Anda referensikan di aplikasi Anda.  
Lihat [spesifikasi perakitan cloud](https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md) untuk detail tentang cara rakitan cloud diformat.  
Untuk berinteraksi dengan rakitan cloud yang dibuat aplikasi AWS CDK Anda, Anda biasanya menggunakan AWS CDK CLI. Namun, alat apa pun yang dapat membaca format perakitan cloud dapat digunakan untuk menerapkan aplikasi Anda.

## Men-deploy aplikasi Anda
<a name="deploy-how-deploy"></a>

Untuk menerapkan aplikasi Anda, kami sarankan Anda menggunakan `cdk deploy` perintah CDK CLI untuk memulai penerapan atau untuk mengonfigurasi penerapan otomatis.

Saat Anda menjalankan`cdk deploy`, CDK CLI `cdk synth` memulai untuk mempersiapkan penerapan. Diagram berikut mengilustrasikan siklus hidup aplikasi dalam konteks penerapan:

![\[Diagram alur siklus hidup aplikasi <shared id="AWS"/> CDK.\]](http://docs.aws.amazon.com/id_id/cdk/v2/guide/images/app-lifecycle_cdk-flowchart.png)


Selama penyebaran, CDK CLI mengambil perakitan cloud yang dihasilkan oleh sintesis dan menyebarkannya ke lingkungan. AWS Aset diunggah ke Amazon S3 dan Amazon ECR dan template dikirimkan CloudFormation AWS CloudFormation untuk penerapan.

Pada saat fase AWS CloudFormation penerapan dimulai, aplikasi CDK Anda telah selesai berjalan dan keluar. Ini memiliki implikasi sebagai berikut:
+ Aplikasi CDK tidak dapat merespons peristiwa yang terjadi selama penerapan, seperti sumber daya yang sedang dibuat atau seluruh penyelesaian penerapan. Untuk menjalankan kode selama fase penerapan, Anda harus menyuntikkannya ke AWS CloudFormation template sebagai sumber daya [khusus](cfn-layer.md#develop-customize-custom). Untuk informasi selengkapnya tentang menambahkan resource kustom ke aplikasi Anda, lihat [AWS CloudFormation modul](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html), atau contoh [sumber daya khusus](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/). Anda juga dapat mengonfigurasi modul [Triggers](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.triggers-readme.html) untuk menjalankan kode selama penerapan.
+ Aplikasi CDK mungkin harus bekerja dengan nilai yang tidak dapat diketahui pada saat dijalankan. Misalnya, jika aplikasi AWS CDK mendefinisikan bucket Amazon S3 dengan nama yang dibuat secara otomatis, dan Anda mengambil atribut (`bucket_name`Python:), nilai `bucket.bucketName` tersebut bukanlah nama bucket yang diterapkan. Sebaliknya, Anda mendapatkan `Token` nilai. Untuk menentukan apakah nilai tertentu tersedia, panggil `cdk.isUnresolved(value)` (Python:`is_unresolved`). Lihat [Token dan AWS CDK](tokens.md) untuk detailnya.<a name="deploy-how-deploy-permissions"></a>

 **Izin penerapan**   
Sebelum penerapan dapat dilakukan, izin harus dibuat. Diagram berikut menggambarkan izin yang digunakan selama penerapan default, saat menggunakan proses bootstrap default dan stack synthesizer:  

![\[Diagram alur proses penerapan <shared id="AWS"/> CDK default.\]](http://docs.aws.amazon.com/id_id/cdk/v2/guide/images/default-deploy-process_cdk_flowchart.png)
  
 **Aktor memulai penyebaran**   
Penerapan diprakarsai oleh *aktor*, menggunakan CDK CLI. Seorang aktor dapat berupa seseorang, atau layanan seperti AWS CodePipeline.  
Jika perlu, CDK CLI `cdk synth` berjalan saat Anda menjalankan. `cdk deploy` Selama sintesis, AWS identitas mengasumsikan `LookupRole` untuk melakukan pencarian konteks di lingkungan. AWS   
 **Izin dibuat**   
Pertama, kredensi keamanan aktor digunakan untuk mengautentikasi AWS dan mendapatkan identitas IAM pertama dalam prosesnya. Untuk pelaku manusia, bagaimana kredensi keamanan dikonfigurasi dan diperoleh tergantung pada bagaimana Anda atau organisasi Anda mengelola pengguna. Untuk informasi selengkapnya, lihat [Mengonfigurasi kredensi keamanan untuk AWS CDK CLI](configure-access.md). Untuk pelaku layanan, seperti CodePipeline, peran eksekusi IAM diasumsikan dan digunakan.  
Selanjutnya, peran IAM yang dibuat di AWS lingkungan Anda selama bootstrap digunakan untuk membuat izin untuk melakukan tindakan yang diperlukan untuk penerapan. Untuk informasi selengkapnya tentang peran ini dan apa yang mereka berikan izin, lihat [peran IAM yang dibuat selama bootstrap](bootstrapping-env.md#bootstrapping-env-roles). Proses ini meliputi:  
+  AWS Identitas mengasumsikan `DeploymentActionRole` peran dan meneruskan `CloudFormationExecutionRole` peran ke CloudFormation, memastikan bahwa CloudFormation mengambil peran ketika melakukan tindakan apa pun di lingkungan Anda AWS . `DeploymentActionRole`memberikan izin untuk melakukan penerapan ke lingkungan Anda dan `CloudFormationExecutionRole` menentukan tindakan CloudFormation apa yang dapat dilakukan.
+  AWS Identitas mengasumsikan`FilePublishingRole`, yang menentukan tindakan yang dapat dilakukan pada bucket Amazon S3 yang dibuat selama bootstrap.
+  AWS Identitas mengasumsikan`ImagePublishingRole`, yang menentukan tindakan yang dapat dilakukan pada repositori Amazon ECR yang dibuat selama bootstrap.
+ Jika perlu, AWS identitas mengasumsikan `LookupRole` untuk melakukan pencarian konteks di lingkungan. AWS Tindakan ini juga dapat dilakukan selama sintesis template.  
 **Penerapan dilakukan**   
Selama penerapan, CDK CLI membaca parameter versi bootstrap untuk mengonfirmasi nomor versi bootstrap. AWS CloudFormation juga membaca parameter ini pada waktu penerapan untuk mengonfirmasi. Jika izin di seluruh alur kerja penerapan valid, penerapan dilakukan. Aset diunggah ke sumber daya bootstrap dan CloudFormation template yang dihasilkan saat sintesis digunakan menggunakan CloudFormation layanan sebagai CloudFormation tumpukan untuk menyediakan sumber daya Anda.

# AWS Validasi kebijakan CDK pada waktu sintesis
<a name="policy-validation-synthesis"></a>

## Validasi kebijakan pada waktu sintesis
<a name="policy-validation"></a>

Jika Anda atau organisasi Anda menggunakan alat validasi kebijakan apa pun, seperti [AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html) atau [OPA, untuk menentukan batasan pada AWS CloudFormation template Anda, Anda dapat mengintegrasikannya dengan CDK pada waktu](https://www.openpolicyagent.org/) sintesis. AWS Dengan menggunakan plugin validasi kebijakan yang sesuai, Anda dapat membuat aplikasi AWS CDK memeriksa AWS CloudFormation template yang dihasilkan terhadap kebijakan Anda segera setelah sintesis. Jika ada pelanggaran, sintesis akan gagal dan laporan akan dicetak ke konsol.

Validasi yang dilakukan oleh AWS CDK pada waktu sintesis memvalidasi kontrol pada satu titik dalam siklus hidup penerapan, tetapi tidak dapat memengaruhi tindakan yang terjadi di luar sintesis. Contohnya termasuk tindakan yang diambil langsung di konsol atau melalui layanan APIs. Mereka tidak tahan terhadap perubahan AWS CloudFormation template setelah sintesis. [Beberapa mekanisme lain untuk memvalidasi aturan yang sama yang ditetapkan secara lebih otoritatif harus disiapkan secara independen, seperti [AWS CloudFormation hook](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html) atau Config.AWS](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html) Namun demikian, kemampuan AWS CDK untuk mengevaluasi aturan yang ditetapkan selama pengembangan masih berguna karena akan meningkatkan kecepatan deteksi dan produktivitas pengembang.

Tujuan dari validasi kebijakan AWS CDK adalah untuk meminimalkan jumlah pengaturan yang diperlukan selama pengembangan, dan membuatnya semudah mungkin.

**catatan**  
Fitur ini dianggap eksperimental, dan API plugin dan format laporan validasi dapat berubah di masa mendatang.

## Untuk pengembang aplikasi
<a name="for-application-developers"></a>

Untuk menggunakan satu atau beberapa plugin validasi dalam aplikasi Anda, gunakan `policyValidationBeta1` properti: `Stage`

```
import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';
const app = new App({
  policyValidationBeta1: [
    new CfnGuardValidator()
  ],
});
// only apply to a particular stage
const prodStage = new Stage(app, 'ProdStage', {
  policyValidationBeta1: [...],
});
```

Segera setelah sintesis, semua plugin yang terdaftar dengan cara ini akan dipanggil untuk memvalidasi semua template yang dihasilkan dalam lingkup yang Anda tentukan. Secara khusus, jika Anda mendaftarkan templat di `App` objek, semua templat akan dikenakan validasi.

**Awas**  
Selain memodifikasi perakitan cloud, plugin dapat melakukan apa saja yang dapat dilakukan oleh aplikasi AWS CDK Anda. Mereka dapat membaca data dari sistem file, mengakses jaringan, dll. Ini adalah tanggung jawab Anda sebagai konsumen plugin untuk memverifikasi bahwa itu aman untuk digunakan.

### AWS CloudFormation Plugin penjaga
<a name="cfnguard-plugin"></a>

Menggunakan [https://github.com/cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard)plugin memungkinkan Anda menggunakan [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) untuk melakukan validasi kebijakan. `CfnGuardValidator`Plugin ini dilengkapi dengan satu set kontrol [proaktif AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html) yang terpasang di dalamnya. Seperangkat aturan saat ini dapat ditemukan dalam [dokumentasi proyek](https://github.com/cdklabs/cdk-validator-cfnguard/blob/main/README.md). [Seperti yang disebutkan dalam [Validasi kebijakan pada waktu sintesis](#policy-validation), kami menyarankan agar organisasi menyiapkan metode validasi yang lebih otoritatif menggunakan kait.AWS CloudFormation ](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html)

Untuk pelanggan [AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html), kontrol proaktif yang sama ini dapat diterapkan di seluruh organisasi Anda. Saat Anda mengaktifkan AWS kontrol proaktif Control Tower di lingkungan AWS Control Tower Anda, kontrol dapat menghentikan penyebaran sumber daya yang tidak sesuai yang digunakan melalui. AWS CloudFormation Untuk informasi selengkapnya tentang kontrol proaktif terkelola dan cara kerjanya, lihat [dokumentasi AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html).

Kontrol yang dibundel AWS CDK dan kontrol proaktif AWS Control Tower terkelola ini paling baik digunakan bersama. Dalam skenario ini Anda dapat mengonfigurasi plugin validasi ini dengan kontrol proaktif yang sama yang aktif di lingkungan cloud AWS Control Tower Anda. Anda kemudian dapat dengan cepat mendapatkan keyakinan bahwa aplikasi AWS CDK Anda akan melewati AWS kontrol Control Tower dengan menjalankan secara `cdk synth` lokal.

### Laporan Validasi
<a name="validation-report"></a>

Saat Anda mensintesis aplikasi AWS CDK, plugin validator akan dipanggil dan hasilnya akan dicetak. Contoh laporan ditampilkan di bawah ini.

```
Validation Report (CfnGuardValidator)
-------------------------------------
(Summary)
╔═══════════╤════════════════════════╗
║ Status    │ failure                ║
╟───────────┼────────────────────────╢
║ Plugin    │ CfnGuardValidator      ║
╚═══════════╧════════════════════════╝
(Violations)
Ensure S3 Buckets are encrypted with a KMS CMK (1 occurrences)
Severity: medium
  Occurrences:

    - Construct Path: MyStack/MyCustomL3Construct/Bucket
    - Stack Template Path: ./cdk.out/MyStack.template.json
    - Creation Stack:
        └──  MyStack (MyStack)
             │ Library: aws-cdk-lib.Stack
             │ Library Version: 2.50.0
             │ Location: Object.<anonymous> (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:25:20)
             └──  MyCustomL3Construct (MyStack/MyCustomL3Construct)
                  │ Library: N/A - (Local Construct)
                  │ Library Version: N/A
                  │ Location: new MyStack (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:15:20)
                  └──  Bucket (MyStack/MyCustomL3Construct/Bucket)
                       │ Library: aws-cdk-lib/aws-s3.Bucket
                       │ Library Version: 2.50.0
                       │ Location: new MyCustomL3Construct (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:9:20)
    - Resource Name: amzn-s3-demo-bucket
    - Locations:
      > BucketEncryption/ServerSideEncryptionConfiguration/0/ServerSideEncryptionByDefault/SSEAlgorithm
  Recommendation: Missing value for key `SSEAlgorithm` - must specify `aws:kms`
  How to fix:
    > Add to construct properties for `cdk-app/MyStack/Bucket`
      `encryption: BucketEncryption.KMS`

Validation failed. See above reports for details
```

Secara default, laporan akan dicetak dalam format yang dapat dibaca manusia. Jika Anda ingin laporan dalam format JSON, aktifkan menggunakan `@aws-cdk/core:validationReportJson` via CLI atau meneruskannya langsung ke aplikasi:

```
const app = new App({
  context: { '@aws-cdk/core:validationReportJson': true },
});
```

Atau, Anda dapat mengatur pasangan nilai kunci konteks ini menggunakan `cdk.context.json` file `cdk.json` atau di direktori proyek Anda (lihat [Nilai konteks dan AWS CDK](context.md)).

Jika Anda memilih format JSON, AWS CDK akan mencetak laporan validasi kebijakan ke file yang dipanggil `policy-validation-report.json` di direktori perakitan cloud. Untuk format default yang dapat dibaca manusia, laporan akan dicetak ke output standar.

## Untuk penulis plugin
<a name="plugin-authors"></a>

### Plugin
<a name="plugins"></a>

Kerangka inti AWS CDK bertanggung jawab untuk mendaftarkan dan memanggil plugin dan kemudian menampilkan laporan validasi yang diformat. Tanggung jawab plugin adalah bertindak sebagai lapisan terjemahan antara kerangka kerja AWS CDK dan alat validasi kebijakan. Plugin dapat dibuat dalam bahasa apa pun yang didukung oleh AWS CDK. Jika Anda membuat plugin yang mungkin dikonsumsi oleh beberapa bahasa maka disarankan agar Anda membuat plugin `TypeScript` sehingga Anda dapat menggunakan JSII untuk mempublikasikan plugin di setiap bahasa AWS CDK.

### Membuat plugin
<a name="creating-plugins"></a>

Protokol komunikasi antara modul inti AWS CDK dan alat kebijakan Anda ditentukan oleh `IPolicyValidationPluginBeta1` antarmuka. Untuk membuat plugin baru, Anda harus menulis kelas yang mengimplementasikan antarmuka ini. Ada dua hal yang perlu Anda terapkan: nama plugin (dengan mengganti `name` properti), dan `validate()` metode.

Kerangka kerja akan memanggil`validate()`, melewati `IValidationContextBeta1` objek. Lokasi template yang akan divalidasi diberikan oleh`templatePaths`. Plugin harus mengembalikan instance dari`ValidationPluginReportBeta1`. Objek ini mewakili laporan yang akan diterima pengguna pada akhir sintesis.

```
validate(context: IPolicyValidationContextBeta1): PolicyValidationReportBeta1 {
  // First read the templates using context.templatePaths...
  // ...then perform the validation, and then compose and return the report.
  // Using hard-coded values here for better clarity:
  return {
    success: false,
    violations: [{
      ruleName: 'CKV_AWS_117',
      description: 'Ensure that AWS Lambda function is configured inside a VPC',
      fix: 'https://docs.bridgecrew.io/docs/ensure-that-aws-lambda-function-is-configured-inside-a-vpc-1',
      violatingResources: [{
        resourceName: 'MyFunction3BAA72D1',
        templatePath: '/home/johndoe/myapp/cdk.out/MyService.template.json',
        locations: 'Properties/VpcConfig',
      }],
    }],
  };
}
```

Perhatikan bahwa plugin tidak diizinkan untuk memodifikasi apa pun di perakitan cloud. Setiap upaya untuk melakukannya akan mengakibatkan kegagalan sintesis.

Jika plugin Anda bergantung pada alat eksternal, perlu diingat bahwa beberapa pengembang mungkin belum menginstal alat itu di workstation mereka. Untuk meminimalkan gesekan, kami sangat menyarankan Anda menyediakan beberapa skrip instalasi bersama dengan paket plugin Anda, untuk mengotomatiskan seluruh proses. Lebih baik lagi, jalankan skrip itu sebagai bagian dari instalasi paket Anda. Dengan`npm`, misalnya, Anda dapat menambahkannya ke `postinstall` [skrip](https://docs.npmjs.com/cli/v9/using-npm/scripts) dalam `package.json` file.

### Penanganan Pengecualian
<a name="handling-exemptions"></a>

Jika organisasi Anda memiliki mekanisme untuk menangani pengecualian, itu dapat diimplementasikan sebagai bagian dari plugin validator.

Contoh skenario untuk mengilustrasikan mekanisme pengecualian yang mungkin:
+ Organisasi memiliki aturan bahwa bucket Amazon S3 publik tidak diizinkan, *kecuali untuk skenario* tertentu.
+ Pengembang membuat bucket Amazon S3 yang termasuk dalam salah satu skenario tersebut dan meminta pengecualian (buat tiket misalnya).
+ Perkakas keamanan tahu cara membaca dari sistem internal yang mendaftarkan pengecualian

Dalam skenario ini pengembang akan meminta pengecualian dalam sistem internal dan kemudian akan memerlukan beberapa cara untuk “mendaftarkan” pengecualian itu. Menambahkan ke contoh plugin penjaga, Anda dapat membuat plugin yang menangani pengecualian dengan memfilter pelanggaran yang memiliki pengecualian yang cocok dalam sistem tiket internal.

Lihat plugin yang ada misalnya implementasi.
+  [@cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard) 

# Integrasi dan pengiriman berkelanjutan (CI/CD) menggunakan CDK Pipelines
<a name="cdk-pipeline"></a>

Gunakan modul [CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html) Pipelines dari AWS Construct Library untuk mengonfigurasi pengiriman aplikasi CDK yang berkelanjutan. AWS 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. APIs 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 keduanya yang didukung APIs, lihat API [asli CDK Pipelines di repositori aws-cdk](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md). GitHub *

## Bootstrap AWS lingkungan Anda
<a name="cdk-pipeline-bootstrap"></a>

Sebelum Anda dapat menggunakan CDK Pipelines, Anda harus mem-bootstrap lingkungan AWS [tempat](environments.md) 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 AWS CDK](bootstrapping.md) untuk informasi lebih lanjut tentang jenis sumber daya yang dibuat dengan 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 pipeline AWS CDK, 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-policies`menentukan ARN dari kebijakan di mana penerapan CDK Pipelines masa depan akan dijalankan. `AdministratorAccess`Kebijakan 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 AWS CDK Anda.

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 dan AWS Wilayah yang diperlukan.

**Example**  

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
```

```
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 aplikasi AWS CDK akan digunakan oleh pipeline, gunakan perintah berikut sebagai gantinya. `--trust`Opsi ini menunjukkan akun lain mana yang harus memiliki izin untuk menyebarkan aplikasi AWS CDK 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 dan AWS Wilayah yang diperlukan.

**Example**  

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
    --trust <PIPELINE-ACCOUNT-NUMBER>
```

```
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
<a name="cdk-pipeline-protect"></a>

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 AWS CLI CloudFormation atau konsol untuk memverifikasi.

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

   ```
   $ cdk bootstrap --termination-protection
   ```

1. Gunakan AWS CLI atau CloudFormation konsol 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
<a name="cdk-pipeline-init"></a>

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.

**Example**  

```
$ cdk init app --language typescript
```

```
$ cdk init app --language javascript
```

```
$ cdk init app --language python
```
Setelah aplikasi dibuat, masukkan juga dua perintah berikut. Ini mengaktifkan lingkungan virtual Python aplikasi dan menginstal dependensi inti AWS CDK.  

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

```
$ 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).

```
$ cdk init app --language csharp
```
Jika Anda menggunakan Visual Studio, buka file solusi di `src` direktori.

```
$ 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 [Nilai konteks dan AWS CDK](context.md).

## Tentukan pipa
<a name="cdk-pipeline-define"></a>

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 ` [CodePipeline](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html) ` adalah 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.

**Example**  
Dalam `lib/my-pipeline-stack.ts` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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']
      })
    });
  }
}
```
Dalam `bin/my-pipeline.ts` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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();
```
Dalam `lib/my-pipeline-stack.js` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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 }
```
Dalam `bin/my-pipeline.js` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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();
```
Dalam `my-pipeline/my-pipeline-stack.py` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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"]
                        )
                    )
```
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()
```
Dalam `src/main/java/com/myorg/MyPipelineStack.java` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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();
    }
}
```
Dalam `src/main/java/com/myorg/MyPipelineApp.java` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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();
    }
}
```
Dalam `src/MyPipeline/MyPipelineStack.cs` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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" }
                })
            });
        }
    }
}
```
Dalam `src/MyPipeline/Program.cs` (dapat bervariasi jika folder proyek Anda tidak diberi nama`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();
        }
    }
}
```

```
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
<a name="cdk-pipeline-stages"></a>

Untuk menentukan AWS aplikasi multi-stack yang dapat ditambahkan ke pipeline sekaligus, tentukan subclass dari. ` [Stage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html) ` (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 memanggil ` [addStage()](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss) ` dengan instance [Stage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html). 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.

**Example**  
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" }
    }));
  }
}
```
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 }
```
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")))
```
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()));
    }
}
```
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 ` [StageDeployment](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.StageDeployment.html) ` instance yang dikembalikan oleh `addStage()` panggilan. Anda dapat menambahkan tindakan pra-penerapan atau pasca-penerapan ke panggung dengan memanggil metodenya atau. `addPre()` `addPost()`

**Example**  

```
// 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'));
```

```
// 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'));
```

```
# 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'))
```

```
// 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"));
```

```
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 ` [Wave](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.Wave.html) ` ke a untuk menerapkannya secara paralel, misalnya saat menerapkan tahapan ke beberapa akun atau Wilayah.

**Example**  

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

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

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

```
// 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()));
```

```
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
<a name="cdk-pipeline-validation"></a>

Anda dapat menambahkan langkah-langkah ke Pipeline CDK untuk memvalidasi penerapan yang sedang Anda lakukan. Misalnya, Anda dapat menggunakan perpustakaan CDK Pipeline ` [ShellStep](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.ShellStep.html) ` 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 CLI AWS 

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

**Example**  

```
// stage was returned by pipeline.addStage

stage.addPost(new ShellStep("validate", {
  commands: ['../tests/validate.sh'],
}));
```

```
// stage was returned by pipeline.addStage

stage.addPost(new ShellStep("validate", {
  commands: ['../tests/validate.sh'],
}));
```

```
# stage was returned by pipeline.add_stage

stage.add_post(ShellStep("validate",
  commands=[''../tests/validate.sh'']
))
```

```
// stage was returned by pipeline.addStage

stage.addPost(ShellStep.Builder.create("validate")
        .commands(Arrays.asList("'../tests/validate.sh'"))
        .build());
```

```
// 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.

**Example**  

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

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

```
# 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"]))
```

```
// 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());
```

```
// 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 di`ShellStep`, 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.

**Example**  

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

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

```
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"],
))
```

```
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());
```

```
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.

**Example**  

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

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

```
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"],
))
```

```
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());
```

```
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
<a name="cdk-pipeline-security"></a>

Segala bentuk pengiriman berkelanjutan memiliki risiko keamanan yang melekat. Di bawah [Model Tanggung Jawab AWS Bersama](https://aws.amazon.com/compliance/shared-responsibility-model/), 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](https://aws.amazon.com/blogs/mt/proactively-keep-resources-secure-and-compliant-with-aws-cloudformation-hooks/) (preventif) atau [AWS Config](https://aws.amazon.com/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
<a name="cdk-pipeline-troubleshooting"></a>

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\$1COMPLETE dan tidak dapat diperbarui**   

```
Stack <STACK_NAME> is in ROLLBACK_COMPLETE state and cannot 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.

# Buat dan terapkan aset image kontainer di aplikasi CDK
<a name="build-containers"></a>

Saat Anda membuat aset image container dengan AWS Cloud Development Kit (AWS CDK), Docker digunakan secara default untuk melakukan tindakan ini. Jika Anda ingin menggunakan alat manajemen kontainer yang berbeda, Anda dapat mengganti Docker melalui variabel `CDK_DOCKER` lingkungan.

## Contoh: Buat dan publikasikan aset gambar kontainer dengan AWS CDK
<a name="build-containers-intro-example"></a>

Berikut ini adalah contoh sederhana dari aplikasi AWS CDK yang membangun dan menerbitkan aset container ke Amazon Elastic Container Registry (Amazon ECR) menggunakan Docker secara default:

 **Struktur proyek**   

```
my-cdk-app/
├── lib/
│   ├── my-stack.ts
│   └── docker/
│       ├── Dockerfile
│       └── app/
│           └── index.js
├── bin/
│   └── my-cdk-app.ts
├── package.json
├── tsconfig.json
└── cdk.json
```

 **Dockerfile**   

```
FROM public.ecr.aws/lambda/nodejs:16

# Copy application code
COPY app/ /var/task/

# (Optional) Install dependencies
# RUN npm install

# The Lambda Node.js base image looks for index.handler by default
```

 **Kode aplikasi**   
Dalam `lib/docker/app/index.js`:  

```
console.log("Hello from inside the container!");
```

 **Tumpukan CDK**   

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Define a Docker image asset
    const dockerImageAsset = new ecr_assets.DockerImageAsset(this, 'MyDockerImage', {
      directory: 'lib/docker', // Path to the directory containing the Dockerfile
    });

    // Output the ECR URI
    new cdk.CfnOutput(this, 'ECRImageUri', {
      value: dockerImageAsset.imageUri,
    });
  }
}
```

 **Aplikasi CDK**   

```
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-stack';

const app = new cdk.App();
new MyStack(app, 'MyStack');
```

Saat kami menjalankan`cdk deploy`, AWS Cloud Development Kit (AWS CDK) Command Line Interface (CLI) melakukan hal berikut:

1.  **Bangun image Docker** — Jalankan `docker build` secara lokal berdasarkan `Dockerfile` pada direktori tertentu ()`lib/docker`.

1.  **Tag gambar** — Jalankan `docker tag` untuk menandai gambar yang dibangun dengan hash unik, berdasarkan konten gambar.

1.  **Publikasikan ke Amazon ECR** - Jalankan `docker push` untuk mempublikasikan gambar kontainer ke repositori Amazon ECR. Repositori ini harus sudah ada. Itu dibuat selama proses bootstrapping default.

1.  **Keluarkan URI Gambar** - Setelah penerapan berhasil, URI ECR Amazon dari image kontainer yang dipublikasikan akan dikeluarkan di command prompt Anda. Ini adalah URI gambar Docker kami di Amazon ECR.

## Cara mengganti Docker dengan alat manajemen kontainer lain
<a name="build-container-replace"></a>

Gunakan variabel `CDK_DOCKER` lingkungan untuk menentukan jalur ke biner alat manajemen kontainer pengganti Anda. Berikut ini adalah contoh mengganti Docker dengan Finch:

```
$ which finch
/usr/local/bin/finch # Locate the path to the binary

$ export CDK_DOCKER='/usr/local/bin/finch' # Set the environment variable

$ cdk deploy # Deploy using the replacement
```

Aliasing atau penautan tidak didukung. Untuk mengganti Docker, Anda harus menggunakan variabel `CDK_DOCKER` lingkungan.

## Mesin pengganti drop-in Docker yang didukung
<a name="build-container-supported"></a>

 Finch didukung, meskipun mungkin ada beberapa fitur Docker yang tidak tersedia atau mungkin bekerja secara berbeda saat alat berkembang. Untuk informasi lebih lanjut tentang Finch, lihat [Siap Penerbangan: Mengumumkan Finch](https://aws.amazon.com/blogs/opensource/ready-for-flight-announcing-finch-1-0-ga/) 1.0 GA\$1 di *Blog AWS Open Source*.

Alat manajemen kontainer lainnya mungkin berfungsi. CDK tidak memeriksa pengganti Docker mana yang Anda gunakan untuk menentukan apakah itu didukung. Jika alat memiliki perintah Docker yang setara dan berperilaku serupa, itu akan berfungsi.

# Memecahkan masalah penerapan CDK AWS
<a name="deploy-troubleshoot"></a>

Memecahkan masalah umum saat menerapkan aplikasi AWS Cloud Development Kit (AWS CDK).

## Prinsipal layanan yang salah sedang dibuat saat penerapan
<a name="deploy-troubleshoot-sp"></a>

Saat menerapkan aplikasi CDK yang berisi peran AWS Identity and Access Management (IAM) and Access Management (IAM) dengan prinsipal layanan, Anda menemukan bahwa domain yang salah untuk prinsipal layanan sedang dibuat.

Berikut ini adalah contoh dasar pembuatan peran IAM yang dapat diasumsikan oleh Amazon CloudWatch Logs menggunakan prinsip layanannya:

```
import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class MyCdkProjectStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create an IAM role for CloudWatch Logs to assume
    const cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsRole', {
      assumedBy: new iam.ServicePrincipal('logs.amazonaws.com'), // This is for CloudWatch Logs
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCloudWatchLogsFullAccess')
      ]
    });

    // You can then use this role in other constructs or configurations where CloudWatch Logs needs to assume a role
  }
}
```

Saat Anda menerapkan tumpukan ini, prinsipal layanan bernama `logs.amazonaws.com` harus dibuat. Dalam kebanyakan kasus, AWS layanan menggunakan penamaan berikut untuk prinsip layanan:. `<service>.amazonaws.com`

### Penyebab umum
<a name="deploy-troubleshoot-sp-causes"></a>

Jika Anda menggunakan versi AWS CDK yang lebih lama dari v2.150.0, Anda mungkin mengalami bug ini. Dalam versi AWS CDK yang lebih lama, penamaan prinsip layanan tidak distandarisasi, yang dapat mengarah pada penciptaan prinsip layanan dengan domain yang salah.

Di AWS CDK v2.51.0, perbaikan diterapkan dengan menstandarisasi semua prinsip layanan yang dibuat secara otomatis untuk digunakan bila memungkinkan. `<service>.amazonaws.com` Perbaikan ini tersedia dengan mengizinkan tanda `@aws-cdk/aws-iam:standardizedServicePrincipals` fitur.

Mulai dari AWS CDK v2.150.0, ini menjadi perilaku default.

### Resolusi
<a name="deploy-troubleshoot-sp-resolution"></a>

Tingkatkan ke AWS CDK v2.150.0 atau yang lebih baru.

Jika Anda tidak dapat meningkatkan ke AWS CDK v2.150.0 atau yang lebih baru, Anda harus meningkatkan ke setidaknya v2.51.0 atau yang lebih baru. Kemudian, izinkan tanda fitur berikut di `cdk.json` file Anda:`@aws-cdk/aws-iam:standardizedServicePrincipals`.