Skip to content

Commit

Permalink
Add ldap support to vault container in docker dev environment (#14777)
Browse files Browse the repository at this point in the history
* add ldap_auth mount and configure it

* added in key engines, userpass auth method, still needs testing

* add policies and fix ldap_user

* start awx automation for vault demo and move ldap

* update docs with new flags/new credentials
  • Loading branch information
thedoubl3j authored Feb 9, 2024
1 parent 2e5306a commit 519fd22
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 15 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,8 @@ docker-compose: awx/projects docker-compose-sources
ansible-galaxy install --ignore-certs -r tools/docker-compose/ansible/requirements.yml;
ansible-playbook -i tools/docker-compose/inventory tools/docker-compose/ansible/initialize_containers.yml \
-e enable_vault=$(VAULT) \
-e vault_tls=$(VAULT_TLS);
-e vault_tls=$(VAULT_TLS) \
-e enable_ldap=$(LDAP);
$(DOCKER_COMPOSE) -f tools/docker-compose/_sources/docker-compose.yml $(COMPOSE_OPTS) up $(COMPOSE_UP_OPTS) --remove-orphans

docker-compose-credential-plugins: awx/projects docker-compose-sources
Expand Down
47 changes: 44 additions & 3 deletions tools/docker-compose/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,13 +538,15 @@ To create a secret connected to this vault in AWX you can run the following play
```bash
export CONTROLLER_USERNAME=<your username>
export CONTROLLER_PASSWORD=<your password>
ansible-playbook tools/docker-compose/ansible/plumb_vault.yml
ansible-playbook tools/docker-compose/ansible/plumb_vault.yml -e enable_ldap=false
```

This will create the following items in your AWX instance:
* A credential called `Vault Lookup Cred` tied to the vault instance.
* A credential called `Vault UserPass Lookup Cred` tied to the vault instance.
* A custom credential type called `Vault Custom Cred Type`.
* A credential called `Credential From Vault` which is of the created type using the `Vault Lookup Cred` to get the password.
* A credential called `Credential From HashiCorp Vault via Token Auth` which is of the created type using the `Vault Lookup Cred` to get the secret.
* A credential called `Credential From HashiCorp Vault via UserPass Auth` which is of the created type using the `Vault Userpass Lookup Cred` to get the secret.

The custom credential type adds a variable when used in a playbook called `the_secret_from_vault`.
If you have a playbook like:
Expand All @@ -559,7 +561,46 @@ If you have a playbook like:
var: the_secret_from_vault
```

And run it through AWX with the credential `Credential From Vault` tied to it, the debug should result in `this_is_the_secret_value`
And run it through AWX with the credential `Credential From Vault via Token Auth` tied to it, the debug should result in `this_is_the_secret_value`. If you run it through AWX with the credential `Credential From Vault via Userpass Auth`, the debug should result in `this_is_the_userpass_secret_value`.

### HashiVault with LDAP

If you wish to have your OpenLDAP container connected to the Vault container, you will first need to have the OpenLDAP container running alongside AWX and Vault.


```bash
VAULT=true LDAP=true make docker-compose
```

Similar to the above, you will need to unseal the vault before we can run the other needed playbooks.

```bash
ansible-playbook tools/docker-compose/ansible/unseal_vault.yml
```

Now that the vault is unsealed, we can plumb the vault container now while passing true to enable_ldap extra var.


```bash
export CONTROLLER_USERNAME=<your username>
export CONTROLLER_PASSWORD=<your password>
ansible-playbook tools/docker-compose/ansible/plumb_vault.yml -e enable_ldap=true
```

This will populate your AWX instance with LDAP specific items.

- A vault LDAP Lookup Cred tied to the LDAP `awx_ldap_vault` user called `Vault LDAP Lookup Cred`
- A credential called `Credential From HashiCorp Vault via LDAP Auth` which is of the created type using the `Vault LDAP Lookup Cred` to get the secret.

And run it through AWX with the credential `Credential From HashiCorp Vault via LDAP Auth` tied to it, the debug should result in `this_is_the_ldap_secret_value`.

The extremely non-obvious input is the fact that the fact prefixes "data/" unexpectedly.
This was discovered by inspecting the secret with the vault CLI, which may help with future troubleshooting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ldap_cert_subject: "/C=US/ST=NC/L=Durham/O=awx/CN="
enable_vault: false
vault_tls: false
hashivault_cert_dir: '{{ sources_dest }}/vault_certs'
hashivault_vars_file: '../vault/defaults/main.yml'
hashivault_server_cert_subject: "/C=US/ST=NC/L=Durham/O=awx/CN=tools-vault-1"
hashivault_server_cert_extensions:
- "subjectAltName = DNS:tools_vault_1, DNS:localhost"
Expand Down
7 changes: 5 additions & 2 deletions tools/docker-compose/ansible/roles/sources/tasks/ldap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
- "{{ ldap_cert_dir }}"
- "{{ ldap_diff_dir }}"

- name: include vault vars
include_vars: "{{ hashivault_vars_file }}"

- name: General LDAP cert
command: 'openssl req -new -x509 -days 365 -nodes -out {{ ldap_public_key_file }} -keyout {{ ldap_private_key_file }} -subj "{{ ldap_cert_subject }}"'
args:
creates: "{{ ldap_public_key_file }}"

- name: Copy ldap.diff
copy:
src: "ldap.ldif"
ansible.builtin.template:
src: "ldap.ldif.j2"
dest: "{{ ldap_diff_dir }}/ldap.ldif"
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,16 @@ objectClass: top
objectClass: groupOfNames
member: cn=awx_ldap_org_admin,ou=users,dc=example,dc=org

{% if enable_ldap|bool and enable_vault|bool %}
dn: cn={{ vault_ldap_username }},ou=users,dc=example,dc=org
changetype: add
mail: vault@example.org
sn: LdapVaultAdmin
cn: {{ vault_ldap_username }}
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
userPassword: {{ vault_ldap_password }}
givenName: awx
{% endif %}
7 changes: 6 additions & 1 deletion tools/docker-compose/ansible/roles/vault/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
---
vault_file: "{{ sources_dest }}/secrets/vault_init.yml"
admin_password_file: "{{ sources_dest }}/secrets/admin_password.yml"
vault_cert_dir: '{{ sources_dest }}/vault_certs'
vault_cert_dir: "{{ sources_dest }}/vault_certs"
vault_server_cert: "{{ vault_cert_dir }}/server.crt"
vault_client_cert: "{{ vault_cert_dir }}/client.crt"
vault_client_key: "{{ vault_cert_dir }}/client.key"
ldap_ldif: "{{ sources_dest }}/ldap.ldifs/ldap.ldif"
vault_ldap_username: "awx_ldap_vault"
vault_ldap_password: "vault123"
vault_userpass_username: "awx_userpass_admin"
vault_userpass_password: "userpass123"
122 changes: 122 additions & 0 deletions tools/docker-compose/ansible/roles/vault/tasks/initialize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,128 @@
validate_certs: false
token: "{{ Initial_Root_Token }}"

- name: Configure the vault ldap auth
block:
- name: Create ldap auth mount
flowerysong.hvault.write:
path: "sys/auth/ldap"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
data:
type: "ldap"
register: vault_auth_ldap
changed_when: vault_auth_ldap.result.errors | default([]) | length == 0
failed_when:
- vault_auth_ldap.result.errors | default([]) | length > 0
- "'path is already in use at ldap/' not in vault_auth_ldap.result.errors | default([])"

- name: Create ldap engine
flowerysong.hvault.engine:
path: "ldap_engine"
type: "kv"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"

- name: Create a ldap secret
flowerysong.hvault.kv:
mount_point: "ldap_engine/ldaps_root"
key: "ldap_secret"
value:
my_key: "this_is_the_ldap_secret_value"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"

- name: Configure ldap auth
flowerysong.hvault.ldap_config:
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
url: "ldap://ldap:1389"
binddn: "cn=awx_ldap_vault,ou=users,dc=example,dc=org"
bindpass: "vault123"
userdn: "ou=users,dc=example,dc=org"
deny_null_bind: "false"
discoverdn: "true"

- name: Create ldap access policy
flowerysong.hvault.policy:
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
name: "ldap_engine"
policy:
ldap_engine/*: [create, read, update, delete, list]
sys/mounts:/*: [create, read, update, delete, list]
sys/mounts: [read]

- name: Add awx_ldap_vault user to auth_method
flowerysong.hvault.ldap_user:
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
state: present
name: "{{ vault_ldap_username }}"
policies:
- "ldap_engine"
when: enable_ldap | bool

- name: Create userpass engine
flowerysong.hvault.engine:
path: "userpass_engine"
type: "kv"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"

- name: Create a userpass secret
flowerysong.hvault.kv:
mount_point: "userpass_engine/userpass_root"
key: "userpass_secret"
value:
my_key: "this_is_the_userpass_secret_value"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"

- name: Create userpass access policy
flowerysong.hvault.policy:
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
name: "userpass_engine"
policy:
userpass_engine/*: [create, read, update, delete, list]
sys/mounts:/*: [create, read, update, delete, list]
sys/mounts: [read]

- name: Create userpass auth mount
flowerysong.hvault.write:
path: "sys/auth/userpass"
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
data:
type: "userpass"
register: vault_auth_userpass
changed_when: vault_auth_userpass.result.errors | default([]) | length == 0
failed_when:
- vault_auth_userpass.result.errors | default([]) | length > 0
- "'path is already in use at userpass/' not in vault_auth_userpass.result.errors | default([])"

- name: Add awx_userpass_admin user to auth_method
flowerysong.hvault.write:
vault_addr: "{{ vault_addr_from_host }}"
validate_certs: false
token: "{{ Initial_Root_Token }}"
path: "auth/userpass/users/{{ vault_userpass_username }}"
data:
password: "{{ vault_userpass_password }}"
policies:
- "userpass_engine"

always:
- name: Stop the vault
community.docker.docker_compose:
Expand Down
Loading

0 comments on commit 519fd22

Please sign in to comment.