Skip to content

Commit

Permalink
Merge pull request #1 from farmdawgnation/authentication-configuration
Browse files Browse the repository at this point in the history
Permit populating kms creds from config
  • Loading branch information
farmdawgnation authored Feb 8, 2021
2 parents 6ec3b67 + 4ea2834 commit 7e93e36
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 22 deletions.
27 changes: 17 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,23 @@ If I get interest in a version of the JAR that uses a _shared_ AWS SDK, I'm happ
That would work better for folks who already package the AWS SDK in Rundeck's classpath in its
entirety.

## Authentication

If you're running Rundeck within AWS, you canuse instance roles to assign the
proper permissions for Rundeck to access KMS for the use of this plugin.

I still need to add code to handle passing these values in from configuration.

For testing purposes, you can also set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
as with any other AWS library, though there are likely reasons this ins't good
in production.
## Configuration

The following in your `rundeck-config.properties` will configure this plugin:

```
rundeck.storage.converter.1.type=rundeck-kms-plugin
rundeck.storage.converter.1.path=keys
rundeck.storage.converter.1.config.keyArn=<ARN TO YOUR KEY>
rundeck.storage.converter.1.config.accessKeyId=<ACCESS KEY ID>
rundeck.storage.converter.1.config.secretAccessKey=<SECRET ACCESS KEY>
rundeck.config.storage.converter.1.type=rundeck-kms-plugin
rundeck.config.storage.converter.1.path=projects
rundeck.config.storage.converter.1.config.keyArn=<ARN TO YOUR KEY>
rundeck.config.storage.converter.1.config.accessKeyId=<ACCESS KEY ID>
rundeck.config.storage.converter.1.config.secretAccessKey=<SECRET ACCESS KEY>
```

# About the Author

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ void testIgnoresNonKmsData() throws IOException {
var exampleMessage = "Hello, KMS!";
var sut = new KmsConverterPlugin();
sut.keyArn = System.getenv("KMS_KEY_ARN");
sut.accessKeyId = System.getenv("AWS_ACCESS_KEY_ID");
sut.secretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY");

if (sut.keyArn == null) {
throw new RuntimeException("Env var KMS_KEY_ARN required for integration tests");
Expand Down Expand Up @@ -63,6 +65,8 @@ void testEncryptDecrypt() throws IOException {
var exampleMessage = "Hello, KMS!";
var sut = new KmsConverterPlugin();
sut.keyArn = System.getenv("KMS_KEY_ARN");
sut.accessKeyId = System.getenv("AWS_ACCESS_KEY_ID");
sut.secretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY");

if (sut.keyArn == null) {
throw new RuntimeException("Env var KMS_KEY_ARN required for integration tests");
Expand Down
31 changes: 29 additions & 2 deletions lib/src/main/java/me/frmr/rundeck/KmsConverterPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
import com.dtolabs.rundeck.plugins.storage.StorageConverterPlugin;
import org.rundeck.storage.api.HasInputStream;
import org.rundeck.storage.api.Path;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.encryptionsdk.*;
import com.amazonaws.encryptionsdk.kms.*;
import com.amazonaws.internal.StaticCredentialsProvider;

import java.util.Collections;
import java.util.Map;
import java.io.*;
Expand All @@ -33,6 +38,18 @@ static void addMetadataWasEncrypted(ResourceMetaBuilder resourceMetaBuilder) {
@PluginProperty(title="Key ARN", description="The ARN of the KMS key to use for encryption and decryption", required=true)
String keyArn;

/**
* Configuration provided Access Key Id
*/
@PluginProperty(title="Access Key ID", description = "The access key that should be used when accessing KMS", required=true)
String accessKeyId;

/**
* Configuration provied secret access key
*/
@PluginProperty(title="Secret Access Key", description = "The secret access key that should be used when accessing KMS", required = true)
String secretAccessKey;

/** read the stored data, decrypt if necessary */
public HasInputStream readResource(
Path path,
Expand All @@ -43,7 +60,12 @@ public HasInputStream readResource(
return null;
}

KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider.builder().buildStrict(keyArn);
KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider
.builder()
.withCredentials(new AWSStaticCredentialsProvider(
new BasicAWSCredentials(accessKeyId, secretAccessKey)
))
.buildStrict(keyArn);
CryptoMaterialsManager materialsManager = new DefaultCryptoMaterialsManager(keyProvider);
return new DecryptionStream(hasInputStream, materialsManager);
}
Expand All @@ -54,7 +76,12 @@ public HasInputStream createResource(
ResourceMetaBuilder resourceMetaBuilder,
HasInputStream hasInputStream){

KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider.builder().buildStrict(keyArn);
KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider
.builder()
.withCredentials(new AWSStaticCredentialsProvider(
new BasicAWSCredentials(accessKeyId, secretAccessKey)
))
.buildStrict(keyArn);
Map<String,String> encryptionContext = Collections.singletonMap("path", path.getPath());
CryptoMaterialsManager materialsManager = new DefaultCryptoMaterialsManager(keyProvider);
addMetadataWasEncrypted(resourceMetaBuilder);
Expand Down
12 changes: 4 additions & 8 deletions test-image/rundeck-config-storage.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,18 @@ rundeck.storage.provider.{{index}}.path={% set path = printf("%s/path", provider
{%- set index = converter | base %}
rundeck.storage.converter.{{index}}.type={% set type = printf("%s/type", converter) %}{{ getv(type, "jasypt-encryption") }}
rundeck.storage.converter.{{index}}.path={% set path = printf("%s/path", converter) %}{{ getv(path, "keys") }}
rundeck.storage.converter.{{index}}.config.encryptorType={% set encryptortype = printf("%s/config/encryptortype", converter) %}{{ getv(encryptortype, "custom") }}
rundeck.storage.converter.{{index}}.config.password={% set password = printf("%s/config/password", converter) %}{{ getv(password, "") }}
rundeck.storage.converter.{{index}}.config.algorithm={% set algorithm = printf("%s/config/algorithm", converter) %}{{ getv(algorithm, "PBEWITHSHA256AND128BITAES-CBC-BC") }}
rundeck.storage.converter.{{index}}.config.provider={% set provider = printf("%s/config/provider", converter) %}{{ getv(provider, "BC") }}
rundeck.storage.converter.{{index}}.config.keyArn={% set keyArn = printf("%s/config/keyarn", converter) %}{{ getv(keyArn, "") }}
rundeck.storage.converter.{{index}}.config.accessKeyId={% set awsAccessKeyId = printf("%s/config/awsaccesskeyid", converter) %}{{ getv(awsAccessKeyId, "") }}
rundeck.storage.converter.{{index}}.config.secretAccessKey={% set awsSecretAccessKey = printf("%s/config/awssecretaccesskey", converter) %}{{ getv(awsSecretAccessKey, "") }}
{% endmacro %}

{%- macro config_storage_converter(converter) %}
{%- set index = converter | base %}
rundeck.config.storage.converter.{{index}}.type={% set type = printf("%s/type", converter) %}{{ getv(type, "jasypt-encryption") }}
rundeck.config.storage.converter.{{index}}.path={% set path = printf("%s/path", converter) %}{{ getv(path, "projects") }}
rundeck.config.storage.converter.{{index}}.config.encryptorType={% set encryptortype = printf("%s/config/encryptortype", converter) %}{{ getv(encryptortype, "custom") }}
rundeck.config.storage.converter.{{index}}.config.password={% set password = printf("%s/config/password", converter) %}{{ getv(password, "") }}
rundeck.config.storage.converter.{{index}}.config.algorithm={% set algorithm = printf("%s/config/algorithm", converter) %}{{ getv(algorithm, "PBEWITHSHA256AND128BITAES-CBC-BC") }}
rundeck.config.storage.converter.{{index}}.config.provider={% set provider = printf("%s/config/provider", converter) %}{{ getv(provider, "BC") }}
rundeck.config.storage.converter.{{index}}.config.keyArn={% set keyArn = printf("%s/config/keyarn", converter) %}{{ getv(keyArn, "") }}
rundeck.config.storage.converter.{{index}}.config.accessKeyId={% set awsAccessKeyId = printf("%s/config/awsaccesskeyid", converter) %}{{ getv(awsAccessKeyId, "") }}
rundeck.config.storage.converter.{{index}}.config.secretAccessKey={% set awsSecretAccessKey = printf("%s/config/awssecretaccesskey", converter) %}{{ getv(awsSecretAccessKey, "") }}
{% endmacro %}

{%- if ls(printf("%s/1", providerBase)) | length == 0 %}
Expand Down
4 changes: 2 additions & 2 deletions test-in-rundeck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ set -e
docker build -t rundeck-kms-test-image test-image

docker run -it \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_REGION \
-e RUNDECK_STORAGE_CONVERTER_1_TYPE=rundeck-kms-plugin \
-e RUNDECK_STORAGE_CONVERTER_1_PATH=keys \
-e RUNDECK_STORAGE_CONVERTER_1_CONFIG_KEYARN=$KMS_KEY_ARN \
-e RUNDECK_STORAGE_CONVERTER_1_CONFIG_AWSACCESSKEYID=$AWS_ACCESS_KEY_ID \
-e RUNDECK_STORAGE_CONVERTER_1_CONFIG_AWSSECRETACCESSKEY=$AWS_SECRET_ACCESS_KEY \
-p 4440:4440 \
-v $(pwd)/lib/build/libs/rundeck-kms-plugin.jar:/home/rundeck/libext/rundeck-kms-plugin.jar \
rundeck-kms-test-image

0 comments on commit 7e93e36

Please sign in to comment.