Apa Itu dan Bagaimana Mengamankan Gambar Container

Bisakah gambar container Anda dipercaya? Pelajari cara Docker Content Trust (DCT) menggunakan tanda tangan digital untuk verifikasi gambar kontainer dan mengelola koleksi konten tepercaya.

Apa Itu dan Bagaimana Mengamankan Gambar Container

"Bisakah mereka dipercaya?" Salah satu masalah keamanan utama yang harus diselesaikan dalam sistem berbasis kontainer adalah memvalidasi bahwa gambar Anda benar dan berasal dari sumber yang benar (atau dimanipulasi secara jahat). Salah satu prediksi keamanan kami untuk tahun 2020 membahas bagaimana gambar container yang berbahaya - jika dipercaya - dapat berdampak merugikan pada pipeline perusahaan. Kami telah melaporkan serangan yang melibatkan penyalahgunaan gambar kontainer untuk melakukan aktivitas berbahaya seperti memindai server yang rentan dan penambangan cryptocurrency .

Untuk membantu mengatasi ini, Docker menyediakan fitur yang disebut "Kepercayaan Konten." Ini memungkinkan pengguna untuk menyebarkan gambar ke cluster atau swarm dengan percaya diri dan memverifikasi bahwa itu adalah gambar yang Anda harapkan. Apa yang tidak dilakukan Docker Content Trust (DCT) adalah memantau gambar Anda di seluruh kerumunan untuk perubahan atau apa pun yang bersifat semacam itu. Ini benar-benar pemeriksaan satu kali yang dilakukan oleh klien Docker, bukan server .

Ini berimplikasi pada kegunaan DCT sebagai sistem pemantauan integritas penuh. Dalam postingan sebelumnya oleh kolega saya Magno tentang sistem cloud-native , dia menyebutkan penggunaan alat penandatanganan gambar seperti Notaris untuk menjawab pertanyaan, "dapatkah mereka dipercaya?" DCT adalah upaya untuk menyediakan alat bawaan bagi klien Docker untuk melakukan hal itu.

Artikel ini akan membahas empat bidang:

  1. Bagaimana DCT bekerja
  2. Cara mengaktifkan DCT
  3. Langkah apa yang dapat diambil untuk mengotomatiskan validasi kepercayaan dalam pipeline continuous integration dan continuous deployment (CI / CD)
  4. Apa batasan sistem

Tujuan tambahan dari artikel ini adalah untuk menyediakan tutorial di tempat tunggal untuk memulai dan menjalankan eksperimen di DCT, terutama karena dokumen yang ada tampaknya tersebar dan tidak terpusat.

Bagaimana cara kerja Docker Content Trust (DCT)?

Intinya, Docker Content Trust sangat sederhana. Ini adalah logika di dalam klien Docker yang dapat memverifikasi gambar yang Anda tarik atau terapkan dari server registri, ditandatangani di server Notaris Docker pilihan Anda.

Alat Docker Notary memungkinkan penerbit untuk menandatangani koleksi mereka secara digital sementara pengguna dapat memverifikasi integritas konten yang mereka tarik. Melalui The Update Framework (TUF) , pengguna Notaris dapat memberikan kepercayaan atas pengumpulan data yang sewenang-wenang dan mengelola operasi yang diperlukan untuk memastikan kesegaran konten. Jika Anda belum pernah menggunakan server Notaris sebelumnya, lihat panduan pengantar Docker .

Grafik pada Gambar 1 menunjukkan bagaimana menyebarkan sebuah Docker swarm atau Docker build –pull memungkinkan klien untuk berbicara dengan server registri untuk mendapatkan gambar yang diperlukan dan server Notary untuk melihat bagaimana mereka ditandatangani. Jika Anda memiliki pengaturan variabel lingkungan yang benar, itu akan gagal untuk menerapkan gambar yang tidak bertanda tangan. Penandatanganan dapat dilakukan di mesin yang berbeda sehingga kunci pribadi tidak perlu disimpan di node manajemen Docker yang digunakan dalam penerapan.

Mengaktifkan DCT

Secara default, DCT dinonaktifkan. Kami perlu melakukan beberapa hal untuk menyiapkannya sehingga kami dapat menandatangani gambar yang ingin kami terapkan:

  1. Siapkan registri kami
  2. Siapkan server Notaris
  3. Dorong gambar ke server registri kami
  4. Tanda tangani gambar yang didorong
  5. Aktifkan DCT - Tetapkan variabel lingkungan yang benar di host manajemen kami sehingga tanda tangan gambar diverifikasi oleh perintah Docker

Langkah 1: Menyiapkan server registri kami

Cara termudah untuk menyiapkan server registri Anda adalah dengan menjalankan gambar registri dasar dari Docker Hub. Kita bisa melakukan ini dengan satu perintah (lihat di bawah). Pastikan Anda mengekspos port 5000 karena inilah yang didengarkan oleh server registri.

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ $ docker run -d -p 5000: 5000 --restart always --name registry registry: 2 
Tidak dapat menemukan image 'registry: 2' secara lokal
2: Menarik dari library / registri Intisari: sha256: 8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d Status: Mengunduh gambar baru untuk registri: 2 5df581b6eb4186edeebb40da766e7907427005d387facdb81365df35647d952d

Untuk memvalidasi bahwa itu sedang berjalan:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ $ buruh pelabuhan ps
PERINTAH GAMBAR ID KONTAINER NAMA PELABUHAN STATUS DIBUAT
5df581b6eb41 registry: 2 "/entrypoint.sh / etc…" 4 detik yang lalu Naik 3 detik 0.0.0.0:5000->5000/tcp registry

Langkah 2: Menyiapkan server Notaris

Selain server registri untuk menyimpan gambar kita, kita membutuhkan server Notaris untuk menyimpan tanda tangan gambar kita. Cukup menjalankan gambar registri dari Docker Hub membutuhkan banyak pengaturan, jadi mari kita gunakan cara paling sederhana untuk melakukannya: dengan mengkloning repositori dari kerangka pembaruan Kami kemudian dapat menggunakan docker-compose sederhana untuk menerapkan dengan Dockerfile mereka.

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ $ git clone https://github.com/theupdateframework/notary[.]git
Kloning menjadi 'notaris' ...
remote: Menghitung objek: 3, selesai.
remote: Menghitung objek: 100% (3/3), selesai.
remote: Mengompresi objek: 100% (3/3), selesai.
remote: Total 26412 (delta 0), digunakan kembali 1 (delta 0), pak-kembali 26409
Menerima objek: 100% (26412/26412), 35.08 MiB | 5,32 MiB / dtk, selesai.
Menyelesaikan delta: 100% (16038/16038), selesai.
ubuntu @ ip- {DIBLOKIR} -20-187 : ~ $ cd notary /
ubuntu @ ip- {BLOCKED} -20-187 : ~ / notary $ docker-compose up -d PERINGATAN: Mesin Docker yang Anda gunakan sedang berjalan dalam mode swarm. Penulisan tidak menggunakan mode swarm untuk menerapkan layanan ke banyak node dalam satu swarm. Semua penampung akan dijadwalkan pada node saat ini. Untuk menerapkan aplikasi Anda di seluruh swarm, gunakan `docker stack deploy`. <… .. Output terlalu banyak… hentikan….> Membuat notary_mysql_1 ... Membuat notary_mysql_1 ... selesai Membuat notary_signer_1 ... Membuat notary_signer_1 ... selesai Membuat notary_server_1 ... Membuat notary_server_1 ... selesai

Saya meninggalkan pesan peringatan tentang tidak menjalankan mode swarm dengan sengaja. File docker-compose.yml yang disediakan oleh framework update tidak kompatibel dengan swarm karena beberapa alasan:

  • Ini menggunakan versi: "2" - Ini sering kali dapat diperbaiki hanya dengan memperbarui ke versi "3". Perubahan lain mungkin diperlukan.
  • Ini menggunakan perintah build: - mode Swarm tidak mendukung operasi build. Anda perlu membangun layanan ini secara terpisah dan menambahkannya ke server registri. Karena Anda tidak akan memiliki tanda tangan kepercayaan konten pada saat ini, Anda harus memastikan Anda tidak memaksakan kepercayaan konten pada klien Docker Anda saat menerapkan layanan ini.

Seperti yang disebutkan sebelumnya, cara termudah untuk menyiapkan server registri Anda adalah dengan menjalankan image registri dasar dari Docker Hub dengan satu perintah. Pastikan port 5000 terbuka karena inilah yang didengarkan oleh server registri.

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ $ docker run -d -p 5000: 5000 --restart always --name registry registry: 2
Tidak dapat menemukan image 'registry: 2' secara lokal
2: Menarik dari library / registry
Digest: sha256: 8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d
Status: Mengunduh gambar yang lebih baru untuk registri: 2
5df581b6eb4186edeebb40da766e7907427005d38952d356427005d38952facdb81d81d81dfd8d8dd5dddddddd2

Mari kita validasi bahwa layanan Notaris kita sekarang sudah aktif. Itu juga harus menerapkan layanan MySQL yang digunakannya:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker ps
PERINTAH GAMBAR ID KONTAINER NAMA PELABUHAN STATUS DIBUAT
6c72520afc2e notary_server "/ usr / bin / env sh -c…" 12 menit yang lalu Naik 12 menit 0.0.0.0:4443->4443/tcp, 0.0.0.0:32769->8080/tcp notary_server_1
862fea9019c9 notary_signer "/ usr / bin / env sh -c…" 12 menit yang lalu Naik 12 menit notary_signer_1
8c8a05af5224 mariadb: 10.4 "docker-entrypoint.s…" 12 menit yang lalu Naik 12 menit 3306 / tcp notary_mysql_1
5df581b6eb41 registry: 2 "/entrypoint.sh / etc…" 21 menit yang lalu Naik 21 menit 0.0.0.0:5000->5000/tcp registry

Sekarang, kita perlu memasukkan gambar ke repositori kita. Kami melakukan ini dengan memberi tag pada gambar dengan URL repositori, lalu memanggil Docker push pada tag itu:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker pull ubuntu: terbaru
terbaru: Menarik dari library / ubuntu
54ee1f796a1e: Sudah ada 
f7bfea53ad12: Sudah ada 
46d371e02073: Sudah ada 
b66c17bbf772: Sudah ada 
Intisari: sha256: 31dfb10d52ce76c5ca0aa19d10b3e6424b830729e32a89a7c6eee2cda2be67a5
Status: Mengunduh gambar yang lebih baru untuk ubuntu: terbaru
docker.io/library/ubuntu:latest
ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker tag ubuntu: localhost terbaru: 5000 / ubuntu: tambang
 ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker push localhost: 5000 / ubuntu: milikku
Dorongan mengacu pada repositori [localhost: 5000 / ubuntu]
a4399aeb9a0e: Didorong 
35a91a75d24b: Didorong 
ad44aa179b33: Didorong 
2ce3c188c38d: Didorong 
tambang: intisari: sha256: 6f2fb2f9fb5582f8b587837afd6ea8f37d8d1d9e41168c90f410a6ef15fa8ce5 ukuran: 1152

Agar klien Docker mengetahui cara menggunakan server ini, Anda perlu menyetel variabel lingkungan yang menunjuk ke sana:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ export DOCKER_CONTENT_TRUST_SERVER = https: // localhost: 4443

Sekarang, mari kita tanda tangani gambar kita. Ada tiga langkah. Pertama, kita harus menambahkan kunci ke Docker yang bisa kita gunakan untuk penandatanganan. Selanjutnya, kita harus menambahkan kunci itu sebagai penanda untuk repositori Notaris untuk gambar ini, lalu kita perlu menandatanganinya.

Menambahkan kunci:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notary $ docker trust key menghasilkan sample_signer
Menghasilkan kunci untuk sample_signer ...
Masukkan frasa sandi untuk kunci sample_signer baru dengan ID f39f731: 
Ulangi frasa sandi untuk kunci sample_signer baru dengan ID f39f731: 
Berhasil membuat dan memuat kunci pribadi. Kunci publik terkait tersedia: /home/ubuntu/notary/sample_signer.pub

Menambahkan kunci sebagai penanda tangan:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker trust signer add --key sample_signer.pub sample_signer localhost: 5000 / ubuntu: mine
Menambahkan penanda tangan "sample_signer" ke localhost: 5000 / ubuntu: mine ...
Memulai repositori yang ditandatangani untuk localhost: 5000 / ubuntu: milik saya ...
Anda akan membuat frasa sandi kunci penandatanganan root baru. Frasa sandi ini
akan digunakan untuk melindungi kunci paling sensitif dalam sistem penandatanganan Anda. Silahkan
pilih kata sandi yang panjang dan rumit serta berhati-hatilah untuk menyimpan kata sandi dan
file kunci itu sendiri aman dan dicadangkan. Sangat disarankan agar Anda menggunakan file
pengelola kata sandi untuk menghasilkan frasa sandi dan menjaganya tetap aman. Tidak akan ada
cara untuk memulihkan kunci ini. Anda dapat menemukan kunci tersebut di direktori konfigurasi Anda.
Masukkan frasa sandi untuk kunci root baru dengan ID 65c87b3: 
Ulangi kata sandi untuk kunci root baru dengan ID 65c87b3: 
Masukkan frasa sandi untuk kunci repositori baru dengan ID 10e5763: 
Ulangi frasa sandi untuk kunci repositori baru dengan ID 10e5763: 
Berhasil menginisialisasi "localhost: 5000 / ubuntu: mine"
Berhasil menambahkan penandatangan: sample_signer ke localhost: 5000 / ubuntu: milik saya

Anda sekarang dapat melakukan inspeksi buruh pelabuhan dan melihat penanda tangan yang Anda tambahkan, tetapi perhatikan bahwa belum ada tag yang ditandatangani:

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker trust memeriksa localhost: 5000 / ubuntu: milik saya
[
    {
        "Nama": "localhost: 5000 / ubuntu: milik saya",
        "SignedTags": [],
        "Penandatangan": [
            {
                "Nama": "sample_signer",
                "Kunci": [
                    {
                        "ID": "f39f731f1c288b66c10d70905de6d98dfa40104741c878cb2766cddc6ed52f28"
                    }
                ]
            }
        ],
        "AdministrativeKeys": [
            {
                "Nama": "Root",
                "Kunci": [
                    {
                        "ID": "58617dd8ce70d089e7a2669bc782472e677466278d4519c2de5ec0148b681129"
                    }
                ]
            },
            {
                "Nama": "Repositori",
                "Kunci": [
                    {
                        "ID": "10e5763ffaaa7e1e606575005f460369f9f3ef49e553914b50589f1b822f695b"
                    }
                ]
            }
        ]
    }
]

Akhirnya, mari kita tanda tangani tag kita  : milik saya.

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker trust sign localhost: 5000 / ubuntu: milik saya
Menandatangani dan mendorong data kepercayaan untuk localhost gambar lokal: 5000 / ubuntu: milik saya, dapat menimpa data kepercayaan jarak jauh
Dorongan mengacu pada repositori [localhost: 5000 / ubuntu]
a4399aeb9a0e: Lapisan sudah ada 
35a91a75d24b: Lapisan sudah ada 
ad44aa179b33: Lapisan sudah ada 
2ce3c188c38d: Lapisan sudah ada 
tambang: intisari: sha256: 6f2fb2f9fb5582f8b587837afd6ea8f37d8d1d9e41168c90f410a6ef15fa8ce5 ukuran: 1152
Menandatangani dan mendorong metadata kepercayaan
Masukkan frasa sandi untuk kunci sample_signer dengan ID f39f731: 
Berhasil masuk localhost: 5000 / ubuntu: milik saya

Pemeriksaan lain menunjukkan bahwa  : tag tambang  telah ditandatangani oleh  sample_signer.

ubuntu @ ip- {DIBLOKIR} -20-187 : ~ / notaris $ docker trust memeriksa localhost: 5000 / ubuntu: milik saya
[
    {
        "Nama": "localhost: 5000 / ubuntu: milik saya",
        "SignedTags": [ 
            { 
                "SignedTag": "mine", 
                "Digest": "6f2fb2f9fb5582f8b587837afd6ea8f37d8d1d9e41168c90f410a6ef15fa8ce5", "Signers 
                ": [ 
                    "sample_signer" 
                ] 
            }
        ],
        "Penandatangan": [
            {
                "Nama": "sample_signer",
                "Kunci": [
                    {
                        "ID": "f39f731f1c288b66c10d70905de6d98dfa40104741c878cb2766cddc6ed52f28"
                    }
                ]
            }
        ],
        "AdministrativeKeys": [
            {
                "Nama": "Root",
                "Kunci": [
                    {
                        "ID": "58617dd8ce70d089e7a2669bc782472e677466278d4519c2de5ec0148b681129"
                    }
                ]
            },
            {
                "Nama": "Repositori",
                "Kunci": [
                    {
                        "ID": "10e5763ffaaa7e1e606575005f460369f9f3ef49e553914b50589f1b822f695b"
                    }
                ]
            }
        ]
    }
]

Kita bisa meminta klien Docker untuk memvalidasi bahwa setiap gambar dari repositori Anda ditandatangani sebelum menerapkan dengan menyetel variabel lingkungan DOCKER_CONTENT_TRUST = 1 . Ingat, jika Anda menggunakan sudo untuk menjalankan Docker, Anda harus menggunakan tanda –E untuk memastikan bahwa variabel lingkungan dipertahankan.

Otomatiskan validasi kepercayaan di pipeline CI / CD

Memeriksa apakah gambar ditandatangani atau tidak (dan tidak memeriksa tanda tangan tertentu) sepertinya tidak menyelesaikan kebutuhan keamanan internal. Namun, kemampuan memeriksa tanda tangan untuk gambar apa pun di repositori Anda memungkinkan untuk mengintegrasikan pemeriksaan ke dalam pipeline CI / CD Anda. Tim Anda dapat menulis kode untuk memastikan bahwa gambar tertentu ditandatangani oleh pemiliknya, dan hanya pemilik tersebut yang akan memiliki akses ke kunci pribadi.

Ini adalah cara yang baik untuk memvalidasi bahwa pihak yang bertanggung jawab yang benar telah menandatangani gambar apa pun yang disebarkan ke produksi. Ini juga mempersulit penyerang yang mencoba menyebarkan gambar berbahaya di dalam gerombolan Anda, baik melalui manipulasi psikologis atau mekanisme teknis.