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ć?
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ć?
Odpowiedzi:
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 @Value
adnotacji
@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ń history
itp. Itp. Możesz:
touch setEnv.sh
setEnv.sh
aby wyeksportować JASYPT_ENCRYPTOR_PASSWORD
zmienną
#! / bin / bash
eksportuj JASYPT_ENCRYPTOR_PASSWORD = supersecretz
. setEnv.sh
mvn spring-boot:run &
setEnv.sh
unset JASYPT_ENCRYPTOR_PASSWORD
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
pojawi się na ps
wyjściu, ujawniając hasło?
JASYPT_ENCRYPTOR_PASSWORD
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.properties
pliku 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 configuration
klasie:
@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:
Więcej informacji można znaleźć w tej dokumentacji .
Spring Cloud Config Server pozwoli na tego typu zachowanie. Za pomocą JCE można ustawić klucz na serwerze i użyć go do zaszyfrowania właściwości aplikacji.
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
Do już proponowanych rozwiązań mogę dodać opcję konfiguracji zewnętrznego Secrets Manager
typu Vault .
vault server -dev
( tylko dla DEV, a nie dla PROD )vault write secret/somename key1=value1 key2=value2
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_TOKEN
jako 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) {
// …
}
}
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
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;
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.