The Black Duck GKE Binary Authorization solution provides the ability to control container deployment into GKE by using attestations tied to Black Duck policies.  The Black Duck Policy Management feature enables you to create rules that govern your use of open source components in your code base, which can help you reduce open source security, license, and operational risks.  Black Duck's Binary Authorization solution is an add-on to the Synopsys Black Duck Cloud Build Solution, and creates an attestation based on the Black Duck policy violation status. The Black Duck attestation attests that a container has passed Black Duck policy and is ready for deployment.

Are you using Binary Authorization? The Synopsys Cloud Build Scanner can write Container Analysis Notes to an Attestor tied to Black Duck scan. If, a policy violation occurs during a Black Duck scan in CloudBuild,  an attestation will not be created and the image will not be deployable to GKE. 


IMPORTANT NOTES:

Please send any questions or suggestions to partner-solutions@synopsys.com.

Architecture

The following diagram shows the components in a Black Duck Binary Authorization Cloud Build setup:

The components are as follows:

Before you begin

There are several steps to prepare your GCP Project, GKE Cluster, and Cloud Build to attest a container image with Black Duck.

Set Up your Project and GKE Cluster

To use Binary Authorization, you must enable it for your Project and Cluster. The quickest way to achieve this, and become familiar with Binary Authorization is to use the Quickstart method.

Note: Do not delete the cluster, because it is required at a later stage.

Create a Service Account for Attesting

To perform an attestation, create a service account with the following permissions, or add them to the Cloud Build Service Account.

Create the Attestor for Black Duck and configure a policy that requires Black Duck attestation

The attestor is responsible for attesting that the Black Duck scan has completed before a container image can be deployed. Click Create an Attestor to learn about creating an attestor for Black Duck

When you configure the cryptographic keys, use the following values:

After creating the attestor, Configure a policy that blocks images from being deployed unless blackduck-scan attests the image. 

Encrypt your Black Duck API token, private key passphrase, and private key file by using KMS

As the private key that is associated with the Attestor is necessary to sign the Attestation Payload, you must make it available to the Synopsys Cloud Build scanner. 

To do this, you export the private key, encrypt it with KMS, and store it in a Cloud Storage bucket. At build time, the encrypted file is passed to Cloud Build, decrypted, used, and then destroyed. 

  1. Export the Private Key from the KeyPair created in the previous step.

    gpg --output pv_key.pgp --armor --export-secret-key $ATTESTOR_EMAIL


  2. Encrypt the file using KMS, then delete the original unencrypted file.

    gcloud kms encrypt --location global \
      --keyring [KEYRING-NAME] --key [KEY-NAME] \
      --plaintext-file pv_key.pgp \
      --ciphertext-file pv_key.pgp.enc


  3. Upload the encrypted file to a cloud storage bucket.

    gsutil mv pv_key.pgp.enc gs://[DESTINATION_BUCKET_NAME]/


  4. Encrypt the Black Duck API token that is generated from the Black Duck application.

    export BLACKDUCK_TOKEN=<<Token from Black Duck>>
     
    echo -n $BLACKDUCK_TOKEN | gcloud kms encrypt \
      --plaintext-file=- \  # - reads from stdin
      --ciphertext-file=- \  # - writes to stdout
      --location=global \
      --keyring=[KEYRING-NAME] \
      --key=[KEY-NAME] | base64


  5. Encrypt the private key passphrase

    export PV_PASSPHRASE=<<Passphrase for the Exported Private Key>>
    
    echo -n $PV_PASSPHRASE | gcloud kms encrypt \
      --plaintext-file=- \  # - reads from stdin
      --ciphertext-file=- \  # - writes to stdout
      --location=global \
      --keyring=[KEYRING-NAME] \
      --key=[KEY-NAME] | base64


Get the image that you to attest ready to pull in GCR

To perform an attestation, you must have an image to attest in GCR.
If you don't have one, follow the steps to push your own image to GCR, or follow the Synopsys Cloud Build example to build and push ducky-crm. 

Adding Black Duck Binary Authorization to Cloud Build

Scanning and Attesting an Image from GCR

You can use the cloudbuild.yaml file in your Cloud Build with minor substitutions, as long as all the pre-requisites are satisfied.
Replace the following values:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['pull', 'gcr.io/$PROJECT_ID/${_IMAGE_NAME}:${_IMAGE_TAG}'] #Pull the Docker Image you want to attest
- name: 'gcr.io/cloud-builders/docker'
  args: ['save', '-o', './${_IMAGE_NAME}.tar', 'gcr.io/$PROJECT_ID/${_IMAGE_NAME}:${_IMAGE_TAG}'] #Save the Docker Image to a TAR File
- name: 'gcr.io/cloud-builders/gcloud-slim'
  args: ['iam', 'service-accounts', 'keys', 'create', '${_SA_KEY_FILE}', '--iam-account', '<<Service Account Name>>@$PROJECT_ID.iam.gserviceaccount.com' ] #Create a Service Account Key
- name: 'gcr.io/cloud-builders/gsutil'
  args: [ 'cp', 'gs://<<Storage Bucket Name>>/${_PV_KEY_FILE}.enc', '.'] #Copy the encrypted Private Key file to the Cloud Build Worker
- name: 'gcr.io/cloud-builders/gcloud' #Decrypt all KMS Secrets using the Key Ring and Key Name
  args:
  - kms
  - decrypt
  - --ciphertext-file=${_PV_KEY_FILE}.enc
  - --plaintext-file=${_PV_KEY_FILE}
  - --location=global
  - --keyring=<<KMS KeyRing Name>>
  - --key=<<KMS Key Name>>
- name: 'gcr.io/cloud-marketplace/blackduck-public/synopsys-cloudbuild-scanner'
  secretEnv: [ 'PRIVATE_KEY_PASSWD', 'BD_TOKEN' ]
  args:
  - '--blackduck.url'
  - '<<Black Duck URL>>' #The URL of your Black Duck Instance
  - '--blackduck.api.token'
  - '$$BD_TOKEN' #Black Duck API Token decrypted by KMS
  - '--blackduck.trust.cert'
  - 'true' #Use this option if your instance of Black Duck has a self-signed certificate
  - '--detect.project.name'
  - '${_IMAGE_NAME}' #Project Name to map scan to in Black Duck UI
  - '--detect.project.version.name'
  - '${_IMAGE_TAG}' #Project Version to map scan to in Black Duck UI
  - '--detect.report.timeout'
  - '1200' #Set Timeout to prevent Detect from Timing Out while waiting for Policy Check
  - '--detect.tools' # List of Scanners to Run
  - 'SIGNATURE_SCAN'
  - '--detect.source.path' # Target for Signature Scan
  - './${_IMAGE_NAME}.tar'
  - '--detect.policy.check.fail.on.severities'
  - 'CRITICAL' #Will not generate an attestation if any CRITICAL policies are violated
  - '--binary.authorization.attestor.id'
  - 'blackduck-scan'
  - '--binary.authorization.attestor.private.key.file'
  - '${_PV_KEY_FILE}'
  - '--binary.authorization.image.path'
  - 'gcr.io/$PROJECT_ID/${_IMAGE_NAME}:${_IMAGE_TAG}'
  - '--binary.authorization.attestor.key.file'
  - '${_SA_KEY_FILE}'
substitutions:
  _IMAGE_NAME: <<IMAGE NAME TO SCAN>>
  _IMAGE_TAG: <<IMAGE TAG TO SCAN>>
  _SA_KEY_FILE: sa_key.json
  _PV_KEY_FILE: pv_key.pgp
secrets:
- kmsKeyName: projects/[PROJECT_ID]/locations/global/keyRings/[KEY_RING_NAME]/cryptoKeys/[KEY_NAME]
  secretEnv:
    BD_TOKEN: <<base64 encoded encrypted Black Duck API Token>>
    PRIVATE_KEY_PASSWD: <<base64 encoded encrypted Private Key Password>>