Skip to content

Commit

Permalink
Support to set owner/group for cert and key
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio Oliveira Campos authored and seocam committed Jun 3, 2020
1 parent 293aa63 commit 248b554
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 5 deletions.
14 changes: 14 additions & 0 deletions examples/owner_and_group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
- hosts: all
become: true

vars:
certificate_requests:
- name: mycert
dns: www.example.com
ca: self-sign
owner: ftp
group: ftp

roles:
- linux-system-roles.certificate
19 changes: 19 additions & 0 deletions library/certificate_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
certificate. Also can provide the default value for
I(common_name).
required: false
owner:
description:
- User name (or user id) for the certificate and key files.
required: false
group:
description:
- Group name (or group id) for the certificate and key files.
required: false
common_name:
description:
- Common Name requested for the certificate subject.
Expand Down Expand Up @@ -113,6 +121,15 @@
dns: www.example.com
key_size: 4096
ca: self-sign
# Define certificate owner and group
- name: Ensure user and group for certificate
certificate_request:
name: single-example
dns: www.example.com
owner: ftp
group: ftp
ca: self-sign
"""

RETURN = ""
Expand Down Expand Up @@ -152,6 +169,8 @@ def _get_argument_spec():
directory=dict(type="str", default="/etc/pki/tls"),
provider=dict(type="str", default="certmonger"),
key_size=dict(type="int", default=2048),
owner=dict(type="str"),
group=dict(type="str"),
)

@property
Expand Down
37 changes: 32 additions & 5 deletions module_utils/certificate/providers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,26 +283,53 @@ def _exit_success(self):
changed=self.changed, msg=self.message,
)

def _set_user_and_group_if_different(self):
file_attrs = {
"path": self.certificate_file_path,
"owner": self.module.params.get("owner"),
"group": self.module.params.get("group"),
"mode": None,
"attributes": None,
"secontext": [],
}
cert_diff = {}
self.changed = self.module.set_fs_attributes_if_different(
file_attrs, self.changed, cert_diff,
)
self.module.debug("Certificate fs attribute diff: {}".format(cert_diff))

file_attrs["path"] = self.certificate_key_path
key_diff = {}
self.changed = self.module.set_fs_attributes_if_different(
file_attrs, self.changed, key_diff,
)
self.module.debug("Certificate Key fs attribute diff: {}".format(key_diff))

return cert_diff or key_diff

def run(self, check_mode=False):
"""Entry point for the providers called from the actual Ansible module."""
if check_mode:
self.message += "(Check mode) "

issue_or_update_cert = False
self.message += "Certificate "
if not self.existing_certificate:
self.message += "requested (new)."
issue_or_update_cert = True
else:
if self.cert_needs_update:
self.message += "requested (update)."
issue_or_update_cert = True
else:
self.message += "is up-to-date."
# If the cert exists and does not require updates we are done
self._exit_success()

if check_mode:
self._exit_success()
if issue_or_update_cert and not check_mode:
self.request_certificate()

self.request_certificate()
updated_fs_attrs = self._set_user_and_group_if_different()
if updated_fs_attrs:
self.message += " File attributes updated."
self._exit_success()

def get_existing_certificate_pem_data(self):
Expand Down
1 change: 1 addition & 0 deletions module_utils/certificate/providers/certmonger.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ def request_certificate(self):
# Set certificate key size
command += ["-g", str(self.module.params.get("key_size"))]

self.module.debug("Certmonger command: {}".format(command))
self._run_command(command, check_rc=True)
self.changed = True
2 changes: 2 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
ip: "{{ item.ip | default(omit) }}"
email: "{{ item.email | default(omit) }}"
common_name: "{{ item.common_name | default(omit) }}"
owner: "{{ item.owner | default(omit) }}"
group: "{{ item.group | default(omit) }}"
ca: "{{ item.ca | default(omit) }}"
provider: "{{ item.provider | default(omit) }}"
directory: "{{ __certificate_default_directory }}"
Expand Down
24 changes: 24 additions & 0 deletions tests/tasks/assert_certificate_parameters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
- result.stat.exists
fail_msg: "Certificate file '{{ cert['path'] }}' does not exist."

- name: Verify certificate file owner and group
assert:
that:
- (cert['owner'] | default('root')) in
[result.stat.pw_name, result.stat.uid]
- (cert['group'] | default('root')) in
[result.stat.gr_name, result.stat.gid]
fail_msg: >-
{{ result.stat.pw_name }}:{{ result.stat.gr_name }} !=
{{ cert['owner'] | default('root') }}:
{{ cert['group'] | default('root') }}
- name: Retrieve key file stats
stat:
path: "{{ cert['key_path'] }}"
Expand All @@ -21,6 +33,18 @@
- result.stat.exists
fail_msg: "Key file '{{ cert['key_path'] }}' does not exist."

- name: Verify key file owner and group
assert:
that:
- (cert['owner'] | default('root')) in
[result.stat.pw_name, result.stat.uid]
- (cert['group'] | default('root')) in
[result.stat.gr_name, result.stat.gid]
fail_msg: >-
{{ result.stat.pw_name }}:{{ result.stat.gr_name }} !=
{{ cert['owner'] | default('root') }}:
{{ cert['group'] | default('root') }}
- name: Retrieve certificate subject
shell: >-
openssl x509 -in {{ cert['path'] }} -noout -subject |
Expand Down
32 changes: 32 additions & 0 deletions tests/tests_fs_attrs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
- name: Issue certificate setting user/group
hosts: all
become: true
vars:
certificate_requests:
- name: mycert
dns: www.example.com
owner: ftp
group: ftp
ca: self-sign
roles:
- linux-system-roles.certificate

- name: Verify certificate
hosts: all
become: true
vars:
certificates:
- path: /etc/pki/tls/certs/mycert.crt
key_path: /etc/pki/tls/private/mycert.key
subject: CN=www.example.com
subject_alt_name:
- DNS:www.example.com
owner: ftp
group: ftp
tasks:
- name: Verify each certificate
include_tasks: tasks/assert_certificate_parameters.yml
loop: "{{ certificates }}"
loop_control:
loop_var: cert

0 comments on commit 248b554

Please sign in to comment.