1
1
package com.cloudogu.ces.cesbuildlib
2
2
3
-
3
+ import junit.framework.AssertionFailedError
4
4
import org.mockito.invocation.InvocationOnMock
5
5
import org.mockito.stubbing.Answer
6
6
@@ -20,17 +20,15 @@ class TrivyTest extends GroovyTestCase {
20
20
Path installDir = Paths . get(" target/trivyInstalls" )
21
21
Path workDir = Paths . get(" " )
22
22
TrivyExecutor trivyExec = new TrivyExecutor (installDir)
23
+ String trivyImage = " aquasec/trivy:" + Trivy . DEFAULT_TRIVY_VERSION
23
24
24
- void testScanImage_successfulTrivyExecution () {
25
- // with hopes that this image will never have CVEs
26
- String imageName = " hello-world"
27
- String severityLevel = TrivySeverityLevel . CRITICAL
25
+
26
+ ScriptMock doTestScan (String imageName , String severityLevel , String strategy , int expectedStatusCode ) {
28
27
File trivyReportFile = new File (" trivy/trivyReport.json" )
29
28
Path trivyDir = Paths . get(trivyReportFile. getParent())
30
29
String trivyArguments = " image --exit-code 10 --exit-on-eol 10 --format ${ TrivyScanFormat.JSON} -o ${ trivyReportFile} --severity ${ severityLevel} ${ additionalFlags} ${ imageName} "
31
30
String expectedTrivyCommand = " trivy $trivyArguments "
32
31
33
- String trivyImage = " aquasec/trivy:" + Trivy . DEFAULT_TRIVY_VERSION
34
32
def scriptMock = new ScriptMock ()
35
33
scriptMock. env. WORKSPACE = " /test"
36
34
Docker dockerMock = mock(Docker . class)
@@ -42,7 +40,6 @@ class TrivyTest extends GroovyTestCase {
42
40
@Override
43
41
Integer answer (InvocationOnMock invocation ) throws Throwable {
44
42
// mock "sh trivy" so that it returns the expected status code and check trivy arguments
45
- Integer expectedStatusCode = 0
46
43
Closure closure = invocation. getArgument(1 )
47
44
scriptMock. expectedShRetValueForScript. put(expectedTrivyCommand, expectedStatusCode)
48
45
Integer statusCode = closure. call() as Integer
@@ -63,7 +60,18 @@ class TrivyTest extends GroovyTestCase {
63
60
}
64
61
})
65
62
Trivy trivy = new Trivy (scriptMock, Trivy . DEFAULT_TRIVY_VERSION , dockerMock)
66
- trivy. scanImage(imageName, severityLevel, TrivyScanStrategy . UNSTABLE )
63
+
64
+ trivy. scanImage(imageName, severityLevel, strategy)
65
+
66
+ return scriptMock
67
+ }
68
+
69
+ void testScanImage_successfulTrivyExecution () {
70
+ // with hopes that this image will never have CVEs
71
+ String imageName = " hello-world"
72
+ String severityLevel = TrivySeverityLevel . CRITICAL
73
+
74
+ def scriptMock = doTestScan(imageName, severityLevel, TrivyScanStrategy . UNSTABLE , 0 )
67
75
68
76
assertEquals (false , scriptMock. getUnstable())
69
77
}
@@ -72,45 +80,8 @@ class TrivyTest extends GroovyTestCase {
72
80
// with hopes that this image will always have CVEs
73
81
String imageName = " alpine:3.18.7"
74
82
String severityLevel = TrivySeverityLevel . ALL
75
- File trivyReportFile = new File (" trivy/trivyReport.json" )
76
- Path trivyDir = Paths . get(trivyReportFile. getParent())
77
- String trivyArguments = " image --exit-code 10 --exit-on-eol 10 --format ${ TrivyScanFormat.JSON} -o ${ trivyReportFile} --severity ${ severityLevel} ${ additionalFlags} ${ imageName} "
78
- String expectedTrivyCommand = " trivy $trivyArguments "
79
83
80
- String trivyImage = " aquasec/trivy:" + Trivy . DEFAULT_TRIVY_VERSION
81
- def scriptMock = new ScriptMock ()
82
- scriptMock. env. WORKSPACE = " /test"
83
- Docker dockerMock = mock(Docker . class)
84
- Docker.Image imageMock = mock(Docker.Image . class)
85
- when(dockerMock. image(trivyImage)). thenReturn(imageMock)
86
- when(imageMock. mountJenkinsUser()). thenReturn(imageMock)
87
- when(imageMock. mountDockerSocket()). thenReturn(imageMock)
88
- when(imageMock. inside(matches(" -v /test/.trivy/.cache:/root/.cache/" ), any())). thenAnswer(new Answer<Integer > () {
89
- @Override
90
- Integer answer (InvocationOnMock invocation ) throws Throwable {
91
- // mock "sh trivy" so that it returns the expected status code and check trivy arguments
92
- Integer expectedStatusCode = 10
93
- Closure closure = invocation. getArgument(1 )
94
- scriptMock. expectedShRetValueForScript. put(expectedTrivyCommand, expectedStatusCode)
95
- Integer statusCode = closure. call() as Integer
96
- assertEquals (expectedStatusCode, statusCode)
97
- assertEquals (expectedTrivyCommand, scriptMock. getActualShMapArgs(). getLast())
98
-
99
- // emulate trivy call with local trivy installation and check that it has the same behavior
100
- Files . createDirectories(trivyDir)
101
- Process process = trivyExec. exec(Trivy . DEFAULT_TRIVY_VERSION , trivyArguments, workDir)
102
- if (process. waitFor(2 , TimeUnit . MINUTES )) {
103
- assertEquals (expectedStatusCode, process. exitValue())
104
- } else {
105
- process. destroyForcibly()
106
- fail (" terminate trivy due to timeout" )
107
- }
108
-
109
- return expectedStatusCode
110
- }
111
- })
112
- Trivy trivy = new Trivy (scriptMock, Trivy . DEFAULT_TRIVY_VERSION , dockerMock)
113
- trivy. scanImage(imageName, severityLevel, TrivyScanStrategy . UNSTABLE )
84
+ def scriptMock = doTestScan(imageName, severityLevel, TrivyScanStrategy . UNSTABLE , 10 )
114
85
115
86
assertEquals (true , scriptMock. getUnstable())
116
87
}
@@ -119,97 +90,35 @@ class TrivyTest extends GroovyTestCase {
119
90
// with hopes that this image will always have CVEs
120
91
String imageName = " alpine:3.18.7"
121
92
String severityLevel = TrivySeverityLevel . ALL
122
- File trivyReportFile = new File (" trivy/trivyReport.json" )
123
- Path trivyDir = Paths . get(trivyReportFile. getParent())
124
- String trivyArguments = " image --exit-code 10 --exit-on-eol 10 --format ${ TrivyScanFormat.JSON} -o ${ trivyReportFile} --severity ${ severityLevel} ${ additionalFlags} ${ imageName} "
125
- String expectedTrivyCommand = " trivy $trivyArguments "
126
-
127
- String trivyImage = " aquasec/trivy:" + Trivy . DEFAULT_TRIVY_VERSION
128
- def scriptMock = new ScriptMock ()
129
- scriptMock. env. WORKSPACE = " /test"
130
- Docker dockerMock = mock(Docker . class)
131
- Docker.Image imageMock = mock(Docker.Image . class)
132
- when(dockerMock. image(trivyImage)). thenReturn(imageMock)
133
- when(imageMock. mountJenkinsUser()). thenReturn(imageMock)
134
- when(imageMock. mountDockerSocket()). thenReturn(imageMock)
135
- when(imageMock. inside(matches(" -v /test/.trivy/.cache:/root/.cache/" ), any())). thenAnswer(new Answer<Integer > () {
136
- @Override
137
- Integer answer (InvocationOnMock invocation ) throws Throwable {
138
- // mock "sh trivy" so that it returns the expected status code and check trivy arguments
139
- Integer expectedStatusCode = 10
140
- Closure closure = invocation. getArgument(1 )
141
- scriptMock. expectedShRetValueForScript. put(expectedTrivyCommand, expectedStatusCode)
142
- Integer statusCode = closure. call() as Integer
143
- assertEquals (expectedStatusCode, statusCode)
144
- assertEquals (expectedTrivyCommand, scriptMock. getActualShMapArgs(). getLast())
145
93
146
- // emulate trivy call with local trivy installation and check that it has the same behavior
147
- Files . createDirectories(trivyDir)
148
- Process process = trivyExec. exec(Trivy . DEFAULT_TRIVY_VERSION , trivyArguments, workDir)
149
- if (process. waitFor(2 , TimeUnit . MINUTES )) {
150
- assertEquals (expectedStatusCode, process. exitValue())
151
- } else {
152
- process. destroyForcibly()
153
- fail (" terminate trivy due to timeout" )
154
- }
155
-
156
- return expectedStatusCode
157
- }
158
- })
159
- Trivy trivy = new Trivy (scriptMock, Trivy . DEFAULT_TRIVY_VERSION , dockerMock)
160
- def errorMsg = shouldFail {
161
- trivy. scanImage(imageName, severityLevel, TrivyScanStrategy . FAIL )
94
+ def gotException = false
95
+ try {
96
+ doTestScan(imageName, severityLevel, TrivyScanStrategy . FAIL , 10 )doTestScan(imageName, severityLevel, TrivyScanStrategy . FAIL , 10 )
97
+ } catch (AssertionFailedError e) {
98
+ // exception could also be a junit assertion exception. This means a previous assertion failed
99
+ throw e
100
+ } catch (Exception e) {
101
+ assertTrue (" exception is: ${ e.getMessage()} " , e. getMessage(). contains(" Trivy has found vulnerabilities in image" ))
102
+ gotException = true
162
103
}
163
- assertTrue (" exception is: $errorMsg " , errorMsg. contains(" Trivy has found vulnerabilities in image" ))
164
- assertEquals (false , scriptMock. getUnstable())
104
+ assertTrue (gotException)
165
105
}
166
106
167
107
void testScanImage_unsuccessfulTrivyExecution () {
168
108
// with hopes that this image will always have CVEs
169
109
String imageName = " inval!d:::///1.1...1.1."
170
110
String severityLevel = TrivySeverityLevel . ALL
171
- File trivyReportFile = new File (" trivy/trivyReport.json" )
172
- Path trivyDir = Paths . get(trivyReportFile. getParent())
173
- String trivyArguments = " image --exit-code 10 --exit-on-eol 10 --format ${ TrivyScanFormat.JSON} -o ${ trivyReportFile} --severity ${ severityLevel} ${ additionalFlags} ${ imageName} "
174
- String expectedTrivyCommand = " trivy $trivyArguments "
175
111
176
- String trivyImage = " aquasec/trivy:" + Trivy . DEFAULT_TRIVY_VERSION
177
- def scriptMock = new ScriptMock ()
178
- scriptMock. env. WORKSPACE = " /test"
179
- Docker dockerMock = mock(Docker . class)
180
- Docker.Image imageMock = mock(Docker.Image . class)
181
- when(dockerMock. image(trivyImage)). thenReturn(imageMock)
182
- when(imageMock. mountJenkinsUser()). thenReturn(imageMock)
183
- when(imageMock. mountDockerSocket()). thenReturn(imageMock)
184
- when(imageMock. inside(matches(" -v /test/.trivy/.cache:/root/.cache/" ), any())). thenAnswer(new Answer<Integer > () {
185
- @Override
186
- Integer answer (InvocationOnMock invocation ) throws Throwable {
187
- // mock "sh trivy" so that it returns the expected status code and check trivy arguments
188
- Integer expectedStatusCode = 1
189
- Closure closure = invocation. getArgument(1 )
190
- scriptMock. expectedShRetValueForScript. put(expectedTrivyCommand, expectedStatusCode)
191
- Integer statusCode = closure. call() as Integer
192
- assertEquals (expectedTrivyCommand, scriptMock. getActualShMapArgs(). getLast())
193
- assertEquals (expectedStatusCode, statusCode)
194
-
195
- // emulate trivy call with local trivy installation and check that it has the same behavior
196
- Files . createDirectories(trivyDir)
197
- Process process = trivyExec. exec(Trivy . DEFAULT_TRIVY_VERSION , trivyArguments, workDir)
198
- if (process. waitFor(2 , TimeUnit . MINUTES )) {
199
- assertEquals (expectedStatusCode, process. exitValue())
200
- } else {
201
- process. destroyForcibly()
202
- fail (" terminate trivy due to timeout" )
203
- }
204
-
205
- return expectedStatusCode
206
- }
207
- })
208
- Trivy trivy = new Trivy (scriptMock, Trivy . DEFAULT_TRIVY_VERSION , dockerMock)
209
- def errorMsg = shouldFail {
210
- trivy. scanImage(" inval!d:::///1.1...1.1." , severityLevel, TrivyScanStrategy . UNSTABLE )
112
+ def gotException = false
113
+ try {
114
+ doTestScan(imageName, severityLevel, TrivyScanStrategy . FAIL , 1 )
115
+ } catch (AssertionFailedError e) {
116
+ // exception could also be a junit assertion exception. This means a previous assertion failed
117
+ throw e
118
+ } catch (Exception e) {
119
+ assertTrue (" exception is: ${ e.getMessage()} " , e. getMessage(). contains(" Error during trivy scan; exit code: 1" ))
120
+ gotException = true
211
121
}
212
- assertTrue (" exception is: $e rrorMsg " , errorMsg . contains( " Error during trivy scan; exit code: 1 " ) )
122
+ assertTrue (gotException )
213
123
}
214
-
215
124
}
0 commit comments