Terraform, repositori mono dan kepatuhan sebagai kode

Halo semuanya. OTUS membuka perekrutan untuk grup baru di kursus “Platform infrastruktur berdasarkan Kubernetes” , sehubungan dengan ini kami menyiapkan terjemahan materi yang menarik tentang topik tersebut.




Anda mungkin salah satu dari mereka yang menggunakan terraform untuk Infrastruktur sebagai Kode, dan Anda bertanya-tanya bagaimana cara menggunakannya secara lebih produktif dan aman. Secara umum, baru-baru ini, ini telah mengganggu banyak orang. Kita semua menulis konfigurasi dan kode menggunakan alat yang berbeda, bahasa, dan menghabiskan banyak waktu menjadikannya lebih mudah dibaca, diperluas, dan terukur.


Mungkin masalahnya ada pada diri kita sendiri?

Kode tertulis harus menciptakan nilai atau memecahkan masalah, serta dapat digunakan kembali untuk deduplikasi. Biasanya, diskusi semacam ini berakhir dengan "Mari kita gunakan modul . " Kita semua menggunakan modul terraform, kan? Saya bisa menulis banyak cerita dengan masalah karena modularitas yang berlebihan, tetapi ini adalah cerita yang sama sekali berbeda, dan saya tidak akan melakukannya.


Tidak saya tidak akan. Jangan bersikeras, tidak ... Oke, mungkin nanti.

Ada praktik terkenal - untuk menandai kode saat menggunakan modul untuk mengunci modul root, untuk menjamin operasinya bahkan ketika mengubah kode modul. Pendekatan ini harus menjadi prinsip tim di mana modul yang sesuai ditandai dan digunakan dengan tepat.

... tapi bagaimana dengan dependensi? Bagaimana jika saya memiliki 120 modul dalam 120 repositori yang berbeda, dan mengubah satu modul mempengaruhi 20 modul lainnya. Apakah ini berarti bahwa kita perlu melakukan 20 + 1 permintaan tarik? Jika jumlah minimum pengulas adalah 2, maka ini berarti 21 x 2 = 44ulasan. Serius! Kami hanya melumpuhkan perintah dengan "mengubah satu modul" dan semua orang akan mulai mengirim meme atau gif dari Lord of the Rings, dan sisa hari akan hilang.


Satu PR untuk memberi tahu semua orang, satu PR untuk menyatukan semua orang, membelenggu dan terjun ke kegelapan

Apakah layak untuk bekerja? Haruskah kita mengurangi jumlah pengulas? Atau, mungkin, buat pengecualian untuk modul dan tidak memerlukan PR jika perubahan itu berdampak besar. Betulkah? Apakah Anda ingin berjalan membabi buta di hutan yang gelap? Atau menyatukan mereka semua, membosankan dan terjun ke dalam kegelapan ?

Tidak, jangan ubah urutan ulasan. Jika Anda berpikir bahwa bekerja dengan PR benar, maka patuhi itu. Jika Anda memiliki pipa cerdas atau Anda mendorong untuk menguasai, maka tetap dengan pendekatan ini.

Dalam hal ini, masalahnya bukan "bagaimana Anda bekerja" , tetapi "apa struktur repositori git Anda" .



Ini mirip dengan apa yang saya rasakan ketika saya pertama kali menerapkan saran di bawah ini.

Mari kita kembali ke dasar-dasarnya. Apa persyaratan umum untuk repositori dengan modul terraform?

  1. Ini harus ditandai agar tidak ada perubahan yang melanggar.
  2. Setiap perubahan harus dapat diuji.
  3. Perubahan harus melalui peninjauan bersama.

Maka saya sarankan yang berikut - JANGAN gunakan repositori mikro untuk modul terraform. Gunakan satu repositori mono .

  • Anda dapat menandai seluruh repositori saat ada perubahan / persyaratan
  • Setiap perubahan, PR atau push dapat diuji.
  • Setiap perubahan dapat melalui ulasan.


Saya memiliki kekuatan!

Oke, tapi bagaimana struktur repositori ini? Selama empat tahun terakhir, saya mengalami banyak kegagalan terkait hal ini, dan saya sampai pada kesimpulan bahwa direktori terpisah untuk modul akan menjadi solusi terbaik.


Contoh struktur direktori untuk repositori mono. Lihat perubahan tag_override?

Dengan demikian, perubahan modul yang mempengaruhi 20 modul lainnya hanya 1 PR ! Bahkan jika Anda menambahkan 5 pengulas ke PR ini, ulasan akan sangat cepat dibandingkan dengan repositori mikro. Jika Anda menggunakan Github, maka ini bahkan lebih baik! Anda dapat menggunakan CODEOWNERS untuk modul yang memiliki pengelola / pemilik, dan setiap perubahan pada modul ini HARUS disetujui oleh pemilik ini.

Bagus, tapi bagaimana cara menggunakan modul seperti itu, yang terletak di direktori mono-repositori?

Mudah:

module "from_mono_repo" {
 source = "git::ssh://.../<org>/<repo>.git//<my_module_dir>"
 ...
}
module "from_mono_repo_with_tags" {
  source = "git::ssh://..../<org>/<repo>.git//<mod_dir>?ref=1.2.4"
  ...
}
module "from_micro_repo" {
  source = "git::ssh://.../<org>/<mod_repo>.git"
  ...
}
module "from_micro_repo_with_tags" {
  source = "git::ssh://.../<org>/<mod_repo>.git?ref=1.2.4"
  ...
}

Apa kerugian dari struktur seperti ini? Nah, jika Anda mencoba menguji "setiap modul" dengan PR / ubah, maka Anda bisa mendapatkan 1,5 jam pipa CI. Anda perlu menemukan modul yang dimodifikasi dalam PR. Saya melakukannya seperti ini:

changed_modules=$(git diff --name-only $(git rev-parse origin/master) HEAD | cut -d "/" -f1 | grep ^aws- | uniq)

Ada kelemahan lain: setiap kali Anda menjalankan "terraform init", ini memuat seluruh repositori ke direktori .terraform. Tapi saya tidak pernah punya masalah dengan ini, karena saya menjalankan pipa saya dalam wadah AWS CodeBuild yang dapat diukur. Jika Anda menggunakan Jenkins dan Jenkins Slave yang gigih, maka Anda mungkin memiliki masalah ini.


Jangan membuat kita menangis.

Dengan repositori mono, Anda masih memiliki semua kelebihan repositori mikro, tetapi sebagai bonus, Anda mengurangi biaya servis modul Anda.

Jujur, setelah bekerja dalam mode ini, proposal untuk menggunakan repositori mikro untuk modul terraform harus dianggap sebagai kejahatan.

Bagus, bagaimana dengan pengujian unit? Apakah Anda benar-benar membutuhkan ini? ... Secara umum, apa yang sebenarnya Anda maksud dengan pengujian unit. Apakah Anda benar-benar akan memeriksa apakah sumber daya AWS dibuat dengan benar? Tanggung jawab siapa ini: terraform atau API yang menangani pembuatan sumber daya? Mungkin kita harus lebih fokus pada pengujian negatif dan idempotensi kode .

Untuk memeriksa idempotensi kode, terraform menyediakan parameter luar biasa yang disebut -detailed-exitcode. Lari saja:

> terraform plan -detailed-exitcode

Setelah itu, jalankan terraform applydan hanya itu. Setidaknya Anda akan yakin bahwa kode Anda idempoten dan tidak membuat sumber daya baru karena string acak atau yang lainnya.

Bagaimana dengan pengujian negatif? Apa, secara umum, pengujian negatif? Sebenarnya, ini tidak jauh berbeda dari pengujian unit, tetapi Anda memperhatikan situasi negatif.

Misalnya, tidak ada yang diizinkan membuat ember S3 yang tidak terenkripsi dan publik .

Jadi, alih-alih memeriksa apakah ember S3 benar-benar dibuat, Anda, pada kenyataannya, berdasarkan serangkaian kebijakan, periksa untuk melihat apakah kode Anda membuat sumber daya. Bagaimana cara melakukannya? Terraform Enterprise menyediakan alat yang hebat untuk ini, Sentinel .

... tetapi ada juga alternatif sumber terbuka. Saat ini, ada banyak alat untuk analisis statis kode HCL. Alat-alat ini, berdasarkan praktik terbaik umum, tidak akan memungkinkan Anda untuk melakukan sesuatu yang tidak diinginkan, tetapi bagaimana jika itu tidak memiliki tes yang Anda butuhkan ... atau, lebih buruk lagi, jika situasi Anda sedikit berbeda. Misalnya, Anda ingin mengizinkan beberapa ember S3 untuk dipublikasikan berdasarkan kondisi tertentu, yang, pada kenyataannya, akan menjadi bug keamanan untuk alat ini.

Di sinilah kepatuhan terraform muncul. Alat ini tidak hanya akan memungkinkan Anda untuk menulis tes Anda sendiri di mana Anda dapat menentukan APA yang Anda inginkan sebagai kebijakan perusahaan Anda, tetapi juga membantu Anda memisahkan keamanan dan pengembangan dengan memindahkan keamanan ke kiri. Kedengarannya cukup kontroversial, bukan? Tidak. Sedangkan?


Logo kepatuhan-terformat

Pertama-tama, kepatuhan terraform menggunakan Pengembangan Perilaku yang Didorong (BDD).

Feature: Ensure that we have encryption everywhere.

    Scenario: Reject if an S3 bucket is not encrypted
        Given I have aws_s3_bucket defined
        Then it must contain server_side_encryption_configuration

Periksa apakah enkripsi diaktifkan.

Jika ini tidak cukup untuk Anda, Anda dapat menulis lebih detail:

Feature: Ensure that we have encryption everywhere.

    Scenario: Reject if an S3 bucket is not encrypted with KMS
        Given I have aws_s3_bucket defined
        Then it must contain server_side_encryption_configuration
        And it must contain rule
        And it must contain apply_server_side_encryption_by_default
        And it must contain sse_algorithm
        And its value must match the "aws:kms" regex

Kami masuk lebih dalam dan memverifikasi bahwa KMS digunakan untuk enkripsi.

Kode terraform untuk pengujian ini:

resource "aws_kms_key" "mykey" {
 description             = "This key is used to encrypt bucket objects"
 deletion_window_in_days = 10
}

resource "aws_s3_bucket" "mybucket" {
 bucket = "mybucket"

 server_side_encryption_configuration {
   rule {
     apply_server_side_encryption_by_default {
       kms_master_key_id = "${aws_kms_key.mykey.arn}"
       sse_algorithm     = "aws:kms"
     }
   }
 }
}

Dengan demikian, tes dipahami secara harfiah SEMUA dalam organisasi Anda. Di sini Anda dapat mendelegasikan penulisan tes ini ke layanan keamanan atau pengembang dengan pengetahuan keamanan yang memadai. Alat ini juga memungkinkan Anda untuk menyimpan file BDD di repositori lain. Ini akan membantu membedakan tanggung jawab ketika perubahan dalam kode dan perubahan dalam kebijakan keamanan yang terkait dengan kode Anda akan menjadi dua entitas yang berbeda. Ini bisa menjadi tim yang berbeda dengan siklus hidup yang berbeda. Luar biasa bukan? Yah, setidaknya bagi saya itu.

Untuk informasi lebih lanjut tentang kepatuhan terraform, lihat presentasi ini .

Kami memecahkan banyak masalah dengan kepatuhan terraform, terutama di mana layanan keamanan cukup jauh dari tim pengembangan, dan mungkin tidak mengerti apa yang dilakukan pengembang. Anda sudah menebak apa yang terjadi di organisasi semacam itu. Biasanya, layanan keamanan mulai memblokir segala sesuatu yang mencurigakan bagi mereka dan membangun sistem keamanan berdasarkan keamanan perimeter. Ya Tuhan ...

Dalam banyak situasi, hanya menggunakan terraform dan kepatuhan terraform untuk tim yang merancang (atau / dan menemani) infrastruktur membantu menempatkan kedua tim yang berbeda ini di meja yang sama. Ketika tim keamanan Anda mulai mengembangkan sesuatu dengan umpan balik langsung dari semua jalur pengembangan, mereka biasanya mendapatkan motivasi untuk melakukan lebih banyak dan lebih banyak lagi. Yah, biasanya ...

Karena itu, ketika menggunakan terraform, kami menyusun repositori git sebagai berikut:



Tentu saja, ini cukup arogan. Tetapi saya beruntung (atau tidak beruntung?) Bekerja dengan struktur yang lebih rinci di beberapa organisasi. Sayangnya, semua ini tidak berakhir dengan baik. Akhir cerita yang bahagia harus disembunyikan di nomor 3.

Beritahu saya jika Anda memiliki kisah sukses dengan repositori mikro, saya benar-benar tertarik!



Kami mengundang Anda ke pelajaran gratis di mana kami akan mempertimbangkan komponen-komponen platform infrastruktur masa depan dan melihat bagaimana mengirimkan aplikasi kami dengan benar .

All Articles