From 55c396860599f5e08757d82125618638b8cc6fb4 Mon Sep 17 00:00:00 2001 From: Pramod Bindal Date: Thu, 10 Oct 2024 16:42:22 +0530 Subject: [PATCH] Add Support for Google Workload Identity Federation --- dev/google-wif.sh | 63 +++++++++++++++++++ dev/install.sh | 23 ++++++- dev/kind/kind-config.yaml | 7 +++ dev/pipeline/pipeline-wif.yaml | 107 ++++++++++++++++++++++++++++++++ dev/pr/gcs-wif-pipelinerun.yaml | 34 ++++++++++ 5 files changed, 232 insertions(+), 2 deletions(-) create mode 100755 dev/google-wif.sh mode change 100644 => 100755 dev/install.sh create mode 100644 dev/kind/kind-config.yaml create mode 100644 dev/pipeline/pipeline-wif.yaml create mode 100644 dev/pr/gcs-wif-pipelinerun.yaml diff --git a/dev/google-wif.sh b/dev/google-wif.sh new file mode 100755 index 000000000..b0784d842 --- /dev/null +++ b/dev/google-wif.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -x +#Step 0 - Define Common Variables + + POOL_ID=openshift-pool + PROVIDER_ID=opeshift-wif + NAMESPACE=default + SERVICE_ACCOUNT=default + PROJECT_ID=pipelines-qe + PROJECT_NUMBER=272779626560 + MAPPED_SUBJECT=system:serviceaccount:$NAMESPACE:$SERVICE_ACCOUNT + +#Step 1 - Enable IAM APIs on Google Cloud + +# Step 2 - Define an attribute mapping and condition + MAPPINGS=google.subject=assertion.sub + + +#Step 3 - Create workload identity pool and provider + ISSUER=$(kubectl get --raw /.well-known/openid-configuration | jq -r .issuer) + + +# Download the cluster's JSON Web Key Set (JWKS): + kubectl get --raw /openid/v1/jwks > cluster-jwks.json + + +# Create a new workload identity pool: + gcloud iam workload-identity-pools create $POOL_ID \ + --location="global" \ + --description=$POOL_ID \ + --display-name=$POOL_ID + + +# Add the Kubernetes cluster as a workload identity pool provider and upload the cluster's JWKS: + + gcloud iam workload-identity-pools providers create-oidc $PROVIDER_ID \ + --location="global" \ + --workload-identity-pool=$POOL_ID \ + --issuer-uri=$ISSUER \ + --allowed-audiences=openshift \ + --attribute-mapping=$MAPPINGS \ + --jwk-json-path="cluster-jwks.json" + + +# Create Service Account or use default one + +# kubectl create serviceaccount $KSA_NAME --namespace $NAMESPACE + +# Grant IAM access to the Kubernetes ServiceAccount for a Google Cloud resource. + gcloud projects add-iam-policy-binding projects/$PROJECT_ID \ + --role=roles/owner \ + --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/subject/$MAPPED_SUBJECT \ + --condition=None + + gcloud iam workload-identity-pools create-cred-config \ + projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \ + --credential-source-file=/workspace/token/token \ + --credential-source-type=text \ + --output-file=credential-configuration.json + + + + kubectl -n $NAMESPACE create secret generic gcs-cred --from-file=credential-configuration.json \ No newline at end of file diff --git a/dev/install.sh b/dev/install.sh old mode 100644 new mode 100755 index 868e4881d..e9c0fe4bc --- a/dev/install.sh +++ b/dev/install.sh @@ -1,9 +1,28 @@ #!/usr/bin/env bash +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +# Create a Kind Cluster if dont have sone +kind create cluster --name tekton-caches --config $SCRIPT_DIR/kind/kind-config.yaml + + +# Install Pipelines if not already installed. +#kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml + +#Enable Step Actions Feature kubectl patch configmap -n tekton-pipelines --type merge -p '{"data":{"enable-step-actions": "true"}}' feature-flags -kubectl create secret generic regcred \ - --from-file=config.json=${HOME}/.docker/config.json +# Create Docker creds secret Specifc to OCI Images +#kubectl create secret generic regcred --from-file=config.json=${HOME}/.docker/config.json + +# Create Secret for AWS S3 +#kubectl create secret generic aws-cred --from-file=${HOME}/.aws/config --from-file=${HOME}/.aws/credentials + +#Deploy Step Actions +ko apply -BRf $SCRIPT_DIR/step-action + +# Deploy Pipelines +kubectl apply -f $SCRIPT_DIR/pipeline diff --git a/dev/kind/kind-config.yaml b/dev/kind/kind-config.yaml new file mode 100644 index 000000000..35467ef85 --- /dev/null +++ b/dev/kind/kind-config.yaml @@ -0,0 +1,7 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane +- role: worker +- role: worker +- role: worker \ No newline at end of file diff --git a/dev/pipeline/pipeline-wif.yaml b/dev/pipeline/pipeline-wif.yaml new file mode 100644 index 000000000..cb1ec1e1a --- /dev/null +++ b/dev/pipeline/pipeline-wif.yaml @@ -0,0 +1,107 @@ +--- +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: pipeline-wif +spec: + params: + - name: repo_url + type: string + - name: revision + type: string + - name: registry + type: string + - name: buildCommand + type: string + default: go build -v . + - name: cachePatterns + type: array + default: [ "**go.mod", "**go.sum" ] + - name: image + type: string + default: golang:latest + - name: force-cache-upload + type: string + default: "false" + workspaces: + - name: source + - name: cred + - name: token + tasks: + - displayName: Build go application + name: build-task + workspaces: + - name: source + - name: cred + - name: token + taskSpec: + params: + - name: buildCommand + default: $(params.buildCommand) + - name: cachePatterns + default: $(params.cachePatterns) + - name: image + default: $(params.image) + steps: + - name: create-repo + image: $(params.image) + script: | + mkdir -p $(workspaces.source.path)/repo + chmod 777 $(workspaces.source.path)/repo + - name: fetch-repo + ref: + resolver: http + params: + - name: url + value: https://raw.githubusercontent.com/tektoncd/catalog/main/stepaction/git-clone/0.1/git-clone.yaml + params: + - name: output-path + value: $(workspaces.source.path)/repo + - name: url + value: $(params.repo_url) + - name: revision + value: $(params.revision) + - name: cache-fetch + ref: + name: cache-fetch + params: + - name: patterns + value: $(params.cachePatterns) + - name: source + value: $(params.registry)/cache-go:{{hash}} + - name: cachePath + value: $(workspaces.source.path)/cache + - name: workingdir + value: $(workspaces.source.path)/repo + - name: googleCredentialsPath + value: $(workspaces.cred.path)/credential-configuration.json + + - name: run-go-build + workingDir: $(workspaces.source.path)/repo + image: $(params.image) + env: + - name: GOCACHE + value: $(workspaces.source.path)/cache/gocache + - name: GOMODCACHE + value: $(workspaces.source.path)/cache/gomodcache + script: | + set -x + git config --global --add safe.directory $(workspaces.source.path)/repo + $(params.buildCommand) + echo "Cache size is $(du -sh $(workspaces.source.path)/cache)" + - name: cache-upload + ref: + name: cache-upload + params: + - name: patterns + value: $(params.cachePatterns) + - name: target + value: $(params.registry)/cache-go:{{hash}} + - name: cachePath + value: $(workspaces.source.path)/cache + - name: workingdir + value: $(workspaces.source.path)/repo + - name: googleCredentialsPath + value: $(workspaces.cred.path)/credential-configuration.json + - name: force-cache-upload + value: $(params.force-cache-upload) diff --git a/dev/pr/gcs-wif-pipelinerun.yaml b/dev/pr/gcs-wif-pipelinerun.yaml new file mode 100644 index 000000000..6c23e9a1e --- /dev/null +++ b/dev/pr/gcs-wif-pipelinerun.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: tekton.dev/v1 +kind: PipelineRun +metadata: + generateName: pipelinerun-gcs- +spec: + pipelineRef: + name: pipeline-wif + params: + - name: repo_url + value: https://github.com/chmouel/go-helloworld + - name: revision + value: main + # This uses GCS bucket to upload Caches + - name: registry + value: gs://tekton-caches + - name: buildCommand + value: go build -v ./ + - name: image + value: golang:1.21 + workspaces: + - name: source + emptyDir: { } + - name: cred + secret: + secretName: gcs-cred + - name: token + projected: + sources: + - serviceAccountToken: + audience: https://iam.googleapis.com/projects/272779626560/locations/global/workloadIdentityPools/openshift-pool/providers/opeshift-wif + expirationSeconds: 3600 + path: token +