Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUN-2626: fix when master password configured #375

Merged
merged 6 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,29 @@ import org.testcontainers.spock.Testcontainers
class BasicIntegrationSpec extends BaseTestConfiguration {

static String PROJ_NAME = 'ansible-test'
static String DEFAULT_NODE_NAME = "ssh-node"

def setupSpec() {
startCompose()
configureRundeck(PROJ_NAME)
configureRundeck(PROJ_NAME, DEFAULT_NODE_NAME)
}

def "ansible node executor with ssh password"(){
setup:
String ansibleNodeExecutorProjectName = "sshPasswordProject"
String nodeName = "ssh-node-password"
configureRundeck(ansibleNodeExecutorProjectName, nodeName)
when:
def jobId = "f04f17a9-77cf-4feb-aec1-889a3de0f5ae"
JobRun request = new JobRun()
request.loglevel = 'INFO'
def result = client.apiCall {api-> api.runJob(jobId, request)}
def executionState = waitForJob(result.id)
def logs = getLogs(result.id)
Map<String, Integer> ansibleNodeExecutionStatus = TestUtil.getAnsibleNodeResult(logs)
then:
executionState!=null
executionState.getExecutionState()=="SUCCEEDED"
}

def "test simple inline playbook"(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import org.testcontainers.spock.Testcontainers
class EncryptedInventorySpec extends BaseTestConfiguration {

static String PROJ_NAME = 'ansible-encrypted-inventory'
static String DEFAULT_NODE_NAME = "ssh-node"

def setupSpec() {
startCompose()
configureRundeck(PROJ_NAME)
configureRundeck(PROJ_NAME, DEFAULT_NODE_NAME)
}

def "test encrypted inventory"(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import org.testcontainers.spock.Testcontainers
class PluginGroupIntegrationSpec extends BaseTestConfiguration {

static String PROJ_NAME = 'ansible-plugin-group-test'
static String DEFAULT_NODE_NAME = "ssh-node"

def setupSpec() {
startCompose()
configureRundeck(PROJ_NAME)
configureRundeck(PROJ_NAME, DEFAULT_NODE_NAME)
}

def "test simple inline playbook"(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class BaseTestConfiguration extends Specification{
return logs
}

def configureRundeck(String projectName){
def configureRundeck(String projectName, String nodeName){

//add private key
RequestBody requestBody = RequestBody.create(new File("src/test/resources/docker/keys/id_rsa"), Client.MEDIA_TYPE_OCTET_STREAM)
Expand Down Expand Up @@ -125,15 +125,18 @@ class BaseTestConfiguration extends Specification{
api.importProjectArchive(projectName, "preserve", true, true, true, true, true, true, true, [:], body)
)

//wait for node to be available
waitForNodeAvailability(projectName, nodeName)

}

def waitForNodeAvailability(String projectName, String nodeName){
def result = client.apiCall {api-> api.listNodes(projectName,".*")}
def count =0

while(result.get("ssh-node")==null && count<5){
while(result.get(nodeName)==null && count<5){
sleep(2000)
result = client.apiCall {api-> api.listNodes(projectName,".*")}
count++
}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[defaults]
inventory = /home/rundeck/ansible/inventory.ini
vault_password_file=/home/rundeck/ansible/mp.pass
host_key_checking = False
interpreter_python=/usr/bin/python3
show_custom_stats = False
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[servers]
ssh-node ansible_host=ssh-node
ssh-node-password ansible_host=ssh-node ansible_connection=ssh ansible_user=rundeck ansible_ssh_pass=testpassword123
1 change: 1 addition & 0 deletions functional-test/src/test/resources/docker/ansible/mp.pass
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123456
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ssh-node-password:
nodename: ssh-node-password
hostname: ssh-node
osFamily: Linux
username: rundeck
tags: ''
11 changes: 6 additions & 5 deletions functional-test/src/test/resources/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ services:
build:
context: node
environment:
NODE_USER_PASSWORD: ${NODE_USER_PASSWORD:-rundeck}
NODE_USER_PASSWORD: testpassword123
networks:
- rundeck
ports:
- "2222:22"
volumes:
- ${PWD}/keys:/configuration:rw
- ./keys:/configuration:rw

rundeck:
build:
context: rundeck
args:
RUNDECK_IMAGE: ${RUNDECK_IMAGE:-rundeck/rundeck:SNAPSHOT}
RUNDECK_IMAGE: rundeck/rundeck:SNAPSHOT
image: rundeck-ansible-plugin:latest
command: "-Dansible.debug=false"
environment:
Expand All @@ -30,9 +30,10 @@ services:
networks:
- rundeck
ports:
- "4440"
- "4440:4440"
ronaveva marked this conversation as resolved.
Show resolved Hide resolved
volumes:
- ${PWD}/ansible:/home/rundeck/ansible:rw
- ./ansible:/home/rundeck/ansible:rw
- ./ansible/ansible.cfg:/etc/ansible/ansible.cfg:rw

volumes:
rundeck-data:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
by:
urn: project:sshPasswordProject
for:
storage:
- match:
path: 'keys/project/sshPasswordProject/.*'
allow: [read]
description: Allow access to key storage
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#Mon Jul 08 21:50:51 GMT 2024
#edit below
project.ansible-binaries-dir-path=/usr/local/bin/
project.ansible-config-file-path=/home/rundeck/ansible/ansible.cfg
project.ansible-executable=/bin/bash
project.ansible-generate-inventory=true
project.ansible-ssh-auth-type=password
project.ansible-ssh-passphrase-option=option.password
project.ansible-ssh-password-storage-path=keys/project/sshPasswordProject/ssh-node.pass
project.ansible-ssh-user=rundeck
project.description=
project.disable.executions=false
project.disable.schedule=false
project.execution.history.cleanup.batch=500
project.execution.history.cleanup.enabled=false
project.execution.history.cleanup.retention.days=60
project.execution.history.cleanup.retention.minimum=50
project.execution.history.cleanup.schedule=0 0 0 1/1 * ? *
project.jobs.gui.groupExpandLevel=1
project.label=
project.later.executions.disable=false
project.later.executions.enable=false
project.later.schedule.disable=false
project.later.schedule.enable=false
project.name=sshPasswordProject
project.nodeCache.enabled=false
project.nodeCache.firstLoadSynch=true
project.output.allowUnsanitized=false
project.retry-counter=3
project.ssh-authentication=privateKey
resources.source.1.type=local
resources.source.2.config.file=/home/rundeck/ansible/rundeckNodes.yaml
resources.source.2.config.format=resourceyaml
resources.source.2.config.generateFileAutomatically=true
resources.source.2.config.writeable=true
resources.source.2.type=file
service.FileCopier.default.provider=sshj-scp
service.NodeExecutor.default.provider=com.batix.rundeck.plugins.AnsibleNodeExecutor
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description>it targets a single ansible node</description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>f04f17a9-77cf-4feb-aec1-889a3de0f5ae</id>
<loglevel>INFO</loglevel>
<name>simpleCommand</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>name: ssh-node-password </filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>whoami</exec>
</command>
</sequence>
<uuid>f04f17a9-77cf-4feb-aec1-889a3de0f5ae</uuid>
</job>
</joblist>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.*;
import com.rundeck.plugins.ansible.ansible.AnsibleException;

@Data
@Builder
Expand Down Expand Up @@ -56,7 +57,7 @@ public boolean checkAnsibleVault() {
}

public String encryptVariable(String key,
String content ) throws IOException {
String content ) throws IOException, AnsibleException, InterruptedException {

List<String> procArgs = new ArrayList<>();
String ansibleCommand = ANSIBLE_VAULT_COMMAND;
Expand All @@ -65,8 +66,8 @@ public String encryptVariable(String key,
}
procArgs.add(ansibleCommand);
procArgs.add("encrypt_string");
procArgs.add("--vault-id");
procArgs.add("internal-encrypt@" + vaultPasswordScriptFile.getAbsolutePath());
procArgs.add("--encrypt-vault-id");
procArgs.add("internal-encrypt");

if(debug){
System.out.println("encryptVariable " + key + ": " + procArgs);
Expand All @@ -81,6 +82,7 @@ public String encryptVariable(String key,

Map<String, String> env = new HashMap<>();
env.put("VAULT_ID_SECRET", masterPassword);
env.put("ANSIBLE_VAULT_IDENTITY_LIST", "internal-encrypt@" + vaultPasswordScriptFile.getAbsolutePath());

Process proc = null;

Expand All @@ -97,29 +99,27 @@ public String encryptVariable(String key,
final InputStream stdoutInputStream = proc.getInputStream();
final BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdoutInputStream));

int exitCode = proc.waitFor();

String line1 = null;
boolean capture = false;
while ((line1 = stdoutReader.readLine()) != null) {
if (line1.toLowerCase().contains("!vault")) {
if (line1.toLowerCase().contains("!vault") || exitCode != 0) {
capture = true;
}
if (capture) {
stringBuilder.append(line1).append("\n");
}
}

int exitCode = proc.waitFor();

if (exitCode != 0) {
System.err.println("ERROR: encryptFileAnsibleVault:" + procArgs);
return null;
throw new AnsibleException(stringBuilder.toString(), AnsibleException.AnsibleFailureReason.IOFailure);
}
return stringBuilder.toString();

} catch (Exception e) {
System.err.println("error encryptFileAnsibleVault file " + e.getMessage());
return null;
} finally {
} catch(Exception e) {
throw e;
}finally {
// Make sure to always cleanup on failure and success
if (proc != null) {
proc.destroy();
Expand Down
Loading