Zabezpieczanie kompilacji kontenerów

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 – lokalnie na komputerze albo zdalnie w Container Registry lub Artifact Registry.
  • Interfejs Container Scanning API umożliwia automatyzację wykrywania luk w zabezpieczeniach systemu operacyjnego. Skanowanie odbywa się za każdym razem, gdy obraz jest przesyłany 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. Zanim zdecydujesz, czy chcesz je przechowywać w rejestrze, możesz zeskanować obrazy w potoku CI/CD za pomocą skanowania na żądanie.

Czego się nauczysz

W tym laboratorium:

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

2. Konfiguracja i wymagania

Konfigurowanie środowiska we własnym tempie

  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. Jest to ciąg znaków, którego nie używają interfejsy API Google. W każdej chwili możesz ją zmienić.
  • Identyfikator projektu jest niepowtarzalny w ramach wszystkich projektów Google Cloud i nie można go zmienić (po ustawieniu). 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ć rozliczenia w konsoli Cloud, aby korzystać z zasobów i interfejsów API Cloud. Przejście przez ten moduł Codelab nie powinno wiązać się z wielkimi kosztami, jeśli w ogóle z nimi będzie. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, możesz usunąć utworzone przez siebie 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 skompiluje obraz kontenera, zeskanuje go, a potem oceni wyniki. Jeśli nie zostaną znalezione żadne krytyczne luki, obraz zostanie przesłany do repozytorium. Jeśli zostaną znalezione luki CRITICAL, kompilacja zakończy się niepowodzeniem i zostanie zamknięta.

Przyznaj dostęp kontu usługi Cloud Build

Cloud Build będzie potrzebować uprawnień dostępu do interfejsu skanowania na żądanie. Aby przyznać dostęp, użyj 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 tą 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

Podane niżej polecenie utworzy w katalogu plik cloudbuild.yaml, który będzie używany w ramach procesu zautomatyzowanego. W tym przykładzie kroki są ograniczone do procesu tworzenia kontenera. W praktyce jednak oprócz instrukcji dotyczących kontenera należy dodać 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, aby używać danych 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 przesłać utworzony 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 uruchamiane automatycznie za każdym razem, gdy przesyłasz nowy obraz do Artifact Registry lub Container Registry. Informacje o lukach w zabezpieczeniach są stale aktualizowane w przypadku wykrywania nowych luk. W tej sekcji sprawdzisz obraz, który został właśnie utworzony i przesłany do Artifact Registry, oraz wyniki dotyczące podatności.

Sprawdź szczegóły obrazu

Po zakończeniu poprzedniego procesu kompilacji sprawdź obraz i wyniki dotyczące 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ę z podanymi wrażliwościami obrazu.

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

361be7b3bf293fca.png

Automatyczne skanowanie jest domyślnie włączone. W ustawieniach Artifact Registry dowiesz się, jak wyłączyć lub włączyć automatyczne skanowanie.

6. Skanowanie na żądanie

Istnieją różne sytuacje, w których konieczne może być przeprowadzenie skanowania przed przekazaniem obrazu do repozytorium. Na przykład deweloper kontenera może zeskanować obraz i naprawić problemy, zanim przekaże kod do kontroli źródłowej. W przykładzie poniżej skompilujesz i przeanalizujesz obraz lokalnie, zanim wykorzystasz wyniki.

Tworzenie obrazu

Na tym etapie użyjesz lokalnego Dockera do skompilowania obrazu do lokalnej pamięci podręcznej.

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

Skanowanie obrazu

Po utworzeniu obrazu poproś o jego skanowanie. 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

Sprawdzanie pliku wyjściowego

Poświęć chwilę na sprawdzenie danych wyjściowych z 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

Sprawdzanie szczegółowych wyników skanowania

Aby wyświetlić rzeczywiste wyniki skanowania, użyj polecenia list-vulnerabilities w miejscu raportu podanym 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.

Oznaczanie krytycznych problemów

Ludzie rzadko korzystają z danych przechowywanych w raporcie bezpośrednio. Wyniki są zwykle wykorzystywane przez proces automatyczny. Aby odczytać szczegóły raportu i sprawdzać, czy znaleziono jakieś krytyczne luki, użyj poniższych poleceń.

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

Wynik tego polecenia będzie taki:

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. Aby przyznać dostęp, użyj 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

Podane niżej polecenie utworzy w katalogu plik cloudbuild.yaml, który będzie używany w ramach procesu zautomatyzowanego. W tym przykładzie kroki są ograniczone do procesu tworzenia kontenera. W praktyce oprócz kroków kontenera należy 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 przetwarzania, aby sprawdzić przerwy w działaniu kompilacji w przypadku wykrycia luki w zabezpieczeniach o wadze KRYTYCZNEJ.

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

Naprawianie luki w zabezpieczeniach

Zaktualizuj plik Dockerfile, aby używać obrazu bazowego, który nie zawiera podatności na zagrożenia o krytycznym znaczeniu.

Zastąp 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ź prawidłowy 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ę Luki 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 tego samouczka.

Ostatnia aktualizacja: 21 marca 2023 r.