Deploying HashiCorp Vault Using Ansible

  ·   4 min read

HashiCorp Vault is a powerful tool for managing secrets and protecting sensitive data. Deploying Vault in a consistent and automated manner is crucial for maintaining a secure infrastructure. In this article, we will explore how to deploy HashiCorp Vault using Ansible, a popular open-source automation tool. We will create an Ansible role to streamline the deployment process, ensuring that Vault is installed and configured correctly on your infrastructure.

Prerequisites

Before we begin, ensure you have the following:

  1. Ansible: Installed on your local machine. You can install it using pip:

    pip install ansible
    
  2. SSH Access: Ensure you have SSH access to the target servers where Vault will be deployed.

  3. Servers: At least one server to deploy Vault. For production, consider a highly available setup with multiple nodes.

  4. Ansible Inventory: A basic inventory file listing your target servers.

Creating an Ansible Role for Vault

Ansible roles allow you to organize tasks, handlers, and variables in a structured way. Let’s create a role named vault to handle the deployment.

Step 1: Create the Role Structure

Run the following command to create the role structure:

ansible-galaxy init vault

This command will create a directory named vault with the following structure:

vault/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

Step 2: Define Variables

Edit vault/defaults/main.yml to define default variables for Vault installation:

vault_version: "1.13.0"
vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_amd64.zip"
vault_install_dir: "/usr/local/bin"
vault_user: "vault"
vault_group: "vault"
vault_config_dir: "/etc/vault.d"
vault_data_dir: "/opt/vault"

Step 3: Create Tasks

Edit vault/tasks/main.yml to define the tasks for installing and configuring Vault:

---
- name: Ensure Vault group exists
  group:
    name: "{{ vault_group }}"
    state: present

- name: Ensure Vault user exists
  user:
    name: "{{ vault_user }}"
    group: "{{ vault_group }}"
    create_home: no
    shell: /bin/false

- name: Download Vault
  get_url:
    url: "{{ vault_download_url }}"
    dest: "/tmp/vault_{{ vault_version }}.zip"
    mode: '0644'

- name: Unzip Vault binary
  unarchive:
    src: "/tmp/vault_{{ vault_version }}.zip"
    dest: "{{ vault_install_dir }}"
    remote_src: yes
    mode: '0755'
  notify: Restart Vault

- name: Create Vault configuration directory
  file:
    path: "{{ vault_config_dir }}"
    state: directory
    owner: "{{ vault_user }}"
    group: "{{ vault_group }}"
    mode: '0750'

- name: Create Vault data directory
  file:
    path: "{{ vault_data_dir }}"
    state: directory
    owner: "{{ vault_user }}"
    group: "{{ vault_group }}"
    mode: '0750'

- name: Copy Vault configuration
  template:
    src: vault.hcl.j2
    dest: "{{ vault_config_dir }}/vault.hcl"
    owner: "{{ vault_user }}"
    group: "{{ vault_group }}"
    mode: '0640'
  notify: Restart Vault

- name: Create systemd service for Vault
  template:
    src: vault.service.j2
    dest: /etc/systemd/system/vault.service
  notify: Restart Vault

- name: Enable and start Vault service
  systemd:
    name: vault
    enabled: yes
    state: started

Step 4: Create Templates

Create a Vault configuration template vault/templates/vault.hcl.j2:

storage "file" {
  path = "{{ vault_data_dir }}"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = 1
}

ui = true

Create a systemd service template vault/templates/vault.service.j2:

[Unit]
Description=Vault service
After=network.target

[Service]
User={{ vault_user }}
Group={{ vault_group }}
ExecStart={{ vault_install_dir }}/vault server -config={{ vault_config_dir }}/vault.hcl
ExecReload=/bin/kill -HUP $MAINPID
LimitNOFILE=65536
Restart=on-failure

[Install]
WantedBy=multi-user.target

Step 5: Define Handlers

Edit vault/handlers/main.yml to define a handler for restarting Vault:

---
- name: Restart Vault
  systemd:
    name: vault
    state: restarted

Step 6: Use the Role in a Playbook

Create a playbook deploy_vault.yml to use the vault role:

---
- hosts: all
  become: yes
  roles:
    - vault

Step 7: Run the Playbook

Execute the playbook to deploy Vault:

ansible-playbook -i inventory deploy_vault.yml

Conclusion

By following these steps, you have successfully created an Ansible role to automate the deployment of HashiCorp Vault. This approach ensures a consistent and repeatable deployment process, enhancing the security and reliability of your infrastructure. You can further customize the role to suit your specific requirements, such as integrating with a backend storage solution or enabling TLS.

For more information on Ansible and HashiCorp Vault, consider the following resources:

By leveraging the power of Ansible, you can efficiently manage your infrastructure and ensure that your secrets management solution is deployed securely and reliably.