Skip to content

Commit 3737e7e

Browse files
Merge pull request #169 from cp-andrew-lindesay/extra-snyk-cli-commands
feat: implement new commands `code-test` and `container-test` + new c…
2 parents d8bcb3a + 97bdf7a commit 3737e7e

File tree

22 files changed

+400
-27
lines changed

22 files changed

+400
-27
lines changed

CONTRIBUTING.md

+16
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,19 @@ Ensure that your code adheres to the included `.eslintrc` config by running `npm
4646
*Important:* when fixing a bug, please commit a **failing test** first so that Travis CI (or I can) can show the code failing. Once that commit is in place, then commit the bug fix, so that we can test *before* and *after*.
4747

4848
Remember that you're developing for multiple platforms and versions of node, so if the tests pass on your Mac or Linux or Windows machine, it *may* not pass elsewhere.
49+
50+
## Local Build
51+
52+
During the build of this plugin, a number of tests will run in the host platform's environment. To get these tests to run from a developer setting requires some environment variables to be set;
53+
54+
### `SNYK_DOWNLOAD_DESTINATION`
55+
56+
This value is a file path where the test is able to download the Snyk binary to for use in the test. An example might be `downloads/snyk`.
57+
58+
### `SNYK_TEST_TOKEN`
59+
60+
A Snyk token that can be used in the execution of the test. You can obtain a token for your Snyk user under the "Account Settings" page in the Snyk Web UI.
61+
62+
### `SNYK_CLI_EXECUTABLE`
63+
64+
The path where the Snyk tool would ordinarily be found on the system. An example would be `/usr/local/bin/snyk`.

README.md

+33
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ officially maintained by [Snyk](https://snyk.io).
5555

5656
## Goals
5757

58+
### `code-test` (experimental)
59+
60+
Default phase: `test`
61+
62+
Performs a static-analysis of your project's source code and provides a list of
63+
vulnerabilities if any are found.
64+
65+
### `container-test` (experimental)
66+
67+
Default phase: `install`
68+
69+
Performs analysis of the layers of a container image. The tag of the image to
70+
be scanned should be provided as an argument;
71+
72+
```xml
73+
<!-- Example of specifying the tag of the image to scan -->
74+
<configuration>
75+
<args>
76+
<arg>--print-deps</arg>
77+
<arg>nginx:1.9.5</arg>
78+
</args>
79+
</configuration>
80+
```
81+
5882
### `test`
5983

6084
Default Phase: `test`
@@ -94,6 +118,15 @@ Skip this execution entirely.
94118

95119
When running `mvn`, you can also use `-Dsnyk.skip` to enable this behavior.
96120

121+
### `failOnIssues` \[boolean\]
122+
123+
Default: `true`
124+
125+
When set to `true` then, should the Snyk CLI tool indicate that action is
126+
required to remedy a security issue, the Maven build will be considered
127+
failed. When set to `false` the build will continue even if action is
128+
required.
129+
97130
### `args` \[array\<string\>\]
98131

99132
This plugin uses [Snyk CLI](https://github.com/snyk/snyk) so you can pass any
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
2+
invoker.goals=test
3+
invoker.buildResult=failure

src/it/test-code-test/pom.xml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>io.snyk.it</groupId>
7+
<artifactId>test-code-test</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
10+
<build>
11+
<plugins>
12+
13+
<plugin>
14+
<groupId>@project.groupId@</groupId>
15+
<artifactId>@project.artifactId@</artifactId>
16+
<version>@project.version@</version>
17+
<executions>
18+
<execution>
19+
<phase>test</phase>
20+
<goals>
21+
<goal>code-test</goal>
22+
</goals>
23+
</execution>
24+
</executions>
25+
<configuration>
26+
<cli>
27+
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
28+
</cli>
29+
<args>
30+
<arg>--print-deps</arg>
31+
</args>
32+
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
33+
</configuration>
34+
</plugin>
35+
36+
<plugin>
37+
<groupId>org.apache.maven.plugins</groupId>
38+
<artifactId>maven-compiler-plugin</artifactId>
39+
<version>3.10.1</version>
40+
<configuration>
41+
<source>1.8</source>
42+
<target>1.8</target>
43+
</configuration>
44+
</plugin>
45+
46+
</plugins>
47+
</build>
48+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.example;
2+
3+
import java.sql.SQLException;
4+
5+
public class Application {
6+
7+
/**
8+
* <p>This code will allow the caller to provide an argument to the application which
9+
* finds its way into a SQL statement. For example <code>';DROP TABLE product;SELECT '</code>
10+
* could be passed in and it would give an opportunity to attack the system at the database
11+
* level.</p>
12+
*/
13+
14+
public static void main(String[] args) {
15+
VulnerableQueryHelper vulnerableQueryHelper = new VulnerableQueryHelper(
16+
null // not relevant for the purpose of analysis
17+
);
18+
19+
try {
20+
System.out.println("" + vulnerableQueryHelper.countProductOrders(args[1]));
21+
} catch (SQLException se) {
22+
throw new Error(se);
23+
}
24+
}
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.example;
2+
3+
import javax.sql.DataSource;
4+
import java.sql.Connection;
5+
import java.sql.PreparedStatement;
6+
import java.sql.ResultSet;
7+
import java.sql.SQLException;
8+
9+
public class VulnerableQueryHelper {
10+
11+
private final DataSource dataSource;
12+
13+
public VulnerableQueryHelper(DataSource dataSource) {
14+
this.dataSource = dataSource;
15+
}
16+
17+
public int countProductOrders(String productCode) throws SQLException {
18+
try (Connection connection = dataSource.getConnection()) {
19+
return countProductOrders(connection, productCode);
20+
}
21+
}
22+
23+
/**
24+
* <p>In this method, the argument provided is put directly into the SQL which would
25+
* allow an attacker to be able to execute arbitrary logic in the database.</p>
26+
*/
27+
28+
public int countProductOrders(Connection connection, String productCode) throws SQLException {
29+
String sql = "SELECT COUNT(id)\n"
30+
+ "FROM order o JOIN product p ON o.product_id = o.id\n"
31+
+ "WHERE p.code = '" + productCode + "'";
32+
33+
try (PreparedStatement statement = connection.prepareStatement(sql)) {
34+
try (ResultSet resultSet = statement.executeQuery()) {
35+
if (!resultSet.next()) {
36+
throw new IllegalStateException("expected a row to be returned from the sql query");
37+
}
38+
return resultSet.getInt(1);
39+
}
40+
}
41+
}
42+
43+
}

src/it/test-code-test/verify.groovy

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import org.codehaus.plexus.util.FileUtils;
2+
3+
String log = FileUtils.fileRead(new File(basedir, "build.log"))
4+
5+
if (!log.contains("[High] SQL Injection")) {
6+
throw new Exception("no sql injection issue found")
7+
}
8+
9+
return true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
2+
invoker.goals=install
3+
invoker.buildResult=failure

src/it/test-container-test/pom.xml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>io.snyk.it</groupId>
7+
<artifactId>test-code-test</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
10+
<build>
11+
<plugins>
12+
13+
<plugin>
14+
<groupId>@project.groupId@</groupId>
15+
<artifactId>@project.artifactId@</artifactId>
16+
<version>@project.version@</version>
17+
<executions>
18+
<execution>
19+
<phase>test</phase>
20+
<goals>
21+
<goal>container-test</goal>
22+
</goals>
23+
</execution>
24+
</executions>
25+
<configuration>
26+
<cli>
27+
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
28+
</cli>
29+
<args>
30+
<arg>--print-deps</arg>
31+
<arg>--platform=linux/amd64</arg>
32+
<arg>nginx:1.21.1</arg>
33+
</args>
34+
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
35+
</configuration>
36+
</plugin>
37+
38+
</plugins>
39+
</build>
40+
</project>
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import org.codehaus.plexus.util.FileUtils;
2+
3+
String log = FileUtils.fileRead(new File(basedir, "build.log"))
4+
5+
if (!log.contains("Medium severity vulnerability found in tiff/libtiff5")) {
6+
throw new Exception("Expected medium vulnerability not found")
7+
}
8+
9+
if (!log.contains("Critical severity vulnerability found in zlib/zlib1g")) {
10+
throw new Exception("Expected critical vulnerability not found")
11+
}
12+
13+
return true

src/it/test-multi-module-child/verify.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ if (!log.contains("child-module-2 ..................................... FAILURE"
1414
throw new Exception("child-module-2 should have failed.");
1515
}
1616

17-
if (!log.contains("introduced by io.snyk.it:[email protected] > axis:[email protected]")) {
18-
throw new Exception("Could not find vulnerability in child-module-2.");
17+
if (!log.contains("introduced by axis:[email protected]")) {
18+
throw new Exception("Could not find expected vulnerability in child-module-2.");
1919
}
2020

2121
return true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
2+
invoker.goals = install
3+
invoker.buildResult = success
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>io.snyk.it</groupId>
7+
<artifactId>test-not-fail-on-issues</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
10+
<dependencies>
11+
<!-- this contains a known vulnerability -->
12+
<dependency>
13+
<groupId>org.postgresql</groupId>
14+
<artifactId>postgresql</artifactId>
15+
<version>42.3.5</version>
16+
</dependency>
17+
</dependencies>
18+
19+
<build>
20+
<plugins>
21+
22+
<plugin>
23+
<groupId>@project.groupId@</groupId>
24+
<artifactId>@project.artifactId@</artifactId>
25+
<version>@project.version@</version>
26+
<executions>
27+
<execution>
28+
<phase>test</phase>
29+
<goals>
30+
<goal>test</goal>
31+
</goals>
32+
</execution>
33+
</executions>
34+
<configuration>
35+
<cli>
36+
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
37+
</cli>
38+
<args>
39+
<arg>--print-deps</arg>
40+
</args>
41+
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
42+
<failOnIssues>false</failOnIssues>
43+
</configuration>
44+
</plugin>
45+
46+
</plugins>
47+
</build>
48+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import org.codehaus.plexus.util.FileUtils;
2+
3+
String log = FileUtils.fileRead(new File(basedir, "build.log"))
4+
5+
if (!log.contains("introduced by org.postgresql:[email protected]")) {
6+
throw new Exception("Vulnerability in dependency not found")
7+
}
8+
9+
return true;

src/it/test-with-specific-cli-version/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55

66
<groupId>io.snyk.it</groupId>
7-
<artifactId>test-without-cli-executable</artifactId>
7+
<artifactId>test-with-specific-cli-version</artifactId>
88
<version>1.0-SNAPSHOT</version>
99

1010
<build>
+10-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import org.codehaus.plexus.util.FileUtils;
22

3-
String log = FileUtils.fileRead(new File(basedir, "build.log"));
3+
String log = FileUtils.fileRead(new File(basedir, "build.log"))
4+
String snykCliExecutable = System.getenv("SNYK_CLI_EXECUTABLE")
5+
6+
if (snykCliExecutable == null || snykCliExecutable.isEmpty()) {
7+
throw new Exception("the environment variable `SNYK_CLI_EXECUTABLE` is not defined")
8+
}
49

510
if (!log.contains("Snyk Executable Path: " + System.getenv("SNYK_CLI_EXECUTABLE"))) {
6-
throw new Exception("snyk executable path log line not found.");
11+
throw new Exception("snyk executable path log line not found.")
712
}
813

914
if (!(log =~ /Snyk CLI Version:\s+\d+\.\d+\.\d+/)) {
10-
throw new Exception("snyk version log line not found");
15+
throw new Exception("snyk version log line not found")
1116
}
1217

1318
if (!log.contains("for known issues, no vulnerable paths found.")) {
14-
throw new Exception("`snyk test` success output not found");
19+
throw new Exception("`snyk test` success output not found")
1520
}
1621

17-
return true;
22+
return true

src/main/java/io/snyk/snyk_maven_plugin/command/Command.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22

33
public enum Command {
44

5+
CODE_TEST("code", "test"),
6+
CONTAINER_TEST("container", "test"),
57
TEST("test"),
68
MONITOR("monitor"),
79
VERSION("version");
810

9-
private final String commandName;
11+
private final String[] commandParameters;
1012

11-
Command(String commandName) {
12-
this.commandName = commandName;
13+
Command(String... commandParameters) {
14+
this.commandParameters = commandParameters;
15+
}
16+
17+
public String[] commandParameters() {
18+
return commandParameters;
1319
}
1420

1521
public String commandName() {
16-
return commandName;
22+
return String.join(" ", commandParameters());
1723
}
1824

1925
}

0 commit comments

Comments
 (0)