|
| 1 | +--- |
| 2 | +title: Secure supply chain - Automated approach |
| 3 | +weight: 35 |
| 4 | +aliases: /layered-zero-trust/lzt-automated-secure-supply-chain/ |
| 5 | +--- |
| 6 | + |
| 7 | +:toc: |
| 8 | +:imagesdir: /images |
| 9 | +:_mod-docs-content-type: ASSEMBLY |
| 10 | +include::modules/comm-attributes.adoc[] |
| 11 | + |
| 12 | +[id="lzt-automated-secure-supply-chain"] |
| 13 | += Use case: Secure Supply Chain - Automated Approach |
| 14 | + |
| 15 | +[role="_abstract"] |
| 16 | +In the previous section, we saw how to implement a secure supply chain for application development using Red{nbsp}Hat Trusted Artifact Signer (RHTAS) and the Red{nbsp}Hat Trusted Profile Analyzer (RHTPA). While that section explained how to perform this process manually, this document will cover how to automate it. |
| 17 | + |
| 18 | +To automate the application building and certifying process, we will use link:https://docs.redhat.com/en/documentation/red_hat_openshift_pipelines/1.20[Red{nbsp}Hat OpenShift Pipelines]. |
| 19 | + |
| 20 | +The Zero Trust Validated Pattern (ZTVP) will create a `Pipeline` in the cluster called `qtodo-supply-chain`. This pipeline will orchestrate the various tasks necessary to build the application from its source code, generate a container image, and publish the resulting image to the defined OCI registry. |
| 21 | + |
| 22 | +Within the pipeline, a Software Bill Of Materials (SBOM) containing the contents of the build is generated, binaries and the build attestation are signed, and the validity of those signatures is verified. |
| 23 | + |
| 24 | +[id="run-pipeline"] |
| 25 | +== How to run the pipeline |
| 26 | + |
| 27 | +You can run the pipeline using the {ocp} Web Console or the CLI. |
| 28 | + |
| 29 | +[id="run-pipeline-console"] |
| 30 | +=== Using {ocp} Web Console |
| 31 | + |
| 32 | +.Procedure |
| 33 | + |
| 34 | +. Launch the {ocp} Web console. |
| 35 | +. Select *Pipelines -> Pipelines* from the left-hand navigation bar. |
| 36 | +. Locate the `qtodo-supply-chain` pipeline. It is within the `layered-zero-trust-hub` project. |
| 37 | +. In the kebab menu (three vertical dots) from the right-hand side, select *Start*. |
| 38 | +. Review the configurable parameters. Most parameters should be correct with their default values if we are in single-cluster mode. However, double-check their values. |
| 39 | +. Configure the *workspaces* at the bottom manually: |
| 40 | +* For `qtodo-source`, select `PersistentVolumeClaim` and ensure the PVC name is `qtodo-workspace-source`. |
| 41 | +* For `registry-auth-config`, select `Secret` and ensure the name of the secret is `qtodo-registry-auth`. |
| 42 | +. Click *Start* to finish and run the pipeline. |
| 43 | + |
| 44 | +[id="run-pipeline-cli"] |
| 45 | +=== Using CLI |
| 46 | + |
| 47 | +You can also start a pipeline execution using a CLI and the Kubernetes API by creating a new `PipelineRun` resource referencing the `qtodo-supply-chain` pipeline. |
| 48 | + |
| 49 | +.Procedure |
| 50 | + |
| 51 | +. Create a new file called `qtodo-pipeline.yaml` with the following content: |
| 52 | ++ |
| 53 | +[source,yaml] |
| 54 | +---- |
| 55 | +apiVersion: tekton.dev/v1 |
| 56 | +kind: PipelineRun |
| 57 | +metadata: |
| 58 | + generateName: qtodo-manual-run- |
| 59 | + namespace: layered-zero-trust-hub |
| 60 | +spec: |
| 61 | + pipelineRef: |
| 62 | + name: qtodo-supply-chain |
| 63 | + taskRunTemplate: |
| 64 | + serviceAccountName: pipeline |
| 65 | + timeouts: |
| 66 | + pipeline: 1h0m0s |
| 67 | + workspaces: |
| 68 | + - name: qtodo-source |
| 69 | + persistentVolumeClaim: |
| 70 | + claimName: qtodo-workspace-source |
| 71 | + - name: registry-auth-config |
| 72 | + secret: |
| 73 | + secretName: qtodo-registry-auth |
| 74 | +---- |
| 75 | ++ |
| 76 | +Verify the values associated with the PVC storage and registry configuration as described previously. |
| 77 | + |
| 78 | +. Start a new execution of the pipeline using the `oc` CLI: |
| 79 | ++ |
| 80 | +[source,terminal] |
| 81 | +---- |
| 82 | +$ oc create -f qtodo-pipeline.yaml |
| 83 | +---- |
| 84 | + |
| 85 | +.Review pipeline logs |
| 86 | +You can review the current pipeline logs using the Tekton CLI: |
| 87 | + |
| 88 | +[source,terminal] |
| 89 | +---- |
| 90 | +$ tkn pipeline logs -n layered-zero-trust-hub -L -f |
| 91 | +---- |
| 92 | + |
| 93 | +[id="pipeline-tasks"] |
| 94 | +== Pipeline tasks |
| 95 | + |
| 96 | +The prepared pipeline consists of the following steps: |
| 97 | + |
| 98 | +* *qtodo-clone-repository*: Clones the `qtodo` repository. |
| 99 | +* *qtodo-build-artifact*: Builds an `uber-jar` of the `qtodo` application. |
| 100 | +* *qtodo-sign-artifact*: Signs the JAR file generated during the build process. |
| 101 | +* *qtodo-verify-artifact*: Verifies the JAR signature generated in the previous step. |
| 102 | +* *qtodo-build-image*: Builds a container with the `qtodo` application and uploads it to an image registry. |
| 103 | +* *qtodo-sign-image*: Signs the container image. |
| 104 | +* *qtodo-generate-sbom*: Generates an SBOM from the image. |
| 105 | +* *qtodo-sbom-attestation*: Creates a (signed) attestation, and attaches it to the image. |
| 106 | +* *qtodo-upload-sbom*: Uploads the generated SBOM file to RHTPA. |
| 107 | +* *qtodo-verify-image*: Verifies the attestation and the signature attached to the image. |
| 108 | + |
| 109 | +[id="inspect-results"] |
| 110 | +== Inspecting the results |
| 111 | + |
| 112 | +You can verify the status and output of the pipeline using the Web UI or the CLI. |
| 113 | + |
| 114 | +[id="inspect-results-ui"] |
| 115 | +=== {ocp} Web UI |
| 116 | + |
| 117 | +.Procedure |
| 118 | + |
| 119 | +. Launch the {ocp} Web console. |
| 120 | +. Select *Pipelines -> Pipelines* from the left-hand navigation bar. |
| 121 | +. Locate the `qtodo-supply-chain` pipeline in the `layered-zero-trust-hub` project. |
| 122 | +. Select the *PipelineRun* link in the *Last run* column. |
| 123 | +. In the *Details* tab, view the summary of the pipeline execution and tasks. |
| 124 | +. Click on each individual task or the *Logs* tab to see the output of specific tasks. |
| 125 | + |
| 126 | +[id="inspect-results-cli"] |
| 127 | +=== CLI |
| 128 | + |
| 129 | +.Procedure |
| 130 | + |
| 131 | +. Check if the pipeline has finished successfully: |
| 132 | ++ |
| 133 | +[source,terminal] |
| 134 | +---- |
| 135 | +$ oc get pipelinerun -n layered-zero-trust-hub |
| 136 | +
|
| 137 | +NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME |
| 138 | +qtodo-manual-run-p46f7 True Succeeded 7m4s 2m12s |
| 139 | +---- |
| 140 | + |
| 141 | +. Review the individual results of each step by reviewing the `TaskRuns`: |
| 142 | ++ |
| 143 | +[source,terminal] |
| 144 | +---- |
| 145 | +$ oc get taskruns -n layered-zero-trust-hub |
| 146 | +
|
| 147 | +NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME |
| 148 | +qtodo-manual-run-p46f7-qtodo-build-artifact True Succeeded 7m44s 5m17s |
| 149 | +qtodo-manual-run-p46f7-qtodo-build-image True Succeeded 4m55s 4m4s |
| 150 | +qtodo-manual-run-p46f7-qtodo-clone-repository True Succeeded 7m55s 7m44s |
| 151 | +... |
| 152 | +---- |
| 153 | + |
| 154 | +. Find the pods associated with the tasks in the `layered-zero-trust-hub` namespace: |
| 155 | ++ |
| 156 | +[source,terminal] |
| 157 | +---- |
| 158 | +$ oc get pods -n layered-zero-trust-hub |
| 159 | +
|
| 160 | +NAME READY STATUS RESTARTS AGE |
| 161 | +qtodo-manual-run-p46f7-qtodo-build-artifact-pod 0/1 Completed 0 10m |
| 162 | +qtodo-manual-run-p46f7-qtodo-build-image-pod 0/1 Completed 0 7m21s |
| 163 | +... |
| 164 | +---- |
| 165 | + |
| 166 | +. View the output of a particular step by checking the pod logs. For example, to view image verification messages: |
| 167 | ++ |
| 168 | +[source,terminal] |
| 169 | +---- |
| 170 | +$ oc logs -n layered-zero-trust-hub qtodo-manual-run-p46f7-qtodo-verify-image-pod |
| 171 | +
|
| 172 | +Success: true |
| 173 | +Result: SUCCESS |
| 174 | +Violations: 0, Warnings: 0, Successes: 3 |
| 175 | +Component: Unnamed |
| 176 | +ImageRef: quay-registry-quay-quay-enterprise.apps.example.com/ztvp/qtodo@sha256:df6506e93a141cfcaeb3b4686b558cddd963410a146b10c3cbd1319122f5f880 |
| 177 | +
|
| 178 | +Results: |
| 179 | +✓ [Success] builtin.attestation.signature_check |
| 180 | +... |
| 181 | +✓ [Success] builtin.image.signature_check |
| 182 | +... |
| 183 | +---- |
| 184 | + |
| 185 | +[id="review-services"] |
| 186 | +== Review the services |
| 187 | + |
| 188 | +The results of the supply chain are also visible in the different services used during the build process. |
| 189 | + |
| 190 | +[id="review-quay"] |
| 191 | +=== Quay |
| 192 | + |
| 193 | +If you used Quay as the image registry, you can review the built image inside the registry. |
| 194 | + |
| 195 | +.Procedure |
| 196 | + |
| 197 | +. Obtain the credentials to access the Quay web interface: |
| 198 | +* *Quay URL*: |
| 199 | ++ |
| 200 | +[source,terminal] |
| 201 | +---- |
| 202 | +$ echo "https://$(oc get route -n quay-enterprise \ |
| 203 | + -l quay-component=quay-app-route \ |
| 204 | + -o jsonpath='{.items[0].spec.host}')" |
| 205 | +---- |
| 206 | +* *Quay username*: The one specified in `values-hub.yaml` or `quay-user`. |
| 207 | +* *Quay password*: |
| 208 | ++ |
| 209 | +[source,terminal] |
| 210 | +---- |
| 211 | +$ oc get secret -n layered-zero-trust-hub qtodo-quay-password -o json | jq '.data["password"] | @base64d' |
| 212 | +---- |
| 213 | + |
| 214 | +. Launch the Quay Web UI and log in. |
| 215 | +. Locate and select the `ztvp/qtodo` repository. |
| 216 | +. In the left menu, select *Tags*. |
| 217 | +. Verify that the image's latest tag is signed (indicated by a shield icon) and that the image attestation (the `.att` file) is present. |
| 218 | + |
| 219 | +image::/images/layered-zero-trust/quay-web-ui.png[Quay Web UI] |
| 220 | + |
| 221 | +[id="review-rekor"] |
| 222 | +=== Rekor |
| 223 | + |
| 224 | +You can check the verification records by using the Rekor search UI in your web browser. You can search records by email address or record index. |
| 225 | + |
| 226 | +.Procedure |
| 227 | + |
| 228 | +. Obtain the URL for the Rekor Search UI: |
| 229 | ++ |
| 230 | +[source,terminal] |
| 231 | +---- |
| 232 | +$ echo "https://$(oc get route -n trusted-artifact-signer -l app.kubernetes.io/component=rekor-ui -o jsonpath='{.items[0].spec.host}')" |
| 233 | +---- |
| 234 | + |
| 235 | +image::/images/layered-zero-trust/rekor-web-ui.png[Rekor's Search UI] |
| 236 | + |
| 237 | +[id="review-rhtpa"] |
| 238 | +=== RHTPA |
| 239 | + |
| 240 | +The RHTPA web UI uses OIDC for user authentication. If you are using *Keycloak* integrated with the pattern, use the following commands to obtain the credentials. |
| 241 | + |
| 242 | +.Procedure |
| 243 | + |
| 244 | +. Obtain the credentials: |
| 245 | +* *RHTPA URL*: |
| 246 | ++ |
| 247 | +[source,terminal] |
| 248 | +---- |
| 249 | +$ echo "https://$(oc get route -n trusted-profile-analyzer \ |
| 250 | + -l app.kubernetes.io/name=server \ |
| 251 | + -o jsonpath='{.items[0].spec.host}')" |
| 252 | +---- |
| 253 | +* *RHTPA user*: `rhtpa-user` |
| 254 | +* *RHTPA user password*: |
| 255 | ++ |
| 256 | +[source,terminal] |
| 257 | +---- |
| 258 | +$ oc get secret keycloak-users -n keycloak-system -o json \ |
| 259 | + | jq '.data["rhtpa-user-password"] | @base64d' |
| 260 | +---- |
| 261 | + |
| 262 | +. Review the SBOM within the RHTPA web UI: |
| 263 | +.. Launch the RHTPA Web UI. |
| 264 | +.. Log in with Keycloak and the RHTPA credentials. |
| 265 | +.. Navigate to the *SBOMs* section via the left-hand menu. |
| 266 | +.. Select the entry corresponding to the name of the container image from the list of available SBOMs. |
| 267 | + |
| 268 | +image::/images/layered-zero-trust/rhtpa-web-ui.png[RHTPA Web UI] |
0 commit comments