credentials = CredentialsProvider
+ .lookupCredentials(VaultCredential.class, build.getParent(), ACL.SYSTEM,
+ Collections.emptyList());
+ VaultCredential credential = CredentialsMatchers
+ .firstOrNull(credentials, new IdMatcher(id));
+
+ if (credential == null) {
+ throw new CredentialsUnavailableException(id);
+ }
+
+ return credential;
+ }
+
+ return null;
+ }
+
+ public static boolean responseHasErrors(VaultConfiguration configuration, PrintStream logger,
+ String path, LogicalResponse response) {
+ RestResponse restResponse = response.getRestResponse();
+ if (restResponse == null) {
+ return false;
+ }
+ int status = restResponse.getStatus();
+ if (status == 403) {
+ logger.printf("Access denied to Vault Secrets at '%s'%n", path);
+ return true;
+ } else if (status == 404) {
+ if (configuration.getFailIfNotFound()) {
+ throw new VaultPluginException(
+ String.format("Vault credentials not found for '%s'", path));
+ } else {
+ logger.printf("Vault credentials not found for '%s'%n", path);
+ return true;
+ }
+ } else if (status >= 400) {
+ String errors = Optional
+ .of(Json.parse(new String(restResponse.getBody(), StandardCharsets.UTF_8))).map(
+ JsonValue::asObject)
+ .map(j -> j.get("errors")).map(JsonValue::asArray).map(JsonArray::values)
+ .map(j -> j.stream().map(JsonValue::asString).collect(Collectors.joining("\n")))
+ .orElse("");
+ logger.printf("Vault responded with %d error code.%n", status);
+ if (StringUtils.isNotBlank(errors)) {
+ logger.printf("Vault responded with errors: %s%n", errors);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public static VaultConfiguration pullAndMergeConfiguration(Run, ?> build,
+ VaultConfiguration buildConfiguration) {
+ VaultConfiguration configuration = buildConfiguration;
+ for (VaultConfigResolver resolver : ExtensionList.lookup(VaultConfigResolver.class)) {
+ if (configuration != null) {
+ configuration = configuration
+ .mergeWithParent(resolver.forJob(build.getParent()));
+ } else {
+ configuration = resolver.forJob(build.getParent());
+ }
+ }
+ if (configuration == null) {
+ throw new VaultPluginException(
+ "No configuration found - please configure the VaultPlugin.");
+ }
+ configuration.fixDefaults();
+
+ return configuration;
+ }
}
diff --git a/src/main/java/com/datapipe/jenkins/vault/VaultBindingStep.java b/src/main/java/com/datapipe/jenkins/vault/VaultBindingStep.java
new file mode 100644
index 00000000..9e64d477
--- /dev/null
+++ b/src/main/java/com/datapipe/jenkins/vault/VaultBindingStep.java
@@ -0,0 +1,191 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Datapipe, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.datapipe.jenkins.vault;
+
+import com.datapipe.jenkins.vault.configuration.VaultConfiguration;
+import com.datapipe.jenkins.vault.log.MaskingConsoleLogFilter;
+import com.datapipe.jenkins.vault.model.VaultSecret;
+import com.google.common.annotations.VisibleForTesting;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
+import hudson.EnvVars;
+import hudson.Extension;
+import hudson.console.ConsoleLogFilter;
+import hudson.model.Run;
+import hudson.model.TaskListener;
+import hudson.util.Secret;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback.TailCall;
+import org.jenkinsci.plugins.workflow.steps.BodyInvoker;
+import org.jenkinsci.plugins.workflow.steps.EnvironmentExpander;
+import org.jenkinsci.plugins.workflow.steps.GeneralNonBlockingStepExecution;
+import org.jenkinsci.plugins.workflow.steps.Step;
+import org.jenkinsci.plugins.workflow.steps.StepContext;
+import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
+import org.jenkinsci.plugins.workflow.steps.StepExecution;
+import org.kohsuke.stapler.DataBoundConstructor;
+import org.kohsuke.stapler.DataBoundSetter;
+
+public class VaultBindingStep extends Step {
+
+ private VaultConfiguration configuration;
+ private List vaultSecrets;
+
+ @DataBoundConstructor
+ public VaultBindingStep(@CheckForNull List vaultSecrets) {
+ this.vaultSecrets = vaultSecrets;
+ }
+
+ public List getVaultSecrets() {
+ return vaultSecrets;
+ }
+
+ @DataBoundSetter
+ public void setConfiguration(VaultConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public VaultConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public StepExecution start(StepContext context) throws Exception {
+ return new Execution(this, context);
+ }
+
+ protected static class Execution extends GeneralNonBlockingStepExecution {
+
+ private static final long serialVersionUID = 1;
+
+ private transient VaultBindingStep step;
+ private transient VaultAccessor vaultAccessor;
+
+ public Execution(VaultBindingStep step, StepContext context) {
+ super(context);
+ this.step = step;
+ }
+
+ @VisibleForTesting
+ public void setVaultAccessor(VaultAccessor vaultAccessor) {
+ this.vaultAccessor = vaultAccessor;
+ }
+
+ @Override
+ public boolean start() throws Exception {
+ run(this::doStart);
+ return false;
+ }
+
+ private void doStart() throws Exception {
+ Run, ?> run = getContext().get(Run.class);
+ TaskListener listener = getContext().get(TaskListener.class);
+ EnvVars envVars = getContext().get(EnvVars.class);
+
+ Map overrides = VaultAccessor
+ .retrieveVaultSecrets(run, listener.getLogger(), envVars, vaultAccessor,
+ step.getConfiguration(), step.getVaultSecrets());
+
+ List secretValues = new ArrayList<>();
+ secretValues.addAll(overrides.values());
+
+ getContext().newBodyInvoker()
+ .withContext(EnvironmentExpander.merge(getContext().get(EnvironmentExpander.class),
+ new VaultBindingStep.Overrider(overrides)))
+ .withContext(BodyInvoker
+ .mergeConsoleLogFilters(getContext().get(ConsoleLogFilter.class),
+ new MaskingConsoleLogFilter(run.getCharset().name(), secretValues)))
+ .withCallback(new Callback())
+ .start();
+ }
+ }
+
+ private static final class Overrider extends EnvironmentExpander {
+
+ private static final long serialVersionUID = 1;
+
+ private final Map overrides = new HashMap();
+
+ Overrider(Map overrides) {
+ for (Map.Entry override : overrides.entrySet()) {
+ this.overrides.put(override.getKey(), Secret.fromString(override.getValue()));
+ }
+ }
+
+ @Override
+ public void expand(EnvVars env) throws IOException, InterruptedException {
+ for (Map.Entry override : overrides.entrySet()) {
+ env.override(override.getKey(), override.getValue().getPlainText());
+ }
+ }
+
+ @Override
+ public Set getSensitiveVariables() {
+ return Collections.unmodifiableSet(overrides.keySet());
+ }
+ }
+
+ private static class Callback extends TailCall {
+
+ @Override
+ protected void finished(StepContext context) throws Exception {
+
+ }
+ }
+
+ @Extension
+ public static final class DescriptorImpl extends StepDescriptor {
+
+ @Override
+ public Set extends Class>> getRequiredContext() {
+ return Collections
+ .unmodifiableSet(
+ new HashSet<>(Arrays.asList(TaskListener.class, Run.class, EnvVars.class)));
+ }
+
+ @Override
+ public boolean takesImplicitBlockArgument() {
+ return true;
+ }
+
+ @Override
+ public String getFunctionName() {
+ return "withVault";
+ }
+
+ @Nonnull
+ @Override
+ public String getDisplayName() {
+ return "Vault Plugin";
+ }
+ }
+}
diff --git a/src/main/java/com/datapipe/jenkins/vault/VaultBuildWrapper.java b/src/main/java/com/datapipe/jenkins/vault/VaultBuildWrapper.java
index 9c05c265..fcc15bbb 100644
--- a/src/main/java/com/datapipe/jenkins/vault/VaultBuildWrapper.java
+++ b/src/main/java/com/datapipe/jenkins/vault/VaultBuildWrapper.java
@@ -23,24 +23,11 @@
*/
package com.datapipe.jenkins.vault;
-import com.bettercloud.vault.VaultConfig;
-import com.bettercloud.vault.VaultException;
-import com.bettercloud.vault.json.Json;
-import com.bettercloud.vault.json.JsonArray;
-import com.bettercloud.vault.json.JsonValue;
-import com.bettercloud.vault.response.LogicalResponse;
-import com.bettercloud.vault.rest.RestResponse;
-import com.cloudbees.plugins.credentials.CredentialsMatchers;
-import com.cloudbees.plugins.credentials.CredentialsProvider;
-import com.cloudbees.plugins.credentials.CredentialsUnavailableException;
-import com.cloudbees.plugins.credentials.matchers.IdMatcher;
import com.datapipe.jenkins.vault.configuration.VaultConfigResolver;
import com.datapipe.jenkins.vault.configuration.VaultConfiguration;
-import com.datapipe.jenkins.vault.credentials.VaultCredential;
import com.datapipe.jenkins.vault.exception.VaultPluginException;
import com.datapipe.jenkins.vault.log.MaskingConsoleLogFilter;
import com.datapipe.jenkins.vault.model.VaultSecret;
-import com.datapipe.jenkins.vault.model.VaultSecretValue;
import com.google.common.annotations.VisibleForTesting;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -49,24 +36,16 @@
import hudson.ExtensionList;
import hudson.FilePath;
import hudson.Launcher;
-import hudson.Util;
import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractProject;
import hudson.model.Run;
import hudson.model.TaskListener;
-import hudson.security.ACL;
import hudson.tasks.BuildWrapperDescriptor;
import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
import jenkins.tasks.SimpleBuildWrapper;
-import org.apache.commons.lang.StringUtils;
-import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
@@ -114,124 +93,16 @@ public void setVaultAccessor(VaultAccessor vaultAccessor) {
this.vaultAccessor = vaultAccessor;
}
- private List retrieveLeaseIds(List logicalResponses) {
- List leaseIds = new ArrayList<>();
- for (LogicalResponse response : logicalResponses) {
- String leaseId = response.getLeaseId();
- if (leaseId != null && !leaseId.isEmpty()) {
- leaseIds.add(leaseId);
- }
- }
- return leaseIds;
- }
-
- protected void provideEnvironmentVariablesFromVault(Context context, Run build, EnvVars envVars) {
- VaultConfiguration config = getConfiguration();
- String url = config.getVaultUrl();
-
- if (StringUtils.isBlank(url)) {
- throw new VaultPluginException(
- "The vault url was not configured - please specify the vault url to use.");
- }
-
- VaultConfig vaultConfig = config.getVaultConfig();
- VaultCredential credential = config.getVaultCredential();
- if (credential == null) credential = retrieveVaultCredentials(build);
-
- String prefixPath = StringUtils.isBlank(config.getPrefixPath())
- ? ""
- : Util.ensureEndsWith(envVars.expand(config.getPrefixPath()), "/");
-
- if (vaultAccessor == null) vaultAccessor = new VaultAccessor();
- vaultAccessor.setConfig(vaultConfig);
- vaultAccessor.setCredential(credential);
- vaultAccessor.setMaxRetries(config.getMaxRetries());
- vaultAccessor.setRetryIntervalMilliseconds(config.getRetryIntervalMilliseconds());
- vaultAccessor.init();
-
- for (VaultSecret vaultSecret : vaultSecrets) {
- String path = prefixPath + envVars.expand(vaultSecret.getPath());
- logger.printf("Retrieving secret: %s%n", path);
- Integer engineVersion = Optional.ofNullable(vaultSecret.getEngineVersion())
- .orElse(configuration.getEngineVersion());
- try {
- LogicalResponse response = vaultAccessor.read(path, engineVersion);
- if (responseHasErrors(path, response)) {
- continue;
- }
- Map values = response.getData();
- for (VaultSecretValue value : vaultSecret.getSecretValues()) {
- String vaultKey = value.getVaultKey();
- String secret = values.get(vaultKey);
- if (StringUtils.isBlank(secret)) {
- throw new IllegalArgumentException(
- "Vault Secret " + vaultKey + " at " + path
- + " is either null or empty. Please check the Secret in Vault.");
- } else {
- valuesToMask.add(secret);
- }
- context.env(value.getEnvVar(), secret);
- }
- } catch (VaultPluginException ex) {
- VaultException e = (VaultException) ex.getCause();
- if (e != null) {
- throw new VaultPluginException(String
- .format("Vault response returned %d for secret path %s",
- e.getHttpStatusCode(), path),
- e);
- }
- throw ex;
- }
- }
- }
+ protected void provideEnvironmentVariablesFromVault(Context context, Run build,
+ EnvVars envVars) {
+ Map overrides = VaultAccessor
+ .retrieveVaultSecrets(build, logger, envVars, vaultAccessor,
+ getConfiguration(), getVaultSecrets());
- private boolean responseHasErrors(String path, LogicalResponse response) {
- RestResponse restResponse = response.getRestResponse();
- if (restResponse == null) return false;
- int status = restResponse.getStatus();
- if (status == 403) {
- logger.printf("Access denied to Vault Secrets at '%s'%n", path);
- return true;
- } else if (status == 404) {
- if (configuration.getFailIfNotFound()) {
- throw new VaultPluginException(
- String.format("Vault credentials not found for '%s'", path));
- } else {
- logger.printf("Vault credentials not found for '%s'%n", path);
- return true;
- }
- } else if (status >= 400) {
- String errors = Optional
- .of(Json.parse(new String(restResponse.getBody(), StandardCharsets.UTF_8))).map(JsonValue::asObject)
- .map(j -> j.get("errors")).map(JsonValue::asArray).map(JsonArray::values)
- .map(j -> j.stream().map(JsonValue::asString).collect(Collectors.joining("\n")))
- .orElse("");
- logger.printf("Vault responded with %d error code.%n", status);
- if (StringUtils.isNotBlank(errors)) {
- logger.printf("Vault responded with errors: %s%n", errors);
- }
- return true;
+ for (Map.Entry secret : overrides.entrySet()) {
+ valuesToMask.add(secret.getValue());
+ context.env(secret.getKey(), secret.getValue());
}
- return false;
- }
-
- protected VaultCredential retrieveVaultCredentials(Run build) {
- String id = getConfiguration().getVaultCredentialId();
- if (StringUtils.isBlank(id)) {
- throw new VaultPluginException(
- "The credential id was not configured - please specify the credentials to use.");
- }
- List credentials = CredentialsProvider
- .lookupCredentials(VaultCredential.class, build.getParent(), ACL.SYSTEM,
- Collections.emptyList());
- VaultCredential credential = CredentialsMatchers
- .firstOrNull(credentials, new IdMatcher(id));
-
- if (credential == null) {
- throw new CredentialsUnavailableException(id);
- }
-
- return credential;
}
private void pullAndMergeConfiguration(Run, ?> build) {
@@ -257,11 +128,10 @@ public ConsoleLogFilter createLoggerDecorator(
/**
- * Descriptor for {@link VaultBuildWrapper}. Used as a singleton. The class is marked as public so
- * that it can be accessed from views.
+ * Descriptor for {@link VaultBuildWrapper}. Used as a singleton. The class is marked as public
+ * so that it can be accessed from views.
*/
@Extension
- @Symbol("withVault")
public static final class DescriptorImpl extends BuildWrapperDescriptor {
public DescriptorImpl() {
diff --git a/src/main/resources/com/datapipe/jenkins/vault/VaultBindingStep/config.jelly b/src/main/resources/com/datapipe/jenkins/vault/VaultBindingStep/config.jelly
new file mode 100644
index 00000000..205f181d
--- /dev/null
+++ b/src/main/resources/com/datapipe/jenkins/vault/VaultBindingStep/config.jelly
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperWithMockAccessor.java b/src/test/java/com/datapipe/jenkins/vault/VaultBindingStepWithMockAccessor.java
similarity index 68%
rename from src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperWithMockAccessor.java
rename to src/test/java/com/datapipe/jenkins/vault/VaultBindingStepWithMockAccessor.java
index 57c3efd4..df19d27b 100644
--- a/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperWithMockAccessor.java
+++ b/src/test/java/com/datapipe/jenkins/vault/VaultBindingStepWithMockAccessor.java
@@ -6,29 +6,36 @@
import com.datapipe.jenkins.vault.credentials.VaultAppRoleCredential;
import com.datapipe.jenkins.vault.credentials.VaultCredential;
import com.datapipe.jenkins.vault.model.VaultSecret;
-import edu.umd.cs.findbugs.annotations.CheckForNull;
+import hudson.EnvVars;
import hudson.Extension;
-import hudson.model.AbstractProject;
-import hudson.model.Descriptor;
-import hudson.tasks.BuildWrapper;
+import hudson.model.Run;
+import hudson.model.TaskListener;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.jenkinsci.plugins.workflow.steps.StepContext;
+import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
+import org.jenkinsci.plugins.workflow.steps.StepExecution;
import org.kohsuke.stapler.DataBoundConstructor;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-/*
-This class is only used for testing the Jenkinsfile - we can not inject our
- MockAccessor there and therefore need to mimic it's behaviour here.
- */
-public class VaultBuildWrapperWithMockAccessor extends VaultBuildWrapper {
-
+public class VaultBindingStepWithMockAccessor extends VaultBindingStep {
@DataBoundConstructor
- public VaultBuildWrapperWithMockAccessor(@CheckForNull List vaultSecrets) {
+ public VaultBindingStepWithMockAccessor(List vaultSecrets) {
super(vaultSecrets);
- setVaultAccessor(new VaultAccessor() {
+ }
+
+ @Override
+ public StepExecution start(StepContext context) throws Exception {
+ Execution execution = new Execution(this, context);
+ execution.setVaultAccessor(new VaultAccessor() {
@Override
public void setConfig(VaultConfig config) {
@@ -73,20 +80,30 @@ public LogicalResponse read(String path, Integer engineVersion) {
return resp;
}
});
+ return execution;
}
@Extension
- public static final class DescriptorImpl extends Descriptor {
+ public static final class DescriptorImpl extends StepDescriptor {
- public DescriptorImpl() {
- super(VaultBuildWrapperWithMockAccessor.class);
- load();
+ @Override
+ public Set extends Class>> getRequiredContext() {
+ return Collections
+ .unmodifiableSet(
+ new HashSet<>(Arrays.asList(TaskListener.class, Run.class, EnvVars.class)));
}
- public boolean isApplicable(AbstractProject, ?> item) {
+ @Override
+ public boolean takesImplicitBlockArgument() {
return true;
}
+ @Override
+ public String getFunctionName() {
+ return "withVaultMock";
+ }
+
+ @Nonnull
@Override
public String getDisplayName() {
return "Vault Mock Plugin";
diff --git a/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperTest.java b/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperTest.java
index de9c9548..b8b714ac 100644
--- a/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperTest.java
+++ b/src/test/java/com/datapipe/jenkins/vault/VaultBuildWrapperTest.java
@@ -3,7 +3,6 @@
import com.bettercloud.vault.response.LogicalResponse;
import com.bettercloud.vault.rest.RestResponse;
import com.datapipe.jenkins.vault.configuration.VaultConfiguration;
-import com.datapipe.jenkins.vault.credentials.VaultCredential;
import com.datapipe.jenkins.vault.exception.VaultPluginException;
import com.datapipe.jenkins.vault.model.VaultSecret;
import com.datapipe.jenkins.vault.model.VaultSecretValue;
@@ -106,15 +105,9 @@ public void run(Context context, Run build, EnvVars envVars, PrintStream logger)
provideEnvironmentVariablesFromVault(context, build, envVars);
}
- @Override
- protected VaultCredential retrieveVaultCredentials(Run build) {
- return null;
- }
-
public void verifyCalls() {
verify(mockAccessor, times(2)).init();
verify(mockAccessor, times(2)).read("not/existing", 2);
}
}
-
}
diff --git a/src/test/java/com/datapipe/jenkins/vault/it/VaultConfigurationIT.java b/src/test/java/com/datapipe/jenkins/vault/it/VaultConfigurationIT.java
index bd92e5dd..b9c2707a 100644
--- a/src/test/java/com/datapipe/jenkins/vault/it/VaultConfigurationIT.java
+++ b/src/test/java/com/datapipe/jenkins/vault/it/VaultConfigurationIT.java
@@ -31,7 +31,12 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.jenkinsci.plugins.workflow.actions.ArgumentsAction;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
+import org.jenkinsci.plugins.workflow.flow.FlowExecution;
+import org.jenkinsci.plugins.workflow.graph.FlowNode;
+import org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner;
+import org.jenkinsci.plugins.workflow.graphanalysis.NodeStepTypePredicate;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Before;
@@ -41,8 +46,10 @@
import static hudson.Functions.isWindows;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.collection.IsMapContaining.hasEntry;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
@@ -254,16 +261,13 @@ public void shouldDealWithTokenBasedCredential() throws Exception {
public void shouldUseJenkinsfileConfiguration() throws Exception {
WorkflowJob pipeline = jenkins.createProject(WorkflowJob.class, "Pipeline");
pipeline.setDefinition(new CpsFlowDefinition("node {\n" +
- " wrap([$class: 'VaultBuildWrapperWithMockAccessor', \n" +
- " configuration: [$class: 'VaultConfiguration', \n" +
- " vaultCredentialId: '" + GLOBAL_CREDENTIALS_ID_2 + "', \n"
- +
- " vaultUrl: '" + JENKINSFILE_URL + "'], \n" +
- " vaultSecrets: [\n" +
- " [$class: 'VaultSecret', path: 'secret/path1', secretValues: [\n"
- +
- " [$class: 'VaultSecretValue', envVar: 'envVar1', vaultKey: 'key1']]]]]) {\n"
- +
+ " withVaultMock(\n" +
+ " configuration: [ \n" +
+ " vaultCredentialId: '" + GLOBAL_CREDENTIALS_ID_2 + "', \n" +
+ " vaultUrl: '" + JENKINSFILE_URL + "'], \n" +
+ " vaultSecrets: [\n" +
+ " [path: 'secret/path1', secretValues: [\n" +
+ " [envVar: 'envVar1', vaultKey: 'key1']]]]) {\n" +
" " + getShellString() + " \"echo ${env.envVar1}\"\n" +
" }\n" +
"}", true));
@@ -273,6 +277,13 @@ public void shouldUseJenkinsfileConfiguration() throws Exception {
jenkins.assertBuildStatus(Result.SUCCESS, build);
jenkins.assertLogContains("echo ****", build);
jenkins.assertLogNotContains("some-secret", build);
+
+ FlowExecution execution = build.getExecution();
+ DepthFirstScanner scanner = new DepthFirstScanner();
+ List shellSteps = scanner.filteredNodes(execution, new NodeStepTypePredicate(getShellString()));
+ assertThat(shellSteps, hasSize(1));
+ assertThat(shellSteps.get(0).getAction(ArgumentsAction.class), is(notNullValue()));
+ assertThat(shellSteps.get(0).getAction(ArgumentsAction.class).getArguments(), hasEntry("script", "echo ${envVar1}"));
}
@Test
diff --git a/src/test/java/com/datapipe/jenkins/vault/it/folder/FolderIT.java b/src/test/java/com/datapipe/jenkins/vault/it/folder/FolderIT.java
index 3dbe6e50..8064700a 100644
--- a/src/test/java/com/datapipe/jenkins/vault/it/folder/FolderIT.java
+++ b/src/test/java/com/datapipe/jenkins/vault/it/folder/FolderIT.java
@@ -251,16 +251,13 @@ public void jobInFolderShouldNotBeAbleToAccessCredentialsScopedToAnotherFolder()
public void jenkinsfileShouldOverrideFolderConfig() throws Exception {
WorkflowJob pipeline = folder1.createProject(WorkflowJob.class, "Pipeline");
pipeline.setDefinition(new CpsFlowDefinition("node {\n" +
- " wrap([$class: 'VaultBuildWrapperWithMockAccessor', \n" +
- " configuration: [$class: 'VaultConfiguration', \n" +
- " vaultCredentialId: '" + GLOBAL_CREDENTIALS_ID_2 + "', \n"
- +
- " vaultUrl: '" + JENKINSFILE_URL + "'], \n" +
- " vaultSecrets: [\n" +
- " [$class: 'VaultSecret', path: 'secret/path1', secretValues: [\n"
- +
- " [$class: 'VaultSecretValue', envVar: 'envVar1', vaultKey: 'key1']]]]]) {\n"
- +
+ " withVaultMock(\n" +
+ " configuration: [ \n" +
+ " vaultCredentialId: '" + GLOBAL_CREDENTIALS_ID_2 + "', \n" +
+ " vaultUrl: '" + JENKINSFILE_URL + "'], \n" +
+ " vaultSecrets: [\n" +
+ " [path: 'secret/path1', secretValues: [\n" +
+ " [envVar: 'envVar1', vaultKey: 'key1']]]]) {\n" +
" " + getShellString() + " \"echo ${env.envVar1}\"\n" +
" }\n" +
"}", true));