Skip to content

Instantly share code, notes, and snippets.

@tsachev
Created April 7, 2020 10:13
Show Gist options
  • Save tsachev/434e631e716486c87e2e28e53b263622 to your computer and use it in GitHub Desktop.
Save tsachev/434e631e716486c87e2e28e53b263622 to your computer and use it in GitHub Desktop.
spring-boot doker/k8s secrets support
/*
* Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tick42.varandb.boot.env;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.boot.origin.TextResourceOrigin;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.FileSystemResource;
import static java.util.stream.Collectors.toMap;
/**
* An {@link EnvironmentPostProcessor} that knows how to load docker/kubernetes secrets.
*
* The contents of every file under {@code /run/secrets} can be easily consumed
* by {@link ConfigurableEnvironment Environment} users via {@code secret.*} properties.
*
* @author Vladimir Tsanev
*/
public class SecretEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final Logger log = LoggerFactory.getLogger(SecretEnvironmentPostProcessor.class);
private String prefix = "secret.";
private final Path directory;
public SecretEnvironmentPostProcessor() {
this(new File("/run/secrets").toPath());
}
public SecretEnvironmentPostProcessor(Path directory) {
this.directory = directory;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, OriginTrackedValue> map;
map = createSecretsMap();
if (!map.isEmpty()) {
MutablePropertySources sources = environment.getPropertySources();
PropertySource<?> source = new OriginTrackedMapPropertySource("secrets", map);
sources.addFirst(source);
}
}
Map<String, OriginTrackedValue> createSecretsMap() {
try {
if (this.directory.toFile().exists()) {
return Files.walk(this.directory, 1)
.filter(p -> p.toFile().isFile())
.collect(toMap(this::getSecretName, this::readValueFromFile));
}
}
catch (Exception e) {
log.error("Cloud not create secrets map", e);
}
return Collections.emptyMap();
}
private String getSecretName(Path path) {
return this.prefix + path.getFileName().toString();
}
private OriginTrackedValue readValueFromFile(Path path) {
char[] secret;
try {
byte[] bytes = Files.readAllBytes(path);
secret = new String(bytes, StandardCharsets.UTF_8).toCharArray();
}
catch (Exception e) {
log.error("Could not read secret value from " + path, e);
secret = null;
}
Origin origin = new TextResourceOrigin(new FileSystemResource(path.toFile()), null);
return OriginTrackedValue.of(secret, origin);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment