Skip to content

Commit f3842bf

Browse files
committed
add logic to detect eso source (openshift v golang)
1 parent 0a45528 commit f3842bf

5 files changed

Lines changed: 201 additions & 94 deletions

File tree

roles/vault_utils/defaults/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ vault_global_policy: global
1919
vault_global_capabilities: '[\\\"read\\\"]'
2020
vault_pushsecrets_policy: pushsecrets
2121
vault_pushsecrets_capabilities: '[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"list\\\",\\\"delete\\\"]'
22+
# Legacy community chart (golang-external-secrets)
2223
legacy_external_secrets_ns: golang-external-secrets
2324
legacy_external_secrets_sa: golang-external-secrets
2425
legacy_external_secrets_secret: golang-external-secrets
26+
# Red Hat openshift-external-secrets chart
2527
external_secrets_ns: external-secrets
26-
# The service account cannot be called "external-secrets" as that SA is used by the downstream ESO
28+
# The service account cannot be called "external-secrets" as that SA is used by the ESO operator
2729
external_secrets_sa: ocp-external-secrets
2830
external_secrets_secret: ocp-external-secrets
31+
# hub-role binds every SA whose token secret exists (see detect_external_secrets_auth.yml)
2932
unseal_secret: "vaultkeys"
3033
unseal_namespace: "imperative"
3134
vault_jwt_config: false
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
# Detect which External Secrets Operator service account tokens exist on the
3+
# cluster and build hub-role bindings. Supports both:
4+
# - openshift-external-secrets (ocp-external-secrets / external-secrets)
5+
# - golang-external-secrets (legacy community chart)
6+
#
7+
# Sets facts used by vault_secrets_init.yaml and vault_app_policies.yaml:
8+
# hub_bound_service_account_names - comma-separated for vault write
9+
# hub_bound_service_account_namespaces - comma-separated for vault write
10+
# hub_bound_service_account_names_list
11+
# hub_bound_service_account_namespaces_list
12+
# token_data / sa_token - reviewer JWT (prefers openshift)
13+
# active_external_secrets_sa - primary SA (for backwards compatibility)
14+
# active_external_secrets_ns
15+
# active_external_secrets_secret
16+
17+
- name: Check for openshift external secrets service account token
18+
no_log: '{{ hide_sensitive_output | default(true) }}'
19+
kubernetes.core.k8s_info:
20+
kind: Secret
21+
namespace: "{{ external_secrets_ns }}"
22+
name: "{{ external_secrets_secret }}"
23+
api_version: v1
24+
register: external_secrets_token_data
25+
failed_when: false
26+
27+
- name: Check for golang external secrets service account token
28+
no_log: '{{ hide_sensitive_output | default(true) }}'
29+
kubernetes.core.k8s_info:
30+
kind: Secret
31+
namespace: "{{ legacy_external_secrets_ns }}"
32+
name: "{{ legacy_external_secrets_secret }}"
33+
api_version: v1
34+
register: legacy_external_secrets_token_data
35+
failed_when: false
36+
37+
- name: Build hub-role service account binding lists
38+
ansible.builtin.set_fact:
39+
hub_bound_service_account_names_list: >-
40+
{{
41+
([] if external_secrets_token_data.resources | length == 0 else [external_secrets_sa])
42+
+ ([] if legacy_external_secrets_token_data.resources | length == 0 else [legacy_external_secrets_sa])
43+
}}
44+
hub_bound_service_account_namespaces_list: >-
45+
{{
46+
([] if external_secrets_token_data.resources | length == 0 else [external_secrets_ns])
47+
+ ([] if legacy_external_secrets_token_data.resources | length == 0 else [legacy_external_secrets_ns])
48+
}}
49+
50+
- name: Set comma-separated hub-role bindings for vault write
51+
ansible.builtin.set_fact:
52+
hub_bound_service_account_names: "{{ hub_bound_service_account_names_list | join(',') }}"
53+
hub_bound_service_account_namespaces: "{{ hub_bound_service_account_namespaces_list | join(',') }}"
54+
55+
- name: Fail if no external secrets service account tokens are found
56+
ansible.builtin.fail:
57+
msg: >-
58+
No External Secrets service account tokens found. Expected at least one of:
59+
{{ external_secrets_ns }}/{{ external_secrets_secret }} (openshift-external-secrets) or
60+
{{ legacy_external_secrets_ns }}/{{ legacy_external_secrets_secret }} (golang-external-secrets).
61+
Deploy openshift-external-secrets or golang-external-secrets before running load-secrets.
62+
when: hub_bound_service_account_names_list | length == 0
63+
64+
- name: Set token reviewer and primary ESO facts (prefer openshift over legacy)
65+
no_log: '{{ hide_sensitive_output | default(true) }}'
66+
ansible.builtin.set_fact:
67+
token_data: >-
68+
{{
69+
external_secrets_token_data
70+
if (external_secrets_token_data.resources | length > 0)
71+
else legacy_external_secrets_token_data
72+
}}
73+
active_external_secrets_sa: >-
74+
{{
75+
external_secrets_sa
76+
if (external_secrets_token_data.resources | length > 0)
77+
else legacy_external_secrets_sa
78+
}}
79+
active_external_secrets_ns: >-
80+
{{
81+
external_secrets_ns
82+
if (external_secrets_token_data.resources | length > 0)
83+
else legacy_external_secrets_ns
84+
}}
85+
active_external_secrets_secret: >-
86+
{{
87+
external_secrets_secret
88+
if (external_secrets_token_data.resources | length > 0)
89+
else legacy_external_secrets_secret
90+
}}
91+
92+
- name: Set sa_token fact
93+
no_log: '{{ hide_sensitive_output | default(true) }}'
94+
ansible.builtin.set_fact:
95+
sa_token: "{{ token_data.resources[0].data.token | b64decode }}"
96+
97+
- name: Debug - External secrets auth detection
98+
ansible.builtin.debug:
99+
msg: >-
100+
ESO hub-role bindings: names={{ hub_bound_service_account_names }},
101+
namespaces={{ hub_bound_service_account_namespaces }},
102+
token reviewer from {{ active_external_secrets_ns }}/{{ active_external_secrets_secret }}
103+
verbosity: 1

roles/vault_utils/tasks/vault_app_policies.yaml

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
verbosity: 1
4141
when: app_prefixes is not defined or app_prefixes | length == 0
4242

43+
- name: Detect external secrets service accounts for hub-role
44+
ansible.builtin.include_tasks: detect_external_secrets_auth.yml
45+
when: app_prefixes is defined and app_prefixes | length > 0
46+
4347
# Build list of policy names we need
4448
- name: Build app policy names list
4549
ansible.builtin.set_fact:
@@ -125,53 +129,28 @@
125129
- _hub_role_result.rc != 0
126130

127131
# Merge current and new policies (removing duplicates)
128-
- name: Merge policies
132+
- name: Merge hub-role policies with app policies
129133
ansible.builtin.set_fact:
130-
_merged_policies: "{{ (_current_policies + _app_policy_names) | unique }}"
134+
_merged_hub_policies: "{{ (_current_policies + _app_policy_names) | unique }}"
131135
when:
132136
- app_prefixes is defined and app_prefixes | length > 0
133137
- app_update_hub_role | default(true) | bool
134138

135-
# Check if hub-role policies need updating
136-
- name: Check if hub-role policies changed
137-
ansible.builtin.set_fact:
138-
_hub_role_policies_changed: "{{ _current_policies | sort != _merged_policies | sort }}"
139-
when:
140-
- app_prefixes is defined and app_prefixes | length > 0
141-
- app_update_hub_role | default(true) | bool
142-
143-
- name: Debug - Hub role policy change status
144-
ansible.builtin.debug:
145-
msg: "Hub role policies changed: {{ _hub_role_policies_changed }} (current: {{ _current_policies | sort }}, merged: {{ _merged_policies | sort }})"
146-
verbosity: 1
147-
when:
148-
- app_prefixes is defined and app_prefixes | length > 0
149-
- app_update_hub_role | default(true) | bool
150-
151-
# Update hub-role only if policies have changed
152-
- name: Update hub-role with app policies
153-
kubernetes.core.k8s_exec:
154-
namespace: "{{ vault_ns }}"
155-
pod: "{{ vault_pod }}"
156-
command: >
157-
vault write auth/{{ vault_hub }}/role/{{ vault_hub }}-role
158-
bound_service_account_names="{{ active_external_secrets_sa | default('golang-external-secrets') }}"
159-
bound_service_account_namespaces="{{ active_external_secrets_ns | default('golang-external-secrets') }}"
160-
policies="{{ _merged_policies | join(',') }}"
161-
ttl="{{ vault_hub_ttl }}"
139+
- name: Write hub-role with app policies and detected ESO service accounts
140+
ansible.builtin.include_tasks: write_hub_role.yml
162141
when:
163142
- app_prefixes is defined and app_prefixes | length > 0
164143
- app_update_hub_role | default(true) | bool
165-
- _hub_role_policies_changed | bool
166144

167145
- name: Display updated hub-role policies
168146
ansible.builtin.debug:
169-
msg: "hub-role policies updated to: {{ _merged_policies | join(', ') }}"
147+
msg: >-
148+
hub-role policies: {{ _merged_hub_policies | join(', ') }};
149+
bindings: {{ hub_bound_service_account_names }}/{{ hub_bound_service_account_namespaces }}
170150
verbosity: 1
171151
when:
172152
- app_prefixes is defined and app_prefixes | length > 0
173153
- app_update_hub_role | default(true) | bool
174-
- _hub_role_policies_changed | bool
175154

176155
# Optionally create JWT roles for app-level isolation
177156
# Only creates roles for entries that have jwt_role defined

roles/vault_utils/tasks/vault_secrets_init.yaml

Lines changed: 5 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -31,43 +31,8 @@
3131
command: "vault auth enable -path={{ vault_hub }} kubernetes"
3232
when: kubernetes_enabled.rc != 0
3333

34-
- name: Check for external secrets namespace and secret
35-
no_log: '{{ hide_sensitive_output | default(true) }}'
36-
kubernetes.core.k8s_info:
37-
kind: Secret
38-
namespace: "{{ external_secrets_ns }}"
39-
name: "{{ external_secrets_secret }}"
40-
api_version: v1
41-
register: external_secrets_token_data
42-
failed_when: false
43-
44-
- name: Check for legacy external secrets namespace and secret
45-
no_log: '{{ hide_sensitive_output | default(true) }}'
46-
kubernetes.core.k8s_info:
47-
kind: Secret
48-
namespace: "{{ legacy_external_secrets_ns }}"
49-
name: "{{ legacy_external_secrets_secret }}"
50-
api_version: v1
51-
register: legacy_external_secrets_token_data
52-
failed_when: false
53-
when: external_secrets_token_data.resources | length == 0
54-
55-
- name: Set external secrets configuration to use (prefer new over legacy)
56-
ansible.builtin.set_fact:
57-
active_external_secrets_ns: "{{ external_secrets_ns if external_secrets_token_data.resources | length > 0 else legacy_external_secrets_ns }}"
58-
active_external_secrets_sa: "{{ external_secrets_sa if external_secrets_token_data.resources | length > 0 else legacy_external_secrets_sa }}"
59-
active_external_secrets_secret: "{{ external_secrets_secret if external_secrets_token_data.resources | length > 0 else legacy_external_secrets_secret }}"
60-
token_data: "{{ external_secrets_token_data if external_secrets_token_data.resources | length > 0 else legacy_external_secrets_token_data }}"
61-
62-
- name: Fail if neither external secrets nor legacy external secrets are found
63-
ansible.builtin.fail:
64-
msg: "Neither {{ external_secrets_ns }}/{{ external_secrets_secret }} nor {{ legacy_external_secrets_ns }}/{{ legacy_external_secrets_secret }} secret found"
65-
when: token_data.resources | length == 0
66-
67-
- name: Set sa_token fact
68-
no_log: '{{ hide_sensitive_output | default(true) }}'
69-
ansible.builtin.set_fact:
70-
sa_token: "{{ token_data.resources[0].data.token | b64decode }}"
34+
- name: Detect external secrets service accounts for hub-role
35+
ansible.builtin.include_tasks: detect_external_secrets_auth.yml
7136

7237
- name: Configure hub kubernetes backend
7338
no_log: '{{ hide_sensitive_output | default(true) }}'
@@ -130,7 +95,7 @@
13095
pod: "{{ vault_pod }}"
13196
command: "vault policy write {{ vault_hub }}-secret /tmp/policy-{{ vault_hub }}.hcl"
13297

133-
# Get current hub-role policies to preserve any custom policies added by patterns
98+
# Preserve custom policies while ensuring VP defaults are present
13499
- name: Get current hub-role policies
135100
kubernetes.core.k8s_exec:
136101
namespace: "{{ vault_ns }}"
@@ -141,7 +106,6 @@
141106
failed_when: false
142107
changed_when: false
143108

144-
# Get existing policies (empty list if role doesn't exist yet)
145109
- name: Set current policies fact from existing hub-role
146110
ansible.builtin.set_fact:
147111
_current_hub_policies: "{{ (_hub_role_result.stdout | from_json).data.token_policies | default([]) }}"
@@ -152,29 +116,9 @@
152116
_current_hub_policies: []
153117
when: _hub_role_result.rc != 0
154118

155-
# Merge existing policies with defaults (preserves custom policies, ensures defaults present)
156119
- name: Merge hub-role policies
157120
ansible.builtin.set_fact:
158121
_merged_hub_policies: "{{ (_current_hub_policies + vault_hub_role_default_policies) | unique }}"
159122

160-
# Determine if we need to update the hub-role
161-
- name: Check if hub-role policies need updating
162-
ansible.builtin.set_fact:
163-
_hub_role_needs_update: "{{ (_hub_role_result.rc != 0) or (_current_hub_policies | sort != _merged_hub_policies | sort) }}"
164-
165-
- name: Debug - Hub role update status
166-
ansible.builtin.debug:
167-
msg: "Hub role needs update: {{ _hub_role_needs_update }} (role exists: {{ _hub_role_result.rc == 0 }}, current: {{ _current_hub_policies | sort }}, merged: {{ _merged_hub_policies | sort }})"
168-
verbosity: 1
169-
170-
- name: Configure kubernetes role for hub with merged policies
171-
kubernetes.core.k8s_exec:
172-
namespace: "{{ vault_ns }}"
173-
pod: "{{ vault_pod }}"
174-
command: >
175-
vault write auth/"{{ vault_hub }}"/role/"{{ vault_hub }}"-role
176-
bound_service_account_names="{{ active_external_secrets_sa }}"
177-
bound_service_account_namespaces="{{ active_external_secrets_ns }}"
178-
policies="{{ _merged_hub_policies | join(',') }}"
179-
ttl="{{ vault_hub_ttl }}"
180-
when: _hub_role_needs_update | bool
123+
- name: Write hub-role with all detected ESO service accounts
124+
ansible.builtin.include_tasks: write_hub_role.yml
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
# Write or update auth/<vault_hub>/role/<vault_hub>-role using hub_bound_service_account_* facts.
3+
# Requires: detect_external_secrets_auth.yml (or equivalent facts)
4+
# Policy list: _merged_hub_policies (vault_secrets_init) or _merged_policies (vault_app_policies)
5+
6+
- name: Normalize merged hub-role policies fact
7+
ansible.builtin.set_fact:
8+
_merged_hub_policies: >-
9+
{{
10+
_merged_hub_policies
11+
| default(_merged_policies)
12+
| default(vault_hub_role_default_policies)
13+
}}
14+
15+
- name: Get current hub-role for comparison
16+
kubernetes.core.k8s_exec:
17+
namespace: "{{ vault_ns }}"
18+
pod: "{{ vault_pod }}"
19+
command: >
20+
vault read -format=json auth/{{ vault_hub }}/role/{{ vault_hub }}-role
21+
register: _hub_role_read
22+
failed_when: false
23+
changed_when: false
24+
25+
- name: Parse existing hub-role policies
26+
ansible.builtin.set_fact:
27+
_current_hub_policies: "{{ (_hub_role_read.stdout | from_json).data.token_policies | default([]) }}"
28+
when: _hub_role_read.rc == 0
29+
30+
- name: Set empty hub-role policies when role does not exist
31+
ansible.builtin.set_fact:
32+
_current_hub_policies: []
33+
when: _hub_role_read.rc != 0
34+
35+
- name: Parse existing hub-role service account bindings
36+
ansible.builtin.set_fact:
37+
_current_hub_bound_names: "{{ (_hub_role_read.stdout | from_json).data.bound_service_account_names | default([]) }}"
38+
_current_hub_bound_namespaces: "{{ (_hub_role_read.stdout | from_json).data.bound_service_account_namespaces | default([]) }}"
39+
when: _hub_role_read.rc == 0
40+
41+
- name: Set empty hub-role bindings when role does not exist
42+
ansible.builtin.set_fact:
43+
_current_hub_bound_names: []
44+
_current_hub_bound_namespaces: []
45+
when: _hub_role_read.rc != 0
46+
47+
- name: Check if hub-role needs updating
48+
ansible.builtin.set_fact:
49+
_hub_role_needs_update: >-
50+
{{
51+
(_hub_role_read.rc != 0)
52+
or (_current_hub_policies | sort != _merged_hub_policies | sort)
53+
or (_current_hub_bound_names | sort != hub_bound_service_account_names_list | sort)
54+
or (_current_hub_bound_namespaces | sort != hub_bound_service_account_namespaces_list | sort)
55+
}}
56+
57+
- name: Debug - Hub role update status
58+
ansible.builtin.debug:
59+
msg: >-
60+
Hub role needs update: {{ _hub_role_needs_update }}
61+
(policies changed: {{ _current_hub_policies | sort != _merged_hub_policies | sort }},
62+
bindings changed: {{
63+
(_current_hub_bound_names | sort != hub_bound_service_account_names_list | sort)
64+
or (_current_hub_bound_namespaces | sort != hub_bound_service_account_namespaces_list | sort)
65+
}})
66+
verbosity: 1
67+
68+
- name: Configure kubernetes role for hub
69+
kubernetes.core.k8s_exec:
70+
namespace: "{{ vault_ns }}"
71+
pod: "{{ vault_pod }}"
72+
command: >
73+
vault write auth/"{{ vault_hub }}"/role/"{{ vault_hub }}"-role
74+
bound_service_account_names="{{ hub_bound_service_account_names }}"
75+
bound_service_account_namespaces="{{ hub_bound_service_account_namespaces }}"
76+
policies="{{ _merged_hub_policies | join(',') }}"
77+
ttl="{{ vault_hub_ttl }}"
78+
when: _hub_role_needs_update | bool

0 commit comments

Comments
 (0)