devonfw / devon4j

devonfw Java stack - create enterprise-grade business apps in Java safe and fast
Apache License 2.0
82 stars 88 forks source link

Document how to deal with environment specific configurations and secrets in Quarkus #475

Closed GuentherJulian closed 2 years ago

GuentherJulian commented 2 years ago

The devon4j (Spring) configuration guide suggests using Jasypt for handling (environment-specific) secrets. This is not a suitable approach for Quarkus. Therefore, adapt the Quarkus configuration guide and add how to handle such secrets and environment configurations. Link to the original issue: https://github.com/devonfw-forge/devonfw-microservices/issues/39

Description (if the original ticket will be deleted): Currently we have test-environment specific properties and even secrets in plain text here: https://github.com/devonfw-forge/devonfw-microservices/blob/main/reference-project/src/main/resources/application.properties#L56 It may be just a demo app but IMHO this is not a good example as projects will later see this as they way to do it and follow. How would you solve this properly in a real world project? Is it still state of the art to have a separate git repo for environment configs? In devon4j we have a suggestion for password encryption: https://github.com/devonfw/devon4j/blob/master/documentation/guide-configuration.asciidoc#password-encryption Should that also apply in quarkus and can jasypt be integrated into quarkus? Or would you have a central and secure infra service per environment where you manage configurations and inject or pull them from the actual pods and containers?

GuentherJulian commented 2 years ago

Comment in the original issue: devon4j has a suggestion to use jasypt-spring-boot extension for encrypted passwords. In Quarkus there is a Camel Quarkus Jasypt extension that can used in combination with a Config Interceptor to store and resolve encrypted secrets. However, this feature only works in JVM mode and not in native mode (apache/camel-quarkus#792). Therefore, this solution is not suitable for our approaches.

_In our reference application, we currently store the database credentials in plain text in the application.properties file. One solution would be to remove this configuration from the file and just set QUARKUS_DATASOURCE_USERNAME and QUARKUS_DATASOURCEPASSWORD environment variables. These will overwrite the configuration from the configuration file in any case, since Quarkus reads configuration properties from multiple sources (see here) and environment variables have a higher priority than the configuration file. This could additionally be combined with a custom credentials provider, which allows custom credentials to be taken from other environment variables or locations. The approach with environment variables can be easily integrated into a containerized environment, as environment variables can be easily passed when starting a container, ans is therefore suitable for cloud applications. In a Kubernetes context, the secrets can be stored as Kubernetes Secret and then passed to the deployment file. For other secrets (e.g. API Tokens) used within the code, the variables can be accessed programmatically from code using the @ConfigProperty annotation or ConfigProvider.getConfig().getConfigValue().

For production environments with many applications and secrets, it is more convenient to use a centralized service to store all secrets. For this purpose Quarkus supports HashiCorp Vault. There are several guides that describe the usage of Vault (https://quarkus.io/guides/vault, https://quarkus.io/guides/credentials-provider, https://quarkus.io/guides/vault-datasource). The Vault extension can be used to get access to secrets at runtime via KV Secrets Engine or to get the database credentials at startup via Vault Credentials Provider