Contact usRequest a demo

HashiCorp Vault integration

HashiCorp Vault is a system for storing sensitive and secret information. When integrated into an Unblu installation, you can use Vault:

  • To store and load Unblu configuration properties with the scope IMMUTABLE or GLOBAL. The configuration properties are loaded when the Collaboration Server starts.

  • As a secrets engine for accessing a PostgreSQL database.

This article outlines how to connect your Vault installation to the Unblu Collaboration Server. This involves three principle tasks:

  1. Create a set of policies for Unblu and upload them to Vault.

  2. Configure access to Vault for Unblu.

  3. Configure Unblu to use Vault.

The sections below describe how to complete these tasks to use Vault as a key/value store for configuration properties and as a database secrets engine, respectively.

All examples assume you’re using the default values of the related Unblu configuration properties.

The information in this article applies to standalone deployments of Unblu. Vault integration isn’t part of unblu-kubernetes-base.

Configuring Vault as a key/value secrets engine

To use Vault as a key/value secrets engine for Unblu configuration properties, complete the steps below:

  1. Create a policy for Unblu. Optionally, store the policies in a file.

    The example policy below is written in HCL. You can write your policies in JSON if you prefer.

    Listing 1. Example Vault policy (unblu-properties-policy.hcl) for Unblu configuration properties
    path "secret/data/unblu" {
        capabilities = ["read"]
    }
  2. Upload your policy to Vault. The example command below uploads the policy from the file /tmp/unblu-properties-policy.hcl and names it unblu-cfg-policy:

    Listing 2. Command to upload a policy to Vault
    vault policy write unblu-cfg-policy /tmp/unblu-properties-policy.hcl

    Adapt the names of the policy and the HCL file to match your use case.

  3. Configure an authentication method. Refer to the section Authentication below for more information.

Adding configuration properties to Vault

To add Unblu configuration properties to your Vault key/value secrets engine, you can now, for example, run the following command:

Listing 3. Command to add an Unblu configuration property to the Vault key/value secrets engine
# vault kv put secret/unblu <configuration-property-key>=<configuration-property-value>
vault kv put secret/unblu com.unblu.mail.smtp.global.pass=redundant-flywheel-dancing

Configuration properties that you add to the Vault key/value secrets engine are applied globally, that is, to all Unblu accounts running on the Collaboration Server. They override configuration properties set by the Collaboration Server, for example, by including a properties file using -Dcom.unblu.propertyoverlay=<properties-file>. Configuration properties that you set in the Account or Global Server Configuration interfaces, on the other hand, override the values specified by the key/value secrets engine.

Any properties in the secrets/unblu path that aren’t Unblu configuration properties or text properties are ignored.

Configuring Vault as a database secrets engine

To use Vault as a database secrets engine for a PostgreSQL database, complete the steps below:

  1. Create a set of policies for Unblu. Optionally, store the policies in a file.

    Listing 4. Example Vault policy (unblu-database-policy.hcl) for Unblu database secrets
    path "database/creds/unblu" {
      capabilities = ["read"]
    }
    path "database/creds/unblu_admin" {
      capabilities = ["read"]
    }
    path "sys/leases/revoke/database/creds/unblu/*" {
      capabilities = ["update"]
    }
    path "sys/leases/revoke/database/creds/unblu_admin/*" {
      capabilities = ["update"]
    }
  2. Upload your policy to Vault. The example command below uploads the policy from the file /tmp/unblu-database-policy.hcl and names it unblu-db-policy:

    Listing 5. Command to upload a policy to Vault
    vault policy write unblu-db-policy /tmp/unblu-database-policy.hcl

    Adapt the names of the policy and the HCL file to match your use case.

  3. Configure an authentication method. Refer to the section Authentication below for further information.

  4. Enable the database secrets engine:

    Listing 6. Command to enable the Vault database secrets engine
    vault secrets enable database
  5. Prepare a database user and role for Vault. This user creates and drops the users that are based on the unblu and unblu_admin Vault roles.

    The example below assumes the user is called vault and has the password vault_password, and the role is called unblu_owner.

    Listing 7. Commands to prepare database user and role for Vault
    CREATE USER vault WITH PASSWORD 'vault_password' CREATEROLE; (1)
    CREATE ROLE unblu_owner WITH NOLOGIN; (2)
    GRANT unblu_owner TO vault;
    1 Replace vault and vault_password with values of your choice. If you do so, adapt references to the values in subsequent examples accordingly.
    2 unblu_owner is the default role name. You can change it if you want to.

    Instead of replacing vault_password, you can also let Vault rotate the password. This has the advantage that there’s no record of the password (in your shell history, for example) once Vault rotates it.

    Listing 8. Command to rotate the password of the vault database user
    vault write -force database/rotate-root/postgresql
  6. Create a Vault role for Unblu to access the database. This example assumes the role is called unblu.

    Listing 9. Command to create a role for Unblu to access the database
    vault write database/roles/unblu \
          db_name=postgresql \
          creation_statements=@unblu_creation.sql \
          revocation_statements=@unblu_revocation.sql \
          renew_statements=@unblu_renewal.sql \
          default_ttl=5m \
          max_ttl=24h
    • The argument creation_statements refers to the following SQL commands:

      Listing 10. Contents of unblu_creation.sql
      CREATE USER "{{name}}" WITH PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
      GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA public TO "{{name}}"; (1)
      GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO "{{name}}"; (2)
      ALTER DEFAULT PRIVILEGES IN SCHEMA public FOR USER "unblu_owner" GRANT SELECT, UPDATE, INSERT, DELETE ON TABLES TO "{{name}}"; (3)
      ALTER DEFAULT PRIVILEGES IN SCHEMA public FOR USER "unblu_owner" GRANT USAGE, SELECT ON SEQUENCES TO "{{name}}"; (4)
      1 Grant access to existing tables.
      2 Grant access to existing sequences.
      3 Grant access to tables created in the future. If necessary, replace unblu_owner with the role you defined when creating a database role for Vault above.
      4 Grant access to sequences created in the future. If necessary, replace unblu_owner with the role you defined when creating a database role for Vault above.
    • The argument revocation_statements refers to the following SQL commands:

      Listing 11. Contents of unblu_revocation.sql
      ALTER DEFAULT PRIVILEGES IN SCHEMA public FOR USER "unblu_owner" REVOKE SELECT, UPDATE, INSERT, DELETE ON TABLES FROM "{{name}}";
      ALTER DEFAULT PRIVILEGES IN SCHEMA public FOR USER "unblu_owner" REVOKE USAGE, SELECT ON SEQUENCES FROM "{{name}}";
      REVOKE SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA public FROM "{{name}}";
      REVOKE USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public FROM "{{name}}";
      DROP USER "{{name}}";
    • The argument renew_statements refers to the following SQL commands:

      Listing 12. Contents of unblu_renewal.sql
      ALTER USER "{{name}}" VALID UNTIL '{{expiration}}';
  7. Create a Vault role to administer the database.

    vault write database/roles/unblu_admin \
          db_name=postgresql \
          creation_statements=@unblu_admin_creation.sql \
          revocation_statements=@unblu_admin_revocation.sql \
          renew_statements=@unblu_renewal.sql \
          default_ttl=5m \
          max_ttl=24h
    • The argument creation_statements refers to the following SQL commands:

      Listing 13. Contents of unblu_admin_creation.sql
      CREATE USER "{{name}}" WITH PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
      GRANT USAGE, CREATE ON SCHEMA public TO "{{name}}";
      GRANT unblu_owner TO "{{name}}"; (1)
      ALTER ROLE "{{name}}" SET ROLE unblu_owner; (2)
      1 Required for Unblu to be able to set the unblu_owner role after login.
      2 The user sets the unblu_owner role after login. All objects created by the user will be owned by the unblu_owner role.
    • The argument revocation_statements refers to the following SQL commands:

      Listing 14. Contents of unblu_admin_revocation.sql
      REVOKE unblu_owner FROM "{{name}}";
      DROP USER "{{name}}";
    • The argument renew_statements refers to the same SQL commands as for the unblu role above.

  8. Configure Vault with the plugin and connection information for your database:

    Listing 15. Command to configure Vault with database plugin and connection information
    vault write database/config/postgresql \
         plugin_name=postgresql-database-plugin \
         connection_url="postgresql://{{username}}:{{password}}@db:5432/unblu?sslmode=disable" \
         allowed_roles=unblu,unblu_admin \ (1)
         username="vault" \ (2)
         password="vault_password" (2)
    1 Replace with the role names you defined.
    2 Replace with the values you used when creating a database user for Vault above.
  9. Configure an authentication method. Refer to the section Authentication below for more information.

Using Vault as a database secrets engine

Using Vault as a database secrets engine changes how Unblu interacts with the PostgreSQL database in a number of ways:

  • The Unblu Collaboration Server isn’t configured with the database users it should use to connect to Postgres (called unblu and unblu_admin by default). Instead, the database users are created by Vault with random names and passwords when the Collaboration Server requests them on startup. The database users are created and dropped using the SQL statements you provide to the unblu and unblu_admin roles you create.

  • The database user has an expiration or time-to-live (TTL). Shortly before the user expires, the Collaboration Server requests that Vault create a new user and drop the old one. The new user has a new random name and password.

  • The Collaboration Server uses temporary users with the unblu_admin role to create and update the schema.

    If you intend to use Vault to run on an existing database, you must ensure that ownership of existing objects is assigned to the unblu_admin role. This operation must be carried out with the Unblu database selected as the default database or it won’t have an effect.

Authentication

Before you can connect a Vault instance and use it with Unblu, you must configure an authentication method. Unblu supports three different authentication methods for Vault:

Since you associate a policy with the role you create for your authentication method, you must already have uploaded your policy to Vault before you create the role.

Configuring the AppRole authentication method

To use the AppRole authentication method, proceed as follows:

  1. Enable the AppRole authentication method if you haven’t done so already:

    Listing 16. Command to enable the AppRole authentication method
    vault auth enable approle
  2. Create an AppRole role for Unblu. The command below assumes you want to create the AppRole "unblu" and encode the token policy "unblu-policy" onto generated tokens.

    Listing 17. Command to create an AppRole role for Unblu
    vault write auth/approle/role/unblu \
      token_policies="unblu-policy"

    Refer to the parameters section in the Vault documentation of the AppRole auth method API for a list of arguments you can provide when creating an AppRole role.

By default, the Collaboration Server makes a call to Vault to renew the authentication lease shortly before it expires. If the lease expires, any database credential leases created by the Postgres database secrets engine also expire.

Configuring the GCP IAM authentication method

To use the Google Cloud authentication method, proceed as follows:

  1. Enable the Google Cloud authentication method if you haven’t done so already:

    Listing 18. Command to enable the Google Cloud authentication method
    vault auth enable gcp
  2. Create an iam-type role for Unblu. The command below assumes you want to create the role "unblu-iam-role" and encode the token policy "unblu-policy" onto generated tokens.

    Listing 19. Command to create a iam-type GCP role for Unblu
    vault write auth/gcp/role/unblu-iam-role \
      type="iam" \
      policies="unblu-policy" \
      bound_service_accounts="<service-account>" (1)
    1 Replace <service-account> with an array of service account emails or IDs that login is restricted to.

    For a list of arguments you can provide when creating a role for Google Cloud authentication, refer to the parameters section of the "create role" endpoint in the Vault Google Cloud auth method API documentation.

Configuring the Kubernetes authentication method

To use the Kubernetes authentication method, proceed as follows:

  1. Enable the Kubernetes authentication method if you haven’t done so already:

    Listing 20. Command to enable the Kubernetes authentication method
    vault auth enable kubernetes
  2. Configure Vault to talk to Kubernetes:

    Listing 21. Command to configure for Vault to talk to Kubernetes
    vault write auth/kubernetes/config \
      kubernetes_host=https://127.0.0.1:12345 \ (1)
      kubernetes_ca_cert="<k8s-ca-cert>" (2)
    1 Replace 127.0.0.1:12345 with the IP address and port of your Kubernetes installation.
    2 Replace <k8s-ca-cert> with the CA certificate extracted from your Kubernetes installation.

    You can extract the Kubernetes host and CA certificate by running the following commands:

    Listing 22. Command to extract the CA certificate
    # Kubernetes host
    kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}'
    # CA certificate
    kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode
  3. Create a Kubernetes role for Unblu. The command below assumes you want to create the role "unblu-role" and encode the token policy "unblu-policy" onto generated tokens.

    Listing 23. Command to create a Kubernetes role for Unblu
    vault write auth/kubernetes/role/unblu-role \
      bound_service_account_names=default \
      bound_service_account_namespaces=unblu \
      policies=unblu-policy \
      ttl=5d

For information about the parameters available when configuring the Kubernetes authentication method, refer to the parameters sections of the various endpoints in the Vault Kubernetes auth method API documentation.

Configuring Unblu to use Vault

Once you’ve configured Vault, you must configure Unblu to use your Vault instance.

General configuration

  • com.unblu.vault.vaultAddress: The URL of your Vault server. If not specified, Unblu uses the value of the VAULT_ADDR environment variable.

Set com.unblu.vault.vaultAuthenticationMethod to specify the authentication method to use for Vault. The configuration property can take one of three values:

  • APPROLE for the AppRole authentication method.

  • GCP_IAM for the Google Cloud authentication method.

  • KUBERNETES for authentication against a Kubernetes Service Account Token.

There are different configuration properties related to the different authentication methods available.

  • com.unblu.vault.vaultAppRoleAuthenticationPath: The path to use for authentication with the AppRole method.

  • com.unblu.vault.vaultAppRoleAuthenticationRoleId[]: The role ID of the role to use for authentication with the AppRole method. To retrieve the role ID, run the following command:

    vault read -field=role_id auth/approle/role/<role-name>/role-id (1)
    1 Replace <role-name> with the name of the role you created for Unblu. In the example above, this was unblu.
  • com.unblu.vault.vaultAppRoleAuthenticationSecretId: The secret ID of the role to use for authentication with the AppRole method. To retrieve the role ID, run the following command:

    vault read -field=secret_id auth/approle/role/<role-name>/secret-id (1)
    1 Replace <role-name> with the name of the role you created for Unblu. In the example above, this was unblu.
  • config: com.unblu.vault.vaultGcpIamAuthenticationServiceAccountKey[]: GCP service account key in JSON format. If no value is specified, Unblu uses Google’s Application Default Credentials method.

  • config: com.unblu.vault.vaultGcpIamAuthenticationRole[]: The Vault iam-type role to use for authentication.

  • config: com.unblu.vault.vaultGcpIamAuthenticationPath[]: The Vault path to use for authentication.

Configuration properties for using Vault as a key/value secrets engine

The following configuration properties need only be set if you use Vault to store configuration properties:

Configuration properties for using Vault as a database secrets engine

The follow configuration properties need only be set if you use Vault as a database secrets engine:

See also