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

Adding support for AWS Secrets Manager #947

Merged
merged 28 commits into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d743f15
[maven-release-plugin] prepare release tessera-0.10.1
chris-j-h Oct 24, 2019
399c1ee
Initial implementation of AWS Secrets Manager support
Nov 4, 2019
d5ecb6c
Merge branch 'master' of https://github.com/vgeorgescu/tessera into f…
Nov 4, 2019
f934343
Build runs successfully
Nov 5, 2019
1e7c7af
AWS Secrets Manager implementation for KeyVault added
Nov 12, 2019
e2b0dd3
Merge branch 'master' of https://github.com/vgeorgescu/tessera into f…
Nov 12, 2019
3aeb497
Fixing pom.xml character
Nov 12, 2019
299ca47
updated version to 0.11-SNAPSHOT
Nov 12, 2019
716b7de
updated version to 0.11-SNAPSHOT
Nov 12, 2019
fe3ed2d
updated version to 0.11-SNAPSHOT
Nov 12, 2019
ff0773d
updated version to 0.11-SNAPSHOT
Nov 12, 2019
231db8f
removed AWSCURRRENT
Nov 13, 2019
be105b3
Merge pull request #2 from vgeorgescu/feature/AWSSecretsManagerDone
vgeorgescu Nov 13, 2019
76551fa
Merge branch 'master' of https://github.com/jpmorganchase/tessera int…
Nov 22, 2019
5fb0b7d
tessera/upstream/master update
Nov 25, 2019
44deb87
Merge branch 'master' into feature/AWSSecretManager
Nov 26, 2019
26f5ea2
rearrange code
Nov 26, 2019
96fc164
rearrange code
Nov 26, 2019
783b86f
rearrange code
Nov 26, 2019
f85f8b6
Update config/src/main/java/com/quorum/tessera/config/keypairs/AWSKey…
Emi14 Dec 4, 2019
ad43a85
Update config/src/main/java/com/quorum/tessera/config/keypairs/AWSKey…
Emi14 Dec 4, 2019
9788674
resolved PR conversations
Dec 4, 2019
d178718
calling validator.validate() for AWSKeyVaultConfig
Dec 4, 2019
0bd3aa6
added acceptance tests for AWS Vault
Dec 9, 2019
1b0c090
Merge branches 'feature/AWSSecretManager' and 'master' of https://git…
Dec 12, 2019
37fc957
added gradle files for AWS Secrets Manager Key Vault implementation
Dec 13, 2019
72c9880
Upstream updates to AWS Secrets Manager change (#1)
chris-j-h Jan 8, 2020
82a312c
Merge branch 'master' into feature/AWSSecretsManager2
chris-j-h Jan 8, 2020
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 @@ -60,7 +60,7 @@ public void emptyPasswordsReturnsSameKeys() {

// null paths since we won't actually be reading them
final ConfigKeyPair keypair = new FilesystemKeyPair(null, null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(null, emptyList(), singletonList(keypair), null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(null, emptyList(), singletonList(keypair), null, null, null);
final Config config = new Config();
config.setKeys(keyConfig);

Expand All @@ -79,7 +79,7 @@ public void noPasswordsReturnsSameKeys() {

// null paths since we won't actually be reading them
final ConfigKeyPair keypair = new FilesystemKeyPair(null, null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(null, null, singletonList(keypair), null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(null, null, singletonList(keypair), null, null, null);
final Config config = new Config();
config.setKeys(keyConfig);

Expand All @@ -100,7 +100,7 @@ public void passwordsAssignedToKeys() {
final ConfigKeyPair keypair = new FilesystemKeyPair(null, null, null);
final KeyConfiguration keyConfig =
new KeyConfiguration(
null, singletonList("passwordsAssignedToKeys"), singletonList(keypair), null, null);
null, singletonList("passwordsAssignedToKeys"), singletonList(keypair), null, null, null);
final Config config = new Config();
config.setKeys(keyConfig);

Expand All @@ -117,7 +117,7 @@ public void unreadablePasswordFileGivesNoPasswords() throws IOException {
final Path passes = Files.createTempDirectory("testdirectory").resolve("nonexistantfile.txt");

final ConfigKeyPair keypair = new FilesystemKeyPair(null, null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(passes, null, singletonList(keypair), null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(passes, null, singletonList(keypair), null, null, null);
final Config config = new Config();
config.setKeys(keyConfig);

Expand All @@ -135,7 +135,7 @@ public void readablePasswordFileAssignsPasswords() throws IOException {
Files.write(passes, "q".getBytes());

final ConfigKeyPair keypair = new FilesystemKeyPair(null, null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(passes, null, singletonList(keypair), null, null);
final KeyConfiguration keyConfig = new KeyConfiguration(passes, null, singletonList(keypair), null, null, null);
final Config config = new Config();
config.setKeys(keyConfig);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private Optional<KeyVaultConfig> keyVaultConfig(CommandLine commandLine) {
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
} else {
} else if(keyVaultType.equals(KeyVaultType.HASHICORP)) {
if (!commandLine.hasOption("filename")) {
throw new CliException(
"At least one -filename must be provided when saving generated keys in a Hashicorp Vault");
Expand All @@ -143,7 +143,16 @@ private Optional<KeyVaultConfig> keyVaultConfig(CommandLine commandLine) {
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
} else {
keyVaultConfig = new AWSKeyVaultConfig(keyVaultUrl);

Set<ConstraintViolation<AWSKeyVaultConfig>> violations =
validator.validate((AWSKeyVaultConfig) keyVaultConfig);

if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}

return Optional.of(keyVaultConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void buildOptions() {
"keys.hashicorpKeyVaultConfig.tlsKeyStorePath",
"keys.hashicorpKeyVaultConfig.tlsTrustStorePath",
"keys.hashicorpKeyVaultConfig.url",
"keys.awsKeyVaultConfig.endpoint",
"alwaysSendTo",
"unixSocketFile",
"useWhiteList",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,50 @@ public void trailingWhitespaceVaultTypeIsOkay() throws Exception {
verify(commandLine, times(1)).getOptionValue("keygenvaulttruststore");
verify(commandLine, times(1)).getOptionValue("keygenvaultsecretengine");
}

@Test
public void ifAwsVaultTypeProvidedAndEndpointProvidedThenOkay() throws Exception {
when(commandLine.hasOption("keygenvaulttype")).thenReturn(true);
when(commandLine.getOptionValue("keygenvaulturl")).thenReturn("https://localhost.com");
when(commandLine.getOptionValue("keygenvaulttype")).thenReturn("AWS");

this.parser.parse(commandLine);

verify(commandLine, times(1)).getOptionValue("keygenvaulturl");
verify(commandLine, times(1)).getOptionValue("keygenvaulttype");
}

@Test
public void ifAwsVaultTypeProvidedAndNoEndpointProvidedThenOkay() throws Exception {
when(commandLine.hasOption("keygenvaulttype")).thenReturn(true);
when(commandLine.getOptionValue("keygenvaulttype")).thenReturn("AWS");

this.parser.parse(commandLine);

verify(commandLine, times(1)).getOptionValue("keygenvaulttype");
}

@Test
public void wrongKeygenvaulturlProvidedWhenUsingAwsVaultThrowsException() {
when(commandLine.hasOption("keygenvaulttype")).thenReturn(true);
when(commandLine.hasOption("keygenvaulturl")).thenReturn(true);
when(commandLine.getOptionValue("keygenvaulturl")).thenReturn("notAValidURL");
when(commandLine.getOptionValue("keygenvaulttype")).thenReturn("AWS");
when(commandLine.hasOption("filename")).thenReturn(false);

Throwable ex = catchThrowable(() -> this.parser.parse(commandLine));

verify(commandLine, times(1)).getOptionValue("keygenvaulttype");
verify(commandLine, times(1)).getOptionValue("keygenvaulturl");

assertThat(ex).isInstanceOf(ConstraintViolationException.class);

Set<ConstraintViolation<?>> violations = ((ConstraintViolationException) ex).getConstraintViolations();

assertThat(violations.size()).isEqualTo(1);

ConstraintViolation violation = violations.iterator().next();

assertThat(violation.getPropertyPath().toString()).isEqualTo("endpoint");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ public KeyConfiguration build() {
privateKeyPasswordFilePath = null;
}

return new KeyConfiguration(privateKeyPasswordFilePath, null, keyData, null, null);
return new KeyConfiguration(privateKeyPasswordFilePath, null, keyData, null, null, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public void ifPublicAndPrivateKeyListAreEmptyThenKeyConfigurationIsAllNulls() th
KeyConfiguration result = tomlConfigFactory.createKeyDataBuilder(configData).build();
assertThat(result).isNotNull();

KeyConfiguration expected = new KeyConfiguration(null, null, Collections.emptyList(), null, null);
KeyConfiguration expected = new KeyConfiguration(null, null, Collections.emptyList(), null, null, null);
assertThat(result).isEqualTo(expected);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public static ConfigBuilder builderWithValidValues() {
new FilesystemKeyPair(
Paths.get("public"), Paths.get("private"), KEY_ENCRYPTOR)),
null,
null,
null));
}

Expand Down Expand Up @@ -124,6 +125,7 @@ public static ConfigBuilder builderWithNullValues() {
new FilesystemKeyPair(
Paths.get("public"), Paths.get("private"), KEY_ENCRYPTOR)),
null,
null,
null));
}

Expand Down
2 changes: 1 addition & 1 deletion config/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
<artifactId>jasypt</artifactId>
</dependency>


</dependencies>
<build>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.quorum.tessera.config;

import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;

@XmlAccessorType(XmlAccessType.FIELD)
public class AWSKeyVaultConfig extends ConfigItem implements KeyVaultConfig {

@Valid
@XmlAttribute
@Pattern(
regexp =
"https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)")
private String endpoint;

public AWSKeyVaultConfig(String endpoint) {
this.endpoint = endpoint;
}

public AWSKeyVaultConfig() {}

@Override
public KeyVaultType getKeyVaultType() {
return KeyVaultType.AWS;
}

public String getEndpoint() {
return this.endpoint;
}

public void setEndpoint(String url) {
this.endpoint = url;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,21 @@ public class KeyConfiguration extends ConfigItem {

@Valid @XmlElement private HashicorpKeyVaultConfig hashicorpKeyVaultConfig;

@Valid @XmlElement private AWSKeyVaultConfig awsKeyVaultConfig;

public KeyConfiguration(
final Path passwordFile,
final List<String> passwords,
final List<ConfigKeyPair> keyData,
final AzureKeyVaultConfig azureKeyVaultConfig,
final HashicorpKeyVaultConfig hashicorpKeyVaultConfig) {
final HashicorpKeyVaultConfig hashicorpKeyVaultConfig,
final AWSKeyVaultConfig awsKeyVaultConfig) {
this.passwordFile = passwordFile;
this.passwords = passwords;
this.keyData = keyData;
this.azureKeyVaultConfig = azureKeyVaultConfig;
this.hashicorpKeyVaultConfig = hashicorpKeyVaultConfig;
this.awsKeyVaultConfig = awsKeyVaultConfig;
}

public KeyConfiguration() {}
Expand All @@ -74,6 +78,10 @@ public HashicorpKeyVaultConfig getHashicorpKeyVaultConfig() {
return hashicorpKeyVaultConfig;
}

public AWSKeyVaultConfig getAwsKeyVaultConfig() {
return this.awsKeyVaultConfig;
}

public void setPasswordFile(Path passwordFile) {
this.passwordFile = passwordFile;
}
Expand All @@ -93,4 +101,8 @@ public void setAzureKeyVaultConfig(AzureKeyVaultConfig azureKeyVaultConfig) {
public void setHashicorpKeyVaultConfig(HashicorpKeyVaultConfig hashicorpKeyVaultConfig) {
this.hashicorpKeyVaultConfig = hashicorpKeyVaultConfig;
}

public void setAwsKeyVaultConfig(AWSKeyVaultConfig awsKeyVaultConfig) {
this.awsKeyVaultConfig = awsKeyVaultConfig;
}
}
25 changes: 24 additions & 1 deletion config/src/main/java/com/quorum/tessera/config/KeyData.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ public class KeyData extends ConfigItem {
@XmlElement
private String hashicorpVaultSecretVersion;

public KeyData(KeyDataConfig config, String privateKey, String publicKey, Path privateKeyPath, Path publicKeyPath, String azureVaultPublicKeyId, String azureVaultPrivateKeyId, String azureVaultPublicKeyVersion, String azureVaultPrivateKeyVersion, String hashicorpVaultPublicKeyId, String hashicorpVaultPrivateKeyId, String hashicorpVaultSecretEngineName, String hashicorpVaultSecretName, String hashicorpVaultSecretVersion) {
@XmlElement
private String awsSecretsManagerPublicKeyId;

@XmlElement
private String awsSecretsManagerPrivateKeyId;

public KeyData(KeyDataConfig config, String privateKey, String publicKey, Path privateKeyPath, Path publicKeyPath, String azureVaultPublicKeyId, String azureVaultPrivateKeyId, String azureVaultPublicKeyVersion, String azureVaultPrivateKeyVersion, String hashicorpVaultPublicKeyId, String hashicorpVaultPrivateKeyId, String hashicorpVaultSecretEngineName, String hashicorpVaultSecretName, String hashicorpVaultSecretVersion, String awsSecretsManagerPublicKeyId, String awsSecretsManagerPrivateKeyId) {
this.config = config;
this.privateKey = privateKey;
this.publicKey = publicKey;
Expand All @@ -73,6 +79,8 @@ public KeyData(KeyDataConfig config, String privateKey, String publicKey, Path p
this.hashicorpVaultSecretEngineName = hashicorpVaultSecretEngineName;
this.hashicorpVaultSecretName = hashicorpVaultSecretName;
this.hashicorpVaultSecretVersion = hashicorpVaultSecretVersion;
this.awsSecretsManagerPublicKeyId = awsSecretsManagerPublicKeyId;
this.awsSecretsManagerPrivateKeyId = awsSecretsManagerPrivateKeyId;
}

public KeyData() {
Expand Down Expand Up @@ -135,6 +143,14 @@ public String getHashicorpVaultSecretVersion() {
return hashicorpVaultSecretVersion;
}

public String getAwsSecretsManagerPublicKeyId() {
return awsSecretsManagerPublicKeyId;
}

public String getAwsSecretsManagerPrivateKeyId() {
return awsSecretsManagerPrivateKeyId;
}

public void setConfig(KeyDataConfig config) {
this.config = config;
}
Expand Down Expand Up @@ -191,4 +207,11 @@ public void setHashicorpVaultSecretVersion(String hashicorpVaultSecretVersion) {
this.hashicorpVaultSecretVersion = hashicorpVaultSecretVersion;
}

public void setAwsSecretsManagerPublicKeyId(String awsSecretsManagerPublicKeyId) {
this.awsSecretsManagerPublicKeyId = awsSecretsManagerPublicKeyId;
}

public void setAwsSecretsManagerPrivateKeyId(String awsSecretsManagerPrivateKeyId) {
this.awsSecretsManagerPrivateKeyId = awsSecretsManagerPrivateKeyId;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.quorum.tessera.config;

public enum KeyVaultType {
AZURE, HASHICORP
AZURE, HASHICORP, AWS
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,19 @@ public ConfigKeyPair unmarshal(final KeyData keyData) {
keyData.getHashicorpVaultSecretVersion());
}

// case 5, the keys are provided inside a file
// case 5, the AWS Secrets Manager data is provided
if (keyData.getAwsSecretsManagerPublicKeyId() != null && keyData.getAwsSecretsManagerPrivateKeyId() != null) {
return new AWSKeyPair(
keyData.getAwsSecretsManagerPublicKeyId(), keyData.getAwsSecretsManagerPrivateKeyId());
}

// case 6, the keys are provided inside a file
if (keyData.getPublicKeyPath() != null && keyData.getPrivateKeyPath() != null) {
final KeyEncryptor keyEncryptor = keyEncryptorHolder.getKeyEncryptor().get();
return new FilesystemKeyPair(keyData.getPublicKeyPath(), keyData.getPrivateKeyPath(), keyEncryptor);
}

// case 6, the key config specified is invalid
// case 7, the key config specified is invalid
return new UnsupportedKeyPair(
keyData.getConfig(),
keyData.getPrivateKey(),
Expand All @@ -80,7 +86,9 @@ public ConfigKeyPair unmarshal(final KeyData keyData) {
keyData.getHashicorpVaultPrivateKeyId(),
keyData.getHashicorpVaultSecretEngineName(),
keyData.getHashicorpVaultSecretName(),
keyData.getHashicorpVaultSecretVersion());
keyData.getHashicorpVaultSecretVersion(),
keyData.getAwsSecretsManagerPublicKeyId(),
keyData.getAwsSecretsManagerPrivateKeyId());
}

@Override
Expand Down Expand Up @@ -128,6 +136,14 @@ public KeyData marshal(final ConfigKeyPair keyPair) {
return keyData;
}

if (keyPair instanceof AWSKeyPair) {
AWSKeyPair kp = (AWSKeyPair) keyPair;

keyData.setAwsSecretsManagerPublicKeyId(kp.getPublicKeyId());
keyData.setAwsSecretsManagerPrivateKeyId(kp.getPrivateKeyId());
return keyData;
}

if (keyPair instanceof FilesystemKeyPair) {
FilesystemKeyPair kp = (FilesystemKeyPair) keyPair;

Expand All @@ -152,7 +168,9 @@ public KeyData marshal(final ConfigKeyPair keyPair) {
kp.getHashicorpVaultPublicKeyId(),
kp.getHashicorpVaultSecretEngineName(),
kp.getHashicorpVaultSecretName(),
kp.getHashicorpVaultSecretVersion());
kp.getHashicorpVaultSecretVersion(),
kp.getAwsSecretsManagerPublicKeyId(),
kp.getAwsSecretsManagerPrivateKeyId());
}

throw new UnsupportedOperationException("The keypair type " + keyPair.getClass() + " is not allowed");
Expand Down
Loading