Ograniczanie wdrożeń za pomocą uwierzytelniania plików binarnych

1. Wprowadzenie

Binary Authorization to mechanizm zapewniający bezpieczeństwo podczas wdrażania, dzięki któremu w Google Kubernetes Engine (GKE) lub Cloud Run wdrażane są tylko zaufane obrazy kontenerów. Dzięki Binary Authorization możesz wymagać, aby obrazy były podpisywane przez zaufane instytucje podczas procesu programowania, a następnie wymuszać weryfikację podpisu podczas wdrażania. Wymuszanie weryfikacji daje ściślejszą kontrolę nad środowiskiem kontenera, ponieważ na integrację w procesie kompilacji i udostępniania pozwala tylko zweryfikowanym obrazom.

Poniższy diagram przedstawia komponenty w konfiguracji Binary Authorization/Cloud Build:

Potok atestów Binary Authorization w Cloud Build.**Rysunek 1.**Potok Cloud Build, który tworzy atest usługi Binary Authorization.

W tym potoku:

  1. Kod do utworzenia obrazu kontenera jest przesyłany do repozytorium kodu źródłowego, np. Cloud Source Repositories.
  2. Narzędzie do trybu ciągłej integracji (CI), Cloud Build, tworzy i testuje kontener.
  3. Proces kompilacji przenosi obraz kontenera do Container Registry lub innego rejestru, w którym są przechowywane skompilowane obrazy.
  4. Cloud Key Management Service, która zarządza parą kluczy kryptograficznych, podpisuje obraz kontenera. Wynikowy podpis jest następnie przechowywany w nowo utworzonym atestu.
  5. Podczas wdrażania podmiot potwierdzający weryfikuje atest przy użyciu klucza publicznego z pary kluczy. Binary Authorization egzekwuje zasady, wymagając podpisanych atestów do wdrożenia obrazu kontenera.

W tym laboratorium skupisz się na narzędziach i technikach zabezpieczania wdrożonych artefaktów. To laboratorium skupia się na artefaktach (kontenerach) po ich utworzeniu, ale przed wdrożeniem w określonym środowisku.

Czego się nauczysz

  • Podpisywanie obrazów
  • Zasady kontroli ruchu przychodzącego
  • Podpisywanie zeskanowanych obrazów
  • Autoryzowanie podpisanych obrazów
  • Blokowanie niepodpisanych obrazów

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Możesz ją zaktualizować w dowolnym momencie.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się nim przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle jest on oznaczony jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i będzie obowiązywać przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, czyli numer projektu, z której korzystają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Konfiguracja środowiska

W Cloud Shell ustaw identyfikator projektu i numer projektu. Zapisz je jako zmienne PROJECT_IDPROJECT_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 

Tworzenie repozytorium Artifact Registry

W tym laboratorium 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 podczas uzyskiwania dostępu do Artifact Registry korzystał z Twoich danych logowania gcloud.

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

Tworzenie katalogu roboczego i przechodzenie do niego

mkdir vuln-scan && cd vuln-scan

Określanie przykładowego obrazu

Utwórz plik o nazwie Dockerfile z tą zawartością.

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

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 i przekazywanie obrazu do AR

Użyj Cloud Build, aby utworzyć kontener i automatycznie przesłać go do Artifact Registry.

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

3. Podpisywanie obrazów

Kim jest atestator

Atestator

  • Ta osoba lub proces odpowiada za jedno ogniwo w łańcuchu zaufania systemu.
  • Posiadają one klucz kryptograficzny i podpisują obraz, jeśli przejdzie on proces zatwierdzania.
  • Twórca zasad określa zasady w sposób ogólny i abstrakcyjny, a atestator jest odpowiedzialny za konkretne egzekwowanie pewnego aspektu zasad.
  • Może to być prawdziwa osoba, np. tester jakości lub menedżer, albo bot w systemie CI.
  • Bezpieczeństwo systemu zależy od ich wiarygodności, dlatego ważne jest, aby ich klucze prywatne były bezpieczne.

Każda z tych ról może reprezentować pojedynczą osobę lub zespół osób w Twojej organizacji. W środowisku produkcyjnym te role byłyby prawdopodobnie zarządzane przez oddzielne projekty Google Cloud Platform (GCP), a dostęp do zasobów byłby między nimi ograniczony za pomocą Cloud IAM.

a37eb2ed54b9c2eb.png

Atestatory w Binary Authorization są implementowane na podstawie interfejsu Cloud Container Analysis API, dlatego zanim przejdziemy dalej, warto opisać, jak to działa. Interfejs Container Analysis API został zaprojektowany tak, aby umożliwić powiązanie metadanych z konkretnymi obrazami kontenerów.

Na przykład notatka może zostać utworzona w celu śledzenia luki w zabezpieczeniach Heartbleed. Dostawcy zabezpieczeń tworzą wtedy skanery, które testują obrazy kontenerów pod kątem luk w zabezpieczeniach, i tworzą wystąpienie powiązane z każdym naruszonym kontenerem.

208aa5ebc53ff2b3.png

Oprócz śledzenia luk w zabezpieczeniach usługa Container Analysis została zaprojektowana jako ogólny interfejs API metadanych. Binary Authorization korzysta z Container Analysis, aby powiązać podpisy z obrazami kontenerów, które weryfikuje. Notatka Container Analysis służy do reprezentowania pojedynczego atestatora, a wystąpienia są tworzone i powiązane z każdym kontenerem, który został zatwierdzony przez tego atestatora.

Interfejs Binary Authorization API korzysta z pojęć „atestatorzy” i „atesty”, ale są one implementowane przy użyciu odpowiednich notatek i wystąpień w interfejsie Container Analysis API.

63a701bd0057ea17.png

Tworzenie notatki atestatora

Notatka atestatora to po prostu niewielki fragment danych, który pełni funkcję etykiety dla typu stosowanego podpisu. Na przykład jedna notatka może dotyczyć skanowania pod kątem luk w zabezpieczeniach, a inna może być używana do zatwierdzania kontroli jakości. Notatka będzie używana podczas procesu podpisywania.

919f997db0ffb881.png

Tworzenie notatki

cat > ./vulnz_note.json << EOM
{
  "attestation": {
    "hint": {
      "human_readable_name": "Container Vulnerabilities attestation authority"
    }
  }
}
EOM

Zapisywanie notatki

NOTE_ID=vulnz_note

curl -vvv -X POST \
    -H "Content-Type: application/json"  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
    --data-binary @./vulnz_note.json  \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"

Weryfikacja notatki

curl -vvv  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

Notatka została zapisana w interfejsie Container Analysis API.

Tworzenie atestatora

Atestatory służą do przeprowadzania procesu podpisywania obrazu i dołączają do niego wystąpienie notatki w celu późniejszej weryfikacji. Aby korzystać z atestatora, musisz też zarejestrować notatkę w Binary Authorization:

ed05d438c79b654d.png

Utwórz atestator

ATTESTOR_ID=vulnz-attestor

gcloud container binauthz attestors create $ATTESTOR_ID \
    --attestation-authority-note=$NOTE_ID \
    --attestation-authority-note-project=${PROJECT_ID}

Weryfikowanie atestatora

gcloud container binauthz attestors list

Zwróć uwagę, że ostatni wiersz wskazuje, że NUM_PUBLIC_KEYS: 0klucze podasz w późniejszym kroku.

Pamiętaj też, że Cloud Build automatycznie tworzy w Twoim projekcie built-by-cloud-build atestatora, gdy uruchamiasz kompilację, która generuje obrazy. Powyższe polecenie zwraca więc 2 potwierdzających: vulnz-attestorbuilt-by-cloud-build. Po pomyślnym utworzeniu obrazów Cloud Build automatycznie je podpisuje i tworzy dla nich atesty.

Dodawanie roli uprawnień

Konto usługi Binary Authorization musi mieć uprawnienia do wyświetlania notatek atestu. Przyznaj dostęp za pomocą tego wywołania interfejsu API

PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}"  --format="value(projectNumber)")

BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"


cat > ./iam_request.json << EOM
{
  'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
  'policy': {
    'bindings': [
      {
        'role': 'roles/containeranalysis.notes.occurrences.viewer',
        'members': [
          'serviceAccount:${BINAUTHZ_SA_EMAIL}'
        ]
      }
    ]
  }
}
EOM

Użyj pliku do utworzenia zasady uprawnień

curl -X POST  \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @./iam_request.json \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"

Dodawanie klucza KMS

1e3af7c177f7a311.png

Zanim zaczniesz korzystać z tego atestatora, Twój urząd musi utworzyć parę kluczy kryptograficznych, których można używać do podpisywania obrazów kontenerów. Możesz to zrobić za pomocą Google Cloud Key Management Service (KMS).

Najpierw dodaj zmienne środowiskowe, aby opisać nowy klucz.

KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1

Utwórz pęk kluczy, aby przechowywać zestaw kluczy

gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"

Utwórz nową asymetryczną parę kluczy podpisywania dla atestatora.

gcloud kms keys create "${KEY_NAME}" \
    --keyring="${KEYRING}" --location="${KEY_LOCATION}" \
    --purpose asymmetric-signing   \
    --default-algorithm="ec-sign-p256-sha256"

Klucz powinien być widoczny na stronie KMS w konsoli Google Cloud.

Teraz powiąż klucz z atestatorem za pomocą polecenia gcloud binauthz:

gcloud beta container binauthz attestors public-keys add  \
    --attestor="${ATTESTOR_ID}"  \
    --keyversion-project="${PROJECT_ID}"  \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

Jeśli ponownie wyświetlisz listę organów, powinien być widoczny zarejestrowany klucz:

gcloud container binauthz attestors list

Tworzenie podpisanego atestu

Na tym etapie masz już skonfigurowane funkcje, które umożliwiają podpisywanie obrazów. Użyj utworzonego wcześniej atestującego, aby podpisać obraz kontenera, z którym pracujesz.

858d7e6feeb6f159.png

Atest musi zawierać podpis kryptograficzny, który potwierdza, że osoba atestująca zweryfikowała dany obraz kontenera i jest on bezpieczny do uruchomienia w klastrze. Aby określić, który obraz kontenera ma zostać poświadczony, musisz ustalić jego skrót.

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

DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
    --format='get(image_summary.digest)')

Teraz możesz użyć gcloud do utworzenia atestu. Polecenie po prostu przyjmuje szczegóły klucza, którego chcesz użyć do podpisywania, oraz konkretny obraz kontenera, który chcesz zatwierdzić.

gcloud beta container binauthz attestations sign-and-create  \
    --artifact-url="${CONTAINER_PATH}@${DIGEST}" \
    --attestor="${ATTESTOR_ID}" \
    --attestor-project="${PROJECT_ID}" \
    --keyversion-project="${PROJECT_ID}" \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

W terminologii Container Analysis spowoduje to utworzenie nowego wystąpienia i dołączenie go do notatki atestatora. Aby upewnić się, że wszystko działa zgodnie z oczekiwaniami, możesz wyświetlić listę swoich zaświadczeń.

gcloud container binauthz attestations list \
   --attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}

4. Zasady kontroli ruchu przychodzącego

Binary Authorization to funkcja GKE i Cloud Run, która umożliwia weryfikację reguł przed uruchomieniem obrazu kontenera. Weryfikacja jest przeprowadzana w przypadku każdej prośby o uruchomienie obrazu, niezależnie od tego, czy pochodzi ona z zaufanego potoku CI/CD, czy od użytkownika, który ręcznie próbuje wdrożyć obraz. Ta funkcja pozwala skuteczniej zabezpieczać środowiska wykonawcze niż same kontrole potoku CI/CD.

Aby poznać tę funkcję, zmodyfikujesz domyślne zasady GKE, aby wymusić ścisłą regułę autoryzacji.

Tworzenie klastra GKE

Utwórz klaster GKE z włączoną autoryzacją plików binarnych:

gcloud beta container clusters create binauthz \
    --zone us-central1-a  \
    --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE

Zezwól Cloud Build na wdrażanie w tym klastrze:

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

Zasada zezwalająca na wszystko

Najpierw sprawdź domyślny stan zasad i możliwość wdrażania dowolnego obrazu.

  1. Sprawdzanie istniejących zasad
gcloud container binauthz policy export
  1. Zwróć uwagę, że zasada egzekwowania jest ustawiona na ALWAYS_ALLOW.

evaluationMode: ALWAYS_ALLOW

  1. Wdróż próbkę, aby sprawdzić, czy możesz wdrożyć dowolny element.
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Sprawdzanie, czy wdrożenie zadziałało
kubectl get pods

Zobaczysz te dane wyjściowe:

161db370d99ffb13.png

  1. Usuń wdrożenie
kubectl delete pod hello-server

Zasada odrzucania wszystkich

Teraz zaktualizuj zasadę, aby zabronić wyświetlania wszystkich obrazów.

  1. Eksportowanie bieżących zasad do edytowalnego pliku
gcloud container binauthz policy export  > policy.yaml
  1. Zmień zasadę

W edytorze tekstu zmień wartość evaluationMode z ALWAYS_ALLOW na ALWAYS_DENY.

edit policy.yaml

Plik YAML zasad powinien wyglądać tak:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_DENY
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy

Ta zasada jest stosunkowo prosta. Wiersz globalPolicyEvaluationMode deklaruje, że te zasady rozszerzają globalne zasady zdefiniowane przez Google. Dzięki temu wszystkie oficjalne kontenery GKE mogą domyślnie działać. Dodatkowo zasady deklarują defaultAdmissionRule, która stwierdza, że wszystkie inne pody zostaną odrzucone. Reguła dopuszczania zawiera wiersz enforcementMode, który określa, że wszystkie pody niezgodne z tą regułą powinny być blokowane przed uruchomieniem w klastrze.

Instrukcje tworzenia bardziej złożonych zasad znajdziesz w dokumentacji autoryzacji plików binarnych.

657752497e59378c.png

  1. Otwórz Terminal i zastosuj nowe zasady. Zaczekaj kilka sekund, aż zmiana zostanie wprowadzona.
gcloud container binauthz policy import policy.yaml
  1. Wypróbuj wdrożenie przykładowego zadania
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Wdrożenie kończy się niepowodzeniem z tym komunikatem:
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule

Przywróć zasadę zezwalającą na wszystko

Zanim przejdziesz do następnej sekcji, cofnij zmiany w zasadach.

  1. Zmień zasadę

W edytorze tekstu zmień wartość evaluationMode z ALWAYS_DENY na ALWAYS_ALLOW.

edit policy.yaml

Plik YAML zasad powinien wyglądać tak:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Zastosuj przywrócone zasady
gcloud container binauthz policy import policy.yaml

5. Podpisywanie zeskanowanych obrazów

Masz włączone podpisywanie obrazów i ręcznie używasz atestatora, aby podpisać przykładowy obraz. W praktyce będziesz stosować atesty w procesach zautomatyzowanych, takich jak potoki CI/CD.

W tej sekcji skonfigurujesz Cloud Build do automatycznego potwierdzania obrazów.

Role

Dodaj rolę wyświetlającego atestatory autoryzacji plików binarnych do konta usługi Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/binaryauthorization.attestorsViewer

Dodaj rolę Podpisujący/weryfikujący klucze CryptoKey Cloud KMS do konta usługi Cloud Build (podpisywanie oparte na KMS):

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/cloudkms.signerVerifier

Dodaj rolę dodającego notatki analizy kontenera do konta usługi Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/containeranalysis.notes.attacher

Przyznawanie dostępu kontu usługi Cloud Build

Cloud Build będzie potrzebować uprawnień dostępu do interfejsu API skanowania na żądanie. Udziel dostępu za pomocą 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"

Przygotowywanie niestandardowego kroku kompilacji Cloud Build

Aby uprościć proces atestowania, użyjesz niestandardowego kroku kompilacji w Cloud Build. Google udostępnia ten krok kompilacji niestandardowej, który zawiera funkcje pomocnicze ułatwiające ten proces. Przed użyciem kod niestandardowego kroku kompilacji musi zostać skompilowany w kontenerze i przesłany do Cloud Build. Aby to zrobić, uruchom te polecenia:

git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community

Dodawanie kroku podpisywania do pliku cloudbuild.yaml

W tym kroku dodasz krok atestowania do potoku Cloud Build.

  1. Zapoznaj się z krokiem podpisywania poniżej.

Tylko do wglądu. Nie kopiuj

#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args:
    - '--artifact-url'
    - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image'
    - '--attestor'
    - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
    - '--keyversion'
    - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
  1. Utwórz plik cloudbuild.yaml z pełną ścieżką poniżej.
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']


#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args:
    - '--artifact-url'
    - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
    - '--attestor'
    - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
    - '--keyversion'
    - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'



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

Uruchamianie kompilacji

gcloud builds submit

Sprawdź kompilację w historii Cloud Build

Otwórz konsolę Cloud na stronie Historia Cloud Build i sprawdź najnowszą kompilację oraz prawidłowe wykonanie kroków kompilacji.

6. Autoryzowanie podpisanych obrazów

W tej sekcji zaktualizujesz GKE, aby używać Binary Authorization do sprawdzania, czy obraz ma podpis ze skanowania pod kątem luk w zabezpieczeniach, zanim zezwolisz na jego uruchomienie.

d5c41bb89e22fd61.png

Aktualizowanie zasad GKE, aby wymagać atestu

Wymagaj, aby obrazy były podpisane przez atestatora, dodając do zasad BinAuth GKE reguły clusterAdmissionRules.

Obecnie w klastrze obowiązują zasady z 1 regułą: zezwalaj na kontenery z oficjalnych repozytoriów i odrzucaj wszystkie inne.

Zastąp zasadę zaktualizowaną konfiguracją za pomocą tego polecenia.

COMPUTE_ZONE=us-central1-a

cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
  evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
  ${COMPUTE_ZONE}.binauthz:
    evaluationMode: REQUIRE_ATTESTATION
    enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
    requireAttestationsBy:
    - projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM

Na dysku powinien teraz znajdować się nowy plik o nazwie updated_policy.yaml. Teraz zamiast odrzucać wszystkie obrazy domyślna reguła najpierw sprawdza, czy atestator ma weryfikacje.

822240fc0b02408e.png

Prześlij nową zasadę do usługi Binary Authorization:

gcloud beta container binauthz policy import binauth_policy.yaml

Wdrażanie podpisanego obrazu

Pobieranie skrótu obrazu dla prawidłowego obrazu

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


DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
    --format='get(image_summary.digest)')

Używanie skrótu w konfiguracji Kubernetes

cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
  name: deb-httpd
spec:
  selector:
    app: deb-httpd
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deb-httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deb-httpd
  template:
    metadata:
      labels:
        app: deb-httpd
    spec:
      containers:
      - name: deb-httpd
        image: ${CONTAINER_PATH}@${DIGEST}
        ports:
        - containerPort: 8080
        env:
          - name: PORT
            value: "8080"

EOM

Wdrażanie aplikacji w GKE

kubectl apply -f deploy.yaml

Sprawdź obciążenie w konsoli i zwróć uwagę na pomyślne wdrożenie obrazu.

7. Blokowanie niepodpisanych obrazów

Tworzenie obrazu

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:bad .

Przesyłanie niepodpisanego obrazu do repozytorium

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

Pobieranie podsumowania obrazu dla nieodpowiedniego obrazu

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


DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
    --format='get(image_summary.digest)')

Używanie skrótu w konfiguracji Kubernetes

cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
  name: deb-httpd
spec:
  selector:
    app: deb-httpd
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deb-httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deb-httpd
  template:
    metadata:
      labels:
        app: deb-httpd
    spec:
      containers:
      - name: deb-httpd
        image: ${CONTAINER_PATH}@${DIGEST}
        ports:
        - containerPort: 8080
        env:
          - name: PORT
            value: "8080"

EOM

Próba wdrożenia aplikacji w GKE

kubectl apply -f deploy.yaml

Sprawdź obciążenie w konsoli i zwróć uwagę na błąd informujący o odmowie wdrożenia:

No attestations found that were valid and signed by a key trusted by the attestor

8. Gratulacje!

Gratulacje! Codelab został ukończony.

Omówione zagadnienia:

  • Podpisywanie obrazów
  • Zasady kontroli ruchu przychodzącego
  • Podpisywanie zeskanowanych obrazów
  • Autoryzowanie podpisanych obrazów
  • Blokowanie niepodpisanych obrazów

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.

Usuwanie projektu

Najprostszym sposobem na uniknięcie płatności jest usunięcie projektu utworzonego w tym samouczku.

Ostatnia aktualizacja: 21.03.2023