Skip to content

feat: implement new commands code-test and container-test + new c… #169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ Ensure that your code adheres to the included `.eslintrc` config by running `npm
*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*.

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.

## Local Build

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;

### `SNYK_DOWNLOAD_DESTINATION`

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`.

### `SNYK_TEST_TOKEN`

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.

### `SNYK_CLI_EXECUTABLE`

The path where the Snyk tool would ordinarily be found on the system. An example would be `/usr/local/bin/snyk`.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ officially maintained by [Snyk](https://snyk.io).

## Goals

### `code-test` (experimental)

Default phase: `test`

Performs a static-analysis of your project's source code and provides a list of
vulnerabilities if any are found.

### `container-test` (experimental)

Default phase: `install`

Performs analysis of the layers of a container image. The tag of the image to
be scanned should be provided as an argument;

```xml
<!-- Example of specifying the tag of the image to scan -->
<configuration>
<args>
<arg>--print-deps</arg>
<arg>nginx:1.9.5</arg>
</args>
</configuration>
```

### `test`

Default Phase: `test`
Expand Down Expand Up @@ -94,6 +118,15 @@ Skip this execution entirely.

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

### `failOnIssues` \[boolean\]

Default: `true`

When set to `true` then, should the Snyk CLI tool indicate that action is
required to remedy a security issue, the Maven build will be considered
failed. When set to `false` the build will continue even if action is
required.

### `args` \[array\<string\>\]

This plugin uses [Snyk CLI](https://github.com/snyk/snyk) so you can pass any
Expand Down
3 changes: 3 additions & 0 deletions src/it/test-code-test/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
invoker.goals=test
invoker.buildResult=failure
48 changes: 48 additions & 0 deletions src/it/test-code-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.snyk.it</groupId>
<artifactId>test-code-test</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
<plugins>

<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>code-test</goal>
</goals>
</execution>
</executions>
<configuration>
<cli>
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
</cli>
<args>
<arg>--print-deps</arg>
</args>
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

</plugins>
</build>
</project>
26 changes: 26 additions & 0 deletions src/it/test-code-test/src/main/java/com/example/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example;

import java.sql.SQLException;

public class Application {

/**
* <p>This code will allow the caller to provide an argument to the application which
* finds its way into a SQL statement. For example <code>';DROP TABLE product;SELECT '</code>
* could be passed in and it would give an opportunity to attack the system at the database
* level.</p>
*/

public static void main(String[] args) {
VulnerableQueryHelper vulnerableQueryHelper = new VulnerableQueryHelper(
null // not relevant for the purpose of analysis
);

try {
System.out.println("" + vulnerableQueryHelper.countProductOrders(args[1]));
} catch (SQLException se) {
throw new Error(se);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.example;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class VulnerableQueryHelper {

private final DataSource dataSource;

public VulnerableQueryHelper(DataSource dataSource) {
this.dataSource = dataSource;
}

public int countProductOrders(String productCode) throws SQLException {
try (Connection connection = dataSource.getConnection()) {
return countProductOrders(connection, productCode);
}
}

/**
* <p>In this method, the argument provided is put directly into the SQL which would
* allow an attacker to be able to execute arbitrary logic in the database.</p>
*/

public int countProductOrders(Connection connection, String productCode) throws SQLException {
String sql = "SELECT COUNT(id)\n"
+ "FROM order o JOIN product p ON o.product_id = o.id\n"
+ "WHERE p.code = '" + productCode + "'";

try (PreparedStatement statement = connection.prepareStatement(sql)) {
try (ResultSet resultSet = statement.executeQuery()) {
if (!resultSet.next()) {
throw new IllegalStateException("expected a row to be returned from the sql query");
}
return resultSet.getInt(1);
}
}
}

}
9 changes: 9 additions & 0 deletions src/it/test-code-test/verify.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import org.codehaus.plexus.util.FileUtils;

String log = FileUtils.fileRead(new File(basedir, "build.log"))

if (!log.contains("[High] SQL Injection")) {
throw new Exception("no sql injection issue found")
}

return true;
3 changes: 3 additions & 0 deletions src/it/test-container-test/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
invoker.goals=install
invoker.buildResult=failure
40 changes: 40 additions & 0 deletions src/it/test-container-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.snyk.it</groupId>
<artifactId>test-code-test</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
<plugins>

<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>container-test</goal>
</goals>
</execution>
</executions>
<configuration>
<cli>
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
</cli>
<args>
<arg>--print-deps</arg>
<arg>--platform=linux/amd64</arg>
<arg>nginx:1.21.1</arg>
</args>
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
</configuration>
</plugin>

</plugins>
</build>
</project>
13 changes: 13 additions & 0 deletions src/it/test-container-test/verify.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import org.codehaus.plexus.util.FileUtils;

String log = FileUtils.fileRead(new File(basedir, "build.log"))

if (!log.contains("Medium severity vulnerability found in tiff/libtiff5")) {
throw new Exception("Expected medium vulnerability not found")
}

if (!log.contains("Critical severity vulnerability found in zlib/zlib1g")) {
throw new Exception("Expected critical vulnerability not found")
}

return true
4 changes: 2 additions & 2 deletions src/it/test-multi-module-child/verify.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ if (!log.contains("child-module-2 ..................................... FAILURE"
throw new Exception("child-module-2 should have failed.");
}

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

return true;
3 changes: 3 additions & 0 deletions src/it/test-not-fail-on-issues/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html#invokerPropertiesFile
invoker.goals = install
invoker.buildResult = success
48 changes: 48 additions & 0 deletions src/it/test-not-fail-on-issues/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.snyk.it</groupId>
<artifactId>test-not-fail-on-issues</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<!-- this contains a known vulnerability -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.5</version>
</dependency>
</dependencies>

<build>
<plugins>

<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<cli>
<executable>${env.SNYK_CLI_EXECUTABLE}</executable>
</cli>
<args>
<arg>--print-deps</arg>
</args>
<apiToken>${env.SNYK_TEST_TOKEN}</apiToken>
<failOnIssues>false</failOnIssues>
</configuration>
</plugin>

</plugins>
</build>
</project>
9 changes: 9 additions & 0 deletions src/it/test-not-fail-on-issues/verify.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import org.codehaus.plexus.util.FileUtils;

String log = FileUtils.fileRead(new File(basedir, "build.log"))

if (!log.contains("introduced by org.postgresql:[email protected]")) {
throw new Exception("Vulnerability in dependency not found")
}

return true;
2 changes: 1 addition & 1 deletion src/it/test-with-specific-cli-version/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>

<groupId>io.snyk.it</groupId>
<artifactId>test-without-cli-executable</artifactId>
<artifactId>test-with-specific-cli-version</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
Expand Down
15 changes: 10 additions & 5 deletions src/it/test-without-dependency/verify.groovy
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import org.codehaus.plexus.util.FileUtils;

String log = FileUtils.fileRead(new File(basedir, "build.log"));
String log = FileUtils.fileRead(new File(basedir, "build.log"))
String snykCliExecutable = System.getenv("SNYK_CLI_EXECUTABLE")

if (snykCliExecutable == null || snykCliExecutable.isEmpty()) {
throw new Exception("the environment variable `SNYK_CLI_EXECUTABLE` is not defined")
}

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

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

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

return true;
return true
14 changes: 10 additions & 4 deletions src/main/java/io/snyk/snyk_maven_plugin/command/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@

public enum Command {

CODE_TEST("code", "test"),
CONTAINER_TEST("container", "test"),
TEST("test"),
MONITOR("monitor"),
VERSION("version");

private final String commandName;
private final String[] commandParameters;

Command(String commandName) {
this.commandName = commandName;
Command(String... commandParameters) {
this.commandParameters = commandParameters;
}

public String[] commandParameters() {
return commandParameters;
}

public String commandName() {
return commandName;
return String.join(" ", commandParameters());
}

}
Loading