├── .github └── workflows │ └── main.yaml ├── Dockerfile ├── README.md ├── hack └── build.sh ├── jenkins └── workshop │ ├── content │ ├── Fin.md │ ├── README.md │ ├── images │ │ ├── authorize_jenkins.png │ │ ├── authorize_jenkins_service.png │ │ ├── builds_pipelines.png │ │ ├── che-commit.png │ │ ├── che-commit_push.png │ │ ├── che-configure-git-name.png │ │ ├── che-configure-git-name2.png │ │ ├── che-create-workspace.png │ │ ├── che-edit-file.png │ │ ├── che-import-git.png │ │ ├── che-import-git2.png │ │ ├── che-import-maven.png │ │ ├── che-import-project.png │ │ ├── che-junit-success.png │ │ ├── che-open-workspace.png │ │ ├── che-run-tests.png │ │ ├── che-user_resource_fix.png │ │ ├── che_commit_push_git.png │ │ ├── cicd-pods.png │ │ ├── eclipse_che_workspace_start.png │ │ ├── gogs-webhook.png │ │ ├── gogs_home.png │ │ ├── gogs_route.png │ │ ├── golden_images.png │ │ ├── import_pipeline.png │ │ ├── import_yaml.png │ │ ├── import_yaml_json.png │ │ ├── jenkins_home.png │ │ ├── jenkins_integrated.png │ │ ├── jenkins_ocp_login.png │ │ ├── jenkins_pod.png │ │ ├── jenkins_skopeo_node.png │ │ ├── jenkinsfile_buildapp.png │ │ ├── jenkinsfile_buildapp_close.png │ │ ├── lab1_oc_coolstore_dev1.png │ │ ├── ocp-login.png │ │ ├── ocp-projects.png │ │ ├── ocp_cicd.png │ │ ├── oscap_report.png │ │ ├── pipeline.png │ │ ├── pipeline_actions_edit.png │ │ ├── pipeline_actions_edityaml.png │ │ ├── pipeline_build.png │ │ ├── pipeline_build_image.png │ │ ├── pipeline_container_scan.png │ │ ├── pipeline_create_dev.png │ │ ├── pipeline_deploy_dev.png │ │ ├── pipeline_deploy_stage.png │ │ ├── pipeline_execution.png │ │ ├── pipeline_failed_unittest.png │ │ ├── pipeline_nexus.png │ │ ├── pipeline_oc_build_image.png │ │ ├── pipeline_oscap.png │ │ ├── pipeline_promote.png │ │ ├── pipeline_sonar.png │ │ ├── pipeline_test.png │ │ ├── pipelinerun_buildapp.png │ │ ├── quay_creat_repo.png │ │ ├── quay_create_account.png │ │ ├── quay_create_repo.png │ │ ├── quay_image_stream.png │ │ ├── quay_login.png │ │ ├── quay_pipeline.png │ │ ├── quay_repo.png │ │ ├── quay_repo_config.png │ │ ├── quay_repo_tags.png │ │ ├── quay_scan.png │ │ ├── remove_ignore.png │ │ ├── rh_container_catalog.png │ │ ├── security_inheritance_model.png │ │ ├── sonarqube-analysis.png │ │ ├── tasks_pipeline.png │ │ ├── trusted_software_supply_chain.png │ │ └── wetty.png │ ├── index.md │ ├── lab01.md │ ├── lab02.md │ ├── lab03.md │ ├── lab04.md │ ├── lab05.md │ ├── lab06.md │ ├── lab07.md │ ├── lab08.md │ ├── lab09.md │ ├── lab10.md │ ├── lab11.md │ ├── lab12.md │ ├── lab13.md │ ├── lab14.md │ ├── lab15.md │ ├── lab16.md │ ├── lab17.md │ └── lab18.md │ ├── modules.yaml │ └── workshop.yaml └── tekton └── workshop ├── content ├── Fin.md ├── appendix.md ├── images │ ├── 16.3_coverage.png │ ├── 23.5_coverage.png │ ├── archive_pipeline_results.png │ ├── click_workspace.png │ ├── cluster_tasks.png │ ├── cluster_tasks_openshift_client.png │ ├── cmd_line_tools_download.png │ ├── cmd_line_tools_help.png │ ├── console_paste_yaml.png │ ├── console_pipeline_creation.png │ ├── deploy_to_dev_pipeline_results.png │ ├── devconsole_topology.png │ ├── developer_console_add.png │ ├── developer_console_image_from_intreg.png │ ├── devsecops-deployments.png │ ├── final_pipeline.png │ ├── full-pipeline-results.png │ ├── gitea_add_webhook_details.png │ ├── gitea_openshift_tasks.png │ ├── gitea_route.png │ ├── gitea_route_developer.png │ ├── gitea_settings_webhook.png │ ├── gitea_webhook_test_delivery.png │ ├── golden_images.png │ ├── grc_io_maven_images.png │ ├── import_yaml.png │ ├── maven_clustertask.png │ ├── maven_snapshots_tasks_war.png │ ├── nexus_artifacts_tasks.png │ ├── ocp-login.png │ ├── ocp_cicd.png │ ├── ocp_dashboard_persona.png │ ├── ocp_devsecops.png │ ├── openscap_report.png │ ├── openshift-pipeline-archive.png │ ├── openshift-pipeline-build.png │ ├── openshift-pipeline-create-dev.png │ ├── openshift-pipeline-imagebuilder.png │ ├── openshift-pipeline-openscap.png │ ├── openshift-pipeline-promote-stage.png │ ├── openshift-pipeline-quay.png │ ├── openshift-pipeline-sonarqube.png │ ├── openshift-pipeline-unittest.png │ ├── openshift-pipeline.png │ ├── pipeline_create_image_completed.png │ ├── pipeline_example.png │ ├── pipeline_fail.png │ ├── pipeline_results_container_vuln_scan.png │ ├── pipeline_start.png │ ├── pipeline_success.png │ ├── pipelinerun_logs.png │ ├── pipelinerun_overview.png │ ├── pipelinerun_resources_ui.png │ ├── pipelinerun_results_after_test.png │ ├── pipelines_integrated.png │ ├── push_git_fix.png │ ├── quay_clair_vulns_summary.png │ ├── quay_container_vuln_scan_queued.png │ ├── quay_new_repo.png │ ├── quay_repos.png │ ├── quay_vulns_details.png │ ├── reload_terminal.png │ ├── rerun_pipelinerun.png │ ├── rh_container_catalog.png │ ├── secure_software_factory.png │ ├── security_inheritance_model.png │ ├── simple-maven-pipeline.png │ ├── simple-pipelinerun-logs.png │ ├── sonarqube_pipelinerun_results.png │ ├── sonqarqube-tasks-dashboard.png │ ├── start-simple-pipeline.png │ ├── tekton-tasks-build-config.png │ ├── tekton-tasks-image-stream.png │ ├── tekton_tasks_build.png │ ├── tekton_tasks_imagestream.png │ ├── tekton_tasks_running.png │ ├── trusted_software_supply_chain.png │ ├── webhook_edit_readme.png │ ├── webhook_pipelinerun.png │ └── webhook_stage_pipeline.png ├── index.md ├── lab01.md ├── lab02.md ├── lab03.md ├── lab04.md ├── lab05.md ├── lab06.md ├── lab07.md ├── lab08.md ├── lab09.md ├── lab10.md ├── lab11.md ├── lab12.md ├── lab13.md ├── lab14.md ├── lab15.md ├── lab16.md └── lab17.md ├── modules.yaml └── workshop.yaml /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: Rebuild Workshop Dashboard 2 | 3 | on: 4 | schedule: 5 | - cron: '0 2 * * *' # everyday at 2am 6 | push: 7 | branches: 8 | - develop 9 | pull_request: 10 | branches: 11 | - develop 12 | 13 | 14 | jobs: 15 | release: 16 | runs-on: ubuntu-latest 17 | 18 | strategy: 19 | matrix: 20 | style: 21 | - tekton 22 | - jenkins 23 | 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v2 27 | 28 | - name: Set up Docker Buildx 29 | uses: docker/setup-buildx-action@v1 30 | 31 | - name: Build only 32 | run: hack/build.sh -l local -t ${{ matrix.style }} -- --build-arg=PIPELINE_STYLE=${{ matrix.style }} 33 | if: github.ref != 'refs/heads/develop' 34 | 35 | - name: Build and push 36 | run: hack/build.sh -l quay -t ${{ matrix.style }} -- --build-arg=PIPELINE_STYLE=${{ matrix.style }} 37 | env: 38 | DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} 39 | DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} 40 | if: github.ref == 'refs/heads/develop' 41 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/redhatgov/workshop-dashboard:latest 2 | ARG PIPELINE_STYLE 3 | 4 | USER root 5 | 6 | COPY ./$PIPELINE_STYLE /tmp/src 7 | 8 | RUN rm -rf /tmp/src/.git* && \ 9 | chown -R 1001 /tmp/src && \ 10 | chgrp -R 0 /tmp/src && \ 11 | chmod -R g+w /tmp/src 12 | 13 | ENV TERMINAL_TAB=split 14 | 15 | USER 1001 16 | 17 | RUN /usr/libexec/s2i/assemble 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DevSecOps Workshop - Secure Software Factory 2 | This repository houses the labguides for the latest iteration of the Red Hat NAPS DevSecOps workshop. 3 | 4 | ## Install 5 | 1. Login to an OpenShift cluster (tested on 4.4 or above) as a `cluster-admin` 6 | 2. Create a `CatalogSource` to import the RedHatGov operator catalog. 7 | ```bash 8 | oc apply -f - << EOF 9 | apiVersion: operators.coreos.com/v1alpha1 10 | kind: CatalogSource 11 | metadata: 12 | name: redhatgov-operators 13 | namespace: openshift-marketplace 14 | spec: 15 | sourceType: grpc 16 | image: quay.io/redhatgov/operator-catalog:latest 17 | displayName: Red Hat NAPS Community Operators 18 | publisher: RedHatGov 19 | EOF 20 | ``` 21 | 3. Create a project named **devsecops** for your pipeline tooling to live. 22 | ```bash 23 | oc create ns devsecops; oc project devsecops 24 | ``` 25 | 4. In the OpenShift Web Console, navigate to **Operators -> OperatorHub** and search for "DevSecOps Operator" in the **devsecops** project. Select it and click **Install** 26 | 5. Set **Installation Mode** to *A specific namespace on the cluster* and set **Installed Namespace** to *devsecops*. 27 | 6. Leave other options as default and click **Install** once more. 28 | 7. Create a `.dockerconfigjson` secret containing a pull token for registry.redhat.io. *If you're using an RHPDS-provisioned cluster, you can skip this step, since this secret is created as part of the default provisioning template.* 29 | It is recommended to generate a new service account before a workshop and delete it after, as this token is available in each of the users' projects (and can be used in the future if the service account isn't deleted). To get a service account: 30 | * Go to https://access.redhat.com/terms-based-registry/ 31 | * Login with your Red Hat credentials, then go to Service Accounts (upper right corner) and create a new service account. 32 | * Click on the name of the service account, go to the 'OpenShift Secret' tab, click 'view its contents' 33 | * Copy value after `.dockerconfigjson`. 34 | * Create your secret with this value: 35 | ```bash 36 | SECRET= 37 | 38 | oc apply -f - << EOF 39 | apiVersion: v1 40 | kind: Secret 41 | metadata: 42 | name: pull-secret 43 | namespace: devsecops 44 | data: 45 | .dockerconfigjson: $SECRET 46 | type: kubernetes.io/dockerconfigjson 47 | EOF 48 | ``` 49 | 8. On the DevSecOps Operator page, create a new `DevSecOpsWorkshop` CustomResource, setting the value of **Devsecopsworkshop -> Workshop Users -> numberOfUsers** as appropriate. 50 | 9. If you modified the namespace or name of your pull secret in Step 7, provide the corresponding values for **Devsecopsworkshop -> Pull Secret** as needed. Otherwise, you can leave this blank. 51 | 52 | ## Running the workshop 53 | Provide the URL of the `username-distribution` app to your workshop users. 54 | ``` 55 | oc get route -n devsecops username-distribution 56 | ``` 57 | It is here that they can request a workshop userID by providing their email address and the workshop password, which is `redhatgov`. Users will be issued a userID `(user1 .. userN)` on a first-come, first-served basis. You can access the administrator's view by navigating to the `/admin` context path of the username-distribution app in your browser. The credentials are stored in a secret called `username-distribution-secret` in the `devsecops` namespace. 58 | 59 | Once a user is granted a username, they'll have access to the **Module Urls** associated with this workshop, which in this case is just the workshop dashboard. The dashboard provides the following tabs: 60 | * Terminal 61 | * Console 62 | * CodeReady Workspaces 63 | * Chat - they'll need to login with their openshift credentials 64 | -------------------------------------------------------------------------------- /hack/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # change these 4 | CONTAINER_IMAGE=devsecops-workshop-dashboard 5 | DOCKERFILE_DIR= 6 | 7 | function print_usage() { 8 | echo "usage: $0 [-l (local|quay)] [-p QUAY_PROJECT] [-t CONTAINER_TAG] [-- BUILD_ARGS]" 9 | } 10 | 11 | # parse args 12 | while [ $# -gt 0 ]; do 13 | case "$1" in 14 | -l|--location=*) 15 | if [ "$1" = '-l' ]; then 16 | shift 17 | LOCATION="$1" 18 | else 19 | LOCATION=$(echo "$1" | cut -d= -f2-) 20 | fi 21 | ;; 22 | -p|--project=*) 23 | if [ "$1" = '-p' ]; then 24 | shift 25 | QUAY_PROJECT="$1" 26 | else 27 | QUAY_PROJECT=$(echo "$1" | cut -d= -f2-) 28 | fi 29 | ;; 30 | -t|--tag=*) 31 | if [ "$1" = '-t' ]; then 32 | shift 33 | CONTAINER_TAG="$1" 34 | else 35 | CONTAINER_TAG=$(echo "$1" | cut -d= -f2-) 36 | fi 37 | ;; 38 | --) 39 | shift 40 | break 41 | ;; 42 | *) 43 | print_usage >&2 44 | exit 127 45 | ;; 46 | esac 47 | shift 48 | done 49 | 50 | cd $(dirname $(realpath $0))/../$DOCKERFILE_DIR 51 | 52 | # some defaults 53 | if [ -f .quay_creds -a -z "$LOCATION" ]; then 54 | LOCATION=quay 55 | . .quay_creds 56 | elif [ -z "$LOCATION" ]; then 57 | LOCATION=local 58 | fi 59 | if [ -z "$QUAY_PROJECT" ]; then 60 | QUAY_PROJECT=redhatgov 61 | fi 62 | if [ -z "$CONTAINER_TAG" ]; then 63 | CONTAINER_TAG=latest 64 | fi 65 | 66 | # docker/podman problems 67 | if ! which docker &>/dev/null; then 68 | if which podman &>/dev/null; then 69 | function docker() { podman "${@}" ; } 70 | else 71 | echo "No docker|podman installed :(" >&2 72 | exit 1 73 | fi 74 | fi 75 | 76 | # build 77 | case $LOCATION in 78 | local) 79 | docker build "${@}" -t quay.io/$QUAY_PROJECT/$CONTAINER_IMAGE:$CONTAINER_TAG . 80 | ;; 81 | quay) 82 | # designed to be used by travis-ci, where the docker_* variables are defined 83 | if [ -z "$DOCKER_PASSWORD" -o -z "$DOCKER_USERNAME" ]; then 84 | echo "Requires DOCKER_USERNAME and DOCKER_PASSWORD variables to be exported." >&2 85 | exit 1 86 | fi 87 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin quay.io || exit 2 88 | 89 | docker build "${@}" -t quay.io/$QUAY_PROJECT/$CONTAINER_IMAGE:$CONTAINER_TAG . || exit 3 90 | docker push quay.io/$QUAY_PROJECT/$CONTAINER_IMAGE:$CONTAINER_TAG || exit 4 91 | ;; 92 | *) 93 | print_usage >&2 94 | exit 127 95 | ;; 96 | esac 97 | -------------------------------------------------------------------------------- /jenkins/workshop/content/Fin.md: -------------------------------------------------------------------------------- 1 | # That's it! 2 | Hopefully, you understand how to build a Trusted Software Supply Chain on OpenShift. 3 | -------------------------------------------------------------------------------- /jenkins/workshop/content/README.md: -------------------------------------------------------------------------------- 1 | # Must have existing OpenShift Environment 2 | You can use either of the OpenShift provsioners from RedHatGov 3 | - https://github.com/RedHatGov/redhatgov.workshops/tree/master/openshift-aws-setup 4 | - https://github.com/RedHatGov/redhatgov.workshops/tree/master/openshift_terraform 5 | - https://github.com/gnunn1/openshift-aws-setup 6 | - https://github.com/jaredhocutt/openshift-provision 7 | - https://github.com/bit4man/ansible_agnostic_deployer 8 | 9 | # Environment Setup 10 | If you'd like to setup an individual environment, use the commands below to set it up or delete the single environment. 11 | 12 | ## Help 13 | 14 | $ scripts/provision.sh --help 15 | 16 | ### Individual Environment 17 | 18 | $ scripts/provision.sh deploy --deploy-che --ephemeral 19 | 20 | ### Individual Delete 21 | 22 | $ scripts/provision.sh delete 23 | 24 | # Batch Setup 25 | If you'd like to setup the workshop for numerous users, go into the provision-batch-setup.sh script and update for loop with the amount of users . This will create an isolated environment per user. 26 | 27 | To run the script 28 | 29 | $ ./provision-batch-setup.sh 30 | 31 | # Batch Delete 32 | If you'd like to delete, run the script for the users you'd like to delete by updating the for loop 33 | 34 | To run the script 35 | 36 | $ ./provision-batch-delete.sh 37 | -------------------------------------------------------------------------------- /jenkins/workshop/content/images/authorize_jenkins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/authorize_jenkins.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/authorize_jenkins_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/authorize_jenkins_service.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/builds_pipelines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/builds_pipelines.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-commit.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-commit_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-commit_push.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-configure-git-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-configure-git-name.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-configure-git-name2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-configure-git-name2.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-create-workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-create-workspace.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-edit-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-edit-file.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-import-git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-import-git.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-import-git2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-import-git2.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-import-maven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-import-maven.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-import-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-import-project.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-junit-success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-junit-success.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-open-workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-open-workspace.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-run-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-run-tests.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che-user_resource_fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che-user_resource_fix.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/che_commit_push_git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/che_commit_push_git.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/cicd-pods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/cicd-pods.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/eclipse_che_workspace_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/eclipse_che_workspace_start.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/gogs-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/gogs-webhook.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/gogs_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/gogs_home.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/gogs_route.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/gogs_route.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/golden_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/golden_images.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/import_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/import_pipeline.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/import_yaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/import_yaml.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/import_yaml_json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/import_yaml_json.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkins_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkins_home.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkins_integrated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkins_integrated.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkins_ocp_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkins_ocp_login.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkins_pod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkins_pod.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkins_skopeo_node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkins_skopeo_node.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkinsfile_buildapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkinsfile_buildapp.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/jenkinsfile_buildapp_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/jenkinsfile_buildapp_close.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/lab1_oc_coolstore_dev1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/lab1_oc_coolstore_dev1.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/ocp-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/ocp-login.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/ocp-projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/ocp-projects.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/ocp_cicd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/ocp_cicd.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/oscap_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/oscap_report.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_actions_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_actions_edit.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_actions_edityaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_actions_edityaml.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_build.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_build_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_build_image.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_container_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_container_scan.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_create_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_create_dev.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_deploy_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_deploy_dev.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_deploy_stage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_deploy_stage.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_execution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_execution.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_failed_unittest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_failed_unittest.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_nexus.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_oc_build_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_oc_build_image.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_oscap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_oscap.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_promote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_promote.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_sonar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_sonar.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipeline_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipeline_test.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/pipelinerun_buildapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/pipelinerun_buildapp.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_creat_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_creat_repo.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_create_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_create_account.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_create_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_create_repo.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_image_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_image_stream.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_login.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_pipeline.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_repo.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_repo_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_repo_config.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_repo_tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_repo_tags.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/quay_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/quay_scan.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/remove_ignore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/remove_ignore.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/rh_container_catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/rh_container_catalog.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/security_inheritance_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/security_inheritance_model.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/sonarqube-analysis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/sonarqube-analysis.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/tasks_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/tasks_pipeline.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/trusted_software_supply_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/trusted_software_supply_chain.png -------------------------------------------------------------------------------- /jenkins/workshop/content/images/wetty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/jenkins/workshop/content/images/wetty.png -------------------------------------------------------------------------------- /jenkins/workshop/content/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: DevSecOps Workshop - Secure Software Factory 3 | menu: 4 | main: 5 | parent: workshops 6 | pre: fa fa-play-circle 7 | --- 8 | 9 | # Description 10 | In this workshop, you'll be building a Secure Software Factory for a Java based website leveraging several containerized tools such as Gogs, Nexus, Jenkins, Sonarqube, and Che hosted on the OpenShift Container Platform 11 | 12 | # Who Should Attend 13 | - Anyone who has had OpenShift 101 14 | - Architects 15 | - Developers 16 | - Technical leads 17 | - Operations Engineers 18 | 19 | # What you will learn 20 | - A tiny bit of Jenkins 21 | - Automating the development process 22 | - Trusted Software Supply Chain 23 | 24 | # Agenda 25 | - Introductions and Agenda 26 | - Familiarization with the Environment 27 | - Setting the Context 28 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab01.md: -------------------------------------------------------------------------------- 1 | This lab provides a quick tour of the console to help you get familiar with the user interface along with some key terminology we will use in subsequent lab content. 2 | 3 | # Key Terms 4 | We will be using the following terms throughout the workshop labs so here are some basic definitions you should be familiar with. You'll learn more terms along the way, but these are the basics to get you started. 5 | 6 | * Container - Your software wrapped in a complete filesystem containing everything it needs to run 7 | * Image - We are talking about docker images; read-only and used to create containers 8 | * Pod - One or more docker containers that run together 9 | * Service - Provides a common DNS name to access a pod (or replicated set of pods) 10 | * Project - A project is a group of services that are related logically 11 | * Deployment - an update to your application triggered by a image change or config change 12 | * Build - The process of turning your source code into a runnable image 13 | * BuildConfig - configuration data that determines how to manage your build 14 | * Route - a labeled and DNS mapped network path to a service from outside OpenShift 15 | * Master - The foreman of the OpenShift architecture; the master schedules operations, watches for problems, and orchestrates everything 16 | * Node - Where the compute happens; your software is run on nodes 17 | * Pipeline - Automates the control, building, deploying, and promoting your applications on OpenShift 18 | 19 | # Accessing OpenShift 20 | OpenShift provides a web console that allows you to perform various tasks via a web browser. Additionally, you can utilize a command line tool to perform tasks. Let's get started by logging into both of these and checking the status of the platform. 21 | 22 | ## Let's Login to the Web Console 23 | 24 |
25 | 26 | Open the Console tab in your dashboard, and you should see your available projects - or a button to create a project if none exist already. 27 | 28 | ## Let's try the 'oc' command line (CLI) tool 29 | Check to see what projects you have access to: 30 | 31 | ```execute 32 | oc get projects 33 | 34 | ``` 35 | 36 | Type the following command to show services, deployment configs, build configurations, and active deployments (this will come in handy later): 37 | 38 | ```execute 39 | oc status 40 | 41 | ``` 42 | 43 | # Summary 44 | You should now be ready to get hands-on with our workshop labs. 45 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab02.md: -------------------------------------------------------------------------------- 1 | The notion of Trusted Software Supply Chain is that of applying an assembly line approach to software that includes building increasing levels of assurance before marking an artifact as ready to deploy to production. 2 | 3 | In this workshop, you will use build orchestration tools such as Jenkins, Kubernetes, and OpenShift to support implementing and integrating [continuous delivery (CD)][1] as the foundation of automating the various stages of the deployment lifecycle are represented – from development, multiple types of testing, user acceptance, staging, to production release. 4 | 5 | 6 | 7 | For many organizations, obtaining Authority to Operate (ATO) is an arduous process requiring hundreds of pages of documentation, and can prevent organizations from adopting continuous delivery practices for fear of falling out of compliance. Each phase in our Trusted Software Supply Chain will have a policy defining the stage gate for success and will generate a documentation artifact that will later be used as part of the [ATO process][2]. 8 | 9 | Having a secure foundation for your applications is a key component to a Trusted Software Supply Chain. In the following lab exercises, your applications will inherit these security controls from the accredited OpenShift platform. 10 | 11 | The approach towards the Authorization and Accreditation (A&A) process with OpenShift follows a Landlord/Tenant model. OpenShift is a container application platform that provides a standardized operating environment and when assessing system boundaries, a delineation should be made between the OpenShift system itself, which operates as a Landlord, and the tenant application, which consumes the OpenShift service. 12 | 13 | 14 | 15 | In Landlord/Tenant system security plans (SSP), many security controls are inherited from the Landlord’s SSP, but some controls remain the responsibility of the OpenShift consumers. Following this division of responsibilities illustrated in the diagram above, some controls would be considered the responsibility of the tenant, whereas a good number of controls are already taken care of by the Landlord. 16 | 17 | [1]: https://en.wikipedia.org/wiki/Continuous_delivery 18 | [2]: https://cloud.gov/docs/compliance/ato-process/ 19 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab03.md: -------------------------------------------------------------------------------- 1 | Before moving forward, it is important to understand the difference between [Continuous Integration (CI), Continuous Delivery (CD), and Continuous Deployment][1]. 2 | 3 | Also, a part of this lab we’ll be using [Pipelines in OpenShift][2] for CI/CD, which gives you control over building, deploying, and promoting your applications on OpenShift. Using a combination of the Jenkins Pipeline Build Strategy, Jenkinsfiles, and the OpenShift Domain Specific Language (DSL) (provided by the OpenShift Jenkins Client Plug-in), you can create advanced build, test, deploy, and promote pipelines for any scenario. 4 | 5 | OK, let’s go ahead and start building an OpenShift CI/CD Pipeline using In the OpenShift Console. 6 | 7 | First, go to the CI/CD Project to the right. 8 | 9 |
10 | 11 | If the project does not exists, then use the CLI and goto the terminal and type the following: 12 | 13 | 14 | 15 | Once inside the CI/CD Project, you will see the following PODS running. This PODS are all leveraged in building our application. 16 | 17 | - Che pod - Eclipse Che is an open source browser based IDE. 18 | - Gogs pod - Gogs is an open source git server written in Go. 19 | - Nexus pod - Nexus is an artifact repository 20 | - Jenkins pod - Jenkins is an open source CI/CD tool 21 | - Sonarqube pod - SonarQube is an open source static code analysis tool 22 | 23 | It might take a few minutes for all PODS to be deployed. 24 | 25 |
26 | 27 |
28 | 29 | # The Flow of the Trusted Software Supply Chain 30 | 31 | - Jenkins is the CI/CD tool that will execute the project. 32 | - The Code is cloned from Gogs onto the Jenkins Executor Node. 33 | - The Code is built by Jenkins using Maven 34 | - JUnit Test are executed against the source code 35 | - In parallel, the source code is analyzed for vulnerabilities, bugs, and bad patterns by SonarQube 36 | - The WAR artifact is pushed to Nexus Repository manager 37 | - A container image (tasks:latest) is built based on the tasks application WAR artifact deployed on JBoss EAP 38 | - The tasks container image is deployed in a fresh container in DEV project 39 | - The DEV image is tagged with the application version (tasks:7.x) in the STAGE project 40 | - The staged image is deployed in a fresh container into the STAGE project 41 | 42 |
43 |
44 | 45 | [1]: https://stackoverflow.com/questions/28608015/continuous-integration-vs-continuous-delivery-vs-continuous-deployment 46 | [2]: https://docs.openshift.com/container-platform/3.11/dev_guide/openshift_pipeline.html 47 | 48 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab04.md: -------------------------------------------------------------------------------- 1 | Jenkins can be integrated with OpenShift in 3 ways. Today, you'll be working with a containerized Jenkins Server that's fully integrated with OpenShift. 2 | 3 | 4 | 5 | # Login through SSO with Jenkins 6 | 7 | Go into your CI/CD project and find the running Jenkins Pod. 8 | 9 | Click the external route (https://jenkins…) to go into your Jenkins Server 10 | 11 | 12 | 13 | Click Login with OpenShift. 14 | 15 | Login with your OpenShift Credentials. You maybe asked to accept authorizations. Go ahead and do so and re-login. 16 | 17 | 18 | 19 | You will be asked to authorize access to the jenkins service account. Go ahead and Allow selected permissions. 20 | 21 | 22 | 23 | 24 | You should now see the Jenkins Home Page 25 | 26 | 27 | 28 | Jenkins follows a master/agent architecture. Your pipeline will run a process called a Jenkins executor. A Jenkins executor is one of the basic building blocks which allow a build to run on an agent (e.g. build server). Think of an executor as a single “process ID”, or as the basic unit of resource that Jenkins executes on your machine to run a build. 29 | 30 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab05.md: -------------------------------------------------------------------------------- 1 | Today, you will be building your Trusted Software Supply Chain using a Jenkins Pipeline that is integrated with OpenShift. 2 | 3 | In addition to standard Jenkins Pipeline Syntax, the OpenShift Jenkins image provides the OpenShift Domain Specific Language (DSL) (through the OpenShift Jenkins Client Plug-in), which aims to provide a readable, concise, comprehensive, and fluent syntax for rich interactions with an OpenShift API server, allowing for even more control over the build, deployment, and promotion of applications on your OpenShift cluster. 4 | 5 | Please refer to the [OpenShift Jenkins Pipelin(DSL) Plugin examples documentation][1] for more info. 6 | 7 | First, we will need to create a [BuildConfig][2] that employs the [Pipeline Build][3] strategy for our Trusted Software Supply Chain. In the OpenShift Console, we’ll do this by clicking “Add to Project”, “Import YAML / JSON” while using the CI/CD project. 8 | 9 | 10 | 11 | Then copy & paste the following into the YAML/JSON input text field and click Create, 12 | 13 | ```copy 14 | apiVersion: v1 15 | kind: BuildConfig 16 | metadata: 17 | annotations: 18 | pipeline.alpha.openshift.io/uses: '[{"name": "jenkins", "namespace": "", "kind": "DeploymentConfig"}]' 19 | labels: 20 | app: cicd-pipeline 21 | name: cicd-pipeline 22 | name: tasks-pipeline 23 | spec: 24 | triggers: 25 | - type: GitHub 26 | github: 27 | secret: "secret101" 28 | - type: Generic 29 | generic: 30 | secret: "secret101" 31 | runPolicy: Serial 32 | source: 33 | type: None 34 | strategy: 35 | jenkinsPipelineStrategy: 36 | env: 37 | - name: DEV_PROJECT 38 | value: dev-%username% 39 | - name: STAGE_PROJECT 40 | value: stage-%username% 41 | jenkinsfile: |- 42 | def version, mvnCmd = "mvn -s configuration/cicd-settings-nexus3.xml" 43 | pipeline { 44 | agent { 45 | label 'maven' 46 | } 47 | 48 | ``` 49 | 50 | Close the window once it's imported. 51 | 52 | Then go to “Builds” → “Pipelines” tab. 53 | 54 | 55 | 56 | Verify that you see your "tasks pipeline" that you just imported. 57 | 58 | 59 | 60 | 61 | Click on the “tasks-pipeline” 62 | 63 | Click Actions -> Edit YAML 64 | 65 | Update your user Dev and Stage projects to make sure reflects your user #. 66 | 67 | ```copy 68 | strategy: 69 | jenkinsPipelineStrategy: 70 | env: 71 | - name: DEV_PROJECT 72 | value: dev-%username% 73 | - name: STAGE_PROJECT 74 | value: stage-%username% 75 | 76 | ``` 77 | 78 | Also, notice that we will be launching a Maven node/agent to execute our pipeline. 79 | 80 | You will also be declaring variables such as version and mvnCmd to be used later in the pipeline. 81 | 82 | The .xml file refers to maven configurations for your application. The reference to this .xml file from our pipeline can be seen here: 83 | 84 | ```copy 85 | jenkinsfile: |- 86 | def version, mvnCmd = "mvn -s configuration/cicd-settings-nexus3.xml" 87 | pipeline { 88 | agent { 89 | label 'maven' 90 | } 91 | 92 | ``` 93 | 94 | Click Save 95 | 96 | [1]: https://github.com/openshift/jenkins-client-plugin#examples 97 | [2]: https://docs.openshift.com/container-platform/3.11/dev_guide/builds/index.html#defining-a-buildconfig 98 | [3]: https://docs.openshift.com/container-platform/3.11/architecture/core_concepts/builds_and_image_streams.html#pipeline-build 99 | 100 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab06.md: -------------------------------------------------------------------------------- 1 | # Add Build App Stage to Pipeline Text File 2 | 3 | Next, you will add the Build App Stage to your pipeline. 4 | 5 | 6 | 7 | The git branch step will clone the openshift-tasks project with the git branch locally from your gogs server to your jenkins node. The jenkins node is leveraging the [git jenkins plugin][1] to communicate to gogs. 8 | 9 | Please note that we are leveraging the eap-7 branch in our git project and not the master branch. 10 | 11 |
12 | 13 | # Append to Jenkins Pipeline Configuration 14 | 15 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 16 | 17 | 18 | 19 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 20 | 21 | ```copy 22 | stages { 23 | stage('Build App') { 24 | steps { 25 | git branch: 'eap-7', url: 'http://gogs:3000/gogs/openshift-tasks.git' 26 | script { 27 | def pom = readMavenPom file: 'pom.xml' 28 | version = pom.version 29 | } 30 | sh "${mvnCmd} install -DskipTests=true" 31 | } 32 | } 33 | 34 | ``` 35 | 36 | Your Jenkinsfile should look like this. 37 | 38 | 39 |
40 | 41 | # Test Your Pipeline 42 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 43 | 44 | ```copy 45 | } 46 | } 47 | 48 | ``` 49 | 50 | Your Jenkinsfile should look like this 51 | 52 | 53 | 54 | Click Save 55 | 56 | Go back to Builds > Pipelines 57 | 58 | Click Start Pipeline 59 | 60 | You should see your first stage run successfully. 61 | 62 | 63 | 64 | # Delete Brackets 65 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 66 | 67 | ```copy 68 | } 69 | } 70 | 71 | ``` 72 | 73 | Click Save 74 | 75 | 76 |
77 | 78 | # View Source Code in Gogs 79 | 80 | View your gogs pod and click select the route (https://gogs...) to log into your gogs server. 81 | 82 | Use the user name and password given to you by your instructor. 83 | 84 |
85 | 86 | View the source of the openshift-tasks project in your gogs server. 87 | 88 |
89 | 90 |
91 | 92 | # Maven 93 | 94 | Maven install will run through the [Maven lifecycle][2] and skip the tests. We will execute tests later in the pipeline. 95 | 96 | - validate - validate the project is correct and all necessary information is available 97 | - compile - compile the source code of the project 98 | - test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed 99 | - package - take the compiled code and package it in its distributable format, such as a JAR. 100 | - verify - run any checks on results of integration tests to ensure quality criteria are met 101 | - install - install the package into the local repository, for use as a dependency in other projects locally 102 | - deploy - done in the build environment, copies the final package to the remote repository for sharing with other developers and projects. 103 | 104 | [1]: https://jenkins.io/doc/pipeline/steps/git/ 105 | [2]: https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html 106 | 107 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab07.md: -------------------------------------------------------------------------------- 1 | # Add Test Stage 2 | 3 | Add the configuration for the Test Stage below to your pipeline text file. 4 | 5 | 6 | 7 | Maven will run the test stage in the life cycle that we skipped at the previous stages. 8 | 9 | Maven will place the test results in the surefire-reports folder. The maven surefire-reports plugin allows for the generation of reports for your unit tests. 10 | 11 |
12 | 13 | # Append to Jenkins Pipeline Configuration 14 | 15 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 16 | 17 | 18 | 19 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 20 | 21 | ```copy 22 | stage('Test') { 23 | steps { 24 | sh "${mvnCmd} test" 25 | step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml']) 26 | } 27 | } 28 | 29 | ``` 30 | 31 | # Test Your Pipeline 32 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 33 | 34 | ```copy 35 | } 36 | } 37 | 38 | ``` 39 | 40 | Save your Jenkinsfile. 41 | 42 | Go back to Builds > Pipelines 43 | 44 | Click Start Pipeline 45 | 46 | # Delete Brackets 47 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 48 | 49 | ```copy 50 | } 51 | } 52 | 53 | ``` 54 | Click Save 55 | 56 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab08.md: -------------------------------------------------------------------------------- 1 | # Static Application Security Testing 2 | 3 | Next we will add a Code Analysis Stage into the pipeline. 4 | 5 | 6 | 7 | We will leverage the Maven Sonar plugin to run SonarQube scanning against our source code. 8 | 9 | SonarQube is an open source static code analysis tool that we can use to automate running security scans against your source code to further improve the security of your application. Every time you check-in code, SonarQube will scan the quality and perform a threat analysis of that code. 10 | 11 | We leverage the sonarqube maven plugin and specify the maven goal "sonar:sonar" to run our project leveraging the sonarqube api. 12 | 13 | SonarQube's security rules originate from these standards: 14 | 15 | * [CWE Database][1] - Common Weakness Enumeration (CWE™) is a formal list or dictionary of common software weaknesses that can occur in software's architecture, design, code or implementation that can lead to exploitable security vulnerabilities. 16 | 17 | * [SANS Top 25][2] - The SANS Top 25 list is a collection of the 25-most dangerous errors listed in the CWE, as compiled by the SANS organization. 18 | 19 | * [OWASP Top 10][3] - The OWASP Top 10 is a list of broad categories of weaknesses, each of which can map to many individual rules. 20 | 21 |
22 | 23 | # Append to Jenkins Pipeline Configuration 24 | 25 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 26 | 27 | 28 | 29 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 30 | 31 | 32 | ```copy 33 | stage('Code Analysis') { 34 | steps { 35 | script { 36 | sh "${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube:9000 -DskipTests=true" 37 | } 38 | } 39 | } 40 | 41 | ``` 42 |
43 | 44 | # SonarQube Dashboard 45 | 46 | Once we build the full pipeline and run it, we will log into SonarQube and view the various metrics, stats, and code coverage as seen from the screenshot below. 47 | 48 |
49 | 50 | # Test Your Pipeline 51 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 52 | 53 | ```copy 54 | } 55 | } 56 | 57 | ``` 58 | 59 | Save your Jenkinsfile. 60 | 61 | Go back to Builds > Pipelines 62 | 63 | Click Start Pipeline 64 | 65 | # Delete Brackets 66 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 67 | 68 | ```copy 69 | } 70 | } 71 | ``` 72 | Click Save 73 | 74 | [1]: http://cwe.mitre.org/about/index.html 75 | [2]: https://www.sans.org/top25-software-errors/ 76 | [3]: https://www.owasp.org/index.php/Top_10-2017_Top_10 77 | 78 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab09.md: -------------------------------------------------------------------------------- 1 | # Add Archive Stage 2 | 3 | Archiving the built and tested application into a trusted repository is important to making sure you are building with trusted parts. You assume this application is built properly and all the previous stages have passed. With that confidence, your built and tested application should be immutable in a trusted repository. The repository will version or audit any changes to the application, configuration, and dependencies. 4 | 5 | Add Archive Stage Steps into your pipeline. 6 | 7 | 8 | 9 | We leveraged the maven nexus plugin for this deployment. The mvn deploy step is the last step in the maven lifecycle. The built application is archived into the nexus repository. We can see it later once we run the pipeline. 10 | 11 | The "-P nexus3" option activates the nexus3 profile defined in the configuration/cicd-settings-nexus3.xml 12 | 13 |
14 | 15 | # Append to Jenkins Pipeline Configuration 16 | 17 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 18 | 19 | 20 | 21 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 22 | 23 | ```copy 24 | stage('Archive App') { 25 | steps { 26 | sh "${mvnCmd} deploy -DskipTests=true -P nexus3" 27 | } 28 | } 29 | 30 | ``` 31 | # Test Your Pipeline 32 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 33 | 34 | ```copy 35 | } 36 | } 37 | 38 | ``` 39 | 40 | Save your Jenkinsfile. 41 | 42 | Go back to Builds > Pipelines 43 | 44 | Click Start Pipeline 45 | 46 | # Delete Brackets 47 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 48 | 49 | ```copy 50 | } 51 | } 52 | 53 | ``` 54 | 55 | Click Save 56 | 57 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab10.md: -------------------------------------------------------------------------------- 1 | # Containers 2 | 3 | Containers are an important foundation for your application in building a Trusted Software Supply Chain. You want a secure and blessed golden container image that your application will inherit security controls from. 4 | 5 | Containers are built using a layered approach. For example, to create a container of a Java web application, you could do so in multiple layers: the OS, the JVM, the web server, and the code itself. 6 | 7 | 8 | 9 | We can incorporate CVE and vulnerability scanning against images in an automated fashion. Any image change is scanned to improve the inherited security of your application. We have partners such as Black Duck and Twistlock that do container image scanning. Also, as a result of Red Hat's acquisition of CoreOS, we now offer Quay as an enterprise-grade registry that does vulnerability scanning. 10 | 11 | We can also cryptographically sign your image so you know your container is running with a verified container image. 12 | 13 |
14 | 15 | # Start with Quality Parts 16 | 17 | Red Hat has a container registry that provides certified Red Hat and third-party container images that will be the foundation of your container images. Our Registry also has a health index of the image so you know the state of the image. 18 | 19 | 20 | 21 |
22 | 23 | # Add Create Image Builder Stage 24 | 25 | Next we will add the Create [Image Builder][1] Stage into your pipeline. 26 | 27 | 28 | 29 | This step will create a new build. We will be leveraging a trusted JBoss EAP 7 container. 30 | 31 | The golden image will will be using for our applications is jboss-eap70-openshift:1.5. Again, you'll want a hardened, secured, patched and up to date container image as a foundation for your application. 32 | 33 |
34 | 35 | # Append to Jenkins Pipeline Configuration 36 | 37 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 38 | 39 | 40 | 41 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 42 | 43 | 44 | ```copy 45 | stage('Create Image Builder') { 46 | when { 47 | expression { 48 | openshift.withCluster() { 49 | openshift.withProject(env.DEV_PROJECT) { 50 | return !openshift.selector("bc", "tasks").exists(); 51 | } 52 | } 53 | } 54 | } 55 | steps { 56 | script { 57 | openshift.withCluster() { 58 | openshift.withProject(env.DEV_PROJECT) { 59 | openshift.newBuild("--name=tasks", "--image-stream=jboss-eap70-openshift:1.5", "--binary=true") 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | ``` 67 | 68 | # Test Your Pipeline 69 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 70 | 71 | ```copy 72 | } 73 | } 74 | 75 | ``` 76 | 77 | Save your Jenkinsfile. 78 | 79 | Go back to Builds > Pipelines 80 | 81 | Click Start Pipeline 82 | 83 | # Delete Brackets 84 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 85 | 86 | ``` 87 | } 88 | } 89 | ``` 90 | Click Save 91 | 92 | [1]: https://docs.openshift.com/container-platform/3.11/architecture/core_concepts/builds_and_image_streams.html 93 | 94 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab11.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Lab 11 - Build Image 3 | workshops: secure_software_factory 4 | workshop_weight: 21 5 | layout: lab 6 | --- 7 | # Add Build Image Stage 8 | 9 | Add the Build Image Stage into your pipeline. 10 | 11 | 12 | 13 | The "sh" are shell commands in your pipeline that are executed on the Jenkins Slave. Maven built the openshift-tasks.war in it the target directory and it will be copied into the created oc-builds directory. 14 | 15 | The startBuild stage is kicked off from Openshift and pointing to the local directory "oc-build" on the Jenkins slave. 16 | 17 |
18 | 19 | # Append to Jenkins Pipeline Configuration 20 | 21 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 22 | 23 | 24 | 25 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 26 | 27 | ```copy 28 | stage('Build Image') { 29 | steps { 30 | sh "rm -rf oc-build && mkdir -p oc-build/deployments" 31 | sh "cp target/openshift-tasks.war oc-build/deployments/ROOT.war" 32 | 33 | script { 34 | openshift.withCluster() { 35 | openshift.withProject(env.DEV_PROJECT) { 36 | openshift.selector("bc", "tasks").startBuild("--from-dir=oc-build", "--wait=true") 37 | } 38 | } 39 | } 40 | } 41 | } 42 | 43 | ``` 44 | # Test Your Pipeline 45 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 46 | 47 | ```copy 48 | } 49 | } 50 | 51 | ``` 52 | 53 | Save your Jenkinsfile. 54 | 55 | Go back to Builds > Pipelines 56 | 57 | Click Start Pipeline 58 | 59 | # Delete Brackets 60 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 61 | 62 | ```copy 63 | } 64 | } 65 | 66 | ``` 67 | Click Save 68 | 69 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab12.md: -------------------------------------------------------------------------------- 1 | # Add Create Dev Stage 2 | 3 | Add Create Dev Stage into the pipeline. 4 | 5 | 6 | 7 | We first check if an deployment config for the Dev Project already exists. If it does not exists, a new application is created and deployment config is defined for the Dev Project. 8 | 9 | Before a trigger is created, the pipeline sleeps for 10 seconds. A deployment configuration can contain triggers, which drive the creation of new deployment processes in response to events inside the cluster. In this case, the trigger is set to a manual deployment of the tasks deployment config. The deployment will happen in Deploy Stage. 10 | 11 |
12 | 13 | # Append to Jenkins Pipeline Configuration 14 | 15 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 16 | 17 | 18 | 19 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 20 | 21 | ```copy 22 | stage('Create DEV') { 23 | when { 24 | expression { 25 | openshift.withCluster() { 26 | openshift.withProject(env.DEV_PROJECT) { 27 | return !openshift.selector('dc', 'tasks').exists() 28 | } 29 | } 30 | } 31 | } 32 | steps { 33 | script { 34 | openshift.withCluster() { 35 | openshift.withProject(env.DEV_PROJECT) { 36 | def app = openshift.newApp("tasks:latest") 37 | app.narrow("svc").expose(); 38 | 39 | def dc = openshift.selector("dc", "tasks") 40 | while (dc.object().spec.replicas != dc.object().status.availableReplicas) { 41 | sleep 10 42 | } 43 | openshift.set("triggers", "dc/tasks", "--manual") 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | ``` 51 | 52 | # Deploy Dev Stage 53 | 54 | Enter the Deploy Dev Stage to your pipeline text file. 55 | 56 | 57 | 58 | OpenShift deploys the application and it's deployment configuration to Dev as previously defined from the Create Dev Stage. 59 | 60 |
61 | 62 | # Append to Jenkins Pipeline Configuration 63 | 64 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 65 | 66 | 67 | 68 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 69 | 70 | 71 | ```copy 72 | stage('Deploy DEV') { 73 | steps { 74 | script { 75 | openshift.withCluster() { 76 | openshift.withProject(env.DEV_PROJECT) { 77 | openshift.selector("dc", "tasks").rollout().latest(); 78 | } 79 | } 80 | } 81 | } 82 | } 83 | 84 | ``` 85 | 86 | 87 | # Test Your Pipeline 88 | If you'd like to do a test of first pipeline stage, add the following brackets at the end of your Jenkinsfile. Make sure to append to the beginning of the last line. 89 | 90 | ```copy 91 | } 92 | } 93 | 94 | ``` 95 | 96 | Save your Jenkinsfile. 97 | 98 | Go back to Builds > Pipelines 99 | 100 | Click Start Pipeline 101 | 102 | # Delete Brackets 103 | Please delete the brackets you just added once testing is complete. We can add them later if you'd like to test your pipeline as you go along. 104 | 105 | ``` 106 | } 107 | } 108 | ``` 109 | Click Save 110 | 111 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab13.md: -------------------------------------------------------------------------------- 1 | # Add Promote to Stage 2 | Enter the Promote to STAGE below into your pipeline. 3 | 4 | 5 | 6 | We set an approval to promote to the application to the Stage Project. The approval process is a good feature for various gates of your deployments. We also set a 15 minute timeout on the approval. You also tag the tasks image with latest and the version from the pom file. 7 | 8 |
9 | 10 | # Append to Jenkins Pipeline Configuration 11 | 12 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 13 | 14 | 15 | 16 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 17 | 18 | ```copy 19 | stage('Promote to STAGE?') { 20 | steps { 21 | timeout(time:15, unit:'MINUTES') { 22 | input message: "Promote to STAGE?", ok: "Promote" 23 | } 24 | 25 | script { 26 | openshift.withCluster() { 27 | openshift.tag("${env.DEV_PROJECT}/tasks:latest", "${env.STAGE_PROJECT}/tasks:${version}") 28 | } 29 | } 30 | } 31 | } 32 | 33 | ``` 34 | 35 | # Add Deploy Stage 36 | 37 | Add the Deploy Stage into your pipeline. 38 | 39 | 40 | 41 | If the deployment config for the application already exists in the Stage Project or Environment the deployment config , service, and route are deleted. This allows for the pipeline to be rerun. 42 | 43 | The new-app is recreated in the Stage Environment from the image that you tagged in the previous stage. The image also has a route created for with the svc.expose command. 44 | 45 | 46 |
47 | 48 | # Append to Jenkins Pipeline Configuration 49 | 50 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 51 | 52 | 53 | 54 | Append the text below to the bottom of the Jenkins Pipeline Configuration. Please make sure to append to the beginning of the next line. 55 | 56 | 57 | ```copy 58 | stage('Deploy STAGE') { 59 | steps { 60 | script { 61 | openshift.withCluster() { 62 | openshift.withProject(env.STAGE_PROJECT) { 63 | if (openshift.selector('dc', 'tasks').exists()) { 64 | openshift.selector('dc', 'tasks').delete() 65 | openshift.selector('svc', 'tasks').delete() 66 | openshift.selector('route', 'tasks').delete() 67 | } 68 | 69 | openshift.newApp("tasks:${version}").narrow("svc").expose() 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | ``` 79 | 80 | Congratulations, this should be the final step in your Trusted Software Supply Chain. Go on to the next lab to verify and run the pipeline. 81 | 82 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab14.md: -------------------------------------------------------------------------------- 1 | # Verify Completed Pipeline 2 | 3 | Before we kick off your pipeline, let's verify it. 4 | 5 | In Builds > Pipelines > tasks-pipeline > Actions > Edit YAML 6 | 7 | 8 | 9 | Take a look and see if it matches the below text. If not, please correct it. 10 | 11 | ```copy 12 | apiVersion: v1 13 | kind: BuildConfig 14 | metadata: 15 | annotations: 16 | pipeline.alpha.openshift.io/uses: '[{"name": "jenkins", "namespace": "", "kind": "DeploymentConfig"}]' 17 | labels: 18 | app: cicd-pipeline 19 | name: cicd-pipeline 20 | name: tasks-pipeline 21 | spec: 22 | triggers: 23 | - type: GitHub 24 | github: 25 | secret: "secret101" 26 | - type: Generic 27 | generic: 28 | secret: "secret101" 29 | runPolicy: Serial 30 | source: 31 | type: None 32 | strategy: 33 | jenkinsPipelineStrategy: 34 | env: 35 | - name: DEV_PROJECT 36 | value: dev-%username% 37 | - name: STAGE_PROJECT 38 | value: stage-%username% 39 | jenkinsfile: |- 40 | def version, mvnCmd = "mvn -s configuration/cicd-settings-nexus3.xml" 41 | 42 | pipeline { 43 | agent { 44 | label 'maven' 45 | } 46 | stages { 47 | stage('Build App') { 48 | steps { 49 | git branch: 'eap-7', url: 'http://gogs:3000/gogs/openshift-tasks.git' 50 | script { 51 | def pom = readMavenPom file: 'pom.xml' 52 | version = pom.version 53 | } 54 | sh "${mvnCmd} install -DskipTests=true" 55 | } 56 | } 57 | stage('Test') { 58 | steps { 59 | sh "${mvnCmd} test" 60 | step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml']) 61 | } 62 | } 63 | stage('Code Analysis') { 64 | steps { 65 | script { 66 | sh "${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube:9000 -DskipTests=true" 67 | } 68 | } 69 | } 70 | stage('Archive App') { 71 | steps { 72 | sh "${mvnCmd} deploy -DskipTests=true -P nexus3" 73 | } 74 | } 75 | stage('Create Image Builder') { 76 | when { 77 | expression { 78 | openshift.withCluster() { 79 | openshift.withProject(env.DEV_PROJECT) { 80 | return !openshift.selector("bc", "tasks").exists(); 81 | } 82 | } 83 | } 84 | } 85 | steps { 86 | script { 87 | openshift.withCluster() { 88 | openshift.withProject(env.DEV_PROJECT) { 89 | openshift.newBuild("--name=tasks", "--image-stream=jboss-eap70-openshift:1.5", "--binary=true") 90 | } 91 | } 92 | } 93 | } 94 | } 95 | stage('Build Image') { 96 | steps { 97 | sh "rm -rf oc-build && mkdir -p oc-build/deployments" 98 | sh "cp target/openshift-tasks.war oc-build/deployments/ROOT.war" 99 | 100 | script { 101 | openshift.withCluster() { 102 | openshift.withProject(env.DEV_PROJECT) { 103 | openshift.selector("bc", "tasks").startBuild("--from-dir=oc-build", "--wait=true") 104 | } 105 | } 106 | } 107 | } 108 | } 109 | stage('Create DEV') { 110 | when { 111 | expression { 112 | openshift.withCluster() { 113 | openshift.withProject(env.DEV_PROJECT) { 114 | return !openshift.selector('dc', 'tasks').exists() 115 | } 116 | } 117 | } 118 | } 119 | steps { 120 | script { 121 | openshift.withCluster() { 122 | openshift.withProject(env.DEV_PROJECT) { 123 | def app = openshift.newApp("tasks:latest") 124 | app.narrow("svc").expose(); 125 | 126 | def dc = openshift.selector("dc", "tasks") 127 | while (dc.object().spec.replicas != dc.object().status.availableReplicas) { 128 | sleep 10 129 | } 130 | openshift.set("triggers", "dc/tasks", "--manual") 131 | } 132 | } 133 | } 134 | } 135 | } 136 | stage('Deploy DEV') { 137 | steps { 138 | script { 139 | openshift.withCluster() { 140 | openshift.withProject(env.DEV_PROJECT) { 141 | openshift.selector("dc", "tasks").rollout().latest(); 142 | } 143 | } 144 | } 145 | } 146 | } 147 | stage('Promote to STAGE?') { 148 | steps { 149 | timeout(time:15, unit:'MINUTES') { 150 | input message: "Promote to STAGE?", ok: "Promote" 151 | } 152 | 153 | script { 154 | openshift.withCluster() { 155 | openshift.tag("${env.DEV_PROJECT}/tasks:latest", "${env.STAGE_PROJECT}/tasks:${version}") 156 | } 157 | } 158 | } 159 | } 160 | stage('Deploy STAGE') { 161 | steps { 162 | script { 163 | openshift.withCluster() { 164 | openshift.withProject(env.STAGE_PROJECT) { 165 | if (openshift.selector('dc', 'tasks').exists()) { 166 | openshift.selector('dc', 'tasks').delete() 167 | openshift.selector('svc', 'tasks').delete() 168 | openshift.selector('route', 'tasks').delete() 169 | } 170 | 171 | openshift.newApp("tasks:${version}").narrow("svc").expose() 172 | } 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | type: JenkinsPipeline 180 | 181 | ``` 182 | 183 |
184 | 185 | # Verify your user Dev and Stage projects 186 | 187 | In your pipeline text file, make sure \ reflects your user # and project. 188 | 189 | ```copy 190 | - name: DEV_PROJECT 191 | value: dev-%username% 192 | - name: STAGE_PROJECT 193 | value: stage-%username% 194 | 195 | ``` 196 | 197 |
198 | 199 | # Import pipeline into OpenShift (if not created already) 200 | 201 | If you created your pipeline in a text editor, you can import your text file in OpenShift. 202 | 203 | At the top right select Add to Project > Import YAML / JSON 204 | 205 |
206 | 207 | 208 | Copy and Paste your pipeline from your text editor to your 209 | 210 | Click Create and Close 211 | 212 |
213 | 214 |
215 | 216 | # Run Pipeline 217 | 218 | Go to Builds > Pipeline 219 | 220 | Click Start Pipeline for the pipeline you just created called tasks-pipeline. 221 | 222 | Your pipeline should now execute through all the stages you created. 223 | 224 | Go ahead and click View Log. This will take you to the Jenkins logs and you can follow the various stages in your pipeline. 225 | 226 | When it asks to promote to stage, go ahead and promote it. 227 | 228 |
229 | 230 |
231 | 232 | # Explore Pipeline Run 233 | - Explore the snapshots repository in Nexus and verify tasks is pushed to the repository 234 | - Explore SonarQube and show the metrics, stats, code coverage, etc 235 | - Explore Tasks - Dev project in OpenShift console and verify the application is deployed in the DEV environment 236 | - Explore Tasks - Stage project in OpenShift console and verify the application is deployed in the STAGE environment 237 | 238 | Sonarqube metrics, stats, and code coverage can be seen such as this screenshot below. 239 | 240 |
241 | 242 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab15.md: -------------------------------------------------------------------------------- 1 | # Trigger the Trusted Software Supply Chain with Code Check-ins 2 | 3 | Through automation, you will trigger the Trusted Software Supply Chain with code check-ins. 4 | 5 |
6 | 7 | # Verify Webhook in Gogs 8 | 9 | The Webhook is what triggers your pipeline upon code check-ins. You want your SCM to trigger the pipeline as opposed to Jenkins constantly polling the source code for changes. 10 | 11 | Click on the Gogs route url in the CI/CD project which takes you to the home page. Sign in using the credentials given to you by your Instructor. 12 | 13 | Go to the openshift-tasks repository. 14 | 15 | Select Settings. 16 | 17 | Select Webhooks 18 | 19 | Verify the Webhook. Make sure the url includes the name 'tasks-pipeline' of the your imported pipeline. 20 | 21 |
22 | 23 | This should match the webhook of the pipeline you previously created except the domain will be openshift.default.svc.cluster.local because the gogs pod calls the internal dns to resolve the address. 24 | 25 | The webhook url is located in builds > pipeline > tasks-pipeline > configuration > generic webhook url 26 | 27 |
28 | 29 | # Using Eclipse Che for Editing Code 30 | 31 | Click on Eclipse Che route url in the CI/CD project which takes you to the workspace administration page. Select the Java stack and click on the Create button to create a workspace for yourself. 32 | 33 |

34 | 35 | You may need to start the workspace. Click Start. 36 | 37 |

38 | 39 | It might take a little while before your workspace is set up and ready to be used in your browser. Once it's ready, click on Import Project in order to import the openshift-tasks Gogs repository into your workspace. 40 | 41 |

42 | 43 | Enter the Gogs repository http url for openshift-tasks as the Git repository url with Git username and password in the url. You can copy this link from your Gogs using the link to clone the openshift-tasks project. 44 | 45 | See the url below as an example. 46 | 47 | - Replace [gogs-hostname] with your gogs server. 48 | - http://gogs:gogs@[gogs-hostname]/gogs/openshift-tasks.git 49 | - So it should look something like this: 50 | - {{< urishortfqdn "http://gogs:gogs@" "master" "" >}}/gogs/openshift-tasks.git 51 | 52 | You can find the repository url in Gogs web console. 53 | 54 | **Important: Make sure to check the Branch field and enter eap-7 in order to clone the eap-7 branch which is used in this demo.** 55 | 56 | Click on Import 57 | 58 |

59 | 60 | Change the project configuration to Maven and then click Save 61 | 62 | 63 |

64 | 65 | Configure you name and email to be stamped on your Git commity by going to Profile > Preferences > Git > Committer. Click Save and Close the Window once Saved. 66 | 67 |

68 | 69 |
70 | # Edit Code in your Workspace 71 | 72 | Remove the @Ignore annotation from src/test/java/org/jboss/as/quickstarts/tasksrs/service/UserResourceTest.java test methods to enable the unit tests. 73 | 74 |

75 | 76 | Click the Git Menu at the top > Commit 77 | 78 |

79 | 80 | **Important: Mare sure you select the check mark for "Push committed changes to: orgin/eap-7"** 81 | 82 | Click Commit 83 | 84 |

85 | 86 | Check out Jenkins, a pipeline instance is created and is being executed. The pipeline will fail during unit tests due to the enabled unit test. 87 | 88 |

89 | 90 | Fix the test by modifying src/main/java/org/jboss/as/quickstarts/tasksrs/service/UserResource.java and uncommenting the sort function in getUsers method. 91 | 92 | You can use CTRL+/ to uncomment multiple lines 93 | 94 |

95 | 96 | 97 | Click on Git > Commit to commit the changes to the openshift-tasks git repository. Make sure Push commited changes to: origin/eap7 is checked. Click on Commit button. 98 | 99 |

100 | 101 | As soon the changes are committed to the git repository, a new instances of pipeline gets triggers to test and deploy the code changes. 102 | 103 | Go Back to OpenShift and Promote to Stage to finish your Pipeline Run 104 | 105 |

106 | 107 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab16.md: -------------------------------------------------------------------------------- 1 | # Create Quay Account 2 | 3 | Please go to the Quay Login with the link given to you by your instructor 4 | 5 | Click Create Account at the bottom of the page. 6 | 7 |
8 | 9 |
10 | 11 | Fill in the account information for Quay. 12 | 13 | - Username: %username% 14 | - E-mail address: your email address 15 | - Password: openshift 16 | - Confirm Password: openshift 17 | 18 | Click Create Account 19 | 20 |
21 | 22 |
23 | 24 |
25 | 26 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab17.md: -------------------------------------------------------------------------------- 1 | # Add Clair Container Scan 2 | 3 | Add the configuration for the Container Vulnerability Scan below to your pipeline text file. 4 | 5 |
6 | 7 |
8 | 9 | # Append to Jenkins Pipeline Configuration 10 | 11 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 12 | 13 | 14 | 15 | In your pipeline, add and update the following variables after the version and mvnCmd definitions. Please fill in the values between the quotes. 16 | 17 | - ocuser : the openshift user given to you by your insturctor 18 | - ocpass : the openshift password given to you by your insturctor 19 | - ocp : the openshift host given to you by your instuctor 20 | - quayuser : the quay user you created previously 21 | - quaypass : the quay password you created previously 22 | - quayrepo : the quay repo you will push your app image to i.e. tasks 23 | 24 | 25 | ```copy 26 | def ocuser = " " 27 | def ocpass = " " 28 | def ocp = " " 29 | def quayuser = " " 30 | def quaypass = " " 31 | def quayrepo = " " 32 | 33 | ``` 34 | 35 | For Example: 36 | 37 | ```copy 38 | def ocuser = "%username%" 39 | def ocpass = "openshift" 40 | def ocp = "{{< urishortfqdn "" "master" "" >}}" 41 | def quayuser = "%username%" 42 | def quaypass = "openshift" 43 | def quayrepo = "jboss-eap70-openshift" 44 | 45 | ``` 46 | 47 | In your pipeline, replace the Jenkins agent 'maven' with 'jenkins-slave-image-mgmt'. 48 | 49 | ```copy 50 | pipeline { 51 | agent { 52 | label 'jenkins-slave-image-mgmt' 53 | } 54 | 55 | ``` 56 | 57 | In your pipeline, add the Vulnerability Scan Stage after the Build Image Stage. 58 | 59 | ```copy 60 | stage('Clair Container Vulnerability Scan') { 61 | steps { 62 | sh "oc login -u $ocuser -p $ocpass --insecure-skip-tls-verify https://$ocp 2>&1" 63 | sh 'skopeo --debug copy --src-creds="$(oc whoami)":"$(oc whoami -t)" --src-tls-verify=false --dest-tls-verify=false' + " --dest-creds=$quayuser:$quaypass docker://docker-registry.default.svc:5000/cicd-$ocuser/jboss-eap70-openshift:1.5 docker://quay.apps.$ocp/$quayuser/$quayrepo:1.5" 64 | } 65 | } 66 | 67 | ``` 68 | 69 | Save your Jenkins file 70 | 71 | # Run Pipeline 72 | 73 | Go to Builds > Pipeline 74 | 75 | Click Start Pipeline for the pipeline you just created called tasks-pipeline. 76 | 77 | Your pipeline should now execute through all the stages you created. 78 | 79 | Go ahead and click View Log. This will take you to the Jenkins logs and you can follow the various stages in your pipeline. 80 | 81 | When it asks to promote to stage, go ahead and promote it. 82 | 83 |
84 | 85 |
86 | 87 | # View Clair Container Scan Report in Quay 88 | 89 | Select the Repository that was created 90 | 91 |
92 | 93 |
94 | 95 | Select Repository Tags on the left hand menu 96 | 97 | - If your scan is queued, you will need to wait for the scan to finish to view the report 98 | 99 | Select the Security Scan for your Image 100 | 101 |
102 | 103 |
104 | 105 | View the Security Scan Report 106 | 107 |
108 | 109 | -------------------------------------------------------------------------------- /jenkins/workshop/content/lab18.md: -------------------------------------------------------------------------------- 1 | # Add OpenSCAP DISA STIG Scan 2 | 3 | Add the configuration for the OpenSCAP Scan below to your pipeline text file. 4 | 5 |
6 | 7 |
8 | 9 | # Append to Jenkins Pipeline Configuration 10 | 11 | In Builds > Pipelines > tasks-pipeline > Actions > Edit 12 | 13 | 14 | 15 | In your pipeline, verify the following variables are there after the version and mvnCmd definitions. Please fill in the values between the quotes if not done previously. 16 | 17 | - ocuser : the openshift user given to you by your insturctor 18 | - ocpass : the openshift password given to you by your insturctor 19 | - ocp : the openshift host given to you by your instuctor 20 | 21 | ```copy 22 | def ocuser = " " 23 | def ocpass = " " 24 | def ocp = " " 25 | 26 | ``` 27 | 28 | For Example: 29 | 30 | ```copy 31 | def ocuser = "%username%" 32 | def ocpass = "openshift" 33 | def ocp = "{{< urishortfqdn "" "master" "" >}}" 34 | 35 | ``` 36 | 37 | In your pipeline, make sure you replaced the Jenkins agent 'maven' with 'jenkins-slave-image-mgmt'. 38 | 39 | ```copy 40 | pipeline { 41 | agent { 42 | label 'jenkins-slave-image-mgmt' 43 | } 44 | 45 | ``` 46 | 47 | In your pipeline, add the OpenSCAP DISA STIG Scan after the Container Vulnerability Scan Stage. 48 | 49 | ```copy 50 | stage('OSCAP DISA STIG Scan') { 51 | steps { 52 | sh "oc login -u $ocuser -p $ocpass --insecure-skip-tls-verify https://$ocp 2>&1" 53 | sh "sshpass -p $ocpass ssh -oStrictHostKeyChecking=no -t $ocuser@$ocp docker login -u $ocuser -p " + '"$(oc whoami -t)"' + " docker-registry-default.apps.$ocp" 54 | sh "sshpass -p $ocpass ssh -oStrictHostKeyChecking=no -t $ocuser@$ocp docker pull docker-registry-default.apps.$ocp/dev-$ocuser/tasks:latest" 55 | sh "sshpass -p $ocpass ssh -oStrictHostKeyChecking=no -t $ocuser@$ocp sudo oscap-docker image docker-registry-default.apps.$ocp/dev-$ocuser/tasks:latest xccdf eval --profile xccdf_org.ssgproject.content_profile_stig-rhel7-disa --report report.html /usr/share/xml/scap/ssg/content/ssg-rhel7-ds.xml" 56 | } 57 | } 58 | 59 | ``` 60 | 61 | Save your Jenkins file 62 | 63 | # Run Pipeline 64 | 65 | Go to Builds > Pipeline 66 | 67 | Click Start Pipeline for the pipeline you just created called tasks-pipeline. 68 | 69 | Your pipeline should now execute through all the stages you created. 70 | 71 | Go ahead and click View Log. This will take you to the Jenkins logs and you can follow the various stages in your pipeline. 72 | 73 | When it asks to promote to stage, go ahead and promote it. 74 | 75 |
76 | 77 |
78 | 79 | # View OpenSCAP DISA STIG Container Scan Report 80 | 81 | You can view the security controls from the OpenSCAP Scan on the jenkins pipeline log. 82 | 83 | Please ask your instructor on how you can view the full report. 84 | 85 | Your report should look similar to the following: [OpenScap DISA STIG SCAN report][1] 86 | 87 |
88 | 89 | 90 | 91 | [1]: http://info.redhatgov.io/devsecops/report.html 92 | 93 | 94 | -------------------------------------------------------------------------------- /jenkins/workshop/modules.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | modules: 3 | index: 4 | name: DevSecOps Workshop - Secure Software Factory 5 | lab01: 6 | name: Lab 01 - Welcome to OpenShift 7 | lab02: 8 | name: Lab 02 - Trusted Software Supply Chain 9 | lab03: 10 | name: Lab 03 - CI/CD Project and Pods 11 | lab04: 12 | name: Lab 04 - Jenkins and OpenShift 13 | lab05: 14 | name: Lab 05 - Creating Your Pipeline 15 | lab06: 16 | name: Lab 06 - Build App Stage 17 | lab07: 18 | name: Lab 07 - Test Stage 19 | lab08: 20 | name: Lab 08 - Static Application Security Testing 21 | lab09: 22 | name: Lab 09 - Archive App 23 | lab10: 24 | name: Lab 10 - Create Image Builder 25 | lab11: 26 | name: Lab 11 - Build Image 27 | lab12: 28 | name: Lab 12 - Create and Deploy to Dev 29 | lab13: 30 | name: Lab 13 - Promote and Deploy to Stage 31 | lab14: 32 | name: Lab 14 - Run Pipeline 33 | lab15: 34 | name: Lab 15 - Trigger the Software Supply Chain 35 | lab16: 36 | name: Lab 16 - Create Quay Account 37 | lab17: 38 | name: Lab 17 - Clair Vulnerability Scan 39 | lab18: 40 | name: Lab 18 - OpenSCAP DISA STIG Scan 41 | Fin: 42 | name: Fin 43 | -------------------------------------------------------------------------------- /jenkins/workshop/workshop.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: DevSecOps Workshop - Secure Software Factory 3 | 4 | modules: 5 | activate: 6 | - index 7 | - lab01 8 | - lab02 9 | - lab03 10 | - lab04 11 | - lab05 12 | - lab06 13 | - lab07 14 | - lab08 15 | - lab09 16 | - lab10 17 | - lab11 18 | - lab12 19 | - lab13 20 | - lab14 21 | - lab15 22 | - lab16 23 | - lab17 24 | - lab18 25 | - Fin 26 | -------------------------------------------------------------------------------- /tekton/workshop/content/Fin.md: -------------------------------------------------------------------------------- 1 | # That's it! 2 | Hopefully, you understand how to build a Secure Software Factory on OpenShift. 3 | -------------------------------------------------------------------------------- /tekton/workshop/content/images/16.3_coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/16.3_coverage.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/23.5_coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/23.5_coverage.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/archive_pipeline_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/archive_pipeline_results.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/click_workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/click_workspace.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/cluster_tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/cluster_tasks.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/cluster_tasks_openshift_client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/cluster_tasks_openshift_client.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/cmd_line_tools_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/cmd_line_tools_download.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/cmd_line_tools_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/cmd_line_tools_help.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/console_paste_yaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/console_paste_yaml.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/console_pipeline_creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/console_pipeline_creation.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/deploy_to_dev_pipeline_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/deploy_to_dev_pipeline_results.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/devconsole_topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/devconsole_topology.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/developer_console_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/developer_console_add.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/developer_console_image_from_intreg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/developer_console_image_from_intreg.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/devsecops-deployments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/devsecops-deployments.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/final_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/final_pipeline.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/full-pipeline-results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/full-pipeline-results.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_add_webhook_details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_add_webhook_details.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_openshift_tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_openshift_tasks.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_route.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_route.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_route_developer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_route_developer.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_settings_webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_settings_webhook.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/gitea_webhook_test_delivery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/gitea_webhook_test_delivery.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/golden_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/golden_images.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/grc_io_maven_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/grc_io_maven_images.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/import_yaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/import_yaml.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/maven_clustertask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/maven_clustertask.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/maven_snapshots_tasks_war.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/maven_snapshots_tasks_war.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/nexus_artifacts_tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/nexus_artifacts_tasks.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/ocp-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/ocp-login.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/ocp_cicd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/ocp_cicd.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/ocp_dashboard_persona.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/ocp_dashboard_persona.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/ocp_devsecops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/ocp_devsecops.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openscap_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openscap_report.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-archive.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-build.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-create-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-create-dev.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-imagebuilder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-imagebuilder.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-openscap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-openscap.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-promote-stage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-promote-stage.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-quay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-quay.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-sonarqube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-sonarqube.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline-unittest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline-unittest.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/openshift-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/openshift-pipeline.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_create_image_completed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_create_image_completed.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_example.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_fail.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_results_container_vuln_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_results_container_vuln_scan.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_start.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipeline_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipeline_success.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipelinerun_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipelinerun_logs.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipelinerun_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipelinerun_overview.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipelinerun_resources_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipelinerun_resources_ui.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipelinerun_results_after_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipelinerun_results_after_test.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/pipelines_integrated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/pipelines_integrated.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/push_git_fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/push_git_fix.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/quay_clair_vulns_summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/quay_clair_vulns_summary.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/quay_container_vuln_scan_queued.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/quay_container_vuln_scan_queued.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/quay_new_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/quay_new_repo.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/quay_repos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/quay_repos.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/quay_vulns_details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/quay_vulns_details.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/reload_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/reload_terminal.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/rerun_pipelinerun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/rerun_pipelinerun.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/rh_container_catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/rh_container_catalog.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/secure_software_factory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/secure_software_factory.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/security_inheritance_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/security_inheritance_model.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/simple-maven-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/simple-maven-pipeline.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/simple-pipelinerun-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/simple-pipelinerun-logs.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/sonarqube_pipelinerun_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/sonarqube_pipelinerun_results.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/sonqarqube-tasks-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/sonqarqube-tasks-dashboard.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/start-simple-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/start-simple-pipeline.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/tekton-tasks-build-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/tekton-tasks-build-config.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/tekton-tasks-image-stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/tekton-tasks-image-stream.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/tekton_tasks_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/tekton_tasks_build.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/tekton_tasks_imagestream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/tekton_tasks_imagestream.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/tekton_tasks_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/tekton_tasks_running.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/trusted_software_supply_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/trusted_software_supply_chain.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/webhook_edit_readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/webhook_edit_readme.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/webhook_pipelinerun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/webhook_pipelinerun.png -------------------------------------------------------------------------------- /tekton/workshop/content/images/webhook_stage_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RedHatGov/devsecops-workshop-dashboard/5ebafe58b44b69276cb647c0fafcd3602ff055c1/tekton/workshop/content/images/webhook_stage_pipeline.png -------------------------------------------------------------------------------- /tekton/workshop/content/index.md: -------------------------------------------------------------------------------- 1 | In this workshop, you'll be building a Secure Software Factory for a Java based website leveraging several containerized tools such as Gitea, Nexus, OpenShift Pipelines, Sonarqube, and Che hosted on the OpenShift Container Platform 2 | 3 | ## Who Should Attend 4 | - Anyone who has had OpenShift 101 5 | - Architects 6 | - Developers 7 | - Technical leads 8 | - Operations Engineers 9 | 10 | ## What you will learn 11 | - Working with OpenShift Pipelines and Tekton 12 | - Automating the development process 13 | - Trusted Software Supply Chain 14 | 15 | ## Agenda 16 | - Introductions and Agenda 17 | - Familiarization with the Environment 18 | - Setting the Context 19 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab01.md: -------------------------------------------------------------------------------- 1 | This lab provides a quick tour of the console to help you get familiar with the user interface along with some key terminology we will use in subsequent lab content. 2 | 3 | ## Key Terms 4 | 5 | We will be using the following terms throughout the workshop labs so here are some basic definitions you should be familiar with. You'll learn more terms along the way, but these are the basics to get you started. 6 | 7 | * **Container** - Your software wrapped in a complete filesystem containing everything it needs to run 8 | * **Image** - We are talking about docker images; read-only and used to create containers 9 | * **Pod** - One or more docker containers that run together 10 | * **Service** - Provides a common DNS name to access a pod (or replicated set of pods) 11 | * **Project** - A project is a group of services that are related logically 12 | * **Deployment** - an update to your application triggered by a image change or config change 13 | * **Build** - The process of turning your source code into a runnable image 14 | * **BuildConfig** - configuration data that determines how to manage your build 15 | * **Route** - a labeled and DNS mapped network path to a service from outside OpenShift 16 | * **Master** - The foreman of the OpenShift architecture; the master schedules operations, watches for problems, and orchestrates everything 17 | * **Node** - Where the compute happens; your software is run on nodes 18 | * **Pipeline** - Automates the control, building, deploying, and promoting your applications on OpenShift 19 | 20 | ## Dashboard Tour 21 | 22 | This workshop is provisioned with a special dashboard that gives you easy access to a web terminal with the `oc` command line tool pre-installed, the OpenShift web console, and Red Hat's in-browser IDE: CodeReady Workspaces. Let's get started by logging into each of these and checking the status of the platform. 23 | 24 | ### View projects with `oc` 25 | 26 | In the Terminal tab, check to see what projects you have access to: 27 | 28 | #### NOTE: Execution blocks 29 | 30 | Throughout this workshop, sometimes a code block will be present with a small play button on the right-hand side. When you see these blocks, you can either click the button to execute it in your terminal pane automatically, or copy and paste or type the command manually. It's up to you! 31 | 32 | ```execute 33 | oc get projects 34 | 35 | ``` 36 | 37 | ### Now check in the Web Console 38 | 39 | Open the Console tab in your dashboard. You may start off in the Developer view. If you change that to Administrator using the pulldown in the top left you should see your available projects. If none had existed already, you would see a button to create one. 40 | 41 | ![OCP Dashboard Personas](images/ocp_dashboard_persona.png) 42 | 43 | ### Access your personal developer workspace 44 | 45 | As part of this workshop, you'll have your own developer workspace, equipped with developer tooling and plugins, all running in a container. Open the CodeReady Workspaces tab to view the workspace we've created for you. We'll explore this in more detail later on. 46 | 47 | ### Summary 48 | 49 | You should now be ready to get hands-on with our workshop labs. 50 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab02.md: -------------------------------------------------------------------------------- 1 | The notion of Secure Software Factory is that of applying an assembly line approach to software that includes building increasing levels of assurance before marking an artifact as ready to deploy to production. 2 | 3 | In this workshop, you will use build orchestration tools such as Tekton, Kubernetes, and OpenShift to support implementing and integrating [continuous delivery (CD)][1] as the foundation of automating the various stages of the deployment lifecycle are represented – from development, multiple types of testing, user acceptance, staging, to production release. 4 | 5 | ![Secure Software Factory](images/secure_software_factory.png) 6 | 7 | For many organizations, obtaining Authority to Operate (ATO) is an arduous process requiring hundreds of pages of documentation, and can prevent organizations from adopting continuous delivery practices for fear of falling out of compliance. Each phase in our Secure Software Factory will have a policy defining the stage gate for success and will generate a documentation artifact that will later be used as part of the [ATO process][2]. 8 | 9 | Having a secure foundation for your applications is a key component to a Secure Software Factory. In the following lab exercises, your applications will inherit these security controls from the accredited OpenShift platform. 10 | 11 | The approach towards the Authorization and Accreditation (A&A) process with OpenShift follows a Landlord/Tenant model. OpenShift is a container application platform that provides a standardized operating environment and when assessing system boundaries, a delineation should be made between the OpenShift system itself, which operates as a Landlord, and the tenant application, which consumes the OpenShift service. 12 | 13 | ![Landlord/Tenant Model](images/security_inheritance_model.png) 14 | 15 | In Landlord/Tenant system security plans (SSP), many security controls are inherited from the Landlord’s SSP, but some controls remain the responsibility of the OpenShift consumers. Following this division of responsibilities illustrated in the diagram above, some controls would be considered the responsibility of the tenant, whereas a good number of controls are already taken care of by the Landlord. 16 | 17 | This is similar to how networking or underlying storage infrastructure is accredited in a virtualized environment, then inherited by virtual machines. A Secure Software Factory simply moves this delineation between Landlord and Teneant higher up the stack. 18 | 19 | [1]: https://en.wikipedia.org/wiki/Continuous_delivery 20 | [2]: https://cloud.gov/docs/compliance/ato-process/ 21 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab03.md: -------------------------------------------------------------------------------- 1 | Before moving forward, it is important to understand the difference between [Continuous Integration (CI), Continuous Delivery (CD), and Continuous Deployment][1]. 2 | 3 | Also, a part of this lab we’ll be using [OpenShift Pipelines][2] for CI/CD, which gives you control over building, deploying, and promoting your applications on OpenShift. OpenShift Pipelines is directly integrated in OpenShift and allows users to build extensible pipelines using familiar cloud native constructs (such as containers) based on the Tekton upstream project. We will dive into further details on Tekton in a follow-on lab. 4 | 5 | OK, let’s start by exploring the components of an OpenShift CI/CD Pipeline using the OpenShift Console. 6 | 7 | First, ensure that the pulldown in the very top left of the embedded OpenShift Web Console indicates "Administrator" and not "Developer", then click on the `devsecops` project from the list of projects. 8 | 9 | ![OCP Admin Project View](images/ocp_devsecops.png) 10 | 11 | You will see the project dashboard which shows the "common infrastructure" for our Secure Software delivery pipeline. If you navigate to the "Deployments" section underneath "Workloads" on the left-hand nav bar, you will see deployments for each of the following software components: 12 | 13 | - codeready - CodeReady Workspaces is a browser-based development environment based on Eclipse Che 14 | - gitea-server - Gitea is an open source git server written in Go. 15 | - nexus - Nexus is a popular artifact repository manager used for storing and retrieving binary artifacts such as jars, npms, etc. 16 | - sonarqube - SonarQube is an open source static code analysis tool 17 | - some additional supporting deployments such as databases 18 | 19 | There are some other components for our pipeline that live inside other projects, for a number of reasons, but these are some exemplar components to make up our Secure Software Factory. 20 | 21 | ![devsecops Project Deployments](images/devsecops-deployments.png) 22 | 23 | # The Flow of the Secure Software Factory 24 | 25 | You may ask, "How am I going to build a CI/CD pipeline if I don't have a tool like Jenkins that builds CI/CD pipelines?" OpenShift Pipelines is the CI/CD tool (based on the upstream Tekton project) that will execute the project. We'll be using using cloud-native container-based tooling and the power of the Kubernetes container orchestrator to do execute our steps. 26 | 27 | Below are the main steps of the "Deploy to Dev" pipeline: 28 | 29 | - Clone the git repository and make it available to the rest of the pipeline tasks 30 | - Compile and packages the code using Maven 31 | - Execute the JUnit tests that exist in the same source tree 32 | - Analyze the source code for vulnerabilities, bugs, and bad patterns using SonarQube 33 | - Package the application as a WAR file, then push the WAR artifact to the Nexus Repository manager 34 | - Create a container image based the JBoss EAP runtime image and the content of the WAR artifact, tagging it with the hash of the git revision 35 | - Deploy the newly created container image into the %username%-dev project 36 | 37 | At this point, the first part of the pipeline only deploys the application to the Dev environment so that it can be tested/verified there. The verification of the deployed application can involve many different aspects : manual verification, execution of some integration tests against the running system, etc. We have intentionally not automated any tests here to simulate a manual quality check and enable you to explore this part of the pipeline. 38 | 39 | When the verification is complete, the "Deploy to Stage" pipeline will perform the following steps: 40 | 41 | - Tag the container created in the "Dev" stage of the pipeline and make it available in the `%username%-stage` project 42 | - Clean up the artifacts from the previous version of the application 43 | - Deploy a new version of the application based on the newly tagged image into the %username%-stage project 44 | 45 | ![OpenShift as a Secure Software Factory](images/openshift-pipeline.png) 46 | 47 | [1]: https://stackoverflow.com/questions/28608015/continuous-integration-vs-continuous-delivery-vs-continuous-deployment 48 | [2]: https://docs.openshift.com/container-platform/4.4/pipelines/understanding-openshift-pipelines.html 49 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab04.md: -------------------------------------------------------------------------------- 1 | 2 | Let's take a quick look at what's already been deployed in your cluster for you. 3 | 4 | OpenShift Pipelines is supported in OpenShift using an operator. When the operator is provisioned in the cluster, the cluster navigation is updated with a navigation section on pipelines. 5 | 6 | ![Pipeline Operator](images/pipelines_integrated.png) 7 | 8 | # Review App Source Code 9 | 10 | Ensure that the `devsecops` project is selected in the "Project" drop-down and change from the "Administrator" view to the "Developer" view. These views are based on persona, and you can provide both or either to specific accounts, with varying levels of control. 11 | 12 | Identify the `gitea-server` deployment in the Topology view and click in the center of the icon. On the right-hand side pane, click the [gitea-server Route](https://gitea-server-devsecops.%cluster_subdomain%/%username%) to open it in a new tab. To log into the gitea server, click the `Sign-In` button and use `%username%` and password provided at the Dashboard login. 13 | 14 | ![Gitea Route](images/gitea_route_developer.png) 15 | 16 | Click on the `%username%/openshift-tasks` repository on the right side to see the project structure, and then choose the `dso4` branch to select the branch we're working with 17 | 18 | ![Gitea OpenShift Tasks source](images/gitea_openshift_tasks.png) 19 | 20 | # Maven Refresher 21 | 22 | Maven install will run through the [Maven lifecycle][1] and skip the tests. We will execute tests later in the pipeline. 23 | 24 | - validate - validate the project is correct and all necessary information is available 25 | - compile - compile the source code of the project 26 | - test - test the compiled source code using a suitable unit testing framework (these tests should not require the code be packaged or deployed) 27 | - package - take the compiled code and package it in its distributable format, such as a JAR. 28 | - verify - run any checks on results of integration tests to ensure quality criteria are met 29 | - install - install the package into the local repository, for use as a dependency in other projects locally 30 | - deploy - done in the build environment, copies the final package to the remote repository for sharing with other developers and projects. 31 | 32 | # Review pre-existing pipelines 33 | 34 | Go into your CI/CD project and review the pipelines that the workshop has pre-provisioned in the cluster. Observe how the pipeline visualizes the parallel execution of tasks. 35 | 36 | ![Pipelinerun Example](images/pipeline_example.png) 37 | 38 | Now, navigate to the Pipeline Runs section and observe the results of the execution of the existing pipeline. It may have failed, as these pipelines were kicked off while the cluster was building itself out. You can manually rerun here from the menu on the top right if you want to observe logs of the run. 39 | 40 | ![Pipelinerun Overview](images/pipelinerun_overview.png) 41 | 42 | If you click on any of the tasks, you will be able to see the output / logs from that task (supposing the run you are reviewing executed). 43 | 44 | ![Pipelinerun Logs](images/pipelinerun_logs.png) 45 | 46 | # Tasks and Cluster Tasks 47 | 48 | If you're interested in peeking under the covers, you can navigate to one of the existing tasks under the "Administrator" view and take a look at the yaml definition. If you look at the `steps` section of the task you will be able to see that the step in this task just starts a container based on the `gcr.io/cloud-builders/mvn:3.5.0-jdk-8` image and passes some arguments to it. 49 | 50 | ```yaml 51 | apiVersion: tekton.dev/v1beta1 52 | kind: Task 53 | metadata: 54 | name: maven-java8 55 | namespace: %username%-cicd 56 | spec: 57 | params: 58 | - default: 59 | - package 60 | description: maven goals to run 61 | name: GOALS 62 | type: array 63 | - default: configuration/cicd-settings-nexus3.xml 64 | description: location of the settings file 65 | name: settings-path 66 | type: string 67 | resources: 68 | inputs: 69 | - name: source 70 | type: git 71 | steps: 72 | - args: 73 | - $(params.GOALS) 74 | - '-s$(inputs.resources.source.path)/$(params.settings-path)' 75 | command: 76 | - /usr/bin/mvn 77 | image: 'gcr.io/cloud-builders/mvn:3.5.0-jdk-8' 78 | name: mvn-goals 79 | resources: {} 80 | workspaces: 81 | - name: maven-repo 82 | 83 | ``` 84 | 85 | If you look a bit more into this task, you will observe that the task can take some input parameters, which allows the creator of the task to create a reusable artifact. If you keep peeking, you can see that the parameters passed into the task are used in one of the steps using a special syntax, e.g. `$(params.settings-path)` to retrieve the value of the `settings-path` parameter. 86 | 87 | In order to kick-start the development of pipelines, OpenShift ships with a number of pre-built common tasks that you can use in your own pipelines 88 | 89 | ![Cluster Tasks](images/cluster_tasks.png) 90 | 91 | Below is an example of the `openshift-client` cluster task: the only thing that's different is that the `kind` is a `ClusterTask`. It still takes parameters and launches containers to do its job. 92 | 93 | ```execute 94 | oc get ClusterTask openshift-client -o yaml 95 | 96 | ``` 97 | 98 | You have the ability to take any container into a task into your pipeline, make it reusable with parameters, and plug it into your pipelines. If one of the ClusterTasks doesn't quite work the way you like, you can just copy it into a task in your own project and change it to your liking. 99 | 100 | [1]: https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html 101 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab05.md: -------------------------------------------------------------------------------- 1 | Before we dive into starting to build our pipeline, let's review some of the key concepts in Tekton 2 | 3 | # Key Concepts 4 | 5 | ## Tasks and Steps, and Task Runs 6 | 7 | Here are the definitions of the main Tekton constructs: 8 | 9 | * Step: run commands in a container with volumes, env vars, etc 10 | * Task: a list of steps that run sequentially in the same pod. 11 | * TaskRun: an invocation of a task with inputs and outputs 12 | 13 | A few things to highlight from the definitions above: 14 | 15 | * Steps are fairly low-level: they basically say "here, run this container, and then run this command in this container". 16 | * Steps in a task cannot take their own parameters beyond what's pre-defined in the Step specification. 17 | * The way you make the Task reusable is by taking in the values that the steps might need, and move them into parameters at the Task level. In order to refer to the parameters in the body of the task (e.g. in steps) use the `$(params.my-param-name)` syntax (if you wanted to use the `my-param-name`) 18 | * TaskRuns are the runtime representation of a Task - where the task and the actual parameters with which the task was called with are put together. The task runs provide the actual values / input to the tasks to execute with, e.g. parameters, resources, service accounts, workspaces 19 | * Note that because Steps in a Task execute in the same pod, they are able to share some local resources. Conversely, because different task execute in different Pods, they are unable to share local resources (e.g. such as local filesystem locations) and other Tekton constructs need to be used when Tasks need to share resources. 20 | 21 | Let's look at an example: 22 | 23 | ```yaml 24 | kind: Task 25 | metadata: 26 | name: maven 27 | spec: 28 | params: 29 | - name: goal 30 | type: string 31 | default: package 32 | steps: 33 | - name: mvn 34 | image: maven:3.6.0-jdk-8-slim 35 | command: [ mvn ] 36 | args: [ $(params.goal) ] 37 | 38 | ``` 39 | 40 | There is quite a bit more to tasks, the gory details (such as resources, workspaces, etc) are available on the [Tekton Github](https://github.com/tektoncd/pipeline/blob/master/docs/tasks.md) 41 | 42 | ## Pipelines and Pipeline Runs 43 | 44 | Let's start with some definitions: 45 | 46 | * Pipelines define the graph of task execution. They can also be customized with parameters, resources, and workspaces that need to be provided 47 | * PipelineRun-s are again the construct that provides the actual values with which the pipelines are to be executed. The pipeline run executes the pipeline to completion, and creates TaskRuns that execute the tasks in the pipelines. Because different Tasks execute in different pods, they could run on different nodes, and if they need to share resources, they need to use a construct like a `workspace` 48 | 49 | ```yaml 50 | apiVersion: tekton.dev/v1alpha1 51 | kind: Pipeline 52 | metadata: 53 | name: app-s2i-build 54 | spec: 55 | resources: 56 | - name: app-git 57 | type: git 58 | - name: app-image 59 | type: image 60 | tasks: 61 | - name: build-app 62 | taskRef: 63 | kind: Task 64 | name: s2i-eap-7 65 | params: 66 | - name: TLSVERIFY 67 | value: 'false' 68 | resources: 69 | inputs: 70 | - name: source 71 | resource: app-git 72 | outputs: 73 | - name: image 74 | resource: app-image 75 | 76 | ``` 77 | 78 | The example pipeline above only has a single task. It defines the resources that it needs (a git repo and an image to output) and passes those values to the single task named `s2i-eap-7` that it executes with the parameters that it's given. 79 | 80 | ## Pipeline Resources 81 | 82 | The Tekton developers recognized that there are some some common elements of cloud native pipelines that are somewhat like parameters, but they are a bit more complex. Pipeline resources are inputs and outputs to tasks and pipelines. In Tasks and Pipelines, PipelineResource-s are defined by name and type. The example Pipeline above requires the following to be given to it: 83 | 84 | * An `app-git` pipeline resource, which is a Git repository. The same resource is then passed on to the `s2i-eap-7` task. 85 | * An `app-image` pipeline resource, which is an image reference. That image reference is passed to the `s2i-eap-7` task, and is the destination where the created image will be pushed. 86 | 87 | The most commonly used Pipeline Resources in Tekton are Git and Image resources, but there are others : e.g. Pull Requests, Cluster Resources, etc. The gory details are at [the Pipeline Resources Docs on GitHub](https://github.com/tektoncd/pipeline/blob/master/docs/resources.md) 88 | 89 | Here's an example of a git Pipeline Resource: 90 | 91 | ```yaml 92 | apiVersion: tekton.dev/v1alpha1 93 | kind: PipelineResource 94 | metadata: 95 | name: tasks-source-code 96 | spec: 97 | params: 98 | - name: url 99 | value: >- 100 | https://gitea-server-devsecops.%cluster_subdomain%/%username%/openshift-tasks.git 101 | - name: revision 102 | value: dso4 103 | type: git 104 | 105 | ``` 106 | 107 | One final note about Pipeline Resource: you can reference the additional parameters of the Pipeline Resource in your Task or Pipeline definitions using the a similar variable substitution syntax, e.g. `$(resources.resource-name.resource-param)`. For example, if I'm using the `$(resources.source.path)` variable substitution in order to access the `path` value of the git resource named `source` 108 | 109 | ```yaml 110 | apiVersion: tekton.dev/v1alpha1 111 | kind: Task 112 | metadata: 113 | name: maven-java8 114 | spec: 115 | params: 116 | - default: 117 | - package 118 | description: maven goals to run 119 | name: GOALS 120 | type: array 121 | - default: configuration/cicd-settings-nexus3.xml 122 | description: location of the settings file 123 | name: settings-path 124 | type: string 125 | resources: 126 | inputs: 127 | - name: source 128 | type: git 129 | steps: 130 | - args: 131 | - $(params.GOALS) 132 | - '-s$(resources.source.path)/$(params.settings-path)' 133 | command: 134 | - /usr/bin/mvn 135 | image: 'gcr.io/cloud-builders/mvn:3.5.0-jdk-8' 136 | name: mvn-goals 137 | resources: {} 138 | workspaces: 139 | - name: maven-repo 140 | ``` 141 | 142 | ## Workspaces 143 | 144 | Workspaces provide a mechanism for sharing data between tasks. Remember that each Task is started in a different pod, so if two tasks need to share some resources (e.g. some storage for the Maven process to download all dependencies that can be reused later on), a workspace comes in. Workspaces are similar to Pipeline Resources in that they are defined as "parameters" to Tasks and Pipelines, and need to be provided when a TaskRun or a PipelineRun is to be created 145 | 146 | ## Others : Task Results, Triggers, Conditions 147 | 148 | There is a lot more to learn about other types of constucts in Tekton, but we will skip them for now while we start using the basic constructs that we discussed so far. 149 | 150 | # Tools 151 | 152 | As we saw so far, all parts of Tekton can be created and used through YAML. That is fantastic when we're looking to automate something, but it's a bit less than ideal for day-to-day usage. For most of our work we will be using a combination of YAML and the OpenShift console. 153 | 154 | ## Working with YAML 155 | 156 | When creating a resource with YAML, the YAML can be supplied directly in the Web Console, via the CLI, from an automation tool that knows how to work with the Kubernetes API like Ansible, or from another Kubernetes-native tool like ArgoCD. 157 | 158 | 159 | In order to create a resource in the Console UI, while you're in the project where the resource needs to be created, click the `+` button in the upper right corner, and paste the YAML for the resource. 160 | ![Console Paste YAML](images/console_paste_yaml.png) 161 | 162 | ## OpenShift Console Web UI 163 | 164 | The OpenShift Console provides support for creating Pipelines directly in the OpenShift UI. 165 | 166 | ![Web UI Console](images/console_pipeline_creation.png) 167 | 168 | If you try to start a Pipeline that requires some Pipeline Resources, the UI will prompt you to provide the necessary resources: 169 | 170 | ![Pipeline Run Resources](images/pipelinerun_resources_ui.png) 171 | 172 | While the majority of Tekton components are still defined in YAML (through the CLI, pasted into the web console, or applied through the API otherwise), this is quickly improving in OpenShift Pipelines and Tekton. 173 | 174 | ## Command line tools 175 | 176 | Finally, any self-respecting project these days has to have a set of native command line tools for simplifying the interactions. In this case, the tool is called `tkn` and is available to download from the "Command Line Tools" sub-menu of the Help/Question Mark menu in the upper right corner of the OpenShift Console. This command has been preinstalled into the "Terminal" pane of your dashboard. 177 | 178 | ![Command line tools popup](images/cmd_line_tools_help.png) 179 | 180 | ![Tkn Download](images/cmd_line_tools_download.png) 181 | 182 | Here's an example you can run showing the available pipelines in your CI/CD project: 183 | 184 | ```execute 185 | tkn pipeline ls -n %username%-cicd 186 | 187 | ``` 188 | 189 | Kicking off a PipelineRun offers prompts for providing the required Pipeline Resources, or you can supply them as parameters: 190 | 191 | ```execute 192 | pipeline_run_output=$(tkn pipeline start app-s2i-build -n %username%-cicd \ 193 | -r app-git=source -r app-image=image) 194 | echo "$pipeline_run_output" 195 | pipeline_run=$(echo "$pipeline_run_output" | awk '/^PipelineRun started:/{print $3}') 196 | 197 | ``` 198 | 199 | You can monitor the progress of those runs directly from the CLI as well: 200 | 201 | ```execute 202 | tkn pipelinerun logs $pipeline_run -f -n %username%-cicd 203 | 204 | ``` 205 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab08.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this lab, we will add the **Unit Test** stage of the DevSecOps pipeline 4 | 5 | ![Unit Test Stage](images/openshift-pipeline-unittest.png) 6 | 7 | # Add New Task to the Pipeline 8 | 9 | Since the tests in a maven project are run directly by Maven, all we need is to add a new task to our pipeline that will call the `test` goal. We can reuse our existing `simple-maven` task and pass a parameter for the `GOAL` param in the task. 10 | 11 | The only thing that is different about the `test-app` task in the pipeline is that we are using the `runAfter` attribute so that the `test-app` task runs in *after* `build-app` instead of in parallel (this will come in handy very shortly). Since we need to add an additional step to the pipeline, we're going to **patch** our `Pipeline` object. We've already wired up a command string for you so you don't have to worry about managing indentation: 12 | 13 | ```execute 14 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 15 | $TASKS 16 | - name: test-app 17 | taskRef: 18 | kind: Task 19 | name: simple-maven 20 | params: 21 | - name: GOALS 22 | value: test 23 | - name: SETTINGS_PATH 24 | value: configuration/cicd-settings-nexus3.xml 25 | - name: POM_PATH 26 | value: pom.xml 27 | resources: 28 | inputs: 29 | - name: source 30 | resource: pipeline-source 31 | workspaces: 32 | - name: maven-repo 33 | workspace: local-maven-repo 34 | runAfter: 35 | - build-app 36 | EOF 37 | )" 38 | ``` 39 | 40 | # Run the Pipeline 41 | OK - so, the pipeline is a little verbose, but beyond a few of the repeated configuration parameters (e.g. like SETTINGS_PATH, resources, etc), we're just leaning the hard work that we did in the previous lab. 42 | 43 | This time, since we're not passing any new parameters to the pipeline, we can just rerun the previous pipeline run. Click [here](%console_url%/k8s/ns/%username%-cicd/tekton.dev~v1beta1~PipelineRun) to jump to the Pipeline Runs screen, then Rerun the top entry in the list. 44 | 45 | ![Rerun Pipeline Run](images/rerun_pipelinerun.png) 46 | 47 | In the Pipeline Run details screen, we can now see the two tasks in the pipeline executing one after another. 48 | 49 | ![PipelineRun Details](images/pipelinerun_results_after_test.png) 50 | 51 | # Conclusion 52 | 53 | In this stage we just ended up reusing our work in building a reusable task and we were able to very quickly add a new Task in the pipeline. -------------------------------------------------------------------------------- /tekton/workshop/content/lab09.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this section, we will add the **Code Analysis** stage into the pipeline. 4 | 5 | ![SonarQube Stage](images/openshift-pipeline-sonarqube.png) 6 | 7 | # Static Application Security Testing 8 | 9 | We will leverage the Maven Sonar plugin to run SonarQube scanning against our source code. 10 | 11 | SonarQube is an open source static code analysis tool that we can use to automate running security scans against your source code to further improve the security of your application. Every time we run the tool, SonarQube will scan the quality and perform a threat analysis of that code. 12 | 13 | We leverage the sonarqube maven plugin and specify the maven goal `sonar:sonar` to run our project leveraging the sonarqube api. 14 | 15 | SonarQube's security rules originate from these standards: 16 | 17 | * [CWE Database][1] - Common Weakness Enumeration (CWE™) is a formal list or dictionary of common software weaknesses that can occur in software's architecture, design, code or implementation that can lead to exploitable security vulnerabilities. 18 | 19 | * [SANS Top 25][2] - The SANS Top 25 list is a collection of the 25-most dangerous errors listed in the CWE, as compiled by the SANS organization. 20 | 21 | * [OWASP Top 10][3] - The OWASP Top 10 is a list of broad categories of weaknesses, each of which can map to many individual rules. 22 | 23 | # Add Pipeline steps for Code Analysis 24 | 25 | With the information above, we can again add an extra step to the pipeline and reuse our `simple-maven` task. A few curious and powerful things to note: 26 | * Since we want the Code Analysis to run in parallel with the Unit Tests, we can ask Tekton to run this `code-analysis` task *after* the build, and that will make the `test-app` and `code-analysis` run in parallel. It's *that* easy!!! 27 | * We will use the OpenShift service name for SonarQube so that the build can access the running SonarQube instance (in the devsecops project) 28 | * We will override the `projectName` and `projectKey` so that your scan results don't conflict with those of other workshop attendees 29 | 30 | Add a new step to the pipeline using the command below: 31 | 32 | ```execute 33 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 34 | $TASKS 35 | - name: code-analysis 36 | taskRef: 37 | kind: Task 38 | name: simple-maven 39 | params: 40 | - name: GOALS 41 | value: 'verify sonar:sonar -Dsonar.projectName=%username%-openshift-tasks -Dsonar.projectKey=%username%-openshift-tasks -Dsonar.host.url=http://sonarqube.devsecops.svc.cluster.local:9000' 42 | - name: SETTINGS_PATH 43 | value: configuration/cicd-settings-nexus3.xml 44 | - name: POM_PATH 45 | value: pom.xml 46 | resources: 47 | inputs: 48 | - name: source 49 | resource: pipeline-source 50 | workspaces: 51 | - name: maven-repo 52 | workspace: local-maven-repo 53 | runAfter: 54 | - build-app 55 | EOF 56 | )" 57 | ``` 58 | # Test Your Pipeline 59 | 60 | ```execute 61 | tkn pipeline start --resource pipeline-source=tasks-source-code --workspace name=local-maven-repo,claimName=maven-repo-pvc tasks-dev-pipeline --showlog 62 | 63 | ``` 64 | 65 | ![SonarQube pipeline results](images/sonarqube_pipelinerun_results.png) 66 | 67 | # SonarQube Dashboard 68 | 69 | Once we build the full pipeline and run it, we will visit [SonarQube](https://sonarqube-devsecops.%cluster_subdomain%/dashboard?id=%username%-openshift-tasks) and view the various metrics, stats, and code coverage as seen from the screenshot below. 70 | 71 | To get the URL of the SonarQube dashboard, we can also run the command: 72 | ```execute 73 | oc get route sonarqube -n devsecops 74 | ``` 75 | 76 | ```bash 77 | NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD 78 | sonarqube sonarqube-devsecops.%cluster_subdomain% sonarqube edge/Redirect None 79 | 80 | ``` 81 | 82 | ![SonarQube dashboard](images/sonqarqube-tasks-dashboard.png) 83 | 84 | 85 | 86 | 87 | # Conclusion 88 | 89 | In this lab we continued adding steps to our pipeline by using our existing `simple-maven` task, and leaning on the capabilities of an existing product like SonarQube to extract valuable information about the quality of the code that is about to be deployed 90 | 91 | 92 | [1]: http://cwe.mitre.org/about/index.html 93 | [2]: https://www.sans.org/top25-software-errors/ 94 | [3]: https://www.owasp.org/index.php/Top_10-2017_Top_10 95 | 96 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab10.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This lab will add the **Archive** stage to the pipeline 4 | 5 | ![Archive App Stage](images/openshift-pipeline-archive.png) 6 | 7 | # Add Archive Stage 8 | 9 | Archiving the built and tested application into a trusted repository is important to making sure we are building with trusted parts. We assume this application is built properly and all the previous stages have passed. With that confidence, our built and tested application should be immutable in a trusted repository. The repository will version or audit any changes to the application, configuration, and dependencies. 10 | 11 | We leveraged the maven nexus plugin for this deployment. The `mvn deploy` step is the last step in the maven lifecycle. The built application is archived into the nexus repository. We can see it later once we run the pipeline. 12 | 13 | The `-P nexus3` option activates the nexus3 profile defined in `configuration/cicd-settings-nexus3.xml`: 14 | 15 | # Update pipeline 16 | 17 | ```execute 18 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 19 | $TASKS 20 | - name: archive 21 | taskRef: 22 | kind: Task 23 | name: simple-maven 24 | params: 25 | - name: GOALS 26 | value: 'deploy -DskipTests=true -Pnexus3' 27 | - name: SETTINGS_PATH 28 | value: configuration/cicd-settings-nexus3.xml 29 | - name: POM_PATH 30 | value: pom.xml 31 | resources: 32 | inputs: 33 | - name: source 34 | resource: pipeline-source 35 | workspaces: 36 | - name: maven-repo 37 | workspace: local-maven-repo 38 | runAfter: 39 | - test-app 40 | - code-analysis 41 | EOF 42 | )" 43 | ``` 44 | 45 | One thing to call out here is that the `runAfter` attribute of the task allows us to wait for both of the tasks to complete (and be successful), before this task can run. 46 | 47 | # Test Your Pipeline 48 | 49 | Either run the pipeline from the command line, or re-run the previous PipelineRun from the Console: 50 | ```execute 51 | tkn pipeline start --resource pipeline-source=tasks-source-code --workspace name=local-maven-repo,claimName=maven-repo-pvc tasks-dev-pipeline --showlog 52 | ``` 53 | 54 | ![Archive Pipeline Run Results](images/archive_pipeline_results.png) 55 | 56 | Now we can view the artifact we just published in this workshop's [Nexus Repository](http://nexus-devsecops.%cluster_subdomain%). 57 | 58 | Navigate to **Browse** from the left-hand navigation menu, and click into the `maven-snapshots` repository. Below is the SNAPSHOT artifacts that have been created so far: 59 | 60 | ![Nexus artifacts](images/nexus_artifacts_tasks.png) 61 | 62 | 63 | # Conclusion 64 | 65 | We have continued extending the pipeline using the `simple-maven` task, and we now have the artifact from the application build securely stored in the Nexus repository after it passes all the tests. This step in the pipeline also illustrates how to use more advanced flows where the flow of execution converges after executing more than one parallel task. 66 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab11.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this lab we will add the **Image Builder** and **Build Container Image** stages in our pipeline 4 | 5 | ![Image Builder Stage](images/openshift-pipeline-imagebuilder.png) 6 | 7 | # OpenShift, Containers, and Container Images 8 | 9 | Containers are an important foundation for applications in building a Secure Software Factory. We want a secure and blessed golden container image that our application will inherit security controls from. 10 | 11 | Containers are built using a layered approach. For example, to create a container of a Java web application, you could do so in multiple layers: the OS, the JVM, the web server, and the code itself. 12 | 13 | ![Container Golden Images](images/golden_images.png) 14 | 15 | We can incorporate CVE and vulnerability scanning against images in an automated fashion. Any image change is scanned to improve the inherited security of our application. We have partners such as Black Duck and Twistlock that do container image scanning. Also, as a result of Red Hat's acquisition of CoreOS, we now offer Quay as an enterprise-grade registry that does vulnerability scanning. 16 | 17 | We can also cryptographically sign the resulting image so we know the container is running with a verified container image. 18 | 19 | ## Start with Quality Parts 20 | 21 | Red Hat has a container registry that provides certified Red Hat and third-party container images that will be the foundation of our container images. Our registry also has a health index of the image so we know the state of the image. 22 | 23 | ![RH Container Catalog](images/rh_container_catalog.png) 24 | 25 | 26 | 27 | ## OpenShift Container Images and Tools 28 | In the last few stages, because goal could be accomplished by invoking a Maven goal, we were able to use the `simple-maven` task that we built in the earlier steps. At this point, however, we will need to work a lot more closely with OpenShift as a platform. Although there are some Maven plugins that allow Maven to interact with OpenShift, this is a place where it makes sense to use OpenShift's own capabilities through the `oc` CLI. 29 | 30 | As we discussed before, we want to have a feedback loop that is as tight as possible so that we can experiment with and learn as quickly as possible. 31 | 32 | There are a few different ways we can go about in creating a container image for the application. One way would be to build our own from scratch using a Dockerfile, e.g. 33 | * Start from a secure base image 34 | * Add the JVM and JBoss EAP runtime binaries 35 | * Add the Tasks apps binaries where the EAP runtime expects them to be 36 | * Build the container image on the local machine and push it to a container registry that is accessible to OpenShift 37 | 38 | Because this is such a common need for container applications, OpenShift provides a set of building blocks that make the process much easier. The OpenShift builds system is beyond the scope of what we can cover in a workshop, but in short here are the essentials. 39 | 40 | An OpenShift binary BuildConfig encapsulates all four steps above: 41 | * We can specify the `builder-image` that would perform the steps above- in this case, it is `jboss-eap72-openshift:1.1` which is available in OpenShift's internal registry. Similar Builder images exist for other common software components - e.g. be it a nodejs application, a plan java app (with a runnable jar), or a python app built using django 42 | * Once this binary build is created, we can stream the contents of the WAR we want to deploy into it 43 | * The BuildConfig will use the builder image to produce a new image that contains the runtime of a hardened, secured, and up-to-date image of the JBoss EAP runtime with the Tasks WAR deployed in it 44 | * The BuildConfig will push the newly created image into the internal repository which we can then use to deploy 45 | 46 | ## openshift-client ClusterTask 47 | Similarly to our experimentation stage in [Lab 06](lab06.md), we first need to find a pre-existing Task (such as a `ClusterTask`), or a container image that has the `oc` CLI. 48 | 49 | Looking at the Task Catalog, we can see that there is an existing `openshift-client` `ClusterTask` 50 | 51 | ![OpenShift Client ClusterTask](images/cluster_tasks_openshift_client.png) 52 | 53 | Let's investigate that `ClusterTask`; it might just do the job. 54 | ```execute 55 | tkn clustertask describe openshift-client 56 | ``` 57 | 58 | The details of the `ClusterTask` look something similar to the output below: 59 | 60 | ```bash 61 | Name: openshift-client 62 | 63 | 📨 Input Resources 64 | 65 | NAME TYPE 66 | ∙ source git 67 | 68 | 📡 Output Resources 69 | 70 | No output resources 71 | 72 | ⚓ Params 73 | 74 | NAME TYPE DESCRIPTION DEFAULT VALUE 75 | ∙ SCRIPT string The OpenShift CLI a... oc $@ 76 | ∙ ARGS array The OpenShift CLI a... [help] 77 | 78 | 🦶 Steps 79 | 80 | ∙ oc 81 | 82 | ``` 83 | This `ClusterTask` comes in very handy if we need to implement a stage that just needs to send a command or two to OpenShift using the `oc` CLI. Alternatively, we could use the same container image as the `ClusterTask` if we need more complicated structure or behavior for the stage. 84 | 85 | # Implement "Create Image" stage in the pipeline 86 | 87 | ## Experiment and validate 88 | Let's take a peek under the covers to see how this works: 89 | 90 | 91 | 1. Create a working directory 92 | 93 | ```execute 94 | mkdir ./oc-build 95 | ``` 96 | 2. Download the Tasks WAR file from Nexus: 97 | 98 | ```execute 99 | wget -O oc-build/jboss-tasks-rs-7.0.0-SNAPSHOT.war 'http://nexus-devsecops.%cluster_subdomain%/service/rest/v1/search/assets/download?sort=version&repository=maven-snapshots&maven.groupId=org.jboss.quickstarts.eap&maven.artifactId=jboss-tasks-rs&maven.baseVersion=7.0.0-SNAPSHOT&maven.extension=war' 100 | 101 | ``` 102 | 103 | 3. Create a new binary build in your OpenShift user's Dev project: 104 | ```execute 105 | oc new-build --name=tekton-tasks --image-stream jboss-eap72-openshift:1.1 --binary=true -n %username%-dev 106 | 107 | ``` 108 | The output of the new build looks similar to the content below: 109 | ```bash 110 | --> Found image 0ca7413 (10 months old) in image stream "openshift/jboss-eap72-openshift" under tag "1.1" for "jboss-eap72-openshift:1.1" 111 | 112 | JBoss EAP 7.2 113 | ------------- 114 | Platform for building and running JavaEE applications on JBoss EAP 7.2 115 | 116 | Tags: builder, javaee, eap, eap7 117 | 118 | * A source build using binary input will be created 119 | * The resulting image will be pushed to image stream tag "tekton-tasks:latest" 120 | * A binary build was created, use "oc start-build --from-dir" to trigger a new build 121 | 122 | --> Creating resources with label build=tekton-tasks ... 123 | imagestream.image.openshift.io "tekton-tasks" created 124 | buildconfig.build.openshift.io "tekton-tasks" created 125 | --> Success 126 | ``` 127 | 128 | 4. Start the OpenShift build and wait for it to complete 129 | 130 | ```execute 131 | oc start-build tekton-tasks --from-dir=./oc-build/ -n %username%-dev --wait=true 132 | ``` 133 | 134 | With these three steps, we can see the following in the OpenShift Console: 135 | * A new `tekton-tasks` Build Config 136 | ![Tekton Tasks Build Config](images/tekton-tasks-build-config.png) 137 | * A new `tekton-tasks-*` build run and complete successfully 138 | ![Tekton Tasks Build](images/tekton_tasks_build.png) 139 | * A new `tekton-tasks` image stream (which is an OpenShift construct similar to a container image but with a few more capabilities), together with the location in the image registry where that image can be pulled from 140 | ![Tekton Tasks Image Stream](images/tekton-tasks-image-stream.png) 141 | 142 | 143 | ## Create a Task to create the container image 144 | 145 | Now that we know the exact commands that we need in our Pipeline, let's add an extra task to make that happen. Because we want to be able to experiment with this Task until we get it right, we will put the commands in a separate Task and run it until we get it right ( and we will parameterize the task out of the box so that we can easily work with it from the pipeline). 146 | 147 | A few things to note: 148 | * The task uses the `quay.io/openshift/origin-cli:latest` container image to execute the commands. If we only had to run a command-or-two for this stage, we could have used the existing `ClusterTask`, but because we also have to do some checking and clean-up (to make the task run repeatable), we will just lean on the same container image that the `ClusterTask` uses. 149 | * The `set -e -o pipefail` makes the step fail if any of the commands fail in running (so that we don't have to check exit codes for each command). 150 | * Since we have access to the local Maven repo in the `maven-repo` workspace, we will use the artifact that the prior steps in the pipeline put there. In a production setup, this artifact would likely be retrieved from the Nexus artifact repository. 151 | * Using our own Task for this stage will also allow us to extend the task as we need to if there are future changes that are required without changing the actual pipeline 152 | 153 | ```execute 154 | oc apply -f - << EOF 155 | apiVersion: tekton.dev/v1beta1 156 | kind: Task 157 | metadata: 158 | name: create-image 159 | spec: 160 | params: 161 | - default: tasks 162 | description: The name of the app 163 | name: app_name 164 | type: string 165 | - description: The name dev project 166 | name: dev_project 167 | type: string 168 | - description: binary artifact path in the local artifact repo 169 | # something like org/jboss/quickstarts/eap/jboss-tasks-rs/7.0.0-SNAPSHOT/jboss-tasks-rs-7.0.0-SNAPSHOT.war 170 | type: string 171 | name: artifact_path 172 | resources: 173 | inputs: 174 | - name: source 175 | type: git 176 | steps: 177 | - name: create-build-config 178 | image: 'quay.io/openshift/origin-cli:latest' 179 | script: > 180 | #!/bin/sh 181 | 182 | set -e -o pipefail 183 | 184 | echo "Creating new build config" 185 | 186 | # This allows the new build to be created whether it exists or not 187 | 188 | oc new-build -o yaml --name=\$(params.app_name) --image-stream=jboss-eap72-openshift:1.1 --binary=true -n 189 | \$(params.dev_project) | oc apply -n \$(params.dev_project) -f - 190 | - name: build-app-image 191 | image: 'quay.io/openshift/origin-cli:latest' 192 | script: > 193 | #!/bin/sh 194 | 195 | set -e -o pipefail 196 | 197 | echo "Start the openshift build" 198 | 199 | 200 | rm -rf \$(inputs.resources.source.path)/oc-build && mkdir -p \$(inputs.resources.source.path)/oc-build/deployments 201 | 202 | 203 | cp \$(workspaces.maven-repo.path)/\$(params.artifact_path) \$(inputs.resources.source.path)/oc-build/deployments/ROOT.war 204 | 205 | 206 | oc start-build \$(params.app_name) --from-dir=\$(inputs.resources.source.path)/oc-build -n \$(params.dev_project) --wait=true 207 | 208 | 209 | workspaces: 210 | - name: maven-repo 211 | EOF 212 | ``` 213 | 214 | Now, let's clean up the resources that we created manually and try running the task: 215 | ```execute 216 | oc delete buildconfig tekton-tasks -n %username%-dev 217 | oc delete imagestream tekton-tasks -n %username%-dev 218 | ``` 219 | 220 | Let's start the task and see it re-create the same resources: 221 | ```execute 222 | tkn task start --inputresource source=tasks-source-code --param app_name=tekton-tasks --param dev_project=%username%-dev --param artifact_path='org/jboss/quickstarts/eap/jboss-tasks-rs/7.0.0-SNAPSHOT/jboss-tasks-rs-7.0.0-SNAPSHOT.war' --workspace name=maven-repo,claimName=maven-repo-pvc create-image --showlog 223 | ``` 224 | 225 | We should observe the same BuildConfig and ImageStream artifacts being created in the %username%-dev project as when we created them manually. 226 | 227 | ## Add the task to create container image to the pipeline 228 | 229 | With all this done, we can update the pipeline to run after the archive task 230 | ```execute 231 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 232 | $TASKS 233 | - name: create-image 234 | taskRef: 235 | kind: Task 236 | name: create-image 237 | params: 238 | - name: app_name 239 | value: tekton-tasks 240 | - name: dev_project 241 | value: %username%-dev 242 | - name: artifact_path 243 | value: 'org/jboss/quickstarts/eap/jboss-tasks-rs/7.0.0-SNAPSHOT/jboss-tasks-rs-7.0.0-SNAPSHOT.war' 244 | resources: 245 | inputs: 246 | - name: source 247 | resource: pipeline-source 248 | workspaces: 249 | - name: maven-repo 250 | workspace: local-maven-repo 251 | runAfter: 252 | - archive 253 | EOF 254 | )" 255 | ``` 256 | 257 | With that in place, restart the last Pipeline run from the [Web Console](%console_url%/k8s/ns/%username%-cicd/tekton.dev~v1beta1~PipelineRun) and observe the completion of the pipeline. Our `BuildCconfig` and `ImageStream` are again found in the [%username%-dev project](%console_url%/search/ns/%username%-dev?kind=build.openshift.io~v1~BuildConfig%2Cimage.openshift.io~v1~ImageStream). 258 | 259 | ![Create Image completed pipeline](images/pipeline_create_image_completed.png) 260 | 261 | # Conclusion 262 | 263 | In this lab we extended the pipeline by creating a container image from our Tasks application. The image we created is based on a secure base image, with a minimal set of bits of JBoss EAP included - only what's needed to run our application. 264 | 265 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab12.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this lab we will implement the **Create Dev** and **Deploy to Dev** stages 4 | 5 | ![Deploy to Dev](images/openshift-pipeline-create-dev.png) 6 | 7 | ## Deploy to Dev 8 | 9 | This is where the rubber meets the road - so far, we've done all the steps in our pipeline that build, test, analyze, archive, and create a container image for our application. If all of these stages complete, we should be ready to run this application in our Dev project. 10 | 11 | In the bigger scheme of things, so far, our application has passed the first few steps in the organization's process of validating that it is ready to be run. At this point, we feel comfortable enough in putting in a full Dev environment (outside the individual developers' worksations) where we can see it in action. Once it's deployed there, some additional tests could be run - maybe some end-to-end smoke tests to make sure that the application indeed functions as expected. 12 | 13 | ### Manual Deploy 14 | 15 | The easiest way to deploy an application is using the Developer Console in OpenShift. Now that we have the application image in the internal registry, the deployment process is a snap ! 16 | 17 | * Switch to the Developer console (from the upper-left corner navigation), double-check the project you have selected in the pulldown (it should be "%username%-dev" and not "devsecops"), and click the "+Add" button and choose the "Container Image" tile 18 | ![Developer Console Add](images/developer_console_add.png) 19 | 20 | * Choose the "Image Stream tag from internal registry" and choose the "%username%-dev" project in the Projects dropdown, then choose the `tekton-tasks` in the ImageStreams (which is pre-populated because we created that image stream in the previous stage) and the `latest` tag from the Tag dropdown. Leave the default and hit the `Create` button 21 | ![Developer Console Deploy Image](images/developer_console_image_from_intreg.png) 22 | 23 | The UI redirects to the `Topology` screen where we can see the application start very quickly. 24 | ![DevConsole Topology](images/devconsole_topology.png) 25 | 26 | If we hit the `Open URL` link (in the upper-right corner of the tekton-tasks deployment), it will show us the running app 27 | ![OpenShift Tasks Running](images/tekton_tasks_running.png) 28 | 29 | ### Automate Deployment 30 | 31 | Alright, we've confirmed that the application runs successfully when deployed from the image we created, now it's time to automate this process using our `oc` CLI. 32 | 33 | First off, we will need to do some cleanup of our manual work. Although this feels like "extra work" that we don't have to do, the reality is that we want to make our automated deployment process idempotent so that even if the application already exists, we still want to deploy the latest version. When we deployed the tekton-tasks app from the existing image, the following resources got created: 34 | 35 | * A Deployment named `tekton-tasks` and a series of child objects (e.g. Replication controller, pods, etc) 36 | * A Service named `tekton-tasks` 37 | * A Route named `tekton-tasks` 38 | 39 | In order to clean that up, we can use the command line: 40 | 41 | ```execute 42 | oc delete deployment tekton-tasks -n %username%-dev 43 | oc delete service tekton-tasks -n %username%-dev 44 | oc delete route tekton-tasks -n %username%-dev 45 | ``` 46 | 47 | Then, if we wanted to deploy a new instance of the application based on the image we wanted, we can run: 48 | 49 | ```shell 50 | oc new-app --image-stream=tekton-tasks:latest -n %username%-dev 51 | oc expose svc tekton-tasks -n %username%-dev 52 | ``` 53 | 54 | Re-running the commands above re-deploys the application and it's back to running - but we don't want that to happen right now. We want it cleaned up, so don't try rerunning that! 55 | 56 | ### Create deploy-image Task 57 | 58 | Now that we have the actions that need to occur, we can proceed to create a new task that puts it all together. Note that: 59 | 60 | * The task script does contain a few more conditions to make sure that the resources are properly cleaned up so that the task would succeed under various scenarios 61 | * The step also sets the rollout of the deployment to manual so that it doesn't automatically re-deploy when a new image is pushed. 62 | 63 | ```execute 64 | oc apply -f - << EOF 65 | apiVersion: tekton.dev/v1beta1 66 | kind: Task 67 | metadata: 68 | name: deploy-to-dev 69 | spec: 70 | params: 71 | - description: The name of the app 72 | name: app_name 73 | type: string 74 | - description: The name of the dev project 75 | name: dev_project 76 | type: string 77 | resources: 78 | inputs: 79 | - name: source 80 | type: git 81 | steps: 82 | - name: deploy-app-from-image 83 | image: 'quay.io/openshift/origin-cli:latest' 84 | script: > 85 | #!/bin/sh 86 | 87 | set -e -o pipefail 88 | 89 | echo "Create new app from image stream in \$(params.dev_project) project" 90 | 91 | oc new-app --image-stream=\$(params.app_name):latest -n 92 | \$(params.dev_project) --as-deployment-config=true -o yaml | oc apply -n \$(params.dev_project) -f - 93 | 94 | echo "Setting manual triggers on deployment \$(params.app_name)" 95 | 96 | oc set triggers dc/\$(params.app_name) --remove-all -n \$(params.dev_project) 97 | 98 | oc set triggers dc/\$(params.app_name) --manual=true -n \$(params.dev_project) 99 | 100 | if ! oc get route/\$(params.app_name) -n \$(params.dev_project) ; then 101 | 102 | oc expose svc \$(params.app_name) -n \$(params.dev_project) || echo "Failed to create route for \$(params.app_name)" 103 | 104 | fi 105 | 106 | oc rollout latest dc/\$(params.app_name) -n \$(params.dev_project) || true 107 | EOF 108 | ``` 109 | 110 | We can test the successful execution of the task from the command line: 111 | 112 | ```execute 113 | tkn task start --inputresource source=tasks-source-code --param app_name=tekton-tasks --param dev_project=%username%-dev deploy-to-dev --showlog 114 | ``` 115 | 116 | We can experiment with this Task to make sure that it succeeds under different conditions of failure. 117 | 118 | ### Add task to pipeline 119 | 120 | Now that we've seen the task succeed, we can add it to our pipeline and kick off a new pipeline run: 121 | 122 | ```execute 123 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 124 | $TASKS 125 | - name: deploy-to-dev 126 | taskRef: 127 | kind: Task 128 | name: deploy-to-dev 129 | params: 130 | - name: app_name 131 | value: tekton-tasks 132 | - name: dev_project 133 | value: %username%-dev 134 | resources: 135 | inputs: 136 | - name: source 137 | resource: pipeline-source 138 | runAfter: 139 | - create-image 140 | EOF 141 | )" 142 | ``` 143 | 144 | Execute the pipeline again: 145 | 146 | ```execute 147 | tkn pipeline start --resource pipeline-source=tasks-source-code --workspace name=local-maven-repo,claimName=maven-repo-pvc tasks-dev-pipeline --showlog 148 | ``` 149 | 150 | ![Deploy to Dev Pipeline](images/deploy_to_dev_pipeline_results.png) 151 | 152 | We can observe that the application is now running in the %username%-dev project. 153 | 154 | ## Conclusion 155 | 156 | In this step we explored how to perform a deployment from an existing image, automated the process, created a new Tekton Step to run the process, and then augmented our pipeline with the new step. 157 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab14.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this lab, we will explore approaches to triggering the Secure Software Factory with code check-ins 4 | 5 | # Tekton Triggers Introduction 6 | 7 | At first glance (if you start reading the [Tekton Triggers Documentation](https://github.com/tektoncd/triggers/tree/master/docs)) it does sounds a bit complicated as the approach is very flexible and has many options. 8 | 9 | However, if we want to create a simple webhook, at the simplest level we need the following: 10 | * Something that has a template to create the Tekton objects we want. In our case, we would want the webhook to kick off our pipelines, so we will need a template for a PipelineRun (based on our prior executions of our pipelines). In the land of Tekton, the `TriggerTemplate` provides that capability, together with some parameterization abilities 11 | * When a request comes in, we need something to extract the data from the incoming request (headers, body, etc) and map it to the parameters of our `TriggerTemplate` 12 | * Something to listen to a URL/route that is accessible to the system that will trigger the webhook. For that, we will use an `EventListener`, which combines the maps the `TriggerBinding` and `TriggerTemplate` for each event that we want to handle. Once Tekton stands up the pod and the service, we will expose the route using the `oc` CLI. 13 | 14 | # Dev Pipeline Webhook 15 | 16 | The goal of setting this up is to trigger a new pipeline run of our `tasks-dev-pipeline` pipeline every time someone commits to our Gitea repository. While this can be made quite much more customizable and extensible, we will start with the simplest thing possible. 17 | 18 | ## Configure Tekton triggers objects 19 | First, create a TriggerTemplate. If we inspect the prior runs of the `tasks-dev-pipeline`, the PipelineRuns that we created were pretty simple. They didn't use any parameters, so that makes the PipelineRun template below as simple as it can be. Switch to the `%username%-cicd` project and add the YAML below. 20 | 21 | 22 | ```execute 23 | oc apply -f - << EOF 24 | apiVersion: triggers.tekton.dev/v1alpha1 25 | kind: TriggerTemplate 26 | metadata: 27 | name: dev-tekton-tasks-trigger-template 28 | spec: 29 | resourcetemplates: 30 | - apiVersion: tekton.dev/v1beta1 31 | kind: PipelineRun 32 | metadata: 33 | generateName: dev-tekton-tasks-triggered- 34 | spec: 35 | pipelineRef: 36 | name: tasks-dev-pipeline 37 | resources: 38 | - name: pipeline-source 39 | resourceRef: 40 | name: tasks-source-code 41 | serviceAccountName: pipeline 42 | workspaces: 43 | - name: local-maven-repo 44 | persistentVolumeClaim: 45 | claimName: maven-repo-pvc 46 | EOF 47 | ``` 48 | 49 | * Then, we need a trigger binding. Again, because we're not mapping any parameters from the incoming request, this is basically an empty object. Create the YAML object below in the `%username%-cicd` project 50 | 51 | ```execute 52 | oc apply -f - << EOF 53 | apiVersion: triggers.tekton.dev/v1alpha1 54 | kind: TriggerBinding 55 | metadata: 56 | name: dev-tekton-tasks-trigger-binding 57 | spec: {} 58 | EOF 59 | ``` 60 | 61 | * We will create the `EventListener` below. As soon as this is created, Tekton creates a service named `el-` and a related pod to serve requests to this service. For the `dev-tekton-event-listener` below, the service will be named `el-dev-tekton-event-listener`. Note that we are using a trivial secret check using an interceptor to only allow incoming requests with the provided value to trigger our pipeline 62 | 63 | ```execute 64 | oc apply -f - << EOF 65 | apiVersion: triggers.tekton.dev/v1alpha1 66 | kind: EventListener 67 | metadata: 68 | name: dev-tekton-event-listener 69 | spec: 70 | serviceAccountName: pipeline 71 | triggers: 72 | - name: gitea-event 73 | bindings: 74 | - ref: dev-tekton-tasks-trigger-binding 75 | interceptors: 76 | - cel: 77 | filter: body.secret == "secret1234" 78 | template: 79 | name: dev-tekton-tasks-trigger-template 80 | EOF 81 | ``` 82 | In order to make this service available externally to the cluster, we will expose the service: 83 | 84 | ```execute 85 | oc expose svc el-dev-tekton-event-listener -n %username%-cicd 86 | ``` 87 | 88 | ## Add a Webhook definition in Gitea 89 | 90 | The last step is to configure Gitea to invoke this webhook 91 | 92 | * Navigate to the [Gitea Server](https://gitea-server-devsecops.%cluster_subdomain%) 93 | 94 | * Log in using your `%username%` username. Click on your `openshift-tasks` repository, navigate to the `Settings` page, and on that page click on the `Webhooks` tab. 95 | ![Gitea Webhook Settings](images/gitea_settings_webhook.png) 96 | 97 | * Click on the `Add Webhook` button and choose **Gitea** as the webhook type. On the resulting page, fill in the following values: 98 | * **Target UrL**: `http://el-dev-tekton-event-listener-%username%-cicd.%cluster_subdomain%` 99 | * **Secret**: `secret1234` 100 | * Everything else can stay as default. 101 | 102 | * Click the **Add Webhook** button to save. 103 | 104 | ![Gitea webhook definition](images/gitea_add_webhook_details.png) 105 | 106 | You will be redirected to the **Webhooks** screen. Click on the webhook that you just created, and scroll to the bottom. Now, when you click on the **Test Delivery** button, you will see your Pipeline triggered (note that the name matched what you specified in the `TriggerTemplate`) 107 | 108 | ![Gitea Webhook Test Delivery](images/gitea_webhook_test_delivery.png) 109 | 110 | ![Webhook Pipelinerun](images/webhook_pipelinerun.png) 111 | 112 | 113 | # Add a Webhook for the stage pipeline. 114 | 115 | The process to creating the webhook to trigger the Stage pipeline is very similar. However, we will simply use `curl` to trigger the pipeline and pass in the required parameters. Create the Tekton objects below, here are a few notable items: 116 | * The `TriggerTemplate` actually takes a parameter and uses the value of the parameter (using the `$(params.app_ver)` parameter substitution) to pass that value to the PipelineRun template. Remember - our Stage pipeline requires the user to provide the `app_version` parameter. 117 | * The `TriggerBinding` extracts the `app_ver` parameter from the body of the incoming request using the `$(body.app_ver)` syntax to extract a value from a JSON body. 118 | 119 | ```execute 120 | oc apply -f - << EOF 121 | apiVersion: triggers.tekton.dev/v1alpha1 122 | kind: TriggerTemplate 123 | metadata: 124 | name: tasks-stage-pipeline-trigger-template 125 | spec: 126 | params: 127 | - name: app_ver 128 | description: App version / gitsha to deploy 129 | resourcetemplates: 130 | - apiVersion: tekton.dev/v1beta1 131 | kind: PipelineRun 132 | metadata: 133 | generateName: tasks-stage-pipeline-triggered- 134 | spec: 135 | pipelineRef: 136 | name: tasks-stage-pipeline 137 | serviceAccountName: pipeline 138 | params: 139 | - name: app_version 140 | value: \$(params.app_ver) 141 | --- 142 | apiVersion: triggers.tekton.dev/v1alpha1 143 | kind: TriggerBinding 144 | metadata: 145 | name: tasks-stage-pipeline-trigger-binding 146 | spec: 147 | params: 148 | - name: app_ver 149 | value: \$(body.app_ver) 150 | --- 151 | apiVersion: triggers.tekton.dev/v1alpha1 152 | kind: EventListener 153 | metadata: 154 | name: stage-tekton-event-listener 155 | spec: 156 | serviceAccountName: pipeline 157 | triggers: 158 | - name: curl-event 159 | bindings: 160 | - ref: tasks-stage-pipeline-trigger-binding 161 | interceptors: 162 | - cel: 163 | filter: body.secret == "secret1234" 164 | template: 165 | name: tasks-stage-pipeline-trigger-template 166 | EOF 167 | ``` 168 | 169 | * Test the newly created Webhook 170 | 171 | After creating these objects, create the `Route` for the `el-stage-tekton-event-listener` service. 172 | 173 | ```execute 174 | oc expose service el-stage-tekton-event-listener 175 | ``` 176 | 177 | Get the URL for the newly exposed `Route` 178 | 179 | ```execute 180 | oc get route el-stage-tekton-event-listener 181 | ``` 182 | 183 | In order to simulate that a new app version was created, we will simply tag the `tekton-tasks` image stream with a new value that we will then use as our `app_ver` parameter, as the Dev pipeline would do exactly the same using the gitsha of the latest commit: 184 | 185 | ```execute 186 | oc tag tekton-tasks:latest tekton-tasks:foobar1 -n %username%-dev 187 | ``` 188 | 189 | Now, trigger the webhook passing `foobar1` as the `app_ver` parameter and observe that the `tasks-stage-pipeline` pipeline is running. Note that if we don't include the `secret` value in the body or include a different value, the webhook will not trigger the pipeline. 190 | 191 | ```execute 192 | curl -X POST -d '{"app_ver":"foobar1", "secret":"secret1234"}' http://el-stage-tekton-event-listener-%username%-cicd.%cluster_subdomain%/ 193 | ``` 194 | 195 | ![Stage pipeline webhook](images/webhook_stage_pipeline.png) 196 | 197 | # Conclusion 198 | 199 | In this lab we went over the simplest possible setup to allow the triggering and integration of our pipelines with external tools using Webhooks. For the Dev pipeline, it will be triggered on each commit in our Gitea repository. For the Stage pipeline, we expose a webhook that can be invoked with a parameter - possibly from a custom tool that processes the approval of promotions between stages. 200 | 201 | Note that the examples above are probably the simplest one possible, and uses a trivial security mechanism to validate the incoming requests that trigger the pipelines. 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab15.md: -------------------------------------------------------------------------------- 1 | # Triggering the Secure Software Factory 2 | 3 | Now that our triggers are in place, let's test out the software factory by performing a little application development. 4 | 5 | If you had a chance to check [SonarQube](https://sonarqube-devsecops.%cluster_subdomain%/dashboard?id=%username%-openshift-tasks) for the results of the static code analysis scan, you may have noticed that our **code coverage**, which is to say: *the percentage of code which is executed during unit testing*, comes in at a not-so-hot **16.3%**. 6 | 7 | ![16.3% Coverage](images/16.3_coverage.png) 8 | 9 | Normally, such low coverage should break the build and stop the pipeline, but fortunately for us, Sonarqube is configured with a very permissive Quality Gate. It doesn't enforce any constraints *at all*, as a matter of fact. Nevertheless, let's address this by writing another unit test to expand our code coverage a bit. To do this, we're going to use **CodeReady Workspaces**, Red Hat's in-browser IDE. 10 | 11 | ## CodeReady Workspaces to the Rescue 12 | 13 | Navigate to the **CodeReady Workspaces** tab on your dashboard, and click on **Stacks** in the left-hand pane to explore the development stacks that come with CodeReady Workspaces out of the box. These are curated to offer readily available development environments for a variety of languages and frameworks. If you select one of them, you'll see that they're backed by a yaml **Devfile** that allows you to preload things like *plugins*, *git repositories*, or *command shortcuts* into the workspace so that onboarding new developers is faster than ever. 14 | 15 | Indeed, we've used just such a Devfile to create a workspace for *you*, our newest developer! Click on **java-eap-maven-%username%** under *RECENT WORKSPACES* in the left-hand pane to open it. 16 | ![Click Workspace](images/click_workspace.png) 17 | 18 | ## Editing code in your workspace 19 | 20 | If you have experience with Visual Studio Code, the look and feel of your workspace should be familiar. Click the **Explorer** Icon in the left-hand pane (two sheets of paper with the corner folded over). You'll notice the `openshift-tasks` project has been imported for you. *Now, what was our task again?* Ah yes, increasing code coverage. Happily, we already have the code for an additional unit test handy, but it's currently disabled. Hit **Ctrl+P** (or **Cmd+P** on a Mac) and enter `UserResourceTest.java`. 21 | 22 | *If you're having trouble with the shortcut, you can expand the file explorer to* `openshift-tasks/src/test/java/org/jboss/as/quickstarts/tasksrs/service/UserResourceTest.java`. 23 | 24 | Look for the test called `getUsersSortedByTask()`; it should look like this: 25 | 26 | ```java 27 | @Test 28 | // TODO: comment out to make the test run 29 | @Ignore 30 | public void getUsersSortedByTask() { 31 | List users = userResource.getUsers(); 32 | 33 | verify(userDao).getAll(); 34 | 35 | assertEquals("user2", users.get(0).getUsername()); 36 | assertEquals("user3", users.get(1).getUsername()); 37 | assertEquals("user1", users.get(2).getUsername()); 38 | 39 | } 40 | ``` 41 | 42 | Notice the `@Ignore` annotation on line 47; that signals to our pipeline that this test should be skipped. Let's *unskip* it by commenting out the annotation using two forward slashes, like this: 43 | 44 | ```java 45 | @Test 46 | // TODO: comment out to make the test run 47 | // @Ignore 48 | public void getUsersSortedByTask() { 49 | List users = userResource.getUsers(); 50 | ... 51 | ``` 52 | 53 | > **Note:** If you've done this correctly, the syntax highlighting in your IDE should turn the line green. Alternatively, you can simply *delete* the `@Ignore` annotation. 54 | 55 | Next, use they keyboard combination **Ctrl+Shift+P** to open the CodeReady Workspaces function search box, and enter `Git: Commit` to bring up the commit interface. The editor might present a dialogue box offering to Stage them first; click Always for this exercise, but in real life pick whatever matches your workflow. When prompted for a commit message, enter something descriptive like `Unignored unit test for sorted users` and press enter. 56 | 57 | Next, we need to push the commit from your workspace back up to the git repository. Use **Ctrl+Shift+P** to open the function search box again, and enter `Git: Push`. 58 | 59 | Git will ask for your credentials, so enter `%username%` and your OpenShift password (e.g. `openshift`) when prompted. 60 | 61 | With our webhook in place, the git commit should trigger a new pipeline run. Now **this** is DevSecOps! Let's sit back and watch the logs as the pipeline does all the hard work. 62 | 63 | ```execute 64 | tkn pr logs --last -f 65 | ``` 66 | 67 | ## Onward 68 | 69 | As this pipeline run proceeds, take moment to bask in the success of what we've accomplished. With just a git commit, we've set the secure software factory in motion. Our pipeline will execute stringent tests against our code so that we can deploy with full confidence... *Wait a minute!* 70 | 71 | ![Pipeline Fail](images/pipeline_fail.png) 72 | 73 | Our new unit test failed! That means we've discovered a **bug**. The pipeline is paying off already. Who *knows* what bad things could happen if `Users` aren't properly sorted! Anyway, let's go back to **CodeReady Workspaces** and fix it. 74 | 75 | Happily, the fix has already been written; it's just been commented out. In your workspace, hit **Ctrl+P** (or **Cmd+P** on a Mac) and enter `UserResource.java`. 76 | 77 | *If you're having trouble with the shortcut, you can expand the file explorer to* `openshift-tasks/src/main/java/org/jboss/as/quickstarts/tasksrs/service/UserResource.java`. 78 | 79 | We need to uncomment lines 32-38, which you can do by manually deleting the two forward slashes at the beginning of each line, *or* by highlighting the relevant lines and pressing **Ctrl+/** - that's a forward slash - (or **Cmd+/** on a Mac). Then we need to commit our changes once more, using a message like `Uncomment user sort`. Once committed, we need to Push again, entering our username and password when prompted. 80 | 81 | ![Push Git Fix](images/push_git_fix.png) 82 | 83 | The git commit should trigger a fresh pipeline run. This time, we'll watch from the [Web Console](%console_url%/k8s/ns/%username%-cicd/tekton.dev~v1beta1~PipelineRun). Select the first Pipeline Run in the list, and we'll cross our fingers while we await our fate. 84 | 85 | ![Pipeline Start](images/pipeline_start.png) 86 | 87 | *** 88 | 89 | **Success!** 90 | 91 | ![Pipeline Success](images/pipeline_success.png) 92 | 93 | Now let's refresh the Sonarqube Report. Here's the [link](https://sonarqube-devsecops.%cluster_subdomain%/dashboard?id=%username%-openshift-tasks) in case you closed it. 94 | 95 | ![23.5% Coverage](images/23.5_coverage.png) 96 | 97 | *Ayyy*, **23.5%**. Not too shabby. We're well on our way! Now that we've seen the ability of a pipeline to quickly reveal defects *and* deliver corresponding fixes, let's explore how we can build on the pipeline even more. 98 | -------------------------------------------------------------------------------- /tekton/workshop/content/lab16.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this lab we will add Container Vulnerability Scanning through Clair, a utility that ships out of the box with **Red Hat Quay**. 4 | 5 | ![Clair Vulnerability Scanning](images/openshift-pipeline-quay.png) 6 | 7 | Incorporating image scans into our pipeline will help to ensure we can *trust* our deployment artifacts as they move from one environment to the next. For our pipeline, container images are allowable in the Development environment without restrictions, but a deployment won't be *promoted* to the Staging environment until the image scan passes our organization's acceptance criteria. 8 | 9 | Go ahead and login to this workshop's [Quay Instance](https://quay.%cluster_subdomain%) with your workshop credentials, and let's get setup for image scans. 10 | ![Quay Repositories](images/quay_repos.png) 11 | 12 | Click on the **Create New Repository** button, name it `tekton-tasks` and choose it to be a **Private** repository. 13 | ![New Repo](images/quay_new_repo.png) 14 | 15 | 16 | # Local Development - Explore Quay 17 | 18 | Now that we have a new repository, we can push and pull images from this repository. 19 | 20 | Before we jump into creating a `Task`, let's take a moment to plan how we will go about publishing our image into Quay. As it happens, this scenario is a very good fit for **Skopeo**: a rootless, daemonless utility for performing image and registry operations. The function we need here is that of *copying* an image from the OpenShift Internal Container Registry into Quay. 21 | 22 | Let's start by creating a dedicated tag for testing purposes: 23 | 24 | ```execute 25 | oc tag tekton-tasks:latest tekton-tasks:quay1 -n %username%-dev 26 | ``` 27 | 28 | Then, just as we did in [Lab 6](lab06.md), let's fire up a Skopeo pod so we can experiment a bit. 29 | 30 | ```execute 31 | oc run skopeo --serviceaccount=pipeline --image=quay.io/skopeo/stable --rm -it --command -- /bin/bash 32 | ``` 33 | 34 | We'll make use of the `pipeline` `ServiceAccount` in the `%username%-cicd` project to authenticate to the internal registry. 35 | 36 | Now your upper **Terminal** window is in a shell within the skopeo `Pod`'s container. First, we'll login to Quay. Enter your workshop password when prompted: 37 | 38 | ```execute 39 | skopeo login quayecosystem-quay.devsecops.svc.cluster.local:80 --username=%username% --tls-verify=false --authfile /tmp/auth.json 40 | ``` 41 | 42 | Next, let's login to OpenShift's internal registry. Here, we use the `pipeline` `ServiceAccount`'s token to authenticate: 43 | 44 | ```execute 45 | skopeo login image-registry.openshift-image-registry.svc.cluster.local:5000 --authfile /tmp/auth.json --tls-verify=false --username=%username% --password=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) 46 | ``` 47 | 48 | Finally, let's run a `skopeo copy` to push our `tekton-tasks` image into Quay. 49 | 50 | ```execute 51 | skopeo copy docker://image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-dev/tekton-tasks:latest docker://quayecosystem-quay.devsecops.svc.cluster.local:80/%username%/tekton-tasks:quay1 --src-tls-verify=false --dest-tls-verify=false --authfile /tmp/auth.json 52 | 53 | ``` 54 | 55 | Now, if we navigate to the Quay repository for `tekton-tasks` [here](https://quay.%cluster_subdomain%/repository/%username%/tekton-tasks?tab=tags) and click on the **Security Scan** for the **quay1** tag, we can see the vulnerabilities that have been found in the image. 56 | 57 | If you haven't already, go ahead and exit your `skopeo` container, and we'll move on to creating a Tekton task: 58 | 59 | ```execute 60 | exit 61 | ``` 62 | 63 | # Create Push-to-Quay task 64 | 65 | Now that we are fairly confident in working with Tekton Tasks, let's use some of the niceties that we can lean on based on our experience so far. As before, the easiest path forward is to create a standalone TaskRun with the TaskSpec bundled in it in order to work out the details of the task. 66 | 67 | A few notable details below: 68 | * We'll again leverage `quay.io/skopeo/stable` for our container image 69 | * We will use the `pipeline` `ServiceAccount` to authenticate to *both* registries here because Tekton does a better job of utilizing attached `Secrets` than we can easily achieve with `oc run` 70 | * We include the `--debug` flag to show additional details in case the operation is failing 71 | 72 | 73 | ```execute 74 | oc create -f - << EOF 75 | apiVersion: tekton.dev/v1beta1 76 | kind: TaskRun 77 | metadata: 78 | generateName: skopeo-quay-copy- 79 | spec: 80 | serviceAccountName: pipeline 81 | taskSpec: 82 | steps: 83 | - name: skopeo-copy 84 | args: 85 | - copy 86 | - --debug 87 | - docker://image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-dev/tekton-tasks:latest 88 | - docker://quay.%cluster_subdomain%/%username%/tekton-tasks:quay 89 | - --src-tls-verify=false 90 | - --dest-tls-verify=false 91 | command: 92 | - /usr/bin/skopeo 93 | image: quay.io/skopeo/stable 94 | EOF 95 | ``` 96 | Now, if we navigate to the [Quay Repository](https://quay.%cluster_subdomain%/repository/%username%/tekton-tasks) we can see the results of our new container image being stored and scanned. 97 | 98 | ![Clair Vulnerabilities Summary](images/quay_clair_vulns_summary.png) 99 | 100 | ![Clair Vulns Details](images/quay_vulns_details.png) 101 | 102 | Once we see this TaskRun completing successfully, we can migrate the Task spec to a standalone task and parameterize it as needed. Below are the resources at hand. A few notable items: 103 | * We could create explicit PipelineResources for the source and target images (in quay and the internal registry); however, we would need to create a new one for each Revision, which doesn't make a lot of sense. 104 | 105 | ```execute 106 | oc apply -f - << EOF 107 | apiVersion: tekton.dev/v1beta1 108 | kind: Task 109 | metadata: 110 | name: send-to-quay 111 | spec: 112 | params: 113 | - description: >- 114 | Source (project/image:tagName) and image:rev to push, e.g. 115 | %username%-dev/tekton-tasks:latest 116 | name: source_image 117 | type: string 118 | - description: >- 119 | The target (user/repo:tagName) where to push in quay, e.g. 120 | %username%/tekton-tasks:quay1 121 | name: target_image 122 | type: string 123 | steps: 124 | - name: skopeo-copy 125 | args: 126 | - copy 127 | - docker://image-registry.openshift-image-registry.svc.cluster.local:5000/\$(params.source_image) 128 | - docker://quay.%cluster_subdomain%/\$(params.target_image) 129 | - --src-tls-verify=false 130 | - --dest-tls-verify=false 131 | command: 132 | - /usr/bin/skopeo 133 | image: quay.io/skopeo/stable 134 | EOF 135 | ``` 136 | 137 | With this Task, we can now test the task run: 138 | ```execute 139 | tkn task start --param source_image=%username%-dev/tekton-tasks:latest --param target_image=%username%/tekton-tasks:quay2 send-to-quay --showlog 140 | ``` 141 | 142 | We can see the `TaskRun` succeed - we're in business! 143 | 144 | 145 | # Add Clair Container Scan to Pipeline 146 | 147 | We can now update our Pipeline to include the `Clair Container Vulnerability Scan` step, right after the `create-image` stage. We'll run this in parallel with the `deploy-to-dev` task since this stage doesn't depend on the results of the scan. 148 | 149 | ```execute 150 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 151 | $TASKS 152 | - name: container-vulnerability-scan 153 | taskRef: 154 | kind: Task 155 | name: send-to-quay 156 | params: 157 | - name: source_image 158 | value: %username%-dev/tekton-tasks:\$(tasks.git-rev.results.gitsha) 159 | - name: target_image 160 | value: %username%/tekton-tasks:\$(tasks.git-rev.results.gitsha) 161 | runAfter: 162 | - create-image 163 | EOF 164 | )" 165 | ``` 166 | 167 | We can re-start the `tasks-dev-pipeline` pipeline and see it go through completion: 168 | ```execute 169 | tkn pipeline start --resource pipeline-source=tasks-source-code --workspace name=local-maven-repo,claimName=maven-repo-pvc tasks-dev-pipeline --showlog 170 | ``` 171 | 172 | ![Container Vuln Scan Pipeline](images/pipeline_results_container_vuln_scan.png) 173 | 174 | If we navigate to Quay, we can also see the newly added tag (based on the gitrev) created in Quay 175 | ![Container Vuln Quay](images/quay_container_vuln_scan_queued.png) 176 | 177 | # Conclusion 178 | 179 | In this lab we explored the features of Quay and its ability to run Container Vulnerability scans on images pushed into Quay. Then, we enhanced our pipeline to include a step to push our created image into Quay so that we can inspect the vulnerabilities in it, before a decision is made whether to send the application to the Stage environment -------------------------------------------------------------------------------- /tekton/workshop/content/lab17.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In this Lab, we will add an OpenSCAP Scan to your pipeline. 4 | 5 | ![OpenSCAP Scanning](images/openshift-pipeline-openscap.png) 6 | 7 | So far, we've taken pause to consider the *stuff* that resides in our application image, but we haven't paid much attention to *what we're doing* with it. While Clair scans offer valuable information on image vulnerabilities, organizational constraints usually require application components to be configured to certain security standards in order to achieve **Authority to Operate (ATO)**. The **National Institute of Standards and Technology (NIST)** maintains one such standard, the **Security Content Automation Protocol (SCAP)**, which is widely recognized across government and industry as a specification that addresses most organizational concerns. 8 | 9 | In our pipeline, we'll be using [OpenSCAP](https://www.open-scap.org/), a project that provides tools for implementing and enforcing the SCAP standard. Useful for our case will be the [SCAP Security Guide](https://www.open-scap.org/security-policies/scap-security-guide/), a tool which transforms SCAP security guidelines into machine-readable format, which OpenSCAP then compares against our application's container image. This process is effective for applying known security baselines such as DISA STIGs, the required settings for Department of Defense Systems. 10 | 11 | # Create an OpenSCAP Task 12 | 13 | Similar to other quality gates in our pipeline, this step will provide informational messages about violations in policy configurations, allowing organization administrators to assess whether an application image should be promoted to the Staging environment. Building a container *in* an OpenShift container requires a privileged context, which is difficult achieve in a workshop setting. In lieu of performing local development, let's consider what an OpenSCAP task might look like and walk through the steps we've taken: 14 | 15 | ```bash 16 | apiVersion: tekton.dev/v1beta1 17 | kind: Task 18 | metadata: 19 | name: oscap-image-scan 20 | namespace: %username%-cicd 21 | spec: 22 | steps: 23 | - name: scan-image 24 | securityContext: 25 | privileged: true 26 | image: quay.io/redhatgov/image-scanner:latest 27 | script: > 28 | #!/bin/sh 29 | 30 | buildah from --tls-verify=false --storage-driver vfs "docker://image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-cicd/tasks:latest:latest" 31 | 32 | CONTAINER_ID=$(buildah --storage-driver vfs containers -q) 33 | 34 | MOUNT_POINT=$(buildah mount --storage-driver vfs $CONTAINER_ID | cut -d' ' -f2) 35 | 36 | oscap-chroot "$MOUNT_POINT" xccdf eval --profile xccdf_org.ssgproject.content_profile_standard --report /tmp/report.html /usr/share/xml/scap/ssg/content/ssg-centos7-ds-1.2.xml 37 | 38 | curl -k --user 'deployment:deployment123' --upload-file /tmp/report.html https://nexus-devsecops.%cluster_subdomain%/repository/oscap-reports/%username%/report.html 39 | 40 | ``` 41 | 42 | The first thing to note is that we're leveraging `quay.io/redhatgov/image-scanner`, a container that has been pre-built with an installation `oscap-chroot`, a CLI for executing OpenSCAP scans against local filesystems. 43 | 44 | Now, the filesystem we're interested in scanning is, of course, that of our application container. In order to mount that filesystem in our Tekton `Pod`, we're going to use [Buildah](https://buildah.io/), a tool used for building and manipulating container images. The cool thing about using **Buildah** for this purpose is that while building a `Dockerfile` is supported, it doesn't *require* one, nor does it require a **daemon** or **root privileges** on a host. 45 | 46 | We use `buildah from` to create a **working container** from our application image, storing this container's ID in the `CONTAINER_ID` environment variable with `buildah containers`. 47 | 48 | ```bash 49 | buildah from --authfile=/tmp/auth.json --tls-verify=false --storage-driver vfs "docker://image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-cicd/tasks:latest" 50 | 51 | CONTAINER_ID=$(buildah --storage-driver vfs containers -q) 52 | ``` 53 | 54 | Then we use `buildah mount` to mount the working container's filesystem into our task pod's filesystem. Here, we store the mount location to the `MOUNT_POINT` environment variable. 55 | 56 | ```bash 57 | MOUNT_POINT=$(buildah --storage-driver vfs mount $CONTAINER_ID | cut -d' ' -f2) 58 | ``` 59 | 60 | And just like that, we're ready to run a scan with `oscap-chroot`. As you might imagine, there are a wide array of **standards** and **profiles** against which to evaluate. For the purpose of this workshop, we've selected an example specification for you. You can learn more about available baselines [here](https://csrc.nist.gov/Projects/Security-Content-Automation-Protocol/Specifications). 61 | 62 | ```bash 63 | oscap-chroot "$MOUNT_POINT" xccdf eval --profile xccdf_org.ssgproject.content_profile_standard --report /tmp/report.html /usr/share/xml/scap/ssg/content/ssg-centos7-ds-1.2.xml 64 | ``` 65 | 66 | All that's left to do is present the scan result in a consumable format so that it can thoroughly evaluated by our system administrator. In addition to a summary streamed to `STDOUT`, `oscap-chroot` will populate a scan report for us in the `/tmp` directory thanks to the `--report "/tmp/report.html"` argument we pass to it. We'll publish this file to a [Raw Nexus Repository](https://help.sonatype.com/repomanager3/formats/raw-repositories) so that it can be viewed in a browser: 67 | 68 | ```bash 69 | curl -k --user 'deployment:deployment123' --upload-file /tmp/report.html https://nexus-devsecops.%cluster_subdomain%/repository/oscap-reports/%username%/report.html 70 | ``` 71 | 72 | Now let's actually create this `Task`. We'll use some of the techniques we've learned throughout this workshop to make it reusable in case we need to change the parameters we provide to `oscap-chroot` at some point: 73 | 74 | ```execute 75 | oc apply -n %username%-cicd -f - << EOF 76 | apiVersion: tekton.dev/v1beta1 77 | kind: Task 78 | metadata: 79 | name: oscap-image-scan 80 | spec: 81 | params: 82 | - name: xccdfProfile 83 | description: The oscap xccdf profile to use when calling the oscap-chroot command 84 | default: xccdf_org.ssgproject.content_profile_standard 85 | - name: oscapProfilePath 86 | description: The full path to the oscap content file 87 | default: /usr/share/xml/scap/ssg/content/ssg-centos7-ds-1.2.xml 88 | - name: container-imagetag 89 | type: string 90 | default: latest 91 | - name: container-image-url 92 | type: string 93 | default: >- 94 | image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-cicd/tasks 95 | steps: 96 | - name: scan-image 97 | securityContext: 98 | privileged: true 99 | image: quay.io/redhatgov/image-scanner:latest 100 | script: > 101 | #!/bin/sh 102 | 103 | echo "Pulling image \$(params.container-image-url)" 104 | 105 | buildah from --tls-verify=false --storage-driver vfs "docker://\$(params.container-image-url):\$(params.container-imagetag)" 106 | 107 | container_id=\$(buildah --storage-driver vfs containers -q) 108 | 109 | echo "Container ID: \$container_id" 110 | 111 | echo "Mounting the container..." 112 | 113 | mount_point=\$(buildah mount --storage-driver vfs \$container_id | cut -d' ' -f2) 114 | 115 | echo "Running oscap-chroot scan" 116 | 117 | oscap-chroot "\$mount_point" xccdf eval --profile "\$(params.xccdfProfile)" --report /tmp/report.html "\$(params.oscapProfilePath)" 118 | 119 | echo "Displaying contents of /tmp/report.html" 120 | 121 | echo "********** START OF report.html **********" 122 | 123 | cat /tmp/report.html 124 | 125 | echo "********** END OF report.html ************" 126 | 127 | echo "Uploading report.html to https://nexus-devsecops.%cluster_subdomain%/repository/oscap-reports/%username%/report.html" 128 | 129 | curl -k --user 'deployment:deployment123' --upload-file /tmp/report.html https://nexus-devsecops.%cluster_subdomain%/repository/oscap-reports/%username%/report.html 130 | EOF 131 | ``` 132 | 133 | Then let's execute this task and watch the output: 134 | 135 | ```execute 136 | tkn task start --showlog \ 137 | --param xccdfProfile=xccdf_org.ssgproject.content_profile_standard \ 138 | --param oscapProfilePath=/usr/share/xml/scap/ssg/content/ssg-centos7-ds-1.2.xml \ 139 | --param container-imagetag=latest \ 140 | --param container-image-url=image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-cicd/tasks \ 141 | oscap-image-scan 142 | ``` 143 | 144 | Observe the scan results as different criteria in the specification are evaluated: 145 | 146 | ```bash 147 | ... 148 | Title Ensure /var/log Located On Separate Partition 149 | Rule xccdf_org.ssgproject.content_rule_partition_for_var_log 150 | Result notapplicable 151 | 152 | Title Ensure Software Patches Installed 153 | Rule xccdf_org.ssgproject.content_rule_security_patches_up_to_date 154 | Result notchecked 155 | 156 | Title Ensure gpgcheck Enabled In Main yum Configuration 157 | Rule xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated 158 | Result pass 159 | 160 | Title Ensure Red Hat GPG Key Installed 161 | Rule xccdf_org.ssgproject.content_rule_ensure_redhat_gpgkey_installed 162 | Result fail 163 | ... 164 | ``` 165 | 166 | When the task finishes, double check to make we've done this correctly by visiting the report's home in [Nexus](https://nexus-devsecops.%cluster_subdomain%/repository/oscap-reports/%username%/report.html). 167 | 168 | ![OpenSCAP Report](images/openscap_report.png) 169 | *Success!* Feel free to poke around here to get a sense for the types of findings OpenSCAP reports on. 170 | 171 | # Add the OpenSCAP Task to the Pipeline 172 | Now we're ready to incorporate our final task into the pipeline. We'll run this in parallel with our vulnerability scan. 173 | 174 | ```execute 175 | TASKS="$(oc get pipelines tasks-dev-pipeline -o yaml | yq r - 'spec.tasks' | yq p - 'spec.tasks')" && oc patch pipelines tasks-dev-pipeline --type=merge -p "$(cat << EOF 176 | $TASKS 177 | - name: oscap-image-scan 178 | taskRef: 179 | kind: Task 180 | name: oscap-image-scan 181 | params: 182 | - name: xccdfProfile 183 | value: xccdf_org.ssgproject.content_profile_standard 184 | - name: oscapProfilePath 185 | value: /usr/share/xml/scap/ssg/content/ssg-centos7-ds-1.2.xml 186 | - name: container-imagetag 187 | value: latest 188 | - name: container-image-url 189 | value: image-registry.openshift-image-registry.svc.cluster.local:5000/%username%-cicd/tasks 190 | runAfter: 191 | - create-image 192 | EOF 193 | )" 194 | ``` 195 | 196 | Our pipeline is now complete! Let's kick it off one last time: 197 | ```execute 198 | tkn pipeline start --resource pipeline-source=tasks-source-code --workspace name=local-maven-repo,claimName=maven-repo-pvc tasks-dev-pipeline --showlog 199 | ``` 200 | 201 | ![Final Pipeline](images/final_pipeline.png) 202 | 203 | # Conclusion 204 | 205 | In this lab, we explored the capabilities of OpenSCAP to help implement and enforce security configuration standards. Incorporating this step into our pipeline ensures that we're in a better position to gain ATO for our application. -------------------------------------------------------------------------------- /tekton/workshop/modules.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | modules: 3 | index: 4 | name: DevSecOps Workshop - Secure Software Factory 5 | lab01: 6 | name: Lab 01 - Welcome to OpenShift 7 | lab02: 8 | name: Lab 02 - Secure Software Factory 9 | lab03: 10 | name: Lab 03 - DevSecOps Project overview 11 | lab04: 12 | name: Lab 04 - Pipelines Walkthrough 13 | lab05: 14 | name: Lab 05 - Tekton Overview 15 | lab06: 16 | name: Lab 06 - Tekton Exploration 17 | lab07: 18 | name: Lab 07 - Tasks Parameterization, Build Stage 19 | lab08: 20 | name: Lab 08 - Unit Test Stage 21 | lab09: 22 | name: Lab 09 - Static Application Security Testing 23 | lab10: 24 | name: Lab 10 - Archive App 25 | lab11: 26 | name: Lab 11 - Create Image 27 | lab12: 28 | name: Lab 12 - Deploy to Dev 29 | lab13: 30 | name: Lab 13 - Promote to Stage 31 | lab14: 32 | name: Lab 14 - Setting Up Pipeline Triggers 33 | lab15: 34 | name: Lab 15 - Activate the Secure Software Factory 35 | lab16: 36 | name: Lab 16 - Clair Vulnerability Scan 37 | lab17: 38 | name: Lab 17 - OpenSCAP Scan 39 | Fin: 40 | name: Fin 41 | appendix: 42 | name: Appendix 43 | -------------------------------------------------------------------------------- /tekton/workshop/workshop.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: DevSecOps Workshop - Secure Software Factory 3 | 4 | modules: 5 | activate: 6 | - index 7 | - lab01 8 | - lab02 9 | - lab03 10 | - lab04 11 | - lab05 12 | - lab06 13 | - lab07 14 | - lab08 15 | - lab09 16 | - lab10 17 | - lab11 18 | - lab12 19 | - lab13 20 | - lab14 21 | - lab15 22 | - lab16 23 | - lab17 24 | - Fin 25 | - appendix 26 | --------------------------------------------------------------------------------