Spring Boot usa el archivo de propiedades y, al menos de forma predeterminada, las contraseñas están en texto sin formato. ¿Es posible ocultarlos / descifrarlos de alguna manera?
Spring Boot usa el archivo de propiedades y, al menos de forma predeterminada, las contraseñas están en texto sin formato. ¿Es posible ocultarlos / descifrarlos de alguna manera?
Respuestas:
Puede usar Jasypt para cifrar propiedades, por lo que podría tener su propiedad así:
db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=)
Jasypt le permite cifrar sus propiedades utilizando diferentes algoritmos, una vez que obtenga la propiedad cifrada que puso dentro del ENC(...)
. Por ejemplo, puede cifrar de esta manera a través de Jasypt usando la terminal:
encrypted-pwd$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="contactspassword" password=supersecretz algorithm=PBEWithMD5AndDES
----ENVIRONMENT-----------------
Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 24.45-b08
----ARGUMENTS-------------------
algorithm: PBEWithMD5AndDES
input: contactspassword
password: supersecretz
----OUTPUT----------------------
XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=
Para configurarlo fácilmente con Spring Boot, puede usar su iniciador jasypt-spring-boot-starter con ID de grupocom.github.ulisesbocchio
Tenga en cuenta que deberá iniciar su aplicación con la misma contraseña que utilizó para cifrar las propiedades. Entonces, puede iniciar su aplicación de esta manera:
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
O usando la variable de entorno (gracias al enlace relajado de Spring Boot):
export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
mvn spring-boot:run
Puede consultar el enlace a continuación para obtener más detalles:
https://www.ricston.com/blog/encrypting-properties-in-spring-boot-with-jasypt-spring-boot/
Para usar sus propiedades cifradas en su aplicación, utilícela como de costumbre, use cualquier método que desee (Spring Boot conecta la magia, de todos modos, la propiedad debe estar, por supuesto, en la ruta de clase):
Usando @Value
anotación
@Value("${db.password}")
private String password;
O usando Environment
@Autowired
private Environment environment;
public void doSomething(Environment env) {
System.out.println(env.getProperty("db.password"));
}
Actualización: para entorno de producción, para evitar exponer la contraseña en la línea de comandos, ya que puedes consultar los procesos con ps
, comandos anteriores con history
, etc.
touch setEnv.sh
setEnv.sh
para exportar la JASYPT_ENCRYPTOR_PASSWORD
variable
#! / bin / bash
exportar JASYPT_ENCRYPTOR_PASSWORD = supersecretz
. setEnv.sh
mvn spring-boot:run &
setEnv.sh
unset JASYPT_ENCRYPTOR_PASSWORD
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
aparecerá en la ps
salida, exponiendo la contraseña?
JASYPT_ENCRYPTOR_PASSWORD
ACTUALIZACIÓN: Me di cuenta de que la gente rechazaba esto, así que debo decir que, aunque no es una solución ideal, funciona y es aceptable en algunos casos de uso. Cloudfoundry utiliza variables de entorno para inyectar credenciales cuando un servicio está vinculado a una aplicación. Más información https://docs.cloudfoundry.org/devguide/services/application-binding.html
Y también si su sistema no se comparte, entonces para el desarrollo local esto también es aceptable. Por supuesto, la forma más segura se explica en Respuesta de @ J-Alex.
Responder:
Si desea ocultar sus contraseñas, la solución más sencilla es utilizar las variables de entorno en el application.properties
archivo o directamente en su código.
En application.properties
:
mypassword=${password}
Luego, en su clase de configuración:
@Autowired
private Environment environment;
[...]//Inside a method
System.out.println(environment.getProperty("mypassword"));
En tu configuration
clase:
@Value("${password}")
private String herokuPath;
[...]//Inside a method
System.out.println(herokuPath);
Nota: Es posible que deba reiniciar después de configurar la variable de entorno. Para ventanas:
Consulte esta documentación para obtener más información.
Spring Cloud Config Server permitirá este tipo de comportamiento. Con JCE puede configurar una clave en el servidor y usarla para cifrar las propiedades de las aplicaciones.
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
A las soluciones ya propuestas puedo agregar una opción para configurar un externo Secrets Manager
como Vault .
vault server -dev
( solo para DEV y no para PROD )vault write secret/somename key1=value1 key2=value2
vault read secret/somename
Agregue la siguiente dependencia a su proyecto SpringBoot:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>
Agregue las propiedades de configuración de Vault:
spring.cloud.vault.host=localhost
spring.cloud.vault.port=8200
spring.cloud.vault.scheme=http
spring.cloud.vault.authentication=token
spring.cloud.vault.token=${VAULT_TOKEN}
Pase VAULT_TOKEN
como variable de entorno.
Consulte la documentación aquí.
Existe un proyecto Spring Vault que también se puede utilizar para acceder, almacenar y revocar secretos.
Dependencia:
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
</dependency>
Configuración de la plantilla de Vault:
@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public VaultEndpoint vaultEndpoint() {
return new VaultEndpoint();
}
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("…");
}
}
Inyecte y use VaultTemplate:
public class Example {
@Autowired
private VaultOperations operations;
public void writeSecrets(String userId, String password) {
Map<String, String> data = new HashMap<String, String>();
data.put("password", password);
operations.write(userId, data);
}
public Person readSecrets(String userId) {
VaultResponseSupport<Person> response = operations.read(userId, Person.class);
return response.getBody();
}
}
Usar Vault PropertySource
:
@VaultPropertySource(value = "aws/creds/s3",
propertyNamePrefix = "aws."
renewal = Renewal.RENEW)
public class Config {
}
Ejemplo de uso:
public class S3Client {
// inject the actual values
@Value("${aws.access_key}")
private String awsAccessKey;
@Value("${aws.secret_key}")
private String awsSecretKey;
public InputStream getFileFromS3(String filenname) {
// …
}
}
En caso de que esté utilizando Kubernetes (K8S) u OpenShift bastante popular en el entorno Spring Boot, existe la posibilidad de almacenar y recuperar propiedades de la aplicación en tiempo de ejecución. Esta técnica se llama secretos . En su archivo yaml de configuración para Kubernetes u OpenShift, declara la variable y el marcador de posición para él, y en el lado de K8S \ OpenShift declara el valor real que corresponde a este marcador de posición. Para obtener detalles sobre la implementación, consulte: K8S: https://kubernetes.io/docs/concepts/configuration/secret/ OpenShift: https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html
Mi solución para ocultar una DB-Password en application.properties de Spring Boot App se implementa aquí .
Escenario: alguna contraseña falsa que ya se está leyendo y guardada de application.properties al inicio, en el objeto ConfigurableEnvironment global de Spring será, en tiempo de ejecución, reemplazada programáticamente por DB-Password real. La contraseña real se leerá desde otro archivo de configuración, guardado en un lugar seguro y externo al proyecto.
No olvide: llame al Bean desde la clase principal con:
@Autowired
private SchedUtilility utl;
Además de las populares soluciones K8, jasypt o bóveda, también está Karmahostage . Te permite hacer:
@EncryptedValue("${application.secret}")
private String application;
Funciona de la misma manera que lo hace jasypt, pero el cifrado se realiza en una solución saas dedicada, con un modelo de ACL más detallado adjunto.