Zabezpieczanie kompilacji kontenerów

Zabezpieczanie kompilacji kontenerów

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: mar 23, 2023
account_circleAutorzy: Christopher Grant

1. Wprowadzenie

ead1609267034bf7.png

Luki w zabezpieczeniach oprogramowania to luki, które mogą spowodować przypadkową awarię systemu lub ułatwić nieuczciwym podmiotom bezpieczeństwo oprogramowania. Container Analysis udostępnia 2 rodzaje skanowania systemu operacyjnego w celu znalezienia luk w zabezpieczeniach w kontenerach:

  • Interfejs On-Demand Scanning API umożliwia ręczne skanowanie obrazów kontenerów pod kątem luk w zabezpieczeniach systemu operacyjnego, zarówno lokalnie na komputerze, jak i zdalnie w Container Registry lub Artifact Registry.
  • Interfejs Container Scanning API umożliwia automatyzację wykrywania luk w zabezpieczeniach systemu operacyjnego przez skanowanie za każdym razem, gdy wypchniesz obraz do Container Registry lub Artifact Registry. Włączenie tego interfejsu API umożliwia też skanowanie pakietów językowych pod kątem luk w zabezpieczeniach w Go i Javie.

Interfejs On-Demand Scanning API umożliwia skanowanie obrazów przechowywanych lokalnie na komputerze lub zdalnie w Container Registry bądź Artifact Registry. Zapewnia to szczegółową kontrolę nad kontenerami, które chcesz skanować pod kątem luk w zabezpieczeniach. Za pomocą skanowania na żądanie możesz skanować obrazy w potoku CI/CD przed podjęciem decyzji, czy zapisać je w rejestrze.

Czego się nauczysz

W tym module:

  • Tworzenie obrazów za pomocą Cloud Build
  • Używanie Artifact Registry dla kontenerów
  • Korzystaj z automatycznego skanowania pod kątem luk w zabezpieczeniach
  • Skonfiguruj skanowanie na żądanie
  • Dodawanie skanowania obrazów w CICD w Cloud Build

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google. W każdej chwili możesz ją zmienić.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić (po jego ustawieniu nie można go zmienić). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń z programowania konieczne jest odwołanie się do identyfikatora projektu (zwykle nazywa się on PROJECT_ID). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować kolejny losowy. Możesz też spróbować własnych sił i sprawdzić, czy jest dostępna. Potem nie będzie można go zmienić. Pozostanie ono przez czas trwania projektu.
  • Dostępna jest trzecia wartość, numer projektu, z którego korzystają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Cloud/interfejsów API. Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Konfiguracja środowiska

W Cloud Shell ustaw identyfikator i numer projektu. Zapisz je jako zmienne PROJECT_ID i PROJECT_ID.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

Włączanie usług

Włącz wszystkie niezbędne usługi:

gcloud services enable \
  cloudkms.googleapis.com \
  cloudbuild.googleapis.com \
  container.googleapis.com \
  containerregistry.googleapis.com \
  artifactregistry.googleapis.com \
  containerscanning.googleapis.com \
  ondemandscanning.googleapis.com \
  binaryauthorization.googleapis.com

3. Tworzenie obrazów za pomocą Cloud Build

W tej sekcji utworzysz automatyczny potok kompilacji, który utworzy obraz kontenera, a następnie przeskanuj go i oceń wyniki. Jeśli nie zostaną wykryte kluczowe luki w zabezpieczeniach, obraz zostanie przeniesiony do repozytorium. W przypadku wykrycia KRYTYCZNYCH luk w zabezpieczeniach kompilacja zakończy się niepowodzeniem i zostanie zakończona.

Przyznaj dostęp kontu usługi Cloud Build

Cloud Build wymaga uprawnień dostępu do interfejsu API skanowania na żądanie. Przyznaj dostęp przy użyciu tych poleceń.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/iam.serviceAccountUser"
       
gcloud
projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/ondemandscanning.admin"

Tworzenie katalogu roboczego i przekształcanie go w katalog roboczy

mkdir vuln-scan && cd vuln-scan

Definiowanie przykładowego obrazu

Utwórz plik o nazwie Dockerfile z poniższą zawartością.

cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a

# System
RUN apt update && apt install python3-pip -y

# App
WORKDIR /app
COPY . ./

RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

EOF

Utwórz plik o nazwie main.py z następującą zawartością

cat > ./main.py << EOF
import os
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
   
name = os.environ.get("NAME", "Worlds")
   
return "Hello {}!".format(name)

if __name__ == "__main__":
   
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF

Tworzenie potoku Cloud Build

Poniższe polecenie utworzy w katalogu plik cloudbuild.yaml, który będzie używany w automatycznym procesie. W tym przykładzie kroki są ograniczone do procesu tworzenia kontenera. W praktyce oprócz kroków kontenera musisz jednak umieścić instrukcje i testy dotyczące konkretnej aplikacji.

Utwórz plik za pomocą tego polecenia.

cat > ./cloudbuild.yaml << EOF
steps
:

# build
- id: "build"
  name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor: ['-']


EOF

Uruchamianie potoku CI

Przesyłanie kompilacji do przetworzenia

gcloud builds submit

Sprawdź szczegóły kompilacji

Po rozpoczęciu procesu kompilacji sprawdź postęp w panelu Cloud Build.

  1. Otwórz Cloud Build w konsoli Cloud
  2. Kliknij kompilację, aby wyświetlić jej zawartość

4. Artifact Registry dla kontenerów

Tworzenie repozytorium Artifact Registry

W tym module będziesz używać Artifact Registry do przechowywania i skanowania obrazów. Utwórz repozytorium za pomocą tego polecenia.

gcloud artifacts repositories create artifact-scanning-repo \
 
--repository-format=docker \
 
--location=us-central1 \
 
--description="Docker repository"

Skonfiguruj Dockera tak, aby wykorzystywał dane logowania gcloud podczas uzyskiwania dostępu do Artifact Registry.

gcloud auth configure-docker us-central1-docker.pkg.dev

Aktualizowanie potoku Cloud Build

Zmodyfikuj potok kompilacji, aby przekazać wynikowy obraz do Artifact Registry

cat > ./cloudbuild.yaml << EOF
steps
:

# build
- id: "build"
  name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor: ['-']

# push to artifact registry
- id: "push"
  name: 'gcr.io/cloud-builders/docker'
  args: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image']

images
:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

Uruchamianie potoku CI

Przesyłanie kompilacji do przetworzenia

gcloud builds submit

5. Automatyczne skanowanie pod kątem luk w zabezpieczeniach

Skanowanie artefaktów jest aktywowane automatycznie za każdym razem, gdy wypchniesz nowy obraz do Artifact Registry lub Container Registry. Informacje o lukach w zabezpieczeniach są stale aktualizowane w przypadku wykrywania nowych luk. W tej sekcji przejrzysz obraz właśnie utworzony i przekazany do Artifact Registry oraz przeanalizujesz wyniki związane z lukami w zabezpieczeniach.

Sprawdź szczegóły obrazu

Po zakończeniu poprzedniego procesu kompilacji sprawdź obraz i wyniki luk w zabezpieczeniach w panelu Artifact Registry.

  1. Otwórz Artifact Registry w konsoli Cloud
  2. Kliknij repozytorium skanowania artefaktów, aby wyświetlić zawartość
  3. Kliknij szczegóły obrazu
  4. Kliknij najnowsze podsumowanie obrazu
  5. Po zakończeniu skanowania kliknij kartę Luki w zabezpieczeniach, aby wyświetlić obraz.

Na karcie Luki w zabezpieczeniach zobaczysz wyniki automatycznego skanowania utworzonego właśnie obrazu.

361be7b3bf293fca.png

Automatyzacja skanowania jest domyślnie włączona. Zapoznaj się z ustawieniami Artifact Registry, aby dowiedzieć się, jak włączyć lub wyłączyć skanowanie automatyczne.

6. Skanowanie na żądanie

W różnych sytuacjach konieczne może być przeskanowanie obrazu przed przekazaniem go do repozytorium. Programista kontenerów może na przykład przeskanować obraz i rozwiązać problemy przed przekazaniem kodu do elementu sterującego źródła. W przykładzie poniżej skompilujesz i przeanalizujesz obraz lokalnie, zanim zaczniesz korzystać z wyników.

Utwórz obraz

W tym kroku użyjesz lokalnego Dockera, aby utworzyć obraz w lokalnej pamięci podręcznej.

docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .

Zeskanuj obraz

Po utworzeniu obrazu poproś o jego zeskanowanie. Wyniki skanowania są przechowywane na serwerze metadanych. Zadanie zakończy się lokalizacją z wynikami na serwerze metadanych.

gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --format="value(response.scan)" > scan_id.txt

Sprawdź plik wyjściowy

Poświęć chwilę na zapoznanie się z danymi wyjściowymi poprzedniego kroku, które zostały zapisane w pliku scan_id.txt. Zwróć uwagę na lokalizację raportu wyników skanowania na serwerze metadanych.

cat scan_id.txt

Sprawdź szczegółowe wyniki skanowania

Aby wyświetlić rzeczywiste wyniki skanowania, użyj polecenia list-vulnerabilities w lokalizacji raportu podanej w pliku wyjściowym.

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) 

Dane wyjściowe zawierają znaczną ilość danych o wszystkich lukach w zabezpieczeniach obrazu.

Oznacz problemy krytyczne

Ludzie rzadko korzystają z danych przechowywanych w raporcie bezpośrednio. Zwykle wyniki są używane w ramach zautomatyzowanego procesu. Za pomocą poniższych poleceń przeczytaj szczegóły raportu i zarejestruj, czy zostały wykryte KRYTYCZNE luki w zabezpieczeniach

export SEVERITY=CRITICAL

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi

Wynikiem tego polecenia będzie

Failed vulnerability check for CRITICAL level

7. Skanowanie w CICD za pomocą Cloud Build

Przyznaj dostęp kontu usługi Cloud Build

Cloud Build wymaga uprawnień dostępu do interfejsu API skanowania na żądanie. Przyznaj dostęp przy użyciu tych poleceń.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/iam.serviceAccountUser"
       
gcloud
projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/ondemandscanning.admin"

Aktualizowanie potoku Cloud Build

Poniższe polecenie utworzy w katalogu plik cloudbuild.yaml, który będzie używany w automatycznym procesie. W tym przykładzie kroki są ograniczone do procesu tworzenia kontenera. W praktyce oprócz kroków kontenera musisz jednak umieścić instrukcje i testy dotyczące konkretnej aplikacji.

Utwórz plik za pomocą tego polecenia.

cat > ./cloudbuild.yaml << EOF
steps
:

# build
- id: "build"
  name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor: ['-']

#Run a vulnerability scan at _SECURITY level
- id: scan
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    (gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --location us \
    --format="value(response.scan)") > /workspace/scan_id.txt

#Analyze the result of the scan
- id: severity check
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
      gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
      --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
      then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi

#Retag
- id: "retag"
  name: 'gcr.io/cloud-builders/docker'
  args: ['tag',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#pushing to artifact registry
- id: "push"
  name: 'gcr.io/cloud-builders/docker'
  args: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']

images
:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

Uruchamianie potoku CI

Prześlij kompilację do przetworzenia, aby sprawdzić przerwy w działaniu kompilacji w przypadku wykrycia luki w zabezpieczeniach o znaczeniu KRYTYCZNYM.

gcloud builds submit

Sprawdź błąd kompilacji

Przesłana kompilacja zakończy się niepowodzeniem, ponieważ obraz zawiera krytyczne luki w zabezpieczeniach.

Sprawdź błąd kompilacji na stronie Historia Cloud Build

Usuwanie luki w zabezpieczeniach

Zaktualizuj plik Dockerfile, aby użyć obrazu podstawowego, który nie zawiera luk w zabezpieczeniach o charakterze krytycznym.

Zastąp plik Dockerfile, aby używać obrazu Debian 10 za pomocą tego polecenia

cat > ./Dockerfile << EOF
from python:3.8-slim  

# App
WORKDIR
/app
COPY
. ./

RUN pip3 install
Flask==2.1.0
RUN pip3 install gunicorn
==20.1.0

CMD
exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app

EOF

Uruchamianie procesu CI z użyciem prawidłowego obrazu

Prześlij kompilację do przetworzenia, aby sprawdzić, czy kompilacja się powiedzie, jeśli nie znajdziemy żadnych luk w zabezpieczeniach o poziomie krytycznym.

gcloud builds submit

Sprawdź udaną kompilację

Przesłana kompilacja zakończy się powodzeniem, ponieważ zaktualizowany obraz nie zawiera luk w zabezpieczeniach KRYTYCZNYCH.

Sprawdź udaną kompilację na stronie Historia Cloud Build

Sprawdź wyniki skanowania

Sprawdź dobry obraz w Artifact Registry

  1. Otwórz Artifact Registry w konsoli Cloud
  2. Kliknij repozytorium skanowania artefaktów, aby wyświetlić zawartość
  3. Kliknij szczegóły obrazu
  4. Kliknij najnowsze podsumowanie obrazu
  5. Kliknij kartę luk w zabezpieczeniach obrazu

8. Gratulacje!

Gratulacje. Udało Ci się ukończyć ćwiczenia z programowania.

Omówione zagadnienia:

  • Tworzenie obrazów za pomocą Cloud Build
  • Artifact Registry dla kontenerów
  • Automatyczne skanowanie pod kątem luk w zabezpieczeniach
  • Skanowanie na żądanie
  • Skanowanie w CICD za pomocą Cloud Build

Co dalej:

Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym samouczku, możesz usunąć projekt zawierający te zasoby lub zachować projekt i usunąć poszczególne zasoby.

Usuwam projekt

Najprostszym sposobem na uniknięcie płatności jest usunięcie projektu utworzonego na potrzeby samouczka.

Ostatnia aktualizacja: 21.03.2023 r.