Skip to content

Commit

Permalink
Merge pull request #13 from rundeck-plugins/private-context-options
Browse files Browse the repository at this point in the history
dynamic username and password/passphrase from secure remote option
  • Loading branch information
ltamaster authored Jan 3, 2020
2 parents 0405068 + c8cba87 commit 4fdcfe8
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 9 deletions.
105 changes: 105 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,55 @@ The plugin can be configured as a default node executor and file copier for a Pr

Also, you can define the configuration at Node Level, setting the node-executor and file-copier attributes.

Settings:

* **authentication**: Authentication.Authentication SSH Type (password or privatekey). A node attribute named ssh-authentication will override this value.
* **ssh_key_storage_path**: SSH key Storage Path. Optional storage path for ssh-key saved on the key storage. Can contain property references to node attributes. A node attribute named ssh-key-storage-path will override this value.
* **ssh_key_passphrase_storage_path**: SSH key Passphrase Storage Path. Optional storage path for ssh-key Passphrase. Can contain property references to node attributes. A node attribute named ssh-key-passphrase-storage-path will override this value.
* **ssh_password_storage_path**: SSH Password Storage Path. Optional storage path for ssh-key Passphrase. Can contain property references to node attributes. A node attribute named ssh-key-passphrase-storage-path will override this value.
* **ssh_options**: SSH Custom Options. Add custom settings to SSH connection. Eg: -o ConnectTimeout=10. A node attribute named ssh-options will override this value.
* **ssh_password_option**: SSH Password with a Job Option. Get the password form a job option (eg: `option.password`). The Job must define a Secure Remote Authentication Option to prompt the user for the password before execution. A node attribute named ssh-password-option will override this value.
* **ssh_key_passphrase_option**: SSH Passphrase with a Job Option. Get the passphrase form a job option (eg: `option.passphrase`). The Job must define a Secure Remote Authentication Option to prompt the user for the passphrase before execution. A node attribute named ssh-key-passphrase-option will override this value.

## Dynamic Username

You can use a dynamic username, defining the username value( `username` node attribute) from the job runner or from an input option.

* ${job.username} - uses the username of the user executing the Rundeck execution.
* ${option.username} - uses the value of a job option named "username".


## Password or Passphrase from Secure Remote Authentication

You can pass Password or Passphrase from a Job's Secure Remote Authentication Option.

* ssh-password-option = "option.NAME" where NAME is the name of the Job's Secure Remote Authentication Option.
* ssh-key-passphrase-option = "option.NAME" where NAME is the name of the Job's Secure Remote Authentication Option.


## Examples

Default project properties examples:

```
service.FileCopier.default.provider=ssh-copier
service.NodeExecutor.default.provider=ssh-exec
project.plugin.NodeExecutor.ssh-exec.authentication=password
project.plugin.NodeExecutor.ssh-exec.ssh_key_passphrase_option=option.passphrase
project.plugin.NodeExecutor.ssh-exec.ssh_options=-o ConnectTimeout\=10
project.plugin.NodeExecutor.ssh-exec.ssh_password_option=option.password
project.plugin.NodeExecutor.ssh-exec.ssh_password_storage_path=keys/node/user.password
project.plugin.FileCopier.ssh-copier.authentication=password
project.plugin.FileCopier.ssh-copier.ssh_key_passphrase_option=option.passphrase
project.plugin.FileCopier.ssh-copier.ssh_options=-o ConnectTimeout\=10
project.plugin.FileCopier.ssh-copier.ssh_password_option=option.password
project.plugin.FileCopier.ssh-copier.ssh_password_storage_path=keys/node/user.password
```


Basic node definition (overwrite the default settings)
```
<node name="RemoteNode"
description="Remote SSH Node"
Expand All @@ -43,3 +92,59 @@ Also, you can define the configuration at Node Level, setting the node-executor
ssh-password-storage-path ="keys/node/user.password"
ssh-options="-o ConnectTimeout=5000"/>
```

Using password from option Secure Remote Authentication
```
<node name="RemoteNode"
description="Remote SSH Node"
tags="vagrant"
hostname="192.168.0.1"
osArch="Linux"
osFamily="x86_64"
osName="Linux"
osVersion="10.12.6"
username="vagrant"
node-executor="ssh-exec"
file-copier="ssh-copier"
ssh-authentication="password"
ssh-password-option="option.password"
ssh-options="-o ConnectTimeout=5000"/>
```
*a Secure Remote Authentication Option must be created on the job

Using dynamic username
```
<node name="RemoteNode"
description="Remote SSH Node"
tags="vagrant"
hostname="192.168.0.1"
osArch="Linux"
osFamily="x86_64"
osName="Linux"
osVersion="10.12.6"
username="${job.username}"
node-executor="ssh-exec"
file-copier="ssh-copier"
ssh-authentication="password"
ssh-password-option="option.password"
ssh-options="-o ConnectTimeout=5000"/>
```

Using dynamic username from job option
```
<node name="RemoteNode"
description="Remote SSH Node"
tags="vagrant"
hostname="192.168.0.1"
osArch="Linux"
osFamily="x86_64"
osName="Linux"
osVersion="10.12.6"
username="${option.username}"
node-executor="ssh-exec"
file-copier="ssh-copier"
ssh-authentication="password"
ssh-password-option="option.password"
ssh-options="-o ConnectTimeout=5000"/>
```
*a option called `username` must be added to the job
38 changes: 37 additions & 1 deletion contents/ssh-copy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ SSHOPTS="-p -P $PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

authentication=$RD_CONFIG_AUTHENTICATION

if [[ -n "${RD_CONFIG_SSH_PASSWORD_OPTION:-}" ]] ; then
option="$(sed 's/option.//g' <<<$RD_CONFIG_SSH_PASSWORD_OPTION)"
rd_secure_password=$(echo "RD_PRIVATE_$option" | awk '{ print toupper($0) }')
fi

if [[ -n "${RD_CONFIG_SSH_KEY_PASSPHRASE_OPTION:-}" ]] ; then
option="$(sed 's/option.//g' <<<$RD_CONFIG_SSH_KEY_PASSPHRASE_OPTION)"
rd_secure_passphrase=$(echo "RD_PRIVATE_$option" | awk '{ print toupper($0) }')
fi

if [[ "$RD_NODE_USERNAME" =~ \$\{(.*)\} ]]; then
username=${BASH_REMATCH[1]}
if [[ "job.username" == "$username" ]] ; then
USER=$RD_JOB_USERNAME
fi

if [[ "option.username" == "$username" ]] ; then
USER=$RD_OPTION_USERNAME
fi
fi

if [[ "privatekey" == "$authentication" ]] ; then

Expand All @@ -65,6 +85,16 @@ if [[ "privatekey" == "$authentication" ]] ; then
fi
RUNSCP="scp $SSHOPTS $FILE $USER@$HOST:$DIR"

if [[ -n "${!rd_secure_passphrase}" ]]; then
mkdir -p "/tmp/.ssh-exec"
SSH_KEY_PASSPHRASE_STORAGE_PATH=$(mktemp "/tmp/.ssh-exec/ssh-passfile.$USER@$HOST.XXXXX")
echo "${!rd_secure_passphrase}" > "$SSH_PASS_STORAGE_PATH"

RUNSSH="sshpass -P passphrase -f $SSH_KEY_PASSPHRASE_STORAGE_PATH ssh $SSHOPTS $USER@$HOST $CMD"

trap 'rm "$SSH_KEY_PASSPHRASE_STORAGE_PATH"' EXIT
fi

## add PASSPHRASE for key
if [[ -n "${RD_CONFIG_SSH_KEY_PASSPHRASE_STORAGE_PATH:-}" ]]
then
Expand All @@ -81,7 +111,13 @@ fi
if [[ "password" == "$authentication" ]] ; then
mkdir -p "/tmp/.ssh-exec"
SSH_PASS_STORAGE_PATH=$(mktemp "/tmp/.ssh-exec/ssh-passfile.$USER@$HOST.XXXXX")
echo "$RD_CONFIG_SSH_PASSWORD_STORAGE_PATH" > "$SSH_PASS_STORAGE_PATH"

if [[ -n "${!rd_secure_password}" ]]; then
echo "${!rd_secure_password}" > "$SSH_PASS_STORAGE_PATH"
else
echo "$RD_CONFIG_SSH_PASSWORD_STORAGE_PATH" > "$SSH_PASS_STORAGE_PATH"
fi

RUNSCP="sshpass -f $SSH_PASS_STORAGE_PATH scp $SSHOPTS $FILE $USER@$HOST:$DIR"

trap 'rm "$SSH_PASS_STORAGE_PATH"' EXIT
Expand Down
44 changes: 42 additions & 2 deletions contents/ssh-exec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ SSHOPTS="-p $PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o

authentication=$RD_CONFIG_AUTHENTICATION


if [[ -n "${RD_CONFIG_SSH_PASSWORD_OPTION:-}" ]] ; then
option="$(sed 's/option.//g' <<<$RD_CONFIG_SSH_PASSWORD_OPTION)"
rd_secure_password=$(echo "RD_PRIVATE_$option" | awk '{ print toupper($0) }')
fi

if [[ -n "${RD_CONFIG_SSH_KEY_PASSPHRASE_OPTION:-}" ]] ; then
option="$(sed 's/option.//g' <<<$RD_CONFIG_SSH_KEY_PASSPHRASE_OPTION)"
rd_secure_passphrase=$(echo "RD_PRIVATE_$option" | awk '{ print toupper($0) }')
fi


if [[ "$RD_NODE_USERNAME" =~ \$\{(.*)\} ]]; then
username=${BASH_REMATCH[1]}
if [[ "job.username" == "$username" ]] ; then
USER=$RD_JOB_USERNAME
fi

if [[ "option.username" == "$username" ]] ; then
USER=$RD_OPTION_USERNAME
fi
fi


if [[ "privatekey" == "$authentication" ]] ; then

#use ssh-keyfile node attribute from env vars
Expand All @@ -60,6 +84,16 @@ if [[ "privatekey" == "$authentication" ]] ; then
fi
RUNSSH="ssh $SSHOPTS $USER@$HOST $CMD"

if [[ -n "${!rd_secure_passphrase}" ]]; then
mkdir -p "/tmp/.ssh-exec"
SSH_KEY_PASSPHRASE_STORAGE_PATH=$(mktemp "/tmp/.ssh-exec/ssh-passfile.$USER@$HOST.XXXXX")
echo "${!rd_secure_passphrase}" > "$SSH_PASS_STORAGE_PATH"

RUNSSH="sshpass -P passphrase -f $SSH_KEY_PASSPHRASE_STORAGE_PATH ssh $SSHOPTS $USER@$HOST $CMD"

trap 'rm "$SSH_KEY_PASSPHRASE_STORAGE_PATH"' EXIT
fi

## add PASSPHRASE for key
if [[ -n "${RD_CONFIG_SSH_KEY_PASSPHRASE_STORAGE_PATH:-}" ]]
then
Expand All @@ -74,15 +108,21 @@ if [[ "privatekey" == "$authentication" ]] ; then
fi

if [[ "password" == "$authentication" ]] ; then

mkdir -p "/tmp/.ssh-exec"
SSH_PASS_STORAGE_PATH=$(mktemp "/tmp/.ssh-exec/ssh-passfile.$USER@$HOST.XXXXX")
echo "$RD_CONFIG_SSH_PASSWORD_STORAGE_PATH" > "$SSH_PASS_STORAGE_PATH"

if [[ -n "${!rd_secure_password}" ]]; then
echo "${!rd_secure_password}" > "$SSH_PASS_STORAGE_PATH"
else
echo "$RD_CONFIG_SSH_PASSWORD_STORAGE_PATH" > "$SSH_PASS_STORAGE_PATH"
fi

RUNSSH="sshpass -f $SSH_PASS_STORAGE_PATH ssh $SSHOPTS $USER@$HOST $CMD"

trap 'rm "$SSH_PASS_STORAGE_PATH"' EXIT
fi


#if ssh-test is set to "true", do a dry run
if [[ "true" == "$RD_CONFIG_DRY_RUN" ]] ; then
echo "[ssh-exec]" "$RUNSSH"
Expand Down
53 changes: 47 additions & 6 deletions plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
name: openssh node execution services
rundeckPluginVersion: 1.2
author: Alex Honor
date: 08/14/2015
version: 1.0
rundeckPluginVersion: 2.0
author: "@author@"
date: "@date@"
version: "@version@"
url: "@url@"
description: "OpenSSH Node Executor"
rundeckCompatibilityVersion: "3.2.x"
targetHostCompatibility: "all"
license: "Apache 2.0"
tags:
- script
- NodeExecutor
- FileCopier
providers:
- name: ssh-exec
service: NodeExecutor
Expand Down Expand Up @@ -72,7 +81,23 @@ providers:
description: "Add custom settings to SSH connection. Eg: -o ConnectTimeout=10. A node attribute named ssh-options will override this value."
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-options"
instance-scope-node-attribute: "ssh-options"
- name: ssh_password_option
title: SSH Password with a Job Option
type: String
required: false
description: "Get the password form a job option (eg: `option.password`). The Job must define a Secure Remote Authentication Option to prompt the user for the password before execution. A node attribute named ssh-password-option will override this value"
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-password-option"
- name: ssh_key_passphrase_option
title: SSH Passphrase with a Job Option
type: String
required: false
description: "Get the passphrase form a job option (eg: `option.passphrase`). The Job must define a Secure Remote Authentication Option to prompt the user for the passphrase before execution. A node attribute named ssh-key-passphrase-option will override this value"
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-key-passphrase-option"
- name: ssh-copier
service: FileCopier
title: 'openssh / file-copier'
Expand Down Expand Up @@ -141,4 +166,20 @@ providers:
description: "Add custom settings to SSH connection. Eg: -o ConnectTimeout=10. A node attribute named ssh-options will override this value."
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-options"
instance-scope-node-attribute: "ssh-options"
- name: ssh_password_option
title: SSH Password with a Job Option
type: String
required: false
description: "Get the password form a job option (eg: `option.password`). The Job must define a Secure Remote Authentication Option to prompt the user for the password before execution. A node attribute named ssh-password-option will override this value"
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-password-option"
- name: ssh_key_passphrase_option
title: SSH Passphrase with a Job Option
type: String
required: false
description: "Get the passphrase form a job option (eg: `option.passphrase`). The Job must define a Secure Remote Authentication Option to prompt the user for the passphrase before execution. A node attribute named ssh-key-passphrase-option will override this value"
scope: Instance
renderingOptions:
instance-scope-node-attribute: "ssh-key-passphrase-option"

0 comments on commit 4fdcfe8

Please sign in to comment.