diff --git a/signing/dct/task-dct-sign.yaml b/signing/dct/task-dct-sign.yaml index a369556c..3d9c1e43 100644 --- a/signing/dct/task-dct-sign.yaml +++ b/signing/dct/task-dct-sign.yaml @@ -28,15 +28,14 @@ spec: - name: apikey-secret-key description: field in the secret that contains the api key used to login to ibmcloud service default: apikey + - name: docker-client-image + description: The Docker image to use to run the Docker client + default: docker - name: pipeline-debug description: Pipeline debug mode default: "0" - workspaces: - - name: artifacts - description: A workspace backing by a volume - mountPath: /artifacts steps: - - name: sign-image + - name: set-sign-context image: ibmcom/pipeline-base-image:2.6 env: - name: IBM_CLOUD_API_KEY @@ -58,26 +57,13 @@ spec: value: $(params.vault-resource-group) - name: VAULT_INSTANCE value: $(params.vault-name) - - name: ARCHIVE_DIR - value: /artifacts - name: HOME value: /root - # Docker client configuration - # Connect to the sidecar over TCP, with TLS. - - name: DOCKER_HOST - value: "tcp://localhost:2376" - # Verify TLS. - - name: DOCKER_TLS_VERIFY - value: "1" - # Use the certs generated by the sidecar daemon. - - name: DOCKER_CERT_PATH - value: /certs/client - name: PIPELINE_DEBUG value: $(params.pipeline-debug) - workingDir: /artifacts + workingDir: /task script: | #!/bin/bash - if [ $PIPELINE_DEBUG == 1 ]; then pwd env @@ -85,10 +71,6 @@ spec: set -x fi - echo "ADD DOCKER" - source <(curl -sSL "https://raw.githubusercontent.com/open-toolchain/commons/master/\ - scripts/image_signing/add_docker.sh") - # if vault region is in the 'ibm:yp:' just keep the region part export VAULT_REGION=$(echo "$VAULT_REGION" | awk -F ':' '{print $NF;}') @@ -106,45 +88,18 @@ spec: REGISTRY_NAMESPACE=$(echo $IMAGE_REPOSITORY | awk -F/ '{print $2}') # Image name is remaining part after the repository and namespace and can contains / IMAGE_NAME=$(echo $IMAGE_REPOSITORY | awk -F/ '{a=match($0, $3); print substr($0,a)}') - - # Find the ibmcloud container registry region - # https://cloud.ibm.com/docs/services/Registry?topic=registry-registry_overview#registry_regions_local - if [[ $REGISTRY_URL =~ ^registry\.[a-z]*.bluemix.net$ ]]; then - # deprecated domain name - REGISTRY_REGION=$(echo $REGISTRY_URL | awk -F. '{print $2}') - if [ "$REGISTRY_REGION" == "ng" ]; then - REGISTRY_REGION="us-south" - fi - else - export REGISTRY_REGION=$(echo $REGISTRY_URL | awk -F. '{print $1}') - if [ "$REGISTRY_REGION" == "jp" ]; then - REGISTRY_REGION="ap-north" - elif [ "$REGISTRY_REGION" == "au" ]; then - REGISTRY_REGION="ap-south" - elif [ "$REGISTRY_REGION" == "de" ]; then - REGISTRY_REGION="eu-central" - elif [ "$REGISTRY_REGION" == "uk" ]; then - REGISTRY_REGION="uk-south" - elif [ "$REGISTRY_REGION" == "us" ]; then - REGISTRY_REGION="us-south" - elif [ "$REGISTRY_REGION" == "stg" ]; then - REGISTRY_REGION="us-south" - else - echo "No IBM Cloud Container Registry region found for the registry url $REGISTRY_URL" - exit 1 - fi - fi - - # configure the container registry - ibmcloud cr region-set $REGISTRY_REGION - ibmcloud cr login - - export DOCKER_CONTENT_TRUST_SERVER="https://$REGISTRY_URL:4443" - IMAGE_TAG=$IMAGE_TAGS - echo "CHECKING $IMAGE_REPOSITORY:$IMAGE_TAG" - docker trust inspect "$IMAGE_REPOSITORY:$IMAGE_TAG" + # create a dry-run k8s secret of type docker-registry to obtain + # the content of a docker config.json file to access the target + # ibmcloud container registry + echo "Creating a Kubernetes secret to access the IBM Cloud Container Registry." + kubectl create secret --dry-run=true --output=json \ + docker-registry registry-dockerconfig-secret \ + --docker-server=${REGISTRY_URL} \ + --docker-password=${IBM_CLOUD_API_KEY} \ + --docker-username=iamapikey --docker-email=a@b.com | \ + jq -r '.data[".dockerconfigjson"]' | base64 -d > config.json # Requires # $VAULT_INSTANCE -name of vault @@ -161,22 +116,89 @@ spec: VAULT_DATA=$(buildVaultAccessDetailsJSON "$VAULT_INSTANCE" "${VAULT_REGION:-$IBMCLOUD_TARGET_REGION}" "${VAULT_RESOURCE_GROUP:-$IBMCLOUD_TARGET_RESOURCE_GROUP}") JSON_DATA="$(readData "$REGISTRY_NAMESPACE.keys" "$VAULT_DATA")" signerkey=$(getJSONValue "$DEVOPS_SIGNER" "$JSON_DATA") - writeFile "$signerkey" - # Retrieve the signer passphrase + # Store the information in the task's volume + mkdir -p ./trust/private + writeFile "$signerkey" ./trust/private + export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$(getJSONValue "passphrase" "$signerkey") - #TODO support multiple signatures. This requires knowing if there is already a signature present. - #Need to set DOCKER_CONTENT_TRUST=1 before the image pull if singture present - # Pull the image + # Keep image repository and DCT context for next step + echo "REGISTRY_URL=$REGISTRY_URL" > env.properties + echo "REGISTRY_NAMESPACE=$REGISTRY_NAMESPACE" >> env.properties + echo "IMAGE_NAME=$IMAGE_NAME" >> env.properties + echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE" >> env.properties + volumeMounts: + - mountPath: /certs/client + name: dind-certs + - mountPath: /task + name: task-volume + - name: sign-image + image: $(params.docker-client-image) + workingDir: /task + env: + - name: IMAGE_REPOSITORY + value: $(params.image-repository) + - name: IMAGE_DIGEST + value: $(params.image-digest) + - name: IMAGE_TAGS + value: $(params.image-tags) + - name: DEVOPS_SIGNER + value: $(params.signer) + # Docker client configuration + # Connect to the sidecar over TCP, with TLS. + - name: DOCKER_HOST + value: "tcp://localhost:2376" + # Verify TLS. + - name: DOCKER_TLS_VERIFY + value: "1" + # Use the certs generated by the sidecar daemon. + - name: DOCKER_CERT_PATH + value: /certs/client + # The location of the client configuration files. + - name: DOCKER_CONFIG + value: /task + - name: PIPELINE_DEBUG + value: $(params.pipeline-debug) + script: | + #!/bin/sh + set -e + + if [ $PIPELINE_DEBUG == 1 ]; then + pwd + env + trap env EXIT + set -x + fi + + # Obtain image registry context from previous step + source env.properties + export $(cut -d= -f1 env.properties) + + # Configure docker content trust context from previous step + export DOCKER_TRUST_DIRECTORY=/task/trust/private + export DOCKER_TRUST_HOME=/task/trust + + # Configure DCT server from private registry url + export DOCKER_CONTENT_TRUST_SERVER="https://$REGISTRY_URL:4443" + + #TODO support multiple signatures + IMAGE_TAG=$IMAGE_TAGS + + echo "CHECKING $IMAGE_REPOSITORY:$IMAGE_TAG" + docker trust inspect "$IMAGE_REPOSITORY:$IMAGE_TAG" + + # Pull the image w/o Docker Content Trust enabled to prevent failure in pulling non signed image docker pull "$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$IMAGE_TAG" + # Sign the image export DOCKER_CONTENT_TRUST=1 docker trust sign "$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$IMAGE_TAG" docker trust inspect --pretty "$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME" - # yamllint enable rule:line-length volumeMounts: - mountPath: /certs/client name: dind-certs + - mountPath: /task + name: task-volume sidecars: - image: docker:dind name: server @@ -197,3 +219,5 @@ spec: volumes: - name: dind-certs emptyDir: {} + - name: task-volume + emptyDir: {}