Spring Boot, jak ukryć hasła w pliku właściwości

81

Spring Boot korzysta z pliku właściwości i przynajmniej domyślnie hasła są w postaci zwykłego tekstu. Czy można je w jakiś sposób ukryć / odszyfrować?

user1340582
źródło

Odpowiedzi:

87

Możesz użyć Jasypt do szyfrowania właściwości, więc możesz mieć taką własność:

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

Jasypt umożliwia szyfrowanie właściwości przy użyciu różnych algorytmów, gdy uzyskasz zaszyfrowaną właściwość, którą umieścisz w pliku ENC(...). Na przykład możesz zaszyfrować w ten sposób przez Jasypt za pomocą terminala:

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=

Aby łatwo skonfigurować go za pomocą Spring Boot, możesz użyć jego startera jasypt-spring-boot-starter z identyfikatorem grupycom.github.ulisesbocchio

Pamiętaj, że będziesz musiał uruchomić aplikację przy użyciu tego samego hasła, którego użyłeś do zaszyfrowania właściwości. Możesz więc uruchomić swoją aplikację w ten sposób:

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

Lub używając zmiennej środowiskowej (dzięki luźnemu wiązaniu w butach sprężynowych):

export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
mvn spring-boot:run

Możesz sprawdzić poniższy link, aby uzyskać więcej informacji:

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

Aby użyć swoich zaszyfrowanych właściwości w swojej aplikacji, po prostu użyj ich jak zwykle, użyj dowolnej metody (Spring Boot łączy magię, w każdym razie właściwość musi być oczywiście w ścieżce klas):

Korzystanie z @Valueadnotacji

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

Lub używając Environment

@Autowired
private Environment environment;

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

Aktualizacja: dla środowiska produkcyjnego, aby uniknąć ujawniania hasła w wierszu poleceń, ponieważ możesz wysyłać zapytania do procesów ps, poprzednich poleceń historyitp. Itp. Możesz:

  • Utwórz taki skrypt: touch setEnv.sh
  • Edytuj, setEnv.shaby wyeksportować JASYPT_ENCRYPTOR_PASSWORDzmienną

    #! / bin / bash

    eksportuj JASYPT_ENCRYPTOR_PASSWORD = supersecretz

  • Uruchom plik za pomocą . setEnv.sh
  • Uruchom aplikację w tle za pomocą mvn spring-boot:run &
  • Usuń plik setEnv.sh
  • Usuń poprzednią zmienną środowiskową za pomocą: unset JASYPT_ENCRYPTOR_PASSWORD
Federico Piazza
źródło
2
Czy mógłbyś wyjaśnić więcej szczegółów za pomocą gradle @ Frerica Piazza
testuser
Nie ma jasności co do używania z maven. mijasz jakiś majątek i co dalej? Gdzie plik właściwości? jak sprawdzić tę wartość w kodzie?
gstackoverflow
1
@FedericoPiazza nie mvn -Djasypt.encryptor.password=supersecretz spring-boot:runpojawi się na pswyjściu, ujawniając hasło?
Srki Rakic
1
@SrkiRakic ​​tak, oczywiście. To jest tylko do programowania, jeśli chcesz to do produkcji, powinieneś użyć zmiennych środowiskowych. Wiosenny but pozwala na użycieJASYPT_ENCRYPTOR_PASSWORD
Federico Piazza
1
haha i jak to się ma do zmiennych środowiskowych? Prawdopodobnie z innego pliku jak difinition usług: D Także jasypt jest nieaktualny, jeśli chodzi o hasło wyprowadzeniu więc upewnij się, aby korzystać z całkowicie losowe hasło 32 znaków
Roman Plašil
14

AKTUALIZACJA: Zauważyłem, że ludzie głosowali w dół, więc muszę powiedzieć, że chociaż nie jest to idealne rozwiązanie, ale działa i jest akceptowalne w niektórych przypadkach użycia. Cloudfoundry używa zmiennych środowiskowych do wstrzykiwania poświadczeń, gdy Usługa jest powiązana z aplikacją. Więcej informacji https://docs.cloudfoundry.org/devguide/services/application-binding.html

A jeśli twój system nie jest współdzielony, to w przypadku rozwoju lokalnego jest to również dopuszczalne. Oczywiście bezpieczniejszy sposób jest wyjaśniony w odpowiedzi od @ J-Alex.

Odpowiedź:

Jeśli chcesz ukryć swoje hasła, najłatwiejszym rozwiązaniem jest użycie zmiennych środowiskowych w application.propertiespliku lub bezpośrednio w kodzie.

W application.properties:

mypassword=${password}

Następnie w swojej klasie konfiguracji:

@Autowired
private Environment environment;

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

W Twojej configurationklasie:

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

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

Uwaga: po ustawieniu zmiennej środowiskowej może być konieczne ponowne uruchomienie. Dla Windowsa:

W systemie Windows

Więcej informacji można znaleźć w tej dokumentacji .

Sanjay Rawat
źródło
25
Nie sądzę, aby ustawienie hasła głównego w zmiennej środowiskowej było dobrym pomysłem. Hasło jest teraz bardziej widoczne niż to konieczne. Zapewnienie mu startu, jak pokazuje Federico, jest mniej narażone i bardziej „bezpieczne” niż umieszczenie go w środowisku.
Jaavaaan
Tak, to nie jest, jeśli używasz wspólnego komputera. Ale jeśli jesteś jedynym administratorem swojego komputera, żaden inny użytkownik nie może zobaczyć zmiennych środowiska. Odpowiedziałem na ukrytą część i na łatwiejszą. Ale tak, zgadzam się, że metoda sugerowana przez Federico jest o wiele lepsza.
Sanjay Rawat
Zobacz: diogomonica.com/2017/03/27/…
Book Of Zeus
11

Do już proponowanych rozwiązań mogę dodać opcję konfiguracji zewnętrznego Secrets Managertypu Vault .

  1. Skonfiguruj serwer Vault vault server -dev( tylko dla DEV, a nie dla PROD )
  2. Pisz sekrety vault write secret/somename key1=value1 key2=value2
  3. Zweryfikuj tajemnice vault read secret/somename

Dodaj następującą zależność do projektu SpringBoot:

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

Dodaj właściwości konfiguracyjne programu 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}

Przekaż VAULT_TOKENjako zmienną środowiskową.

Zapoznaj się z dokumentacją tutaj.

Istnieje projekt Spring Vault , którego można również użyć do uzyskiwania dostępu, przechowywania i odwoływania sekretów.

Zależność:

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

Konfigurowanie szablonu repozytorium:

@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {

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

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

Wstrzyknij i użyj 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();
  }
}

Użyj Vault PropertySource:

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

}

Przykład użycia:

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
źródło
+1 za to rozwiązanie. Najlepszym rozwiązaniem jest użycie systemu takiego jak vault / etcd (lub jakikolwiek inny). diogomonica.com/2017/03/27/…
Book Of Zeus
3
-1, ponieważ to nie wyjaśnia, w jaki sposób zabezpieczony jest klucz „główny” (VAULT_TOKEN). Skąd się wzięła zmienna środowiskowa VAULT_TOKEN? Jak to jest zabezpieczone? Bez ochrony tego klucza osoba atakująca może go użyć do odzyskania kluczy tajnych ze skarbca za pomocą kodu spakowanego w pliku Spring Boot jar.
corporatedrone
Głównym problemem jest również zabezpieczenie produktu. Więc trzeba to tutaj powiedzieć. Wskazówki dotyczące środowisk deweloperskich / zapewniania jakości, jeśli są odpowiednie.
sofs 1
Działa to w przypadku wielu haseł. Działa dla jednego hasła do połączenia, ale zabawne jest umieszczenie hasła skarbca w środowisku, aby nie trzeba było umieszczać drugiego hasła w tym samym środowisku.
Lee Meador
0

W przypadku korzystania z dość popularnego w środowisku Spring Boot Kubernetes (K8S) lub OpenShift, istnieje możliwość przechowywania i pobierania właściwości aplikacji w czasie wykonywania. Ta technika nazywa się tajemnicami . W pliku konfiguracyjnym yaml dla Kubernetes lub OpenShift deklarujesz zmienną i symbol zastępczy dla niej, a po stronie K8S \ OpenShift deklarujesz rzeczywistą wartość, która odpowiada temu symbolowi zastępczemu. Szczegóły implementacji: K8S: https://kubernetes.io/docs/concepts/configuration/secret/ OpenShift: https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html

żądło
źródło
0

Moje rozwiązanie do ukrywania hasła DB w application.properties aplikacji Spring Boot zostało zaimplementowane tutaj .

Scenariusz: niektóre fałszywe hasła, które zostały już odczytane i zapisane z application.properties przy uruchomieniu, w globalnym obiekcie Spring ConfigurableEnvironment zostaną programowo zastąpione w Run-Time przez rzeczywiste hasło DB. Prawdziwe hasło zostanie odczytane z innego pliku konfiguracyjnego, zapisanego w bezpiecznym, zewnętrznym miejscu projektu.

Nie zapomnij: zadzwoń do Fasolki z klasy głównej z:

@Autowired
private SchedUtilility utl;
Iakov Senatov
źródło
0

Oprócz popularnych rozwiązań K8, jasypt czy vault, istnieje również Karmahostage . Umożliwia:

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

Działa w ten sam sposób, co jasypt, ale szyfrowanie odbywa się na dedykowanym rozwiązaniu SaaS, z dołączonym bardziej szczegółowym modelem ACL.

Qkyrie
źródło