Spring Boot, wie Kennwörter in der Eigenschaftendatei ausgeblendet werden

80

Spring Boot verwendet die Eigenschaftendatei, und zumindest standardmäßig sind die Kennwörter im Klartext. Ist es möglich, diese irgendwie zu verstecken / zu entschlüsseln?

user1340582
quelle

Antworten:

84

Sie können Jasypt verwenden , um Eigenschaften zu verschlüsseln, sodass Sie Ihre Eigenschaft wie folgt haben können:

db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=)

Mit Jasypt können Sie Ihre Eigenschaften mit verschiedenen Algorithmen verschlüsseln, sobald Sie die verschlüsselte Eigenschaft erhalten haben, die Sie in das Feld eingegeben haben ENC(...). Zum Beispiel können Sie auf diese Weise über Jasypt mit dem Terminal verschlüsseln:

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=

Um es einfach mit Spring Boot zu konfigurieren, können Sie den Starter jasypt-spring-boot-Starter mit Gruppen-ID verwendencom.github.ulisesbocchio

Beachten Sie, dass Sie Ihre Anwendung mit demselben Kennwort starten müssen, mit dem Sie die Eigenschaften verschlüsselt haben. Sie können Ihre App also folgendermaßen starten:

mvn -Djasypt.encryptor.password=supersecretz spring-boot:run

Oder verwenden Sie die Umgebungsvariable (dank Spring Boot Relaxed Binding):

export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
mvn spring-boot:run

Sie können den folgenden Link für weitere Details überprüfen:

https://www.ricston.com/blog/encrypting-properties-in-spring-boot-with-jasypt-spring-boot/

Um Ihre verschlüsselten Eigenschaften in Ihrer App zu verwenden, verwenden Sie sie wie gewohnt. Verwenden Sie eine der von Ihnen gewünschten Methoden (Spring Boot verdrahtet die Magie, die Eigenschaft muss sich natürlich im Klassenpfad befinden):

Mit @ValueAnmerkung

@Value("${db.password}")
private String password;

Oder mit Environment

@Autowired
private Environment environment;

public void doSomething(Environment env) {
    System.out.println(env.getProperty("db.password"));
}

Update: Für die Produktionsumgebung, um zu vermeiden, dass das Kennwort in der Befehlszeile angezeigt wird, da Sie die Prozesse mit ps, vorherige Befehle mit historyusw. usw. abfragen können . Sie könnten:

  • Erstellen Sie ein Skript wie folgt: touch setEnv.sh
  • Bearbeiten setEnv.sh, um die JASYPT_ENCRYPTOR_PASSWORDVariable zu exportieren

    #! / bin / bash

    export JASYPT_ENCRYPTOR_PASSWORD = supersecretz

  • Führen Sie die Datei mit aus . setEnv.sh
  • Führen Sie die App im Hintergrund mit aus mvn spring-boot:run &
  • Löschen Sie die Datei setEnv.sh
  • Deaktivieren Sie die vorherige Umgebungsvariable mit: unset JASYPT_ENCRYPTOR_PASSWORD
Federico Piazza
quelle
2
Könnten Sie bitte mehr Details mit gradle @Frerica Piazza
Testbenutzer
Es ist nicht klar über die Verwendung mit Maven. Sie passieren ein Grundstück und was weiter? Wo Eigenschaftsdatei? Wie wird dieser Wert im Code angegeben?
gstackoverflow
1
@FedericoPiazza Wird mvn -Djasypt.encryptor.password=supersecretz spring-boot:runin der psAusgabe nicht angezeigt und das Kennwort angezeigt ?
Srki Rakic
1
@SrkiRakic ​​ja natürlich. Dies ist nur für die Entwicklung gedacht. Wenn Sie es für die Produktion wünschen, sollten Sie Umgebungsvariablen verwenden. Spring Boot ermöglicht es Ihnen,JASYPT_ENCRYPTOR_PASSWORD
Federico Piazza
1
haha und wie kommt es in umgebungsvariablen? Wahrscheinlich aus einer anderen Datei wie Service Difinition: D Auch Jasypt ist veraltet, wenn es um die Ableitung von Passwörtern geht. Verwenden Sie daher
unbedingt ein
14

UPDATE: Ich habe bemerkt, dass die Leute dies abgelehnt haben, daher muss ich sagen, dass dies zwar keine ideale Lösung ist, aber dies funktioniert und in einigen Anwendungsfällen akzeptabel ist. Cloudfoundry verwendet Umgebungsvariablen, um Anmeldeinformationen einzufügen, wenn ein Dienst an eine Anwendung gebunden ist. Weitere Informationen unter https://docs.cloudfoundry.org/devguide/services/application-binding.html

Und auch wenn Ihr System nicht gemeinsam genutzt wird, ist dies für die lokale Entwicklung akzeptabel. Der sicherere Weg wird natürlich in Antwort von @ J-Alex erklärt.

Antworten:

Wenn Sie Ihre Kennwörter verbergen möchten, ist es am einfachsten, Umgebungsvariablen in einer application.propertiesDatei oder direkt in Ihrem Code zu verwenden.

In application.properties:

mypassword=${password}

Dann in Ihrer Konfigurationsklasse:

@Autowired
private Environment environment;

[...]//Inside a method
System.out.println(environment.getProperty("mypassword"));

In deiner configurationKlasse:

@Value("${password}")
private String herokuPath;

[...]//Inside a method
System.out.println(herokuPath);

Hinweis: Möglicherweise müssen Sie nach dem Festlegen der Umgebungsvariablen neu starten. Für Windows:

In Windows

Weitere Informationen finden Sie in dieser Dokumentation .

Sanjay Rawat
quelle
25
Ich halte es nicht für eine gute Idee, das Hauptkennwort in den Umgebungsvariablen festzulegen. Das Passwort ist jetzt mehr offen als nötig. Das Bereitstellen eines Starts, wie von Federico gezeigt, ist weniger exponiert und "sicherer" als das Festlegen in der Umgebung.
Jaavaaan
Ja, es ist nicht, wenn Sie einen gemeinsam genutzten Computer verwenden. Wenn Sie jedoch der einzige Administrator Ihres Computers sind, kann kein anderer Benutzer die Umgebungsvariablen sehen. Ich antwortete auf das Verstecken und das einfachere. Aber ja, ich stimme zu, dass Federicos vorgeschlagene Methode viel besser ist.
Sanjay Rawat
Bitte sehen Sie: diogomonica.com/2017/03/27/…
Buch des Zeus
10

Zu den bereits vorgeschlagenen Lösungen kann ich eine Option zum Konfigurieren einer externen Lösung Secrets Managerwie Vault hinzufügen .

  1. Vault Server konfigurieren vault server -dev( nur für DEV und nicht für PROD )
  2. Schreibe Geheimnisse vault write secret/somename key1=value1 key2=value2
  3. Geheimnisse überprüfen vault read secret/somename

Fügen Sie Ihrem SpringBoot-Projekt die folgende Abhängigkeit hinzu:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>

Hinzufügen von Vault-Konfigurationseigenschaften:

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}

Übergeben Sie VAULT_TOKENals Umgebungsvariable.

Siehe die Dokumentation hier.

Es gibt ein Spring Vault- Projekt, mit dem auch auf Geheimnisse zugegriffen, diese gespeichert und widerrufen werden können.

Abhängigkeit:

<dependency>
    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>
</dependency>

Konfigurieren der Tresorvorlage:

@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {

  @Override
  public VaultEndpoint vaultEndpoint() {
    return new VaultEndpoint();
  }

  @Override
  public ClientAuthentication clientAuthentication() {
    return new TokenAuthentication("…");
  }
}

Injizieren und verwenden Sie 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();
  }
}

Vault verwenden PropertySource:

@VaultPropertySource(value = "aws/creds/s3",
  propertyNamePrefix = "aws."
  renewal = Renewal.RENEW)
public class Config {

}

Anwendungsbeispiel:

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
quelle
+1 für diese Lösung. Die Verwendung eines Systems wie vault / etcd (oder eines anderen) ist der richtige Weg. diogomonica.com/2017/03/27/…
Buch des Zeus
3
-1, da dies nicht erklärt, wie der "Hauptschlüssel" (VAULT_TOKEN) gesichert ist. Woher kommt die Umgebungsvariable VAULT_TOKEN? Wie ist es gesichert? Ohne diesen Schlüssel zu schützen, kann der Angreifer ihn verwenden, um die Geheimnisse aus dem Tresor mithilfe des im Spring Boot-JAR enthaltenen Codes abzurufen.
Corporatedrone
Auch die Sicherung des Produkts ist das Hauptproblem. Es muss also hier gesprochen werden. Anleitung für Dev / QA-Umgebungen, wenn in Ordnung.
sofs1
Dies funktioniert, wenn viele Passwörter vorhanden sind. Es funktioniert, wenn ein Kennwort eine Verbindung herstellt, aber es ist lustig zu sagen, dass Sie das Tresorkennwort in die Umgebung einfügen, damit Sie das andere Kennwort nicht in derselben Umgebung ablegen müssen.
Lee Meador
0

Wenn Sie in der Spring Boot-Umgebung Kubernetes (K8S) oder OpenShift sehr beliebt verwenden, besteht die Möglichkeit, Anwendungseigenschaften zur Laufzeit zu speichern und abzurufen. Diese Technik heißt Geheimnisse . In Ihrer Konfigurations-Yaml-Datei für Kubernetes oder OpenShift deklarieren Sie die Variable und den Platzhalter dafür und auf der K8S \ OpenShift-Seite den tatsächlichen Wert, der diesem Platzhalter entspricht. Einzelheiten zur Implementierung finden Sie unter: K8S: https://kubernetes.io/docs/concepts/configuration/secret/ OpenShift: https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html

Stachel
quelle
0

Meine Lösung zum Ausblenden eines DB-Passworts in den application.properties von Spring Boot App wurde implementiert hier .

Szenario: Ein falsches Passwort, das bereits gelesen und gespeichert wurde beim Start application.properties , werden im globalen Spring-Objekt ConfigurableEnvironment in der Laufzeit programmatisch durch ein echtes DB-Kennwort ersetzt. Das echte Passwort wird aus einer anderen Konfigurationsdatei gelesen, die an einem sicheren, projektfremden Ort gespeichert ist.

Vergessen Sie nicht: Rufen Sie die Bohne aus der Hauptklasse an mit:

@Autowired
private SchedUtilility utl;
Iakov Senatov
quelle
0

Neben den beliebten K8-, Jasypt- oder Vault-Lösungen gibt es auch Karmahostage . Es ermöglicht Ihnen Folgendes:

@EncryptedValue("${application.secret}")
private String application;

Es funktioniert genauso wie Jasypt, aber die Verschlüsselung erfolgt mit einer dedizierten Saas-Lösung, an die ein feinkörnigeres ACL-Modell angehängt ist.

Qkyrie
quelle