Complete Vagrant deployment

This commit is contained in:
Jan Dittberner 2023-08-08 15:21:27 +02:00
parent 4a7e46f2ad
commit 372532c943
19 changed files with 280 additions and 91 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
/.idea/
/.vagrant/
/deployment/*-from-vagrant.*
/mkcert_ca/
/tmp/

View file

@ -144,16 +144,11 @@ ansible-playbook to the Vagrant managed virtual machine.
```shell
sudo apt install vagrant-libvirt virt-manager libvirt-clients
vagrant up
vagrant ssh -- cat .local/share/mkcert/rootCA.pem | sudo tee /usr/local/share/ca-certificates/mkcert-vagrant-oidc.crt
sudo update-ca-certificates
CAROOT=$(pwd)/mkcert_ca mkcert -install
```
## Finally
*Note:* You may also want to configure your browser to trust the CA certificate
in `/usr/local/share/ca-certificates/mkcert-vagrant-oidc.crt`. If you do not
add this trust configuration you will get browser warnings for an unknown
certificate authority.
The last step installs the `mkcert` CA certificate in your user's browser trust
store.
## Testing your local setup
@ -162,7 +157,6 @@ After running `make` and `ansible-playbook`, Hydra and oidc-idp will both be run
To run the rest of the components, in each of two new terminal windows, execute
`oidc_app/demo-app` and `oidc_registration/cacert-oidc-registration`.
### Test the authorization server
Request the OpenID connect auto discovery information from Hydra

3
Vagrantfile vendored
View file

@ -27,5 +27,8 @@ Vagrant.configure("2") do |config|
"authserver" => ["oidcbox"],
"demoserver" => ["oidcbox"]
}
ansible.extra_vars = {
mkcert_caroot: "/vagrant/mkcert_ca"
}
end
end

View file

@ -1,2 +1,16 @@
---
hydra_home: /srv/hydra
oidc_urls:
hydra_admin:
host: hydra.cacert.localhost
port: 4445
hydra_public:
host: auth.cacert.localhost
port: 4444
idp:
host: login.cacert.localhost
port: 3000
demoapp:
host: app.cacert.localhost
port: 4000

View file

@ -0,0 +1,4 @@
---
demoapp_tls:
cert: "{{ cacert_home }}/etc/app.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/app.cacert.localhost-key.pem"

View file

@ -11,14 +11,14 @@ hydra_tls:
# different random values encrypted via ansible-vault
hydra_system_secret: "AczA+NZ25Ye9eAreglv5bo9XcND6uwBQHVUYCvPfwXo="
register_tls:
cert: "{{ cacert_home }}/etc/register.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/register.cacert.localhost-key.pem"
demoapp_tls:
cert: "{{ cacert_home }}/etc/app.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/app.cacert.localhost-key.pem"
idp_tls:
cert: "{{ cacert_home }}/etc/idp.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/idp.cacert.localhost-key.pem"
oidc_urls:
hydra_admin:
host: hydra.cacert.localhost
@ -33,8 +33,3 @@ oidc_urls:
demoapp:
host: app.cacert.localhost
port: 4000
register:
host: register.cacert.localhost
port: 5000
use_mkcert: true

View file

@ -11,29 +11,10 @@ hydra_tls:
# different random values encrypted via ansible-vault
hydra_system_secret: "AczA+NZ25Ye9eAreglv5bo9XcND6uwBQHVUYCvPfwXo="
register_tls:
cert: "{{ cacert_home }}/etc/register.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/register.cacert.localhost-key.pem"
idp_tls:
cert: "{{ cacert_home }}/etc/idp.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/idp.cacert.localhost-key.pem"
demoapp_tls:
cert: "{{ cacert_home }}/etc/app.cacert.localhost.pem"
key: "{{ cacert_home }}/etc/app.cacert.localhost-key.pem"
oidc_urls:
hydra_admin:
host: hydra.cacert.localhost
port: 4445
hydra_public:
host: auth.cacert.localhost
port: 4444
idp:
host: login.cacert.localhost
port: 3000
demoapp:
host: app.cacert.localhost
port: 4000
register:
host: register.cacert.localhost
port: 5000
use_mkcert: true

View file

@ -1,7 +1,7 @@
---
- name: hydra_systemd_reload
ansible.builtin.systemd:
state: started
state: restarted
name: hydra
daemon_reload: true
enabled: true

View file

@ -70,6 +70,8 @@
- name: Create Hydra key and certificate
ansible.builtin.command:
cmd: "mkcert -cert-file {{ hydra_cert_temp_dir.path }}/hydra.pem -key-file {{ hydra_cert_temp_dir.path }}/hydra.key.pem {{ oidc_urls.hydra_admin.host }} {{ oidc_urls.hydra_public.host }}"
environment:
CAROOT: "{{ mkcert_caroot | default(omit) }}"
- name: Move Hydra certificate and key to target
ansible.builtin.copy:
@ -89,30 +91,9 @@
path: "{{ hydra_cert_temp_dir.path }}"
state: absent
when: use_mkcert and not hydra_cert_st.stat.exists
when: not hydra_cert_st.stat.exists
become: false
- name: Copy Hydra key and certificate from inventory
block:
- name: Copy Hydra certificate
ansible.builtin.copy:
dest: "{{ hydra_tls.cert }}"
owner: root
group: "{{ hydra_os_group }}"
mode: '0644'
content: "{{ hydra_tls.certdata }}"
- name: Copy Hydra key
ansible.builtin.copy:
dest: "{{ hydra_tls.key }}"
owner: root
group: "{{ hydra_os_group }}"
mode: '0640'
content: "{{ hydra_tls.keydata }}"
when: not use_mkcert
- name: Run Hydra SQL migrations
ansible.builtin.command:
cmd: "{{ hydra_home }}/bin/hydra migrate sql --yes --read-from-env --config {{ hydra_home }}/etc/hydra.yml"

View file

@ -1,2 +1,4 @@
---
# defaults file for roles/oidc_demo_application
cacert_os_user: cacert
cacert_os_group: cacert
cacert_home: /srv/cacert

View file

@ -1,2 +1,7 @@
---
# handlers file for roles/oidc_demo_application
- name: demoapp_systemd_reload
ansible.builtin.systemd:
state: restarted
name: cacert-demoapp
daemon_reload: true
enabled: true

View file

@ -1,2 +1,166 @@
---
# tasks file for roles/oidc_demo_application
- name: Manage /etc/hosts
blockinfile:
path: /etc/hosts
create: true
block: |
127.0.0.1 localhost
127.0.0.2 bookworm
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
{{ oidc_urls.hydra_public.address | default(ansible_default_ipv4.address) }} {{ oidc_urls.hydra_public.host }}
127.0.0.1 {{ oidc_urls.demoapp.host }}
- name: Create CAcert group
ansible.builtin.group:
name: "{{ cacert_os_group }}"
state: present
system: true
- name: Create CAcert user
ansible.builtin.user:
name: "{{ cacert_os_user }}"
group: "{{ cacert_os_group }}"
home: "{{ cacert_home }}"
state: present
system: true
- name: Create CAcert directories
ansible.builtin.file:
path: "{{ cacert_home }}/{{ item.path }}"
owner: "{{ cacert_os_user }}"
group: "{{ cacert_os_group }}"
mode: "{{ item.mode }}"
state: directory
loop:
- { path: etc, mode: '0750' }
- { path: bin, mode: '0750' }
- { path: download, mode: '0750' }
- name: Create session directory
ansible.builtin.file:
path: "{{ demoapp_session_path | default('/var/cache/cacert/sessions') }}"
owner: "{{ cacert_os_user }}"
group: "{{ cacert_os_group }}"
mode: "0750"
state: directory
- name: Copy demo application binary
ansible.builtin.copy:
src: ../oidc_app/demo-app
dest: "{{ cacert_home }}/bin/cacert-oidcdemo"
owner: root
group: "{{ cacert_os_group }}"
mode: "0750"
- name: Check whether certificate exists
ansible.builtin.stat:
path: "{{ demoapp_tls.cert }}"
register: demoapp_cert_st
- name: Create demo application key and certificate with mkcert
block:
- name: Create temporary directory for demo application key and certificate
ansible.builtin.tempfile:
prefix: "demoapp-cert."
state: directory
register: demoapp_cert_temp_dir
- name: Create demo application key and certificate
ansible.builtin.command:
cmd: "mkcert -cert-file {{ demoapp_cert_temp_dir.path }}/demoapp.pem -key-file {{ demoapp_cert_temp_dir.path }}/demoapp.key.pem {{ oidc_urls.demoapp.host }}"
environment:
CAROOT: "{{ mkcert_caroot | default(omit) }}"
- name: Move demo application certificate and key to target
ansible.builtin.copy:
src: "{{ demoapp_cert_temp_dir.path }}/{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: "{{ cacert_os_group }}"
mode: "{{ item.mode }}"
remote_src: true
loop:
- {src: demoapp.pem, dest: "{{ demoapp_tls.cert }}", mode: '0644'}
- {src: demoapp.key.pem, dest: "{{ demoapp_tls.key }}", mode: '0640'}
become: true
- name: Remove temporary directory
ansible.builtin.file:
path: "{{ demoapp_cert_temp_dir.path }}"
state: absent
when: not demoapp_cert_st.stat.exists
become: false
- name: Check whether configuration file exists
ansible.builtin.stat:
path: "{{ cacert_home }}/etc/cacert-demoapp.toml"
register: demoapp_config_st
- name: Get credentials from existing file
block:
- name: fetch existing configuration file
ansible.builtin.fetch:
src: "{{ demoapp_config_st.stat.path }}"
dest: demoapp_config-from-vagrant.toml
flat: true
- name: set credential facts
ansible.builtin.set_fact:
demoapp_client_id: "{{ lookup('ansible.builtin.ini', 'client-id', section='oidc', file='demoapp_config-from-vagrant.toml') | from_json }}"
demoapp_client_secret: "{{ lookup('ansible.builtin.ini', 'client-secret', section='oidc', file='demoapp_config-from-vagrant.toml') | from_json }}"
demoapp_auth_key: "{{ lookup('ansible.builtin.ini', 'auth-key', section='session', file='demoapp_config-from-vagrant.toml') | from_json }}"
demoapp_enc_key: "{{ lookup('ansible.builtin.ini', 'enc-key', section='session', file='demoapp_config-from-vagrant.toml') | from_json }}"
when: demoapp_config_st.stat.exists
- name: Generate new credentials
block:
- name: Create new client via Hydra admin API
ansible.builtin.uri:
url: "https://{{ oidc_urls.hydra_admin.host }}:{{ oidc_urls.hydra_admin.port }}/admin/clients"
method: "POST"
body:
client_name: "CAcert OIDC demo application"
redirect_uris:
- "https://{{ oidc_urls.demoapp.host }}:{{ oidc_urls.demoapp.port }}/callback"
post_logout_redirect_uris:
- "https://{{ oidc_urls.demoapp.host }}:{{ oidc_urls.demoapp.port }}/after-logout"
scope: "openid email profile groups"
body_format: "json"
headers:
Accept: "application/json"
Content-Type: "application/json"
status_code: [201]
register: hydra_response
- name: Set credential facts
ansible.builtin.set_fact:
demoapp_client_id: "{{ hydra_response.json.client_id }}"
demoapp_client_secret: "{{ hydra_response.json.client_secret }}"
when: not demoapp_config_st.stat.exists
- name: Create demo application configuration
ansible.builtin.template:
src: demoapp_config.toml.j2
dest: "{{ cacert_home }}/etc/cacert-demoapp.toml"
owner: root
group: "{{ cacert_os_group }}"
mode: '0640'
notify: demoapp_systemd_reload
- name: Create demoapp systemd unit file
ansible.builtin.template:
src: cacert-demoapp.service.j2
dest: /etc/systemd/system/cacert-demoapp.service
owner: root
group: root
mode: "0640"
notify: demoapp_systemd_reload

View file

@ -0,0 +1,14 @@
[Unit]
Description=CAcert OpenID Connect demo application
After=network.target
Documentation=https://code.cacert.org/cacert/oidc-demo-app
[Service]
ExecStart={{ cacert_home }}/bin/cacert-oidcdemo --conf "{{ cacert_home }}/etc/cacert-demoapp.toml"
WorkingDirectory={{ cacert_home }}
User={{ cacert_os_user }}
Group={{ cacert_os_group }}
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,19 @@
[oidc]
client-id = "{{ demoapp_client_id }}"
client-secret = "{{ demoapp_client_secret }}"
server = "https://{{ oidc_urls.hydra_public.host }}:{{ oidc_urls.hydra_public.port }}/"
[server]
name = "{{ oidc_urls.demoapp.host }}"
address = "{{ oidc_urls.demoapp.address | default(ansible_default_ipv4.address) }}"
port = {{ oidc_urls.demoapp.address | default("4000") }}
certificate = "{{ demoapp_tls.cert }}"
key = "{{ demoapp_tls.key }}"
[session]
auth-key = "{{ demoapp_auth_key | default(lookup('community.general.random_string', length=64, base64=true)) }}"
enc-key = "{{ demoapp_enc_key | default(lookup('community.general.random_string', length=32, base64=true)) }}"
path = "{{ demoapp_session_path | default('/var/cache/cacert/sessions') }}"
[log]
level = "trace"

View file

@ -1,7 +1,7 @@
---
- name: idp_systemd_reload
ansible.builtin.systemd:
state: started
state: restarted
name: cacert-idp
daemon_reload: true
enabled: true

View file

@ -50,6 +50,8 @@
- name: Create IDP key and certificate
ansible.builtin.command:
cmd: "mkcert -cert-file {{ idp_cert_temp_dir.path }}/idp.pem -key-file {{ idp_cert_temp_dir.path }}/idp.key.pem {{ oidc_urls.idp.host }}"
environment:
CAROOT: "{{ mkcert_caroot | default(omit) }}"
- name: Move IDP certificate and key to target
ansible.builtin.copy:
@ -69,30 +71,9 @@
path: "{{ idp_cert_temp_dir.path }}"
state: absent
when: use_mkcert and not idp_cert_st.stat.exists
when: not idp_cert_st.stat.exists
become: false
- name: Copy IDP key and certificate from inventory
block:
- name: Copy IDP certificate
ansible.builtin.copy:
dest: "{{ idp_tls.cert }}"
owner: root
group: "{{ cacert_os_group }}"
mode: '0644'
content: "{{ idp.server_certificate_data }}"
- name: Copy IDP key
ansible.builtin.copy:
dest: "{{ idp_tls.key }}"
owner: root
group: "{{ cacert_os_group }}"
mode: '0640'
content: "{{ idp.server_key_data }}"
when: not use_mkcert
- name: Copy client CA certificates
ansible.builtin.copy:
dest: "{{ idp_tls.client_cas }}"
@ -101,6 +82,28 @@
mode: '0640'
content: "{{ idp.client_certificate_data }}"
- name: Check whether configuration file exists
ansible.builtin.stat:
path: "{{ cacert_home }}/etc/cacert-idp.toml"
register: idp_config_st
- name: Get credentials from existing file
block:
- name: fetch existing configuration file
ansible.builtin.fetch:
src: "{{ idp_config_st.stat.path }}"
dest: idp_config-from-vagrant.toml
flat: true
- name: set credential facts
ansible.builtin.set_fact:
idp_csrf_key: "{{ lookup('ansible.builtin.ini', 'csrf.key', section='security', file='idp_config-from-vagrant.toml') | from_json }}"
idp_auth_key: "{{ lookup('ansible.builtin.ini', 'auth-key', section='session', file='idp_config-from-vagrant.toml') | from_json }}"
idp_enc_key: "{{ lookup('ansible.builtin.ini', 'enc-key', section='session', file='idp_config-from-vagrant.toml') | from_json }}"
when: idp_config_st.stat.exists
- name: Create IDP configuration
ansible.builtin.template:
src: idp_config.toml.j2

View file

@ -8,5 +8,12 @@ port = {{ oidc_urls.idp.address | default("3000") }}
certificate = "{{ idp_tls.cert }}"
key = "{{ idp_tls.key }}"
[session]
auth-key = "{{ idp_auth_key | default(lookup('community.general.random_string', length=64, base64=true)) }}"
enc-key = "{{ idp_enc_key | default(lookup('community.general.random_string', length=32, base64=true)) }}"
[admin]
url = "https://{{ oidc_urls.hydra_admin.address | default("hydra.cacert.localhost") }}:{{ oidc_urls.hydra_admin.port | default("3000") }}"
[log]
level = "trace"

View file

@ -11,7 +11,8 @@
- name: Install mkcert CA
ansible.builtin.command:
cmd: "mkcert -install"
environment:
CAROOT: "{{ mkcert_caroot | default(omit) }}"
changed_when: false
when: use_mkcert
become: false

@ -1 +1 @@
Subproject commit a5c583f1f65cf5a09054ad7249c451551089cd0f
Subproject commit 9aeca21faa2db96ecd359e26eb4dc392d7c6bf1a