Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #13 from rapid7/support-agent-task-credentials
Browse files Browse the repository at this point in the history
Implement RuntimeDataProvider to pre-fetch API Key for task
  • Loading branch information
zyoutz-r7 authored Jun 9, 2020
2 parents ddce2a0 + 5ea0393 commit a45bf1f
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 40 deletions.
2 changes: 1 addition & 1 deletion extension.spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ products: [insightappsec]
name: insightappsec_bamboo_plugin
title: Atlassian Bamboo Plugin
description: Integrate InsightAppSec application security scans into Atlassian Bamboo build and release pipelines
version: 1.0.0
version: 1.1.0
vendor: rapid7
status: []
support: rapid7
Expand Down
1 change: 1 addition & 0 deletions help.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ If the scan gating doesn't appear to occur as expected, confirm that the vulnera

# Version History

* 1.1.0 - Support for Atlassian Bamboo 7.0.X, Implements RuntimeDataProvider to assist with pre-fetch of API Key for tasks run on remote agents
* 1.0.0 - Initial integration

# Links
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.rapid7.ias.bamboo</groupId>
<artifactId>insightappsec-bamboo-plugin</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<scm>
<url>https://github.com/rapid7/insightappsec-bamboo-plugin</url>
<connection>scm:git:git@github.com:rapid7/insightappsec-bamboo-plugin.git</connection>
Expand All @@ -23,8 +23,8 @@
<packaging>atlassian-plugin</packaging>

<properties>
<bamboo.version>6.10.4</bamboo.version>
<bamboo.data.version>6.10.4</bamboo.data.version>
<bamboo.version>7.0.4</bamboo.version>
<bamboo.data.version>7.0.4</bamboo.data.version>
<amps.version>6.3.21</amps.version>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/com/rapid7/ias/bamboo/impl/InsightAppSecHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,23 @@ public Map<String,String> scanStatus(String scanId) throws InsightAppSecExceptio
try {
ResourceScan scan = scansApi.getScan(UUID.fromString(scanId));

status = new HashMap<String,String>() {{
put("Status", scan.getStatus().getValue());
if (scan.getFailureReason() != null) {
put("Reason", Objects.toString(scan.getFailureReason().getValue(), ""));
} else {
put("Reason", "");
}
}};
// There are times the API returns null for status; be defensive
if (scan.getStatus() != null && scan.getStatus().getValue() != null) {
status = new HashMap<String, String>() {{
put("Status", scan.getStatus().getValue());
if (scan.getFailureReason() != null) {
put("Reason", Objects.toString(scan.getFailureReason().getValue(), ""));
} else {
put("Reason", "");
}
}};
}
} catch (ApiException iase) {
logger.error("Failed to retrieve scan by ID " + scanId + ": " + iase.getCode());
handleException(iase);
} finally {
return status;
}
return status;
}

public ResourceScanConfig getScanConfiguration(String scanConfigName, UUID appId) throws InsightAppSecException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.rapid7.ias.bamboo.impl;

import com.atlassian.bamboo.ResultKey;
import com.atlassian.bamboo.credentials.CredentialsAccessor;
import com.atlassian.bamboo.credentials.CredentialsData;
import com.atlassian.bamboo.security.SecureToken;
import com.atlassian.bamboo.security.SecureTokenService;
import com.atlassian.bamboo.serialization.WhitelistedSerializable;
import com.atlassian.bamboo.task.RuntimeTaskDataProvider;
import com.atlassian.bamboo.task.TaskDefinition;
import com.atlassian.bamboo.task.runtime.RuntimeTaskDefinition;
import com.atlassian.bamboo.v2.build.CommonContext;
import com.atlassian.bamboo.v2.build.agent.messages.AuthenticableMessage;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;

import static com.atlassian.bamboo.credentials.UsernamePasswordCredentialType.CFG_PASSWORD;

public class InsightAppSecRuntimeDataProvider implements RuntimeTaskDataProvider, IasConstants {
@Inject
private CredentialsAccessor credentialsAccessor;

@NotNull
@Override
public Map<String, String> populateRuntimeTaskData(@NotNull TaskDefinition taskDefinition,
@NotNull CommonContext commonContext) {
final Map<String, String> configuration = taskDefinition.getConfiguration();
final Map<String, String> result = new HashMap<>();

// Get Shared Credential for API auth
propagateSharedCredentialsValues(InsightAppSecScanTaskConfigurator.SELECTED_CREDENTIAL, taskDefinition, configuration, result);

return result;
}

private void propagateSharedCredentialsValues(String sharedCredentialsKey, @NotNull TaskDefinition taskDefinition,
Map<String, String> configuration, Map<String, String> result) {
final String credentialsId = configuration.get(sharedCredentialsKey);
if (StringUtils.isNotBlank(credentialsId)) {
final CredentialsData credentials = credentialsAccessor.getCredentials(Long.parseLong(credentialsId));
if (credentials == null) {
throw new IllegalStateException("Can't find API Key as shared credentials with id " + credentialsId
+ " for task "
+ (StringUtils.isEmpty(taskDefinition.getUserDescription()) ? taskDefinition.getPluginKey() : taskDefinition.getUserDescription()));
}

// We only need password field for api_key; we don't use the name
final String password = credentials.getConfiguration().get(CFG_PASSWORD);
result.put(CFG_PASSWORD, password);
}
}

@Override
public void processRuntimeTaskData(@NotNull RuntimeTaskDefinition runtimeTaskDefinition, @NotNull CommonContext commonContext)
{
}
}
24 changes: 11 additions & 13 deletions src/main/java/com/rapid7/ias/bamboo/impl/InsightAppSecScanTask.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.rapid7.ias.bamboo.impl;

import com.atlassian.bamboo.configuration.ConfigurationMap;
import com.atlassian.bamboo.credentials.CredentialsData;
import com.atlassian.bamboo.credentials.CredentialsManager;
import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContext;
import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContextImpl;
import com.atlassian.bamboo.plan.artifact.ArtifactPublishingResult;
import com.atlassian.bamboo.security.SecureToken;
import com.atlassian.bamboo.task.*;
import com.atlassian.bamboo.util.Narrow;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.atlassian.bamboo.build.artifact.ArtifactManager;
import static com.atlassian.bamboo.credentials.UsernamePasswordCredentialType.CFG_PASSWORD;

import com.rapid7.ias.bamboo.util.UtilityLogger;
import com.rapid7.ias.client.model.ResourceApp;
Expand All @@ -26,7 +26,6 @@

@Scanned
public class InsightAppSecScanTask implements CommonTaskType, IasConstants {
private CredentialsManager credentialsManager;
private UtilityLogger logger;
private static final Logger log = Logger.getLogger(InsightAppSecScanTask.class);

Expand All @@ -36,9 +35,7 @@ public class InsightAppSecScanTask implements CommonTaskType, IasConstants {

@ComponentImport ArtifactManager artifactManager;

public InsightAppSecScanTask(@ComponentImport ArtifactManager artifactManager,
@ComponentImport CredentialsManager credentialsManager) {
this.credentialsManager = credentialsManager;
public InsightAppSecScanTask(@ComponentImport ArtifactManager artifactManager) {
this.artifactManager = artifactManager;
}

Expand All @@ -48,17 +45,18 @@ public TaskResult execute(CommonTaskContext taskContext) throws TaskException {
TaskResultBuilder result = TaskResultBuilder.newBuilder(taskContext);
logger = new UtilityLogger(log, taskContext.getBuildLogger());

// Get RuntimeContext for pre-task pull of API Key
Map<String, String> runtimeContext = taskContext.getRuntimeTaskContext();
final String apiKey = runtimeContext.get(CFG_PASSWORD);

ConfigurationMap configMap = taskContext.getConfigurationMap();
region = configMap.get(SELECTED_REGION);
appName = configMap.get(APP_NAME);
scanConfigName = configMap.get(SCAN_CONFIG_NAME);

String credentialId = configMap.get(SELECTED_CREDENTIAL);
CredentialsData cred = credentialsManager.getCredentials(Long.parseLong(credentialId));

if (cred == null) {
if (apiKey == null) {
logger.error("Previously configured credential is no longer defined within Bamboo; please review task and" +
"credential configuration");
" credential configuration");
Thread.currentThread().interrupt();
return result.failedWithError().build();
}
Expand All @@ -68,7 +66,7 @@ public TaskResult execute(CommonTaskContext taskContext) throws TaskException {
logger.info("Scan Config: "+ scanConfigName);

// Initialize helper with necessary clients
InsightAppSecHelper iasHelper = new InsightAppSecHelper(region, cred.getConfiguration().get("password"), logger);
InsightAppSecHelper iasHelper = new InsightAppSecHelper(region, apiKey, logger);

try {
ResourceApp app = iasHelper.getApplication(appName);
Expand Down Expand Up @@ -213,7 +211,7 @@ private void publishArtifacts(TaskContext taskContext, String name, File directo

logger.info("Publishing artifact(s) for scan");

ArtifactDefinitionContext artifact = new ArtifactDefinitionContextImpl(name, true, null);
ArtifactDefinitionContext artifact = new ArtifactDefinitionContextImpl(name, true, SecureToken.create());
artifact.setCopyPattern("insightappsec-scan-*.json");

ArtifactPublishingResult result = artifactManager.publish(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

import com.atlassian.bamboo.collections.ActionParametersMap;
import com.atlassian.bamboo.credentials.CredentialsData;
import com.atlassian.bamboo.credentials.CredentialsManager;
import com.atlassian.bamboo.credentials.CredentialsAccessor;
import com.atlassian.bamboo.task.AbstractTaskConfigurator;
import com.atlassian.bamboo.task.TaskDefinition;
import com.atlassian.bamboo.utils.error.ErrorCollection;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.atlassian.bamboo.utils.i18n.I18nBean;
import com.atlassian.bamboo.utils.i18n.I18nBeanFactory;
import com.atlassian.util.concurrent.NotNull;
import com.atlassian.util.concurrent.Nullable;
import static com.atlassian.bamboo.credentials.UsernamePasswordCredentialType.CFG_PASSWORD;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.rapid7.ias.bamboo.util.UtilityLogger;
import com.rapid7.ias.client.model.ResourceApp;
Expand All @@ -26,18 +27,18 @@
@Scanned
public class InsightAppSecScanTaskConfigurator extends AbstractTaskConfigurator implements IasConstants {

private CredentialsManager credentialsManager;
@ComponentImport CredentialsAccessor credentialsAccessor;
private I18nBean i18nBean;

/**
*
* @param i18nBeanFactory
* @param credentialsManager
* @param credentialsAccessor
*/
public InsightAppSecScanTaskConfigurator(
@ComponentImport I18nBeanFactory i18nBeanFactory,
@ComponentImport CredentialsManager credentialsManager) {
this.credentialsManager = credentialsManager;
@ComponentImport CredentialsAccessor credentialsAccessor) {
this.credentialsAccessor = credentialsAccessor;
this.i18nBean = i18nBeanFactory.getI18nBean();
}

Expand All @@ -47,7 +48,7 @@ public InsightAppSecScanTaskConfigurator(
*/
private Map<Long, String> getCredentials() {
Map<Long, String> credentials = new Hashtable<>();
for (CredentialsData data : credentialsManager.getAllCredentials()) {
for (CredentialsData data : credentialsAccessor.getAllCredentials()) {
if (data.getName().startsWith("Rapid7")) {
credentials.put(data.getId(), data.getName());
}
Expand Down Expand Up @@ -107,7 +108,7 @@ public void validate(@NotNull ActionParametersMap params,

if (credentialId == null) {
errorCollection.addError(SELECTED_CREDENTIAL, i18nBean.getText("error.apiKey"));
}else if (credentialsManager.getCredentials(Long.parseLong(credentialId)) == null) {
}else if (credentialsAccessor.getCredentials(Long.parseLong(credentialId)) == null) {
errorCollection.addError(SELECTED_CREDENTIAL, i18nBean.getText("error.apiKeyNotExist"));
}else if (StringUtils.isEmpty(regionValue)){
errorCollection.addError(SELECTED_REGION, i18nBean.getText("error.region"));
Expand All @@ -116,9 +117,9 @@ public void validate(@NotNull ActionParametersMap params,
}else if(StringUtils.isEmpty(scanConfigNameValue)){
errorCollection.addError(SCAN_CONFIG_NAME, i18nBean.getText("error.scanConfigName"));
}else{
CredentialsData cred = credentialsManager.getCredentials(Long.parseLong(credentialId));
CredentialsData cred = credentialsAccessor.getCredentials(Long.parseLong(credentialId));

InsightAppSecHelper iasHelper = new InsightAppSecHelper(regionValue, cred.getConfiguration().get("password"), logger);
InsightAppSecHelper iasHelper = new InsightAppSecHelper(regionValue, cred.getConfiguration().get(CFG_PASSWORD), logger);

try {
ResourceApp application = iasHelper.getApplication(appNameValue);
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/atlassian-plugin-marketing.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<atlassian-plugin-marketing>
<!--Describe names and versions of compatible applications -->
<compatibility>
<product name="bamboo" min="6.3" max="6.10.4"/>
<product name="bamboo" min="6.3" max="7.0.4"/>
</compatibility>
<!-- Describe your add-on logo and banner. The banner is only displayed in the UPM. -->
<logo image="images/rapid7-icon.png"/>
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/atlassian-plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<category name="builder"/>
<category name="deployment"/>
<configuration class="com.rapid7.ias.bamboo.impl.InsightAppSecScanTaskConfigurator"/>
<runtimeTaskDataProvider class="com.rapid7.ias.bamboo.impl.InsightAppSecRuntimeDataProvider"/>
<resource type="freemarker" name="edit" location="template/InsightAppSecScanTaskTemplate.ftl"/>
<resource type="download" name="icon" location="images/rapid7-icon.png"/>
<help link="task.help.link" title="task.help.title" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class InsightAppSecScanTaskUnitTest
@Test
public void testMyName()
{
InsightAppSecScanTask component = new InsightAppSecScanTask(null, null);
InsightAppSecScanTask component = new InsightAppSecScanTask(null);
assertEquals("names do not match!", "Rapid7 InsightAppSec",component.getName());
}
}
1 change: 0 additions & 1 deletion src/test/resources/atlassian-plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@

<!--&lt;!&ndash; from the product container &ndash;&gt;-->
<!--<component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" />-->

</atlassian-plugin>

0 comments on commit a45bf1f

Please sign in to comment.