Spring Boot cómo ocultar contraseñas en el archivo de propiedades

81

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?

usuario1340582
fuente

Respuestas:

86

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 @Valueanotació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.

  • Cree un script como este: touch setEnv.sh
  • Edite setEnv.shpara exportar la JASYPT_ENCRYPTOR_PASSWORDvariable

    #! / bin / bash

    exportar JASYPT_ENCRYPTOR_PASSWORD = supersecretz

  • Ejecuta el archivo con . setEnv.sh
  • Ejecute la aplicación en segundo plano con mvn spring-boot:run &
  • Eliminar el archivo setEnv.sh
  • Desarme la variable de entorno anterior con: unset JASYPT_ENCRYPTOR_PASSWORD
Plaza Federico
fuente
2
¿Podría explicar más en detalle usando gradle @Frerica Piazza
testuser
No está claro cómo usarlo con maven. Pasas alguna propiedad y que mas? ¿Dónde archivo de propiedad? ¿Cómo ise este valor en el código?
gstackoverflow
1
@FedericoPiazza ¿No mvn -Djasypt.encryptor.password=supersecretz spring-boot:runaparecerá en la pssalida, exponiendo la contraseña?
Srki Rakic
1
@SrkiRakic ​​sí, por supuesto. Esto es solo para desarrollo, si lo desea para producción, debe usar variables de entorno. La bota de primavera te permite usarJASYPT_ENCRYPTOR_PASSWORD
Federico Piazza
1
jaja y ¿cómo entra en las variables de entorno? Probablemente de otro archivo como definición de servicio: D También jasypt está desactualizado cuando se trata de derivación de contraseñas, así que asegúrese de usar una contraseña de 32 caracteres totalmente aleatoria
Roman Plášil
14

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.propertiesarchivo 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 configurationclase:

@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:

En Windows

Consulte esta documentación para obtener más información.

Sanjay Rawat
fuente
25
No creo que establecer la contraseña maestra en el entorno vars sea una buena idea. La contraseña ahora está más expuesta de lo necesario. Proporcionarle una startup como lo muestra Federico está menos expuesto y es más "seguro" que instalarlo en el entorno.
Jaavaaan
Yaa, no es si estás usando una computadora compartida. Pero si usted es el único administrador de su computadora, ningún otro usuario podrá ver las variables env. Respondí la parte oculta y la más fácil. Pero sí, estoy de acuerdo en que el método sugerido por Federico es mucho mejor.
Sanjay Rawat
Consulte: diogomonica.com/2017/03/27/…
Libro de Zeus
11

A las soluciones ya propuestas puedo agregar una opción para configurar un externo Secrets Managercomo Vault .

  1. Configurar Vault Server vault server -dev( solo para DEV y no para PROD )
  2. Escribe secretos vault write secret/somename key1=value1 key2=value2
  3. Verificar secretos 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_TOKENcomo 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) {
    // …
  }
}
J-Alex
fuente
+1 para esta solución. Usar un sistema como vault / etcd (o cualquier otro) es el camino a seguir. diogomonica.com/2017/03/27/…
Libro de Zeus
3
-1 porque esto no explica cómo se protege la clave "maestra" (VAULT_TOKEN). ¿De dónde vino la variable de entorno VAULT_TOKEN? ¿Cómo se asegura? Sin proteger esa clave, el atacante puede usarla para recuperar los secretos de la bóveda usando el código empaquetado en el jar de Spring Boot.
corporatedrone
También asegurar la prod es el problema principal. Entonces, hay que hablarlo aquí. Orientación para entornos Dev / QA si está bien.
sofs1
Esto funciona cuando hay muchas contraseñas. Funciona para que se conecte una contraseña, pero es divertido decir que coloque la contraseña de la bóveda en el entorno para que no tenga que poner la otra contraseña en el mismo entorno.
Lee Meador
0

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

aguijón
fuente
0

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;
Iakov Senatov
fuente
0

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.

Qkyrie
fuente