Skip to content
This repository was archived by the owner on May 7, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions content/tenant-project/set-up-workload-identity-federation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: "Set up Workload Identity Federation"
weight: 4
description: "Duration: 10 min | Persona: Platform Admin"
tags: ["kcc", "platform-admin", "security-tips", "wif"]
---
![Platform Admin](/images/platform-admin.png)
_{{< param description >}}_

In this section, you will set up Workload Identity Federation for the Tenant project. Workload Identity Federation will be used later in this workshop by the GitHub actions building the containers for the applications like Whereami and Online Boutique and then will push them into the private Artifact Registry. This replaces the need to download the Google Service Account keys, so it's improving your security posture.

Define variables:
```Bash
WORK_DIR=~/
source ${WORK_DIR}acm-workshop-variables.sh
echo "export WORKLOAD_IDENTITY_POOL_NAME=container-images-builder-wi-pool" >> ${WORK_DIR}acm-workshop-variables.sh
echo "export CONTAINERS_BUILDER_SERVICE_ACCOUNT_NAME=container-images-builder" >> ${WORK_DIR}acm-workshop-variables.sh
source ${WORK_DIR}acm-workshop-variables.sh
```

## Configure the Workload Identity Federation

Define the [Workload Identity Pool](https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamworkloadidentitypool):
```Bash
cat <<EOF > ${WORK_DIR}$HOST_PROJECT_DIR_NAME/projects/$TENANT_PROJECT_ID/workkloadidentitypool.yaml
apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMWorkloadIdentityPool
metadata:
name: ${WORKLOAD_IDENTITY_POOL_NAME}
spec:
location: global
displayName: ${WORKLOAD_IDENTITY_POOL_NAME}
projectRef:
external: projects/${TENANT_PROJECT_ID}
EOF
```

Define the [Workload Identity Pool Provider](https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamworkloadidentitypoolprovider) for the GitHub repositories:
```Bash
cat <<EOF > ${WORK_DIR}$HOST_PROJECT_DIR_NAME/projects/$TENANT_PROJECT_ID/workkloadidentitypoolprovider.yaml
apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMWorkloadIdentityPoolProvider
metadata:
name: ${WORKLOAD_IDENTITY_POOL_NAME}
spec:
projectRef:
external: projects/${TENANT_PROJECT_ID}
location: global
workloadIdentityPoolRef:
name: ${WORKLOAD_IDENTITY_POOL_NAME}
attributeMapping:
google.subject: assertion.repository
attribute.actor: assertion.actor
attribute.aud: assertion.aud
attribute.repository: assertion.repository
oidc:
issuerUri: "https://token.actions.githubusercontent.com"
EOF
```

## Configure the Google Service Account

Define a [Google Service Account](https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccount) which will used later by the GitHub actions in order to build the container images:
```Bash
cat <<EOF > ${WORK_DIR}$HOST_PROJECT_DIR_NAME/projects/$TENANT_PROJECT_ID/containers-builder-sa.yaml
apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMServiceAccount
metadata:
name: ${CONTAINERS_BUILDER_SERVICE_ACCOUNT_NAME}
namespace: ${TENANT_PROJECT_ID}
spec:
displayName: ${CONTAINERS_BUILDER_SERVICE_ACCOUNT_NAME}
EOF
```

## Deploy Kubernetes manifests

```Bash
cd ${WORK_DIR}$HOST_PROJECT_DIR_NAME/
git add . && git commit -m "Setting up Workload Identity Federation" && git push origin main
```

## Check deployments

{{< mermaid >}}
graph TD;
IAMServiceAccount-.->Project
IAMWorkloadIdentityPool-.->Project
IAMWorkloadIdentityPoolProvider-->IAMWorkloadIdentityPool
{{< /mermaid >}}

List the Kubernetes resources managed by Config Sync in **Config Controller** for the **Host project configs** repository:
```Bash
gcloud alpha anthos config sync repo describe \
--project $HOST_PROJECT_ID \
--managed-resources all \
--sync-name root-sync \
--sync-namespace config-management-system
```
Wait and re-run this command above until you see `"status": "SYNCED"` for this `RootSync`. All the `managed_resources` listed should have `STATUS: Current` as well.

List the GitHub runs for the **Host project configs** repository:
```Bash
cd ${WORK_DIR}$HOST_PROJECT_DIR_NAME && gh run list
```

List the Google Cloud resources created:
```Bash
gcloud iam workload-identity-pools describe $WORKLOAD_IDENTITY_POOL_NAME \
--location global \
--project $TENANT_PROJECT_ID
gcloud iam workload-identity-pools providers describe $WORKLOAD_IDENTITY_POOL_NAME \
--workload-identity-pool $WORKLOAD_IDENTITY_POOL_NAME \
--location global \
--project $TENANT_PROJECT_ID
```
2 changes: 1 addition & 1 deletion content/whereami/deploy-app.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Deploy app"
weight: 4
weight: 5
description: "Duration: 10 min | Persona: Apps Operator"
tags: ["apps-operator", "asm"]
---
Expand Down
2 changes: 1 addition & 1 deletion content/whereami/deploy-authorization-policy.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Deploy AuthorizationPolicy"
weight: 7
weight: 8
description: "Duration: 5 min | Persona: Apps Operator"
tags: ["apps-operator", "asm", "security-tips"]
---
Expand Down
2 changes: 1 addition & 1 deletion content/whereami/deploy-network-policy.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Deploy NetworkPolicy"
weight: 6
weight: 7
description: "Duration: 5 min | Persona: Apps Operator"
tags: ["apps-operator", "security-tips"]
---
Expand Down
2 changes: 1 addition & 1 deletion content/whereami/deploy-sidecar.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Deploy Sidecar"
weight: 5
weight: 6
description: "Duration: 5 min | Persona: Apps Operator"
tags: ["apps-operator", "asm"]
---
Expand Down
83 changes: 64 additions & 19 deletions content/whereami/prepare-container.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Prepare container"
weight: 3
weight: 4
description: "Duration: 5 min | Persona: Apps Operator"
tags: ["apps-operator", "security-tips", "shift-left"]
---
Expand All @@ -19,29 +19,74 @@ echo "export PRIVATE_WHEREAMI_IMAGE_NAME=${PRIVATE_WHEREAMI_IMAGE_NAME}" >> ${WO
source ${WORK_DIR}acm-workshop-variables.sh
```

Copy the public image to your private registry:
Create the GitHub actions definition:
```Bash
UPSTREAM_WHEREAMI_IMAGE_NAME=us-docker.pkg.dev/google-samples/containers/gke/whereami:$WHEREAMI_VERSION
docker pull $UPSTREAM_WHEREAMI_IMAGE_NAME
docker tag $UPSTREAM_WHEREAMI_IMAGE_NAME $PRIVATE_WHEREAMI_IMAGE_NAME
docker push $PRIVATE_WHEREAMI_IMAGE_NAME
cd ${WORK_DIR}$WHERE_AMI_DIR_NAME
cat <<EOF > ${WORK_DIR}$WHERE_AMI_DIR_NAME/.github/workflows/copy-container.yaml
name: copy-container
permissions:
id-token: write
contents: read
env:
SEVERITY: CRITICAL
WHEREAMI_APP_NAME: whereami
WHEREAMI_VERSION: 1.2.10
UPSTREAM_WHEREAMI_IMAGE_NAME: us-docker.pkg.dev/google-samples/containers/gke/whereami
jobs:
job:
runs-on: ubuntu-22.04
steps:
- uses: actions/[email protected]
with:
submodules: true
- uses: google-github-actions/[email protected]
with:
workload_identity_provider: '${{ secrets.WORKLOAD_IDENTITY_POOL_PROVIDER }}'
service_account: '${{ secrets.CONTAINER_IMAGE_BUILDER_SERVICE_ACCOUNT_ID }}'
token_format: 'access_token'
- uses: google-github-actions/[email protected]
with:
version: latest
- name: copy the container
run: |
docker pull ${UPSTREAM_WHEREAMI_IMAGE_NAME}:${WHEREAMI_VERSION}
imageName=${{ secrets.CONTAINER_REGISTRY_HOST_NAME }}/${{ secrets.CONTAINER_REGISTRY_PROJECT_ID }}/${{ secrets.CONTAINER_REGISTRY_NAME }}/${WHEREAMI_APP_NAME}
echo "PRIVATE_WHEREAMI_IMAGE_NAME=$imageName" >> $GITHUB_ENV
docker tag ${UPSTREAM_WHEREAMI_IMAGE_NAME}:${WHEREAMI_VERSION} ${PRIVATE_WHEREAMI_IMAGE_NAME}:${WHEREAMI_VERSION}
docker push ${PRIVATE_WHEREAMI_IMAGE_NAME}:${WHEREAMI_VERSION}
- name: scan the container
run: |
gcloud components install local-extract --quiet
gcloud artifacts docker images scan ${PRIVATE_WHEREAMI_IMAGE_NAME}:${WHEREAMI_VERSION} --format='value(response.scan)' > scan_id.txt
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format='table(vulnerability.effectiveSeverity, vulnerability.cvssScore, noteName, vulnerability.packageIssue[0].affectedPackage, vulnerability.packageIssue[0].affectedVersion.name, vulnerability.packageIssue[0].fixedVersion.name)'
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format='value(vulnerability.effectiveSeverity)' | if grep -Fxq ${{ env.SEVERITY }}; then echo 'Failed vulnerability check' && exit 1; else exit 0; fi
EOF
```
{{% notice tip %}}
You could see that we scan the container image as part of the Continuous Integration pipeline and generate an error if any `Critical` vulnerabilities is found.
{{% /notice %}}

List the container images in your private registry:
Set GitHub actions secrets:
```Bash
gcloud artifacts docker images list $CONTAINER_REGISTRY_REPOSITORY \
--include-tags
gh secret set CONTAINER_REGISTRY_PROJECT_ID -b"${projectId}"
gh secret set CONTAINER_REGISTRY_NAME -b"${artifactRegistryName}"
gh secret set CONTAINER_REGISTRY_HOST_NAME -b"${artifactRegistryLocation}-docker.pkg.dev"
gh secret set CONTAINER_IMAGE_BUILDER_SERVICE_ACCOUNT_ID -b"${saId}"
gh secret set WORKLOAD_IDENTITY_POOL_PROVIDER -b"${providerId}"
```

[Scan the `whereami` container image](https://cloud.google.com/container-analysis/docs/on-demand-scanning-howto):
Commit the file:
```Bash
gcloud artifacts docker images scan $PRIVATE_WHEREAMI_IMAGE_NAME \
--project ${TENANT_PROJECT_ID} \
--format='value(response.scan)' > ${WORK_DIR}scan_id.txt
gcloud artifacts docker images list-vulnerabilities $(cat ${WORK_DIR}scan_id.txt) \
--project ${TENANT_PROJECT_ID} \
--format='table(vulnerability.effectiveSeverity, vulnerability.cvssScore, noteName, vulnerability.packageIssue[0].affectedPackage, vulnerability.packageIssue[0].affectedVersion.name, vulnerability.packageIssue[0].fixedVersion.name)'

```

Manually trigger the GitHub actions run:
```Bash

```

List the container images in your private registry:
```Bash
gcloud artifacts docker images list $CONTAINER_REGISTRY_REPOSITORY \
--include-tags
```
{{% notice tip %}}
You could use this `gcloud artifacts docker images scan` command in your Continuous Integration system in order to detect as early as possible for example `Critical` or `High` vulnerabilities.
{{% /notice %}}
3 changes: 3 additions & 0 deletions content/whereami/set-up-whereami-git-repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ cd ${WORK_DIR}$WHERE_AMI_DIR_NAME
git pull
git checkout main
WHERE_AMI_REPO_URL=$(gh repo view --json url --jq .url)
WHERE_AMI_REPO_NAME_WITH_OWNER=$(gh repo view --json nameWithOwner --jq .nameWithOwner)
echo "export WHERE_AMI_REPO_NAME_WITH_OWNER=${WHERE_AMI_REPO_NAME_WITH_OWNER}" >> ${WORK_DIR}acm-workshop-variables.sh
source ${WORK_DIR}acm-workshop-variables.sh
```

## Define RepoSync
Expand Down
69 changes: 69 additions & 0 deletions content/whereami/set-up-workload-identity-federation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "Set up Workload Identity Federation"
weight: 3
description: "Duration: 3 min | Persona: Platform Admin"
tags: ["kcc", "platform-admin", "security-tips", "wif"]
---
![Platform Admin](/images/platform-admin.png)
_{{< param description >}}_

In this section, you will set up Workload Identity Federation for the Whereami GitHub repository.

Define variables:
```Bash
WORK_DIR=~/
source ${WORK_DIR}acm-workshop-variables.sh
```

## Configure the Workload Identity Federation

Define the [Workload Identity Pool](https://cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamworkloadidentitypool):
```Bash
cat <<EOF > ${WORK_DIR}$HOST_PROJECT_DIR_NAME/projects/$TENANT_PROJECT_ID/containers-builder-workload-identity-user.yaml
apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPartialPolicy
metadata:
name: containers-builder-sa-wi-user
namespace: ${TENANT_PROJECT_ID}
annotations:
config.kubernetes.io/depends-on: iam.cnrm.cloud.google.com/namespaces/${TENANT_PROJECT_ID}/IAMServiceAccount/${CONTAINERS_BUILDER_SERVICE_ACCOUNT_NAME}
spec:
resourceRef:
name: ${CONTAINERS_BUILDER_SERVICE_ACCOUNT_NAME}
kind: IAMServiceAccount
bindings:
- role: roles/iam.workloadIdentityUser
members:
- member: principalSet://iam.googleapis.com/projects/${TENANT_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${WORKLOAD_IDENTITY_POOL_NAME}/attribute.repository/${WHERE_AMI_REPO_NAME_WITH_OWNER}
EOF
```

## Deploy Kubernetes manifests

```Bash
cd ${WORK_DIR}$HOST_PROJECT_DIR_NAME/
git add . && git commit -m "Setting up Workload Identity Federation for Whereami repository" && git push origin main
```

## Check deployments

{{< mermaid >}}
graph TD;
IAMPartialPolicy-.->IAMServiceAccount
IAMPartialPolicy-.->Project
{{< /mermaid >}}

List the Kubernetes resources managed by Config Sync in **Config Controller** for the **Host project configs** repository:
```Bash
gcloud alpha anthos config sync repo describe \
--project $HOST_PROJECT_ID \
--managed-resources all \
--sync-name root-sync \
--sync-namespace config-management-system
```
Wait and re-run this command above until you see `"status": "SYNCED"` for this `RootSync`. All the `managed_resources` listed should have `STATUS: Current` as well.

List the GitHub runs for the **Host project configs** repository:
```Bash
cd ${WORK_DIR}$HOST_PROJECT_DIR_NAME && gh run list
```