├── Jenkinsfile
├── LICENSE
├── README.md
├── config.xml
├── docker-compose.yml
├── jenkins
├── Dockerfile
├── ansible.cfg
├── plugins.txt
└── setupJenkins.groovy
├── jenkins_home
├── ansible_hosts
├── authDAST.py
├── configureTestEnv.yml
├── configureWAF.yml
├── createAwsEc2.yml
├── hostaudit.yml
├── killec2.yml
└── strategy.ini
└── setup-ubuntu.sh
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | /*
2 | This pipeline will carry out the following on the project:
3 |
4 | 1. Git secret checker
5 | 2. Software Composition Analysis
6 | 3. Static Application Security Testing
7 | 4. Container security audit
8 | 5. Dynamic Application Security Testing
9 | 6. Host system security audit
10 | 7. Host application protection
11 |
12 | */
13 |
14 | testenv = "null"
15 |
16 | pipeline {
17 | /* Which agent are we running this pipeline on? We can configure different OS */
18 | agent any
19 |
20 | stages {
21 | stage('Checkout project'){
22 | steps {
23 | echo 'downloading git directory..'
24 | git 'https://github.com/pawnu/secDevLabs.git'
25 | }
26 | }
27 | stage('git secret check'){
28 | steps{
29 | script{
30 | echo 'running trufflehog to check project history for secrets'
31 | sh 'trufflehog --regex --entropy=False --max_depth=3 https://github.com/pawnu/secDevLabs'
32 | }
33 | }
34 | }
35 | stage('SCA'){
36 | steps{
37 | echo 'running python safety check on requirements.txt file'
38 | sh 'safety check -r $WORKSPACE/owasp-top10-2017-apps/a7/gossip-world/app/requirements.txt'
39 | /*
40 | echo 'running liccheck on dependencies'
41 | sh """
42 | virtualenv --no-site-packages .
43 | source bin/activate
44 | pip install -r $WORKSPACE/owasp-top10-2017-apps/a7/gossip-world/app/requirements.txt
45 | liccheck -s ~/my_strategy.ini -r $WORKSPACE/owasp-top10-2017-apps/a7/gossip-world/app/requirements.txt
46 | deactivate
47 | """
48 | */
49 | }
50 | }
51 | stage('SAST') {
52 | steps {
53 | echo 'Testing source code for security bugs and vulnerabilities'
54 | sh 'bandit -r $WORKSPACE/owasp-top10-2017-apps/a7/gossip-world/app/ -ll || true'
55 | }
56 | }
57 | stage('Container audit') {
58 | steps {
59 | echo 'Audit the dockerfile used to spin up the web application'
60 | script{
61 | def exists = fileExists '/var/jenkins_home/lynis/lynis'
62 | if(exists){
63 | echo 'lynis already exists'
64 | }else{
65 | sh """
66 | wget https://downloads.cisofy.com/lynis/lynis-2.7.5.tar.gz
67 | tar xfvz lynis-2.7.5.tar.gz -C ~/
68 | rm lynis-2.7.5.tar.gz
69 | """
70 | }
71 | }
72 | dir("/var/jenkins_home/lynis"){
73 | sh """
74 | mkdir $WORKSPACE/$BUILD_TAG/
75 | ./lynis audit dockerfile $WORKSPACE/owasp-top10-2017-apps/a7/gossip-world/deployments/Dockerfile | ansi2html > $WORKSPACE/$BUILD_TAG/docker-report.html
76 | mv /tmp/lynis.log $WORKSPACE/$BUILD_TAG/docker_lynis.log
77 | mv /tmp/lynis-report.dat $WORKSPACE/$BUILD_TAG/docker_lynis-report.dat
78 | """
79 | }
80 | }
81 | }
82 | stage('Setup test env') {
83 | steps {
84 | sh """
85 | #refresh inventory
86 | echo "[local]" > ~/ansible_hosts
87 | echo "localhost ansible_connection=local" >> ~/ansible_hosts
88 | echo "[tstlaunched]" >> ~/ansible_hosts
89 |
90 | tar cvfz /var/jenkins_home/pythonapp.tar.gz -C $WORKSPACE/owasp-top10-2017-apps/a7/ .
91 |
92 | ssh-keygen -t rsa -N "" -f ~/.ssh/psp_ansible_key || true
93 | ansible-playbook -i ~/ansible_hosts ~/createAwsEc2.yml
94 | """
95 | script{
96 | testenv = sh(script: "sed -n '/tstlaunched/{n;p;}' /var/jenkins_home/ansible_hosts", returnStdout: true).trim()
97 | }
98 | echo "${testenv}"
99 | sh 'ansible-playbook -i ~/ansible_hosts ~/configureTestEnv.yml'
100 | }
101 | }
102 | stage('DAST') {
103 | steps {
104 | script{
105 | //Test the web application from its frontend
106 | /*
107 | def exists = fileExists '/var/jenkins_home/nikto-master/program/nikto.pl'
108 | if(exists){
109 | echo 'nikto already exists'
110 | }else{
111 | sh """
112 | wget https://github.com/sullo/nikto/archive/master.zip
113 | unzip master.zip -d ~/ || true
114 | rm master.zip
115 | """
116 | }
117 | */
118 | def seleniumIp = env.SeleniumPrivateIp
119 | if("${testenv}" != "null"){
120 | sh "python ~/authDAST.py $seleniumIp ${testenv} $WORKSPACE/$BUILD_TAG/DAST_results.html"
121 | //sh "perl /var/jenkins_home/nikto-master/program/nikto.pl -h http://${testenv}:10007/login"
122 | }
123 | }
124 | }
125 | }
126 | stage('System security audit') {
127 | steps {
128 | echo 'Run lynis audit on host and fetch result'
129 | sh 'ansible-playbook -i ~/ansible_hosts ~/hostaudit.yml --extra-vars "logfolder=$WORKSPACE/$BUILD_TAG/"'
130 | }
131 | }
132 | stage('Deploy WAF') {
133 | steps {
134 | echo 'Deploy modsecurity as reverse proxy'
135 | sh 'ansible-playbook -i ~/ansible_hosts ~/configureWAF.yml'
136 | }
137 | }
138 | }
139 | post {
140 | always {
141 | echo 'We could bring down the ec2 here'
142 | /*
143 | echo 'Tear down activity'
144 | script{
145 | if("${testenv}" != "null"){
146 | echo "killing host ${testenv}"
147 | sh 'ansible-playbook -i ~/ansible_hosts ~/killec2.yml'
148 | }
149 | }
150 | */
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Pawan Uppadey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DevSecOps pipeline for Python project
2 |
3 | A Jenkins end-to-end DevSecOps pipeline for Python web application, hosted on AWS Ubuntu 18.04
4 |
5 | 
6 |
7 |
8 |
9 | *Disclaimer: This project is for demonstration purpose with surface level checks only, do not use it as-is for production*
10 |
11 | > **Checkout project** - check out python application project repository with XSS vulnerability
12 |
13 | > **git secret check** - check there is no password/token/keys/secrets accidently commited to project github
14 |
15 | > **SCA** - check external dependencies/libraries used by the project have no known vulnerabilities
16 |
17 | > **SAST** - static analysis of the application source code for exploits, bugs, vulnerabilites
18 |
19 | > **Container audit** - audit the container that is used to deploy the python application
20 |
21 | > **DAST** - deploy the application, register, login, attack & analyse it from the frontend as authenticated user
22 |
23 | > **System security audit** - analyse at the security posture of the system hosting the application
24 |
25 | > **WAF** - deploy application with WAF which will filter malicious requests according to OWASP core ruleset
26 |
27 |
28 | ## Installation steps
29 |
30 | 1. Clone this repository to your Ubuntu Server (t2-medium recommended)
31 | ```
32 | git clone https://github.com/pawnu/PythonSecurityPipeline.git
33 | ```
34 |
35 | 2. Edit the code to make it work on your AWS
36 | - Change to your AWS subnet [vpc_subnet_id](jenkins_home/createAwsEc2.yml#L30)
37 | - Change to your AWS [security_group](jenkins_home/createAwsEc2.yml#L10) (allow inbound ssh(22), WAF(80), *Optional* web-app(10007) from your IP ONLY)
38 | - Create an IAM role which gives full-ec2-access and assign it to your ubuntu server
39 |
40 | 3. Run the setup script to create CICD server with Jenkins+pipeline ready to go
41 | ```
42 | cd PythonSecurityPipeline
43 | sudo sh setup-ubuntu.sh
44 | ```
45 |
46 | 4. Make sure your firewall allows incoming traffic to port 8080. Then, go to your jenkins server URL
47 | ```
48 | http://your-jenkins-server:8080/
49 | ```
50 | 5. Use the temporary credentials provided on the logs to login. Change your password!
51 | 6. Go to the python pipeline project dashboard, click on "Build Now" button to start it off.
52 |
53 | ## Setting up a Jenkins Pipeline project manually
54 |
55 | **A sample pipeline is already provided through automation**
56 |
57 | 1. Click on New Item, input name for your project and select Pipeline as the option and click OK.
58 | 2. Scroll down to Pipeline section - Definition, select "Pipeline script from SCM" from drop down menu.
59 | 3. Select Git under SCM, and input Repository URL.
60 | 4. (Optional) Create and Add your credentials for the Git repo if your repo is private, and click Save.
61 | 5. You will be brought to the Dashboard of your Pipeline project, click on "Build Now" button to start off the pipeline.
62 |
63 |
64 | **To do list:**
65 | - [x] Select appropriate security tools and sample python project
66 | - [x] Set up Jenkins server using docker (Dockerfile) and pipeline as code (Jenkinsfile) to run the checks
67 | - [x] Use ansible to create AWS ec2 test instance, configure the environment, and interact with it
68 | - [x] Hook up the web-app with ~~nginx~~+modsecurity providing WAF, ~~DDoS protection~~, reverse proxy capabilities
69 | - [x] Bootstrap with Jenkins API/configfile to setup and automatically create the pipeline job
70 | - [x] Carry out authenticated DAST scan on the python web app
71 |
72 | ## Demo
73 |
74 | 
75 |
76 | ### Report
77 |
78 | 
79 |
80 | ## Authors
81 |
82 | * **Pawan Uppadey** - [pawnu](https://github.com/pawnu)
83 |
84 |
--------------------------------------------------------------------------------
/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | false
14 |
15 |
16 |
17 | 2
18 |
19 |
20 | https://github.com/pawnu/PythonSecurityPipeline.git
21 |
22 |
23 |
24 |
25 | */master
26 |
27 |
28 | false
29 |
30 |
31 |
32 | Jenkinsfile
33 | true
34 |
35 |
36 | false
37 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | jenkins-master:
4 | build:
5 | context: ./jenkins
6 | restart: always
7 | ports:
8 | - "50000:50000"
9 | - "8080:8080"
10 | volumes:
11 | - ./jenkins_home:/var/jenkins_home
12 | container_name: jenkins-master
13 | environment:
14 | - "Jenkins_PW=${Jenkins_PW}"
15 | - "JAVA_OPTS=${JAVA_OPTS}"
16 | - "JenkinsPublicHostname=${JenkinsPublicHostname}"
17 | - "SeleniumPrivateIp=${SeleniumPrivateIp}"
18 | selenium-chrome:
19 | image: selenium/standalone-chrome
20 | restart: always
21 | container_name: selenium-chrome
22 | ports:
23 | - "4444:4444"
24 | volumes:
25 | - "/dev/shm:/dev/shm"
26 |
--------------------------------------------------------------------------------
/jenkins/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jenkins/jenkins:lts
2 | MAINTAINER pawan uppadey
3 |
4 | #Install Jenkins plugin to make this pipeline work
5 | COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
6 | RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
7 |
8 | #Copy script to auto create user to jenkins init folder
9 | COPY setupJenkins.groovy /usr/share/jenkins/ref/init.groovy.d/
10 |
11 | #setup the docker container for scanners
12 | USER root
13 | RUN apt-get update && apt-get install -y \
14 | python-pip \
15 | curl \
16 | maven \
17 | git \
18 | perl \
19 | wget \
20 | kbtin \
21 | libnet-ssleay-perl \
22 | software-properties-common
23 |
24 | #add public key for the multiverse repo which has nikto
25 | RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32
26 | RUN add-apt-repository 'deb http://archive.ubuntu.com/ubuntu bionic multiverse'
27 | RUN add-apt-repository 'deb http://archive.ubuntu.com/ubuntu bionic-security multiverse'
28 | RUN add-apt-repository 'deb http://archive.ubuntu.com/ubuntu bionic-updates multiverse'
29 |
30 | RUN apt-get update -y
31 | RUN apt-get install -y nikto
32 |
33 | #Install virtualenv to isolate each project dependencies
34 | RUN pip install virtualenv
35 | #Install python SCA tool/dependency checker, license check
36 | RUN pip install safety
37 | RUN pip install liccheck
38 | #Install the git history checker for secrets
39 | RUN pip install trufflehog
40 | #Install python SAST tool
41 | RUN pip install bandit
42 |
43 | # Used for authenticated DAST scan
44 | RUN pip install selenium
45 |
46 | #install the orchestration tool, boto for ec2 module, some lib upgrade under requests
47 | RUN pip install ansible
48 | RUN pip install boto
49 | RUN pip install boto3
50 |
51 | # configure ansible to use right keys and not check host auth for this ephemeral/temp aws host
52 | # Not authenticating existing/long-term hosts requiring relogins may lead to mitm.. be careful
53 | COPY ansible.cfg /etc/ansible/ansible.cfg
54 |
55 | # drop back to the regular jenkins user - good practice
56 | USER jenkins
57 |
--------------------------------------------------------------------------------
/jenkins/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | host_key_checking = False
3 | private_key_file = ~/.ssh/psp_ansible_key
4 |
--------------------------------------------------------------------------------
/jenkins/plugins.txt:
--------------------------------------------------------------------------------
1 | pipeline-input-step:2.11
2 | git-server:1.9
3 | junit:1.28
4 | workflow-multibranch:2.21
5 | apache-httpcomponents-client-4-api:4.5.10-2.0
6 | lockable-resources:2.7
7 | matrix-auth:2.5
8 | pipeline-milestone-step:1.3.1
9 | workflow-job:2.36
10 | ldap:1.21
11 | token-macro:2.10
12 | structs:1.20
13 | script-security:1.68
14 | workflow-support:3.3
15 | ssh-credentials:1.18
16 | pipeline-model-declarative-agent:1.1.1
17 | ws-cleanup:0.38
18 | git-client:3.0.0
19 | resource-disposer:0.14
20 | display-url-api:2.3.2
21 | gradle:1.35
22 | ant:1.10
23 | email-ext:2.68
24 | ace-editor:1.1
25 | docker-commons:1.16
26 | cloudbees-folder:6.10.1
27 | authentication-tokens:1.3
28 | pipeline-model-definition:1.5.0
29 | antisamy-markup-formatter:1.6
30 | workflow-scm-step:2.9
31 | bouncycastle-api:2.17
32 | trilead-api:1.0.5
33 | ssh-slaves:1.31.0
34 | timestamper:1.10
35 | workflow-step-api:2.21
36 | jdk-tool:1.4
37 | durable-task:1.33
38 | mailer:1.29
39 | workflow-api:2.38
40 | workflow-aggregator:2.6
41 | pipeline-github-lib:1.0
42 | pipeline-model-extensions:1.5.0
43 | pipeline-model-api:1.5.0
44 | workflow-durable-task-step:2.35
45 | github-branch-source:2.5.8
46 | branch-api:2.5.5
47 | jackson2-api:2.10.1
48 | build-timeout:1.19
49 | pam-auth:1.6
50 | jsch:0.1.55.1
51 | workflow-cps-global-lib:2.15
52 | jquery-detached:1.2.1
53 | git:4.0.0
54 | pipeline-stage-step:2.3
55 | subversion:2.13.0
56 | github:1.29.5
57 | pipeline-stage-tags-metadata:1.5.0
58 | command-launcher:1.4
59 | scm-api:2.6.3
60 | matrix-project:1.14
61 | pipeline-graph-analysis:1.10
62 | mapdb-api:1.0.9.0
63 | momentjs:1.1.1
64 | workflow-cps:2.78
65 | pipeline-stage-view:2.12
66 | plain-credentials:1.5
67 | credentials-binding:1.20
68 | credentials:2.3.0
69 | pipeline-build-step:2.10
70 | handlebars:1.1.1
71 | docker-workflow:1.21
72 | workflow-basic-steps:2.18
73 | github-api:1.95
74 | pipeline-rest-api:2.12
75 |
--------------------------------------------------------------------------------
/jenkins/setupJenkins.groovy:
--------------------------------------------------------------------------------
1 | import jenkins.model.*
2 | import hudson.security.*
3 | import jenkins.security.s2m.AdminWhitelistRule
4 | import jenkins.model.Jenkins
5 | import hudson.security.csrf.DefaultCrumbIssuer
6 |
7 | //don't let slave instance kill the master
8 | Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class)
9 | .setMasterKillSwitch(false)
10 |
11 | def env = System.getenv()
12 |
13 | /*
14 | Jenkins needs URL in order for reference links to point to other pages, resources, pipeline build etc
15 | */
16 | jlc = JenkinsLocationConfiguration.get()
17 | jlc.setUrl("http://"+env.JenkinsPublicHostname +":8080/")
18 | jlc.save()
19 |
20 | //Set CSRF token for Jenkins server
21 | def instance = Jenkins.instance
22 | instance.setCrumbIssuer(new DefaultCrumbIssuer(true))
23 | instance.save()
24 |
25 | /*
26 | Create admin user to login
27 | */
28 | def jenkins = Jenkins.getInstance()
29 | if(!(jenkins.getSecurityRealm() instanceof HudsonPrivateSecurityRealm))
30 | jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false))
31 |
32 | if(!(jenkins.getAuthorizationStrategy() instanceof GlobalMatrixAuthorizationStrategy))
33 | jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy())
34 |
35 | def user = jenkins.getSecurityRealm().createAccount("myjenkins", env.Jenkins_PW)
36 | user.save()
37 | jenkins.getAuthorizationStrategy().add(Jenkins.ADMINISTER, "myjenkins")
38 |
39 | jenkins.save()
40 |
--------------------------------------------------------------------------------
/jenkins_home/ansible_hosts:
--------------------------------------------------------------------------------
1 | [local]
2 | localhost ansible_connection=local
3 |
4 | [tstlaunched]
5 |
--------------------------------------------------------------------------------
/jenkins_home/authDAST.py:
--------------------------------------------------------------------------------
1 | from selenium import webdriver
2 | from selenium.webdriver.common.keys import Keys
3 | from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
4 | import json
5 | import subprocess
6 | import sys
7 | import random
8 | import string
9 |
10 | def randomString(stringLength):
11 | letters = string.ascii_letters
12 | return ''.join(random.choice(letters) for i in range(stringLength))
13 |
14 | def bash_command(cmd):
15 | subprocess.Popen(cmd, shell=True, executable='/bin/bash')
16 |
17 | myusername = randomString(8)
18 | mypassword = randomString(12)
19 |
20 | if len(sys.argv) < 4:
21 | print '1. Provide the ip address for selenium remote server!'
22 | print '2. Provide the ip address for target DAST scan!'
23 | print '3. Provide the output location of html report!'
24 | sys.exit(1)
25 |
26 | driver = webdriver.Remote("http://"+sys.argv[1]+":4444/wd/hub", DesiredCapabilities.CHROME)
27 |
28 | driver.get("http://"+sys.argv[2]+":10007/login")
29 |
30 | registerbutton = driver.find_element_by_xpath("/html/body/div/div/div/form/center[3]/a")
31 | registerbutton.click()
32 | print("we're at: " + driver.current_url)
33 |
34 | print("creating a user..")
35 | username = driver.find_element_by_name("username")
36 | password1 = driver.find_element_by_name("password1")
37 | password2 = driver.find_element_by_name("password2")
38 |
39 | username.clear()
40 | username.send_keys(myusername)
41 | password1.clear()
42 | password1.send_keys(mypassword)
43 | password2.clear()
44 | password2.send_keys(mypassword)
45 | password2.send_keys(Keys.RETURN)
46 | login = driver.find_element_by_xpath('/html/body/div/div/div/center[2]/h4')
47 | assert "Login" in login.text
48 |
49 | print("created user")
50 |
51 | driver.get("http://"+sys.argv[2]+":10007/login")
52 | print("we're at: " + driver.current_url)
53 | username = driver.find_element_by_name("username")
54 | password = driver.find_element_by_name("password")
55 | username.clear()
56 | username.send_keys(myusername)
57 | password.clear()
58 | password.send_keys(mypassword)
59 | password.send_keys(Keys.RETURN)
60 | header = driver.find_element_by_xpath("/html/body/div/div/div[1]/h1")
61 | assert "Last gossips" in header.text
62 | print("logged in successfully.. getting cookie")
63 |
64 | nikto_string = "STATIC-COOKIE="
65 | cookies_list = driver.get_cookies()
66 | for cookie in cookies_list:
67 | nikto_string+= '\"' + cookie['name'] + '\"='
68 | nikto_string+= '\"'+ cookie['value'] + '\"'
69 | bash_command("cp /etc/nikto/config.txt ~/nikto-config.txt")
70 | bash_command("echo '" + nikto_string +"' >> ~/nikto-config.txt")
71 | print("added cookie to nikto config file to carry out authenticated scan..")
72 | bash_command("nikto -ask no -config ~/nikto-config.txt -Format html -h http://"+sys.argv[2]+":10007/gossip -output "+ sys.argv[3])
73 |
--------------------------------------------------------------------------------
/jenkins_home/configureTestEnv.yml:
--------------------------------------------------------------------------------
1 | # Configure launched instance for test
2 | - name: Configure instance(s)
3 | hosts: tstlaunched
4 | become: True
5 | remote_user: ubuntu
6 | gather_facts: True
7 | tasks:
8 | - name: update package manager
9 | apt: update_cache=yes
10 | - name: Install docker
11 | apt: name=docker.io state=present
12 | - name: Install docker-compose
13 | apt: name=docker-compose update_cache=yes state=present
14 | - name: Install kbtin for lynis to produce html report
15 | apt: name=kbtin state=present
16 | - name: Install make to build the pythonapp
17 | apt: name=make state=present
18 | - name: Copy the zip file of project
19 | copy:
20 | src: pythonapp.tar.gz
21 | dest: /home/ubuntu/pythonapp.tar.gz
22 | - name: Unzip it
23 | unarchive:
24 | src: /home/ubuntu/pythonapp.tar.gz
25 | dest: /home/ubuntu/
26 | copy: no
27 | - name: Run the application with docker
28 | shell: make install
29 | args:
30 | chdir: gossip-world/
31 |
--------------------------------------------------------------------------------
/jenkins_home/configureWAF.yml:
--------------------------------------------------------------------------------
1 | # Configure launched instance for WAF
2 | - name: Configure instance(s)
3 | hosts: tstlaunched
4 | become: True
5 | remote_user: ubuntu
6 | gather_facts: True
7 | tasks:
8 | - name: Run the WAF on docker
9 | docker_container:
10 | name: modsecurity_waf
11 | image: owasp/modsecurity-crs
12 | state: started
13 | restart_policy: always
14 | ports:
15 | - "80:80"
16 | env:
17 | PARANOIA: "2"
18 | PROXY: "1"
19 | PROXYLOCATION: "http://{{ ansible_default_ipv4.address }}:10007/"
20 |
--------------------------------------------------------------------------------
/jenkins_home/createAwsEc2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Create ec2 instance and add it to ansible inventory
3 | - name: Create a sandbox instance
4 | hosts: localhost
5 | connection: local
6 | gather_facts: False
7 | vars:
8 | keyname: psp_ansible_key
9 | instance_type: t2.micro
10 | security_group: launch-wizard-1
11 | image: ami-0be057a22c63962cb
12 | region: eu-west-2
13 | tagname: Name=TestServer
14 |
15 | tasks:
16 | - name: Upload public key to AWS
17 | ec2_key:
18 | name: "{{ keyname }}"
19 | key_material: "{{ lookup('file', '~/.ssh/{{ keyname }}.pub') }}"
20 | region: "{{ region }}"
21 |
22 | - name: Launch instance
23 | ec2:
24 | key_name: "{{ keyname }}"
25 | group: "{{ security_group }}"
26 | instance_type: "{{ instance_type }}"
27 | image: "{{ image }}"
28 | wait: true
29 | region: "{{ region }}"
30 | vpc_subnet_id: subnet-02a17e56e6827124a
31 | assign_public_ip: yes
32 | instance_tags: "{{tagname}}"
33 | register: ec2
34 |
35 | - name: Add new instance to hosts group for test
36 | local_action: lineinfile
37 | dest="~/ansible_hosts"
38 | regexp={{ item.private_ip }}
39 | insertafter="[tstlaunched]"
40 | line="{{ item.private_ip }}"
41 | state=present
42 | with_items: "{{ ec2.instances }}"
43 |
44 | - name: Wait for SSH to come up
45 | local_action: wait_for
46 | host={{ item.private_ip }}
47 | port=22
48 | state=started
49 | with_items: "{{ ec2.instances }}"
50 |
--------------------------------------------------------------------------------
/jenkins_home/hostaudit.yml:
--------------------------------------------------------------------------------
1 | # Run lynis audit on system and fetch logs
2 | - name: Run host audit in instance(s)
3 | hosts: tstlaunched
4 | remote_user: ubuntu
5 | gather_facts: False
6 | tasks:
7 | - name: Get the lynis installer
8 | get_url:
9 | url: https://downloads.cisofy.com/lynis/lynis-2.7.5.tar.gz
10 | dest: /tmp/
11 | - name: Unzip it
12 | unarchive:
13 | src: /tmp/lynis-2.7.5.tar.gz
14 | dest: /home/ubuntu/
15 | copy: no
16 | - name: Run system audit
17 | shell: ./lynis audit system --quick --auditor "The Auditor" | ansi2html > host_audit_report.html
18 | args:
19 | chdir: lynis/
20 | - name: Fetch log file from host
21 | fetch:
22 | src: /tmp/lynis.log
23 | dest: "{{ logfolder }}"
24 | flat: yes
25 | - name: Fetch report file from host
26 | fetch:
27 | src: /tmp/lynis-report.dat
28 | dest: "{{ logfolder }}"
29 | flat: yes
30 | - name: Fetch fancy html report
31 | fetch:
32 | src: /home/ubuntu/lynis/host_audit_report.html
33 | dest: "{{ logfolder }}"
34 | flat: yes
35 | - name: Remove html report on host
36 | file:
37 | path: /home/ubuntu/lynis/host_audit_report.html
38 | state: absent
39 | - name: Remove log file on host
40 | file:
41 | path: /tmp/lynis.log
42 | state: absent
43 | - name: Remove report on host
44 | file:
45 | path: /tmp/lynis-report.dat
46 | state: absent
47 |
--------------------------------------------------------------------------------
/jenkins_home/killec2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Gather remote host info
3 | hosts: tstlaunched
4 | remote_user: ubuntu
5 | vars:
6 | region: "eu-west-2"
7 | tasks:
8 | - name: get remote instance metadata
9 | ec2_metadata_facts:
10 | - name: destroy the instance with instance id
11 | ec2:
12 | state: 'absent'
13 | region: "{{ region }}"
14 | instance_ids: "{{ ansible_ec2_instance_id }}"
15 | delegate_to: localhost
16 |
--------------------------------------------------------------------------------
/jenkins_home/strategy.ini:
--------------------------------------------------------------------------------
1 | # Authorized and unauthorized licenses in LOWER CASE
2 | [Licenses]
3 | authorized_licenses:
4 | bsd
5 | new bsd
6 | bsd license
7 | new bsd license
8 | simplified bsd
9 | apache
10 | apache 2.0
11 | apache software license
12 | gnu lgpl
13 | lgpl with exceptions or zpl
14 | isc license
15 | isc license (iscl)
16 | mit
17 | mit license
18 | python software foundation license
19 | zpl 2.1
20 |
21 | unauthorized_licenses:
22 | gpl v3
23 |
24 | [Authorized Packages]
25 | # Python software license (see http://zesty.ca/python/uuid.README.txt)
26 | uuid: 1.30
27 |
--------------------------------------------------------------------------------
/setup-ubuntu.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | apt-get update
4 | apt install docker.io -y
5 | apt-get install -y docker-compose
6 | apt install default-jre -y
7 |
8 | #have to relogin as ubuntu user
9 | usermod -aG docker ubuntu
10 |
11 | # restart new session with docker group
12 | #newgrp docker
13 |
14 | #let docker run when server is restarted
15 | systemctl enable docker
16 |
17 | #create random password for jenkins user which will be created automatically
18 | export Jenkins_PW=$(openssl rand -base64 16)
19 | export JAVA_OPTS="-Djenkins.install.runSetupWizard=false"
20 |
21 | #we're providing the server its public hostname for its relative links
22 | export JenkinsPublicHostname=$(curl -s http://169.254.169.254/latest/meta-data/public-hostname)
23 | export SeleniumPrivateIp=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
24 | #build the jenkins container
25 | docker-compose up -d --build
26 |
27 | #let the jenkins docker complete bootstrapping with our groovy script provided
28 | sleep 45
29 |
30 | #create new environment without inheriting anything from this shell for this wget to work..
31 | env -i /bin/bash -c 'wget http://127.0.0.1:8080/jnlpJars/jenkins-cli.jar'
32 |
33 | sleep 5
34 | #create the pipeline in jenkins
35 | java -jar ./jenkins-cli.jar -s http://localhost:8080 -auth myjenkins:$Jenkins_PW create-job pythonpipeline < config.xml
36 |
37 | echo "------- Your temporary Jenkins login ---------"
38 | echo "myjenkins"
39 | echo $Jenkins_PW
40 |
--------------------------------------------------------------------------------