Skip to content

Commit

Permalink
Issue thelastpickle#809 : Markdown for defining 'cryptograph' configu…
Browse files Browse the repository at this point in the history
…ration in the reaper yaml
  • Loading branch information
denniskline authored and DENNIS KLINE committed Jan 15, 2020
1 parent c2e4082 commit 56eb04e
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 29 deletions.
8 changes: 8 additions & 0 deletions src/docs/content/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,11 @@ Returns OK if all goes well NOT_MODIFIED if new state is the same as the old one
If no tables given, then the whole keyspace is targeted. (Optional)
* *snapshot_name*: name to use for the snapshot. (Optional)
* Create a snapshot on a specific host.

## Crypto Resource

* **GET /crypto/encrypt/{text}**
* Expected query parameters:
* *text*: The text to encrypt.
* Encrypt text when cryptograph settings are configured in the reaper yaml.

70 changes: 70 additions & 0 deletions src/docs/content/docs/configuration/reaper_specific.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,73 @@ Type: *Integer*
Default: *20*

Reaper will prevent repair from overwhelming the cluster when lots of SSTables are streamed, by pausing segment processing if there are more than a specific number of pending compactions. Adjust this setting if you have a lot of tables in the cluster and the total number of pending compactions is usually high.

<br/>

### `cryptograph`

Optional settings to configure how confidential text (ie: passwords) are encyrpted/decrypted.

cryptograph:
type: symmetric
systemPropertySecret: SOME_SYSTEM_PROPERTY_KEY

### `type`

The encryption technique used when encrypting, decrypting, or validating confidential text. Symmetric encryption is the default.

### `algorithm`

Type: *String*

Default: PBKDF2WithHmacSHA512

The optional standard name of the requested secret-key algorithm. See the SecretKeyFactory section in the Java Cryptography Architecture Standard Algorithm Name Documentation for information about standard algorithm names.

### `cipher`

Type: *String*

Default: AES/CBC/PKCS5Padding

The optional name of the transformation, e.g., AES/CBC/PKCS5Padding. See the Cipher section in the Java Cryptography Architecture Standard Algorithm Name Documentation for information about standard transformation names.

### `cipherType`

Type: *String*

Default: AES

The optional name of the secret-key algorithm to be associated with the given key material. See Appendix A in the Java Cryptography Architecture Reference Guide for information about standard algorithm names.

### `iterationCount`

Type: Integer

Default: 1024

The optional number of times the password is hashed.

### `keyStrength`

Type: Integer

Default: 256

The optional length in bits of the derived symmetric key

### `salt`

Type: *String*

Default: deadbeef

The optional salt used for creating the PBEKeySpec

### `systemPropertySecret`

Type: *String*

The key of a system property that holds the shared secret for the symmetric encryption. If encrypted text is required, then this key and its value need to be defined in the environment before reaper can be started.
```export SOME_SYSTEM_PROPERTY_KEY=mysharedsecret```

Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ public final class SymmetricCryptograph implements Cryptograph {
private static final int DEFAULT_ITERATION_COUNT = 1024;
private static final int DEFAULT_KEY_STRENGTH = 256;

private final String salt;
private final String algorithm;
private final String cipher;
private final String cipherType;
private final String algorithm;
private final Integer iterationCount;
private final Integer keyStrength;
private final String salt;
private final String systemPropertySecret;

private SymmetricCryptograph(SymmetricCryptograph.Builder builder) {
Expand Down Expand Up @@ -202,19 +202,19 @@ private byte[] subArray(byte[] array, int beginIndex, int endIndex) {

public static final class Builder {

private String salt;
private String algorithm;
private String cipher;
private String cipherType;
private String algorithm;
private Integer iterationCount;
private Integer keyStrength;
private String salt;
private String systemPropertySecret;

private Builder() {
}

public SymmetricCryptograph.Builder withSalt(String salt) {
this.salt = StringUtils.trimToNull(salt);
public SymmetricCryptograph.Builder withAlgorithm(String algorithm) {
this.algorithm = StringUtils.trimToNull(algorithm);
return this;
}

Expand All @@ -228,11 +228,6 @@ public SymmetricCryptograph.Builder withCipherType(String cipherType) {
return this;
}

public SymmetricCryptograph.Builder withAlgorithm(String algorithm) {
this.algorithm = StringUtils.trimToNull(algorithm);
return this;
}

public SymmetricCryptograph.Builder withIterationCount(Integer iterationCount) {
this.iterationCount = iterationCount;
return this;
Expand All @@ -243,6 +238,11 @@ public SymmetricCryptograph.Builder withKeyStrength(Integer keyStrength) {
return this;
}

public SymmetricCryptograph.Builder withSalt(String salt) {
this.salt = StringUtils.trimToNull(salt);
return this;
}

public SymmetricCryptograph.Builder withSystemPropertySecret(String systemPropertySecret) {
String trimmedPropertyKey = StringUtils.trimToNull(systemPropertySecret);
Preconditions.checkNotNull(trimmedPropertyKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ protected JmxProxy connectImpl(Node node) throws ReaperException, InterruptedExc

try {
JmxConnectionProvider provider = new JmxConnectionProvider(
host, jmxCredentials, context.config.getJmxConnectionTimeoutInSeconds(), this.metricRegistry);
host, jmxCredentials, context.config.getJmxConnectionTimeoutInSeconds(),
this.metricRegistry, cryptograph);
JMX_CONNECTIONS.computeIfAbsent(host, provider::apply);
JmxProxy proxy = JMX_CONNECTIONS.get(host);
if (!proxy.isConnectionAlive()) {
Expand Down Expand Up @@ -187,13 +188,6 @@ public Optional<JmxCredentials> getJmxCredentialsForCluster(Node node) {
credentials = jmxAuth;
}

if (credentials != null) {
credentials = JmxCredentials.builder()
.withUsername(credentials.getUsername())
.withPassword(cryptograph.decrypt(credentials.getPassword()))
.build();
}

return Optional.ofNullable(credentials);
}

Expand All @@ -203,24 +197,27 @@ private class JmxConnectionProvider implements Function<String, JmxProxy> {
private final Optional<JmxCredentials> jmxCredentials;
private final int connectionTimeout;
private final MetricRegistry metricRegistry;
private final Cryptograph cryptograph;

JmxConnectionProvider(
String host,
Optional<JmxCredentials> jmxCredentials,
int connectionTimeout,
MetricRegistry metricRegistry) {
String host,
Optional<JmxCredentials> jmxCredentials,
int connectionTimeout,
MetricRegistry metricRegistry,
Cryptograph cryptograph) {
this.host = host;
this.jmxCredentials = jmxCredentials;
this.connectionTimeout = connectionTimeout;
this.metricRegistry = metricRegistry;
this.cryptograph = cryptograph;
}

@Override
public JmxProxy apply(String host) {
Preconditions.checkArgument(host.equals(this.host));
try {
JmxProxy proxy = JmxProxyImpl.connect(
host, jmxCredentials, addressTranslator, connectionTimeout, metricRegistry);
host, jmxCredentials, addressTranslator, connectionTimeout, metricRegistry, cryptograph);
if (hostConnectionCounters.getSuccessfulConnections(host) <= 0) {
accessibleDatacenters.add(EndpointSnitchInfoProxy.create(proxy).getDataCenter());
}
Expand Down
15 changes: 10 additions & 5 deletions src/server/src/main/java/io/cassandrareaper/jmx/JmxProxyImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.cassandrareaper.core.Cluster;
import io.cassandrareaper.core.JmxCredentials;
import io.cassandrareaper.core.Table;
import io.cassandrareaper.crypto.Cryptograph;
import io.cassandrareaper.service.RingRange;

import java.io.IOException;
Expand Down Expand Up @@ -149,14 +150,15 @@ private JmxProxyImpl(
}

/**
* @see #connect(String, int, Optional, EC2MultiRegionAddressTranslator, int, MetricRegistry)
* @see #connect(String, int, Optional, EC2MultiRegionAddressTranslator, int, MetricRegistry, Cryptograph)
*/
static JmxProxy connect(
String host,
Optional<JmxCredentials> jmxCredentials,
final EC2MultiRegionAddressTranslator addressTranslator,
int connectionTimeout,
MetricRegistry metricRegistry)
MetricRegistry metricRegistry,
Cryptograph cryptograph)
throws ReaperException, InterruptedException {

if (host == null) {
Expand All @@ -171,7 +173,8 @@ static JmxProxy connect(
jmxCredentials,
addressTranslator,
connectionTimeout,
metricRegistry);
metricRegistry,
cryptograph);
}

/**
Expand All @@ -189,7 +192,8 @@ private static JmxProxy connect(
Optional<JmxCredentials> jmxCredentials,
final EC2MultiRegionAddressTranslator addressTranslator,
int connectionTimeout,
MetricRegistry metricRegistry) throws ReaperException, InterruptedException {
MetricRegistry metricRegistry,
Cryptograph cryptograph) throws ReaperException, InterruptedException {

JMXServiceURL jmxUrl;
String host = originalHost;
Expand All @@ -209,7 +213,8 @@ private static JmxProxy connect(
try {
final Map<String, Object> env = new HashMap<>();
if (jmxCredentials.isPresent()) {
String[] creds = {jmxCredentials.get().getUsername(), jmxCredentials.get().getPassword()};
String jmxPassword = cryptograph.decrypt(jmxCredentials.get().getPassword());
String[] creds = {jmxCredentials.get().getUsername(), jmxPassword};
env.put(JMXConnector.CREDENTIALS, creds);
}
env.put("com.sun.jndi.rmi.factory.socket", getRmiClientSocketFactory());
Expand Down

0 comments on commit 56eb04e

Please sign in to comment.