├── gradle.properties ├── .travis.yml ├── settings.gradle ├── .gitignore ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src ├── main │ ├── resources │ │ └── META-INF │ │ │ └── gradle-plugins │ │ │ └── com.contrastsecurity.contrastplugin.properties │ └── groovy │ │ └── com │ │ └── contrastsecurity │ │ ├── ContrastPluginExtension.groovy │ │ ├── ConnectToContrast.groovy │ │ ├── DownloadContrastAgent.groovy │ │ ├── InstallContrastAgent.groovy │ │ ├── ContrastGradlePlugin.groovy │ │ └── VerifyContrast.groovy └── test │ └── groovy │ └── com │ └── contrastsecurity │ ├── ContrastPluginTest.groovy │ └── ContrastTaskTests.groovy ├── gradlew.bat ├── gradlew └── README.md /gradle.properties: -------------------------------------------------------------------------------- 1 | 2 | version=2.1.0-SNAPSHOT -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk8 3 | language: groovy 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ContrastGradlePlugin' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /.idea/ 3 | /bin/ 4 | /build/ 5 | *.iml 6 | .DS_Store 7 | .classpath 8 | .project 9 | .settings 10 | out/ 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-gradle-plugin/main/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/META-INF/gradle-plugins/com.contrastsecurity.contrastplugin.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.contrastsecurity.ContrastGradlePlugin -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 08 09:29:07 EST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip 7 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/ContrastPluginExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity; 2 | 3 | 4 | class ContrastPluginExtension { 5 | String username 6 | String apiKey 7 | String serviceKey 8 | String apiUrl 9 | String orgUuid 10 | String appName 11 | String serverName 12 | String minSeverity = 'Medium' //default 13 | String jarPath 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/ConnectToContrast.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import com.contrastsecurity.sdk.ContrastSDK 4 | import org.gradle.api.DefaultTask 5 | import org.gradle.api.GradleException 6 | import org.gradle.api.tasks.TaskAction 7 | 8 | 9 | class ConnectToContrast extends DefaultTask { 10 | 11 | @TaskAction 12 | def exec() { 13 | logger.debug('Connecting to Contrast TeamServer') 14 | 15 | ContrastPluginExtension extension = project.contrastConfiguration 16 | 17 | try { 18 | ContrastGradlePlugin.contrastSDK = extension.apiUrl?.trim() 19 | ? new ContrastSDK(extension.username, extension.serviceKey, extension.apiKey, extension.apiUrl) 20 | : new ContrastSDK(extension.username, extension.serviceKey, extension.apiKey) 21 | } catch (IllegalArgumentException e) { 22 | throw new GradleException('Unable to connect to TeamServer. Please check your Gradle settings.') 23 | } 24 | 25 | logger.debug('Successfully connected to Contrast TeamServer') 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/DownloadContrastAgent.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import com.contrastsecurity.models.AgentType 4 | import com.contrastsecurity.sdk.ContrastSDK 5 | import org.apache.commons.io.FileUtils 6 | import org.gradle.api.DefaultTask 7 | import org.gradle.api.tasks.StopExecutionException 8 | import org.gradle.api.tasks.TaskAction 9 | 10 | 11 | class DownloadContrastAgent extends DefaultTask { 12 | 13 | final File agentFile = new File(project.buildDir, 'contrast.jar') 14 | 15 | DownloadContrastAgent() { 16 | // TODO Add a check to make sure the JAR is up to date??? 17 | outputs.upToDateWhen{ 18 | agentFile.exists() 19 | } 20 | } 21 | 22 | @TaskAction 23 | def exec () { 24 | logger.debug('Downloading latest Contrast agent') 25 | 26 | ContrastSDK contrast = ContrastGradlePlugin.contrastSDK 27 | ContrastPluginExtension extension = project.contrastConfiguration 28 | 29 | try { 30 | byte[] javaAgent = contrast.getAgent(AgentType.JAVA, extension.orgUuid) 31 | FileUtils.writeByteArrayToFile(agentFile, javaAgent) 32 | logger.debug("Saved Contrast agent to ${agentFile.absolutePath}") 33 | } catch (IOException e) { 34 | logger.warn("Unable to save Contrast agent to ${agentFile.absolutePath} (${e.class.name}: ${e.message})") 35 | throw new StopExecutionException('Unable to download the latest java agent') 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/InstallContrastAgent.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import org.apache.commons.configuration.PropertiesConfiguration 4 | import org.apache.commons.configuration.PropertiesConfigurationLayout 5 | import org.gradle.api.DefaultTask 6 | import org.gradle.api.GradleException 7 | import org.gradle.api.tasks.StopExecutionException 8 | import org.gradle.api.tasks.TaskAction 9 | 10 | import java.text.SimpleDateFormat 11 | 12 | class InstallContrastAgent extends DefaultTask { 13 | 14 | boolean ignoreFailures 15 | 16 | @TaskAction 17 | def exec() { 18 | ContrastGradlePlugin.appVersionQualifier = ContrastGradlePlugin.computeAppVersionQualifier(System.getenv("TRAVIS_BUILD_NUMBER"), System.getenv("CIRCLE_BUILD_NUM")) 19 | 20 | addContrastArgLine() 21 | 22 | ContrastPluginExtension extension = project.contrastConfiguration 23 | 24 | File agentFile = new File(extension.jarPath) 25 | if (agentFile.exists()) { 26 | logger.debug("Loaded Java agent from ${extension.jarPath}") 27 | } else if (ignoreFailures) { 28 | throw new StopExecutionException("Unable to load Java agent from ${extension.jarPath}") 29 | } else { 30 | throw new GradleException("Unable to load Java agent from ${extension.jarPath}") 31 | } 32 | } 33 | 34 | private void addContrastArgLine() { 35 | String gradleProperties = "gradle.properties" 36 | String jvmArgs = "org.gradle.jvmargs" 37 | 38 | File file = new File(gradleProperties) 39 | file.createNewFile() 40 | 41 | PropertiesConfiguration config = new PropertiesConfiguration() 42 | PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(config) 43 | layout.load(new InputStreamReader(new FileInputStream(file))) 44 | 45 | String property = config.getProperty(jvmArgs) 46 | if (property == null) { 47 | config.setProperty(jvmArgs, ContrastGradlePlugin.buildArgLine(project)) 48 | layout.save(new FileWriter(gradleProperties, false)) 49 | } else { 50 | if (!argLineContainsContrastArgLine(property)) { 51 | config.setProperty(jvmArgs, property + " " + ContrastGradlePlugin.buildArgLine(project)) 52 | layout.save(new FileWriter(gradleProperties, false)) 53 | } 54 | } 55 | } 56 | 57 | private static boolean argLineContainsContrastArgLine(String argLine) { 58 | if (!argLine.contains("-javaagent") && !argLine.contains("-Dcontrast.override.appname") 59 | && !argLine.contains("-Dcontrast.server") && !argLine.contains("-Dcontrast.env") 60 | && !argLine.contains("-Dcontrast.override.appversion")) { 61 | return false 62 | } 63 | return true 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/ContrastGradlePlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import com.contrastsecurity.sdk.ContrastSDK 4 | import org.gradle.api.Plugin 5 | import org.gradle.api.Project 6 | import org.gradle.api.Task 7 | import org.gradle.language.base.plugins.LifecycleBasePlugin 8 | 9 | import java.text.SimpleDateFormat 10 | 11 | 12 | class ContrastGradlePlugin implements Plugin { 13 | 14 | static ContrastSDK contrastSDK 15 | static String appVersionQualifier 16 | 17 | private static final String EXTENSION_NAME = 'contrastConfiguration' 18 | 19 | @Override 20 | public void apply(Project target) { 21 | //allows for client to define their settings in their projects build.gradle 22 | ContrastPluginExtension extension = target.extensions.create(EXTENSION_NAME, ContrastPluginExtension) 23 | extension.appName = target.rootProject.name 24 | extension.serverName = InetAddress.localHost.hostName 25 | 26 | Task contrastLogin = target.tasks.create(name: 'contrastLogin', type: ConnectToContrast) 27 | 28 | Task contrastInstall = target.tasks.create(name: 'contrastInstall', type: InstallContrastAgent) { 29 | description = 'Installs a Contrast agent in your working copy.' 30 | } 31 | 32 | Task contrastVerify = target.tasks.create(name: 'contrastVerify', type: VerifyContrast) { 33 | dependsOn = [contrastLogin] 34 | description = 'Checks for new application vulnerabilities.' 35 | group = LifecycleBasePlugin.VERIFICATION_GROUP 36 | } 37 | 38 | target.afterEvaluate { 39 | if (!extension.jarPath?.trim()) { 40 | Task contrastDownload = target.tasks.create(name: 'contrastDownload', type: DownloadContrastAgent) { 41 | dependsOn = [contrastLogin] 42 | description = 'Downloads the latest version of the Contrast agent.' 43 | } 44 | extension.jarPath = contrastDownload.agentFile.absolutePath 45 | contrastInstall.dependsOn = [contrastDownload] 46 | } 47 | } 48 | } 49 | 50 | protected static String getAppVersion(String appName, String appVersionQualifier) { 51 | return appName + "-" + appVersionQualifier 52 | } 53 | 54 | protected static String buildArgLine(Project project) { 55 | 56 | ContrastPluginExtension extension = project.contrastConfiguration 57 | String appVersion = getAppVersion(extension.appName, appVersionQualifier) 58 | 59 | String newArgLine = "-javaagent:${extension.jarPath} -Dcontrast.override.appname=${extension.appName} -Dcontrast.server=${extension.serverName} -Dcontrast.env=qa -Dcontrast.override.appversion=${appVersion}" 60 | 61 | return newArgLine 62 | } 63 | 64 | static String computeAppVersionQualifier(String travisBuildNumber, String circleBuildNum) { 65 | 66 | if (appVersionQualifier != null) { 67 | return appVersionQualifier 68 | } 69 | 70 | String appVersionQualifier = "" 71 | if(travisBuildNumber != null) { 72 | appVersionQualifier = travisBuildNumber 73 | } else if (circleBuildNum != null) { 74 | appVersionQualifier = circleBuildNum 75 | } else { 76 | appVersionQualifier = new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) 77 | } 78 | return appVersionQualifier 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARCHIVED as of March 2025 2 | See: https://github.com/Contrast-Security-OSS/contrast-sdk-java/tree/main/gradle-plugin 3 | 4 | # Contrast Gradle Plugin 5 | 6 | Repository for the Contrast Gradle plugin. This plugin will allow for a Contrast Java agent to be downloaded and then ensure that there are no new vulnerabilities found. 7 | 8 | ## Version 2 9 | New in 2.X version of the plugin: 10 | * Vulnerabilities are now filtered using an app version instead of a timestamp. 11 | * App version can be generated using $TRAVIS_BUILD_NUMBER or $CIRCLE_BUILD_NUM. 12 | 13 | ## Documentation 14 | Always refer to Contrast's Open Docs site for the most up to date documentation: https://docs.contrastsecurity.com/tools-build.html#gradle 15 | 16 | ## Goals 17 | 18 | * `contrastInstall`: installs a Contrast Java agent to your local project. 19 | The plugin will edit org.gradle.jvmargs property in gradle.properties file to launch the JVM with the Contrast agent. 20 | An application version, by which the vulnerabilities are filtered, is generated during this task. 21 | We generate the app version as follows and in this order: 22 | * If your build is running in TravisCI, we'll use appName-$TRAVIS_BUILD_NUMBER 23 | * If your build is running in CircleCI, we'll use appName-$CIRCLE_BUILD_NUM 24 | * If your build is running neither in TravisCI nor in CircleCI, we'll generate one in the following format: appName-yyyyMMddHHmm 25 | 26 | * `contrastVerify`: checks for new vulnerabilities in your web application 27 | 28 | ## Configuration Options 29 | 30 | | Parameter | Required | Default | Description | 31 | |-------------|----------|---------|---------------------------------------------------------| 32 | | username | True | | Username in TeamServer | 33 | | serviceKey | True | | Service Key found in Your Account => Profile page => Your keys => Personal Keys | 34 | | apiKey | True | | Api Key found in Your Account => Profile page => Your keys => Organization Keys | 35 | | orgUuid | True | | Organization Uuid found in Your Account => Profile page => Your keys => Organization Keys | 36 | | appName | False | | Application name | 37 | | apiUrl | True | | API Url to your TeamServer instance found in Your Account => Profile page => Your keys => Organization Keys | 38 | | serverName | False | | Name of server you set with -Dcontrast.server | 39 | | minSeverity | False | Medium | Minimum severity level to verify | 40 | | jarPath | False | | Path to contrast.jar if you already have one downloaded | 41 | 42 | # How To Guide 43 | * Install Gradle via Homebrew ```brew install gradle ``` 44 | 45 | 46 | * The easiest way to setup a project is to clone out sample application. This application has been migrated from Maven to Gradle, and relies on MongoDB, so we will install that and setup it's database path. 47 | ``` 48 | git clone https://github.com/Contrast-Security-OSS/Contrast-Sample-Gradle-Application.git 49 | brew install mongodb 50 | sudo mkdir -p /data/db 51 | brew services start mongodb 52 | ``` 53 | 54 | * Open up the Contrast-Sample-Gradle-Application/build.gradle file. Scroll to the very bottom and you should find the following contrastConfiguration. All of these values can be found in TeamServer already **except** for appName and serverName. 55 | ``` 56 | contrastConfiguration { 57 | username = "username" 58 | apiKey = "apiKey" 59 | serviceKey = "serviceKey" 60 | apiUrl = "apiUrl" 61 | orgUuid = "orgUuid" 62 | appName = "editLATER" 63 | serverName = "editLATER" 64 | minSeverity = "Medium" 65 | } 66 | ``` 67 | * Once username, apiKey, serviceKey, apiUrl, and orgUuid have been configured we can install the contrast jar file by calling the `contrastInstall` task. This will install **contrast.jar** within the projects build directory. 68 | It will also append to the `org.gradle.jvmargs` property in `gradle.properties` file of the project to include the 69 | jvm arguments required to run the application with the contrast java agent. 70 | ``` 71 | cd path/to/Contrast-Sample-Gradle-Application 72 | gradle build contrastInstall 73 | ``` 74 | 75 | * The next step is to run the application with the java agent. 76 | ``` 77 | cd path/to/Contrast-Sample-Gradle-Application/build 78 | java -jar libs/Contrast-Sample-Gradle-Application-0.0.1-SNAPSHOT.jar 79 | ``` 80 | Now, verify that your application is running here: That the test application is running at http://localhost:8080 81 | 82 | Next, verify that the applicaiton shows up on Teamserver. 83 | 84 | * In the VehicleMPG projects build.gradle we will now edit the contrastConfiguration to specify the appName and serverName from Teamserver 85 | ``` 86 | contrastConfiguration { 87 | username = "alreadySetup" 88 | apiKey = "alreadySetup" 89 | serviceKey = "alreadySetup" 90 | apiUrl = "alreadySetup" 91 | orgUuid = "alreadySetup" 92 | appName = "mytestapp" 93 | serverName = "mytestserver" 94 | minSeverity = "Medium" 95 | } 96 | ``` 97 | * Run the verification task at any time to check for vulnerabilties. 98 | ``` 99 | gradle build contrastVerify -x test 100 | ``` 101 | 102 | ## Configuration Reference 103 | ``` 104 | buildscript { 105 | repositories { 106 | maven { 107 | url "https://plugins.gradle.org/m2/" 108 | } 109 | } 110 | dependencies { 111 | classpath "gradle.plugin.com.contrastsecurity:ContrastGradlePlugin:1.0-SNAPSHOT" 112 | } 113 | } 114 | 115 | apply plugin: 'com.contrastsecurity.contrastplugin' 116 | contrastConfiguration { 117 | username = "demo" 118 | apiKey = "demo" 119 | serviceKey = "demo" 120 | apiUrl = "http://localhost:19080/Contrast/api" 121 | orgUuid = "ASDF-LKJH-POIU-MNBV-LKJH" 122 | appName = "appNameFromTeamServer" 123 | serverName = "serverNameFromTeamServer" 124 | minSeverity = "Medium" 125 | } 126 | ``` 127 | 128 | ## Local Development and Testing 129 | 130 | To build and test the Gradle plugin locally: 131 | 132 | * `gradle build` 133 | 134 | To build an 'uber jar' 135 | 136 | * `gradle shadowJar` 137 | 138 | To build and 'uber jar' and install into Maven local: 139 | 140 | * `gradle publishToMavenLocal` 141 | -------------------------------------------------------------------------------- /src/test/groovy/com/contrastsecurity/ContrastPluginTest.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import org.gradle.api.Project 4 | import org.gradle.testfixtures.ProjectBuilder 5 | import org.junit.Test 6 | 7 | import java.text.SimpleDateFormat 8 | 9 | import static org.junit.Assert.assertEquals 10 | import static org.junit.Assert.assertTrue 11 | 12 | 13 | class ContrastPluginTest { 14 | 15 | //Ensures that the plugin is applicable 16 | @Test 17 | public void contrastPluginAddPlugin(){ 18 | Project project = ProjectBuilder.builder().build() 19 | project.pluginManager.apply "com.contrastsecurity.contrastplugin" 20 | assertTrue(project.getPlugins().hasPlugin("com.contrastsecurity.contrastplugin")) 21 | } 22 | 23 | //Ensures that the plugin allows the contrastInstall task to be called 24 | @Test 25 | public void contrastPluginAddsInstallTask() { 26 | Project project = ProjectBuilder.builder().build() 27 | project.pluginManager.apply "com.contrastsecurity.contrastplugin" 28 | project.afterEvaluate { 29 | assertTrue(project.tasks.getByName("contrastInstall") instanceof InstallContrastAgent) 30 | } 31 | } 32 | 33 | //Ensures that the plugin allows the contrastVerify task to be called 34 | @Test 35 | public void contrastPluginAddsVerifyTask(){ 36 | Project project = ProjectBuilder.builder().build() 37 | project.pluginManager.apply "com.contrastsecurity.contrastplugin" 38 | project.afterEvaluate { 39 | assertTrue(project.tasks.getByName("contrastVerify") instanceof VerifyContrast) 40 | } 41 | } 42 | 43 | //Ensures that the plugin creates the contrastConfiguration extension to allow clients to configure their settings 44 | @Test 45 | public void contrastPluginEnablesContrastConfigurationExtension(){ 46 | Project project = ProjectBuilder.builder().build() 47 | project.pluginManager.apply "com.contrastsecurity.contrastplugin" 48 | assertTrue(project.getExtensions().getByName("contrastConfiguration") instanceof ContrastPluginExtension) 49 | 50 | } 51 | 52 | 53 | @Test 54 | public void testBuildArgLine() { 55 | 56 | Project project = ProjectBuilder.builder().build() 57 | project.pluginManager.apply "com.contrastsecurity.contrastplugin" 58 | project.contrastConfiguration.setJarPath("/demo/jar/path") 59 | project.contrastConfiguration.setAppName("WebGoat") 60 | project.contrastConfiguration.setServerName("linux") 61 | 62 | ContrastGradlePlugin.appVersionQualifier = "1.0.0" 63 | 64 | String argLine = ContrastGradlePlugin.buildArgLine(project) 65 | String actualArgLine = "-javaagent:/demo/jar/path -Dcontrast.override.appname=WebGoat -Dcontrast.server=linux -Dcontrast.env=qa -Dcontrast.override.appversion=WebGoat-1.0.0" 66 | 67 | assertEquals(argLine, actualArgLine) 68 | } 69 | 70 | @Test 71 | public void testComputeAppVersionQualifierTravisBuildNum() { 72 | 73 | ContrastGradlePlugin.appVersionQualifier = null 74 | 75 | String travisBuildNumber = "5" 76 | String circleBuildNum = null 77 | 78 | String actualAppVersionQualifier = "" 79 | if(travisBuildNumber != null) { 80 | actualAppVersionQualifier = travisBuildNumber 81 | } else if (circleBuildNum != null) { 82 | actualAppVersionQualifier = circleBuildNum 83 | } else { 84 | actualAppVersionQualifier = new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) 85 | } 86 | 87 | String appVersionQualifier = ContrastGradlePlugin.computeAppVersionQualifier(travisBuildNumber, circleBuildNum) 88 | 89 | assertEquals(appVersionQualifier, actualAppVersionQualifier) 90 | } 91 | 92 | @Test 93 | public void testComputeAppVersionQualifierCircleBuildNum() { 94 | 95 | ContrastGradlePlugin.appVersionQualifier = null 96 | 97 | String travisBuildNumber = null 98 | String circleBuildNum = "5" 99 | 100 | String actualAppVersionQualifier = "" 101 | if(travisBuildNumber != null) { 102 | actualAppVersionQualifier = travisBuildNumber 103 | } else if (circleBuildNum != null) { 104 | actualAppVersionQualifier = circleBuildNum 105 | } else { 106 | actualAppVersionQualifier = new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) 107 | } 108 | 109 | String appVersionQualifier = ContrastGradlePlugin.computeAppVersionQualifier(travisBuildNumber, circleBuildNum) 110 | 111 | assertEquals(appVersionQualifier, actualAppVersionQualifier) 112 | } 113 | 114 | @Test 115 | public void testComputeAppVersionQualifierTravisAndCircleBuildNum() { 116 | 117 | ContrastGradlePlugin.appVersionQualifier = null 118 | 119 | String travisBuildNumber = "5" 120 | String circleBuildNum = "5" 121 | 122 | String actualAppVersionQualifier = "" 123 | if(travisBuildNumber != null) { 124 | actualAppVersionQualifier = travisBuildNumber 125 | } else if (circleBuildNum != null) { 126 | actualAppVersionQualifier = circleBuildNum 127 | } else { 128 | actualAppVersionQualifier = new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) 129 | } 130 | 131 | String appVersionQualifier = ContrastGradlePlugin.computeAppVersionQualifier(travisBuildNumber, circleBuildNum) 132 | 133 | assertEquals(appVersionQualifier, actualAppVersionQualifier) 134 | } 135 | 136 | @Test 137 | public void testComputeAppVersionQualifier() { 138 | 139 | ContrastGradlePlugin.appVersionQualifier = null 140 | 141 | String travisBuildNumber = null 142 | String circleBuildNum = null 143 | 144 | String actualAppVersionQualifier = "" 145 | if(travisBuildNumber != null) { 146 | actualAppVersionQualifier = travisBuildNumber 147 | } else if (circleBuildNum != null) { 148 | actualAppVersionQualifier = circleBuildNum 149 | } else { 150 | actualAppVersionQualifier = new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) 151 | } 152 | 153 | String appVersionQualifier = ContrastGradlePlugin.computeAppVersionQualifier(travisBuildNumber, circleBuildNum) 154 | 155 | assertEquals(appVersionQualifier, actualAppVersionQualifier) 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/groovy/com/contrastsecurity/VerifyContrast.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import com.contrastsecurity.exceptions.UnauthorizedException 4 | import com.contrastsecurity.http.RuleSeverity 5 | import com.contrastsecurity.http.ServerFilterForm 6 | import com.contrastsecurity.http.TraceFilterForm 7 | import com.contrastsecurity.models.* 8 | import com.contrastsecurity.sdk.ContrastSDK 9 | import org.gradle.api.DefaultTask 10 | import org.gradle.api.GradleException 11 | import org.gradle.api.tasks.TaskAction 12 | 13 | class VerifyContrast extends DefaultTask { 14 | 15 | @TaskAction 16 | def exec() { 17 | logger.debug('Checking for new vulnerabilities') 18 | 19 | ContrastSDK contrast = ContrastGradlePlugin.contrastSDK 20 | ContrastPluginExtension extension = project.contrastConfiguration 21 | 22 | String applicationId = getApplicationId(contrast, extension.orgUuid, extension.appName) 23 | 24 | long serverId = getServerId(contrast, extension.orgUuid, applicationId, extension.serverName) 25 | 26 | TraceFilterForm form = new TraceFilterForm() 27 | form.setSeverities(getSeverityList(extension.minSeverity)) 28 | form.setAppVersionTags(Collections.singletonList(ContrastGradlePlugin.getAppVersion(extension.appName, ContrastGradlePlugin.appVersionQualifier))) 29 | form.setServerIds(Arrays.asList(serverId)) 30 | 31 | logger.debug('Requesting vulnerability report from TeamServer') 32 | 33 | Traces traces 34 | 35 | try { 36 | traces = contrast.getTraces(extension.orgUuid, applicationId, form) 37 | } catch (IOException e) { 38 | throw new GradleException('Unable to retrieve the traces.', e) 39 | } catch (UnauthorizedException e) { 40 | throw new GradleException('Unable to connect to TeamServer.', e) 41 | } 42 | 43 | if (traces != null && traces.count > 0) { 44 | logger.lifecycle("${traces.count} new vulnerabilit${traces.count > 1 ? 'ies' : 'y'} were found!") 45 | logger.debug('Printing vulnerability report') 46 | for (Trace trace : traces.traces) { 47 | logger.lifecycle(generateTraceReport(trace)) 48 | } 49 | 50 | throw new GradleException('Your application is vulnerable. Please see the above report for new vulnerabilities.') 51 | } else { 52 | logger.debug('No new vulnerabilities were found!') 53 | } 54 | 55 | logger.debug('Finished verifying your application.') 56 | } 57 | 58 | /** Retrieves the server id by server name 59 | * 60 | * @param sdk Contrast SDK object 61 | * @param orgUuid organization id to filter on 62 | * @param applicationId application id to filter on 63 | * @param serverName server name to filter on 64 | * @return Long id of the server 65 | * @throws GradleException 66 | */ 67 | private static long getServerId(ContrastSDK sdk, String orgUuid, String applicationId, String serverName) throws GradleException { 68 | ServerFilterForm serverFilterForm = new ServerFilterForm() 69 | serverFilterForm.setApplicationIds(Arrays.asList(applicationId)) 70 | serverFilterForm.setQ(serverName) 71 | 72 | Servers servers 73 | 74 | try { 75 | servers = sdk.getServersWithFilter(orgUuid, serverFilterForm) 76 | } catch (IOException e) { 77 | throw new GradleException('Unable to retrieve the servers.', e) 78 | } catch (UnauthorizedException e) { 79 | throw new GradleException('Unable to connect to TeamServer.', e) 80 | } 81 | 82 | if (servers.servers.isEmpty()) { 83 | throw new GradleException("Server with name '${serverName}' not found.") 84 | } 85 | 86 | return servers.servers[0].serverId 87 | } 88 | 89 | /** Retrieves the application id by application name else null 90 | * 91 | * @param sdk Contrast SDK object 92 | * @param orgUuid organization id to filter on 93 | * @param applicationName application name to filter on 94 | * @return String of the application 95 | * @throws GradleException 96 | */ 97 | private static String getApplicationId(ContrastSDK sdk, String orgUuid, String applicationName) throws GradleException { 98 | 99 | Applications applications 100 | 101 | try { 102 | applications = sdk.getApplications(orgUuid) 103 | } catch (IOException e) { 104 | throw new GradleException('Unable to retrieve the applications.', e) 105 | } catch (UnauthorizedException e) { 106 | throw new GradleException('Unable to connect to TeamServer.', e) 107 | } 108 | 109 | for (Application application : applications.applications) { 110 | if (applicationName == application.name) { 111 | return application.id 112 | } 113 | } 114 | 115 | throw new GradleException("Application with name '${applicationName}' not found.") 116 | } 117 | 118 | /** 119 | * Creates a basic report for a Trace object 120 | * @param trace Trace object 121 | * @return String report 122 | */ 123 | private static String generateTraceReport(Trace trace) { 124 | StringBuilder sb = new StringBuilder() 125 | sb.append("Trace: ${trace.title}${System.lineSeparator()}") 126 | sb.append("Trace Uuid: ${trace.uuid}${System.lineSeparator()}") 127 | sb.append("Trace Severity: ${trace.severity}${System.lineSeparator()}") 128 | sb.append("Trace Likelihood: ${trace.likelihood}${System.lineSeparator()}") 129 | return sb.toString() 130 | } 131 | 132 | /** 133 | * Returns the sublist of severities greater than or equal to the configured severity level 134 | * 135 | * @param severity include severity to filter with severity list with 136 | * @return list of severity strings 137 | */ 138 | static EnumSet getSeverityList(String severity) { 139 | 140 | List ruleSeverities = new ArrayList() 141 | switch (severity) { 142 | case 'Note': 143 | ruleSeverities.add(RuleSeverity.NOTE) 144 | case 'Low': 145 | ruleSeverities.add(RuleSeverity.LOW) 146 | case 'Medium': 147 | ruleSeverities.add(RuleSeverity.MEDIUM) 148 | case 'High': 149 | ruleSeverities.add(RuleSeverity.HIGH) 150 | case 'Critical': 151 | ruleSeverities.add(RuleSeverity.CRITICAL) 152 | } 153 | 154 | return EnumSet.copyOf(ruleSeverities) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/test/groovy/com/contrastsecurity/ContrastTaskTests.groovy: -------------------------------------------------------------------------------- 1 | package com.contrastsecurity 2 | 3 | import com.contrastsecurity.http.RuleSeverity 4 | import org.gradle.BuildResult 5 | import org.gradle.api.Project 6 | import org.gradle.testfixtures.ProjectBuilder 7 | import org.gradle.testkit.runner.BuildResult; 8 | import org.gradle.testkit.runner.GradleRunner 9 | import org.gradle.testkit.runner.UnexpectedBuildFailure; 10 | import org.junit.Before; 11 | import org.junit.Rule; 12 | import org.junit.Test; 13 | import org.junit.rules.TemporaryFolder; 14 | 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertTrue; 18 | 19 | import static org.gradle.testkit.runner.TaskOutcome.*; 20 | 21 | class ContrastTaskTests { 22 | 23 | @Rule public final TemporaryFolder testProjectDir = new TemporaryFolder() 24 | private File buildFile 25 | 26 | @Before 27 | public void setup() throws IOException { 28 | buildFile = testProjectDir.newFile("build.gradle") 29 | } 30 | 31 | //No username supplied 32 | @Test(expected = UnexpectedBuildFailure) 33 | public void testInstallTaskInvalidConfigurationNoUsername() { 34 | 35 | String buildFileContent = (getBuildScriptDependencies() + 36 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 37 | "contrastConfiguration { \n" + 38 | "username = ''\n" + 39 | "apiKey = 'demo' \n " + 40 | "serviceKey = 'demo' \n " + 41 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 42 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 43 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 44 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 45 | "minSeverity = 'Medium' \n " + 46 | "}"); 47 | 48 | writeFile(buildFile, buildFileContent) 49 | BuildResult result = GradleRunner.create() 50 | .withProjectDir(testProjectDir.getRoot()) 51 | .withArguments("contrastInstall") 52 | .build(); 53 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 54 | } 55 | 56 | //No api key 57 | @Test(expected = UnexpectedBuildFailure) 58 | public void testInstallTaskInvalidConfigurationNoApiKey() { 59 | 60 | String buildFileContent = (getBuildScriptDependencies() + 61 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 62 | "contrastConfiguration { \n" + 63 | "username = 'contrast_admin'\n" + 64 | "apiKey = '' \n " + 65 | "serviceKey = 'demo' \n " + 66 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 67 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 68 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 69 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 70 | "minSeverity = 'Medium' \n " + 71 | "}"); 72 | 73 | writeFile(buildFile, buildFileContent) 74 | BuildResult result = GradleRunner.create() 75 | .withProjectDir(testProjectDir.getRoot()) 76 | .withArguments("contrastInstall") 77 | .build(); 78 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 79 | } 80 | 81 | //No service key 82 | @Test(expected = UnexpectedBuildFailure) 83 | public void testInstallTaskInvalidConfigurationNoServiceKey() { 84 | 85 | String buildFileContent = (getBuildScriptDependencies() + 86 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 87 | "contrastConfiguration { \n" + 88 | "username = 'contrast_admin'\n" + 89 | "apiKey = 'demo' \n " + 90 | "serviceKey = '' \n " + 91 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 92 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 93 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 94 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 95 | "minSeverity = 'Medium' \n " + 96 | "}"); 97 | 98 | writeFile(buildFile, buildFileContent) 99 | BuildResult result = GradleRunner.create() 100 | .withProjectDir(testProjectDir.getRoot()) 101 | .withArguments("contrastInstall") 102 | .build(); 103 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 104 | } 105 | 106 | //No api URL 107 | @Test(expected = UnexpectedBuildFailure) 108 | public void testInstallTaskInvalidConfigurationNoApiUrl() { 109 | 110 | String buildFileContent = (getBuildScriptDependencies() + 111 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 112 | "contrastConfiguration { \n" + 113 | "username = 'contrast_admin'\n" + 114 | "apiKey = 'demo' \n " + 115 | "serviceKey = 'demo' \n " + 116 | "apiUrl = '' \n " + 117 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 118 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 119 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 120 | "minSeverity = 'Medium' \n " + 121 | "}"); 122 | 123 | writeFile(buildFile, buildFileContent) 124 | BuildResult result = GradleRunner.create() 125 | .withProjectDir(testProjectDir.getRoot()) 126 | .withArguments("contrastInstall") 127 | .build(); 128 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 129 | } 130 | 131 | //No orgUuid 132 | @Test(expected = UnexpectedBuildFailure) 133 | public void testInstallTaskInvalidConfigurationNoOrgUuid() { 134 | 135 | String buildFileContent = (getBuildScriptDependencies() + 136 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 137 | "contrastConfiguration { \n" + 138 | "username = 'contrast_admin'\n" + 139 | "apiKey = '' \n " + 140 | "serviceKey = 'demo' \n " + 141 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 142 | "orgUuid = '' \n " + 143 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 144 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 145 | "minSeverity = 'Medium' \n " + 146 | "}"); 147 | 148 | writeFile(buildFile, buildFileContent) 149 | BuildResult result = GradleRunner.create() 150 | .withProjectDir(testProjectDir.getRoot()) 151 | .withArguments("contrastInstall") 152 | .build(); 153 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 154 | } 155 | 156 | //No AppId 157 | @Test(expected = UnexpectedBuildFailure) 158 | public void testInstallTaskInvalidConfigurationNoAppId() { 159 | 160 | String buildFileContent = (getBuildScriptDependencies() + 161 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 162 | "contrastConfiguration { \n" + 163 | "username = 'contrast_admin'\n" + 164 | "apiKey = '' \n " + 165 | "serviceKey = 'demo' \n " + 166 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 167 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 168 | "appName = '' \n " + 169 | "serverName = 'ip-192-168-1-50.ec2.internal' \n " + 170 | "minSeverity = 'Medium' \n " + 171 | "}"); 172 | 173 | writeFile(buildFile, buildFileContent) 174 | BuildResult result = GradleRunner.create() 175 | .withProjectDir(testProjectDir.getRoot()) 176 | .withArguments("contrastInstall") 177 | .build(); 178 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 179 | } 180 | 181 | //No Server name 182 | @Test(expected = UnexpectedBuildFailure) 183 | public void testInstallTaskInvalidConfigurationNoServerName() { 184 | 185 | String buildFileContent = (getBuildScriptDependencies() + 186 | "apply plugin: 'com.contrastsecurity.contrastplugin' \n " + 187 | "contrastConfiguration { \n" + 188 | "username = 'contrast_admin'\n" + 189 | "apiKey = '' \n " + 190 | "serviceKey = 'demo' \n " + 191 | "apiUrl = 'http://localhost:19080/Contrast/api' \n " + 192 | "orgUuid = '632AAF07-557E-4B26-99A0-89F85D1748DB' \n " + 193 | "appName = '54afdf56-8b5f-4cf3-a9a9-cbfe2c134927' \n " + 194 | "serverName = '' \n " + 195 | "minSeverity = 'Medium' \n " + 196 | "}"); 197 | 198 | writeFile(buildFile, buildFileContent) 199 | BuildResult result = GradleRunner.create() 200 | .withProjectDir(testProjectDir.getRoot()) 201 | .withArguments("contrastInstall") 202 | .build(); 203 | assertEquals(result.task(":contrastInstall").getOutcome(), FAILED); 204 | } 205 | 206 | @Test 207 | public void enumSet() { 208 | 209 | EnumSet severities = VerifyContrast.getSeverityList("Low"); 210 | assertEquals(severities.contains(RuleSeverity.NOTE), false); 211 | assertEquals(severities.contains(RuleSeverity.LOW), true); 212 | assertEquals(severities.contains(RuleSeverity.MEDIUM), true); 213 | assertEquals(severities.contains(RuleSeverity.HIGH), true); 214 | assertEquals(severities.contains(RuleSeverity.CRITICAL), true); 215 | 216 | 217 | } 218 | 219 | 220 | 221 | //Testing helpers for writing the build.gradle file 222 | private void writeFile(File destination, String content) throws IOException { 223 | BufferedWriter output = null; 224 | try { 225 | output = new BufferedWriter(new FileWriter(destination)); 226 | output.write(content); 227 | } finally { 228 | if (output != null) { 229 | output.close(); 230 | } 231 | } 232 | } 233 | private String getBuildScriptDependencies(){ 234 | return ("buildscript { \n" + 235 | " repositories { \n" + 236 | "mavenLocal() \n" + 237 | " } \n" + 238 | " dependencies { \n" + 239 | " classpath('com.contrastsecurity:ContrastGradlePlugin:1.0-SNAPSHOT') \n" + 240 | " }\n " + 241 | " } \n"); 242 | } 243 | 244 | } 245 | --------------------------------------------------------------------------------