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

feat(secret): decrypt secrets before sending to deck #1379

Merged
merged 4 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
@@ -0,0 +1,40 @@
package com.netflix.spinnaker.halyard.deploy.config.v1.secrets;

import com.netflix.spinnaker.halyard.core.secrets.v1.SecretSessionManager;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile;
import com.netflix.spinnaker.kork.secrets.EncryptedSecret;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.RandomStringUtils;

public class BindingsSecretDecrypter {
protected Profile profile;
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
protected Path decryptedOutputDirectory;
protected SecretSessionManager secretSessionManager;

public BindingsSecretDecrypter(
SecretSessionManager secretSessionManager, Profile profile, Path decryptedOutputDirectory) {
super();
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
this.secretSessionManager = secretSessionManager;
this.profile = profile;
this.decryptedOutputDirectory = decryptedOutputDirectory;
}

public String trackSecretFile(String value, String fieldName) {
if (EncryptedSecret.isEncryptedSecret(value)) {
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
String name = newRandomFilePath(fieldName);
byte[] bytes = secretSessionManager.decryptAsBytes(value);
profile.getDecryptedFiles().put(name, bytes);
value = getCompleteFilePath(name);
}
return value;
}

protected String newRandomFilePath(String fieldName) {
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
return fieldName + "-" + RandomStringUtils.randomAlphanumeric(5);
}

protected String getCompleteFilePath(String filename) {
return Paths.get(decryptedOutputDirectory.toString(), filename).toString();
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ protected ArtifactService getArtifactService() {

@Override
protected Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints) {
Map<String, Object> result = new HashMap<>();
result.put("accessKeyId", accessKeyId);
result.put(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ protected String getMinimumSecretDecryptionVersion(String deploymentName) {
* @return true if the target service supports decryption of secrets
*/
protected boolean supportsSecretDecryption(String deploymentName) {
if (getArtifact().equals(SpinnakerArtifact.DECK)) {
return false;
}
String minVersion = getMinimumSecretDecryptionVersion(deploymentName);
if (minVersion == null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public abstract class TemplateBackedProfileFactory extends ProfileFactory {
protected abstract String getTemplate();

protected abstract Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints);
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints);

protected List<String> requiredFiles(DeploymentConfiguration deploymentConfiguration) {
return new ArrayList<>();
Expand All @@ -46,7 +48,7 @@ protected void setProfile(
SpinnakerRuntimeSettings endpoints) {
StringResource template = new StringResource(profile.getBaseContents());
profile.setRequiredFiles(requiredFiles(deploymentConfiguration));
Map<String, Object> bindings = getBindings(deploymentConfiguration, endpoints);
Map<String, Object> bindings = getBindings(deploymentConfiguration, profile, endpoints);
profile.setContents(template.setBindings(bindings).toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.TemplateBackedProfileFactory;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerService.Type;
Expand Down Expand Up @@ -51,7 +52,9 @@ public class ConsulClientProfileFactory extends TemplateBackedProfileFactory {

@Override
protected Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints) {
Map<String, Object> bindings = new HashMap<>();
ServiceSettings consul = endpoints.getServiceSettings(Type.CONSUL_CLIENT);
bindings.put("scheme", consul.getScheme());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.TemplateBackedProfileFactory;
import com.netflix.spinnaker.kork.secrets.EncryptedSecret;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -52,10 +53,16 @@ protected void setProfile(

@Override
protected Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints) {
Map<String, Object> bindings = new HashMap<>();
ApacheSsl ssl = deploymentConfiguration.getSecurity().getUiSecurity().getSsl();
bindings.put("passphrase", ssl.getSslCertificatePassphrase());
if (EncryptedSecret.isEncryptedSecret(ssl.getSslCertificatePassphrase())) {
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
bindings.put("passphrase", secretSessionManager.decrypt(ssl.getSslCertificatePassphrase()));
} else {
bindings.put("passphrase", ssl.getSslCertificatePassphrase());
}
return bindings;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ protected void setProfile(

@Override
protected Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints) {
Map<String, Object> bindings = new HashMap<>();
bindings.put("deck-host", endpoints.getServiceSettings(Type.DECK).getHost());
bindings.put("deck-port", endpoints.getServiceSettings(Type.DECK).getPort() + "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.netflix.spinnaker.halyard.config.model.v1.security.UiSecurity;
import com.netflix.spinnaker.halyard.core.resource.v1.StringResource;
import com.netflix.spinnaker.halyard.core.resource.v1.TemplatedResource;
import com.netflix.spinnaker.halyard.deploy.config.v1.secrets.BindingsSecretDecrypter;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile;
Expand Down Expand Up @@ -77,13 +78,24 @@ protected void setProfile(

@Override
protected Map<String, Object> getBindings(
DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
DeploymentConfiguration deploymentConfiguration,
Profile profile,
SpinnakerRuntimeSettings endpoints) {
TemplatedResource resource = new StringResource(SSL_TEMPLATE);
Map<String, Object> bindings = new HashMap<>();
BindingsSecretDecrypter bsc =
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
new BindingsSecretDecrypter(
secretSessionManager,
profile,
halconfigDirectoryStructure.getStagingDependenciesPath(
deploymentConfiguration.getName()));
UiSecurity uiSecurity = deploymentConfiguration.getSecurity().getUiSecurity();
ApacheSsl apacheSsl = uiSecurity.getSsl();
bindings.put("cert-file", apacheSsl.getSslCertificateFile());
bindings.put("key-file", apacheSsl.getSslCertificateKeyFile());
bindings.put(
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
"cert-file", bsc.trackSecretFile(apacheSsl.getSslCertificateFile(), "sslCertificateFile"));
bindings.put(
"key-file",
bsc.trackSecretFile(apacheSsl.getSslCertificateKeyFile(), "sslCertificateKeyFile"));
String ssl = resource.setBindings(bindings).toString();
bindings.clear();
bindings.put("ssl", ssl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration;
import com.netflix.spinnaker.halyard.config.model.v1.security.ApacheSsl;
import com.netflix.spinnaker.halyard.config.services.v1.AccountService;
import com.netflix.spinnaker.halyard.deploy.config.v1.secrets.BindingsSecretDecrypter;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile;
Expand Down Expand Up @@ -56,12 +57,22 @@ protected void setProfile(
Map<String, String> env = profile.getEnv();

if (apacheSsl.isEnabled()) {
BindingsSecretDecrypter bsc =
new BindingsSecretDecrypter(
secretSessionManager,
profile,
halconfigDirectoryStructure.getStagingDependenciesPath(
deploymentConfiguration.getName()));
env.put("DECK_HOST", deckSettings.getHost());
env.put("DECK_PORT", deckSettings.getPort() + "");
env.put("API_HOST", gateSettings.getBaseUrl());
env.put("DECK_CERT", apacheSsl.getSslCertificateFile());
env.put("DECK_KEY", apacheSsl.getSslCertificateKeyFile());
env.put("PASSPHRASE", apacheSsl.getSslCertificatePassphrase());
env.put(
KathrynLewis marked this conversation as resolved.
Show resolved Hide resolved
"DECK_CERT",
bsc.trackSecretFile(apacheSsl.getSslCertificateFile(), "sslCertificateFile"));
env.put(
"DECK_KEY",
bsc.trackSecretFile(apacheSsl.getSslCertificateKeyFile(), "sslCertificateKeyFile"));
env.put("PASSPHRASE", secretSessionManager.decrypt(apacheSsl.getSslCertificatePassphrase()));
}

env.put(
Expand Down