diff --git a/defaults/main.yml b/defaults/main.yml index 3019d30..8d27937 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -8,3 +8,28 @@ radicale_users: [] # Example: # - name: toto # password: +# password is either the plain-text password, hashed at deploy time (SHA-512 +# crypt, stable per-user salt so the file stays idempotent), or an existing +# htpasswd hash ($apr1$, bcrypt $2y$, $5$, $6$, argon2), written as is. + +# Access rights. Empty: built-in "owner_only" model. Otherwise a rights file is +# deployed and used ("from_file"); sections are evaluated in order, the first +# matching one wins. See https://radicale.org/v3.html#authorization-and-rights +radicale_rights: [] +# Example (same as owner_only, plus anonymous GET on one calendar): +# - name: root +# user: ".+" +# collection: "" +# permissions: R +# - name: principal +# user: ".+" +# collection: "{user}" +# permissions: RW +# - name: calendars +# user: ".+" +# collection: "{user}/[^/]+" +# permissions: rw +# - name: public +# user: ".*" +# collection: "toto/public" +# permissions: i diff --git a/tasks/main.yml b/tasks/main.yml index 045c46c..836857c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -50,6 +50,7 @@ group: "{{ radicale_user }}" mode: u=rw,g=r,o= become: true + diff: false notify: Restart radicale.service - name: Deploy configuration file @@ -61,3 +62,14 @@ mode: u=rw,g=r,o= become: true notify: Restart radicale.service + +- name: Deploy rights file + ansible.builtin.template: + src: rights.j2 + dest: "{{ radicale_root_path }}/rights" + owner: root + group: "{{ radicale_user }}" + mode: u=rw,g=r,o= + become: true + when: radicale_rights | length > 0 + notify: Restart radicale.service diff --git a/templates/radicale.conf.j2 b/templates/radicale.conf.j2 index 5ae3b91..3387cc8 100644 --- a/templates/radicale.conf.j2 +++ b/templates/radicale.conf.j2 @@ -12,7 +12,12 @@ stock=utf-8 level=debug [rights] +{% if radicale_rights | length > 0 %} +type=from_file +file={{ radicale_root_path }}/rights +{% else %} type=owner_only +{% endif %} [server] hosts=0.0.0.0:5232, [::]:5232 diff --git a/templates/rights.j2 b/templates/rights.j2 new file mode 100644 index 0000000..25af1f0 --- /dev/null +++ b/templates/rights.j2 @@ -0,0 +1,8 @@ +# {{ ansible_managed }} +{% for rule in radicale_rights %} + +[{{ rule.name }}] +user: {{ rule.user }} +collection: {{ rule.collection }} +permissions: {{ rule.permissions }} +{% endfor %} diff --git a/templates/users.htpasswd.j2 b/templates/users.htpasswd.j2 index fb9dec3..ac78fa7 100644 --- a/templates/users.htpasswd.j2 +++ b/templates/users.htpasswd.j2 @@ -1,5 +1,9 @@ # {{ ansible_managed }} {% for user in radicale_users %} +{% if user.password is match('^\$(apr1|2[abxy]?|argon2(i|d|id)|5|6)\$') %} {{ user.name }}:{{ user.password }} +{% else %} +{{ user.name }}:{{ user.password | password_hash('sha512', ((user.name ~ '@' ~ inventory_hostname) | hash('sha256'))[:16]) }} +{% endif %} {% endfor %}