Skip to content

Commit d2c2c55

Browse files
committed
feat: add SASL support to operation playbooks and new SASL playbooks
Updates operation playbooks to support SASL-enabled clusters: - operation-rolling-restart.yml: Add rpk_opts/rpk_admin_opts for SASL auth - operation-apply-license.yml: Add SASL support for license application - operation-configure-logging.yml: Add SASL support for logging config New playbooks: - provision-cluster-tls-sasl.yml: Deploy TLS + SASL enabled clusters - manage-sasl-users.yml: Manage SASL users and ACLs via user_management role Usage: Pass SASL credentials via extra vars: -e "kafka_enable_authorization=true" -e "admin_api_require_auth=true" -e "sasl_superuser_username=admin" -e "sasl_superuser_password=<password>"
1 parent 4206e55 commit d2c2c55

File tree

6 files changed

+259
-15
lines changed

6 files changed

+259
-15
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,36 @@ ansible-playbook ansible/deploy-client.yml --private-key ~/.ssh/id_rsa
6363

6464
The playbooks can all be run in any order. However they are designed with the assumption that you will run only either the TLS or non TLS playbooks, not both. Currently we do not support converting a cluster from non-TLS to TLS or vice versa.
6565

66+
## SASL Authentication Deployments
67+
68+
### TLS + SASL Cluster
69+
70+
Deploy a cluster with both TLS encryption and SASL authentication:
71+
72+
```bash
73+
export REDPANDA_SASL_PASSWORD="your-secure-password"
74+
export SR_SERVICE_PASSWORD="schema-registry-password"
75+
export PP_SERVICE_PASSWORD="pandaproxy-password"
76+
77+
ansible-playbook ansible/provision-cluster-tls-sasl.yml \
78+
--private-key ~/.ssh/id_rsa \
79+
--inventory artifacts/hosts_gcp_$DEPLOYMENT_PREFIX.ini
80+
```
81+
82+
### Managing Users and ACLs
83+
84+
After deploying a SASL-enabled cluster, you can manage additional users and ACLs:
85+
86+
```bash
87+
export REDPANDA_SASL_PASSWORD="your-admin-password"
88+
export PRODUCER_APP_PASSWORD="producer-password"
89+
export CONSUMER_APP_PASSWORD="consumer-password"
90+
91+
ansible-playbook ansible/manage-sasl-users.yml \
92+
--private-key ~/.ssh/id_rsa \
93+
--inventory artifacts/hosts_gcp_$DEPLOYMENT_PREFIX.ini
94+
```
95+
6696
## Additional Documentation
6797

6898
More information on consuming this collection

ansible/manage-sasl-users.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
# manages users, roles, and ACLs declaratively via user_management role
3+
- name: Manage SASL Users, Roles, and ACLs
4+
hosts: redpanda[0]
5+
become: true
6+
vars:
7+
enable_tls: true
8+
redpanda_truststore_file: "/etc/redpanda/certs/truststore.pem"
9+
sasl_admin_username: "admin"
10+
sasl_admin_password: "{{ lookup('env', 'REDPANDA_SASL_PASSWORD') }}"
11+
12+
# users (set state: absent to delete)
13+
sasl_users:
14+
- username: "producer_app"
15+
password: "{{ lookup('env', 'PRODUCER_APP_PASSWORD') | default('producer-secret', true) }}"
16+
mechanism: "SCRAM-SHA-256"
17+
state: present
18+
19+
- username: "consumer_app"
20+
password: "{{ lookup('env', 'CONSUMER_APP_PASSWORD') | default('consumer-secret', true) }}"
21+
mechanism: "SCRAM-SHA-256"
22+
state: present
23+
24+
# roles (enterprise RBAC)
25+
sasl_roles: []
26+
27+
# kafka ACLs
28+
sasl_acls:
29+
- principal: "User:producer_app"
30+
resource_type: topic
31+
resource_name: "events-"
32+
pattern_type: prefixed
33+
operation:
34+
- write
35+
- describe
36+
permission: allow
37+
state: present
38+
39+
- principal: "User:consumer_app"
40+
resource_type: topic
41+
resource_name: "events-"
42+
pattern_type: prefixed
43+
operation:
44+
- read
45+
- describe
46+
permission: allow
47+
state: present
48+
49+
- principal: "User:consumer_app"
50+
resource_type: group
51+
resource_name: "consumer-"
52+
pattern_type: prefixed
53+
operation: read
54+
permission: allow
55+
state: present
56+
57+
# schema registry ACLs (enterprise)
58+
schema_registry_acls:
59+
- principal: "User:producer_app"
60+
resource_type: subject
61+
resource_name: "events-"
62+
pattern_type: prefixed
63+
operation: write
64+
permission: allow
65+
state: present
66+
67+
- principal: "User:consumer_app"
68+
resource_type: subject
69+
resource_name: "events-"
70+
pattern_type: prefixed
71+
operation: read
72+
permission: allow
73+
state: present
74+
75+
roles:
76+
- role: redpanda.cluster.user_management

ansible/operation-apply-license.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,54 @@
55
vars:
66
rpk_bin: rpk
77

8+
# SASL/TLS settings for authenticated clusters
9+
kafka_enable_authorization: false
10+
admin_api_require_auth: false
11+
sasl_superuser_username: "admin"
12+
sasl_superuser_password: ""
13+
enable_tls: false
14+
redpanda_truststore_file: /etc/redpanda/certs/truststore.pem
15+
redpanda_kafka_port: 9092
16+
17+
rpk_opts: >-
18+
-X brokers={{ hostvars[inventory_hostname].private_ip | default(ansible_default_ipv4.address) }}:{{ redpanda_kafka_port }}
19+
{% if enable_tls | default(false) %}-X tls.enabled=true -X tls.ca={{ redpanda_truststore_file }}{% endif %}
20+
{% if kafka_enable_authorization | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }} -X sasl.mechanism=SCRAM-SHA-256{% endif %}
21+
22+
rpk_admin_opts: >-
23+
{% if enable_tls | default(false) %}-X admin.tls.enabled=true -X admin.tls.ca={{ redpanda_truststore_file }}{% endif %}
24+
{% if admin_api_require_auth | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }}{% endif %}
25+
826
tasks:
927
- name: Check cluster health
1028
ansible.builtin.shell: |
11-
{{ rpk_bin }} cluster health | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
29+
{{ rpk_bin }} cluster health {{ rpk_opts }} {{ rpk_admin_opts }} | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
1230
register: health_check
1331
run_once: true
1432
failed_when: "health_check.stdout != 'true'"
1533
changed_when: false
34+
no_log: "{{ kafka_enable_authorization | default(false) }}"
1635

1736
- name: Set Redpanda license (string)
18-
ansible.builtin.command: rpk cluster license set {{ redpanda_license }}
37+
ansible.builtin.command: "{{ rpk_bin }} cluster license set {{ redpanda_license }} {{ rpk_opts }} {{ rpk_admin_opts }}"
1938
run_once: true
2039
changed_when: false
2140
when:
2241
- redpanda_license is defined
42+
no_log: true
2343

2444
- name: Set Redpanda license (path)
25-
ansible.builtin.command: rpk cluster license set --path {{ redpanda_license_path }}
45+
ansible.builtin.command: "{{ rpk_bin }} cluster license set --path {{ redpanda_license_path }} {{ rpk_opts }} {{ rpk_admin_opts }}"
2646
changed_when: false
2747
run_once: true
2848
when:
2949
- redpanda_license_path is defined
50+
no_log: "{{ kafka_enable_authorization | default(false) }}"
3051

3152
- name: Check broker status
3253
ansible.builtin.shell: |
33-
{{ rpk_bin }} redpanda admin brokers list | grep -q 'active.*true'
54+
{{ rpk_bin }} redpanda admin brokers list {{ rpk_admin_opts }} | grep -q 'active.*true'
3455
register: broker_status
3556
changed_when: false
3657
failed_when: broker_status.rc != 0
58+
no_log: "{{ kafka_enable_authorization | default(false) }}"

ansible/operation-configure-logging.yml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,34 @@
55
vars:
66
rpk_bin: rpk
77

8+
# SASL/TLS settings for authenticated clusters
9+
kafka_enable_authorization: false
10+
admin_api_require_auth: false
11+
sasl_superuser_username: "admin"
12+
sasl_superuser_password: ""
13+
enable_tls: false
14+
redpanda_truststore_file: /etc/redpanda/certs/truststore.pem
15+
redpanda_kafka_port: 9092
16+
17+
rpk_opts: >-
18+
-X brokers={{ hostvars[inventory_hostname].private_ip | default(ansible_default_ipv4.address) }}:{{ redpanda_kafka_port }}
19+
{% if enable_tls | default(false) %}-X tls.enabled=true -X tls.ca={{ redpanda_truststore_file }}{% endif %}
20+
{% if kafka_enable_authorization | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }} -X sasl.mechanism=SCRAM-SHA-256{% endif %}
21+
22+
rpk_admin_opts: >-
23+
{% if enable_tls | default(false) %}-X admin.tls.enabled=true -X admin.tls.ca={{ redpanda_truststore_file }}{% endif %}
24+
{% if admin_api_require_auth | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }}{% endif %}
25+
826
tasks:
927
- name: Check cluster health
1028
ansible.builtin.shell: |
1129
set -o pipefail
12-
{{ rpk_bin }} cluster health | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
30+
{{ rpk_bin }} cluster health {{ rpk_opts }} {{ rpk_admin_opts }} | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
1331
register: health_check
1432
run_once: true
1533
failed_when: "health_check.stdout != 'true'"
1634
changed_when: false
35+
no_log: "{{ kafka_enable_authorization | default(false) }}"
1736

1837
- name: Apply logging role
1938
ansible.builtin.include_role:
@@ -59,10 +78,11 @@
5978
- name: Check broker status
6079
ansible.builtin.shell: |
6180
set -o pipefail
62-
{{ rpk_bin }} redpanda admin brokers list | grep -q 'active.*true'
81+
{{ rpk_bin }} redpanda admin brokers list {{ rpk_admin_opts }} | grep -q 'active.*true'
6382
register: broker_status
6483
changed_when: false
6584
failed_when: broker_status.rc != 0
85+
no_log: "{{ kafka_enable_authorization | default(false) }}"
6686

6787
- name: Display logging configuration summary
6888
ansible.builtin.debug:

ansible/operation-rolling-restart.yml

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,66 @@
66
vars:
77
rpk_bin: rpk
88

9+
# SASL/TLS settings for authenticated clusters
10+
kafka_enable_authorization: false
11+
admin_api_require_auth: false
12+
sasl_superuser_username: "admin"
13+
sasl_superuser_password: ""
14+
enable_tls: false
15+
redpanda_truststore_file: /etc/redpanda/certs/truststore.pem
16+
redpanda_kafka_port: 9092
17+
18+
rpk_opts: >-
19+
-X brokers={{ hostvars[inventory_hostname].private_ip | default(ansible_default_ipv4.address) }}:{{ redpanda_kafka_port }}
20+
{% if enable_tls | default(false) %}-X tls.enabled=true -X tls.ca={{ redpanda_truststore_file }}{% endif %}
21+
{% if kafka_enable_authorization | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }} -X sasl.mechanism=SCRAM-SHA-256{% endif %}
22+
23+
rpk_admin_opts: >-
24+
{% if enable_tls | default(false) %}-X admin.tls.enabled=true -X admin.tls.ca={{ redpanda_truststore_file }}{% endif %}
25+
{% if admin_api_require_auth | default(false) and sasl_superuser_password != '' %}-X user={{ sasl_superuser_username }} -X pass={{ sasl_superuser_password }}{% endif %}
26+
927
tasks:
1028
- name: Check cluster health
1129
ansible.builtin.shell: |
12-
{{ rpk_bin }} cluster health | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
30+
{{ rpk_bin }} cluster health {{ rpk_opts }} {{ rpk_admin_opts }} | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
1331
register: health_check
1432
failed_when: "health_check.stdout != 'true'"
1533
changed_when: false
34+
no_log: "{{ kafka_enable_authorization | default(false) }}"
1635

1736
- name: Get node ID
1837
ansible.builtin.shell: |
19-
{{ rpk_bin }} cluster info | awk '$2 == "{{ ansible_host }}" {gsub("\\*", "", $1); print $1}'
38+
{{ rpk_bin }} cluster info {{ rpk_opts }} | awk '$2 == "{{ ansible_host }}" {gsub("\\*", "", $1); print $1}'
2039
register: node_id
2140
changed_when: false
41+
no_log: "{{ kafka_enable_authorization | default(false) }}"
2242

2343
- name: Enable maintenance mode
24-
ansible.builtin.command: "{{ rpk_bin }} cluster maintenance enable {{ node_id.stdout }} --wait"
44+
ansible.builtin.command: "{{ rpk_bin }} cluster maintenance enable {{ node_id.stdout }} --wait {{ rpk_opts }} {{ rpk_admin_opts }}"
2545
register: maintenance_result
2646
failed_when:
2747
- "'Successfully enabled maintenance mode' not in maintenance_result.stdout"
2848
- "'Maintenance mode is already enabled for node' not in maintenance_result.stdout"
2949
changed_when: "'Successfully enabled maintenance mode' in maintenance_result.stdout"
50+
no_log: "{{ kafka_enable_authorization | default(false) }}"
3051

3152
- name: Verify maintenance mode status
3253
ansible.builtin.shell: |
33-
{{ rpk_bin }} cluster maintenance status | grep -q '{{ node_id.stdout }}'
54+
{{ rpk_bin }} cluster maintenance status {{ rpk_opts }} {{ rpk_admin_opts }} | grep -q '{{ node_id.stdout }}'
3455
register: maintenance_status
3556
failed_when: maintenance_status.rc != 0
3657
changed_when: false
58+
no_log: "{{ kafka_enable_authorization | default(false) }}"
3759

3860
- name: Check cluster health after enabling maintenance mode
3961
ansible.builtin.shell: |
40-
{{ rpk_bin }} cluster health --watch --exit-when-healthy | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
62+
{{ rpk_bin }} cluster health --watch --exit-when-healthy {{ rpk_opts }} {{ rpk_admin_opts }} | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
4163
register: health_check_maintenance
4264
failed_when: "health_check_maintenance.stdout != 'true'"
4365
retries: 10
4466
delay: 30
4567
changed_when: false
68+
no_log: "{{ kafka_enable_authorization | default(false) }}"
4669

4770
- name: Stop Redpanda service
4871
ansible.builtin.systemd:
@@ -55,30 +78,34 @@
5578
state: started
5679

5780
- name: Disable maintenance mode
58-
ansible.builtin.command: "{{ rpk_bin }} cluster maintenance disable {{ node_id.stdout }}"
81+
ansible.builtin.command: "{{ rpk_bin }} cluster maintenance disable {{ node_id.stdout }} {{ rpk_opts }} {{ rpk_admin_opts }}"
5982
register: disable_maintenance_result
6083
changed_when: "'Successfully disabled maintenance mode' in disable_maintenance_result.stdout"
6184
failed_when: "'Successfully disabled maintenance mode' not in disable_maintenance_result.stdout"
85+
no_log: "{{ kafka_enable_authorization | default(false) }}"
6286

6387
- name: Verify maintenance mode is disabled
6488
ansible.builtin.shell: |
65-
{{ rpk_bin }} cluster maintenance status | grep -qv '{{ node_id.stdout }}'
89+
{{ rpk_bin }} cluster maintenance status {{ rpk_opts }} {{ rpk_admin_opts }} | grep -qv '{{ node_id.stdout }}'
6690
register: maintenance_status_after
6791
failed_when: maintenance_status_after.rc != 0
6892
changed_when: false
93+
no_log: "{{ kafka_enable_authorization | default(false) }}"
6994

7095
- name: Check cluster health after disabling maintenance mode
7196
ansible.builtin.shell: |
72-
{{ rpk_bin }} cluster health --watch --exit-when-healthy | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
97+
{{ rpk_bin }} cluster health --watch --exit-when-healthy {{ rpk_opts }} {{ rpk_admin_opts }} | grep -i 'healthy:' | tr -d '[:space:]' | awk -F ':' '{print tolower($2)}'
7398
register: health_check_maintenance
7499
failed_when: "health_check_maintenance.stdout != 'true'"
75100
retries: 10
76101
delay: 30
77102
changed_when: false
103+
no_log: "{{ kafka_enable_authorization | default(false) }}"
78104

79105
- name: Check broker status
80106
ansible.builtin.shell: |
81-
{{ rpk_bin }} redpanda admin brokers list | grep -q 'active.*true'
107+
{{ rpk_bin }} redpanda admin brokers list {{ rpk_admin_opts }} | grep -q 'active.*true'
82108
register: broker_status
83109
changed_when: false
84110
failed_when: broker_status.rc != 0
111+
no_log: "{{ kafka_enable_authorization | default(false) }}"

0 commit comments

Comments
 (0)