diff --git a/2022/Days/day28.md b/2022/Days/day28.md index 71e299a..a40ab9e 100644 --- a/2022/Days/day28.md +++ b/2022/Days/day28.md @@ -100,6 +100,6 @@ I am also going to build out a scenario as I have done in the other sections whe - [Hybrid Cloud and MultiCloud](https://www.youtube.com/watch?v=qkj5W98Xdvw) - [Microsoft Azure Fundamentals](https://www.youtube.com/watch?v=NKEFWyqJ5XA&list=WL&index=130&t=12s) - [Google Cloud Digital Leader Certification Course](https://www.youtube.com/watch?v=UGRDM86MBIQ&list=WL&index=131&t=10s) -- [AWS Basics for Beginners - Full Course](https://www.youtube.com/watch?v=ulprqHHWlng&t=5352s) +- [AWS Basics for Beginners - Full Course](https://youtu.be/k1RI5locZE4?si=0wPB2cdTY5hHgjl5) See you on [Day 29](day29.md) diff --git a/2022/tr/Days/day42.md b/2022/tr/Days/day42.md new file mode 100644 index 0000000..ef00f0a --- /dev/null +++ b/2022/tr/Days/day42.md @@ -0,0 +1,124 @@ +## Containers(Konteynerlar) + +Şimdi yeni bir bölüme başlıyoruz ve bu bölüm, özellikle Docker'a odaklanacak ve Konteynerler hakkında daha fazla anlayış kazanmak için bazı temel konulara odaklanacak. + +Ayrıca, bu bölümde ve ilerleyen zorlukların sonraki bölümlerinde kullanabileceğimiz bir konteyner oluşturmak için burada pratik yapmaya çalışacağım. + +Her zamanki gibi, bu ilk gönderi, nasıl buraya geldiğimiz ve bunun ne anlama geldiği hakkında büyük resme odaklanacaktır. + +#Platformların ve uygulama geliştirmenin tarihi +#Sanallaştırma ve Konteynerleştirme hakkında konuşmak istiyor muyuz? + +### Neden başka bir uygulama çalıştırma yöntemi? + +Bakmamız gereken ilk şey, neden yazılım veya uygulamalarımızı çalıştırmak için başka bir yönteme ihtiyacımız var? İşte sadece seçeneğin harika olmasıyla ilgili, uygulamalarımızı birçok farklı şekilde çalıştırabiliriz. Fiziksel donanıma sahip bir işletim sistemi ve tek bir uygulamanın dağıtıldığı durumları görebiliriz veya uygulamamızı çalıştıran sanal makine veya bulut tabanlı IaaS örneklerini görebiliriz, bunlar daha sonra bir veritabanına entegre olabilir veya kamu bulutunda bir PaaS teklifi olarak sunulabilir. Veya uygulamalarımızı konteynerlerde çalıştırırken görebiliriz. + +Yukarıdaki seçeneklerin hiçbiri yanlış veya doğru değil, ancak her birinin var olma nedenleri vardır ve ayrıca bu seçeneklerden hiçbirinin ortadan kalkacağına inanmıyorum. Konteynerler vs. Sanal Makineler gibi konuları ele alan birçok içerik gördüm ve gerçekten bir tartışma olmamalı çünkü bu daha çok elma ile armut karşılaştırması gibi bir şey, her ikisi de meyve (uygulamalarımızı çalıştırmanın yolları) olsa da aynı değil. + +Ayrıca, eğer başlıyorsanız ve bir uygulama geliştiriyorsanız, konteynerlere doğru yönelmeniz gerektiğini söylerim, çünkü bu konulara daha sonra değineceğiz, ancak bu verimlilik, hız ve boyutla ilgilidir. Ancak bunun bir bedeli vardır, konteynerler hakkında hiçbir fikriniz yoksa, nedenini anlamak ve bu zihniyete girmek için bir öğrenme eğrisi olacaktır. Eğer uygulamalarınızı belirli bir şekilde geliştirdiyseniz veya yeşil saha bir ortamda değilseniz, konteynerleri düşünmeden önce ele almanız gereken daha fazla zorluk yaşayabilirsiniz. + +Belirli bir yazılım parçasını indirme konusunda birçok farklı seçeneğimiz var, kullanabileceğimiz bir dizi farklı işletim sistemi var. Ve uygulamalarımızı nasıl kurmamız gerektiği için belirli talimatlar mevcut. + +![](Images/Day42_Containers1.png) + +Son zamanlarda giderek daha fazla gözlemliyorum ki bir zamanlar tam bir sunucu işletim sistemine, bir sanal makineye, fiziksel bir sunucuya veya bulut örneğine ihtiyaç duyduğumuz uygulamalar, şimdi yazılımlarının konteyner tabanlı sürümlerini yayınlıyorlar. Bu durumu ilginç buluyorum çünkü bu, konteynerlerin ve ardından herkese değil sadece uygulama geliştiricilerine odaklanmayı açan Kubernetes dünyasını herkese açıyor gibi görünüyor. + +![](Images/Day42_Containers2.png) + +Muhtemelen daha önce söylediğim gibi, cevabın ne olduğunu söyleyeceğimi savunmayacağım, soru nedir! Ama uygulamalarımızı dağıttığımızda farkında olmamız gereken başka bir seçenek olduğunu tartışmak istiyorum. + +![](Images/Day42_Containers4.png) + +Uzun bir süredir konteyner teknolojimiz var, o zaman neden son 10 yılda, son 5 yılda daha da popüler hale geldiğini söyleyebilirim. Onlarca yıldır konteynerlerimiz var. Bunun nedeni, sadece konteyner teknolojisine sahip olsak bile, yazılım yönetimi ile yaşadığımız aynı sorunlara sahip olmamızdır. + +Docker'ı bir araç olarak düşünürsek, popüler hale gelmesinin nedeni, kullanımı kolay ve bulması kolay görüntüler ekosistemidir. Sistemlerinize almak ve çalıştırmak kolaydır. Bunun büyük bir kısmı, yazılım ile karşılaştığımız tüm bu farklı zorlukların tamamında tutarlılıktır. MongoDB veya nodeJS olsun, her ikisini de çalıştırmak için izlenen süreç aynı olacaktır. Her ikisini durdurma süreci de aynıdır. Tüm bu sorunlar hala var olacak, ancak iyi bir konteyner ve görüntü teknolojisini bir araya getirdiğimizde, artık tüm bu farklı sorunları ele almamıza yardımcı olacak tek bir araç setine sahibiz. Bu sorunların bazıları aşağıda listelenmiştir: + +- İlk olarak, internet üzerinde yazılım bulmamız gerekiyor. +- Ardından bu yazılımı indirmemiz gerekiyor. +- Kaynağa güveniyor muyuz? +- Sonra bir lisansa mı ihtiyacımız var? Hangi lisans? +- Farklı platformlarla uyumlu mu? +- Paket nedir? İkili mi? Yürütülebilir mi? Paket yöneticisi mi? +- Yazılımı nasıl yapılandırırız? +- Bağımlılıklar? Genel indirme işini örttü mü, yoksa bunları da mı gerektiriyor? +- Bağımlılıkların bağımlılıkları? +- Uygulamayı nasıl başlatırız? +- Uygulamayı nasıl durdururuz? +- Otomatik yeniden başlar mı? +- Başlangıçta otomatik başlar mı?? +- Kaynak çatışmaları? +- Çakışan kütüphaneler? +- Port cakısmaları +- Yazılım için güvenlik? +- Yazılım güncellemeleri? +- Yazılımı nasıl kaldırabilirim?? + +Yukarıdakileri yazılımın karmaşıklığının üç alanına bölebiliriz ve konteynerler ve görüntüler bu konularda yardımcı olurlar + +| Distribution | Installation | Operation | +| ------------ | ------------ | ----------------- | +| Find | Install | Start | +| Download | Configuration| Security | +| License | Uninstall | Ports | +| Package | Dependencies | Resource Conflicts | +| Trust | Platform | Auto-Restart | +| Find | Libraries | Updates | + +Konteynerler ve görüntüler, muhtemelen diğer yazılım ve uygulamalarda yaşadığımız bazı zorlukları aşmamıza yardımcı olacak. + +Yüksek seviyede, kurulumu ve işletmeyi aynı liste taşıyabiliriz, Görüntüler bize bir dağıtım açısından yardımcı olurken, konteynerler kurulum ve işletme konularına yardımcı olur. + +Tahminen harika ve heyecan verici gelebilir, ancak hala bir konteynerin ne olduğunu anlamamız gerekiyor ve şimdi görüntülerden bahsettim, bu yüzden bir sonraki bölümde bu konuları ele alalım. + +Yazılım geliştirme için Konteynerler hakkında konuşurken sıkça gördüğünüz bir diğer şey, gemi konteynerleri ile birlikte kullanılan bir benzetme, denizlerin üzerinde büyük gemiler kullanılarak çeşitli malların taşınmasında gemi konteynerlerinin kullanıldığı bir gerçektir. + +![](Images/Day42_Containers5.png) + +Bu, konteynerler konusundaki konumuzla ne ilgisi var? Yazılım geliştiricilerinin yazdığı kodları düşünün, bu belirli kodu bir makineden başka bir makineye nasıl taşıyabiliriz? + +Önce yazılım dağıtımı, kurulum ve işletmeye dokunduğumuz şeyi düşünürsek ve şimdi bunu bir çevresel görsel olarak inşa etmeye başlarsak, donanım ve bir işletim sistemi ile birden fazla uygulama çalıştıracağınız bir ortamınız var. Örneğin, nodejs belirli bağımlılıklara ve belirli kütüphanelere ihtiyaç duyar. Daha sonra MySQL'i yüklemek istiyorsanız, gerekli kütüphaneler ve bağımlılıklara ihtiyaç duyar. Her yazılım uygulamasının kendi kütüphanesi ve bağımlılığı olacaktır. Özel kütüphaneler ve bağımlılıkların çakıştığı ve sorunlara yol açtığı özel bir durumumuz olmadıkça, herhangi bir uygulama arasında çakışma olasılığının daha fazla olduğu daha fazla uygulama olacaktır. Bununla birlikte, bu yalnızca her şeyin yazılım uygulamalarınızı düzelten bir dağıtım olduğu bir durum değildir, yazılım uygulamalarınız güncellenecek ve bu çakışmaları da tanıtabiliriz. + +![](Images/Day42_Containers6.png) + +Konteynerler bu sorunu çözmeye yardımcı olabilir. Konteynerler uygulamanızı **inşa etme**nize, uygulamayı **paketleme**nize, **dağıtma**nıza ve **ölçeklendirme**nize yardımcı olur. Mimarisine bir göz atalım, donanım ve işletim sisteminizin üzerinde daha sonra ele alacağımız bir konteyner motoruna sahip olacaksınız. Konteyner motoru yazılımları, uygulamanın ihtiyaç duyduğu kütüphaneleri ve bağımlılıkları paketleyen konteynerler oluşturmanıza yardımcı olur, bu nedenle bu konteyneri bir makineden diğerine sorunsuzca taşıyabilirsiniz ve uygulamanın çalışması için gereken kütüphaneler ve bağımlılıklar hakkında endişelenmeniz gerekmez, çünkü bunlar bir paketin parçası olarak gelir, ki bu da konteynerden başka bir şey değildir, bu nedenle farklı konteynerlere sahip olabilirsiniz ve bu konteyneri sistemler arasında taşıyabilirsinizken uygulamanın çalışması için gerekli olan altta yatan bağımlılıklardan endişelenmeden. + +![](Images/Day42_Containers7.png) + +### Bu Containerların Avantajları + +- Konteynerler, tüm bağımlılıkları içinde paketlemeye ve izole etmeye yardımcı olur. + +- Konteynerleri yönetmek kolaydır. + +- Bir sistemden diğerine taşımak kolaydır. + +- Konteynerler, yazılımı paketlemeye yardımcı olur ve herhangi bir tekrar çaba gerektirmeden kolayca taşıyabilirsiniz. + +- Konteynerler kolayca ölçeklenebilir. + +Konteynerleri kullanarak bağımsız konteynerleri ölçeklendirebilir ve bir yük dengeleyici veya hizmet kullanabilirsiniz, bu da trafiği bölmeye yardımcı olur ve uygulamaları yatay olarak ölçeklendirebilirsiniz. Konteynerler, uygulamalarınızı nasıl yönettiğinizde büyük bir esneklik ve kolaylık sunar. + +### Container Nedir? + +Bilgisayarlarımızda uygulamaları çalıştırdığımızda, bu web tarayıcısı veya bu yazıyı okumak için kullandığınız VScode gibi bir şey olabilir. Bu uygulama, bir işlem olarak çalışır veya işlem olarak bilinen bir şeydir. Dizüstü bilgisayarlarımız veya sistemlerimizde genellikle birden fazla uygulama veya işlem çalıştırmaya çalışırız. Yeni bir uygulama açtığımızda veya uygulama simgesine tıkladığımızda, çalıştırmak istediğimiz bir uygulamadır; bazen bu uygulama sadece arka planda çalışmasını istediğimiz bir hizmet olabilir. İşletim sistemimiz, arka planda çalışan ve sistemle ilgili kullanıcı deneyimini sağlayan birçok hizmetle doludur. + +Bu uygulama simgesi, dosya sisteminizdeki bir yürütülebilir dosyaya bir bağlantıyı temsil eder; işletim sistemi daha sonra bu yürütülebilir dosyayı belleğe yükler. İlginç bir şekilde, bu yürütülebilir dosya bazen bir işlem hakkında konuştuğumuzda bir görüntü olarak adlandırılır. + +Konteynerler işlemlerdir. Bir konteyner, kodu ve tüm bağımlılıklarını paketleyen standart bir yazılım birimidir, böylece uygulama bir hesaplama ortamından başka birine hızlı ve güvenilir bir şekilde çalışır. + +Konteynerleştirilmiş yazılım her zaman altyapıdan bağımsız olarak aynı şekilde çalışacaktır. Konteynerler yazılımı ortamından izole eder ve geliştirme ve sahneleme gibi farklılıklar olsa bile aynı şekilde çalışmasını sağlar. + +Önceki bölümde, konteynerlerin neden ve nasıl popüler hale geldiği konusunda konteynerler ve görüntülerin nasıl birleştiğinden bahsettim. + +### Image Nedir? + +Bir konteyner görüntüsü, bir uygulamayı çalıştırmak için gereken her şeyi içeren hafif, bağımsız, yürütülebilir bir yazılım paketidir: kod, çalıştırma zamanı (runtime), sistem araçları, sistem kütüphaneleri ve ayarlar. Konteyner görüntüleri, çalışma zamanında konteynerlere dönüşürler. + +## Kaynaklar + +- [TechWorld with Nana - Docker Tutorial for Beginners](https://www.youtube.com/watch?v=3c-iBn73dDE) +- [Programming with Mosh - Docker Tutorial for Beginners](https://www.youtube.com/watch?v=pTFZFxd4hOI) +- [Docker Tutorial for Beginners - What is Docker? Introduction to Containers](https://www.youtube.com/watch?v=17Bl31rlnRM&list=WL&index=128&t=61s) +- [Introduction to Container By Red Hat](https://www.redhat.com/en/topics/containers) + +Gorusmek Uzere [Gun 43](day43.md) diff --git a/2022/vi/Days/day71.md b/2022/vi/Days/day71.md new file mode 100644 index 0000000..89bcfbe --- /dev/null +++ b/2022/vi/Days/day71.md @@ -0,0 +1,111 @@ +--- +title: '#90DaysOfDevOps - Jenkins là gì? - Ngày 71' +published: false +description: 90DaysOfDevOps - Jenkins là gì? +tags: 'DevOps, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1048745 +--- + +## Jenkins là gì? + +Jenkins là một công cụ triển khai liên lục cho phép việc phát triển, kiểm thử và triển khai liên tục của mã nguồn mới được tạo ra. + +Có hai cách chúng ta có thể đạt được điều này, thông qua việc xây dựng hàng đêm (Nightly builds) hoặc phát triển liên tục. Lựa chọn đầu tiên là các nhà phát triển phát triển mã nguồn cho các công việc vào ban ngày và đến cuối ngày làm việc, họ đẩy những thay đổi đó lên kho mã nguồn. Sau đó, vào ban đêm, chúng ta thực hiện các bài kiểm tra đơn vị và xây dựng phần mềm. Điều này được coi như cách cũ để tích hợp tất cả mã nguồn lại với nhau. + +![](../../Days/Images/Day71_CICD1.png) + +Lựa chọn còn lại và cũng là cách được ưa thích hơn đó là các nhà phát triển vẫn tiếp tục thực hiện việc commit mã nguồn tới kho mã nguồn, sau khi commit mã nguồn đó được thực hiện quá trình xây dựng mã nguồn được khởi động liên tục. + +![](../../Days/Images/Day71_CICD2.png) + +Các phương pháp trên có nghĩa là với việc các kỹ sư phát triển ở các địa điểm khác nhau trên khắp thế giới, chúng ta không có một thời gian cố định hàng ngày để dừng lại quá trình commit và thay đổi mã nguồn. Đây chính là thời điểm Jenkins ra đời đóng vai trò như một máy chủ CI để kiểm soát các quá trình kiểm thử và xây dựng. + +![](../../Days/Images/Day71_CICD3.png) + +Tôi biết chúng ta đang nói về Jenkins ở bài này nhưng tôi cũng muốn thêm một vài công cụ khác phía dưới để có cái nhìn tại sao tôi thấy Jenkins là công cụ phổ biến nhất và tại sao các công cụ khác có thể làm gì tốt hơn Jenkins. + +- TravisCI - Một dịch vụ tích hợp lưu trữ, phân phối liên tục được sử dụng để xây và kiểm thử các dự án phần mềm được lưu trữ trên Github. + +- Bamboo - Có thể chạy nhiều tiến trình xây dựng song song để biên dịch nhanh hơn, chức năng kết nối với kho lưu trữ tích hợp và có các tác vụ xây dựng cho Ant và Maven. + +- Buildbot - là một framework mã nguồn mở để tự động hóa quy trình xây dựng, kiểm thử và phát hành phần mềm. Nó được viết bằng Python và hỗ trợ việc thực hiện song song, phân tán các công việc trên nhiều nền tảng khác nhau. + +- Apache Gump - Dành riêng cho các dự án Java, được thiết kế để xây dựng và kiểm thử các dự án Java mỗi đêm, đảm bảo tất cả các dự án đều tương thích ở cả cấp độ chức năng và API. + +Vì chúng ta bây giờ sẽ tập trung vào Jenkins - Jenkins một lần nữa là công cụ mã nguồn mở như các công cụ trên và là một máy chủ tự động hóa được viết bằng Java. Nó được sử dụng để tự động hóa quá trình phát triển phần mềm thông qua tích hợp liên tục và hỗ trợ quá trình phân phối liên tục. + +### Đặc điểm của Jenkins + +Như bạn mong đợi, Jenkins có nhiều đặc điểm bảo phủ nhiều lĩnh vực. + +**Cài đặt dễ dàng** - Jenkins là một chương trình độc lập (self-contained) viết bằng java và sẵn sàng trên mọi hệ điều hành như Windows, macOS và Linux. + +**Cấu hình dễ dàng** - Cài đặt và cấu hình dễ dàng thông qua giao diện web bao gồm kiểm tra lỗi và hỗ trợ tích hợp sẵn. + +**Plug-in** - Nhiều plugin có sẵn trong Trung tâm Cập nhật và tích hợp với nhiều công cụ khác trong chuỗi công cụ CI / CD. + +**Có thể mở rộng**- Ngoài các plugin có sẵn, Jenkins có thể mở rộng được thông qua kiến trúc plugin, cung cấp gần như vô tận các tùy chọn cho những gì nó có thể được sử dụng. + +**Phân tán** - Jenkins dễ dàng chạy trên hệ phân tán với nhiều máy chủ, giúp tăng tốc độ xây dựng, kiếm thử và triển khai qua nhiều nền tảng. + +### Jenkins Pipeline + +Bạn sẽ thấy pipeline này nhưng được sử dụng ở phạm vi rộng hơn và ở đây chúng tôi đề cập tới các công cụ cụ thể. + +Bạn commit mã nguồn tới Jenkins, nơi sau đó sẽ xây dựng ứng dụng của bạn, với tất cả bài kiểm thử tự động, nó sẽ phát hành và triển khai mã nguồn đó khi mỗi bước được hoàn thành. Jenkins sẽ tự động hoá quá trình này. + +![](../../Days/Images/Day71_CICD4.png) + +### Kiến trúc Jenkins + +Đầu tiên, để không làm lại những thứ đã có sẵn, [Tài liệu chính thức của Jenkins](https://www.jenkins.io/doc/developer/architecture/) luôn là nơi để bắt đầu, dù vậy, tôi vẫn sẽ ghi lại các ghi chú và kiến thức của mình ở đây. + +Jenkins có thể được cài đặt trên nhiều hệ điều hành khác nhau như Windows, Linux và macOS và cả khả năng triển khai như một Docker container và trong Kubernetes. [Cài đặt Jenkins](https://www.jenkins.io/doc/book/installing/) + +Đi sâu hơn vào vấn đề này, chúng ta có thể xem xét việc cài đặt Jenkins trong một cụm minikube mô phỏng việc triển khai trên Kubernetes. Nhưng điều này sẽ phụ thuộc vào các kịch bản chúng ta tạo ra trong phần còn lại của bài học. + +Chúng ta hãy phân tích hình ảnh dưới đây. + + +Bước 1 - Nhà phát triển commit các thay đổi tới kho lưu trữ mã nguồn. + + +Bước 2 - Jenkins kiểm tra kho mã nguồn theo các khoảng thời gian đều đặn và kéo mã nguồn mới. + +Bước 3 - Máy chủ xây dựng sau đó xây các mã nguồn thành chương trình thực thi, trong ví dụ này chúng ta đang dùng maven - một máy chủ xây dựng phổ biến. Đây là một lĩnh vực khác cần đề cập. + +Bước 4 - Nếu việc xây dựng thất bại thì phản hồi được gửi trả về các nhà phát triển. + +Bước 5 - Jenkins sau đó chuyển giao ứng dụng đã xây dựng lên máy chủ kiểm thử, trong ví dụ này, chúng ta đang dùng selenium - một máy chủ kiểm thử phổ biến. Đây là cũng là một lĩnh vực khác cần bàn luận. + +Bước 6 - Nếu việc kiểm thử thất bại thì phản hồi được gửi trả về các nhà phát triển. + +Bước 7 - Nếu kiểm thử thành công thì chúng ta có thể phát hành tới môi trường sản phẩm. + +Chu kỳ này diễn ra liên tục, điều này cho phép các ứng dụng được cập nhật trong vài phút thay vì hàng giờ, ngày, tháng, năm! + +![](../../Days/Images/Day71_CICD5.png) + +Có rất nhiều khía cạnh khác về kiến trúc của Jenkins, ví dụ như nó có khả năng hoạt động theo kiến trúc master-slave, cho phép một master phân tán tới các slave của Jenkins. + +Để tham khảo thêm, Jenkins là mã nguồn mở, sẽ có nhiều doanh nghiệp cần được hỗ trợ, Cloudbees là phiên bản doanh nghiệp của Jenkins cung cấp hỗ trợ và các chức năng trả phí khác cho các khách hàng doanh nghiệp. + +Ví dụ như một trong số các khách hàng là Bosch, bạn có thể tìm hiểu về trường hợp của Bosch ở [đây](https://assets.ctfassets.net/vtn4rfaw6n2j/case-study-boschpdf/40a0b23c61992ed3ee414ae0a55b6777/case-study-bosch.pdf) + +Tôi sẽ tìm kiếm một ví dụ về một ứng dụng mà chúng ta có thể dùng qua đó hiểu được việc sử dụng Jenkins và sử dụng nó với các công cụ khác. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 72](day72.md) + diff --git a/2022/vi/Days/day72.md b/2022/vi/Days/day72.md new file mode 100644 index 0000000..5cca987 --- /dev/null +++ b/2022/vi/Days/day72.md @@ -0,0 +1,164 @@ +--- +title: '#90DaysOfDevOps - Thực hành cùng Jenkins - Ngày 72' +published: false +description: 90DaysOfDevOps - Thực hành cùng Jenkins +tags: 'DevOps, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1048829 +--- + +## Thực hành cùng Jenkins + +Hôm nay chúng ta sẽ thực hành cùng Jenkins và thực hiện một số việc như một phần của CI pipeline, xem xét một số mã nguồn ví dụ mà chúng ta có thể sử dụng. + +### Pipeline là gì? + +Trước khi bắt đầu chúng ta cần biết một pipeline là gì khi đến với CI, và chúng ta đã đề cập điều này ở ngày trước đó với ảnh sau đây + +![](../../Days/Images/Day71_CICD4.png) + +Chúng ta muốn thực hiện quy trình hoặc các bước phía trên và tự động hóa chúng để có một kết quả cuối cùng, nghĩa là chúng ta đã triển khai ứng dụng mà chúng ta có thể đưa tới khách hàng, người dùng cuối, vân vân. + +Quy trình tự động này cho phép chúng ta duy trì kiểm soát phiên bản đến người dùng và khách hàng của chúng ta. Mọi thay đổi, nâng cao tính năng, sửa lỗi, vân vân đều thông qua quy trình tự động này xác nhận rằng mọi thứ đều ổn mà không tốn quá nhiều sự can thiệp thủ công để đảm bảo rằng mà nguồn của chúng ta là tốt. + +Quy trình này bao gồm việc xây dựng phần mềm một cách đáng tin cậy và có thể lặp lại, cũng như đưa phần mềm đã được xây dựng (gọi là "build") qua nhiều giai đoạn kiểm thử và triển khai. + +Jenkins pipeline được viết vào một tệp văn bản gọi là Jenkinsfile. Nó được commit tới một kho điều khiển mã nguồn. Điều này cũng được biết như là Pipeline dưới dạng mã nguồn, chúng ta cũng có thể thấy rất giống với Cơ sở hạ tầng dưới dạng mã nguồn mà ta đã đề cập ở vài tuần trước. + +[Jenkins Pipeline Definition](https://www.jenkins.io/doc/book/pipeline/#ji-toolbar) + +### Triển khai Jenkins + +Tôi có chút thích thú khi triển khai Jenkins, bạn sẽ nhận ra từ [tài liệu](https://www.jenkins.io/doc/book/installing/) rằng có nhiều tùy chọn giúp bạn có thể cài đặt Jenkins. + +Với việc tôi đã có sẵn minikube và chúng ta đã sử dụng nó một số lần, tôi cũng muốn sử dụng nó cho tác vụ này.(Nó cũng là miễn phí!) Mặc dù các bước đưa ra trong [Cài đặt Kubernetes](https://www.jenkins.io/doc/book/installing/kubernetes/) khiến tôi gặp khó khăn và không khởi chạy được Jenkins, bạn có thể so sánh với các bước tôi ghi lại ở đây. + +Bước đầu tiên là khởi chạy cụm minikube của chúng ta, chúng ta có thể làm điều này với câu lệnh `miniube start` + +![](../../Days/Images/Day72_CICD1.png) + +Tôi đã thêm một thư mục với tất cả giá trị và cấu hình YAML có thể thấy ở [đây](../../Days/CICD/Jenkins). Bây giờ chúng ta đã có cụm riêng và có thể chạy lệnh sau đây để tạo không gian tên jenkins. `kubectl create -f` + +![](../../Days/Images/Day72_CICD2.png) + +Chúng ta sẽ sử dụng Helm để triển khai Jenkins tới cụm, chúng ta đã đề cập tới helm ở phần Kubernetes. Đầu tiên chúng ta cần thêm kho lưu trữ jenkinsci helm `helm repo add jenkinsci https://charts.jenkins.io` sau đó cập nhật các biểu đồ của helm `helm repo update` . + +![](../../Days/Images/Day72_CICD3.png) + +Ý tưởng đằng sau Jenkins là nó sẽ lưu trạng thái pipeline của nó, bạn có thể khởi chạy cài đặt helm như ở trên nhưng nếu các pod đó khởi động lại, bị thay đổi hoặc chỉnh sửa thì mọi pipeline hoặc cấu hình đã tạo sẽ bị mất. Chúng ta sẽ tạo một ổ đĩa để lưu trữ lâu dài bằng sử dụng tệp jenkins-volume.yml với câu lệnh `kubectl apply -f jenkins-volume.yml` . + +![](../../Days/Images/Day72_CICD4.png) + +Chúng ta cũng cần một service account (shoud i change to `tài khoản dịch vụ`) có thể tạo bằng câu lệnh và tệp YAML này. `kubectl apply -f jenkins-sa.yml` + +![](../../Days/Images/Day72_CICD5.png) + +Ở giai đoạn này, chúng ta đã sẵn sàng triển khai bằng cách sử dụng biểu đồ helm, chúng ta đầu tiên cần định nghĩa biểu đồ sử dụng `chart=jenkinsci/jenkins` và sau đó chúng ta sẽ triển khai sử dụng câu lệnh này, trong đó tệp jenkins-values.yml các service account mà chúng ta đã triển khai trước đó tới cụm. `helm install jenkins -n jenkins -f jenkins-values.yml $chart` + +![](../../Days/Images/Day72_CICD6.png) + +Tại giai đoạn này, các pod sẽ kéo hình ảnh nhưng pod sẽ không có quyền truy cập tới tài nguyên lưu trữ, vì vậy cấu hình không thể bắt đầu để khởi tạo Jenkins. + +Đây chính là điều mà tài liệu không giúp tôi hiểu rõ điều gì cần phải xảy ra. Nhưng chúng ta có thể thấy rằng chúng ta không có quyền để bắt đầu việc cài đặt Jenkins. + +![](../../Days/Images/Day72_CICD7.png) + +Để khắc phục vấn đề trên hoặc giải quyết nó, chúng ta cần đảm bảo rằng chúng ta cung cấp quyền truy cập hoặc quyền hợp lệ cho các Jenkins pod có thể ghi dữ liệu vào vị trí chúng ta đề xuất. Chúng ta có thể thực hiện điều này bằng cách sử dụng `minikube ssh`, điều này sẽ đưa chúng ta vào bên trong container docker của minikube mà chúng ta đang chạy, sau đó sử dụng `sudo chown -R 1000:1000 /data/jenkins-volume` để đảm bảo rằng chúng ta đã đặt quyền hợp lệ trên volume lưu dữ liệu của chúng ta. + +![](../../Days/Images/Day72_CICD8.png) + +Quá trình trên có thể sửa được lỗi các pod, tuy nhiên, nếu không thành công bạn có thể làm mới các pod với câu lệnh `kubectl delete pod jenkins-0 -n jenkins`. Lúc này, bạn sẽ có 2/2 pod đang chạy gọi là jenkns-0. + +![](../../Days/Images/Day72_CICD9.png) + +Bây giờ chúng ta cần mật khẩu admin và có thể sử dụng câu lệnh sau để lấy thông tin. `kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo` + +![](../../Days/Images/Day72_CICD10.png) + +Hãy mở một cửa sổ terminal mới vì chúng ta sẽ sử dụng câu lệnh `port-forward` cho phép chúng ta truy cập từ máy trạm. `kubectl --namespace jenkins port-forward svc/jenkins 8080:8080` + +![](../../Days/Images/Day72_CICD11.png) + +Chúng ta bây giờ có thể mở trình duyệt và truy cập `http://localhost:8080` xác thực với tài khoản: admin và mật khẩu đã lấy ở bước trước đó. + +![](../../Days/Images/Day72_CICD12.png) + +Sau khi xác thực thành công, trang chào mừng tới Jenkins sẽ có giao diện như hình: + +![](../../Days/Images/Day72_CICD13.png) + +Từ đây, tôi đề xuất bạn đi đến mục "Manage Jenkins" và ban sẽ thấy mục "Manage Plugins" có một số bản cập nhật có sẵn. Chọn tất cả các plugin và chọn "Download now and install after restart" + +![](../../Days/Images/Day72_CICD14.png) + +Nếu bạn muốn đi sâu hơn và tự động triển khai Jenkins sử dụng tập lệnh shell hãy tham khảo kho lưu trữ này đã được chia sẻ với tôi trên Twitter [mehyedes/nodejs-k8s](https://github.com/mehyedes/nodejs-k8s/blob/main/docs/automated-setup.md) + +### Jenkinsfile + +Bây giờ chúng ta đã có Jenkins được triển khai trong cụm Kubernetes, chúng ta có thể quay lại và suy nghĩ về Jenkinsfile. + +Mọi Jenkinsfile có thể bắt đầu như sau, đầu tiên là nơi bạn xác định các bước của pipeline, ở trường hợp này bạn có Xây dựng > Kiểm thử > Triển khai. Nhưng chúng ta sẽ không làm điều gì khác ngoài sử dụng lệnh `echo` để gọi ra các giai đoạn cụ thể. + +``` + +Jenkinsfile (Declarative Pipeline) + +pipeline { + agent any + + stages { + stage('Build') { + steps { + echo 'Building..' + } + } + stage('Test') { + steps { + echo 'Testing..' + } + } + stage('Deploy') { + steps { + echo 'Deploying....' + } + } + } +} + +``` + +Trong bảng điều khiển Jenkins, chọn "New Item" và đặt tên, tôi sẽ đặt là "echo1" và tôi đề xuất lựa chọn tiếp theo là Pipeline. + +![](../../Days/Images/Day72_CICD15.png) + +Bấm OK và bạn sẽ có các tab (General, Build Triggers, Advanced Project Options and Pipeline), cho một bài kiểm tra đơn giản chúng ta chỉ quan tâm đến Pipeline. Dưới Pipeline bạn có thể thêm tập lệnh, chúng ta có thể sao chép và dán tập lệnh ở trên vào ô trống. + +Như đã đề cập ở trên, Pipeline này sẽ không làm gì nhiều nhưng nó sẽ cho chúng ta thấy các giai đoạn của Xây dựng > Kiểm thử > Triển khai. + +![](../../Days/Images/Day72_CICD16.png) + +Bấm Save, chúng ta bây giờ có thể khởi chạy xây dựng sử dụng lựa chọn build now như ảnh dưới. + +![](../../Days/Images/Day72_CICD17.png) + +Chúng ta cũng sẽ mở một cửa sổ terminal và chạy câu lệnh `kubectl get pods -n jenkins` để xem điều gì xảy ra. + +![](../../Days/Images/Day72_CICD18.png) + +Được rồi, rất đơn giản nhưng chúng ta có thể thấy rằng triển khai và cài đặt Jenkins của chúng ta đã hoạt động chính xác và có thể bắt đầu thấy các khối xây dựng của CI pipeline ở đây. + +Ở phần tiếp theo, chúng ta sẽ xây dựng một Jenkins Pipeline. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 73](day73.md) diff --git a/2022/vi/Days/day73.md b/2022/vi/Days/day73.md new file mode 100644 index 0000000..7a214fa --- /dev/null +++ b/2022/vi/Days/day73.md @@ -0,0 +1,225 @@ +--- +title: '#90DaysOfDevOps - Xây dựng Jenkins pipeline - Day 73' +published: false +description: 90DaysOfDevOps - Xây dựng Jenkins pipeline +tags: 'DevOps, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1048766 +--- + +## Xây dựng Jenkins pipeline + +Ở bài trước, chúng ta đã triển khai Jenkins tới cụm Minikube và đã thiết lập một Jenkins Pipeline cơ bản in ra các giai đoạn của nó. + +Bạn cũng có thể thấy rằng có một số kịch bản mẫu cho chúng ta chạy trong quá trình tạo Jenkins Pipeline. + +![](../../Days/Images/Day73_CICD1.png) + +Kịch bản demo đầu tiên là "Declarative (Kubernetes)" và bạn có thể thấy các giai đoạn bên dưới. + +```Yaml +// Sử dụng cú pháp Declarative để chạy câu lệnh bên trong một container +pipeline { + agent { + kubernetes { + // Rather than inline YAML, in a multibranch Pipeline you could use: yamlFile 'jenkins-pod.yaml' + // Or, to avoid YAML: + // containerTemplate { + // name 'shell' + // image 'ubuntu' + // command 'sleep' + // args 'infinity' + // } + yaml ''' +apiVersion: v1 +kind: Pod +spec: + containers: + - name: shell + image: ubuntu + command: + - sleep + args: + - infinity +''' + // Can also wrap individual steps: + // container('shell') { + // sh 'hostname' + // } + defaultContainer 'shell' + } + } + stages { + stage('Main') { + steps { + sh 'hostname' + } + } + } +} +``` +Bạn có thể thấy kết quả của những gì đã xảy ra khi Pipeline này chạy ở bên dưới. + +![](../../Days/Images/Day73_CICD2.png) + +### Tạo Job + +#### Mục tiêu + +- Tạo một ứng dụng đơn giản và lưu trên kho lưu trữ công khai Github [https://github.com/scriptcamp/kubernetes-kaniko.git](https://github.com/scriptcamp/kubernetes-kaniko.git) + +- Sử dụng Jenkins xây dựng docker Container image và đẩy lên docker hub. (Chúng ta sẽ sử dụng kho lưu riêng tư cho việc này) + +- Để đạt được điều này trong cụm Kubernetes đang chạy hoặc sử dụng Minikube chúng ta cần sử dụng một thứ gọi là [Kaniko](https://github.com/GoogleContainerTools/kaniko#running-kaniko-in-a-kubernetes-cluster) . Công cụ này cũng có thể sử dụng nếu bạn đang sử dụng Jenkins trong một cụm Kubernetes thực sự hoặc bạn đang chạy nó trên một máy chủ sau đó bạn có thể chỉ định một agent cung cấp cho bạn khả năng thực hiện các lệnh xây dựng Docker và tải lên DockerHub. + +Với thông tin trên, chúng ta cũng sẽ triển khai một secret vào Kubernetes với thông tin đăng nhập GitHub của chúng ta. + +```Shell +kubectl create secret docker-registry dockercred \ + --docker-server=https://index.docker.io/v1/ \ + --docker-username= \ + --docker-password=\ + --docker-email= +``` + +Tôi muốn chia sẻ một nguồn tài nguyên tuyệt vời khác từ [DevOpsCube.com](https://devopscube.com/build-docker-image-kubernetes-pod/), giúp bạn tiếp cận nhiều thông tin mà chúng ta sẽ bàn luận ở đây. + +### Thêm thông tin xác thực vào Jenkins + +Tuy nhiên, nếu bạn đang sử dụng một hệ thống Jenkins khác với hệ thống của chúng ta, thì bạn có thể muốn định nghĩa thông tin xác thực trong Jenkins và sau đó có thể tái sử dụng trong các Pipelines và cấu hình của bạn. Chúng ta có thể tham chiếu đến các thông tin xác thực này trong Pipelines bằng cách sử dụng ID mà chúng ta quy định khi tạo chúng. Tôi đã tiến hành và tạo một mục người dùng cho DockerHub và GitHub. + +Đầu tiên chọn "Manage Jenkins" sau đó chọn "Manage Credentials" + +![](../../Days/Images/Day73_CICD3.png) + +Bạn sẽ thấy ở trung tâm của trang là "Stores scoped to Jenkins", hãy bấm chọn Jenkins. + +![](../../Days/Images/Day73_CICD4.png) + +Tiếp theo chọn Global Credentials (Unrestricted) + +![](../../Days/Images/Day73_CICD5.png) + +Sau đó ở phía trên bên trái, lựa chọn Add Credentials. + +![](../../Days/Images/Day73_CICD6.png) + +Điền thông tin chi tiết tài khoản của bạn và chọn OK, nhớ rằng ID sẽ được dùng để tham chiếu khi bạn muốn gọi thông tin xác thực này. Lời khuyên của tôi ở đây là bạn nên sử dụng mã thông báo truy cập cụ thể thay vì mật khẩu. + +![](../../Days/Images/Day73_CICD7.png) + +Đối với GitHub, bạn nên sử dụng [Personal Access Token](https://vzilla.co.uk/vzilla-blog/creating-updating-your-github-personal-access-token) + +Tôi thấy quy trình này khá khó hiểu để tạo các tài khoản này, vì vậy ngay cả khi chúng ta không sử dụng, tôi muốn chia sẻ quy trình vì nó không rõ ràng từ giao diện người dùng. + +### Xây dựng Pipeline + +Chúng ta đã có thông tin xác thực với Dockerhub được triển khai như một secret vào trong cụm Kubernetes, và chúng ta sẽ gọi nó trong giai đoạn triển khai docker đến DockerHub trong pipeline của chúng ta. + +Bạn có thể thấy kịch bản pipeline bên dưới, nó có thể trở thành Jenkinsfile của chúng ta nằm trong kho lưu trữ GitHub, bạn cũng có thể thấy nó được liệt kê trong giai đoạn "Get the project" của pipeline. + +```Yaml +podTemplate(yaml: ''' + apiVersion: v1 + kind: Pod + spec: + containers: + - name: maven + image: maven:3.8.1-jdk-8 + command: + - sleep + args: + - 99d + - name: kaniko + image: gcr.io/kaniko-project/executor:debug + command: + - sleep + args: + - 9999999 + volumeMounts: + - name: kaniko-secret + mountPath: /kaniko/.docker + restartPolicy: Never + volumes: + - name: kaniko-secret + secret: + secretName: dockercred + items: + - key: .dockerconfigjson + path: config.json +''') { + node(POD_LABEL) { + stage('Get the project') { + git url: 'https://github.com/scriptcamp/kubernetes-kaniko.git', branch: 'main' + container('maven') { + stage('Test the project') { + sh ''' + echo pwd + ''' + } + } + } + + stage('Build & Test the Docker Image') { + container('kaniko') { + stage('Deploy to DockerHub') { + sh ''' + /kaniko/executor --context `pwd` --destination michaelcade1/helloworld:latest + ''' + } + } + } + + } +} +``` + +Để bắt đầu dùng bảng điều khiển Jenkins chúng ta cần chọn "New Item" + +![](../../Days/Images/Day73_CICD8.png) + +Chúng ta sau đó sẽ đặt tên cho item, chọn Pipeline và bấm ok. + +![](../../Days/Images/Day73_CICD9.png) + +Chúng ta sẽ không chọn thẻ "general" hoặc "build triggers" nhưng hãy thử nghiệm chúng vì có một số cấu hình đặt lịch và cấu hình thú vị khác có thể hữu ích. + +![](../../Days/Images/Day73_CICD10.png) + +Chúng ta chỉ quan tâm đến thẻ Pipeline ở cuối. + +![](../../Days/Images/Day73_CICD11.png) + +Trong phần Pipeline definition, chúng ta sẽ sao chép và dán kịch bản pipeline mà chúng ta có ở phía trên vào phần Script và bấm lưu. + +![](../../Days/Images/Day73_CICD12.png) + +Tiếp theo, chúng ta sẽ chọn "Build Now" ở bên trái của trang. + +![](../../Days/Images/Day73_CICD13.png) + +Hãy chờ một chút, và bạn sẽ thấy phía dưới status là các giai đoạn mà chúng ta đã định nghĩa phía trên ở kịch bản của chúng ta. + +![](../../Days/Images/Day73_CICD14.png) + +Quan trọng hơn, bây giờ hãy xem thử DockerHub của chúng ta đã có bản build mới hay chưa. + +![](../../Days/Images/Day73_CICD15.png) + +Nhìn chung, việc tìm hiểu sẽ mất chút thời gian nhưng tôi muốn tiếp tục thực hành và làm việc thông qua một kịch bản bất kỳ ai cũng có thể thực hiện thông qua minikube và truy cập tới Github và dockerhub. + +Kho lưu trữ DockerHub mà tôi sử dụng cho bản demo này là kho lưu trữ riêng tư. Nhưng trong phần tới, tôi muốn mở rộng một số giai đoạn này và cho chúng thực hiện một số công việc thay vì chỉ in ra `pwd` và chạy một số kiểm thử và xây dựng. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 74](day74.md) diff --git a/2022/vi/Days/day74.md b/2022/vi/Days/day74.md new file mode 100644 index 0000000..0c7ff4b --- /dev/null +++ b/2022/vi/Days/day74.md @@ -0,0 +1,93 @@ +--- +title: '#90DaysOfDevOps - Hello World - Jenkinsfile App Pipeline - Day 74' +published: false +description: 90DaysOfDevOps - Hello World - Jenkinsfile App Pipeline +tags: 'devops, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1048744 +--- + +## Hello World - Jenkinsfile App Pipeline + +Ở bài trước, chúng ta đã xây một Pipeline đơn giản trong Jenkins có thể đẩy Docker images từ dockerfile trong một kho lưu trữ Github công khai tới kho lưu trữ Dockerhub riêng tư. + +Trong bài này, chúng ta muốn bước một bước xa hơn và đạt được các mục tiêu sau với ứng dụng đơn giản của chúng ta. +### Mục tiêu + +- Dockerfile (Hello World) +- Jenkinsfile +- Jenkins Pipeline để kích hoạt khi Kho lưu trữ GitHub được cập nhật +- Sử dụng Kho lưu trữ GitHub làm nguồn. +- Chạy - Sao chép/Lấy Kho lưu trữ, Xây dựng, Kiểm tra, Triển khai Các giai đoạn +- Triển khai lên DockerHub với số phiên bản tăng dần +- Mục tiêu mở rộng để triển khai lên Cụm Kubernetes của chúng ta (Điều này sẽ liên quan đến công việc và kho manifest khác sử dụng thông tin xác thực GitHub) + +### Bước một + +Chúng ta có [GitHub repository](https://github.com/MichaelCade/Jenkins-HelloWorld) đang chứa Dockerfile và tệp index.html +![](../../Days/Images/Day74_CICD1.png) + +Với nội dung trên, đây là những gì chúng ta đang sử dụng làm nguồn trong Pipeline của mình, giờ đây chúng ta cũng muốn thêm kịch bản Jenkins Pipeline đó vào kho GitHub của chúng ta. + +![](../../Days/Images/Day74_CICD2.png) + +Hãy quay trở lại bảng điều khiển Jenkins, chúng ta sẽ tạo một pipeline mới nhưng thay vì sử kịch bản của chúng ta, chúng ta sẽ sử dụng "Pipeline script from SCM" và các tùy chọn cấu hình dưới đây. + +Để tham khảo, chúng ta sẽ sử dụng `https://github.com/MichaelCade/Jenkins-HelloWorld.git` làm URL của kho lưu trữ. + +![](../../Days/Images/Day74_CICD3.png) + +Ở bước này, chúng ta có thể nhấn "Lưu" và "Áp dụng", sau đó chúng ta sẽ có thể chạy thủ công Pipeline của mình để xây dựng Docker images mới và tải lên kho DockerHub của chúng ta. +Tuy nhiên, tôi cũng muốn đảm bảo rằng chúng ta đã đặt lịch mỗi khi kho lưu trữ hoặc mã nguồn thay đổi sẽ kích hoạt một tiến trình xây dựng. Chúng ta có thể sử dụng webhooks hoặc đồng bộ kéo định kỳ. + +Điều này đáng để quan tâm vì nếu bạn đang sử dụng các tài nguyên đám mây mất phí để duy trì pipeline và bạn có nhiều thay đổi tới kho lưu trữ mã nguồn bạn sẽ chịu phát sinh nhiều chi phí. Chúng ta biết rằng đây chỉ là một môi trường chạy thử đó là lí do tôi đang sử dụng lựa chọn "poll scm". (Ngoài ra, tôi tin rằng khi sử dụng minikube tôi sẽ thiếu đi chức năng webhook) + +![](../../Days/Images/Day74_CICD4.png) + +Một thứ tôi đã thay đổi trong bài trước đó là tôi muốn tải ảnh tới một kho lưu trữ công cộng đó là michaelcade1\90DaysOfDevOps, Jenkinsfile của tôi đã có thay đổi này từ trước. Và từ bài trước, tôi đã gỡ toàn bộ các ảnh container demo. + +![](../../Days/Images/Day74_CICD5.png) + +Quay trở lại bước trước, chúng ta đã tạo Pipelie của chúng ta và như đã được trình bày trước đó chúng ta đã thêm cấu hình của mình. + +![](../../Days/Images/Day74_CICD6.png) + +Ở giai đoạn này, Pipeline của chúng ta chưa hề chạy và giao diện giai đoạn sẽ trông như sau. + +![](../../Days/Images/Day74_CICD7.png) + +Bây giờ hãy bấm nút "Build Now" và thẻ stage view của chúng ta sẽ hiển thị các giai đọan. + +![](../../Days/Images/Day74_CICD8.png) + +Nếu chúng ta sau đó đi đến kho DockerHub của mình, chúng ta sẽ thấy có 2 Docker images mới. Chúng ta nên có một Build ID là 1 và latest vì đối với mỗi lần xây dựng mà chúng ta tạo dựa trên "Upload to DockerHub" chúng ta gửi một phiên bản bằng biến môi trường Jenkins Build_ID và chúng ta cũng phát hành một phiên bản "latest". + +![](../../Days/Images/Day74_CICD9.png) + +Bây giờ hãy tạo và cập nhật tệp index.html ở trong kho lưu trữ Github như bên dưới, tôi sẽ để bạn tìm hiểu phiên bản 1 của tệp index.html có những gì + +![](../../Days/Images/Day74_CICD10.png) + +Nếu chúng ta quay lại Jenkins và chọn "Build Now" một lần nữa, chúng ta sẽ thấy build #2 có thành công hay không. + +![](../../Days/Images/Day74_CICD11.png) + +Chuyển sang DockerHub, chúng ta có thể thấy chúng ta đã có phiên bản đã đánh dấu 2 và nhãn "latest". + +![](../../Days/Images/Day74_CICD12.png) + +Đáng lưu ý ở đây là tôi đã thêm vào cụm Kubernetes của mình một secret cho phép tôi truy cập và xác thực để đẩy các bản xây Docker của mình vào DockerHub. Nếu bạn đang theo dõi, bạn nên lặp lại quy trình này cho tài khoản của bạn và cũng thực hiện một thay đổi trong Jenkinsfile liên quan đến kho lưu trữ và tài khoản của tôi. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 75](day75.md) diff --git a/2022/vi/Days/day75.md b/2022/vi/Days/day75.md new file mode 100644 index 0000000..f7f3c21 --- /dev/null +++ b/2022/vi/Days/day75.md @@ -0,0 +1,187 @@ +--- +title: '#90DaysOfDevOps - Tổng quan về GitHub Actions - Day 75' +published: false +description: 90DaysOfDevOps - Tổng quan về GitHub Actions +tags: 'devops, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1049070 +--- + +## Tổng quan về GitHub Actions + +Ở bài này, tôi muốn tiếp tục và xem xét có thể là ở một cách tiếp cận khác so với những gì chúng ta đã học ở các bài trước. Github Actions là điều chúng ta sẽ tập trung ở bài này. + +Github Actions là một nền tảng CI/CD cho phép chúng ta xây dựng, kiểm thử và triển khai giữa các tác vụ trong pipeline. Nó mang trong mình khái niệm về các workflow để xây dựng và kiểm thử trên một kho lưu trữ GitHub. Bạn cũng có thể sử dụng GitHub Actions để điều hướng các luồng công việc khác dựa trên các sự kiện diễn ra trong kho lưu trữ của bạn. + +### Workflows + +Nhìn chung, trong Github Actions, tác vụ được gọi là **Workflow**: + +- Một **workflow** là tiến trình tự động có thể cấu hình được. +- Được định nghĩa dưới dạng tệp YAML. +- Chứa và chạy một hoặc nhiều **jobs** +- Được kích hoạt bởi một **event** trong kho lưu trữ hoặc có thể chạy thủ công +- Có thể có nhiều workflows trên một kho lưu trữ +- Một **workflow** sẽ chứa một **job** và sau đó là các **step** để hoàn thành **job** +- Trong **workflow** chúng ta cũng có một **runner** mà **workflow** chạy trên đó. + +Ví dụ, bạn có thể có một **workflow** để xây dựng và kiểm thử các pull requests, một **workflow** khác để triển khai ứng dụng mỗi khi một bản release được tạo, và một **workflow** để đánh nhãn mỗi khi ai đó mở một issue mới. + +### Events + +Các Event là sự kiện cụ thể trong một kho lưu trữ qua đó kích hoạt workflow chạy. + +### Jobs + +Một job bao gồm các step trong một workflow được thực thi trên một runner + +### Steps + +Mỗi step trong job có thể là một đoạn mã shell được thực thi hoặc một hành động. Các step được thực thi theo trình tự và chúng phụ thuộc vào nhau. + +### Actions + +Là một ứng dụng tùy chỉnh có thể lặp lại được sử dụng cho các tác vụ thường xuyên lặp lại. + +### Runners + +Một runner là một máy chủ thực thi workflow, mỗi runner chạy một job duy nhất tại một thời điểm. GitHub Actions cung cấp khả năng chạy các runner trên hệ điều hành Ubuntu Linux, Microsoft Windows và macOS. Bạn cũng có thể tự lưu trữ runner của mình trên một hệ điều hành hoặc phần cứng cụ thể. + +Dưới đây, bạn có thể thấy cách mọi thứ hoạt động, sự kiện kích hoạt workflow của chúng ta > workflow của chúng ta bao gồm hai job > trong job, chúng ta có các step và sau đó là các action. + +![](../../Days/Images/Day75_CICD1.png) + +### YAML + +Trước khi chúng ta bắt đầu với một trường hợp sử dụng thực tế, hãy nhìn nhanh vào hình ảnh trên dưới dạng một tệp YAML minh họa. + +Tôi đã thêm dấu # để ghi chú vị trí chúng ta có thể tìm thấy các thành phần của YAML workflow. + +```Yaml +#Workflow +name: 90DaysOfDevOps +#Event +on: [push] +#Jobs +jobs: + check-bats-version: + #Runners + runs-on: ubuntu-latest + #Steps + steps: + #Actions + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' + - run: npm install -g bats + - run: bats -v +``` + +### Thực hành với GitHub Actions + +Tôi nghĩ rằng có rất nhiều tùy chọn khi nói đến GitHub Actions, nó sẽ đáp ứng nhu cầu CI/CD của bạn khi đến giai đoạn Xây dựng, Kiểm tra và Triển khai mã nguồn và các bước tiếp theo sau đó. + +Tôi có thể thấy nhiều tùy chọn và các tác vụ tự động khác mà chúng ta có thể sử dụng GitHub Actions cho chúng. + +### Sử dụng GitHub Actions để Kiểm tra mã nguồn của bạn + +Một trong những tùy chọn là đảm bảo mã nguồn của bạn sạch sẽ và gọn gàng trong kho lưu trữ của bạn. Đây sẽ là ví dụ thực hiện đầu tiên của chúng ta. + +Tôi sẽ sử dụng một đoạn mã mẫu được liên kết trong một trong những tài nguyên của bài này, chúng ta sẽ sử dụng `GitHub/super-linter` để kiểm tra mã nguồn của mình. + +```Yaml +name: Super-Linter + +on: push + +jobs: + super-lint: + name: Lint code base + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Run Super-Linter + uses: github/super-linter@v3 + env: + DEFAULT_BRANCH: main + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +**github/super-linter** +Bạn có thể thấy phía trên rằng đối với một trong các bước của chúng tôi, chúng tôi có một action được gọi là `GitHub/super-linter` và điều này đang tham chiếu đến một step đã được cộng đồng viết trước đó. Bạn có thể tìm hiểu thêm về nó tại đây [Super-Linter](https://github.com/github/super-linter) + +"Kho lưu trữ này dành cho GitHub Action để chạy Super-Linter. Đây là một sự kết hợp đơn giản của các trình kiểm tra mã nguồn khác nhau, được viết bằng bash, để giúp xác minh mã nguồn của bạn." + +Cũng trong đoạn mã ở trên có đề cập đến GITHUB_TOKEN, nên tôi muốn tìm hiểu tại sao nó lại cần thiết và dùng để làm gì. + +"GHI CHÚ: Nếu bạn truyền biến môi trường `GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}` trong workflow của bạn, thì GitHub Super-Linter sẽ đánh dấu trạng thái của mỗi lần chạy linter trong phần Kiểm tra của pull request. Nếu không, bạn chỉ sẽ thấy trạng thái tổng quan của toàn bộ quá trình chạy. **Không cần phải thiết lập GitHub Secret vì nó được cài đặt tự động bởi GitHub, chỉ cần truyền nó cho action.**" + +Đoạn in đậm trên là điều quan trọng cần lưu ý ở giai đoạn này. Chúng ta đang sử dụng nó nhưng không cần phải thiết lập bất kỳ biến môi trường nào trong kho lưu trữ của chúng ta. + +Chúng ta sẽ sử dụng kho lưu trữ mà chúng tôi đã sử dụng trong bài thực hành Jenkins để kiểm tra.[Jenkins-HelloWorld](https://github.com/MichaelCade/Jenkins-HelloWorld) + +Dưới đây là kho lưu trữ của chúng ta sau khi chúng ta kết thúc trong các buổi thực hành về Jenkins. + +![](../../Days/Images/Day75_CICD2.png) + +Để tận dụng, chúng ta có thể sử dụng tab Actions phía trên để chọn từ thư viện, điều mà tôi sẽ giải thích kỹ sau, hoặc chúng ta có thể tạo tệp của riêng mình bằng cách sử dụng mã super-linter ở trên. Để tạo một tệp của riêng mình, bạn phải tạo một tệp mới trong kho lưu trữ của bạn tại vị trí chính xác này: `.github/workflows/workflow_name` đảm bảo workflow_name là một cái gì đó hữu ích để nhận diện, trong đây, chúng ta có thể có nhiều workflow khác nhau thực hiện các job và nhiệm vụ khác nhau đối với kho lưu trữ của chúng ta. + +Chúng ta sẽ tạo `.github/workflows/super-linter.yml.` + +![](../../Days/Images/Day75_CICD3.png) + +Sau đó, chúng ta có thể dán mã nguồn của mình và commit mã vào kho lưu trữ của mình. Sau đó, nếu chúng ta chuyển đến tab Actions, bây giờ chúng ta sẽ thấy Super-Linter workflow của mình được liệt kê dưới đây, + +![](../../Days/Images/Day75_CICD4.png) + +Chúng ta đã xác định trong mã của mình rằng workflow này sẽ chạy khi chúng ta đẩy bất kỳ thay đổi nào lên kho lưu trữ của mình, vì vậy khi đẩy super-linter.yml lên kho lưu trữ của mình, chúng ta đã kích hoạt worflow. + +![](../../Days/Images/Day75_CICD5.png) + +Như bạn có thể thấy từ trên, chúng ta có một số lỗi, có thể là do khả năng "hack" của tôi so với khả năng viết mã của tôi. + +Dù đó không phải là mã của tôi, ít nhất là chưa phải, khi chạy điều này và nhận được một lỗi, tôi đã tìm thấy [issue](https://github.com/github/super-linter/issues/2255) + +Lần thứ hai, tôi đã thay đổi phiên bản Super-Linter từ phiên bản 3 lên 4 và đã chạy lại tác vụ. + +![](../../Days/Images/Day75_CICD6.png) + + +Như dự đoán, việc "hack" mã của tôi đã gây ra một số vấn đề và bạn có thể thấy chúng ở đây trong [workflow](https://github.com/MichaelCade/Jenkins-HelloWorld/runs/5600278515?check_suite_focus=true). + +Tôi muốn kể từ bây giờ sẽ hiển trị trên kho lưu trữ của chúng ta khi có điều gì đó trong workflow đã thất bại hoặc báo lỗi lại. + +![](../../Days/Images/Day75_CICD7.png) + +Bây giờ nếu chúng ta giải quyết lỗi trong commit trên với mã của tôi và đẩy lại các thay đổi, workflow của chúng ta sẽ chạy lại (bạn có thể thấy từ hình ảnh rằng nó mất một thời gian để giải quyết các "lỗi" của chúng ta). Xóa một tệp có thể không được khuyến nghị nhưng đó là một cách rất nhanh chóng để thể hiện vấn đề được giải quyết. + +![](../../Days/Images/Day75_CICD8.png) + +Nếu bạn nhấp vào nút **new workflow** được đánh dấu ở trên, điều này sẽ mở ra cửa sổ cho một loạt lớn các action. Một điều bạn có thể đã nhận thấy trong suốt thử thách này là chúng tôi không muốn phải tạo lại mọi thứ, chúng tôi muốn đứng trên vai những người khổng lồ và chia sẻ mã nguồn, tự động hóa và kỹ năng của mình rộng rãi để làm cuộc sống dễ dàng hơn. + +![](../../Days/Images/Day75_CICD9.png) + +Oh, tôi quên không cho bạn thấy dấu tích màu xanh trên kho lưu trữ khi workflow của chúng ta thành công. + +![](../../Days/Images/Day75_CICD10.png) + +Tôi nghĩ rằng những điều này đã bao quát mọi thứ từ quan điểm cơ bản về GitHub Actions, nhưng nếu bạn giống như tôi, bạn có thể đang nhìn thấy cách GitHub Actions có thể được sử dụng để tự động hóa nhiều nhiệm vụ khác. + +Tiếp theo, chúng ta sẽ nói về một lĩnh vực khác của Continuous Deployment, chúng ta sẽ tìm hiểu về ArgoCD để triển khai ứng dụng của chúng ta tới môi trường của mình. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 76](day76.md) diff --git a/2022/vi/Days/day76.md b/2022/vi/Days/day76.md new file mode 100644 index 0000000..c29ff5d --- /dev/null +++ b/2022/vi/Days/day76.md @@ -0,0 +1,84 @@ +--- +title: '#90DaysOfDevOps - Tổng quan về ArgoCD - Day 76' +published: false +description: 90DaysOfDevOps - Tổng quan về ArgoCD +tags: 'devops, 90daysofdevops, learning' +cover_image: null +canonical_url: null +id: 1048809 +--- + +## Tổng quan về ArgoCD + +“Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes” + +Việc kiểm soát phiên bản là điều quan trọng ở đây. Bạn có từng thay đổi môi trường của mình một cách nhanh chóng mà không nhớ được điều đó, và bởi vì mọi thứ vẫn hoạt động bình thường, bạn tiếp tục thực hiện như bình thường chứ? Bạn có từng thực hiện một thay đổi và làm hỏng mọi thứ hoặc một phần của mọi thứ không? Có thể bạn đã biết rằng bạn đã thực hiện thay đổi và bạn có thể nhanh chóng quay lại trạng thái trước, bao gồm cả các tệp lệnh không tốt hoặc việc gõ sai chính tả. Việc thực hiện những điều này trên quy mô lớn có thể là không phải do bạn hoặc có thể không tìm thấy nguyên nhân ngay lập tức và khi đó doanh nghiệp sẽ gặp khó khăn. Do đó, việc kiểm soát phiên bản là vô cùng quan trọng. Không chỉ vậy mà "Định nghĩa ứng dụng, cấu hình, và môi trường nên tuân theo nguyên tắc khai báo và kiểm soát phiên bản." Ngoài ra (điều này được đề cập từ ArgoCD), đề cập rằng "Triển khai ứng dụng và quản lý vòng đời của ứng dụng nên được tự động hóa, có thể kiểm tra và dễ hiểu." + +Từ lĩnh vực Quản trị nhưng đã nghiên cứu rất nhiều về Cơ sở hạ tầng dưới dạng mã, đây là bước tiếp theo để đảm bảo rằng tất cả những điều tốt lành đó được chăm sóc thông qua các luồng công việc triển khai / phát hành liên tục.". + + +[ArgoCD là gì](https://argo-cd.readthedocs.io/en/stable/) + +### Triển khai ArgoCD + +Chúng ta sẽ sử dụng Kubernetes cluster với minikube cục bộ cho việc triển khai này. + +```Shell +kubectl create namespace argocd +kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml +``` + +![](../../Days/Images/Day76_CICD1.png) + +Đảm bảo tất cả pods của ArgoCD đang hoạt động với lệnh `kubectl get pods -n argocd` + +![](../../Days/Images/Day76_CICD2.png) + +Cùng với đó, hãy kiểm tra mọi thứ chúng ta đã triển khai trong namespace `kubectl get all -n argocd` + +![](../../Days/Images/Day76_CICD3.png) + +Khi mọi thử ở trên đều ổn, chúng ta có thể cân nhắc truy cập nó qua port foward. Sử dụng lệnh `kubectl port-forward svc/argocd-server -n argocd 8080:443`. Hãy thực hiện điều này ở một cửa sổ terminal mới. + +Sau đó mở một trình duyệt và truy cập `https://localhost:8080` + +![](../../Days/Images/Day76_CICD4.png) + +Để đăng nhập bạn cần một username của admin và sau đó lấy secret đã được tạo để làm password, sử dụng câu lệnh `kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo` + +![](../../Days/Images/Day76_CICD5.png) + +Khi đăng nhập thành công bạn sẽ thấy giao diện CD đang trống. + +![](../../Days/Images/Day76_CICD6.png) + +### Triển khai ứng dụng + +Bây giờ chúng ta đã có ArgoCD hoạt động và có thể bắt đầu sử dụng nó để triển khai ứng dụng từ kho lưu trữ Git cũng như Helm. + +Ứng dụng tôi muốn triển khai ở đây mà Pac-Man, một tựa game nổi tiếng và là thứ tôi sử dụng để chạy thử rất nhiều khi nói về quản lý dữ liệu, đây sẽ không phải là lần cuối chúng ta thấy Pac-Man. + +Bạn có thể tìm thấy kho lưu trữ [Pac-Man](https://github.com/MichaelCade/pacman-tanzu.git) ở đây. + +Thay vì đi qua từng bước sử dụng các screenshot, tôi nghĩ sẽ dễ dàng hơn bằng việc tạo một video hướng dẫn các bước cần thiết cho việc triển khai ứng dụng này. + +[ArgoCD Demo - 90DaysOfDevOps](https://www.youtube.com/watch?v=w6J413_j0hA) + +Ghi chú - Trong video, có một dịch vụ không bao giờ có một dịch vụ không bao giờ có status là healthy. Điều này xảy ra vì loại LoadBalancer được đặt cho dịch vụ Pacman đang có status là pending, trong Minikube chúng ta không có cấu hình load balancer. Nếu bạn muốn kiểm tra điều này, bạn có thể thay đổi YAML của dịch vụ thành ClusterIP và sử dụng port fowarding để chơi trò chơi. + +Chúng ta kết thúc phần về Pipelines CI/CD tại đây. Tôi cảm thấy hiện tại khái niệm này đang được tập trung và bạn cũng sẽ nghe rất nhiều các thuật ngữ liên quan đến GitOps cũng như các phương pháp được sử dụng trong CICD trong công việc hàng ngày. + +Phần tiếp theo chúng ta sẽ chuyển sang khía cạnh mới là Giám sát, một khái niệm hoặc lĩnh vực không mới nhưng ngày càng quan trọng hơn khi chúng ta muốn kiểm soát tốt hiệu suất của môi trường của mình. + +## Tài liệu tham khảo + +- [Jenkins là một cách để xây dựng, kiểm thử, triển khai](https://www.youtube.com/watch?v=_MXtbjwsz3A) +- [Jenkins.io](https://www.jenkins.io/) +- [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) +- [Hướng dẫn ArgoCD cho người mới bắt đầu](https://www.youtube.com/watch?v=MeU5_k9ssrs) +- [Jenkins là gì](https://www.youtube.com/watch?v=LFDrDnKPOTg) +- [Hướng dẫn Jenkins đầy đủ](https://www.youtube.com/watch?v=nCKxl7Q_20I&t=3s) +- [GitHub Actions](https://www.youtube.com/watch?v=R8_veQiYBjI) +- [GitHub Actions CI/CD](https://www.youtube.com/watch?v=mFFXuXjVgkU) + +Hẹn gặp lại vào [Ngày 77](day77.md) \ No newline at end of file diff --git a/2023/day77.md b/2023/day77.md index 0df8ba2..073f8db 100644 --- a/2023/day77.md +++ b/2023/day77.md @@ -9,7 +9,7 @@ These are small subset of challenges when it comes to running and managing appli Enter a Service Mesh. A Service Mesh is an application network layer that handles service-to-service communication, by providing a layer for granular traffic control, AuthN, AuthZ, and observability. -### What are the challenges a Service Mesh aims to solve?m +### What are the challenges a Service Mesh aims to solve? 1. Unreliable and changing networks that are complex, while having to adapt while your microservices scale 2. Ensuring a near zero-trust like environment where, RBAC, AuthZ and AuthN are critical. 3. Ensuring a data-loss prevention approach using encryption and traffic filtration techniques diff --git a/2023/ko/days/day14.md b/2023/ko/days/day14.md new file mode 100644 index 0000000..846d3da --- /dev/null +++ b/2023/ko/days/day14.md @@ -0,0 +1,279 @@ +# 컨테이너 이미지 스캐닝 + +컨테이너 이미지는 이미지 매니페스트, 파일 시스템 및 이미지 구성으로 구성됩니다. [1](https://opencontainers.org/about/overview/) + +예를 들어, Java 애플리케이션용 컨테이너 이미지의 파일 시스템에는 Linux 파일 시스템, JVM 및 애플리케이션을 나타내는 JAR/WAR 파일이 있습니다. + +컨테이너를 사용하는 경우 CI/CD 파이프라인의 중요한 부분은 이러한 컨테이너에 알려진 취약성이 있는지 스캐닝하는 프로세스여야 합니다. +이를 통해 컨테이너 내부에 있는 취약성의 수에 대한 귀중한 정보를 얻을 수 있으며, 취약한 애플리케이션을 운영 환경에 배포하고 이러한 취약성으로 인해 해킹되는 것을 방지할 수 있습니다. + +2021년 말 발견된 [Log4Shell](https://en.wikipedia.org/wiki/Log4Shell) 취약성을 예로 들어보겠습니다. +너무 자세히 설명하지 않아도 응용프로그램에 이 취약성이 있다는 것은 공격자가 서버에서 임의 코드를 실행할 수 있다는 것을 의미합니다. +이 취약성은 가장 인기 있는 Java 라이브러리 중 하나인 [Log4j](https://logging.apache.org/log4j/2.x/) 에 있기 때문에 더욱 악화되었습니다. +꽤나 나쁘네요! + +그렇다면 우리가 취약한지 어떻게 알 수 있을까요? + +정답은 **Image Scanning**입니다. + +이미지 스캐닝 프로세스는 컨테이너 내부를 살펴보고, 설치된 패키지 목록(리눅스 패키지일 수도 있지만 자바, Go, 자바스크립트 패키지 등일 수도 있음)을 가져오고, 패키지 목록을 각 패키지에 대해 알려진 취약성 데이터베이스와 교차 참조하고, 최종적으로 지정된 컨테이너 이미지에 대한 취약성 목록을 생성하는 것으로 구성됩니다. + +컴퓨터 로컬이나 CI/CD 파이프라인에서 컨테이너 이미지를 바로 설치하고 스캔을 시작할 수 있는 오픈 소스 및 독점 이미지 스캐너가 많이 있습니다. +가장 인기 있는 두 가지는 [Triby](https://github.com/aquasecurity/trivy) 와 [Grype](https://github.com/anchore/grype) 입니다. +일부 독점 제품은 [Snyk](https://docs.snyk.io/products/snyk-container/snyk-cli-for-container-security) (계정 필요, Free tier 있음) 및 [VMware Carbon Black](https://carbonblack.vmware.com/resource/carbon-black-cloud-container-security-faq#overview) (계정 필요, Free tier 없음)입니다. + +컨테이너 이미지를 스캔하는 것은 다음 중 하나를 설치하고 실행하는 것처럼 간단합니다: + +```console +$ grype ubuntu:latest + ✔ Vulnerability DB [updated] + ✔ Pulled image + ✔ Loaded image + ✔ Parsed image + ✔ Cataloged packages [101 packages] + ✔ Scanned image [16 vulnerabilities] +NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY +bash 5.1-6ubuntu1 deb CVE-2022-3715 Medium +coreutils 8.32-4.1ubuntu1 deb CVE-2016-2781 Low +gpgv 2.2.27-3ubuntu2.1 deb CVE-2022-3219 Low +libc-bin 2.35-0ubuntu3.1 deb CVE-2016-20013 Negligible +libc6 2.35-0ubuntu3.1 deb CVE-2016-20013 Negligible +libncurses6 6.3-2 deb CVE-2022-29458 Negligible +libncursesw6 6.3-2 deb CVE-2022-29458 Negligible +libpcre3 2:8.39-13ubuntu0.22.04.1 deb CVE-2017-11164 Negligible +libsystemd0 249.11-0ubuntu3.6 deb CVE-2022-3821 Medium +libtinfo6 6.3-2 deb CVE-2022-29458 Negligible +libudev1 249.11-0ubuntu3.6 deb CVE-2022-3821 Medium +login 1:4.8.1-2ubuntu2 deb CVE-2013-4235 Low +ncurses-base 6.3-2 deb CVE-2022-29458 Negligible +ncurses-bin 6.3-2 deb CVE-2022-29458 Negligible +passwd 1:4.8.1-2ubuntu2 deb CVE-2013-4235 Low +zlib1g 1:1.2.11.dfsg-2ubuntu9.2 deb CVE-2022-42800 Medium +``` + +이 명령을 사용하여 `ubuntu:latest` 컨테이너 이미지를 스캔한 결과 16개의 취약점이 있는 것으로 나타났습니다. + +각 취약성에는 [CVSS](https://nvd.nist.gov/vuln-metrics/cvss) 점수에 따라 심각도가 있습니다. +심각도는 '낮음'부터 '심각함'까지 다양합니다. + +16개의 취약점은 많아 보이지만, 어느 것도 '크리티컬(Critical)'한 심각성을 가지고 있지 않습니다. + +또한 결과 테이블의 'FIXED-IN' 열이 비어 있습니다. +이는 해당 패키지의 최신 버전에서 이 취약성이 수정되지 않음을 의미합니다. + +`ubuntu:latest`는 Ubuntu의 공식 컨테이너 이미지의 최신 버전이기 때문에 이는 예상됩니다. +일반적으로 이러한 이미지는 정기적으로 업데이트되므로 이러한 이미지에 많은 취약점이 있을 것으로 예상해서는 안 됩니다.(적어도 사용 가능한 수정 사항이 있는 이미지는 아님). + +오래된 이미지, 임의의 이미지, 대기업에서 지원하지 않는 이미지 또는 자신이 관리하지 않는 이미지의 경우에는 그렇지 않을 수 있습니다. + +예를 들어, Docker Hub의 `springio` 조직에서 임의 이미지 2년 된 이미지를 스캔하면 훨씬 더 많은 취약점이 잠재해 있음을 알 수 있습니다: + +```console +$ grype springio/petclinic:latest + ✔ Vulnerability DB [no update available] + ✔ Pulled image + ✔ Loaded image + ✔ Parsed image + ✔ Cataloged packages [213 packages] + ✔ Scanned image [167 vulnerabilities] +NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY +bash 4.4.18-2ubuntu1.2 deb CVE-2022-3715 Medium +bash 4.4.18-2ubuntu1.2 4.4.18-2ubuntu1.3 deb CVE-2019-18276 Low +coreutils 8.28-1ubuntu1 deb CVE-2016-2781 Low +dpkg 1.19.0.5ubuntu2.3 1.19.0.5ubuntu2.4 deb CVE-2022-1664 Medium +e2fsprogs 1.44.1-1ubuntu1.3 1.44.1-1ubuntu1.4 deb CVE-2022-1304 Medium +gcc-8-base 8.4.0-1ubuntu1~18.04 deb CVE-2020-13844 Medium +gpgv 2.2.4-1ubuntu1.4 2.2.4-1ubuntu1.6 deb CVE-2022-34903 Medium +gpgv 2.2.4-1ubuntu1.4 2.2.4-1ubuntu1.5 deb CVE-2019-13050 Low +gpgv 2.2.4-1ubuntu1.4 deb CVE-2022-3219 Low +gzip 1.6-5ubuntu1 1.6-5ubuntu1.2 deb CVE-2022-1271 Medium +h2 1.4.200 2.0.202 java-archive GHSA-7rpj-hg47-cx62 High +h2 1.4.200 2.0.206 java-archive GHSA-h376-j262-vhq6 Critical +h2 1.4.200 java-archive CVE-2021-23463 Critical +h2 1.4.200 java-archive CVE-2021-42392 Critical +h2 1.4.200 java-archive CVE-2022-23221 Critical +h2 1.4.200 2.1.210 java-archive GHSA-45hx-wfhj-473x Critical +jackson-databind 2.11.4 2.12.7.1 java-archive GHSA-jjjh-jjxp-wpff High +jackson-databind 2.11.4 2.12.7.1 java-archive GHSA-rgv9-q543-rqg4 High +jackson-databind 2.11.4 java-archive CVE-2022-42004 High +jackson-databind 2.11.4 java-archive CVE-2020-36518 High +jackson-databind 2.11.4 java-archive CVE-2022-42003 High +jackson-databind 2.11.4 2.12.6.1 java-archive GHSA-57j2-w4cx-62h2 High +jquery 2.2.4 java-archive CVE-2019-11358 Medium +jquery 2.2.4 java-archive CVE-2020-11022 Medium +jquery 2.2.4 java-archive CVE-2015-9251 Medium +jquery 2.2.4 java-archive CVE-2020-11023 Medium +jquery 2.2.4 java-archive CVE-2007-2379 Medium +jquery-ui 1.11.4 java-archive CVE-2021-41184 Medium +jquery-ui 1.11.4 java-archive CVE-2016-7103 Medium +jquery-ui 1.11.4 java-archive CVE-2021-41182 Medium +jquery-ui 1.11.4 java-archive CVE-2021-41183 Medium +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-29562 Low +libc-bin 2.27-3ubuntu1.4 deb CVE-2016-20013 Negligible +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-6096 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-27618 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23218 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2016-10228 Negligible +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2019-25013 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3326 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3999 Medium +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23219 Low +libc-bin 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-35942 Low +libc-bin 2.27-3ubuntu1.4 deb CVE-2009-5155 Negligible +libc-bin 2.27-3ubuntu1.4 deb CVE-2015-8985 Negligible +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3999 Medium +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2016-10228 Negligible +libc6 2.27-3ubuntu1.4 deb CVE-2009-5155 Negligible +libc6 2.27-3ubuntu1.4 deb CVE-2016-20013 Negligible +libc6 2.27-3ubuntu1.4 deb CVE-2015-8985 Negligible +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3326 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-35942 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-27618 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-6096 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-29562 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23218 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23219 Low +libc6 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2019-25013 Low +libcom-err2 1.44.1-1ubuntu1.3 1.44.1-1ubuntu1.4 deb CVE-2022-1304 Medium +libext2fs2 1.44.1-1ubuntu1.3 1.44.1-1ubuntu1.4 deb CVE-2022-1304 Medium +libgcc1 1:8.4.0-1ubuntu1~18.04 deb CVE-2020-13844 Medium +libgcrypt20 1.8.1-4ubuntu1.2 1.8.1-4ubuntu1.3 deb CVE-2021-40528 Medium +libgcrypt20 1.8.1-4ubuntu1.2 1.8.1-4ubuntu1.3 deb CVE-2021-33560 Low +libgmp10 2:6.1.2+dfsg-2 2:6.1.2+dfsg-2ubuntu0.1 deb CVE-2021-43618 Low +libgnutls30 3.5.18-1ubuntu1.4 3.5.18-1ubuntu1.6 deb CVE-2021-4209 Low +libgnutls30 3.5.18-1ubuntu1.4 deb CVE-2018-16868 Low +libgnutls30 3.5.18-1ubuntu1.4 3.5.18-1ubuntu1.6 deb CVE-2022-2509 Medium +libhogweed4 3.4-1ubuntu0.1 3.4.1-0ubuntu0.18.04.1 deb CVE-2021-3580 Medium +libhogweed4 3.4-1ubuntu0.1 3.4.1-0ubuntu0.18.04.1 deb CVE-2018-16869 Low +liblz4-1 0.0~r131-2ubuntu3 0.0~r131-2ubuntu3.1 deb CVE-2021-3520 Medium +liblzma5 5.2.2-1.3 5.2.2-1.3ubuntu0.1 deb CVE-2022-1271 Medium +libncurses5 6.1-1ubuntu1.18.04 deb CVE-2019-17594 Negligible +libncurses5 6.1-1ubuntu1.18.04 deb CVE-2021-39537 Negligible +libncurses5 6.1-1ubuntu1.18.04 deb CVE-2022-29458 Negligible +libncurses5 6.1-1ubuntu1.18.04 deb CVE-2019-17595 Negligible +libncursesw5 6.1-1ubuntu1.18.04 deb CVE-2019-17595 Negligible +libncursesw5 6.1-1ubuntu1.18.04 deb CVE-2021-39537 Negligible +libncursesw5 6.1-1ubuntu1.18.04 deb CVE-2022-29458 Negligible +libncursesw5 6.1-1ubuntu1.18.04 deb CVE-2019-17594 Negligible +libnettle6 3.4-1ubuntu0.1 3.4.1-0ubuntu0.18.04.1 deb CVE-2021-3580 Medium +libnettle6 3.4-1ubuntu0.1 3.4.1-0ubuntu0.18.04.1 deb CVE-2018-16869 Low +libpcre3 2:8.39-9 deb CVE-2017-11164 Negligible +libpcre3 2:8.39-9 2:8.39-9ubuntu0.1 deb CVE-2020-14155 Negligible +libpcre3 2:8.39-9 2:8.39-9ubuntu0.1 deb CVE-2019-20838 Low +libsepol1 2.7-1 2.7-1ubuntu0.1 deb CVE-2021-36086 Low +libsepol1 2.7-1 2.7-1ubuntu0.1 deb CVE-2021-36085 Low +libsepol1 2.7-1 2.7-1ubuntu0.1 deb CVE-2021-36087 Low +libsepol1 2.7-1 2.7-1ubuntu0.1 deb CVE-2021-36084 Low +libss2 1.44.1-1ubuntu1.3 1.44.1-1ubuntu1.4 deb CVE-2022-1304 Medium +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.15 deb CVE-2022-0778 High +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.20 deb CVE-2022-2097 Medium +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.13 deb CVE-2021-3712 Medium +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.13 deb CVE-2021-3711 High +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.17 deb CVE-2022-1292 Medium +libssl1.1 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.19 deb CVE-2022-2068 Medium +libstdc++6 8.4.0-1ubuntu1~18.04 deb CVE-2020-13844 Medium +libsystemd0 237-3ubuntu10.47 237-3ubuntu10.56 deb CVE-2022-2526 Medium +libsystemd0 237-3ubuntu10.47 deb CVE-2022-3821 Medium +libsystemd0 237-3ubuntu10.47 237-3ubuntu10.49 deb CVE-2020-13529 Low +libsystemd0 237-3ubuntu10.47 237-3ubuntu10.49 deb CVE-2021-33910 High +libtinfo5 6.1-1ubuntu1.18.04 deb CVE-2019-17595 Negligible +libtinfo5 6.1-1ubuntu1.18.04 deb CVE-2021-39537 Negligible +libtinfo5 6.1-1ubuntu1.18.04 deb CVE-2019-17594 Negligible +libtinfo5 6.1-1ubuntu1.18.04 deb CVE-2022-29458 Negligible +libudev1 237-3ubuntu10.47 237-3ubuntu10.49 deb CVE-2020-13529 Low +libudev1 237-3ubuntu10.47 237-3ubuntu10.49 deb CVE-2021-33910 High +libudev1 237-3ubuntu10.47 deb CVE-2022-3821 Medium +libudev1 237-3ubuntu10.47 237-3ubuntu10.56 deb CVE-2022-2526 Medium +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23219 Low +locales 2.27-3ubuntu1.4 deb CVE-2016-20013 Negligible +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3999 Medium +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2016-10228 Negligible +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2019-25013 Low +locales 2.27-3ubuntu1.4 deb CVE-2009-5155 Negligible +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-35942 Low +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2022-23218 Low +locales 2.27-3ubuntu1.4 deb CVE-2015-8985 Negligible +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-27618 Low +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-29562 Low +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2021-3326 Low +locales 2.27-3ubuntu1.4 2.27-3ubuntu1.5 deb CVE-2020-6096 Low +log4j-api 2.13.3 java-archive CVE-2021-45105 Medium +log4j-api 2.13.3 java-archive CVE-2021-44832 Medium +log4j-to-slf4j 2.13.3 java-archive CVE-2021-44832 Medium +log4j-to-slf4j 2.13.3 java-archive CVE-2021-45105 Medium +logback-core 1.2.3 1.2.9 java-archive GHSA-668q-qrv7-99fm Medium +login 1:4.5-1ubuntu2 deb CVE-2013-4235 Low +login 1:4.5-1ubuntu2 1:4.5-1ubuntu2.2 deb CVE-2018-7169 Low +ncurses-base 6.1-1ubuntu1.18.04 deb CVE-2022-29458 Negligible +ncurses-base 6.1-1ubuntu1.18.04 deb CVE-2019-17595 Negligible +ncurses-base 6.1-1ubuntu1.18.04 deb CVE-2019-17594 Negligible +ncurses-base 6.1-1ubuntu1.18.04 deb CVE-2021-39537 Negligible +ncurses-bin 6.1-1ubuntu1.18.04 deb CVE-2021-39537 Negligible +ncurses-bin 6.1-1ubuntu1.18.04 deb CVE-2022-29458 Negligible +ncurses-bin 6.1-1ubuntu1.18.04 deb CVE-2019-17595 Negligible +ncurses-bin 6.1-1ubuntu1.18.04 deb CVE-2019-17594 Negligible +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.13 deb CVE-2021-3712 Medium +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.19 deb CVE-2022-2068 Medium +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.20 deb CVE-2022-2097 Medium +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.13 deb CVE-2021-3711 High +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.15 deb CVE-2022-0778 High +openssl 1.1.1-1ubuntu2.1~18.04.9 1.1.1-1ubuntu2.1~18.04.17 deb CVE-2022-1292 Medium +passwd 1:4.5-1ubuntu2 1:4.5-1ubuntu2.2 deb CVE-2018-7169 Low +passwd 1:4.5-1ubuntu2 deb CVE-2013-4235 Low +perl-base 5.26.1-6ubuntu0.5 5.26.1-6ubuntu0.6 deb CVE-2020-16156 Medium +snakeyaml 1.27 java-archive GHSA-w37g-rhq8-7m4j Medium +snakeyaml 1.27 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium +snakeyaml 1.27 1.31 java-archive GHSA-3mc7-4q67-w48m High +snakeyaml 1.27 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium +snakeyaml 1.27 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium +snakeyaml 1.27 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium +spring-core 5.3.6 java-archive CVE-2022-22950 Medium +spring-core 5.3.6 java-archive CVE-2022-22965 Critical +spring-core 5.3.6 java-archive CVE-2021-22096 Medium +spring-core 5.3.6 java-archive CVE-2022-22968 Medium +spring-core 5.3.6 java-archive CVE-2022-22970 Medium +spring-core 5.3.6 java-archive CVE-2022-22971 Medium +spring-core 5.3.6 java-archive CVE-2021-22118 High +spring-core 5.3.6 java-archive CVE-2016-1000027 Critical +spring-core 5.3.6 java-archive CVE-2021-22060 Medium +tar 1.29b-2ubuntu0.2 1.29b-2ubuntu0.3 deb CVE-2021-20193 Low +zlib1g 1:1.2.11.dfsg-0ubuntu2 1:1.2.11.dfsg-0ubuntu2.2 deb CVE-2022-37434 Medium +zlib1g 1:1.2.11.dfsg-0ubuntu2 1:1.2.11.dfsg-0ubuntu2.1 deb CVE-2018-25032 Medium +zlib1g 1:1.2.11.dfsg-0ubuntu2 deb CVE-2022-42800 Medium +``` + +여기서 우리는 훨씬 더 많은 `중요한` 취약점을 볼 수 있을 뿐만 아니라 많은 취약점이 해당 종속성의 최신 버전에서 수정되었음을 알 수 있습니다. +즉, 해당 종속성의 간단한 버전 업데이트만으로도 취약점을 제거하고 이미지를 더 안전하게 만들 수 있습니다. + +물론 항상 그렇게 간단한 것은 아닙니다. +때로는 종속성의 새 버전에 소스 코드를 변경해야 하는 API 변경 사항이 포함되거나, 종속성과 상호 작용하는 방식에 버그를 유발하는 동작 변경이 포함되거나, 수정될 때까지 피하고 싶은 버그가 발생할 수 있습니다. + +또 한 가지 언급할 만한 점은 이러한 유형의 스캔은 _알려진_ 취약점만 탐지한다는 것입니다. +즉, 보안 연구원이 발견하고 CVE를 지정한 취약점만 탐지합니다. +아직 알려지지 않은 취약점이 코드/종속성에 숨어 있을 수 있습니다. (Log4Shell은 2013년부터 사용되었지만 2021년에야 발견됨) + +요약하자면, 이미지 스캔은 만병통치약이 아닙니다. +이미지 스캐너가 이미지에 취약점이 0개라고 알려준다고 해서 100% 안전하다는 의미는 아닙니다. + +또한 취약점을 완화하는 것은 종속성 버전을 변경하거나 다운그레이드하는 것만큼 간단할 수도 있지만, 때로는 버전 변경을 위해 코드를 변경해야 할 수도 있기 때문에 더 까다로울 수 있습니다. + +## CVEs + +스캐너가 제공하는 취약점 표에서 'CVE-'로 시작하는 것을 볼 수 있습니다: + +```text +bash 4.4.18-2ubuntu1.2 deb CVE-2022-3715 Medium +``` + +[CVE**](https://cve.mitre.org/)는 **C**ommon **V**ulnerability and **E**xposures.의 약자입니다. + +취약점을 추적하고 쉽게 검색할 수 있도록 하는 시스템입니다. + +새로운 취약점이 발견될 때마다 [CNA](https://www.cve.org/ProgramOrganization/CNAs)(CVE 번호 부여 기관)에서 CVE를 할당하고 해당 취약점이 포함된 모든 구성 요소와 연관시킵니다. + +이 작업이 완료되면 이 정보는 취약점 데이터베이스로 전파되며 이미지 스캐너를 통해 컨테이너에 존재하는 CVE/취약점에 대해 경고하는 데 활용될 수 있습니다. + +## 요약 + +이제 이미지 스캔이 중요한 이유와 보안을 강화하는 데 어떻게 도움이 되는지 알게 되었습니다. +[15일차](day15.md)에서는 이미지 스캐너가 내부에서 작동하는 방식에 대해 자세히 살펴보고 SBOM과 취약성 데이터베이스 등을 살펴보겠습니다. diff --git a/2023/ko/days/day15.md b/2023/ko/days/day15.md new file mode 100644 index 0000000..5ea2145 --- /dev/null +++ b/2023/ko/days/day15.md @@ -0,0 +1,233 @@ +# 컨테이너 이미지 스캐닝 고급 + +## SBOM + +**SBOM**은 **S**oftware **B**ill **O**f **M**aterials의 약자입니다. + +이것은 소프트웨어 애플리케이션 또는 시스템을 구성하는 모든 구성 요소의 목록입니다. +여기에는 소프트웨어를 구축하는 데 사용되는 다양한 타사 라이브러리, 프레임워크 및 기타 오픈 소스 또는 독점 구성 요소에 대한 정보가 포함됩니다. +또한 SBOM에는 이러한 구성 요소의 버전, 라이선스 정보, 알려진 취약점 또는 보안 문제에 대한 세부 정보도 포함될 수 있습니다. + +SBOM의 목적은 이러한 구성 요소를 나열하여 소프트웨어 사용자에게 소프트웨어 제품에 포함된 구성 요소에 대한 가시성을 제공하고 보안 또는 법적 이유로 유해할 수 있는 구성 요소를 피할 수 있도록 하는 것입니다. + +[올해](https://www.immuniweb.com/blog/5-biggest-supply-chain-attacks-in-2022-so-far.html) 와 [작년](https://cyolo.io/blog/top-5-supply-chain-attacks-of-2021/) 지난 몇 년간 대규모 공급망 공격이 발생한 후 SBOM의 사용이 더욱 보편화되었습니다. + + +컨테이너 이미지의 컨텍스트에서, 컨테이너 이미지에 대한 SBOM에는 다음이 포함됩니다: + +- 컨테이너에 설치된 리눅스 패키지 및 라이브러리 +- 컨테이너에서 실행 중인 애플리케이션을 위해 설치된 언어별 패키지(예: Python 패키지, Go 패키지 등) + +컨테이너 이미지에서 SBOM을 추출하는 데 도움이 되는 도구가 있습니다. + +그러한 도구 중 하나는 [syft](https://github.com/anchore/syft)입니다. + +예를 들어, syft를 사용하여 `ubuntu:latest` 컨테이너 이미지에 대한 SBOM을 생성할 수 있습니다: + +```console +$ syft ubuntu + ✔ Parsed image + ✔ Cataloged packages [101 packages] +NAME VERSION TYPE +adduser 3.118ubuntu5 deb +apt 2.4.8 deb +base-files 12ubuntu4.2 deb +base-passwd 3.5.52build1 deb +bash 5.1-6ubuntu1 deb +bsdutils 1:2.37.2-4ubuntu3 deb +coreutils 8.32-4.1ubuntu1 deb +dash 0.5.11+git20210903+057cd650a4ed-3build1 deb +debconf 1.5.79ubuntu1 deb +debianutils 5.5-1ubuntu2 deb +diffutils 1:3.8-0ubuntu2 deb +dpkg 1.21.1ubuntu2.1 deb +e2fsprogs 1.46.5-2ubuntu1.1 deb +findutils 4.8.0-1ubuntu3 deb +gcc-12-base 12.1.0-2ubuntu1~22.04 deb +gpgv 2.2.27-3ubuntu2.1 deb +grep 3.7-1build1 deb +gzip 1.10-4ubuntu4.1 deb +hostname 3.23ubuntu2 deb +init-system-helpers 1.62 deb +libacl1 2.3.1-1 deb +libapt-pkg6.0 2.4.8 deb +libattr1 1:2.5.1-1build1 deb +libaudit-common 1:3.0.7-1build1 deb +libaudit1 1:3.0.7-1build1 deb +libblkid1 2.37.2-4ubuntu3 deb +libbz2-1.0 1.0.8-5build1 deb +libc-bin 2.35-0ubuntu3.1 deb +libc6 2.35-0ubuntu3.1 deb +libcap-ng0 0.7.9-2.2build3 deb +libcap2 1:2.44-1build3 deb +libcom-err2 1.46.5-2ubuntu1.1 deb +libcrypt1 1:4.4.27-1 deb +libdb5.3 5.3.28+dfsg1-0.8ubuntu3 deb +libdebconfclient0 0.261ubuntu1 deb +libext2fs2 1.46.5-2ubuntu1.1 deb +libffi8 3.4.2-4 deb +libgcc-s1 12.1.0-2ubuntu1~22.04 deb +libgcrypt20 1.9.4-3ubuntu3 deb +libgmp10 2:6.2.1+dfsg-3ubuntu1 deb +libgnutls30 3.7.3-4ubuntu1.1 deb +libgpg-error0 1.43-3 deb +libgssapi-krb5-2 1.19.2-2 deb +libhogweed6 3.7.3-1build2 deb +libidn2-0 2.3.2-2build1 deb +libk5crypto3 1.19.2-2 deb +libkeyutils1 1.6.1-2ubuntu3 deb +libkrb5-3 1.19.2-2 deb +libkrb5support0 1.19.2-2 deb +liblz4-1 1.9.3-2build2 deb +liblzma5 5.2.5-2ubuntu1 deb +libmount1 2.37.2-4ubuntu3 deb +libncurses6 6.3-2 deb +libncursesw6 6.3-2 deb +libnettle8 3.7.3-1build2 deb +libnsl2 1.3.0-2build2 deb +libp11-kit0 0.24.0-6build1 deb +libpam-modules 1.4.0-11ubuntu2 deb +libpam-modules-bin 1.4.0-11ubuntu2 deb +libpam-runtime 1.4.0-11ubuntu2 deb +libpam0g 1.4.0-11ubuntu2 deb +libpcre2-8-0 10.39-3ubuntu0.1 deb +libpcre3 2:8.39-13ubuntu0.22.04.1 deb +libprocps8 2:3.3.17-6ubuntu2 deb +libseccomp2 2.5.3-2ubuntu2 deb +libselinux1 3.3-1build2 deb +libsemanage-common 3.3-1build2 deb +libsemanage2 3.3-1build2 deb +libsepol2 3.3-1build1 deb +libsmartcols1 2.37.2-4ubuntu3 deb +libss2 1.46.5-2ubuntu1.1 deb +libssl3 3.0.2-0ubuntu1.7 deb +libstdc++6 12.1.0-2ubuntu1~22.04 deb +libsystemd0 249.11-0ubuntu3.6 deb +libtasn1-6 4.18.0-4build1 deb +libtinfo6 6.3-2 deb +libtirpc-common 1.3.2-2ubuntu0.1 deb +libtirpc3 1.3.2-2ubuntu0.1 deb +libudev1 249.11-0ubuntu3.6 deb +libunistring2 1.0-1 deb +libuuid1 2.37.2-4ubuntu3 deb +libxxhash0 0.8.1-1 deb +libzstd1 1.4.8+dfsg-3build1 deb +login 1:4.8.1-2ubuntu2 deb +logsave 1.46.5-2ubuntu1.1 deb +lsb-base 11.1.0ubuntu4 deb +mawk 1.3.4.20200120-3 deb +mount 2.37.2-4ubuntu3 deb +ncurses-base 6.3-2 deb +ncurses-bin 6.3-2 deb +passwd 1:4.8.1-2ubuntu2 deb +perl-base 5.34.0-3ubuntu1.1 deb +procps 2:3.3.17-6ubuntu2 deb +sed 4.8-1ubuntu2 deb +sensible-utils 0.0.17 deb +sysvinit-utils 3.01-1ubuntu1 deb +tar 1.34+dfsg-1build3 deb +ubuntu-keyring 2021.03.26 deb +usrmerge 25ubuntu2 deb +util-linux 2.37.2-4ubuntu3 deb +zlib1g 1:1.2.11.dfsg-2ubuntu9.2 deb +``` + +SBOM에는 컨테이너 이미지 내부에 설치된 패키지와 라이브러리가 포함되어 있을 뿐만 아니라, +유형과 버전도 나열되어 있습니다. +이제 이 목록을 취약점 데이터베이스와 상호 참조하여 컨테이너 내부에 취약점이 있는지 확인할 수 있습니다. + +그렇다면 **취약점 데이터베이스(Vulnerability Database)**란 무엇인가요? + +## 취약점 데이터베이스 + +취약점 데이터베이스는 소프트웨어, 하드웨어 및 기타 시스템의 알려진 취약점에 대한 정보 모음입니다. +일반적으로 취약점의 유형, 취약점의 심각도, 취약점의 잠재적 영향과 같은 취약점의 특성에 대한 세부 정보가 포함됩니다. +취약점 데이터베이스에는 취약점이 악용될 수 있는 방법과 해당 취약점에 대해 사용 가능한 패치 또는 수정 사항에 대한 정보도 포함될 수 있습니다. + +일부 취약점 데이터베이스는 [vuldb.com](https://vuldb.com/), [NIST](https://nvd.nist.gov/vuln), [cvedetails.com](https://www.cvedetails.com/) 및 [Snyk 취약점 데이터베이스](https://security.snyk.io/) 등이 있습니다. + +이들 기관은 사용자가 다운로드할 수 있는 API 또는 원시 데이터를 제공하며, SBOM의 패키지와 취약점 정보를 상호 참조할 수 있습니다. +이렇게 하면 패키지에 주의해야 할 취약점이 있는지 확인할 수 있습니다. + +일반적으로 이 취약점이 도입된 라이브러리 버전과 최신 버전에서 취약점이 수정되었는지 여부에 대한 정보도 찾을 수 있습니다. +이 정보를 사용하여 취약점을 완화하기 위해 종속성을 업데이트/다운그레이드할지 여부를 결정할 수 있습니다. +[14일차](./day14.md)에서 이미 설명했듯이, 종속성 업데이트에는 동작 또는 API 변경이 수반되는 경우가 있기 때문에 종속성을 업데이트하는 것이 항상 간단한 것은 아닙니다. + +취약점에 대한 또 다른 중요한 정보는 취약점의 **CVSS 점수**입니다. + +## CVSS + +**CVSS**는 **C**ommon **V**ulnerability **S**coring **S**ystem의 약자입니다. + +이 시스템은 취약점의 주요 특성을 파악하고 그 심각성을 반영하는 수치 점수를 생성하는 방법을 제공합니다. +그런 다음 이 수치 점수를 정성적 표현(낮음, 중간, 높음, 심각 등)으로 변환하여 조직이 취약점 관리 프로세스를 적절히 평가하고 우선순위를 정할 수 있도록 도와줍니다. + +기본적으로 하나의 취약점이 다른 취약점보다 더 심각할 수 있습니다. +익스플로잇이 얼마나 쉬운지, 얼마나 큰 피해를 입힐 수 있는지에 따라 취약점의 순위를 객관적으로 매길 수 있는 시스템이 필요합니다. + +이것이 바로 CVSS가 필요한 이유입니다. + +CVSS v3는 CVSS 점수를 계산하는 8가지 기준을 정의합니다. +이러한 기준은 다음과 같습니다: + +### 공격 벡터 Attack Vector + +취약점 악용이 가능한 컨텍스트를 반영합니다. + +가능한 값 : **Network(N)**, **Adjacent(A)**, **Local(L)**, **Physical(P)** + +### 공격 복잡성 Attack Complexity + +취약점을 익스플로잇하기 위해 공격자가 통제할 수 없는 조건에 대해 설명합니다. + +가능한 값 : **Low(L)**, **High(H)** + +### 필요한 권한 Priviledges Required + +공격자가 취약점을 성공적으로 익스플로잇하기 전에 보유해야 하는 권한 수준을 설명합니다. + +가능한 값 : **None(N)**, **Low(L)**, **High(H)** + +### 사용자 상호작용 User Interaction + +공격자 이외의 사용자가 취약한 구성 요소의 성공적인 침해에 참여하기 위한 요구 사항입니다. + +가능한 값 : **None(N)**, **Required(R)** + +#### 범위 Scope + +한 소프트웨어 구성 요소의 취약점이 리소스 또는 권한에 영향을 미칠 수 있는 능력입니다. + +가능한 값 : **Unchanged(U)**, **Changed(C)** + +### 기밀성 Confidentiality + +성공적으로 익스플로잇된 취약점으로 인해 소프트웨어 구성 요소가 관리하는 정보 리소스의 기밀성에 미치는 영향입니다. + +가능한 값 : **None(N)**, **Low(L)**, **High(H)** + +### 무결성 Integrity + +성공적으로 익스플로잇된 취약점이 무결성에 미치는 영향입니다. + +가능한 값 : **None(N)**, **Low(L)**, **High(H)** + +### 가용성 Availability + +성공적으로 익스플로잇된 취약점으로 인해 영향을 받은 구성 요소의 가용성에 미치는 영향입니다. + +가능한 값 : **None(N)**, **Low(L)**, **High(H)** + +이 8가지 벡터의 조합에 따라 CVSS 점수가 결정됩니다. +0에서 10 사이입니다. +0이 가장 낮고 10이 가장 높습니다.(가장 위험) +[이 곳](https://www.first.org/cvss/calculator/3.0)에서 각 취약점의 점수를 계산할 수 있는 CVSS 계산기를 찾을 수 있습니다. + +## 리소스 + + + + + + +[16일차](day16.md)에서는 "Fuzzing" 또는 Fuzz Test에 대해 살펴보겠습니다. \ No newline at end of file diff --git a/2023/ko/days/day16.md b/2023/ko/days/day16.md new file mode 100644 index 0000000..321c158 --- /dev/null +++ b/2023/ko/days/day16.md @@ -0,0 +1,94 @@ +# 퍼징 Fuzzing + +'퍼즈 테스트'라고도 하는 퍼징은 컴퓨터 프로그램에 유효하지 않거나 예상치 못한 임의의 데이터를 입력으로 제공하는 소프트웨어 테스트 기법입니다. +퍼징의 목표는 프로그램이 충돌하거나 의도하지 않은 동작을 나타내어 프로그램의 보안 취약점 및 기타 버그를 식별하는 것입니다. + +퍼징은 수동으로 수행하거나 테스트 라이브러리/프레임워크를 사용하여 입력을 만들어서 수행할 수 있습니다. + +퍼징을 더 잘 이해하기 위해 다음 코드를 예로 들어보겠습니다: + +```go +func DontPanic(s string) { + if len(s) == 4 { + if s[0] == 'f' { + if s[1] == 'u' { + if s[2] == 'z' { + if s[3] == 'z' { + panic("error: wrong input") + } + } + } + } + } +} +``` + +이것은 '문자열'을 유일한 인수로 받아들이는 Go 함수입니다. + +함수를 살펴보면, 제공된 입력이 '퍼즈'라는 단어인 경우 한 가지 조건에서만 함수가 'panic'(예: crash)을 일으키는 것처럼 보입니다. + +물론 이 함수는 매우 간단하며 보기만 해도 그 동작을 알 수 있습니다. +그러나 더 복잡한 시스템에서는 이러한 실패 지점이 명확하지 않을 수 있으며, 이를 테스트하거나 단위 테스트 케이스를 작성하는 사람이 놓칠 수 있습니다. + +이때 퍼징이 유용합니다. + +Go 퍼징 라이브러리(Go 1.18부터 표준 언어 라이브러리의 일부)는 테스트 케이스에 대한 많은 입력을 생성한 다음 커버리지와 결과에 따라 어떤 입력이 "흥미로운지"를 결정합니다.이 함수에 대한 퍼즈 테스트를 작성하면 다음과 같은 일이 발생합니다: + +1. 퍼징 라이브러리가 작은 문자열부터 시작하여 크기가 커지는 무작위 문자열을 제공하기 시작합니다. +2. 라이브러리가 길이 4의 문자열을 제공하면 테스트 범위의 변경을 감지하고(`if (len(s) == 4)`가 이제 `true`가 됨) 이 길이의 입력을 계속 생성합니다. +3. 라이브러리가 `f`로 시작하는 길이 4의 문자열을 제공하면 테스트 커버리지의 또 다른 변경 사항(`if s[0] == "f"`는 이제 `true`)을 감지하고 `f`로 시작하는 입력을 계속 생성합니다. +4. `u`와 이중 `z`에 대해서도 같은 일이 반복됩니다. +5. `fuzz`를 입력으로 제공하면 함수가 패닉 상태에 빠지고 테스트가 실패합니다. +6. __퍼즈__에 성공했습니다! + +퍼징의 또 다른 좋은 방법은 코드 충돌을 일으킨 입력을 저장하고 매번 실행하여 퍼징을 통해 발견한 원래 오류가 다시는 코드에 도입되지 않도록 하는 것입니다. + +이 역시 퍼징 프레임워크의 특징일 수 있습니다. + +대부분의 퍼징 라이브러리에서는 테스트하려는 특정 값을 추가할 수 있습니다. +이렇게 하면 우리가 이미 알고 있는 "흥미로운" 값을 라이브러리에 표시하여 생성된 값을 모델링할 수 있으므로 라이브러리에도 도움이 됩니다. + +## 퍼징만으로는 충분하지 않은 경우 + +퍼징은 유용한 기술이지만 도움이 되지 않는 상황도 있습니다. + +예를 들어, 코드에 실패하는 입력이 너무 구체적이어서 도움이 되는 단서가 없는 경우 퍼징 라이브러리가 이를 추측하지 못할 수 있습니다. + +이전 단락의 예제 코드를 다음과 같이 변경해 보겠습니다. + +```go +func DontPanic(s input) { + if (len(s) == 4) && s[0] == 'f' && s[1] == 'u' && s[2] == 'z' && s[3] == 'z' { + panic("error") + } +} +``` + +또는 + +```go +func DontPanic(s input) { + if s == "fuzz" { + panic("error") + } +} +``` + +이런 경우 퍼징은 아무런 단서 없이 정확한 문자열 `퍼즈`를 생성할 가능성이 적기 때문에 도움이 되지 않습니다. +그리고 이전 사례에서 코드 커버리지 변경을 트리거했던 입력(크기 4의 문자열, `z`로 시작하는 크기 4의 문자열 등)은 이제 코드 커버리지를 트리거하지 않습니다. (이전 예제에서는 `if` 체크가 5개인데 비해 지금은 하나만 있기 때문입니다) + +따라서 퍼징은 코드의 이상 징후와 코너 케이스를 감지하는 좋은 방법이지만 100% 올바른 코드를 위한 만병통치약은 아니라는 점을 이해하는 것이 중요합니다. + +## 실제 예제 + +Go에서 퍼징을 직접 해보고 싶으시다면 [해당 주제에 대한 예제가 있는 내 리포지토리](https://github.com/asankov/go-fuzzing-101/tree/v1)를 확인하세요. + +여기에는 이 글에서 사용한 예제와 실패를 트리거하는 퍼즈 테스트, 그리고 테스트를 직접 실행하는 방법에 대한 지침이 포함되어 있습니다. + +## 리소스 + +- +- [Fuzzing in Go by Valentin Deleplace, Devoxx Belgium 2022](https://www.youtube.com/watch?v=Zlf3s4EjnFU) +- [Write applications faster and securely with Go by Cody Oss, Go Day 2022](https://www.youtube.com/watch?v=aw7lFSFGKZs) + +[17일차](day17.md)에 뵙겠습니다. \ No newline at end of file diff --git a/2023/ko/days/day17.md b/2023/ko/days/day17.md new file mode 100644 index 0000000..36cd71e --- /dev/null +++ b/2023/ko/days/day17.md @@ -0,0 +1,247 @@ +# 퍼징(Fuzzing) 고급 + +어제 우리는 퍼징이 무엇인지, 그리고 퍼즈 테스트(퍼지 입력을 사용하는 단위 테스트)를 작성하는 방법을 배웠습니다. +하지만 퍼즈 테스트는 단순한 단위 테스트 그 이상입니다. +이 방법론을 사용하여 서버로 전송되는 요청을 퍼징하여 웹 애플리케이션을 테스트할 수 있습니다. + +오늘은 웹 서버 퍼지 테스트에 대한 실용적인 접근 방식을 살펴보겠습니다. + +이를 위해 다양한 도구가 도움이 될 수 있습니다. + +[Burp Intruder](https://portswigger.net/burp/documentation/desktop/tools/intruder), [SmartBear](https://smartbear.com/) 등이 있습니다. +하지만 유료 라이선스가 필요한 독점 도구(proprietary tools)도 있습니다. + + +그렇기 때문에 오늘 데모에서는 `Burp Intruder`에서 영감을 받아 유사한 기능을 제공하는 Go로 작성된 간단한 오픈 소스 CLI를 사용하려고 합니다. +이름은 [httpfuzz](https://github.com/JonCooperWorks/httpfuzz)입니다. + + +## Getting started + +이 도구는 아주 간단합니다. +요청에 대한 템플릿(퍼지 데이터에 대한 placeholder를 정의), 단어 목록(퍼지 데이터)을 제공하면 `httpfuzz`가 요청을 렌더링하여 서버로 전송합니다. + +먼저 요청에 대한 템플릿을 정의해야 합니다. +다음 내용으로 `request.txt`라는 파일을 생성합니다. + +```text +POST / HTTP/1.1 +Content-Type: application/json +User-Agent: PostmanRuntime/7.26.3 +Accept: */* +Cache-Control: no-cache +Host: localhost:8000 +Accept-Encoding: gzip, deflate +Connection: close +Content-Length: 35 + +{ + "name": "`S9`", +} +``` + +이것은 JSON 본문이 있는 `/` 경로에 대한 유효한 HTTP `POST` 요청입니다. +본문의 "\`" 기호는 우리가 제공하는 데이터로 대체될 플레이스홀더를 정의합니다. + +`httpfuzz`는 헤더, 경로, URL 매개변수를 퍼즈 처리할 수도 있습니다. + +다음으로 요청에 넣을 입력의 단어 목록을 제공해야 합니다. +다음 내용으로 `data.txt`라는 파일을 생성합니다: + +```text +SOME_NAME +Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36 +``` + +이 파일에서는 본문 내부에 대체될 두 개의 입력을 정의했습니다. +실제 시나리오에서는 적절한 퍼즈 테스트를 위해 훨씬 더 많은 데이터를 여기에 넣어야 합니다. + +이제 템플릿과 입력이 준비되었으니 도구를 실행해 보겠습니다. +안타깝게도 이 도구는 바이너리로 배포되지 않으므로 소스에서 빌드해야 합니다. +리포지토리를 복제하고 실행합니다. + +```shell +go build -o httpfuzz cmd/httpfuzz.go +``` +(컴퓨터에 최신 버전의 Go가 설치되어 있어야 합니다.) + +이제 바이너리를 얻었으니 실행해 보겠습니다. + +```shell +./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ +``` + +- `httpfuzz`는 우리가 호출하는 바이너리입니다. +- `--wordlist data.txt`는 우리가 제공한 입력이 포함된 파일입니다. +- `--seed-request requests.txt`는 요청 템플릿입니다. +- `--target-header User-Agent`는 `httpfuzz`가 `User-Agent` 헤더 대신에 제공된 입력을 사용하도록 지시합니다. +- `--target-param fuzz`는 제공된 입력을 `fuzz` URL 매개변수의 값으로 사용하도록 `httpfuzz`에 지시합니다. +- `--delay-ms 50`은 요청 사이에 50ms를 기다리도록 `httpfuzz`에 지시합니다. +- `--skip-cert-verify`는 `httpfuzz`에게 TLS 확인을 수행하지 않도록 지시합니다. +- `--proxy-url http://localhost:8080`는 `httpfuzz`에게 HTTP 서버의 위치를 알려줍니다. + +2개의 입력과 3개의 위치(본문, `User-Agent` 헤더, `fuzz` 매개변수)에 배치할 수 있습니다. +즉, `httpfuzz`는 6개의 요청을 생성하여 서버로 전송합니다. + +실행해서 어떤 일이 일어나는지 봅시다. +서버로 들어오는 요청을 확인할 수 있도록 모든 요청을 기록하는 간단한 웹 서버를 작성했습니다. + +```shell +$ ./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ + +httpfuzz: httpfuzz.go:164: Sending 6 requests +``` + +그리고 서버 로그입니다. + +```text +----- +Got request to http://localhost:8000/ +User-Agent header = [SOME_NAME] +Name = S9 +----- +Got request to http://localhost:8000/?fuzz=SOME_NAME +User-Agent header = [PostmanRuntime/7.26.3] +Name = S9 +----- +Got request to http://localhost:8000/ +User-Agent header = [PostmanRuntime/7.26.3] +Name = SOME_NAME +----- +Got request to http://localhost:8000/ +User-Agent header = [Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36] +Name = S9 +----- +Got request to http://localhost:8000/?fuzz=Mozilla%2F5.0+%28Linux%3B+Android+7.0%3B+SM-G930VC+Build%2FNRD90M%3B+wv%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Version%2F4.083+Mobile+Safari%2F537.36 +User-Agent header = [PostmanRuntime/7.26.3] +Name = S9 +----- +Got request to http://localhost:8000/ +User-Agent header = [PostmanRuntime/7.26.3] +Name = Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36 +``` + +6개의 HTTP 요청이 수신된 것을 확인할 수 있습니다. + +이 중 2개는 `User-Agent` 헤더에 대한 값 파일의 값을 가지고 있고, 4개는 템플릿의 기본 헤더를 가지고 있습니다. + +그 중 2개는 `fuzz` 쿼리 매개변수에 대한 값 파일의 값을 가지고 있고, 4개는 템플릿의 기본 헤더를 가지고 있습니다. + +그 중 2개는 `Name` 본문 속성에 대한 값 파일에서 값을 가져오고, 4개는 템플릿의 기본 헤더를 사용합니다. + +이 도구를 약간 개선하면 이러한 요청의 순열을 다르게 만들 수 있습니다(예: 값 파일의 값으로 `?fuzz=`와 `User-Agent`가 모두 있는 요청). + +`httpfuzz`가 요청의 결과에 대한 정보를 제공하지 않는다는 점에 주목하세요. +이를 파악하려면 서버에 대한 일종의 모니터링을 설정하거나 우리에게 의미 있는 방식으로 결과를 처리하는 `httpfuzz` 플러그인을 작성해야 합니다. +그렇게 해봅시다. + +사용자 정의 플러그인을 작성하려면 [`Listener`](https://github.com/JonCooperWorks/httpfuzz/blob/master/plugin.go#L13) 인터페이스를 구현해야합니다. + +```go +// Listener must be implemented by a plugin to users to hook the request - response transaction. +// The Listen method will be run in its own goroutine, so plugins cannot block the rest of the program, however panics can take down the entire process. +type Listener interface { + Listen(results <-chan *Result) +} +``` + +```go +package main + +import ( + "bytes" + "io/ioutil" + "log" + + "github.com/joncooperworks/httpfuzz" +) + +type logResponseCodePlugin struct { + logger *log.Logger +} + +func (b *logResponseCodePlugin) Listen(results <-chan *httpfuzz.Result) { + for result := range results { + b.logger.Printf("Got %d response from the server\n", result.Response.StatusCode) + } +} + +// New returns a logResponseCodePlugin plugin that simple logs the response code of the response. +func New(logger *log.Logger) (httpfuzz.Listener, error) { + return &logResponseCodePlugin{logger: logger}, nil +} +``` + +이제 플러그인을 빌드해야 합니다. + +```shell +go build -buildmode=plugin -o log exampleplugins/log/log.go +``` + +그리고 `--post-request` 플래그를 통해 `httpfuzz`에 연결할 수 있습니다: + +```shell +$ ./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ + --post-request log + +httpfuzz: httpfuzz.go:164: Sending 6 requests +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +``` + +짜잔! +이제 최소한 서버의 응답 코드가 무엇인지 확인할 수 있습니다. + +물론 훨씬 더 많은 데이터를 출력하는 훨씬 더 정교한 플러그인을 작성할 수도 있지만, 이 연습의 목적상 이 정도면 충분합니다. + + +## 요약 + +퍼징은 단위 테스트를 훨씬 뛰어넘는 매우 강력한 테스트 기법입니다. + +퍼징은 유효한 HTTP 요청의 일부를 서버의 취약점이나 결함을 노출할 수 있는 데이터로 대체하여 HTTP 서버를 테스트하는 데 매우 유용할 수 있습니다. + +웹 애플리케이션 퍼지 테스트에 도움이 되는 무료 및 유료 도구가 많이 있습니다. + +## 리소스 + +[OWASP: Fuzzing](https://owasp.org/www-community/Fuzzing) + +[OWASP: Fuzz Vectors](https://owasp.org/www-project-web-security-testing-guide/v41/6-Appendix/C-Fuzz_Vectors) + +[Hacking HTTP with HTTPfuzz](https://medium.com/swlh/hacking-http-with-httpfuzz-67cfd061b616) + +[Fuzzing the Stack for Fun and Profit at DefCamp 2019](https://www.youtube.com/watch?v=qCMfrbpuCBk&list=PLnwq8gv9MEKiUOgrM7wble1YRsrqRzHKq&index=33) + +[HTTP Fuzzing Scan with SmartBear](https://support.smartbear.com/readyapi/docs/security/scans/types/fuzzing-http.html) + +[Fuzzing Session: Finding Bugs and Vulnerabilities Automatically](https://youtu.be/DSJePjhBN5E) + +[Fuzzing the CNCF Landscape](https://youtu.be/zIyIZxAZLzo) + +[18일차](day18.md)에 뵙겠습니다. diff --git a/2023/ko/days/day18.md b/2023/ko/days/day18.md new file mode 100644 index 0000000..8beb171 --- /dev/null +++ b/2023/ko/days/day18.md @@ -0,0 +1,40 @@ +# DAST (동적 애플리케이션 보안 테스트) +DAST(Dynamic Application Security Testing)는 외부 소스로부터의 공격을 시뮬레이션하여 애플리케이션의 보안을 평가하는 데 사용되는 기술입니다. +아이디어는 가능한 한 많은 블랙박스 침투 테스트를 자동화하는 것입니다. +실제 사람의 시간을 절약하고 다른 보안 도구(예: IAST)로의 트래픽을 생성하는 데 추가로 사용할 수 있습니다. + +그럼에도 불구하고 조직이 애플리케이션을 프로덕션 환경에 배포하기 전에 개발 프로세스 초기에 잠재적인 취약점을 발견할 수 있도록 도와주기 때문에 SSDLC의 필수 구성 요소입니다. DAST 테스트를 수행함으로써 조직은 보안 사고를 예방하고 공격자에 의해 데이터와 자산이 손상되지 않도록 보호할 수 있습니다. + +## 도구 + +DAST를 수행하는 데 사용할 수 있는 다양한 오픈 소스 도구가 있습니다. ZAP, Burp Suite, Arachni 등이 있습니다. + + 이러한 도구는 SQL 인젝션, 크로스 사이트 스크립팅 및 기타 일반적인 취약점 등 애플리케이션에 대한 다양한 유형의 공격을 시뮬레이션할 수 있습니다. + + 예를 들어 애플리케이션이 SQL 인젝션에 취약한 경우, DAST 툴은 애플리케이션에 `OR 1=1 --`과 같은 악성 SQL 쿼리를 전송하고 응답을 평가하여 취약한지 여부를 확인할 수 있습니다. 애플리케이션이 취약한 경우 데이터베이스의 모든 레코드를 반환하여 SQL 인젝션 공격이 성공했음을 나타낼 수 있습니다. + +일부 테스트는 상당히 침략적일 수 있으며(예: 'DROP TABLE' 또는 이와 유사한 것을 포함할 수 있음), 적어도 데이터베이스에 많은 양의 테스트 데이터를 넣거나 심지어 앱에 DOS를 가할 수도 있습니다. + +> __DAST 도구는 프로덕션 환경에서 절대 실행해서는 안 됩니다!!!__ + +모든 도구에는 애플리케이션에 대한 인증 가능성이 있으며 이로 인해 프로덕션 자격 증명이 손상될 수 있습니다. 또한 테스트 환경에 대해 인증된 스캔을 실행할 때는 적절한 역할을 사용해야 합니다(물론 RBAC 모델이 존재하는 경우 애플리케이션에 대해). 예를 들어, DAST는 다른 사용자를 삭제하거나 수정할 수 있는 역할을 사용하면 전체 환경을 사용할 수 없게 될 수 있으므로 사용하지 않아야 합니다. +다른 테스트 방법론과 마찬가지로 범위를 분석해야 하므로 불필요한 대상을 검사하지 않습니다. + +## 사용법 +일반적인 오류는 실제 애플리케이션이 아닌 보상 보안 제어 (compensating security control, 예: WAF)를 스캔하는 것입니다. + +DAST는 본질적으로 애플리케이션 보안 테스트 도구이며 보안 완화가 아닌 실제 애플리케이션에 대해 사용해야 합니다. 상당히 표준화된 공격을 사용하기 때문에 외부 제어가 공격 트래픽을 차단할 수 있으며, 이러한 방식으로 잠재적으로 악용될 수 있는 플로우를 커버할 수 있습니다.(정의에 따라 공격자는 결국 이러한 조치를 우회할 수 있음) + +실제 스캔은 매우 느리기 때문에 때때로 DevOps 파이프라인 외부에서 실행해야 합니다. 야간이나 주말에 실행하는 것이 좋은 예입니다. 일부 간단한 도구(zap / arachny 등)를 파이프라인에 사용할 수 있지만 스캔의 특성으로 인해 전체 개발 프로세스의 속도가 느려질 수 있습니다. + +DAST 테스트가 완료되면 결과를 분석하여 발견된 취약점을 식별합니다. 그런 다음 조직은 취약점을 해결하고 애플리케이션의 전반적인 보안을 개선하기 위해 적절한 수정 조치를 취할 수 있습니다. 여기에는 기본 코드 수정, 입력 유효성 검사 및 필터링과 같은 추가 보안 제어 구현 또는 두 가지 모두 포함될 수 있습니다. + +결론적으로, 애플리케이션의 보안을 보장하기 위해서는 SSDLC에서 DAST를 사용하는 것이 필수적입니다. 개발 프로세스 초기에 DAST 테스트를 수행하고 취약점을 식별함으로써 조직은 보안 사고를 예방하고 잠재적인 위협으로부터 자산을 보호할 수 있습니다. ZAP, Burp Suite, Arachni와 같은 오픈 소스 도구를 사용하여 DAST 테스트를 수행하고 조직의 전반적인 보안 태세를 개선할 수 있습니다. +DevSecOps 파이프라인의 다른 모든 도구와 마찬가지로 DAST가 유일한 스캐너가 되어서는 안 되며, 다른 모든 도구와 마찬가지로 모의 침투 테스트와 모범 개발 관행을 대체할 수 없습니다. + +## 유용한 링크와 오픈소스 도구가 몇 가지 +- https://github.com/zaproxy/zaproxy +- https://www.arachni-scanner.com/ +- https://owasp.org/www-project-devsecops-guideline/latest/02b-Dynamic-Application-Security-Testing + +[19일차](day19.md)에 뵙겠습니다. diff --git a/2023/ko/days/day19.md b/2023/ko/days/day19.md new file mode 100644 index 0000000..5227df1 --- /dev/null +++ b/2023/ko/days/day19.md @@ -0,0 +1,43 @@ +# IAST (Interactive Application Security Testing) +IAST는 웹 애플리케이션의 취약점을 식별하고 개발자가 이를 수정할 수 있도록 설계된 보안 테스트 도구의 일종입니다. 이 도구는 애플리케이션의 런타임 환경에 작은 에이전트를 삽입하고 실시간으로 동작을 모니터링하는 방식으로 작동합니다. 따라서 IAST 도구는 정적 분석이나 모의 공격에 의존하지 않고 취약점이 발생할 때 이를 식별할 수 있습니다. + +IAST는 소프트웨어 계측(software instrumentation) 또는 계측기를 사용하여 애플리케이션이 실행되는 동안 모니터링하고 애플리케이션이 수행하는 작업과 성능에 대한 정보를 수집하는 방식으로 작동합니다. IAST 솔루션은 실행 중인 애플리케이션에 에이전트와 센서를 배포하고 수동 테스트, 자동 테스트 또는 이 둘의 조합으로 시작된 모든 애플리케이션 상호 작용을 지속적으로 분석하여 실시간으로 취약성을 식별함으로써 애플리케이션을 계측합니다. +IAST 에이전트는 애플리케이션 내부에서 실행되며 알려진 공격 패턴을 모니터링합니다. 애플리케이션의 일부이므로 서로 다른 구성 요소 간의 트래픽을 모니터링할 수 있습니다. (클래식 MVC 배포 및 마이크로서비스 배포 간) + +## IAST의 전제조건 +- 애플리케이션을 계측해야 합니다. (Agent를 주입해야 함.) +- 수동 또는 자동 테스트를 통해 트래픽을 생성해야 합니다. 또 다른 가능한 접근 방식은 DAST 도구를 사용하는 것입니다. (예를 들어 OWASP ZAP을 사용할 수 있음) + +## 장점 + +IAST 도구의 주요 장점 중 하나는 취약점과 취약점 수정 방법에 대한 상세하고 정확한 정보를 제공할 수 있다는 것입니다. 개발자가 수동으로 취약점을 검색하거나 테스트 환경에서 취약점을 재현할 필요가 없으므로 많은 시간과 노력을 절약할 수 있습니다. + +또한 IAST 도구는 사용자 상호 작용이 필요하거나 특정 조건에서 트리거되는 취약점 등 다른 테스트 방법으로는 놓칠 수 있는 취약점을 식별할 수 있습니다. + +테스트 시간은 사용되는 테스트에 따라 다르며(IAST는 독립형 시스템이 아니므로), 더 빠른 테스트(자동화된 테스트)를 CI/CD 파이프라인에 포함할 수 있습니다. 다양한 종류의 취약점을 탐지하는 데 사용할 수 있으며 도구의 특성상('실제 트래픽만' 찾기 때문에) 다른 테스트 유형에 비해 위양성/위음성 결과가 상대적으로 뒤처집니다. +IAST는 일반적인 테스트 도구와 실시간 보호(이 경우 RAST라고 함)의 두 가지 방식으로 사용할 수 있습니다. 두 가지 모두 동일한 원칙에 따라 작동하며 함께 사용할 수 있습니다. + +## 몇 가지 단점 +- 비교적 새로운 기술이기 때문에 보안 팀과 도구 빌더(오픈 소스 또는 상용) 모두에 대한 지식과 경험이 많지 않습니다. +- 이 솔루션은 단독으로 사용할 수 없으며 누군가(또는 무언가)가 트래픽 패턴을 생성해야 합니다. 테스트 중에 가능한 모든 엔드포인트를 쿼리하는 것이 중요합니다. +- 결과는 트래픽을 기반으로 합니다. 앱/사이트의 일부에 대한 트래픽이 없는 경우 테스트가 이루어지지 않으므로 결과가 생성되지 않습니다. +- 앱에 대한 계측이 필요하기 때문에 특히 소스 스캔 도구(SAST 또는 SCA)에 비해 상당히 복잡할 수 있습니다. + +각각 고유한 특징과 기능을 갖춘 여러 가지 IAST 도구를 사용할 수 있습니다. + +## IAST 도구의 일반적인 기능 + +- 실시간 모니터링: IAST 도구는 애플리케이션의 동작을 실시간으로 모니터링하여 취약점이 발생할 때 이를 식별할 수 있습니다. +- 취약점 식별: IAST 도구는 인젝션 공격, 크로스 사이트 스크립팅(XSS), 크로스 사이트 요청 위조(CSRF)를 포함한 광범위한 취약점을 식별할 수 있습니다. +- 수정 지침: IAST 도구는 코드 스니펫 및 보안 코딩 관행에 대한 권장 사항을 포함하여 식별된 취약점을 수정하는 방법에 대한 자세한 정보를 제공하는 경우가 많습니다. +- 다른 도구와의 통합: IAST 도구는 정적 코드 분석 또는 침투 테스트 도구와 같은 다른 보안 테스트 도구와 통합하여 애플리케이션의 보안에 대한 보다 포괄적인 보기를 제공할 수 있습니다. + +IAST 도구는 실시간으로 취약점을 식별하고 수정하여 시간과 노력을 절약할 수 있으므로 개발자의 툴킷에 추가할 수 있는 유용한 도구가 될 수 있습니다. 개발자로서 IAST 도구 사용에 관심이 있다면 다양한 옵션을 사용할 수 있으므로 여러 도구를 조사하고 비교하여 자신의 필요에 가장 적합한 도구를 찾는 것이 중요합니다. + +## 도구 예시 + +시중에는 오픈 소스 도구가 거의 없습니다. 상용 도구를 예로 들 수 있습니다: Contrast Community Edition(CE) - 앱 1개와 최대 5명의 사용자를 위한 모든 기능을 갖춘 버전(일부 엔터프라이즈 기능은 비활성화됨). Contrast CE는 Java 및 .NET만 지원합니다. + +여기에서 찾을 수 있습니다. https://www.contrastsecurity.com/contrast-community-edition + +[20일차](day20.md)에 뵙겠습니다. diff --git a/2023/ko/days/day20.md b/2023/ko/days/day20.md new file mode 100644 index 0000000..bcfd24b --- /dev/null +++ b/2023/ko/days/day20.md @@ -0,0 +1,155 @@ +# IAST와 DAST의 결합 - 실습 시간 + +IAST와 DAST가 무엇인지 배웠다면 이제 실제 애플리케이션에서 이 프로세스를 사용하여 취약점을 찾아보는 실습을 해보겠습니다. + +**참고: 오픈 소스 IAST 구현이 없으므로 상용 솔루션을 사용해야 합니다. +무료 티어가 있으므로 비용을 지불하지 않고도 실습을 따라갈 수 있으니 걱정하지 마세요. + + + +여기에는 테스트하고 활용할 취약한 Java 애플리케이션, 손쉬운 설정을 위한 Docker 및 Docker Compose, IAST 솔루션용 [Contrast Community Edition](https://www.contrastsecurity.com/contrast-community-edition?utm_campaign=ContrastCommunityEdition&utm_source=GitHub&utm_medium=WebGoatLab)이 포함되어 있습니다. + +## 전제조건 + +- [Docker](https://www.docker.com/products/docker-desktop/) +- [Docker Compose](https://docs.docker.com/compose/) +- Contrast CE 계정. [이 곳](https://www.contrastsecurity.com/contrast-community-edition?utm_campaign=ContrastCommunityEdition&utm_source=GitHub&utm_medium=WebGoatLab)에서 무료로 회원가입하세요. + +**참고** : 이 글과 90일간의 데브옵스 프로그램의 작성자는 Contrast Security와 어떤 식으로든 관련이 있거나 관련이 있습니다. +오픈 소스 솔루션이 없고, 이 솔루션에는 결제나 신용카드 제공이 필요 없는 무료 티어가 있기 때문에 이 상용 솔루션을 사용하고 있습니다. + +1. 오픈 소스 IAST 구현이 없기 때문에 일부 무료 라이선스가 있는 상용 소스를 사용합니다. 이를 위해 2 개의 구성 요소가 필요합니다: + IAST 솔루션 - . Mac 또는 Linux 환경에 설치된 docker 및 docker-compose가 필요합니다(이 실습은 Mint에서 테스트되었습니다). README를 따라 Contrast에서 계정을 생성하세요. + +## Getting started + + +시작하려면 [리포지토리](https://github.com/rstatsinger/contrast-java-webgoat-docker)를 복제합니다. + +Contrast Security에서 자격 증명을 받습니다. +오른쪽 상단의 `Organization Settings` -> `Agent`에서 당신의 이름을 클릭합니다. +그리고 `Agent Username`, `Agent Service Key` and `API Key`를 가져옵니다. +새로 복제된 리포지토리의 `.env.template` 파일에서 이 값으로 바꿉니다. + +**참고:** 이 값은 비밀입니다. +Git에 커밋하지 마세요. +실수로 이 값을 커밋하지 않도록 `.env.template`을 `.gitignore` 아래에 두는 것이 가장 좋습니다. + + +## 취약한 애플리케이션 실행하기 + +취약한 애플리케이션을 실행합니다. + +```sh +./run.sh +``` + +또는 + +```sh +docker compose up +``` + +준비가 완료되면 에서 애플리케이션 UI에 액세스할 수 있습니다. + +## 피해 입히기 + +이제 취약한 애플리케이션이 생겼으니 이를 익스플로잇해 보겠습니다. + +1. [여기](https://www.zaproxy.org/download/)에서 ZAP 프록시를 설치합니다. + + 가장 쉬운 방법은 DAST 스캐너를 이용하는 것입니다. + 이러한 스캐너 중 하나는 [ZAP Proxy](https://www.zaproxy.org/)입니다. + 무료 오픈소스 웹 앱 스캐너입니다. + +2. [여기](https://github.com/Grunny/zap-cli)에서 `zap-cli`를 설치합니다. + + 다음으로 `zap-cli`를 설치합니다. + `zap-cli`는 ZAP Proxy를 위한 오픈소스 CLI입니다. + +3. ZAP 프록시 실행 + + 설치된 위치에서 ZAP 프록시를 실행합니다. + Linux Mint에서는 기본적으로 `/opt/zaproxy`에 있습니다. + MacOS에서는 `Applications`에 있습니다. + +4. `ZAP_API_KEY` 및 `ZAP_PORT`에 대한 환경 변수를 설정합니다. + + ZAP 프록시에서 이 값을 가져옵니다. + `Options...` -> `API`로 이동하여 API 키를 가져옵니다. + + `Options...` -> `Network` -> `Local Servers/Proxies`로 이동하여 포트를 설정하고 가져옵니다. + +5. `zap-cli`로 몇 가지 명령을 실행합니다. + + 예시: + + ```sh + zap-cli quick-scan -s all --ajax-spider -r http://127.0.0.1:8080/WebGoat/login.mvc + ``` + + 또는 [리포지토리](https://github.com/rstatsinger/contrast-java-webgoat-docker/blob/master/Lab-WebGoat.pdf)에 있는 지침에 따라 취약한 애플리케이션을 손상시킬 수 있습니다. + +6. Constrast에서 결과 관찰 + + 어느 쪽이든, Contrast에서 애플리케이션의 **Vulnerabilities** 탭으로 이동하면, Contrast가 취약점을 감지한 것을 확인할 수 있을 것입니다. + 조치를 취하라는 경고가 표시됩니다. + +## 보너스: 이미지 스캐닝 + +애플리케이션의 동작을 관찰하여 공격을 탐지하는 데 IAST 솔루션이 어떻게 도움이 되었는지 살펴보았습니다. +이러한 공격을 애초에 막을 수 있었는지 살펴봅시다. + +이 데모에 사용한 취약한 애플리케이션은 컨테이너로 된 패키지였습니다. +[14일차](day14.md)와 [15일차](day15.md)에서 배운 `grype` 스캐너를 통해 이 컨테이너를 스캔하고 결과를 확인해 보겠습니다. + +```sh +$ grype contrast-java-webgoat-docker-webgoat + ✔ Vulnerability DB [no update available] + ✔ Loaded image + ✔ Parsed image + ✔ Cataloged packages [316 packages] + ✔ Scanned image [374 vulnerabilities] +NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY +apt 1.8.2.3 deb CVE-2011-3374 Negligible +axis 1.4 java-archive GHSA-55w9-c3g2-4rrh Medium +axis 1.4 java-archive GHSA-96jq-75wh-2658 Medium +bash 5.0-4 deb CVE-2019-18276 Negligible +bash 5.0-4 (won't fix) deb CVE-2022-3715 High +bsdutils 1:2.33.1-0.1 deb CVE-2022-0563 Negligible +bsdutils 1:2.33.1-0.1 (won't fix) deb CVE-2021-37600 Low +commons-beanutils 1.8.3 java-archive CVE-2014-0114 High +commons-beanutils 1.8.3 java-archive CVE-2019-10086 High +commons-beanutils 1.8.3 1.9.2 java-archive GHSA-p66x-2cv9-qq3v High +commons-beanutils 1.8.3 1.9.4 java-archive GHSA-6phf-73q6-gh87 High +commons-collections 3.2.1 java-archive CVE-2015-6420 High +commons-collections 3.2.1 3.2.2 java-archive GHSA-6hgm-866r-3cjv High +commons-collections 3.2.1 3.2.2 java-archive GHSA-fjq5-5j5f-mvxh Critical +commons-fileupload 1.3.1 java-archive CVE-2016-1000031 Critical +commons-fileupload 1.3.1 java-archive CVE-2016-3092 High +commons-fileupload 1.3.1 1.3.2 java-archive GHSA-fvm3-cfvj-gxqq High +commons-fileupload 1.3.1 1.3.3 java-archive GHSA-7x9j-7223-rg5m Critical +commons-io 2.4 java-archive CVE-2021-29425 Medium +commons-io 2.4 2.7 java-archive GHSA-gwrp-pvrq-jmwv Medium +coreutils 8.30-3 deb CVE-2017-18018 Negligible +coreutils 8.30-3 (won't fix) deb CVE-2016-2781 Low +curl 7.64.0-4+deb10u3 deb CVE-2021-22922 Negligible +curl 7.64.0-4+deb10u3 deb CVE-2021-22923 Negligible + +``` + +보시다시피 이 이미지는 취약점으로 가득 차 있습니다. + +각 취약점을 자세히 살펴보면 RCE(원격 코드 실행), SQL 인젝션, XML 외부 엔티티 취약점 등과 같은 취약점이 있음을 알 수 있습니다. + +## 주간 요약 + +IAST와 DAST는 애플리케이션의 동작을 모니터링하여 애플리케이션의 취약점을 찾는 데 도움이 되는 중요한 방법입니다. +이 작업은 애플리케이션이 이미 배포된 후에 수행됩니다. + +컨테이너 이미지 스캔은 컨테이너 내부에 있는 라이브러리를 기반으로 애플리케이션의 취약점을 찾는 데 도움이 될 수 있습니다. + +이미지 스캔과 IAST/DAST는 상호 배타적이지 않습니다. +둘 다 보안 SDLC에서 각자의 역할을 하며 공격자보다 먼저 다양한 문제를 발견하는 데 도움이 될 수 있습니다. + +[21일차](day21.md)에 뵙겠습니다. diff --git a/2023/vi/2023.md b/2023/vi/2023.md new file mode 100644 index 0000000..72b9f5f --- /dev/null +++ b/2023/vi/2023.md @@ -0,0 +1,170 @@ +# 90DaysOfDevOps + +

+ 90DaysOfDevOps Logo +

+ +English Version | [한국어](2023/ko/README.md) | [Tiếng Việt](/2023/vi/2023.md) + +Dự án này được sử dụng để làm tư liệu cho chuyến hành trình có được nền tảng kiến thức tốt về “DevOps của tôi. + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/N4N33YRCS) + +Nếu bạn có những thắc mắc và muốn tham gia thì hãy gia nhập vào discord, chia sẽ những thắc mắc và cũng như những câu chuyện của bạn với cộng đồng. + +[![](https://dcbadge.vercel.app/api/server/vqwPrNQsyK)](https://discord.gg/vqwPrNQsyK) + +Hoặc liên hệ chúng tôi trên Twitter, tên hay gọi của tôi là [@MichaelCade1](https://twitter.com/MichaelCade1) bạn có thể tìm ra tác giả phiên bản 2023 cũng như trên Twitter được liên kết ở ngay bên dưới. + +## Danh sách các chủ đề + +| Chủ đề | Tác giả | Thời gian | Twitter Handle | +| -------------------------------------- | ----------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------- | +| DevSecOps | Michael Cade | 1st Jan - 6th Jan | [@MichaelCade1](https://twitter.com/MichaelCade1) | +| Secure Coding | Prateek Jain | 7th Jan - 13th Jan | [@PrateekJainDev](https://twitter.com/PrateekJainDev) | +| Continuous Build, Integration, Testing | Anton Sankov and Svetlomir Balevski | 14th Jan - 20th Jan | [@a_sankov](https://twitter.com/a_sankov) | +| Continuous Delivery & Deployment | Anton Sankov | 21st Jan - 27th Jan | [@a_sankov](https://twitter.com/a_sankov) | +| Runtime Defence & Monitoring | Ben Hirschberg | 28th Jan - 3rd Feb | [@slashben81](https://twitter.com/slashben81) | +| Secrets Management | Bryan Krausen | 4th Feb - 10th Feb | [@btkrausen](https://twitter.com/btkrausen) | +| Python | Rishab Kumar | 11th Feb - 17th Feb | [@rishabk7](https://twitter.com/rishabk7) | +| AWS | Chris Williams | 18th Feb - 24th Feb | [@mistwire](https://twitter.com/mistwire) | +| OpenShift | Dean Lewis | 25th Feb - 3rd Mar | [@saintdle](https://twitter.com/saintdle) | +| Databases | Taylor Riggan & Andrew Pruski | 4th Mar - 10th Mar | [@triggan](https://twitter.com/triggan) & [@dbafromthecold](https://twitter.com/dbafromthecold) | +| Serverless | Kristi Perreault | 11th Mar - 17th Mar | [@kperreault95](https://twitter.com/kperreault95) | +| Service Mesh | Marino Wijay | 18th Mar - 24th Mar | [@virtualized6ix](https://twitter.com/virtualized6ix) | +| Engineering for Day 2 Ops | Alistair Hey | 25th Mar - 31st Mar | [@alistair_hey](https://twitter.com/alistair_hey) | + +## Progress + +- [✔️] ♾️ 1 > [Nhìn lại 2022 & Chào đón 2023](2023/day01.md) + +### DevSecOps + +- [✔️] ♾️ 2 > [The Big Picture: DevSecOps](2023/day02.md) +- [✔️] ♾️ 3 > [Think like an Attacker](2023/day03.md) +- [✔️] ♾️ 4 > [Red Team vs. Blue Team](2023/day04.md) +- [✔️] ♾️ 5 > [OpenSource Security](2023/day05.md) +- [✔️] ♾️ 6 > [Hands-On: Building a weak app](2023/day06.md) + +### Secure Coding + +- [✔️] 🔐 7 > [Secure Coding Overview](2023/day07.md) +- [✔️] 🔐 8 > [SAST Overview](2023/day08.md) +- [✔️] 🔐 9 > [SAST Implementation with SonarCloud](2023/day09.md) +- [✔️] 🔐 10 > [Software Composition Analysis Overview](2023/day10.md) +- [✔️] 🔐 11 > [SCA Implementation with OWASP Dependency Check](2023/day11.md) +- [✔️] 🔐 12 > [Secure Coding Practices](2023/day12.md) +- [✔️] 🔐 13 > [Additional Secure Coding Practices](2023/day13.md) + +### Continuous Build, Integration, Testing + +- [✔️] ⚒️ > [Container Image Scanning](2023/day14.md) +- [✔️] ⚒️ > [Container Image Scanning Advanced](2023/day15.md) +- [✔️] ⚒️ > [Fuzzing](2023/day16.md) +- [✔️] ⚒️ > [Fuzzing Advanced](2023/day17.md) +- [✔️] ⚒️ > [DAST](2023/day18.md) +- [✔️] ⚒️ > [IAST](2023/day19.md) +- [✔️] ⚒️ > [Practical Lab on IAST and DAST](2023/day20.md) + +### Continuous Delivery & Deployment + +- [✔️] 🚚 21 > [Continuous Image Repository Scan](2023/day21.md) +- [✔️] 🚚 22 > [Continuous Image Repository Scan - Container Registries](2023/day22.md) +- [✔️] 🚚 23 > [Artifacts Scan](2023/day23.md) +- [✔️] 🚚 24 > [Signing](2023/day24.md) +- [✔️] 🚚 25 > [Systems Vulnerability Scanning](2023/day25.md) +- [✔️] 🚚 26 > [Containers Vulnerability Scanning](2023/day26.md) +- [✔️] 🚚 27 > [Network Vulnerability Scan](2023/day27.md) + +### Runtime Defence & Monitoring + +- [✔️] 🏃 28 > [System monitoring and auditing](2023/day28.md) +- [✔️] 🏃 29 > [Application level monitoring](2023/day29.md) +- [✔️] 🏃 30 > [Detecting suspicious application behavior](2023/day30.md) +- [✔️] 🏃 31 > [Runtime network protections and policies](2023/day31.md) +- [✔️] 🏃 32 > [Vulnerability and patch management](2023/day32.md) +- [✔️] 🏃 33 > [Application runtime and network policies](2023/day33.md) +- [✔️] 🏃 34 > [Runtime access control](2023/day34.md) + +### Secrets Management + +- [✔️] 🕵 35 > [Understanding the Importance of Secrets Management](2023/day35.md) +- [✔️] 🕵 36 > [Securing Secrets with HashiCorp Vault](2023/day36.md) +- [✔️] 🕵 37 > [Working with HashiCorp Vault's Secrets Engines](2023/day37.md) +- [✔️] 🕵 38 > [Increase the Security Posture of Your Organization with Dynamic Credentials](2023/day38.md) +- [✔️] 🕵 39 > [Getting Hands-On with HashiCorp Vault](2023/day39.md) +- [] 🕵 40 > [](2023/day40.md) +- [] 🕵 41 > [](2023/day41.md) + +### Python + +- [✔️] 🐍 42 > [Programming Language: Introduction to Python](2023/day42.md) +- [✔️] 🐍 43 > [Python Loops, functions, modules and libraries](2023/day43.md) +- [✔️] 🐍 44 > [Data Structures and OOP in Python](2023/day44.md) +- [✔️] 🐍 45 > [Debugging, testing and Regular expression](2023/day45.md) +- [✔️] 🐍 46 > [Web development in Python](2023/day46.md) +- [✔️] 🐍 47 > [Automation with Python](2023/day47.md) +- [✔️] 🐍 48 > [Let's build an App in Python](2023/day48.md) + +### AWS + +- [✔️] ☁️ 49 > [AWS Cloud Overview](2023/day49.md) +- [✔️] ☁️ 50 > [Create Free Tier Account & Enable Billing Alarms](2023/day50.md) +- [✔️] ☁️ 51 > [Infrastructure as Code (IaC) and CloudFormation](2023/day51.md) +- [✔️] ☁️ 52 > [Identity and Access Management (IAM)](2023/day52.md) +- [✔️] ☁️ 53 > [AWS Systems Manager](2023/day53.md) +- [✔️] ☁️ 54 > [AWS CodeCommit](2023/day54.md) +- [✔️] ☁️ 55 > [AWS CodePipeline](2023/day55.md) + +### Red Hat OpenShift + +- [✔️] ⛑️ 56 > [What does Red Hat OpenShift bring to the party? An Overview](2023/day56.md) +- [✔️] ⛑️ 57 > [Understanding the OpenShift Architecture, Installation Methods and Process](2023/day57.md) +- [✔️] ⛑️ 58 > [Deploying Red Hat OpenShift on VMware vSphere](2023/day58.md) +- [✔️] ⛑️ 59 > [Deploying applications and getting a handle on Security Constraints Context (SCC)](2023/day59.md) +- [✔️] ⛑️ 60 > [Looking at OpenShift Projects - Creation, Configuration and Governance](2023/day60.md) +- [✔️] ⛑️ 61 > [Understanding Authentication, Role-Based Access Control (RBAC) and Auditing in Red Hat OpenShift: Control and Secure Your Cluster](2023/day61.md) +- [✔️] ⛑️ 62 > [Compliance and Vulnerability Scanning provided by Red Hat OpenShift Operators](2023/day62.md) + +### Databases + +- [✔️] 🛢 63 > [An introduction to databases](2023/day63.md) +- [✔️] 🛢 64 > [Querying data in databases](2023/day64.md) +- [✔️] 🛢 65 > [Backing up and restoring databases](2023/day65.md) +- [✔️] 🛢 66 > [High availability and disaster recovery](2023/day66.md) +- [✔️] 🛢 67 > [Performance tuning](2023/day67.md) +- [✔️] 🛢 68 > [Database security](2023/day68.md) +- [✔️] 🛢 69 > [Monitoring and troubleshooting database issues](2023/day69.md) + +### Serverless + +- [✔️] 👩🏿‍💻 70 > [What is Serverless?](2023/day70.md) +- [✔️] 👩🏿‍💻 71 > [Serverless Compute](2023/day71.md) +- [✔️] 👩🏿‍💻 72 > [Serverless Storage](2023/day72.md) +- [✔️] 👩🏿‍💻 73 > [Serverless APIs](2023/day73.md) +- [✔️] 👩🏿‍💻 74 > [Serverless Orchestration](2023/day74.md) +- [✔️] 👩🏿‍💻 75 > [Serverless & Well Architected](2023/day75.md) +- [✔️] 👩🏿‍💻 76 > [Serverless - Beyond the Basics](2023/day76.md) + +### Service Mesh + +- [✔️] 🧩 77 > [Let's break down a Service Mesh](2023/day77.md) +- [✔️] 🧩 78 > [Install and Test a Service Mesh](2023/day78.md) +- [✔️] 🧩 79 > [Comparing Different Service Meshes](2023/day79.md) +- [✔️] 🧩 80 > [Traffic Engineering Basics](2023/day80.md) +- [✔️] 🧩 81 > [Observability in your Mesh](2023/day81.md) +- [✔️] 🧩 82 > [Securing your microservices](2023/day82.md) +- [✔️] 🧩 83 > [Sidecar or Sidecar-less? Enter Ambient Mesh](2023/day83.md) + +### Engineering for Day 2 Ops + +- [✔️] 👷🏻‍♀️ 84 > [Writing an API - What is an API?](2023/day84.md) +- [✔️] 👷🏻‍♀️ 85 > [Queues, Queue workers and Tasks (Asynchronous architecture)](2023/day85.md) +- [✔️] 👷🏻‍♀️ 86 > [Designing for Resilience, Redundancy and Reliability](2023/day86.md) +- [✔️] 👷🏻‍♀️ 87 > [Zero Downtime Deployments](2023/day87.md) +- [✔️] 👷🏻‍♀️ 88 > [Monitoring, Alerting and On-Call](2023/day88.md) +- [✔️] 👷🏻‍♀️ 89 > [Oops: When something goes wrong - Post Mortems](2023/day89.md) + +### 2023 wrap up + +- [✔️] 🏁 90 > [Wrapping up the 2023 edition](2023/day90.md) diff --git a/2023/vi/2023.png b/2023/vi/2023.png new file mode 100644 index 0000000..8533dfa Binary files /dev/null and b/2023/vi/2023.png differ diff --git a/2023/vi/days/day01.md b/2023/vi/days/day01.md new file mode 100644 index 0000000..043d8aa --- /dev/null +++ b/2023/vi/days/day01.md @@ -0,0 +1,67 @@ +## Nhìn lại 2022 & Chào đón 2023 + +Chào mọi người và mừng trở lại với phiên bản 2023 #90DaysOfDevOps trong bài đăng Ngày 1 này, kế hoạch là nhìn lại phiên bản năm 2022, một vài thống kê, phản hồi và những ý tưởng mà chúng ta đã có trong suốt năm qua. + +### Tóm tắt 2022 + +Đầu tiên, WAO! Nhớ đến công việc này mà tôi đã nghĩ ra ở giao thừa 2021 là dành ra 90 ngày đầu của năm 2022 để học và tổng hợp tư liệu, ghi chú một cách cơ bản sau khi xem nhiều người cực kì giỏi hơn tôi trên Youtube. + +Một năm nhanh chóng, chúng ta có khá nhiều con số ấn tượng ở dự án này, tôi nghĩ tôi đã đề cập ít nhất ở nơi đâu đó trong dự án, nhưng tôi chắc rằng tôi đã từng đề cập ở chỗ khác rất nhiều lần là bất kì nội dung nào mà giúp được thậm chí dù chỉ một người thì nó rất xứng đáng để làm, quả là đáng kinh ngạc khi có được những con số như này từ khi dự án chúng ta được đánh dấu (stars) đến khi được phân nhánh copy từ người khác (folks). + +![](images/day01-1.jpg) + +Cũng như, gần **500** người theo dõi dự án này. + +Điều đầu tiên, tôi muốn chân thành cảm ơn tất cả mọi người vì đã chia sẻ dự án này với cộng đồng. Thật là tuyệt với khi nghe rằng Microsoft và những nhà cung cấp công nghệ lớn khác đã chia sẻ dự án này với đội ngũ của họ. + +Điều thứ hai, tôi rất muốn cảm ơn những người đã đóng góp vào dự án. Điều này đã làm nên một nới mà ta có thể ghi chép cũng như học hỏi một cách minh bạch, cho đến khi có người bắt gặp lỗi sai chính tả cũng như ngữ pháp của tôi và chỉnh nó. (Tôi chắc rằng điều tương tự sẽ diễn ra trong năm nay) Nhưng điều quan trọng và thú vị nhất là cộng đồng này đã bắt đầu phiên dịch dự án này thành ngôn ngữ bản địa của họ! Thật là tuyệt +vời khi nghĩ điều này đang đã đang diễn ra và giúp những người nói tiếng anh bản xứ học nhiều hơn về sức mạnh tuyệt vời của DevOps. + +![](images/day01-2.png) + +Nếu bạn muốn tìm hiểu về những người đã đóng góp vào dự án, thì bạn có thể đến với [Contributors](https://github.com/MichaelCade/90DaysOfDevOps/blob/main/Contributors.md) + +### Tiếp tục học hỏi + +Tôi đã đề cập và nhấn mạnh rằng việc học không bao giờ là đủ, nếu bạn cho rằng là không phải, thì bạn đã chọn sai ngành vì tất cả mọi thứ ở ngành này điều thay đổi với một tốc độ cách nhanh chóng theo thời gian. + +Nó là lý do vì sao chúng ta phải tiếp tục học, học nữa và nó cũng chính là thử thách cho mỗi người, tôi khuyến khích bạn tìm cho mình một môi trường mà bạn cảm thấy hứng thú. Tôi đã rất say mê tổng hợp tài liệu về những thứ mà tôi học như dự án DevOps này chẳng hạn và bắt tay vào làm nó. Bước tiền đề của dự án này chính xác là nó, chính là nền tảng kiến thức cốt lõi của lĩnh vực DevOps và những công cụ giúp lãnh hội điều ấy, nếu bạn nghĩ rằng bạn sẽ tốt nghiệp và trở thành một kỹ sư DevOps khi học xong dự án này thì có lẽ sẽ không phải, nhưng việc trở nên am hiểu hơn về những thuật ngữ và sẵn sàng tiếp cận thực hành với nhiều công nghệ mà có thể trong cuộc sống hàng ngày bạn không nghĩ đến. + +Tôi cũng mong muốn rằng mọi người sẽ tiếp tục phát triển bản thân và không ngừng học hỏi, không ngoài trừ bạn là một giám đốc công nghệ (CTO) của một công ty công nghệ hay là một người điều hành hệ thống (SA) đang muốn học nhiều hơn về tự động hoá, thấy đó, tất cả mọi người đều đang học hỏi, +hay một số nhỏ nghĩ rằng điều ấy quá sức với mình (hội chứng kẻ giả mạo) nhưng điều ấy hoàn toàn bình thường bạn ạ. Lời khuyên của tôi đó là cứ tiến thẳng về phía trước, đừng nghĩ về những thứ tiêu cực như ấy và bạn sẽ chắc chắn gặt hái được nhiều thành công, cũng như học được những thứ như này giúp bạn hứng thú hơn khi học điều gì đó. + +### Tập trung vào bảo mật + +Dành cho những người đã đi suốt chặng đường cùng dự án, bạn đã biết rằng thứ quan trọng mà chúng ta bỏ lỡ trong phiên bản 2022 là bảo mật đúng hơn là DevSecOps và cách chúng ta tích hợp bảo mật vào vòng đời vô hạn của DevOps để đảm bảo rằng chúng ta luôn nghĩ về bảo mật khi nhắc đến DevOps. + +Trong phiên bản 2023 này, chúng ta sẽ tiến thẳng vào các quy trình bảo mật, các quy tắc, bao gồm cả sự quan trọng DevSecOps và chúng ta sẽ bắt đầu với vài chủ đề mà chúng ta đã bỏ lỡ ở phần đầu. + +### Một vài sự giúp đỡ từ những người bạn của tôi + +Phiên bản 2022 giống với việc viết một bài đăng vào mỗi ngày. Chúng ta đã nỗ lực hơn 100k từ và nếu chúng ta chuẩn bị chuyển mình sang sách điện tử (eBook) là một sự lựa chọn và phần hướng dẫn có thể được tìm thấy trong dự án nếu bạn muốn nhưng bạn sẽ phải tìm hơn tổng 700 trang giấy A4. Cuốn sách điện tử này sẽ không bị lãng quên nên tôi đang chuẩn bị cho một phiên bản nhỏ hơn và có thể tôi sẽ dành tặng cho các bạn vài cuốn tại buổi hội thảo gần với bạn cùng với vài mẫu sticker độc đáo. + +Một sự thiếu sót của tôi có thể chính là tính xác thực của dự án này khi tôi mới đang bắt đầu nghiên cứu và tổng hợp chúng cũng như hành trình học hỏi của tôi ở nhiều khía cạnh khác của dự án này. + +Đây là hai lý do của việc ấy: + +1. Tôi nghĩ điều quan trọng để có được những quan điểm khác nhau về các chủ đề và cũng như chúng ta sẽ học hỏi một cách tốt nhất nếu nhận được những lời khuyên từ các chuyên gia đi trước về những chủ đề lĩnh vực liên quan sâu sắc. + +2. Một vài người bạn của tôi sẽ sẵn sàng giúp đỡ cộng đồng tiếp tục phát triển thương hiệu của họ đi lên và thậm chí diễn giả tại các sự kiện về những chủ đề của họ và có thể tiến xa hơn dự án này. + +Bạn có thể tìm thấy tác gỉa của phiên bản 2023 này ở ngay phần mở đầu của trang được liên kết đến thông tin liên hệ của họ. + +Tôi nghĩ nó cũng là lúc để làm rõ ràng về dự án này. Không một ai được trả công để viết, không ai được trả để nói về dự án này cả. Tôi đã được các nhãn hàng tiếp cần vài lần, nhưng mục đích ban đầu của dự án này là đảm bảo sự công bằng, bình đẳng và vì cộng đồng. Vâng, chúng ta đã sử dụng vài dự án và sản phẩm này từ đầu đến cuối, nhưng không một công ty nào quảng cáo hoặc có ý ngỏ lời với những gì chúng tôi đã viết lên. + +Cuối cùng, sự nghiệp của tôi tại Veeam Software, tôi thật là may mắn khi có một công ty hiểu cho tôi để hoà mình vào cộng đồng và thực hiện dự án mà không can thiệp vào. Tôi không làm việc 9-5 như truyền thống và tôi chắc rằng có rất nhiều người đọc điều này thì có lẽ không giống tôi, tôi làm việc khá là tự do để tạo nên những nội dung như này. + +### Tài nguyên + +Trong suốt dự án và ấn bản năm 2022 trước đó, bạn sẽ tìm thấy phần tài nguyên, đây là danh sách nội dung mà tôi hoặc các tác giả đồng nghiệp của tôi đã xem qua và nếu bạn muốn tìm hiểu thêm những nội dung bạn đang đọc tại đây, hãy truy cập nội dung này. + +Bạn có thể tìm thấy phiên bản 2022 [đây](https://github.com/MichaelCade/90DaysOfDevOps/blob/main/2022.md) + +Nhưng cũng có một số thành viên cộng đồng đang bận rộn trong công việc chuyển đổi và làm ra giao diện mới thông qua [Trang GitHub](https://www.90daysofdevops.com/#/) + +Trên [trang 2023](https://www.90daysofdevops.com/#/2023) bạn sẽ có thể tìm được nhiều cách để kết nối với cộng đồng. + +Như đã nói ở trên, chúng ta bắt đầu với [Ngày 2](day02.md). \ No newline at end of file diff --git a/2024.md b/2024.md index f82406c..d21a2be 100644 --- a/2024.md +++ b/2024.md @@ -20,137 +20,97 @@ If you have questions and want to get involved then join the discord and share y Or contact us via Twitter, my handle is [@MichaelCade1](https://twitter.com/MichaelCade1) you can find the authors for 2023 also on Twitter linked below. -## Progress +## Agenda -- [] ♾️ 1 > [](2024/day01.md) +## Agenda -### - -- [] ♾️ 2 > [](2024/day02.md) -- [] ♾️ 3 > [](2024/day03.md) -- [] ♾️ 4 > [](2024/day04.md) -- [] ♾️ 5 > [](2024/day05.md) -- [] ♾️ 6 > [](2024/day06.md) - -### - -- [] 🔐 7 > [](2024/day07.md) -- [] 🔐 8 > [](2024/day08.md) -- [] 🔐 9 > [](2024/day09.md) -- [] 🔐 10 > [](2024/day10.md) -- [] 🔐 11 > [](2024/day11.md) -- [] 🔐 12 > [](2024/day12.md) -- [] 🔐 13 > [](2024/day13.md) - -### - -- [] ⚒️ > [](2024/day14.md) -- [] ⚒️ > [](2024/day15.md) -- [] ⚒️ > [](2024/day16.md) -- [] ⚒️ > [](2024/day17.md) -- [] ⚒️ > [](2024/day18.md) -- [] ⚒️ > [](2024/day19.md) -- [] ⚒️ > [](2024/day20.md) - -### - -- [] 🚚 21 > [](2024/day21.md) -- [] 🚚 22 > [](2024/day22.md) -- [] 🚚 23 > [](2024/day23.md) -- [] 🚚 24 > [](2024/day24.md) -- [] 🚚 25 > [](2024/day25.md) -- [] 🚚 26 > [](2024/day26.md) -- [] 🚚 27 > [](2024/day27.md) - -### - -- [] 🏃 28 > [](2024/day28.md) -- [] 🏃 29 > [](2024/day29.md) -- [] 🏃 30 > [](2024/day30.md) -- [] 🏃 31 > [](2024/day31.md) -- [] 🏃 32 > [](2024/day32.md) -- [] 🏃 33 > [](2024/day33.md) -- [] 🏃 34 > [](2024/day34.md) - -### - -- [] 🕵 35 > [](2024/day35.md) -- [] 🕵 36 > [](2024/day36.md) -- [] 🕵 37 > [](2024/day37.md) -- [] 🕵 38 > [](2024/day38.md) -- [] 🕵 39 > [](2024/day39.md) -- [] 🕵 40 > [](2024/day40.md) -- [] 🕵 41 > [](2024/day41.md) - -### - -- [] 🐍 42 > [](2024/day42.md) -- [] 🐍 43 > [](2024/day43.md) -- [] 🐍 44 > [](2024/day44.md) -- [] 🐍 45 > [](2024/day45.md) -- [] 🐍 46 > [](2024/day46.md) -- [] 🐍 47 > [](2024/day47.md) -- [] 🐍 48 > [](2024/day48.md) - -### - -- [] ☁️ 49 > [](2024/day49.md) -- [] ☁️ 50 > [](2024/day50.md) -- [] ☁️ 51 > [](2024/day51.md) -- [] ☁️ 52 > [](2024/day52.md) -- [] ☁️ 53 > [](2024/day53.md) -- [] ☁️ 54 > [](2024/day54.md) -- [] ☁️ 55 > [](2024/day55.md) - -### - -- [] ⛑️ 56 > [](2024/day56.md) -- [] ⛑️ 57 > [](2024/day57.md) -- [] ⛑️ 58 > [](2024/day58.md) -- [] ⛑️ 59 > [](2024/day59.md) -- [] ⛑️ 60 > [](2024/day60.md) -- [] ⛑️ 61 > [](2024/day61.md) -- [] ⛑️ 62 > [](2024/day62.md) - -### - -- [] 🛢 63 > [](2024/day63.md) -- [] 🛢 64 > [](2024/day64.md) -- [] 🛢 65 > [](2024/day65.md) -- [] 🛢 66 > [](2024/day66.md) -- [] 🛢 67 > [](2024/day67.md) -- [] 🛢 68 > [](2024/day68.md) -- [] 🛢 69 > [](2024/day69.md) - -### - -- [] 👩🏿‍💻 70 > [](2024/day70.md) -- [] 👩🏿‍💻 71 > [](2024/day71.md) -- [] 👩🏿‍💻 72 > [](2024/day72.md) -- [] 👩🏿‍💻 73 > [](2024/day73.md) -- [] 👩🏿‍💻 74 > [](2024/day74.md) -- [] 👩🏿‍💻 75 > [](2024/day75.md) -- [] 👩🏿‍💻 76 > [](2024/day76.md) - -### - -- [] 🧩 77 > [](2024/day77.md) -- [] 🧩 78 > [](2024/day78.md) -- [] 🧩 79 > [](2024/day79.md) -- [] 🧩 80 > [](2024/day80.md) -- [] 🧩 81 > [](2024/day81.md) -- [] 🧩 82 > [](2024/day82.md) -- [] 🧩 83 > [](2024/day83.md) - -### - - -- [] 👷🏻‍♀️ 84 > [](2024/day84.md) -- [] 👷🏻‍♀️ 85 > [](2024/day85.md) -- [] 👷🏻‍♀️ 86 > [](2024/day86.md) -- [] 👷🏻‍♀️ 87 > [](2024/day87.md) -- [] 👷🏻‍♀️ 88 > [](2024/day88.md) -- [] 👷🏻‍♀️ 89 > [](2024/day89.md) - -### -- [] 🏁 90 > [](2024/day90.md) +- [x] ♾️ 1 > [Day 1](2024/day01.md) +- [ ] ♾️ 2 > [The Digital Factory](2024/day02.md) - Romano Roth +- [ ] ♾️ 3 > [High-performing engineering teams and the Holy Grail](2024/day03.md) - Jeremy Meiss +- [ ] ♾️ 4 > [Manage Kubernetes Add-Ons for Multiple Clusters Using Cluster Run-Time State](2024/day04.md) - Gianluca Mardente +- [ ] ♾️ 5 > [Cross-functional empathy](2024/day05.md) - Chris Kranz +- [ ] ♾️ 6 > [DevSecOps - Defined, Explained & Explored](2024/day06.md) - Sameer Paradkar +- [ ] ♾️ 7 > [Advanced Code Coverage with Jenkins and API Mocking](2024/day07.md) - Oleg Nenashev +- [ ] ♾️ 8 > [Azure ARM now got Bicep](2024/day08.md) - Tushar Kumar +- [ ] ♾️ 9 > [GitOps: The next Frontier in DevOps!](2024/day09.md) - Megha Kadur +- [ ] ♾️ 10 > [Is Kubernetes Too Complicated? No, And Here's Why](2024/day10.md) - Julia Furst +- [ ] ♾️ 11 > [Architecting for Versatility](2024/day11.md) - Tim Banks +- [ ] ♾️ 12 > [Container Security for Enterprise Kubernetes environments](2024/day12.md) - Imran Roshan +- [ ] ♾️ 13 > [Automate like a pro: Dealing with test automation hassles](2024/day13.md) - Mesut Durukal +- [ ] ♾️ 14 > [Navigating Cloud-Native DevOps: Strategies for Seamless Deployment](2024/day14.md) - Yhorby Matias +- [ ] ♾️ 15 > [Building Resilience: A Journey of Crafting and Validating Our Disaster Recovery Plan](2024/day15.md) - Yedidya Schwartz +- [ ] ♾️ 16 > [Distracted Development](2024/day16.md) - Josh Ether +- [ ] ♾️ 17 > [Know your data: The Stats behind the Alerts](2024/day17.md) - Dave McAllister +- [ ] ♾️ 18 > [Continuous Delivery: From Distributed Monolith to Microservices as a unit of deployment](2024/day18.md) - Naresh Waswani +- [ ] ♾️ 19 > [An introduction to API Security in Kubernetes](2024/day19.md) - Geoff Burke +- [ ] ♾️ 20 > [Kunal Kushwaha](2024/day20.md) +- [ ] ♾️ 21 > [Smarter, Better, Faster, Stronger - Testing at Scale](2024/day21.md) - Ada Lündhé +- [ ] ♾️ 22 > [Test in Production with Kubernetes and Telepresence](2024/day22.md) - Mohammad-Ali A'râbi +- [ ] ♾️ 23 > [SQL Server 2022 on Linux Containers and Kubernetes from Zero to a Hero!](2024/day23.md) - Yitzhak David +- [ ] ♾️ 24 > [From Chaos to Resilience: Decoding the Secrets of Production Readiness](2024/day24.md) - Alejandro Pedraza Borrero +- [ ] ♾️ 25 > [Kube-Nation: Exploring the Land of Kubernetes](2024/day25.md) - Siddhant Khisty & Aakansha Priya +- [ ] ♾️ 26 > [Platform Engineering Is Not About Tech](2024/day26.md) - Nicolò Cambiaso Erizzo & Francesca Carta +- [ ] ♾️ 27 > [Automating cloud infrastructure with Ansible](2024/day27.md) - Soumyadip Chowdhury +- [ ] ♾️ 28 > [Policy-as-Code Super-Powers! Rethinking Modern IaC With Service Mesh And CNI](2024/day28.md) - Kat Morgan & Marino Wijay +- [ ] ♾️ 29 > [The Reverse Technology Thrust](2024/day29.md) - Rom Adams +- [ ] ♾️ 30 > [How GitHub delivers GitHub using GitHub](2024/day30.md) - April Edwards +- [ ] ♾️ 31 > [DevSecOps: Integrating Security into the DevOps Pipeline](2024/day31.md) - Reda Hajjami +- [ ] ♾️ 32 > [Cracking Cholera’s Code: Victorian Insights for Today’s Technologist](2024/day32.md) - Simon Copsey +- [ ] ♾️ 33 > [Building Efficient and Secure Docker Images with Multi-Stage Builds](2024/day33.md) - Pradumna V Saraf +- [ ] ♾️ 34 > [How to Implement Automated Deployment Pipelines for Your DevOps Projects](2024/day34.md) - Neel Shah +- [ ] ♾️ 35 > [Using code dependency analysis to decide what to test](2024/day35.md) - Patrick Kusebauch +- [ ] ♾️ 36 > [Exploring Firecracker](2024/day36.md) - Irine Kokilashvili +- [ ] ♾️ 37 > [Practical introduction to OpenTelemetry tracing](2024/day37.md) - Nicolas Fränkel +- [ ] ♾️ 38 > [Open Standards: Empowering Cloud-Native Innovation](2024/day38.md) - Kunal Verma +- [ ] ♾️ 39 > [DIs TLS in Kubernetes really that hard to understand?](2024/day39.md) - Shivang Shandilya +- [ ] ♾️ 40 > [Infrastructure as Code - A look at Azure Bicep and Terraform](2024/day40.md) - Sarah Lean +- [ ] ♾️ 41 > [Building Scalable Infrastructure For Advanced Air Mobility](2024/day41.md) - Dan Lambeth +- [ ] ♾️ 42 > [The North Star: Risk-driven security](2024/day42.md) - Jonny Tyers +- [ ] ♾️ 43 > [End to End Data Governance using AWS Serverless Stack](2024/day43.md) - Ankit Sheth +- [ ] ♾️ 44 > [The Lean DevOps Playbook: Make it a success from Day one](2024/day44.md) - Aman Sharma +- [ ] ♾️ 45 > [Microsoft DevOps Solutions or how to integrate the best of Azure DevOps and GitHub](2024/day45.md) - Peter De Tender +- [ ] ♾️ 46 > [Mastering AWS Systems Manager: Simplifying Infrastructure Management](2024/day46.md) - Adit Modi +- [ ] ♾️ 47 > [From Puddings to Platforms: Bringing Ideas to life with ChatGPT](2024/day47.md) - Anthony Spiteri +- [ ] ♾️ 48 > [Azure logic app, low / no code](2024/day48.md) - Ian Engelbrecht +- [ ] ♾️ 49 > [Enhancing DevOps with MLOps for GenAI and AI-Powered Solutions](2024/day49.md) - Azhar Amir +- [ ] ♾️ 50 > [State of cloud native 2024](2024/day50.md) - Saiyam Pathak +- [ ] ♾️ 51 > [PCI Compliance in the Cloud](2024/day51.md) - Barinua Kane +- [ ] ♾️ 52 > [Multi-Model Databases and its place in DevOps](2024/day52.md) - Pratim Bhosale +- [ ] ♾️ 53 > [Implementing SRE (Site Reliability Engineering)](2024/day53.md) - Andy Babiec +- [ ] ♾️ 54 > [Let's go sidecarless in Ambient Mesh!](2024/day54.md) - Leon Nunes +- [ ] ♾️ 55 > [Bringing Together IaC and CM with Terraform Provider for Ansible](2024/day55.md) - Razvan Ionescu +- [ ] ♾️ 56 > [Automated database deployment within the DevOps process](2024/day56.md) - Marc Müller +- [ ] ♾️ 57 > [Multi-Cloud Service Discovery and Load Balancing](2024/day57.md) - Vladislav Bilay +- [ ] ♾️ 58 > [OSV Scanner: A Powerful Tool for Open Source Security](2024/day58.md) - Paras Mamgain +- [ ] ♾️ 59 > [Continuous Delivery pipelines for cloud infrastructure](2024/day59.md) - Michael Lihs +- [ ] ♾️ 60 > [Migrating a monolith to Cloud-Native and the stumbling blocks that you don’t know about](2024/day60.md) - JJ Asghar +- [ ] ♾️ 61 > [Demystifying Modernisation: True Potential of Cloud Technology](2024/day61.md) - Anupam Phoghat +- [ ] ♾️ 62 > [Chatbots are going to destroy infrastructures and your cloud bills](2024/day62.md) - Stanislas Girard +- [ ] ♾️ 63 > [Introduction to Database Operators for Kubernetes](2024/day63.md) - Juarez Junior +- [ ] ♾️ 64 > [The Invisible Guardians: Unveiling the Power of Monitoring and Observability in the Digital Age](2024/day64.md) - Santosh Kumar Perumal +- [ ] ♾️ 65 > [Azure pertinent DevOps for non-coders](2024/day65.md) - Sucheta Gawade +- [ ] ♾️ 66 > [A Developer's Journey to the DevOps: The Synergy of Two Worlds](2024/day66.md) - Jonah Andersson +- [ ] ♾️ 67 > [Art of DevOps: Harmonizing Code, Culture, and Continuous Delivery](2024/day67.md) - Rohit Ghumare +- [ ] ♾️ 68 > [Service Mesh for Kubernetes 101: The Secret Sauce to Effortless Microservices Management](2024/day68.md) - Mohd Imran +- [ ] ♾️ 69 > [Enhancing Kubernetes security, visibility, and networking control logic](2024/day69.md) - Dean Lewis +- [ ] ♾️ 70 > [Simplified Cloud Adoption with Microsoft's Terraforms Azure Landing Zone Module](2024/day70.md) - Simone Bennett +- [ ] ♾️ 71 > [Azure for DevSecOps Operators](2024/day71.md) - Kevin Evans +- [ ] ♾️ 72 > [Infrastructure as Code with Pulumi](2024/day72.md) - Scott Lowe +- [ ] ♾️ 73 > [E2E Test Before Merge](2024/day73.md) - Natalie Lunbeck +- [ ] ♾️ 74 > [Workload Identity Federation with Azure DevOps and Terraform](2024/day74.md) - Arindam Mitra +- [ ] ♾️ 75 > [Achieving Regulatory Compliance in Multi-Cloud Deployments with Terraform](2024/day75.md) - Eric Evans +- [ ] ♾️ 76 > [All you need to know about AWS CDK.](2024/day76.md) - Amogha Kancharla +- [ ] ♾️ 77 > [DConnect to Microsoft APIs in Azure DevOps Pipelines using Workload Identity Federation](2024/day77.md) - Jan Vidar Elven +- [ ] ♾️ 78 > [Scaling Terraform Deployments with GitHub Actions: Essential Configurations](2024/day78.md) - Thomas Thornton +- [ ] ♾️ 79 > [DevEdOps](2024/day79.md) - Adam Leskis +- [ ] ♾️ 80 > [Unlocking K8s Troubleshooting Best Practices with Botkube](2024/day80.md) - Maria Ashby +- [ ] ♾️ 81 > [Leveraging Kubernetes to build a better Cloud Native Development Experience](2024/day81.md) - Nitish Kumar +- [ ] ♾️ 82 > [Dev Containers in VS Code](2024/day82.md) - Chris Ayers +- [ ] ♾️ 83 > [IaC with Pulumi and GitHub Actions](2024/day83.md) - Till Spindler +- [ ] ♾️ 84 > [Hacking Kubernetes For Beginners](2024/day84.md) - Benoit Entzmann +- [ ] ♾️ 85 > [Reuse, Don't Repeat - Creating an Infrastructure as Code Module Library](2024/day85.md) - Sam Cogan +- [ ] ♾️ 86 > [Tools To Make Your Terminal DevOps and Kubernetes Friendly](2024/day86.md) - Maryam Tavakkoli +- [ ] ♾️ 87 > [Hands-on Performance Testing with k6](2024/day87.md) - Pepe Cano +- [ ] ♾️ 88 > [What Developers Want from Internal Developer Portals](2024/day88.md) - Ganesh Datta +- [ ] ♾️ 89 > [Seeding Infrastructures: Merging Terraform with Generative AI for Effortless DevOps Gardens](2024/day89.md) - Renaldi Gondosubroto +- [ ] ♾️ 90 > [](2024/day90.md) diff --git a/Resources.md b/Resources.md index a0b4176..eff931f 100644 --- a/Resources.md +++ b/Resources.md @@ -4,7 +4,7 @@ Day-01 - [https://www.youtube.com/watch?v=Xrgk023l4lI](https://www.youtube.com/watch?v=Xrgk023l4lI) DevOps in 5 Minutes - [https://www.youtube.com/watch?v=\_Gpe1Zn-1f&t=43s](https://www.youtube.com/watch?v=_Gpe1Zn-1fE&t=43s&ab_channel=HiteshChoudhary) What is DevOps? Easy Way -- [https://www.youtube.com/watch?v=7l_n97Mt0ko](tv) DevOps roadmap 2022 | Success Roadmap 2022 +- [https://www.youtube.com/watch?v=7l_n97Mt0ko](https://www.youtube.com/watch?v=7l_n97Mt0ko&t=16s) DevOps roadmap 2022 | Success Roadmap 2022 Day-02