Skip to content

Commit

Permalink
Merge pull request #24 from rundeck-plugins/RUN-1537
Browse files Browse the repository at this point in the history
RUN-1537:  report the list of keys
  • Loading branch information
ltamaster authored Jun 6, 2023
2 parents 96d5980 + 963414b commit cdc0eb9
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 25 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ configurations{
}

dependencies {
implementation 'org.rundeck:rundeck-core:4.13.0-20230515'
implementation 'org.rundeck:rundeck-core:4.14.0-rc1-20230606'

pluginLibs group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.14'
pluginLibs group: 'com.google.code.gson', name: 'gson', version:'2.10.1'
Expand Down
17 changes: 4 additions & 13 deletions src/main/java/edu/ohio/ais/rundeck/HttpBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
import edu.ohio.ais.rundeck.util.OAuthClient;
import edu.ohio.ais.rundeck.util.SecretBundleUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
Expand Down Expand Up @@ -331,25 +332,15 @@ String getAuthHeader(PluginStepContext pluginStepContext, Map<String, Object> o

if(options.containsKey("password") ){
String passwordRaw = options.containsKey("password") ? options.get("password").toString() : null;

//to avid the test error add a try-catch
//if it didn't find the key path, it will use the password directly
try {
ResourceMeta contents = pluginStepContext.getExecutionContext().getStorageTree().getResource(passwordRaw).getContents();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

contents.writeContent(byteArrayOutputStream);

password = new String(byteArrayOutputStream.toByteArray());
} catch (Exception e) {
password=null;
byte[] content = SecretBundleUtil.getStoragePassword(pluginStepContext.getExecutionContext(),passwordRaw );
if(content!=null){
password = new String(content);
}

if(password==null){
password=passwordRaw;
}

}

if(authentication.equals(AUTH_BASIC)) {
Expand Down
20 changes: 16 additions & 4 deletions src/main/java/edu/ohio/ais/rundeck/HttpWorkflowNodeStepPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.core.dispatcher.DataContextUtils;
import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.proxy.ProxySecretBundleCreator;
import com.dtolabs.rundeck.core.execution.proxy.SecretBundle;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepException;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepFailureReason;
import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepException;
Expand All @@ -13,18 +16,17 @@
import com.dtolabs.rundeck.plugins.step.NodeStepPlugin;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import edu.ohio.ais.rundeck.util.OAuthClient;
import edu.ohio.ais.rundeck.util.SecretBundleUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ByteArrayEntity;

import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;

@Plugin(name = HttpWorkflowNodeStepPlugin.SERVICE_PROVIDER_NAME, service = ServiceNameConstants.WorkflowNodeStep)
public class HttpWorkflowNodeStepPlugin implements NodeStepPlugin, Describable {
public class HttpWorkflowNodeStepPlugin implements NodeStepPlugin, Describable, ProxySecretBundleCreator {
public static final String SERVICE_PROVIDER_NAME = "edu.ohio.ais.rundeck.HttpWorkflowNodeStepPlugin";

/**
Expand Down Expand Up @@ -134,4 +136,14 @@ public void executeNodeStep(PluginStepContext context, Map<String, Object> confi
}

}

@Override
public SecretBundle prepareSecretBundleWorkflowNodeStep(ExecutionContext context, INodeEntry node, Map<String, Object> configuration) {
return SecretBundleUtil.getSecrets(context, configuration);
}

@Override
public List<String> listSecretsPathWorkflowNodeStep(ExecutionContext context, INodeEntry node, Map<String, Object> configuration) {
return SecretBundleUtil.getListSecrets(configuration);
}
}
21 changes: 16 additions & 5 deletions src/main/java/edu/ohio/ais/rundeck/HttpWorkflowStepPlugin.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package edu.ohio.ais.rundeck;

import com.dtolabs.rundeck.core.dispatcher.DataContextUtils;
import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.proxy.ProxySecretBundleCreator;
import com.dtolabs.rundeck.core.execution.proxy.SecretBundle;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepException;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepFailureReason;
import com.dtolabs.rundeck.core.plugins.Plugin;
Expand All @@ -11,23 +14,22 @@
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.dtolabs.rundeck.plugins.step.StepPlugin;
import edu.ohio.ais.rundeck.util.OAuthClient;
import edu.ohio.ais.rundeck.util.SecretBundleUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ByteArrayEntity;

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;


/**
* Main implementation of the plugin. This will handle fetching
* tokens when they're expired and sending the appropriate request.
*/
@Plugin(name = HttpWorkflowStepPlugin.SERVICE_PROVIDER_NAME, service = ServiceNameConstants.WorkflowStep)
public class HttpWorkflowStepPlugin implements StepPlugin, Describable {
public class HttpWorkflowStepPlugin implements StepPlugin, Describable, ProxySecretBundleCreator {

/**
* Maximum number of attempts with which to try the request.
Expand Down Expand Up @@ -63,7 +65,6 @@ public Description getDescription() {
return new HttpDescription(SERVICE_PROVIDER_NAME, "HTTP Request Step", "Performs an HTTP request with or without authentication").getDescription();
}


@Override
public void executeStep(PluginStepContext pluginStepContext, Map<String, Object> options) throws StepException {
PluginLogger log = pluginStepContext.getLogger();
Expand Down Expand Up @@ -131,4 +132,14 @@ public void executeStep(PluginStepContext pluginStepContext, Map<String, Object>
builder.doRequest(options, request.build(), 1);
}

@Override
public SecretBundle prepareSecretBundleWorkflowStep(ExecutionContext context, Map<String, Object> configuration) {
return SecretBundleUtil.getSecrets(context, configuration);
}

@Override
public List<String> listSecretsPathWorkflowStep(ExecutionContext context, Map<String, Object> configuration) {
return SecretBundleUtil.getListSecrets(configuration);
}

}
49 changes: 49 additions & 0 deletions src/main/java/edu/ohio/ais/rundeck/util/SecretBundleUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package edu.ohio.ais.rundeck.util;

import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.proxy.DefaultSecretBundle;
import com.dtolabs.rundeck.core.execution.proxy.SecretBundle;
import com.dtolabs.rundeck.core.storage.ResourceMeta;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SecretBundleUtil {

public static List<String> getListSecrets(Map<String, Object> configuration) {
List<String> listSecretPath = new ArrayList<>();
String passwordPath = (String)configuration.get("password");

if(passwordPath!=null && !passwordPath.isEmpty() ){
listSecretPath.add(passwordPath);
}

return listSecretPath;
}

public static SecretBundle getSecrets(ExecutionContext context, Map<String, Object> configuration){
DefaultSecretBundle secretBundle = new DefaultSecretBundle();
String passwordPath = (String)configuration.get("password");

if(passwordPath!=null && !passwordPath.isEmpty() ){
byte[] content = SecretBundleUtil.getStoragePassword(context,passwordPath);
if(content!=null){
secretBundle.addSecret(passwordPath, content);
}
}
return secretBundle;
}

public static byte[] getStoragePassword(ExecutionContext context, String path){
try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
ResourceMeta contents = context.getStorageTree().getResource(path).getContents();
contents.writeContent(byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
context.getExecutionLogger().log(0, e.getMessage());
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,12 @@ public void setUp() {
.willReturn(WireMock.aResponse().withFixedDelay(SLOW_TIMEOUT).withStatus(200)));

node = Mockito.mock(INodeEntry.class);
pluginContext = Mockito.mock(PluginStepContext.class);
pluginLogger = Mockito.mock(PluginLogger.class);
pluginContext = Mockito.mock(PluginStepContext.class);
ExecutionContext executionContext = Mockito.mock(ExecutionContext.class);
when(executionContext.getExecutionLogger()).thenReturn(pluginLogger);
when(pluginContext.getLogger()).thenReturn(pluginLogger);
when(pluginContext.getExecutionContext()).thenReturn(executionContext);

dataContext =new HashMap<>();
when(pluginContext.getDataContext()).thenReturn(dataContext);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.ohio.ais.rundeck;

import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.workflow.steps.PluginStepContextImpl;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepException;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepFailureReason;
Expand All @@ -19,6 +20,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;

public class HttpWorkflowStepPluginTest {
protected static final String REMOTE_URL = "/trigger";
Expand Down Expand Up @@ -153,7 +155,10 @@ public void setUp() {

pluginContext = Mockito.mock(PluginStepContext.class);
pluginLogger = Mockito.mock(PluginLogger.class);
Mockito.when(pluginContext.getLogger()).thenReturn(pluginLogger);
ExecutionContext executionContext = Mockito.mock(ExecutionContext.class);
when(executionContext.getExecutionLogger()).thenReturn(pluginLogger);
when(pluginContext.getLogger()).thenReturn(pluginLogger);
when(pluginContext.getExecutionContext()).thenReturn(executionContext);

dataContext =new HashMap<>();
Mockito.when(pluginContext.getDataContext()).thenReturn(dataContext);
Expand Down

0 comments on commit cdc0eb9

Please sign in to comment.