donal
2018-04-26 c7c85417442b3620b8a9147b503a5d5a6421c4f7
commit | author | age
e36a5b 1 # An Enslaved Hope
43f2f2 2
dd12d4 3 > In this exercise we'll break free from the chains of point'n'click Jenkins by introducing pipeline as code in the form of `Jenkinsfile`. Following this we will introduce some new Jenkins slaves that will be used in later labs. 
e36a5b 4
921415 5 ![jenkins-fail-meme](../images/exercise4/jenkins-fail-meme.jpeg)
D 6
e36a5b 7 There are a number of ways pipeline as code can be achieved in Jenkins.
D 8  * The Job DSL Plugin - this is a slightly older but very functional DSL mechanism to create reusable pipelines. Create a `groovy` file to run Jenkins Domain Specific Language to create jobs, functions and other items. In Jenkins; you then can execute this file which will build all of the config.xml files needed for each Job. 
dd12d4 9  * The Scripted Pipeline - The scripted pipeline introduced the Jenkinsfile and the ability for developers to write their jenkins setup as groovy code. A repo with a Jenkinsfile in it's root can be pointed to by Jenkins and it will automatically build out each of the stages described within. The scripted pipeline is ultimately Groovy at it's core.
A 10  * The Declarative Pipeline - This approach looks to simplify and opinionate what you can do and when you can do it in a pipeline. It does this by giving you top level `block` which define sections, directives and steps. The declarative syntax is not run as groovy but you can execute groovy inside script blocks. The advantage of it over scripted is validation of the config and lighter approach with requirement to understand all of the `groovy` syntax
e36a5b 11
43f2f2 12 _____
D 13
14 ## Learning Outcomes
15 As a learner you will be able to
e36a5b 16 - Use a Jenkinsfile to create a declarative pipeline to build, bake and deploy the Todolist App 
D 17 - Identify the differences between scripted, declarative and DSL pipelines 
18 - Create Jenkins slave nodes for use in builds in future labs
43f2f2 19
D 20 ## Tools and Frameworks
21 > Name of tool - short description and link to docs or website
22
e36a5b 23 1. [Pipeline](https://jenkins.io/doc/book/pipeline/) - Overview of the Jenkinsfile approach
D 24 1. [Pipeline Syntax](https://jenkins.io/doc/book/pipeline/syntax/) - Documentation for the declarative pipeline
25 1. [Groovy](http://groovy-lang.org/) - Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.
b664dc 26 1. [Zed Attack Proxy](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) - The OWASP Zed Attack Proxy (ZAP) is one of the world’s most popular free security tools and is actively maintained by hundreds of international volunteers*. It can help you automatically find security vulnerabilities in your web applications while you are developing and testing your applications. Its also a great tool for experienced pentesters to use for manual security testing.
D 27 1. [Arachni Crawler](http://www.arachni-scanner.com/) - Arachni is a feature-full, modular, high-performance Ruby framework aimed towards helping penetration testers and administrators evaluate the security of modern web applications. It is free, with its source code public and available for review. It is versatile enough to cover a great deal of use cases, ranging from a simple command line scanner utility, to a global high performance grid of scanners, to a Ruby library allowing for scripted audits, to a multi-user multi-scan web collaboration platform. In addition, its simple REST API makes integration a cinch.
43f2f2 28
D 29 ## Big Picture
30 This exercise begins cluster containing blah blah
31
32 _____
33
34 ## 10,000 Ft View
e36a5b 35 > The goal of this exercise is to move to using the Jenkinsfile in the todolist-api and todolist-fe projects. Additionally we will create new slaves for use in the next lab
43f2f2 36
e36a5b 37 2. On Jenkins; create a multibranch pipeline project to scan the GitLab endpoint for each app. Use the Jenkinsfile provided to run the stages. Replace the `<YOUR_NAME>` with appropriate variable.
43f2f2 38
e36a5b 39 2. Create two new Jenkins slaves for the `OWASP ZAP` scanner and the `Arachni` WebCrawler
43f2f2 40
D 41 ## Step by Step Instructions
e36a5b 42 > This is a fairly structured guide with references to exact filenames and sections of text to be added. 
43f2f2 43
e36a5b 44 ### Part 1 - The Jenkinsfile
D 45 > _In this exercise we'll replace the Pipeline we created in Lab 2 with a Jenkinsfile approach_
43f2f2 46
e36a5b 47 2. On your terminal navigate to your `todolist-api` project and checkout the pipeline feature branch that's been already created for you.
D 48 ```bash
49 $ git checkout feature/jenkinsfile
43f2f2 50 ```
D 51
e36a5b 52 2. Open up your `todolist-api` application in your favourite editor and move to the `Jenkinsfile` in the root of the project. The highlevel structure of the file is shown collapsed below. 
D 53 ![pipeline-overview](../images/exercise4/pipeline-overview.png)
54 Some of the key things to note:
55     * `pipeline {}` is how all declarative jenkins pipelines begin.
db509f 56     * `environment {}` defines environment variables to be used across all build stages
A 57     * `options {}` contains specific Job specs you want to run globally across the jobs e.g. setting the terminal colour
58     * `stage {}` all jobs must have one stage. This is the logical part of the build that will be executed e.g. `bake-image`
e36a5b 59     * `steps {}` each `stage` has one or more steps involved. These could be execute shell or git checkout etc.
D 60     * `agent {}` specifies the node the build should be run on eg `jenkins-slave-npm`
61     * `post {}` hook is used to specify the post-build-actions. Jenkins declarative provides very useful callbacks for `success`, `failure` and `always` which are useful for controlling the job flow
62     * `when {}` is used for flow control. It can be used at stage level and be used to stop pipeline entering that stage. eg when branch is master; deploy to `test` environment.
63
70ba2a 64 2. The Jenkinsfile is mostly complete to do all the testing etc that was done in previous labs. Some minor changes will be needed to orchestrate namespaces. Find and replace all instances of `<YOUR_NAME>` in the Jenkinsfile. Update the `<GIT_USERNAME>` to the one you login to the cluster with; this variable is used in the namespace of your git projects when checking out code etc. Ensure the `GITLAB_DOMAIN` matches your git host.
e36a5b 65 ```groovy
D 66     environment {
67         // GLobal Vars
dd12d4 68         PIPELINES_NAMESPACE = "<YOUR_NAME>-ci-cd"
e36a5b 69         APP_NAME = "todolist-api"
D 70
71         JENKINS_TAG = "${JOB_NAME}.${BUILD_NUMBER}".replace("/", "-")
72         JOB_NAME = "${JOB_NAME}".replace("/", "-")
73
74         GIT_SSL_NO_VERIFY = true
75         GIT_CREDENTIALS = credentials('jenkins-git-creds')
70ba2a 76         GITLAB_DOMAIN = "gitlab.apps.lader.rht-labs.com"
D 77         GITLAB_PROJECT = "<GIT_USERNAME>"
e36a5b 78     }
D 79 ```
80
81 2. With these changes in place, push your changes to the `feature/jenkinsfile` branch.
82 ```bash
83 $ git add Jenkinsfile
84 $ git commit -m "ADD - namespace and git repo to pipeline"
85 $ git push
86 ```
87
88 2. When the changes have been successfully pushed; Open Jenkins.
89
90 2. Create a `New Item` on Jenkins. Give it the name `todolist-api` and select `Multibranch Pipeline` from the bottom of the list as the job type.
91 ![multibranch-select](../images/exercise4/multibranch-select.png)
92
93 2. On the job's configure page; set the Branch Sources to `git`
94 ![multibranch-select-git](../images/exercise4/multibranch-select-git.png)
95
44d41c 96 2. Fill in the Git settings with your `todolist-api` GitLab url and set the credentials as you've done before. `https://gitlab.apps.<SOMEDOMAIN>.com/<YOUR_NAME>/todolist-api.git`
e36a5b 97 ![multibranch-git](../images/exercise4/multibranch-git.png)
D 98
44d41c 99 2. Set the `Scan Multibranch Pipeline Triggers` to be periodic and the interval to 1 minute. This will poll the gitlab instance for new branches or change sets to build.
e36a5b 100 ![multibranch-scan-time](../images/exercise4/multibranch-scan-time.png)
D 101
2ff842 102 2. Save the Job configuration to run the intial scan. The log will show scans for `master` and `develop` branch which have no `Jenkinsfile` so are skipped. The resulting view will show the `feature/jenkinsfile` job corresponding the only branch that currently has one. The build should run automatically. 
e36a5b 103 ![todolist-api-multi](../images/exercise4/todolist-api-multi.png)
D 104
ed472a 105 2. The pipeline file is setup to only run `bake` & `deploy` stages when on `master` or `develop` branch. This is to provide us with very fast feedback for team members working on feature or bug fix branches. Each time someone commits or creates a new branch a basic build with testing occurs to give very rapid feedback to the team. Let's now update our  `master` and `develop` branches to include the Jenkinsfile and delete the feature branch.
e36a5b 106 ```bash
D 107 $ git checkout develop
108 $ git merge feature/jenkinsfile
ed472a 109 # you may get merge conflicts at this point
D 110 $ git add .
111 $ git commit -m "Jenkinsfile updates"
e36a5b 112 $ git checkout master
D 113 $ git merge develop
114 $ git push -u origin --all
115 # this is to delete the branch from the remote
116 $ git push origin :feature/jenkinsfile
117 ```
118
119 2. Back on Jenkins we should see our `todolist-api` pipelines have changed with the `develop` and `master` now appearing. The feature was deleted so this job should have gone away.
120 ![todolist-api-multi-dev-test](../images/exercise4/todolist-api-multi-dev-test.png)
121
122 2. With the builds running for  `develop` and `master` we can explore the Blue Ocean View for Jenkins. On the Job overview page, hit the Open Blue Ocean ![open-blue-ocean](../images/exercise4/open-blue-ocean.png)
123  button on the side to see what modern Jenkins looks like.
124 ![blue-ocean-todolist-api](../images/exercise4/blue-ocean-todolist-api.png)
125
126 2.  We can move on to the `todolist-fe` job. The process is the same as before, checkout the feature branch
127 ```bash
128 $ cd todolist-fe
129 $ git checkout feature/jenkinsfile
130 ```
131
ed472a 132 2. Open up your `todolist-fe` application in your favourite editor and move to the `Jenkinsfile` in the root of the project. Update all `<YOUR_NAME>` and `<GIT_USERNAME>` as you did before, including in the prepare environment steps. Check the  `GITLAB_DOMAIN` is set too. 
D 133 ![jenkinsfile-prep](../images/exercise4/jenkinsfile-prep.png)
e36a5b 134
D 135 2. Commit your changes to your feature branch as you did previously. 
136 ```bash
137 $ git add Jenkinsfile
138 $ git commit -m "ADD - namespace and git repo to pipeline"
139 $ git push
140 ```
141
142 2. This time update your master and develop branches before creating config in Jenkins
143 ```
ed472a 144 $ git checkout develop
D 145 $ git merge feature/jenkinsfile
146 # you may get merge conflicts at this point
147 $ git add .
148 $ git commit -m "Jenkinsfile updates"
149 $ git checkout master
150 $ git merge develop
151 # this is to delete the branch from the remote
152 $ git push origin :feature/jenkinsfile
153 $ git push -u origin --all
e36a5b 154 ```
D 155
156 2. On Jenkins; create a new `Multibranch Pipeline` job called `todolist-fe`.
157
158 2. Add the `todolist-fe` git repository and set the credentials for git accordingly. 
159
160 2. Set the trigger to scan every minute as done previously. Save the configuration and we should see the collection of Jobs as shown below.
161 ![todolist-fe-multi](../images/exercise4/todolist-fe-multi.png)
162
6769e3 163 2. Run the jobs and validate the app is working as expected in the `test` environment!
ed472a 164 ![todolist-test](../images/exercise4/todolist-test.png)
34fb36 165
D 166 ### Part 2 - OCP Pipeline
167 > _This exercise adds a new BuildConfig to our cluster for the todolist-apps to run their pipelines in OpenShift using the OpenShift Jenkins Sync Plugin. We will use the OpenShift Applier to create the content in the cluster_
168
b2ce13 169 2. Open the `todolist-fe` app in your favourite editor. Move to the `.openshift-applier` directory. Explore the `template/ocp-pipeline`. This template creates a BuildConfig for OpenShift with a Jenkinsfile from a given repo. In this case; it will be the `Jenkinsfile` at the root of our application.
34fb36 170
D 171 2. Open the `params/ocp-pipeline` file and update `PIPELINE_SOURCE_REPOSITORY_URL` with the git url of your project (Don't forget to add the `.git` at the end). For example:
172 ```
70ba2a 173 PIPELINE_SOURCE_REPOSITORY_URL=https://gitlab.apps.lader.rht-labs.com/<GIT_USERNAME>/todolist-fe.git
34fb36 174 PIPELINE_SOURCE_REPOSITORY_REF=develop
D 175 NAME=todolist-fe
176 ```
177
b2ce13 178 2. Create a new object in `inventory/group_vars/all.yml` to drive the `ocp-pipeline` template with the parameters file you've just created. It can be put under the existing `todolist-fe-build` object.
34fb36 179 ```yaml
D 180   - name: todolist-ocp-pipeline
181     template: "{{ playbook_dir }}/templates/ocp-pipeline.yml"
182     params: "{{ playbook_dir }}/params/ocp-pipeline"
183     namespace: "{{ ci_cd_namespace }}"
184     tags:
185     - pipeline
186 ```
187 ![ocp-pipeline-applier](../images/exercise4/ocp-pipeline-applier.png)
188
189 2. Use the OpenShift Applier to create the cluster content 
190 ```bash
191 $ cd .openshift-applier
192 $ ansible-playbook apply.yml -i inventory/ \
193      -e "filter_tags=pipeline"
194 ```
195
d4f1fa 196 2. With these changes in place, commit your changes to GitLab
D 197 ```bash
198 $ git add .
199 $ git commit -m "ADD - ocp pipeline in git repo"
200 $ git push
201 ```
202
34fb36 203 2. Login to your OpenShift Cluster and go to the `<YOUR_NAME>-ci-cd` namespace. On the side menu; hit Builds > Pipeline to see your newly created pipeline running in OCP Land.
D 204 ![ocp-pipeline-view](../images/exercise4/ocp-pipeline-view.png)
205
206 2. Running the pipeline from here will run it in Jenkins. You can see the job sync between OpenShift and Jenkins if you login to Jenkins. You should see a folder with `<YOUR_NAME>-ci-cd` and your pipeline jobs inside of it.
207 ![ocp-pipeline-jenkins](../images/exercise4/ocp-pipeline-jenkins.png)
208
209 2. With the configuration in place for the `todolist-fe`; repeat the process for the `todolist-api`. Update the `todolist-api/.openshift-applier/inventory/group_vars/all.yml` with a new object to drive the params and template
210 ```yaml
d4f1fa 211   - name: todolist-ocp-pipeline
34fb36 212     template: "{{ playbook_dir }}/templates/ocp-pipeline.yml"
D 213     params: "{{ playbook_dir }}/params/ocp-pipeline"
214     namespace: "{{ ci_cd_namespace }}"
215     tags:
216     - pipeline
217 ```
218
219 2. Update the `todolist-api/.openshift-applier/params/ocp-pipeline`
220 ```
70ba2a 221 PIPELINE_SOURCE_REPOSITORY_URL=https://gitlab.apps.lader.rht-labs.com/<GIT_USERNAME>/todolist-api.git
34fb36 222 PIPELINE_SOURCE_REPOSITORY_REF=develop
D 223 NAME=todolist-api
224 ```
225
226 2. Use the OpenShift Applier to create the cluster content 
227 ```bash
d4f1fa 228 $ cd todolist-api/.openshift-applier
34fb36 229 $ ansible-playbook apply.yml -i inventory/ \
D 230      -e "filter_tags=pipeline"
231 ```
232
233 2. Login to your OpenShift Cluster and go to the `<YOUR_NAME>-ci-cd` namespace. On the side menu; hit Builds > Pipeline to see your newly created pipeline running in OCP Land.
234 ![ocp-pipeline-view2](../images/exercise4/ocp-pipeline-view2.png)
235
d4f1fa 236 2. Commit your changes to GitLab
D 237 ```bash
238 $ git add .
239 $ git commit -m "ADD - ocp pipeline in git repo"
240 $ git push
241 ```
34fb36 242
D 243 ### Part 3 - Security Scanning Slaves
e36a5b 244 > _This exercise focuses on updating the `enablement-ci-cd` repo with some new jenkins-slave pods for use in future exercise_
43f2f2 245
d4f1fa 246 #### 3a - OWASP ZAP
6769e3 247 > _OWASP ZAP (Zed Attack Proxy) is a free open source security tool used for finding security vulnerabilities in web applications._
A 248
e32e5c 249 3. On your  terminal; move to the `enablement-ci-cd` repo. We already have the `templates/jenkins-slave-generic-template.yml` template we're going to re-use from the previous lab so all we need is to check out the params file
6769e3 250 ```bash
e32e5c 251 $ git checkout exercise4/zap-and-arachni params/jenkins-slave-zap
6769e3 252 ```
A 253
e32e5c 254 3. This should have created the following files which we will fill out. We will use a `ZAP` image hosted on the `rht-labs/ci-cd` repo so there will be no `Dockerfile` needed as we did with the `jenkins-slave-npm` in exercise 2:
D 255     - `params/jenkins-slave-zap`
6769e3 256
da9923 257 3. Create an object in `inventory/host_vars/ci-cd-tooling.yml` called `jenkins-slave-zap` and add the following content:
054490 258 ```yaml
da9923 259     - name: "jenkins-slave-zap"
b664dc 260       namespace: "{{ ci_cd_namespace }}"
D 261       template: "{{ playbook_dir }}/templates/jenkins-slave-generic-template.yml"
da9923 262       params: "{{ playbook_dir }}/params/jenkins-slave-zap"
b664dc 263       tags:
D 264       - zap
6769e3 265 ```
2c15b7 266 ![zap-object](../images/exercise4/zap-object.png)
6769e3 267
A 268 3. Run the ansible playbook filtering with tag `zap` so only the zap build pods are run.
269 ```bash
b664dc 270 $ ansible-playbook apply.yml -e target=tools \
D 271      -i inventory/ \
272      -e "filter_tags=zap"
6769e3 273 ```
A 274
da9923 275 3. Head to (https://console.somedomain.com/console/project/<YOUR_NAME>-ci-cd/browse/builds) on Openshift and you should see `jenkins-slave-zap`.
e32e5c 276 ![zap-build](../images/exercise4/zap-build.png)
6769e3 277
d4f1fa 278 #### 3b - Arachni Scan
6769e3 279 > _Arachni is a feature-full, modular, high-performance Ruby framework aimed towards helping penetration testers and administrators evaluate the security of web applications._
e32e5c 280
D 281 3. On your terminal; checkout the params and Docker file. The Dockerfile for the `Arachni` scanner is included here and we will point the build to it. 
282 ```bash
283 $ git checkout exercise4/zap-and-arachni params/jenkins-slave-arachni docker/jenkins-slave-arachni 
284 ```
6769e3 285
da9923 286 3. Create an object in `inventory/host_vars/ci-cd-tooling.yml` called `jenkins-slave-arachni` with the following content:
054490 287 ```yaml
da9923 288     - name: "jenkins-slave-arachni"
b664dc 289       namespace: "{{ ci_cd_namespace }}"
D 290       template: "{{ playbook_dir }}/templates/jenkins-slave-generic-template.yml"
da9923 291       params: "{{ playbook_dir }}/params/jenkins-slave-arachni"
b664dc 292       tags:
D 293       - arachni
6769e3 294 ```
A 295
2ff842 296 3. Update the `jenkins-slave-arachni` files `SOURCE_REPOSITORY_URL` to point to your gitlab's hosted version of the `enablement-ci-cd` repo.
e32e5c 297 ```
D 298 SOURCE_REPOSITORY_URL=https://gitlab.apps.lader.rht-labs.com/<GIT_USERNAME>/enablement-ci-cd.git
299 SOURCE_CONTEXT_DIR=docker/jenkins-slave-arachni
300 BUILDER_IMAGE_NAME=registry.access.redhat.com/openshift3/jenkins-slave-base-rhel7:latest
301 NAME=jenkins-slave-arachni
302 SOURCE_REPOSITORY_REF=master
303 ```
304
305 3. With these changes in place, push your changes to the `master` branch.
306 ```bash
307 $ git add .
308 $ git commit -m "ADD - Arachni scanning image"
309 $ git push
310 ```
311
fd433b 312 3. Run the ansible playbook filtering with tag `arachni` so only the arachni build pods are run.
6769e3 313 ```bash
b664dc 314 $ ansible-playbook apply.yml -e target=tools \
D 315      -i inventory/ \
316      -e "filter_tags=arachni"
6769e3 317 ```
A 318
da9923 319 3. Head to (https://console.somedomain.com/console/project/<YOUR_NAME>-ci-cd/browse/builds) on Openshift and you should see `jenkins-slave-arachni`.
054490 320 ![todolist-fe-multi](../images/exercise4/builds-zap-arachni.png)
43f2f2 321
D 322 _____
323
324 ## Extension Tasks
325 > _Ideas for go-getters. Advanced topic for doers to get on with if they finish early. These will usually not have a solution and are provided for additional scope._
e36a5b 326
D 327 Jenkins S2I
328  - Add the multi-branch configuration to the S2I to have Jenkins come alive with the `todolist-api` and `-fe` configuration cooked into it for future uses.
329
d608d6 330 Jenkins Pipeline Extension
D 331  - Add an extension to the pipeline that promotes code to UAT environment once the master job has been successful. 
332  - Use a WAIT to allow for manual input to appove the promotion
333
334 Jenkins e2e extension (blue/green)
db509f 335  - Add a step in the pipeline to only deploy to the `test` environment if the e2e tests have run successfully against which ever environment (blue or green) is not deployed.
43f2f2 336
D 337 ## Additional Reading
338 > List of links or other reading that might be of use / reference for the exercise
339
01c4da 340 ## Slide Links
RH 341
342 - [Intro](https://docs.google.com/presentation/d/1B3Fv4g66zZ8ZkqBq9TYmImJhUDvMecXCt4q3DXGWhjc/)
343 - [Wrap-up](https://docs.google.com/presentation/d/1EOk6y798Xh1hsaQlxRuqyr23FIIf7sNY4any_yXIL7A/)
344 - [All Material](https://drive.google.com/drive/folders/1oCjpl33Db7aPocmpu3NNF0B9czRvFq3m)