Skip to content
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
31 changes: 31 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,37 @@ output:

![](docs/images/console-after.png)

# Pipeline Support

This plugin provides the `nonStoredPassword` parameter type for Jenkins pipelines, allowing you to define password parameters that are only provided at runtime and not stored in the job configuration. This is ideal for sensitive credentials that should not persist in your pipeline code.

**Declarative Pipeline Example:**
```groovy
pipeline {
agent none
parameters {
nonStoredPassword(name: 'MY_PASSWORD', description: 'Database password')
}
stages {
stage('Deploy') {
steps {
echo 'Using password parameter'
}
}
}
}
```

**Scripted Pipeline Example:**
```groovy
node {
properties([parameters([nonStoredPassword(name: 'API_KEY', description: 'API authentication key')])])
stage('Build') {
echo 'Using API key parameter'
}
}
```

# User guide

First, go to Jenkins' main configuration screen (**Manage Jenkins** \>
Expand Down
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@
<artifactId>workflow-durable-task-step</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>pipeline-stage-step</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-multibranch</artifactId>
<scope>test</scope>
</dependency>
<dependency> <!-- StepConfigTester -->
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import hudson.model.ParameterDefinition;
import hudson.util.Secret;
import org.jvnet.localizer.ResourceBundleHolder;
import org.jenkinsci.Symbol;

public class PasswordParameterDefinition extends ParameterDefinition {

Expand Down Expand Up @@ -68,6 +69,7 @@ public PasswordParameterValue createValue(StaplerRequest2 req, JSONObject formDa
}

@Extension
@Symbol("nonStoredPassword")
public final static class ParameterDescriptorImpl extends ParameterDescriptor {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.michelin.cio.hudson.plugins.passwordparam;

import hudson.model.ParametersAction;
import hudson.util.Secret;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;

@WithJenkins
class DeclarativePipelineTest {

private static final String SCRIPT_WITH_NON_STORED_PASSWORD =
"""
pipeline {
agent none
parameters {
nonStoredPassword(name: 'MY_PASSWORD', description: 'Test password parameter')
}
stages {
stage('Test') {
steps {
echo 'Testing nonStoredPassword parameter'
}
}
}
}
""";

private JenkinsRule j;

@BeforeEach
void beforeEach(JenkinsRule j) throws Exception {
this.j = j;
}

@Test
void test_nonStoredPassword_symbol_in_declarative_pipeline() throws Exception {
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "test-nonStoredPassword");
job.setDefinition(new CpsFlowDefinition(SCRIPT_WITH_NON_STORED_PASSWORD, true));

// First run: defines the parameter for the job
WorkflowRun run1 = job.scheduleBuild2(0).get();
j.waitForCompletion(run1);
j.assertBuildStatusSuccess(run1);

// Second run: accepts the parameter value
PasswordParameterValue paramValue = new PasswordParameterValue(
"MY_PASSWORD", Secret.fromString("testPassword123"), "Test password parameter");
WorkflowRun run2 =
job.scheduleBuild2(0, new ParametersAction(paramValue)).get();
j.waitForCompletion(run2);
j.assertBuildStatusSuccess(run2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.michelin.cio.hudson.plugins.passwordparam;

import hudson.model.ParametersAction;
import hudson.util.Secret;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;

@WithJenkins
class ScriptedPipelineTest {

private static final String SCRIPT_WITH_NON_STORED_PASSWORD =
"""
node {
properties([parameters([nonStoredPassword(name: 'MY_PASSWORD', description: 'Test password parameter')])])
stage('Test') {
echo 'Testing nonStoredPassword parameter in a scripted pipeline'
}
}
""";

private JenkinsRule j;

@BeforeEach
void beforeEach(JenkinsRule j) throws Exception {
this.j = j;
}

@Test
void test_nonStoredPassword_in_scripted_pipeline() throws Exception {
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "test-scripted-nonStoredPassword");
job.setDefinition(new CpsFlowDefinition(SCRIPT_WITH_NON_STORED_PASSWORD, false));

// First run: defines the parameter for the job
WorkflowRun run1 = job.scheduleBuild2(0).get();
j.waitForCompletion(run1);
j.assertBuildStatusSuccess(run1);

// Second run: accepts the parameter value
PasswordParameterValue paramValue = new PasswordParameterValue(
"MY_PASSWORD", Secret.fromString("testPassword123"), "Test password parameter");
WorkflowRun run2 =
job.scheduleBuild2(0, new ParametersAction(paramValue)).get();
j.waitForCompletion(run2);
j.assertBuildStatusSuccess(run2);
}
}