diff --git a/README.md b/README.md index 9338298..1d7a58f 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,11 @@ All domains are in the list, so the list can contains multiple domain configs. I - Domains is a list in list format. You can set root domain and wildcard domain. However it is important that the first element used in the filenames, so avoid to use wildcard in the first position! - Hooks: Refer acme.sh help or documentation, these are runs in the different stages of issue and renew. Everytime scripts runs in the domain directory so you can use relative command to copy the cert as source. - acme_sh_issue_env_vars: Following the acme.sh documentation you need to optain three data (two API keys and a zone ID) from Cloudflare and need to set them here. +- acme_sh_user_sudo_commands: Optional, list commands in this array that will be added to the sudoers file of user (so these commands are only allowed as root) +> Important: Specify the full path, E.G. /usr/bin/docker or /usr/sbin/something to avoid the sudo missing full path problems. +- acme_sh_user_sudoers_file: Contents of the sudoers file for acme user +> Note: Avoid to use the sudoers file and sudo commands together because sudoers file has higher precedence. +- acme_sh_user_sudoers_file: You can specify the name of the sudoers file in `/etc/sudoers.d` for this user to exec limited amount commands without password. And again, you need to set these vars for every single cert issue (that can contain multiple subdoms, see CA for more info and limitations). @@ -51,7 +56,6 @@ It is a good practice to create new user with the role for acme.sh. You can add ## todo - Avoid resetting the default CA on every run -- List commands if needed to give limited sudo privileges for acme user. List commands in an array that can run by acme. - Set up notification system of acme.sh - Reconnect after adding acme to groups to avoid possible access denied problems diff --git a/defaults/main.yaml b/defaults/main.yaml index 781f744..233da3e 100644 --- a/defaults/main.yaml +++ b/defaults/main.yaml @@ -1,6 +1,8 @@ - acme_sh_domains: [] acme_sh_user: "acme" +acme_sh_user_sudoers_file: "50-ansible-acmesh-{{ acme_sh_user }}" +acme_sh_user_sudo_commands: [] +acme_sh_user_sudoers_file_contents: "" acme_sh_user_groups: [] acme_sh_user_home: "/home/{{ acme_sh_user }}" acme_sh_git_repo: "https://github.com/acmesh-official/acme.sh.git" @@ -13,3 +15,4 @@ acme_sh_default_ca_server: "https://acme-v02.api.letsencrypt.org/directory" acme_sh_set_notify: "" acme_sh_set_notify_level: "2" + diff --git a/tasks/install_acmesh.yml b/tasks/install_acmesh.yml index ba15abd..4e502c0 100644 --- a/tasks/install_acmesh.yml +++ b/tasks/install_acmesh.yml @@ -25,3 +25,5 @@ --set-default-ca --server {{ acme_sh_default_ca_server | quote }} creates: "{{ acme_sh_home }}/ca_set_by_ansible" + + diff --git a/tasks/issue_certs.yml b/tasks/issue_certs.yml index c960abc..9124185 100644 --- a/tasks/issue_certs.yml +++ b/tasks/issue_certs.yml @@ -9,21 +9,21 @@ ansible.builtin.copy: content: "{{ item['pre_hook'] | default('') }}" dest: "{{ acme_sh_cert_home }}/{{ item['domains'][0] }}_ecc/pre_hook.sh" - mode: "755" + mode: "750" loop: "{{ acme_sh_domains }}" - name: Copy post_hooks ansible.builtin.copy: content: "{{ item['post_hook'] | default('')}}" dest: "{{ acme_sh_cert_home }}/{{ item['domains'][0] }}_ecc/post_hook.sh" - mode: "755" + mode: "750" loop: "{{ acme_sh_domains }}" - name: Copy update_hooks ansible.builtin.copy: content: "{{ item['renew_hook'] | default('')}}" dest: "{{ acme_sh_cert_home }}/{{ item['domains'][0] }}_ecc/renew_hook.sh" - mode: "755" + mode: "750" loop: "{{ acme_sh_domains }}" diff --git a/tasks/main.yaml b/tasks/main.yaml index 8ee5945..0093923 100644 --- a/tasks/main.yaml +++ b/tasks/main.yaml @@ -1,9 +1,10 @@ --- -- name: Install git +- name: Install git and acl become: true ansible.builtin.apt: name: - git + - acl state: present update_cache: yes @@ -20,6 +21,35 @@ append: true when: acme_sh_user_groups|length > 0 +- name: Add custom sudoers content if provided + become: true + ansible.builtin.copy: + content: "{{ acme_sh_user_sudoers_file_contents }}" + dest: "/etc/sudoers.d/{{ acme_sh_user_sudoers_file }}" + mode: "0440" + validate: "visudo -cf %s" + when: acme_sh_user_sudoers_file_contents | length > 0 + +- name: Ensure sudoers file exists + become: true + ansible.builtin.file: + path: "/etc/sudoers.d/{{ acme_sh_user_sudoers_file }}" + state: touch + mode: "0440" + when: acme_sh_user_sudoers_file_contents | default('') == "" + +- name: Add commands to sudoers file for acme_user + become: true + ansible.builtin.lineinfile: + path: "/etc/sudoers.d/{{ acme_sh_user_sudoers_file }}" + create: true + line: "{{ acme_sh_user }} ALL=(ALL) NOPASSWD: {{ item }}" + validate: "visudo -cf %s" + loop: "{{ acme_sh_user_sudo_commands }}" + when: + - acme_sh_user_sudo_commands | length > 1 + - acme_sh_user_sudoers_file_contents | default('') == "" + - name: Install acme.sh become: true become_user: "{{ acme_sh_user }}"