I have an enterprise Java application and want to securely manage database connection configuration.
To address this requirement, this article will briefly describe how to securely manage database credentials with HashiCorp Vault and how to configure JPA for database connectivity in a Kubernetes environment.
Key management
Key storage
In a Kubernetes environment, we use HashiCorp Vault as the key management tool. The configuration is stored in the `values.yaml’ file, which uses the Helm configuration values:
# values.yaml
secretList:
- name: database-credentials
vaultPath: /secret/database/prod
Key acquisition process
- store sensitive information (e.g. database username, password) in the Vault
- retrieve credentials information from the Vault via
vaultPath
- use
name
as a reference identifier (e.g.database-credentials.username
)
Configuration File Management
When the application is deployed, Kubernetes injects the values from values.yaml
into the application configuration file, which mainly consists of:
context.xml
(Tomcat data source configuration)persistence.xml
(JPA configuration)application.properties/yml
(Spring configuration)
In the configuration file, we use the placeholder format: ^CFG:DATABASE_PASSWORD^
.
Tomcat data source configuration
context.xml
is Tomcat’s context configuration file for creating and managing data sources and other container-level resources.
Example:
<Context>
<Resource
name="jdbc/MainDatabase"
type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb"
username="^CFG:DATABASE_USERNAME^"
password="^CFG:DATABASE_PASSWORD^"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000"/>
</Context>
Detailed reference: Apache Tomcat 9 (9.0.97) - JNDI Resources How-To
JPA configuration
JPA (Java Persistence API) is a specification/interface, the most common JPA implementation is Hibernate.
persistance.xml
is the configuration file for jpa:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
<persistence-unit name="mainPU" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:comp/env/jdbc/MainDatabase</non-jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
where java:comp/env/
is the standard prefix for JNDI namespaces, as explained here: jakarta ee - what is java:comp/env? - Stack Overflow
You can find the corresponding Resource by using it.
Application startup process
Now let’s string together the above configuration files.
- Kubernetes initialization
- Reading
values.yaml
- Get keys from Vault
- Replace the placeholders in the configuration file
- **Tomcat startup
- Load the
context.xml
- Initialize the data source connection pool
- **Application deployment
- Reads
persistence.xml
. - Hibernate initialization
- Create database connection
Code example
By importing the JPA specification and its implementation, Hibernate, as well as the Spring framework, we can properly manipulate the data in the database.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String username;
// getters and setters
}
@Service
@Transactional
public class UserService {
// Specify the persistence-unit with the name attribute.
@PersistenceContext(unitName = "mainPU")
private EntityManager entityManager;
public User findById(Long id) {
return entityManager.find(User.class, id);
}
public void save(User user) {
entityManager.persist(user);
}
}
Summary
We have simply implemented a complete database security configuration scheme:
- key management with HashiCorp Vault
- configuration injection via Kubernetes
- Combining Tomcat data sources and JPA for database connectivity.
This solution ensures security and maintains good maintainability, which is suitable for the development and deployment of enterprise-level Java applications.