Skip to content

Commit

Permalink
Added vaultTmpPath option (#133) (#134)
Browse files Browse the repository at this point in the history
* Resolve issue #133
Added vaultTmpPath option to set a different temporary path, rather than the default workspace,for temporary files generated by interacting with the vault

* Test modified to get temp path from system property java.io.tmpdir, maybe fix Windows test

* Fixed test in Windows environment, moved vaultTmpPath 'not presence check' to the right test
  • Loading branch information
bbobbettoS authored Oct 20, 2023
1 parent 2bcf4bb commit ef26df3
Show file tree
Hide file tree
Showing 24 changed files with 188 additions and 14 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ See also [jenkins.io](https://jenkins.io/doc/pipeline/steps/ansible/) documentat
| Inventory inline content | inventoryContent | CLI arg: `-i`: See the Inventory section for additional details. |
| Credentials | credentialsId | The Jenkins credential to use for the SSH connection. See the Authentication section for additional details. |
| Vault Credentials | vaultCredentialsId | CLI arg: `--vault-password-file`: The Jenkins credential to use as the vault credential. See the Vault Credentials section for additional details. |
| Vault temp path | vaultTmpPath | Path where to store temporary vault secrets files, ssh key files, etc... Default is in workspace. |
| sudo | become | CLI arg: `-s` |
| sudo user | becomeUser | CLI arg: `-U` |
| Number of parallel processes | forks | CLI arg: `-f` |
Expand Down Expand Up @@ -123,6 +124,7 @@ for documentation extracted from the online help of the plugin.
| Inventory inline content | inventoryContent | CLI arg: `-i`: See the inventory section for details. |
| Credentials | credentialsId | The Jenkins credential to use for the SSH connection. See the Authentication section for additional details |
| Vault Credentials | vaultCredentialsId | The Jenkins credential to use as the vault credential. See the Vault Credentials section for more details |
| Vault temp path | vaultTmpPath | Path where to store temporary vault secrets files, ssh key files, etc... rkspace. |
| sudo | sudo | CLI arg: `-s` |
| sudo user | sudoUser | CLI arg: `-U` |
| Host subset | limit | CLI arg: `-l` |
Expand Down Expand Up @@ -269,6 +271,7 @@ See also [jenkins.io Pipeline step](https://jenkins.io/doc/pipeline/steps/ansibl
| Action | action | Mandatory. The name of the action to use. Interactive operations such as create, edit, and view are not supported. |
| Vault Credentials | vaultCredentialsId | CLI arg: `--vault-password-file`. The Jenkins credential to use as the vault credential. See the Vault Credentials section for more details |
| New Vault Credentials | newVaultCredentialsId | CLI arg: `--new-vault-password-file`. The Jenkins credential to use as the vault credential. See the Vault Credentials section for more details |
| Vault temp path | vaultTmpPath | Path where to store temporary vault secrets files, ssh key files, etc... Default is in workspace. |
| Content | content | The content to encrypt with the 'encrypt_string' action. |
| Input | input | The file to encrypt with the encrypt actions. |
| Output | output | CLI arg: `--output` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ abstract class AbstractAnsibleInvocation<T extends AbstractAnsibleInvocation<T>>
protected boolean sudo;
protected String sudoUser;
protected StandardCredentials vaultCredentials;
protected FilePath vaultTmpPath;
protected StandardUsernameCredentials credentials;
protected List<ExtraVar> extraVars;
protected String additionalParameters;
Expand Down Expand Up @@ -216,6 +217,11 @@ public T setVaultCredentials(StandardCredentials vaultCredentials) {
return (T) this;
}

public T setVaultTmpPath(FilePath vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
return (T) this;
}

protected ArgumentListBuilder prependPasswordCredentials(ArgumentListBuilder args) {
if (credentials instanceof UsernamePasswordCredentials) {
UsernamePasswordCredentials passwordCredentials = (UsernamePasswordCredentials)credentials;
Expand All @@ -228,12 +234,13 @@ protected ArgumentListBuilder appendCredentials(ArgumentListBuilder args)
throws IOException, InterruptedException
{
if (credentials instanceof SSHUserPrivateKey) {
FilePath tmpPath = vaultTmpPath != null ? vaultTmpPath : ws;
SSHUserPrivateKey privateKeyCredentials = (SSHUserPrivateKey)credentials;
key = Utils.createSshKeyFile(key, ws, privateKeyCredentials, copyCredentialsInWorkspace);
key = Utils.createSshKeyFile(key, tmpPath, privateKeyCredentials, copyCredentialsInWorkspace);
args.add("--private-key").add(key.getRemote().replace("%", "%%"));
args.add("-u").add(privateKeyCredentials.getUsername());
if (privateKeyCredentials.getPassphrase() != null) {
script = Utils.createSshAskPassFile(script, ws, privateKeyCredentials, copyCredentialsInWorkspace);
script = Utils.createSshAskPassFile(script, tmpPath, privateKeyCredentials, copyCredentialsInWorkspace);
environment.put("SSH_ASKPASS", script.getRemote());
// inspired from https://github.com/jenkinsci/git-client-plugin/pull/168
// but does not work with MacOSX
Expand All @@ -252,13 +259,14 @@ protected ArgumentListBuilder appendVaultPasswordFile(ArgumentListBuilder args)
throws IOException, InterruptedException
{
if(vaultCredentials != null){
FilePath tmpPath = vaultTmpPath != null ? vaultTmpPath : ws;
if (vaultCredentials instanceof FileCredentials) {
FileCredentials secretFile = (FileCredentials)vaultCredentials;
vaultPassword = Utils.createVaultPasswordFile(vaultPassword, ws, secretFile);
vaultPassword = Utils.createVaultPasswordFile(vaultPassword, tmpPath, secretFile);
args.add("--vault-password-file").add(vaultPassword.getRemote().replace("%", "%%"));
} else if (vaultCredentials instanceof StringCredentials) {
StringCredentials secretText = (StringCredentials)vaultCredentials;
vaultPassword = Utils.createVaultPasswordFile(vaultPassword, ws, secretText);
vaultPassword = Utils.createVaultPasswordFile(vaultPassword, tmpPath, secretText);
args.add("--vault-password-file").add(vaultPassword.getRemote().replace("%", "%%"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.jenkinsci.plugins.ansible;

import java.io.IOException;
import java.io.File;
import java.util.List;
import javax.annotation.Nonnull;

Expand Down Expand Up @@ -55,6 +56,8 @@ public class AnsibleAdHocCommandBuilder extends Builder implements SimpleBuildSt

public String vaultCredentialsId = null;

public String vaultTmpPath = null;

public final String hostPattern;

/**
Expand Down Expand Up @@ -135,6 +138,11 @@ public void setCredentialsId(String credentialsId) {
public void setVaultCredentialsId(String vaultCredentialsId) {
this.vaultCredentialsId = vaultCredentialsId;
}

@DataBoundSetter
public void setVaultTmpPath(String vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
}

public void setBecome(boolean become) {
this.become = become;
Expand Down Expand Up @@ -215,6 +223,7 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath ws, @Nonnull Launc
invocation.setVaultCredentials(StringUtils.isNotBlank(vaultCredentialsId) ?
CredentialsProvider.findCredentialById(vaultCredentialsId, StandardCredentials.class, run) :
null);
invocation.setVaultTmpPath(StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
invocation.setExtraVars(extraVars);
invocation.setAdditionalParameters(additionalParameters);
invocation.setDisableHostKeyCheck(disableHostKeyChecking);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.jenkinsci.plugins.ansible;

import java.io.IOException;
import java.io.File;
import java.util.List;
import javax.annotation.Nonnull;

Expand Down Expand Up @@ -69,6 +70,8 @@ public class AnsiblePlaybookBuilder extends Builder implements SimpleBuildStep

public String vaultCredentialsId = null;

public String vaultTmpPath = null;

public boolean become = false;

public String becomeUser = "root";
Expand Down Expand Up @@ -165,6 +168,11 @@ public void setVaultCredentialsId(String vaultCredentialsId) {
this.vaultCredentialsId = vaultCredentialsId;
}

@DataBoundSetter
public void setVaultTmpPath(String vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
}

public void setBecome(boolean become) {
this.become = become;
}
Expand Down Expand Up @@ -253,6 +261,7 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull Node node, @Nonnull FilePat
copyCredentialsInWorkspace);
invocation.setVaultCredentials(StringUtils.isNotBlank(vaultCredentialsId) ?
CredentialsProvider.findCredentialById(vaultCredentialsId, StandardCredentials.class, run) : null);
invocation.setVaultTmpPath(StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
invocation.setExtraVars(extraVars);
invocation.setAdditionalParameters(additionalParameters);
invocation.setDisableHostKeyCheck(disableHostKeyChecking);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.jenkinsci.plugins.ansible;

import java.io.IOException;
import java.io.File;
import javax.annotation.Nonnull;

import com.cloudbees.plugins.credentials.CredentialsProvider;
Expand Down Expand Up @@ -53,6 +54,8 @@ public class AnsibleVaultBuilder extends Builder implements SimpleBuildStep

public String newVaultCredentialsId = null;

public String vaultTmpPath = null;

public String content = null;

public String input = null;
Expand Down Expand Up @@ -84,6 +87,11 @@ public void setNewVaultCredentialsId(String newVaultCredentialsId) {
this.newVaultCredentialsId = newVaultCredentialsId;
}

@DataBoundSetter
public void setVaultTmpPath(String vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
}

@DataBoundSetter
public void setContent(String content) {
this.content = content;
Expand Down Expand Up @@ -123,6 +131,7 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull Node node, @Nonnull FilePat
CredentialsProvider.findCredentialById(vaultCredentialsId, StandardCredentials.class, run) : null);
invocation.setNewVaultCredentials(StringUtils.isNotBlank(newVaultCredentialsId) ?
CredentialsProvider.findCredentialById(newVaultCredentialsId, StandardCredentials.class, run) : null);
invocation.setVaultTmpPath(StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
invocation.setContent(content);
invocation.setInput(input);
invocation.setOutput(output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ protected ArgumentListBuilder appendNewVaultPasswordFile(ArgumentListBuilder arg
throws IOException, InterruptedException
{
if(newVaultCredentials != null){
FilePath tmpPath = vaultTmpPath != null ? vaultTmpPath : ws;
if (newVaultCredentials instanceof FileCredentials) {
FileCredentials secretFile = (FileCredentials)newVaultCredentials;
newVaultPassword = Utils.createVaultPasswordFile(newVaultPassword, ws, secretFile);
newVaultPassword = Utils.createVaultPasswordFile(newVaultPassword, tmpPath, secretFile);
args.add("--new-vault-password-file").add(newVaultPassword.getRemote().replace("%", "%%"));
} else if (newVaultCredentials instanceof StringCredentials) {
StringCredentials secretText = (StringCredentials)newVaultCredentials;
newVaultPassword = Utils.createVaultPasswordFile(newVaultPassword, ws, secretText);
newVaultPassword = Utils.createVaultPasswordFile(newVaultPassword, tmpPath, secretText);
args.add("--new-vault-password-file").add(newVaultPassword.getRemote().replace("%", "%%"));
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/jenkinsci/plugins/ansible/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@ class Utils
* @throws IOException
* @throws InterruptedException
*/
static FilePath createSshKeyFile(FilePath key, FilePath workspace, SSHUserPrivateKey credentials, boolean inWorkspace) throws IOException, InterruptedException {
static FilePath createSshKeyFile(FilePath key, FilePath tmpPath, SSHUserPrivateKey credentials, boolean inThisDir) throws IOException, InterruptedException {
StringBuilder sb = new StringBuilder();
List<String> privateKeys = credentials.getPrivateKeys();
for (String s : privateKeys) {
sb.append(s);
}
key = workspace.createTextTempFile("ssh", ".key", sb.toString(), inWorkspace);
key = tmpPath.createTextTempFile("ssh", ".key", sb.toString(), inThisDir);
key.chmod(0400);
return key;
}

static FilePath createSshAskPassFile(FilePath script, FilePath workspace, SSHUserPrivateKey credentials, boolean inWorkspace) throws IOException, InterruptedException {
static FilePath createSshAskPassFile(FilePath script, FilePath tmpPath, SSHUserPrivateKey credentials, boolean inThisDir) throws IOException, InterruptedException {
StringBuilder sb = new StringBuilder();
sb.append("#! /bin/sh\n").append("/bin/echo \"" + Secret.toString(credentials.getPassphrase()) + "\"");
script = workspace.createTextTempFile("ssh", ".sh", sb.toString(), inWorkspace);
script = tmpPath.createTextTempFile("ssh", ".sh", sb.toString(), inThisDir);
script.chmod(0700);
return script;
}
Expand All @@ -65,9 +65,9 @@ static FilePath createSshAskPassFile(FilePath script, FilePath workspace, SSHUse
* @throws IOException
* @throws InterruptedException
*/
static FilePath createVaultPasswordFile(FilePath key, FilePath workspace, FileCredentials credentials) throws IOException, InterruptedException {
static FilePath createVaultPasswordFile(FilePath key, FilePath tmpPath, FileCredentials credentials) throws IOException, InterruptedException {
try (InputStream content = credentials.getContent()) {
key = workspace.createTempFile("vault", ".password");
key = tmpPath.createTempFile("vault", ".password");
key.copyFrom(content);
key.chmod(0400);
}
Expand All @@ -83,8 +83,8 @@ static FilePath createVaultPasswordFile(FilePath key, FilePath workspace, FileCr
* @throws IOException
* @throws InterruptedException
*/
static FilePath createVaultPasswordFile(FilePath key, FilePath workspace, StringCredentials credentials) throws IOException, InterruptedException {
key = workspace.createTextTempFile("vault", ".password", credentials.getSecret().getPlainText(), true);
static FilePath createVaultPasswordFile(FilePath key, FilePath tmpPath, StringCredentials credentials) throws IOException, InterruptedException {
key = tmpPath.createTextTempFile("vault", ".password", credentials.getSecret().getPlainText(), true);
key.chmod(0400);
return key;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public Object ansibleAdHoc(String module, String command, Runnable closure) {
adhoc.setAnsibleName(context.getAnsibleName());
adhoc.setCredentialsId(context.getCredentialsId());
adhoc.setVaultCredentialsId(context.getVaultCredentialsId());
adhoc.setVaultTmpPath(context.getVaultTmpPath());
adhoc.setColorizedOutput(context.isColorizedOutput());
adhoc.setForks(context.getForks());
adhoc.setDisableHostKeyChecking(context.isDisableHostKeyChecking());
Expand All @@ -52,6 +53,7 @@ public Object ansiblePlaybook(String playbook, Runnable closure) {
plbook.setAnsibleName(context.getAnsibleName());
plbook.setCredentialsId(context.getCredentialsId());
plbook.setVaultCredentialsId(context.getVaultCredentialsId());
plbook.setVaultTmpPath(context.getVaultTmpPath());
plbook.setColorizedOutput(context.isColorizedOutput());
plbook.setForks(context.getForks());
plbook.setDisableHostKeyChecking(context.isDisableHostKeyChecking());
Expand Down Expand Up @@ -80,6 +82,7 @@ public Object ansibleVault(Runnable closure) {
vault.setAction(context.getAction());
vault.setVaultCredentialsId(context.getVaultCredentialsId());
vault.setNewVaultCredentialsId(context.getNewVaultCredentialsId());
vault.setVaultTmpPath(context.getVaultTmpPath());
vault.setContent(context.getContent());
vault.setInput(context.getInput());
vault.setOutput(context.getOutput());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class AnsibleContext implements Context {
private String credentialsId;
private String vaultCredentialsId;
private String newVaultCredentialsId;
private String vaultTmpPath = null;
private String content;
private String input;
private String output;
Expand Down Expand Up @@ -82,6 +83,10 @@ public void newVaultCredentialsId(String newVaultCredentialsId) {
this.newVaultCredentialsId = newVaultCredentialsId;
}

public void setVaultTmpPath(String vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
}

public void content(String content) {
this.content = content;
}
Expand Down Expand Up @@ -174,6 +179,10 @@ public String getNewVaultCredentialsId() {
return newVaultCredentialsId;
}

public String getVaultTmpPath() {
return vaultTmpPath;
}

public String getContent() {
return content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class AnsibleAdhocStep extends AbstractStepImpl {
private String installation;
private String credentialsId;
private String vaultCredentialsId;
private String vaultTmpPath = null;
private boolean become = false;
private String becomeUser = "root";
private List<ExtraVar> extraVars = null;
Expand Down Expand Up @@ -113,6 +114,11 @@ public void setVaultCredentialsId(String vaultCredentialsId) {
this.vaultCredentialsId = Util.fixEmptyAndTrim(vaultCredentialsId);
}

@DataBoundSetter
public void setVaultTmpPath(String vaultTmpPath) {
this.vaultTmpPath = vaultTmpPath;
}

@DataBoundSetter
public void setBecome(boolean become) {
this.become = become;
Expand Down Expand Up @@ -189,6 +195,10 @@ public String getVaultCredentialsId() {
return vaultCredentialsId;
}

public String getVaultTmpPath() {
return vaultTmpPath;
}

public boolean isBecome() {
return become;
}
Expand Down Expand Up @@ -305,6 +315,7 @@ protected Void run() throws Exception {
builder.setBecomeUser(step.getBecomeUser());
builder.setCredentialsId(step.getCredentialsId());
builder.setVaultCredentialsId(step.getVaultCredentialsId());
builder.setVaultTmpPath(step.getVaultTmpPath());
builder.setForks(step.getForks());
builder.setExtraVars(step.getExtraVars());
builder.setAdditionalParameters(step.getExtras());
Expand Down
Loading

0 comments on commit ef26df3

Please sign in to comment.