Now that you have seen how a developer can quickly start to code using modern cloud native tooling, it’s time to learn how to push the application towards a production environment. The first step is to implement a CI/CD pipeline to automate new builds. Let’s call this stage int for integration.
To create and run the build pipeline you’ll use OpenShift Pipelines based on project Tekton. The first step is to install it:
Red Hat OpenShift Pipelines Operator
Red Hat OpenShift Pipelines Operator and install it with the default settingsSince the Piplines assets are installed asynchronously it is possible that the Pipeline Templates are not yet setup when proceeding immedately to the next step. So now is good time to grab a coffee.
After installing the Operator, create a new deployment of your game-changing application:
workshop-int (e.g. using the Projects menu item at the top)workshop-int project by verifying in the top Project menuquarkus-build-options repo in your Gitea instance
 othermasterBuilder ImageJava and openjdk-11-el7 / Red Hat OpenJDK 11 (RHEL 7)
workshop-appworkshopIf you don’t have the checkbox Add pipeline and get the message There are no pipeline templates available for Java and Deployment combination in the next step then just give it few more minutes and reload the page.
 The current Pipeline deploys to the Internal Registry by default. The image that was just created by the first run was pushed there.
To leverage our brand new Quay registry we need to modify the Pipeline in order to push the images to the Quay registry. In addition the OpenShift ImageStream must be modified to point to the Quay registry, too.
s2i-java ClusterTaskThe first thing is to create a new Source-To-Image Pipeline Task to automatically update the ImageStream to point to Quay. You could of course copy and modify the default s2i-java task using the built-in YAML editor of the OpenShift Web Console. But to make this as painless as possible we have prepared the needed YAML object definition for you already.
oc commandshttps://github.com/devsecops-workshop/yaml.git, go there and review the YAML definition.oc create -f https://raw.githubusercontent.com/devsecops-workshop/yaml/main/s2i-java-workshop.yml
 To make this lab pretty much self-contained, we run oc commands from the OCP Web Terminal. But of course you can do the above steps from any Linux system where you set up the oc command.
You should now have a new ClusterTask named s2i-java-workshop, go to the OpenShift Web Console and check:
workshop-int Projects2i-java-workshop ClusterTask and open itPlease take the time to review the additions to the default s2i-java task:
In the params section there are two new parameters, that will tell the pipeline which ImageStream and tag to update.
- default: ''
    description: The name of the ImageStream which should be updated
    name: IMAGESTREAM
    type: string
- default: ''
    description: The Tag of the ImageStream which should be updated
    name: IMAGESTREAMTAG
    type: string
At the end of the steps section is a new step that takes care of actaully creating the ImageStream tag that points to the image in Quay
- env:
    - name: HOME
      value: /tekton/home
    image: 'image-registry.openshift-image-registry.svc:5000/openshift/cli:latest'
    name: update-image-stream
    resources: {}
    script: >
      #!/usr/bin/env bash
      oc tag --source=docker $(params.IMAGE)
      $(params.IMAGESTREAM):$(params.IMAGESTREAMTAG) --insecure
    securityContext:
      runAsNonRoot: true
      runAsUser: 65532
Now that we have our new build tasks we need to modify the pipeline to:
s2i-java-workshop taskTo make this easier we again provide you with a full YAML definition for the Pipeline.
Do the following:
If you use this lab guide with your domain as query parameter (see here), you are good to go with the command below because your domain was already inserted into the command. If not, you have to replace <DOMAIN> manually.
curl https://raw.githubusercontent.com/devsecops-workshop/yaml/main/workshop-pipeline-without-git-update.yml -o workshop-pipeline-without-git-update.yml
REPLACEME placeholders in the YAML file with your lab domain.sed -i 's/REPLACEME/<DOMAIN>/g' workshop-pipeline-without-git-update.yml
oc replace -f workshop-pipeline-without-git-update.yml
Again take the time to review the changes in the web console:
workshop Pipeline and switch to YAML- default: workshop
  name: IMAGESTREAM
  type: string
- default: latest
  name: IMAGESTREAMTAG
  type: string
The preexisting parameter IMAGE_NAME now points to your local Quay registry:
   - default: >-
        quay-quay-quay.apps.<DOMAIN>/openshift_workshop-int/workshop
      name: IMAGE_NAME
      type: string
And finally the build task was modified to work with the two new parameters:
tasks:
    - name: build
      params:
        [...]
        - name: IMAGESTREAM
          value: $(params.IMAGESTREAM)
        - name: IMAGESTREAMTAG
          value: $(params.IMAGESTREAMTAG)
taskRef was changed to s2i-java-workshop, in order to use our custom Pipeline Task:taskRef:
  kind: ClusterTask
  name: s2i-java-workshop
You are done with adapting the Pipeline to use the Quay registry!
We are ready to give it a try, but first let’s have quick look at our target Quay repository
openshift_workshop-int organization.openshift_workshop-int / workshop repository access the Tags in the menu to the left.
 Now it’s time to configure and start the Pipeline.
workshop PipelineIn the Start Pipeline window that opens, but before (!) starting the actual pipeline, we need to add a Secret so the pipeline can authenticate and push to the Quay repository:
openshift_workshop-int / workshop repositoryopenshift_workshop-int+builder Robot Account and copy the token
 quay-workshop-int-tokenImage RegistryBasic Authenticationquay-quay-quay.apps.<DOMAIN>/openshift_workshop-int (replace your cluster domain if necessary)openshift_workshop-int+builderIf the pipeline fails you may have to recheck the Secret quay-workshop-int-token directly if the username and password are set correctly.
Once the Pipeline run has finished, go to the Quay Portal and check the Repository openshift_workshop-int/workshop again. Under Tags you should now see a new workshop Image version that was just pushed by the pipeline.
Congratulations: Quay is now a first level citizen of your pipeline build strategy.
Now that your build pipeline has been set up and is ready. There is one more step in preparation of the security part of this workshop. We need a way to build and deploy from an older image with some security issues in it. For this we will add another ImageStream Tag in the default Java ImageStream that points to an older version with a known CVE issue in it.
openshift and under Builds click on ImageStreamsjavaspec > tags: section.
- name: java-old-image
  annotations:
    description: Build and run Java applications using Maven and OpenJDK 8.
    iconClass: icon-rh-openjdk
    openshift.io/display-name: Red Hat OpenJDK 8 (UBI 8)
    sampleContextDir: undertow-servlet
    sampleRepo: "https://github.com/jboss-openshift/openshift-quickstarts"
    supports: "java:8,java"
    tags: "builder,java,openjdk"
    version: "8"
  from:
    kind: DockerImage
    name: "registry.redhat.io/openjdk/openjdk-11-rhel7:1.10-1"
  generation: 4
  importPolicy: {}
  referencePolicy:
    type: Local
This will add a tag java-old-image that points to an older version of the RHEL Java image. The image and security vulnerabilities can be inspected in the Red Hat Software Catalog here
1.10-1We will use this tag to test our security setup in a later chapter.
For the subsequent exercises we need a new project:
workshop-prod