-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathJenkinsfile
More file actions
254 lines (228 loc) · 12.3 KB
/
Jenkinsfile
File metadata and controls
254 lines (228 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#!/usr/bin/env groovy
//****************************************************************************************************
// An example pipeline for DevSecOps using OpenText Fortify Application Security products
// @author: Kevin A. Lee (klee2@opentext.com)
//
//
// Pre-requisites:
// - [Optional] Fortify on Demand Jenkins plugin has been installed and configured (if not using fcli)
// - [Optional] Debricked account
//
// Typical node setup:
// - Create a new Jenkins agent (or reuse one) for running Fortify Commands
// - Install Fortify CLI (fcli) tool on the agent machine and add to system/agent path (default is to download from internet)
//
// Credentials setup:
// Create the following credentials in Jenkins and enter values as follows:
// iwa-git-auth - Git login as Jenkins "Username with Password" credential
// iwa-fod-client-id - Fortify on Demand API Client Id as Jenkins Secret credential
// iwa-fod-client-secret - Fortify on Demand API Client Secret as Jenkins Secret credential
// iwa-debricked-token - Debricked API access token as Jenkins Secret credential
// Note: All of the credentials should be created (with empty values if necessary) even if you are not using the capabilities.
//
//****************************************************************************************************
pipeline {
agent any
//
// The following parameters can be selected when the pipeline is executed manually to execute
// different capabilities in the pipeline or configure the servers that are used.
// Note: the pipeline needs to be executed at least once for the parameters to be available
//
parameters {
booleanParam(name: 'FOD_SAST', defaultValue: params.FOD_SAST ?: false,
description: 'Use Fortify on Demand for Static Application Security Testing')
booleanParam(name: 'FOD_DAST', defaultValue: params.FOD_DAST ?: false,
description: 'Use Fortify on Demand for Dynamic Application Security Testing')
booleanParam(name: 'DEBRICKED_SCA', defaultValue: params.DEBRICKED_SCA ?: false,
description: 'Use Debricked for Open Source Software Composition Analysis')
}
environment {
// Application settings
APP_NAME = "iwa-java" // Short form component name
APP_VERSION = "1.0" // Short form component version
GIT_URL = scm.getUserRemoteConfigs()[0].getUrl() // Git Repo
GIT_REPO_NAME = GIT_URL.split('/').last().replace('.git', '') // Git Repo name
// Credential references
GIT_CREDS = credentials('iwa-git-auth')
FOD_CLIENT_ID = credentials('iwa-fod-client-id')
FOD_CLIENT_SECRET = credentials('iwa-fod-client-secret')
DEBRICKED_TOKEN = credentials('iwa-debricked-token')
// The following are defaulted and can be overriden by creating a "Build parameter" of the same name
// You can update this Jenkinsfile and set defaults here for internal pipelines
APP_URL = "${params.APP_URL ?: 'https://iwajava.azurewebsites.net'}" // URL of application to be tested by ScanCentral DAST
FOD_URL = "${params.FOD_URL ?: 'https://api.emea.fortify.com'}" // URL of Fortify on Demand
FORTIFY_APP_NAME_POSTFIX = "${params.FORTIFY_APP_NAME_POSTFIX ?: ''}" // Fortify on Demand application name postfix
FOD_RELEASE_ID = "${params.FOD_RELEASE_ID ?: '0'}" // Fortify on Demand release id
// The following are "set" for use in `fcli action run ci`
GITHUB_SHA = sh (script: "git rev-parse HEAD", returnStdout: true).trim()
GITHUB_REPOSITORY = "${env.GIT_REPO_NAME}${env.FORTIFY_APP_NAME_POSTFIX}"
GITHUB_REF_NAME = sh (script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
GITHUB_BRANCH = "${params.FOD_APPVER_NAME ?: env.GIT_REF_NAME}"
}
//tools {
//
//}
stages {
stage('Build') {
agent any
steps {
script {
// Run gradle to build application
sh """
./gradlew clean build
"""
}
}
post {
success {
// Record the test results (success)
junit "**/build/test-results/test/TEST-*.xml"
// Archive the built file
archiveArtifacts "build/libs/${env.APP_NAME}-${env.APP_VERSION}.jar"
// Stash the deployable files
stash includes: "build/libs/${env.APP_NAME}-${env.APP_VERSION}.jar", name: "${env.APP_NAME}_release"
}
failure {
script {
if (fileExists('build/test-results/test')) {
junit "**/build/test-results/test/TEST-*.xml"
}
}
}
}
}
stage('SAST') {
when {
beforeAgent true
anyOf {
expression { params.FOD_SAST == true }
}
}
agent any
steps {
script {
if (params.FOD_SAST) {
sh """
echo "GITHUB_SHA: ${env.GITHUB_SHA}"
echo "GITHUB_REPOSITORY: ${env.GITHUB_REPOSITORY}"
echo "GITHUB_BRANCH: ${env.GITHUB_BRANCH}"
echo "FOD_URL: ${env.FOD_URL}"
echo "FOD_CLIENT_ID: ${env.FOD_CLIENT_ID}"
echo "FOD_CLIENT_SECRET: ${env.FOD_CLIENT_SECRET}"
echo "FOD_RELEASE_ID: ${env.FOD_RELEASE_ID}"
"""
// uncomment below to use fcli
// comment out below to use Fortify on Demand Jenkins Plugin
sh """
curl -L https://github.com/fortify/fcli/releases/download/latest/fcli-linux.tgz | tar -xz fcli
export FOD_RELEASE="${env.GITHUB_REPOSITORY}:${env.GITHUB_BRANCH}"
./fcli action run ci
"""
// uncomment below to use Fortify on Demand Jenkins Plugin
// comment out below to use fcli
//fodStaticAssessment releaseId: "${env.FOD_RELEASE_ID}", isMicroservice: false, openSourceScan: 'false',
// inProgressBuildResultType: 'WarnBuild', inProgressScanActionType: 'Queue', remediationScanPreferenceType: 'NonRemediationScanOnly',
// scanCentral: 'Gradle', scanCentralBuildCommand: 'clean build', scanCentralBuildFile: 'build.gradle'
//fodPollResults releaseId: "${env.FOD_RELEASE_ID}", policyFailureBuildResultPreference: 1, pollingInterval: 5
} else {
echo "No Static Application Security Testing (SAST) to do."
}
}
}
}
stage('SCA') {
when {
beforeAgent true
anyOf {
expression { params.DEBRICKED_SCA == true }
}
}
agent any
steps {
script {
if (params.DEBRICKED_SCA) {
script {
// Inspiration taken from https://github.com/trustin/os-maven-plugin/blob/master/src/main/java/kr/motd/maven/os/Detector.java
// Note: exit from 'debricked scan' is ignored - remove '|| true' to fail the pipeline if it fails
def osName = System.getProperty("os.name").toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "")
if (osName.startsWith("linux")) { osName = "linux" }
else if (osName.startsWith("mac") || osName.startsWith("osx")) { osName = "macOS" }
else if (osName.startsWith("windows")) { osName = "windows" }
else { osName = "linux" } // Default to linux
def osArch = System.getProperty("os.arch").toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "")
if (osArch.matches("(x8664|amd64|ia32e|em64t|x64)")) { osArch = "x86_64" }
else if (osArch.matches("(x8632|x86|i[3-6]86|ia32|x32)")) { osArch = "i386" }
else if (osArch.matches("(aarch_64)")) { osArch = "arm64" }
else { osArch = "x86_64" } // Default to x86 64-bit
println("OS detected: " + osName + " and architecture " + osArch)
sh 'curl -LsS https://github.com/debricked/cli/releases/download/release-v2/cli_' + osName + '_' + osArch + '.tar.gz | tar -xz debricked'
sh './debricked scan || true'
}
} else {
echo "No Software Composition Analysis to do."
}
}
}
}
stage('Deploy') {
agent any
steps {
script {
sh """
echo "Simulating deploying the application to a server"
"""
}
}
}
stage('DAST') {
when {
beforeAgent true
anyOf {
expression { params.FOD_DAST == true }
}
}
steps {
script {
if (params.FOD_DAST) {
sh """
curl -L https://github.com/fortify/fcli/releases/download/latest/fcli-linux.tgz | tar -xz fcli
echo "Running DAST scan against: ${env.APP_URL}"
./fcli fod session login --client-id ${env.FOD_CLIENT_ID} --client-secret ${env.FOD_CLIENT_SECRET} --url ${env.FOD_URL} --fod-session jenkins
echo ./fcli fod dast-scan start --release "${env.GITHUB_REPOSITORY}:${env.GITHUB_BRANCH}" --fod-session jenkins --store curScan
echo ./fcli fod dast-scan wait-for ::curScan:: --fod-session jenkins
./fcli fod session logout --fod-session jenkins
"""
// uncomment below to use Fortify on Demand Jenkins Plugin
// comment out below to use fcli
//fodStaticAssessment releaseId: "${env.FOD_RELEASE_ID}", isMicroservice: false, openSourceScan: 'false',
// inProgressBuildResultType: 'WarnBuild', inProgressScanActionType: 'Queue', remediationScanPreferenceType: 'NonRemediationScanOnly',
// scanCentral: 'Gradle', scanCentralBuildCommand: 'clean build', scanCentralBuildFile: 'build.gradle'
//fodPollResults releaseId: "${env.FOD_RELEASE_ID}", policyFailureBuildResultPreference: 1, pollingInterval: 5
} else {
echo "No Dynamic Application Security Testing (DAST) to do."
}
}
}
}
// An example release gate/checkpoint
stage('Gate') {
agent any
steps {
script {
sh """
curl -L https://github.com/fortify/fcli/releases/download/latest/fcli-linux.tgz | tar -xz fcli
echo "Running gate check"
./fcli fod session login --client-id ${env.FOD_CLIENT_ID} --client-secret ${env.FOD_CLIENT_SECRET} --url ${env.FOD_URL} --fod-session jenkins
./fcli fod action run check-policy --release "${env.GITHUB_REPOSITORY}:${env.GITHUB_BRANCH}" --fod-session jenkins
./fcli fod session logout --fod-session jenkins
"""
//input id: 'Release',
// message: 'Ready to Release?',
// ok: 'Yes, let\'s go',
// submitter: 'admin',
// submitterParameter: 'approver'
}
}
}
}
}