项目作者: dschadow

项目描述 :
Cloud security projects with Spring Cloud Config Server and Vault
高级语言: Java
项目地址: git://github.com/dschadow/CloudSecurity.git
创建时间: 2017-04-11T14:38:14Z
项目社区:https://github.com/dschadow/CloudSecurity

开源协议:Apache License 2.0

下载


Cloud Security Project Guidelines

Build codecov License

Project Overview

This project demonstrates cloud security implementations using Spring Cloud Config and HashiCorp Vault, with examples of secure configuration management and secret handling.

Tech Stack

  • Java 21
  • Spring Boot 3.4
  • Spring Cloud 2024
  • HashiCorp Vault 1.19
  • PostgreSQL 17
  • Jasypt for encryption
  • SpringDoc OpenAPI
  • Docker for containerization
  • Maven for build management

Project Structure

  1. CloudSecurity/
  2. ├── config-client/ # Basic config client implementation
  3. ├── config-client-vault/ # Vault-integrated config client
  4. ├── config-server/ # Basic config server
  5. ├── config-server-vault/ # Vault-integrated config server
  6. ├── standalone-client/ # Independent client implementation
  7. ├── config-repo/ # Configuration repository
  8. └── Docker/ # Container configurations

Architecture Overview

The system is designed with multiple layers of configuration and security management:

  1. +-------------------------------------------------------------------------+
  2. | Client Applications |
  3. | +----------------+ +-------------------+ +------------------+ |
  4. | | Standalone | | Config Client | | Config Client | |
  5. | | Client | | (Basic) | | (Vault) | |
  6. | | [Jasypt] | | | | | |
  7. | +--------+-------+ +---------+---------+ +--------+---------+ |
  8. | | | | |
  9. | | | | |
  10. +-----------|--------------------+---------------------|--------------------+
  11. | | |
  12. v v v
  13. +-------------------------------------------------------------------------+
  14. | Configuration Layer |
  15. | +----------------+ +-------------------+ +------------------+ |
  16. | | Jasypt | | Config Server | | Config Server | |
  17. | | Encryption | | (Basic) | | (Vault) | |
  18. | | | | | | | |
  19. | +----------------+ +--------+----------+ +--------+---------+ |
  20. | | | |
  21. +------------------------------|-----------------------)--------------------+
  22. | |
  23. v v
  24. +-------------------------------------------------------------------------+
  25. | Security & Storage |
  26. | +----------------+ +-------------------+ +------------------+ |
  27. | | Config Repo | | HashiCorp | | PostgreSQL | |
  28. | | (Git) | | Vault | | Database | |
  29. | | | | | | | |
  30. | +----------------+ +-------------------+ +------------------+ |
  31. | |
  32. +-------------------------------------------------------------------------+

The architecture consists of three main layers:

  1. Client Applications Layer

    • Standalone Client with Jasypt encryption
    • Basic Config Client using Spring Cloud Config
    • Vault-enabled Config Client for advanced secret management
  2. Configuration Layer

    • Basic Config Server for centralized configuration
    • Vault-enabled Config Server for secure secret management
    • Jasypt encryption for standalone operations
  3. Security & Storage Layer

    • Git-based Configuration Repository
    • HashiCorp Vault for secret management and dynamic credentials
    • PostgreSQL database for application data

standalone-client

The standalone application is using Jasypt for Spring Boot to secure sensitive configuration properties. This demo application shows the simplest way to encrypt sensitive properties without requiring another service or system. You have to provide an environment variable named jasypt.encryptor.password with the value sample-password to decrypt the database password during application start. After launching, http://localhost:8080 shows basic application information.

Spring Cloud Config

All client applications use Spring Cloud Config to separate code and configuration and therefore require a running config server before starting the actual application.

config-server

This project contains the Spring Cloud Config server which must be started like a Spring Boot application before using the config-client web application. After starting the config server with the default profile, the server is available on port 8888 and will use the configuration files provided in the config-repo folder in my GitHub repository. Starting the config server without a profile therefore requires Internet access to read the configuration files

There are two application configurations available:

  • config-client with the profile cipher
  • config-client with the profile plain

config-client

This Spring Boot based web application exposes the REST endpoints /, /users and /credentials. Depending on the active Spring profile, the configuration files used are not encrypted (plain) or secured using Spring Config encryption functionality (cipher). There is no default profile available, so you have to provide a specific profile during start.

Profile plain

Configuration files are not protected at all, even sensitive configuration properties are stored in plain text.

Profile cipher

This profile uses Config Server functionality to encrypt sensitive properties. It requires either a symmetric or asymmetric key. The sample is based on asymmetric encryption and is using a keystore (server.jks) which was created with the following command:

  1. keytool -genkeypair -alias configserver -storetype JKS -keyalg RSA \
  2. -dname "CN=Config Server,OU=Unit,O=Organization,L=City,S=State,C=Germany" \
  3. -keypass secret -keystore server.jks -storepass secret

The Config Server endpoints help to encrypt and decrypt data:

  1. curl http://localhost:8888/encrypt -d secretToEncrypt
  2. curl http://localhost:8888/decrypt -d secretToDecrypt

Build & Run

  1. Build the project:

    1. mvn clean install
  2. Start infrastructure:

    1. cd Docker
    2. docker-compose up -d
  3. Initialize Vault:

    • Open Vault UI at http://localhost:8200
    • Use the following unseal keys (any 3 out of 5):
      1. Key 1: ndPiS12Q92PqSdahBL4xFkDSjHTivINXQeC62jUv6tVa
      2. Key 2: 8FpTPAQSFj2j2NyAt1V47iZtBn4g+a3V5hgc6L6ogiw5
      3. Key 3: xRDWjq+0n72AjfC6Zt19Aiw3XCnMBJ424QoKATDROi+F
      4. Key 4: wBEG41KMWWpYbhYwtSl/+0hYOhSNQGhsvH8T1FZiJh4w
      5. Key 5: YJ+WiIAzWDatj3eAiiULjw/BoNF+30DWsrFqs6xnDadR
    • Initial Root Token: hvs.WzBcwSIguPzLnhfJmPaCIMnK
  4. Run applications in order:

    • Start config-server or config-server-vault
    • Start client applications

Testing

  • JUnit tests are available for each module
  • Run tests with: mvn test
  • JaCoCo test coverage reports are generated automatically
  • Test reports location: target/site/jacoco/index.html

Manual Vault Configuration

In case you don’t want to use the configured Vault Docker container you can find all required commands to initialize Vault below:

  1. vault server -config Docker/config/file-storage.hcl
  2. export VAULT_ADDR=http://127.0.0.1:8200
  3. vault operator init
  4. export VAULT_TOKEN=[Root Token]
  5. vault operator unseal [Key 1]
  6. vault operator unseal [Key 2]
  7. vault operator unseal [Key 3]

Execute the following commands in order to enable the required backend and other services and to provide the required data:

  1. # enable secrets backend
  2. vault secrets enable -path=secret kv-v2
  3. # provide configuration data for the config-client-vault application
  4. vault kv put secret/Config-Client-Vault config.client.vault.application.name="Config Client Vault" config.client.vault.application.profile="vault"
  5. # import policy
  6. vault policy write config-client-policy Docker/policies/config-client-policy.hcl
  7. # create a token for config-client-vault
  8. vault token create -policy=config-client-policy
  9. # enable and configure AppRole authentication
  10. vault auth enable approle
  11. # create roles with 24 hour TTL (can be renewed for up to 48 hours of its first creation)
  12. vault write auth/approle/role/config-client \
  13. token_ttl=24h \
  14. token_max_ttl=48h \
  15. token_policies=config-client-policy
  16. # update config-client-vault/application.yml with the returned role-id
  17. vault read auth/approle/role/config-client/role-id
  18. # update config-client-vault/application.yml with the returned secret-id
  19. vault write -f auth/approle/role/config-client/secret-id
  20. # enable the Transit backend and provide a key
  21. vault secrets enable transit
  22. vault write -f transit/keys/symmetric-sample-key
  23. # enable dynamic database secrets
  24. vault secrets enable database
  25. # create an all privileges role
  26. vault write database/roles/config_client_vault_all_privileges \
  27. db_name=config_client_vault \
  28. creation_statements="CREATE ROLE \"{{name}}\" \
  29. WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
  30. GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"{{name}}\"; \
  31. ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO \"{{name}}\";" \
  32. revocation_statements="ALTER ROLE \"{{name}}\" NOLOGIN;" \
  33. default_ttl="24h" \
  34. max_ttl="48h"
  35. # create the database connection (the database must already exist, create it with "CREATE DATABASE config_client_vault;")
  36. vault write database/config/config_client_vault \
  37. plugin_name=postgresql-database-plugin \
  38. allowed_roles="*" \
  39. connection_url="postgresql://{{username}}:{{password}}@postgres:5432/config_client_vault?sslmode=disable" \
  40. username="postgres" \
  41. password="password"
  42. # force rotation for root user (THIS WILL DESTROY the existing root password, make sure you have another one)
  43. vault write --force /database/rotate-root/config_client_vault
  44. # create new credentials
  45. vault read database/creds/config_client_vault_all_privileges