mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
New roles for smartcard server and client setup
There are new smartcard roles in the roles folder:
roles/ipasmartcard_server
roles/ipasmartcard_client
This roles allows to setup smartcard for servers and clients.
Here is the documentation for the roles:
roles/ipasmartcard_server/README.md
roles/ipasmartcard_client/README.md
New example playbooks have been added:
playbooks/install-smartcard-server.yml
playbooks/install-smartcard-replicas.yml
playbooks/install-smartcard-servers.yml
playbooks/install-smartcard-clients.yml
This commit is contained in:
@@ -12,6 +12,7 @@ Features
|
||||
* One-time-password (OTP) support for client installation
|
||||
* Repair mode for clients
|
||||
* Backup and restore, also to and from controller
|
||||
* Smartcard setup for servers and clients
|
||||
* Modules for automembership rule management
|
||||
* Modules for automount key management
|
||||
* Modules for automount location management
|
||||
@@ -425,6 +426,8 @@ Roles
|
||||
* [Replica](roles/ipareplica/README.md)
|
||||
* [Client](roles/ipaclient/README.md)
|
||||
* [Backup](roles/ipabackup/README.md)
|
||||
* [SmartCard server](roles/ipasmartcard_server/README.md)
|
||||
* [SmartCard client](roles/ipasmartcard_client/README.md)
|
||||
|
||||
Modules in plugin/modules
|
||||
=========================
|
||||
|
||||
8
playbooks/install-smartcard-clients.yml
Normal file
8
playbooks/install-smartcard-clients.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA clients
|
||||
hosts: ipaclients
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_client
|
||||
state: present
|
||||
8
playbooks/install-smartcard-replicas.yml
Normal file
8
playbooks/install-smartcard-replicas.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA replicas
|
||||
hosts: ipareplicas
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
8
playbooks/install-smartcard-server.yml
Normal file
8
playbooks/install-smartcard-server.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA server
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
8
playbooks/install-smartcard-servers.yml
Normal file
8
playbooks/install-smartcard-servers.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA server and replicas
|
||||
hosts: ipaserver, ipareplicas
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
111
roles/ipasmartcard_client/README.md
Normal file
111
roles/ipasmartcard_client/README.md
Normal file
@@ -0,0 +1,111 @@
|
||||
ipasmartcard_client role
|
||||
========================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This role allows to configure IPA clients for Smart Card authentication.
|
||||
|
||||
**Note**: The ansible-freeipa smartcard client role requires an enrolled IPA client.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
* Client setup for Smart Card authentication
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.5 and up are supported by this role.
|
||||
|
||||
|
||||
Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* Fedora 26+
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
* Supported distribution (needed for package installation only, see above)
|
||||
* Enrolled IPA client
|
||||
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Only the enablement of smartcards is supported by the role, there is no disablement.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file with IPA clients:
|
||||
|
||||
```ini
|
||||
[ipaclients]
|
||||
ipaclient1.example.com
|
||||
ipaclient2.example.com
|
||||
|
||||
[ipaclients:vars]
|
||||
ipaadmin_password=SomeADMINpassword
|
||||
ipasmartcard_client_ca_certs=/etc/ipa/ca.crt
|
||||
```
|
||||
|
||||
Example playbook to setup smartcard for the IPA clients using admin password and ipasmartcard_client_ca_certs from inventory file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA clients
|
||||
hosts: ipaclients
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_client
|
||||
state: present
|
||||
```
|
||||
|
||||
Playbooks
|
||||
=========
|
||||
|
||||
The playbooks needed to setup smartcard for the IPA clients is part of the repository in the playbooks folder.
|
||||
|
||||
```
|
||||
install-smartcard-clients.yml
|
||||
```
|
||||
|
||||
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
|
||||
|
||||
|
||||
How to setup smartcard for clients
|
||||
----------------------------------
|
||||
|
||||
```bash
|
||||
ansible-playbook -v -i inventory/hosts install-smartcard-clients.yml
|
||||
```
|
||||
This will setup the clients for smartcard use.
|
||||
|
||||
|
||||
Variables
|
||||
=========
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The kerberos principal used for admin. Will be set to `admin` if not set. (string) | no
|
||||
`ipaadmin_password` | The password for the IPA admin user. As an alternative an admin user keytab can be used instead with `ipaadmin_keytab`. (string) | yes
|
||||
`ipaadmin_keytab` | The admin keytab as an alternative to `ipaadmin_password`. (string) | no
|
||||
`ipasmartcard_client_ca_certs` | The CA certificates for smartcard use. If `ipasmartcard_client_ca_certs` is not set, but `ipasmartcard_server_ca_certs`, then `ipasmartcard_server_ca_certs` will be used. | yes
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
4
roles/ipasmartcard_client/defaults/main.yml
Normal file
4
roles/ipasmartcard_client/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
# defaults file for ipasmartcard_client role
|
||||
|
||||
ipaclient_install_packages: yes
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cert_file=$1
|
||||
db=$2
|
||||
|
||||
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
|
||||
echo "Usage: $0 <ca cert> <db file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "${cert_file}" >> "${db}"
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cert_file=$1
|
||||
db=$2
|
||||
|
||||
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
|
||||
echo "Usage: $0 <ca cert> <db file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
uuid=$(uuidgen)
|
||||
certutil -d "${db}" -A -i "${cert_file}" -n "Smart Card CA ${uuid}" -t CT,C,C
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
nssdb=$1
|
||||
module_name="OpenSC"
|
||||
pkcs11_shared_lib="/usr/lib64/opensc-pkcs11.so"
|
||||
|
||||
if [ -z "${nssdb}" ]; then
|
||||
echo "Usage: $0 <nssdb>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if modutil -dbdir "${nssdb}" -list | grep -q "${module_name}" || p11-kit list-modules | grep -i "${module_name}" -q
|
||||
then
|
||||
echo "${module_name} PKCS#11 module already configured"
|
||||
else
|
||||
echo "" | modutil -dbdir "${nssdb}" -add "${module_name}" -libfile "${pkcs11_shared_lib}"
|
||||
fi
|
||||
@@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.0',
|
||||
'supported_by': 'community',
|
||||
'status': ['preview'],
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: ipasmartcard_client_get_vars
|
||||
short description:
|
||||
Get variables from ipaplatform and python interpreter used for the module.
|
||||
description:
|
||||
Get variables from ipaplatform and python interpreter used for the module.
|
||||
options:
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Get VARS from IPA
|
||||
ipasmartcard_client_get_vars:
|
||||
register: ipasmartcard_client_vars
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
NSS_DB_DIR:
|
||||
description: paths.NSS_DB_DIR from ipaplatform
|
||||
returned: always
|
||||
type: str
|
||||
USE_AUTHSELECT:
|
||||
description: True if "AUTHSELECT" is defined in paths
|
||||
returned: always
|
||||
type: bool
|
||||
python_interpreter:
|
||||
description: Python interpreter from sys.executable
|
||||
returned: always
|
||||
type: str
|
||||
'''
|
||||
|
||||
import sys
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ipaplatform.paths import paths
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
argument_spec={},
|
||||
supports_check_mode=False,
|
||||
)
|
||||
|
||||
ansible_module.exit_json(changed=False,
|
||||
NSS_DB_DIR=paths.NSS_DB_DIR,
|
||||
USE_AUTHSELECT=hasattr(paths, "AUTHSELECT"),
|
||||
python_interpreter=sys.executable)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,110 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Based on ipa-replica-install code
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.0',
|
||||
'supported_by': 'community',
|
||||
'status': ['preview'],
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: ipasmartcard_server_validate_ca_certs
|
||||
short description: Validate CA certs
|
||||
description: Validate CA certs
|
||||
options:
|
||||
ca_cert_files:
|
||||
description:
|
||||
List of files containing CA certificates for the service certificate
|
||||
files
|
||||
required: yes
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
import os.path
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
try:
|
||||
from ipalib import x509
|
||||
except ImportError:
|
||||
x509 = None
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
ca_cert_files=dict(required=False, type='list', default=[]),
|
||||
),
|
||||
supports_check_mode=False,
|
||||
)
|
||||
|
||||
# get parameters #
|
||||
|
||||
ca_cert_files = ansible_module.params.get('ca_cert_files')
|
||||
|
||||
# import check #
|
||||
|
||||
if x509 is None:
|
||||
ansible_module.fail_json(msg="Failed to import x509 from ipalib")
|
||||
|
||||
# validate ca certs #
|
||||
|
||||
if ca_cert_files is not None:
|
||||
if not isinstance(ca_cert_files, list):
|
||||
ansible_module.fail_json(
|
||||
msg="Expected list, got %s" % repr(ca_cert_files))
|
||||
# remove duplicates
|
||||
ca_cert_files = list(dict.fromkeys(ca_cert_files))
|
||||
# validate
|
||||
for cert in ca_cert_files:
|
||||
if not os.path.exists(cert):
|
||||
ansible_module.fail_json(msg="'%s' does not exist" % cert)
|
||||
if not os.path.isfile(cert):
|
||||
ansible_module.fail_json(msg="'%s' is not a file" % cert)
|
||||
if not os.path.isabs(cert):
|
||||
ansible_module.fail_json(
|
||||
msg="'%s' is not an absolute file path" % cert)
|
||||
try:
|
||||
x509.load_certificate_from_file(cert)
|
||||
except Exception:
|
||||
ansible_module.fail_json(
|
||||
msg="'%s' is not a valid certificate file" % cert)
|
||||
|
||||
# exit #
|
||||
|
||||
ansible_module.exit_json(changed=False,
|
||||
ca_cert_files=ca_cert_files)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
22
roles/ipasmartcard_client/meta/main.yml
Normal file
22
roles/ipasmartcard_client/meta/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
dependencies: []
|
||||
|
||||
galaxy_info:
|
||||
author: Thomas Woerner
|
||||
description: A role to setup IPA server(s) for Smart Card authentication
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: 2.8
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
- all
|
||||
- name: EL
|
||||
versions:
|
||||
- 7
|
||||
- 8
|
||||
galaxy_tags:
|
||||
- identity
|
||||
- ipa
|
||||
- freeipa
|
||||
- smartcard
|
||||
173
roles/ipasmartcard_client/tasks/main.yml
Normal file
173
roles/ipasmartcard_client/tasks/main.yml
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
# tasks file for ipasmartcard_client role
|
||||
|
||||
- name: Uninstall smartcard client
|
||||
ansible.builtin.fail: msg="Uninstalling smartcard for IPA is not supported"
|
||||
when: state|default('present') == 'absent'
|
||||
|
||||
- name: Import variables specific to distribution
|
||||
ansible.builtin.include_vars: "{{ item }}"
|
||||
with_first_found:
|
||||
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['distribution'] }}.yml"
|
||||
# os_family is used as a fallback for distros which are not currently
|
||||
# supported, but are based on a supported distro family. For example,
|
||||
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
|
||||
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['os_family'] }}.yml"
|
||||
# If neither distro nor family is supported, try a default configuration.
|
||||
- "vars/default.yml"
|
||||
|
||||
- block:
|
||||
|
||||
# CA CERTS
|
||||
|
||||
# Use "ipasmartcard_server_ca_certs"
|
||||
|
||||
- name: Use "ipasmartcard_server_ca_certs"
|
||||
ansible.builtin.set_fact:
|
||||
ipasmartcard_client_ca_certs: "{{ ipasmartcard_server_ca_certs }}"
|
||||
when: ipasmartcard_client_ca_certs is not defined and
|
||||
ipasmartcard_server_ca_certs is defined
|
||||
|
||||
# Fail on empty "ipasmartcard_client_ca_certs"
|
||||
|
||||
- name: Fail on empty "ipasmartcard_client_ca_certs"
|
||||
ansible.builtin.fail: msg="No CA certs given in 'ipasmartcard_client_ca_certs'"
|
||||
when: ipasmartcard_client_ca_certs is not defined or
|
||||
ipasmartcard_client_ca_certs | length < 1
|
||||
|
||||
# Validate ipasmartcard_client_ca_certs
|
||||
|
||||
- name: Validate CA certs "{{ ipasmartcard_client_ca_certs }}"
|
||||
ipasmartcard_client_validate_ca_certs:
|
||||
ca_cert_files: "{{ ipasmartcard_client_ca_certs }}"
|
||||
register: result_validate_ca_certs
|
||||
|
||||
# INSTALL needed packages: opensc, dconf and krb5-pkinit-openssl
|
||||
|
||||
- name: Ensure needed packages are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipasmartcard_client_packages }}"
|
||||
state: present
|
||||
|
||||
# REMOVE pam_pkcs11
|
||||
|
||||
- name: Ensure pam_pkcs11 is missing
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipasmartcard_client_remove_pam_pkcs11_packages }}"
|
||||
state: absent
|
||||
|
||||
# KINIT
|
||||
|
||||
- name: Set default principal if not given
|
||||
ansible.builtin.set_fact:
|
||||
ipaadmin_principal: admin
|
||||
when: ipaadmin_principal is undefined
|
||||
|
||||
- name: kinit using "{{ ipaadmin_principal }}" password
|
||||
ansible.builtin.command: kinit "{{ ipaadmin_principal }}"
|
||||
args:
|
||||
stdin: "{{ ipaadmin_password }}"
|
||||
when: ipaadmin_password is defined
|
||||
|
||||
- name: kinit using "{{ ipaadmin_principal }}" keytab
|
||||
ansible.builtin.command: kinit -kt "{{ ipaadmin_keytab }}" "{{ ipaadmin_principal }}"
|
||||
when: ipaadmin_keytab is defined
|
||||
|
||||
# Enable and start smartcard daemon
|
||||
|
||||
- name: Enable and start smartcard daemon
|
||||
ansible.builtin.service:
|
||||
name: pcscd
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
# GET VARS FROM IPA
|
||||
|
||||
- name: Get VARS from IPA
|
||||
ipasmartcard_client_get_vars:
|
||||
register: ipasmartcard_client_vars
|
||||
|
||||
# Add pkcs11 module to systemwide db
|
||||
|
||||
- name: Add pkcs11 module to systemwide db
|
||||
ansible.builtin.script: ipasmartcard_client_add_pkcs11_module_to_systemwide_db.sh
|
||||
"{{ ipasmartcard_client_vars.NSS_DB_DIR }}"
|
||||
|
||||
# Ensure /etc/sssd/pki exists
|
||||
|
||||
- block:
|
||||
- name: Ensure /etc/sssd/pki exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/sssd/pki
|
||||
state: directory
|
||||
mode: 0711
|
||||
|
||||
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
|
||||
ansible.builtin.file:
|
||||
path: /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
state: absent
|
||||
|
||||
when: ipasmartcard_client_vars.USE_AUTHSELECT
|
||||
|
||||
# Upload smartcard CA certificates to systemwide db
|
||||
|
||||
- name: Upload smartcard CA certificates to systemwide db
|
||||
ansible.builtin.script: ipasmartcard_client_add_ca_to_systemwide_db.sh
|
||||
"{{ item }}"
|
||||
"{{ ipasmartcard_client_vars.NSS_DB_DIR }}"
|
||||
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
|
||||
|
||||
# Newer version of sssd use OpenSSL and read the CA certs
|
||||
# from /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
|
||||
- name: Add CA certs to /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
ansible.builtin.script: ipasmartcard_client_add_ca_to_sssd_auth_ca_db.sh
|
||||
"{{ item }}"
|
||||
/etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
|
||||
when: ipasmartcard_client_vars.USE_AUTHSELECT
|
||||
|
||||
# Update ipa CA certificate store
|
||||
|
||||
- name: Update ipa CA certificate store
|
||||
ansible.builtin.command: ipa-certupdate
|
||||
|
||||
# Run authselect or authconfig to configure smartcard auth
|
||||
|
||||
- name: Use authselect to enable Smart Card authentication
|
||||
ansible.builtin.command: authselect enable-feature with-smartcard
|
||||
when: ipasmartcard_client_vars.USE_AUTHSELECT
|
||||
|
||||
- name: Use authconfig to enable Smart Card authentication
|
||||
ansible.builtin.command: authconfig --enablesssd --enablesssdauth --enablesmartcard --smartcardmodule=sssd --smartcardaction=1 --updateall
|
||||
when: not ipasmartcard_client_vars.USE_AUTHSELECT
|
||||
|
||||
# Set pam_cert_auth=True in /etc/sssd/sssd.conf
|
||||
|
||||
- name: Store NSS OCSP upgrade state
|
||||
ansible.builtin.command: "{{ ipasmartcard_client_vars.python_interpreter }}"
|
||||
args:
|
||||
stdin: |
|
||||
from SSSDConfig import SSSDConfig
|
||||
c = SSSDConfig()
|
||||
c.import_config()
|
||||
c.set("pam", "pam_cert_auth", "True")
|
||||
c.write()
|
||||
when: ipasmartcard_client_vars.USE_AUTHSELECT
|
||||
|
||||
# Restart sssd
|
||||
|
||||
- name: Restart sssd
|
||||
ansible.builtin.service:
|
||||
name: sssd
|
||||
state: restarted
|
||||
|
||||
### ALWAYS ###
|
||||
|
||||
always:
|
||||
- name: kdestroy
|
||||
ansible.builtin.command: kdestroy -A
|
||||
3
roles/ipasmartcard_client/vars/default.yml
Normal file
3
roles/ipasmartcard_client/vars/default.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
ipasmartcard_client_remove_pam_pkcs11_packages: [ "pam_pkcs11" ]
|
||||
ipasmartcard_client_packages: [ "opensc", "dconf", "krb5-pkinit-openssl" ]
|
||||
169
roles/ipasmartcard_server/README.md
Normal file
169
roles/ipasmartcard_server/README.md
Normal file
@@ -0,0 +1,169 @@
|
||||
ipasmartcard_server role
|
||||
========================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This role allows to configure an IPA server (master or replica) for Smart Card authentication.
|
||||
|
||||
**Note**: The ansible-freeipa smartcard server role requires a configured IPA server with ipa-ca.DOMAIN resolvable by the DNS server.
|
||||
|
||||
With external DNS ipa-ca.DOMAIN needs to be set.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
* Server setup for Smart Card authentication
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.5 and up are supported by this role.
|
||||
|
||||
|
||||
Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* Fedora 26+
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
* Supported distribution (needed for package installation only, see above)
|
||||
* Deployed IPA server
|
||||
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Only the enablement of smartcards is supported by the role, there is no disablement. The disablement of features in IPA in not supported.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file with ipa server and replicas:
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.example.com
|
||||
|
||||
[ipareplicas]
|
||||
ipareplica1.example.com
|
||||
ipareplica2.example.com
|
||||
|
||||
[ipacluster:children]
|
||||
ipaserver
|
||||
ipareplicas
|
||||
|
||||
[ipacluster:vars]
|
||||
ipaadmin_password=SomeADMINpassword
|
||||
ipasmartcard_server_ca_certs=/etc/ipa/ca.crt
|
||||
```
|
||||
|
||||
Example playbook to setup smartcard for the IPA server using admin password and ipasmartcard_server_ca_certs from inventory file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA server
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
```
|
||||
|
||||
Example playbook to setup smartcard for the IPA servers in ipareplicas group using admin password and ipasmartcard_server_ca_certs from inventory file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA replicas
|
||||
hosts: ipareplicas
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
```
|
||||
|
||||
Example playbook to setup smartcard for the IPA servers in ipaserver and ipareplicas group using admin password and ipasmartcard_server_ca_certs from inventory file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to setup smartcard for IPA server and replicas
|
||||
hosts: ipaserver, ipareplicas
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipasmartcard_server
|
||||
state: present
|
||||
```
|
||||
|
||||
|
||||
Playbooks
|
||||
=========
|
||||
|
||||
The playbooks needed to setup smartcard for the IPA server and the replicas are part of the repository in the playbooks folder.
|
||||
|
||||
```
|
||||
install-smartcard-server.yml
|
||||
install-smartcard-servers.yml
|
||||
install-smartcard-replicas.yml
|
||||
```
|
||||
|
||||
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
|
||||
|
||||
|
||||
How to setup smartcard for server
|
||||
---------------------------------
|
||||
|
||||
```bash
|
||||
ansible-playbook -v -i inventory/hosts install-smartcard-server.yml
|
||||
```
|
||||
This will setup the server for smartcard use.
|
||||
|
||||
|
||||
How to setup smartcard for replicas
|
||||
-----------------------------------
|
||||
|
||||
```bash
|
||||
ansible-playbook -v -i inventory/hosts install-smartcard-replicas.yml
|
||||
```
|
||||
This will setup the replicas for smartcard use.
|
||||
|
||||
|
||||
How to setup smartcard for server and replicas
|
||||
----------------------------------------------
|
||||
|
||||
```bash
|
||||
ansible-playbook -v -i inventory/hosts install-smartcard-servers.yml
|
||||
```
|
||||
This will setup the replicas for smartcard use.
|
||||
|
||||
|
||||
Variables
|
||||
=========
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The kerberos principal used for admin. Will be set to `admin` if not set. (string) | no
|
||||
`ipaadmin_password` | The password for the IPA admin user. As an alternative an admin user keytab can be used instead with `ipaadmin_keytab`. (string) | yes
|
||||
`ipaadmin_keytab` | The admin keytab as an alternative to `ipaadmin_password`. (string) | no
|
||||
`ipaserver_hostname` | Fully qualified name of the server. By default `ansible_facts['fqdn']` will be used. (string) | no
|
||||
`ipaserver_domain` | The primary DNS domain of an existing IPA deployment. By default the domain will be used from ipa server-find result. (string) | no
|
||||
`ipasmartcard_server_ca_certs` | The CA certificates for smartcard use. (list of string) | yes
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
4
roles/ipasmartcard_server/defaults/main.yml
Normal file
4
roles/ipasmartcard_server/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
# defaults file for ipasmartcard_server role
|
||||
|
||||
ipaserver_install_packages: yes
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cert_file=$1
|
||||
db=$2
|
||||
|
||||
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
|
||||
echo "Usage: $0 <ca cert> <db file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "${cert_file}" >> "${db}"
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cert_file=$1
|
||||
db=$2
|
||||
|
||||
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
|
||||
echo "Usage: $0 <ca cert> <db file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
uuid=$(uuidgen)
|
||||
certutil -d "${db}" -A -i "${cert_file}" -n "Smart Card CA ${uuid}" -t CT,C,C
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
directive=$1
|
||||
conf_file=$2
|
||||
|
||||
if [ -z "${directive}" ] || [ -z "${conf_file}" ]; then
|
||||
echo "Usage: $0 <directive> <config file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -q "${directive} " "${conf_file}"
|
||||
then
|
||||
sed -i.ipabkp -r "s/^#*[[:space:]]*${directive}[[:space:]]+(on|off)$/${directive} on/" "${conf_file}"
|
||||
else
|
||||
sed -i.ipabkp "/<\/VirtualHost>/i ${directive} on" "${conf_file}"
|
||||
fi
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
directive=$1
|
||||
nss_conf=$2
|
||||
nickname=$3
|
||||
alias_dir=$4
|
||||
|
||||
if [ -z "${directive}" ] || [ -z "${nss_conf}" ] || [ -z "${nickname}" ] ||
|
||||
[ -z "${alias_dir}" ]
|
||||
then
|
||||
echo "Usage: $0 <directive> <nss conf> <nickname directive> <alias directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
http_cert_nick=$(grep "${nickname}" "${nss_conf}" | cut -f 2 -d ' ')
|
||||
certutil -M -n "$http_cert_nick" -d "${alias_dir}" -f "${alias_dir}/pwdfile.txt" -t "Pu,u,u"
|
||||
@@ -0,0 +1,159 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.0',
|
||||
'supported_by': 'community',
|
||||
'status': ['preview'],
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: ipasmartcard_server_get_vars
|
||||
short description:
|
||||
Get variables from ipaplatform and ipaserver and python interpreter.
|
||||
description:
|
||||
Get variables from ipaplatform and ipaserver and python interpreter.
|
||||
options:
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Get VARS from IPA
|
||||
ipasmartcard_server_get_vars:
|
||||
register: ipasmartcard_server_vars
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
NSS_OCSP_ENABLED:
|
||||
description:
|
||||
Empty string for newer systems using ssl.conf and not nss.conf for
|
||||
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
|
||||
ipaserver.install.httpinstance, else NSS_OCSP_ENABLED imported from
|
||||
ipaserver.install.httpinstance.
|
||||
returned: always
|
||||
type: str
|
||||
NSS_OCSP_DIRECTIVE:
|
||||
description:
|
||||
Empty string for newer systems using ssl.conf and not nss.conf for
|
||||
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
|
||||
ipaserver.install.httpinstance, else NSSOCSP.
|
||||
returned: always
|
||||
type: str
|
||||
NSS_NICKNAME_DIRECTIVE:
|
||||
description:
|
||||
Empty string for newer systems using ssl.conf and not nss.conf for
|
||||
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
|
||||
ipaserver.install.httpinstance, else NSSNickname
|
||||
returned: always
|
||||
type: str
|
||||
OCSP_ENABLED:
|
||||
description:
|
||||
OCSP_ENABLED imported from ipaserver.install.httpinstance, if import
|
||||
succeeds, else ""
|
||||
returned: always
|
||||
type: str
|
||||
OCSP_DIRECTIVE:
|
||||
description:
|
||||
OCSP_DIRECTIVE imported from ipaserver.install.httpinstance, if import
|
||||
succeeds, else ""
|
||||
returned: always
|
||||
type: str
|
||||
HTTPD_SSL_CONF:
|
||||
description: paths.HTTPD_SSL_CONF from ipaplatform
|
||||
returned: always
|
||||
type: str
|
||||
HTTPD_NSS_CONF:
|
||||
description: paths.HTTPD_NSS_CONF from ipaplatform
|
||||
returned: always
|
||||
type: str
|
||||
HTTPD_ALIAS_DIR:
|
||||
description: paths.HTTPD_ALIAS_DIR from ipaplatform
|
||||
returned: always
|
||||
type: str
|
||||
allow_httpd_ifp:
|
||||
description:
|
||||
True if sssd_enable_ifp can be imported from ipaclient.install.client,
|
||||
else false.
|
||||
returned: always
|
||||
type: bool
|
||||
NSS_DB_DIR:
|
||||
description: paths.NSS_DB_DIR from ipaplatform
|
||||
returned: always
|
||||
type: str
|
||||
USE_AUTHSELECT:
|
||||
description: True if "AUTHSELECT" is defined in paths
|
||||
returned: always
|
||||
type: bool
|
||||
python_interpreter:
|
||||
description: Python interpreter from sys.executable
|
||||
returned: always
|
||||
type: str
|
||||
'''
|
||||
|
||||
import sys
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ipaplatform.paths import paths
|
||||
try:
|
||||
from ipaserver.install.httpinstance import OCSP_ENABLED, OCSP_DIRECTIVE
|
||||
NSS_OCSP_ENABLED = ""
|
||||
NSS_OCSP_DIRECTIVE = ""
|
||||
NSS_NICKNAME_DIRECTIVE = ""
|
||||
except ImportError:
|
||||
from ipaserver.install.httpinstance import NSS_OCSP_ENABLED
|
||||
NSS_OCSP_DIRECTIVE = "NSSOCSP"
|
||||
NSS_NICKNAME_DIRECTIVE = "NSSNickname"
|
||||
OCSP_ENABLED = ""
|
||||
OCSP_DIRECTIVE = ""
|
||||
try:
|
||||
from ipaclient.install.client import sssd_enable_ifp
|
||||
except ImportError:
|
||||
sssd_enable_ifp = None
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
argument_spec={},
|
||||
supports_check_mode=False,
|
||||
)
|
||||
|
||||
ansible_module.exit_json(changed=False,
|
||||
NSS_OCSP_ENABLED=NSS_OCSP_ENABLED,
|
||||
NSS_OCSP_DIRECTIVE=NSS_OCSP_DIRECTIVE,
|
||||
NSS_NICKNAME_DIRECTIVE=NSS_NICKNAME_DIRECTIVE,
|
||||
OCSP_ENABLED=OCSP_ENABLED,
|
||||
OCSP_DIRECTIVE=OCSP_DIRECTIVE,
|
||||
HTTPD_SSL_CONF=paths.HTTPD_SSL_CONF,
|
||||
HTTPD_NSS_CONF=paths.HTTPD_NSS_CONF,
|
||||
HTTPD_ALIAS_DIR=paths.HTTPD_ALIAS_DIR,
|
||||
allow_httpd_ifp=sssd_enable_ifp is not None,
|
||||
NSS_DB_DIR=paths.NSS_DB_DIR,
|
||||
USE_AUTHSELECT=hasattr(paths, "AUTHSELECT"),
|
||||
python_interpreter=sys.executable)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,110 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Based on ipa-replica-install code
|
||||
#
|
||||
# Copyright (C) 2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.0',
|
||||
'supported_by': 'community',
|
||||
'status': ['preview'],
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: ipasmartcard_server_validate_ca_certs
|
||||
short description: Validate CA certs
|
||||
description: Validate CA certs
|
||||
options:
|
||||
ca_cert_files:
|
||||
description:
|
||||
List of files containing CA certificates for the service certificate
|
||||
files
|
||||
required: yes
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
import os.path
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
try:
|
||||
from ipalib import x509
|
||||
except ImportError:
|
||||
x509 = None
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
ca_cert_files=dict(required=False, type='list', default=[]),
|
||||
),
|
||||
supports_check_mode=False,
|
||||
)
|
||||
|
||||
# get parameters #
|
||||
|
||||
ca_cert_files = ansible_module.params.get('ca_cert_files')
|
||||
|
||||
# import check #
|
||||
|
||||
if x509 is None:
|
||||
ansible_module.fail_json(msg="Failed to import x509 from ipalib")
|
||||
|
||||
# validate ca certs #
|
||||
|
||||
if ca_cert_files is not None:
|
||||
if not isinstance(ca_cert_files, list):
|
||||
ansible_module.fail_json(
|
||||
msg="Expected list, got %s" % repr(ca_cert_files))
|
||||
# remove duplicates
|
||||
ca_cert_files = list(dict.fromkeys(ca_cert_files))
|
||||
# validate
|
||||
for cert in ca_cert_files:
|
||||
if not os.path.exists(cert):
|
||||
ansible_module.fail_json(msg="'%s' does not exist" % cert)
|
||||
if not os.path.isfile(cert):
|
||||
ansible_module.fail_json(msg="'%s' is not a file" % cert)
|
||||
if not os.path.isabs(cert):
|
||||
ansible_module.fail_json(
|
||||
msg="'%s' is not an absolute file path" % cert)
|
||||
try:
|
||||
x509.load_certificate_from_file(cert)
|
||||
except Exception:
|
||||
ansible_module.fail_json(
|
||||
msg="'%s' is not a valid certificate file" % cert)
|
||||
|
||||
# exit #
|
||||
|
||||
ansible_module.exit_json(changed=False,
|
||||
ca_cert_files=ca_cert_files)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
22
roles/ipasmartcard_server/meta/main.yml
Normal file
22
roles/ipasmartcard_server/meta/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
dependencies: []
|
||||
|
||||
galaxy_info:
|
||||
author: Thomas Woerner
|
||||
description: A role to setup IPA server(s) for Smart Card authentication
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: 2.8
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
- all
|
||||
- name: EL
|
||||
versions:
|
||||
- 7
|
||||
- 8
|
||||
galaxy_tags:
|
||||
- identity
|
||||
- ipa
|
||||
- freeipa
|
||||
- smartcard
|
||||
247
roles/ipasmartcard_server/tasks/main.yml
Normal file
247
roles/ipasmartcard_server/tasks/main.yml
Normal file
@@ -0,0 +1,247 @@
|
||||
---
|
||||
# tasks file for ipasmartcard_server role
|
||||
|
||||
- name: Uninstall smartcard server
|
||||
ansible.builtin.fail: msg="Uninstalling smartcard for IPA is not supported"
|
||||
when: state|default('present') == 'absent'
|
||||
|
||||
- name: Import variables specific to distribution
|
||||
ansible.builtin.include_vars: "{{ item }}"
|
||||
with_first_found:
|
||||
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['distribution'] }}.yml"
|
||||
# os_family is used as a fallback for distros which are not currently
|
||||
# supported, but are based on a supported distro family. For example,
|
||||
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
|
||||
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
|
||||
- "vars/{{ ansible_facts['os_family'] }}.yml"
|
||||
# If neither distro nor family is supported, try a default configuration.
|
||||
- "vars/default.yml"
|
||||
|
||||
- block:
|
||||
|
||||
# CA CERTS
|
||||
|
||||
# Fail on empty "ipasmartcard_server_ca_certs"
|
||||
- name: Fail on empty "ipasmartcard_server_ca_certs"
|
||||
ansible.builtin.fail: msg="No CA certs given in 'ipasmartcard_server_ca_certs'"
|
||||
when: ipasmartcard_server_ca_certs is not defined or
|
||||
ipasmartcard_server_ca_certs | length < 1
|
||||
|
||||
# Validate ipasmartcard_server_ca_certs
|
||||
|
||||
- name: Validate CA certs "{{ ipasmartcard_server_ca_certs }}"
|
||||
ipasmartcard_server_validate_ca_certs:
|
||||
ca_cert_files: "{{ ipasmartcard_server_ca_certs }}"
|
||||
register: result_validate_ca_certs
|
||||
|
||||
# INSTALL bind-utils
|
||||
|
||||
- name: Ensure {{ ipasmartcard_server_bindutils_packages }} are installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ ipasmartcard_server_bindutils_packages }}"
|
||||
state: present
|
||||
when: ipaserver_install_packages | bool
|
||||
|
||||
# KINIT
|
||||
|
||||
- name: Set default principal if not given
|
||||
ansible.builtin.set_fact:
|
||||
ipaadmin_principal: admin
|
||||
when: ipaadmin_principal is undefined
|
||||
|
||||
- name: kinit using "{{ ipaadmin_principal }}" password
|
||||
ansible.builtin.command: kinit "{{ ipaadmin_principal }}"
|
||||
args:
|
||||
stdin: "{{ ipaadmin_password }}"
|
||||
when: ipaadmin_password is defined
|
||||
|
||||
- name: kinit using "{{ ipaadmin_principal }}" keytab
|
||||
ansible.builtin.command: kinit -kt "{{ ipaadmin_keytab }}" "{{ ipaadmin_principal }}"
|
||||
when: ipaadmin_keytab is defined
|
||||
|
||||
# IS MASTER
|
||||
|
||||
- name: Check that this is an IPA master
|
||||
ansible.builtin.command: ipa server-show --raw "{{ ipaserver_hostname | default(ansible_facts['fqdn']) }}"
|
||||
register: result_ipa_server_show
|
||||
|
||||
- name: Fail if not an IPA server
|
||||
ansible.builtin.fail: msg="Not an IPA server"
|
||||
when: result_ipa_server_show.failed
|
||||
|
||||
- name: Get Domain from server-find server name
|
||||
ansible.builtin.set_fact:
|
||||
ipaserver_domain: "{{ (result_ipa_server_show.stdout | regex_search('cn: (.+)', '\\1'))[0].split('.')[1:] | join ('.') }}"
|
||||
when: ipaserver_domain is not defined
|
||||
|
||||
- name: Get ipa-ca records
|
||||
ansible.builtin.command: "dig +short ipa-ca.{{ ipaserver_domain }}"
|
||||
register: result_get_ipaca_records
|
||||
|
||||
- name: Fail if ipa-ca records are not resolvable
|
||||
ansible.builtin.fail: msg="ipa-ca records are not resolvable"
|
||||
when: result_get_ipaca_records.failed or
|
||||
result_get_ipaca_records.stdout | length == 0
|
||||
|
||||
# GET VARS FROM IPA
|
||||
|
||||
- name: Get VARS from IPA
|
||||
ipasmartcard_server_get_vars:
|
||||
register: ipasmartcard_server_vars
|
||||
|
||||
# ENABLE NSS OCSP
|
||||
|
||||
- name: Enable the OCSP directive in nss.conf
|
||||
ansible.builtin.script: ipasmartcard_server_enable_ocsp_directive.sh
|
||||
"{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}"
|
||||
"{{ ipasmartcard_server_vars.HTTPD_NSS_CONF }}"
|
||||
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
|
||||
|
||||
# MARK NSS HTTPD CERT AS TRUSTED
|
||||
|
||||
- name: Mark HTTPD CERT as trusted
|
||||
ansible.builtin.script: ipasmartcard_server_mark_httpd_cert_as_trusted.sh
|
||||
"{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}"
|
||||
"{{ ipasmartcard_server_vars.HTTPD_NSS_CONF }}"
|
||||
"{{ ipasmartcard_server_vars.NSS_NICKNAME_DIRECTIVE }}"
|
||||
"{{ ipasmartcard_server_vars.HTTPD_ALIAS_DIR }}"
|
||||
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
|
||||
|
||||
# ENABLE SSL OCSP
|
||||
|
||||
- name: Enable the OCSP directive in ssl.conf
|
||||
ansible.builtin.script: ipasmartcard_server_enable_ocsp_directive.sh
|
||||
"{{ ipasmartcard_server_vars.OCSP_DIRECTIVE }}"
|
||||
"{{ ipasmartcard_server_vars.HTTPD_SSL_CONF }}"
|
||||
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
|
||||
|
||||
# Restart apache
|
||||
|
||||
- name: Restart apache
|
||||
ansible.builtin.service:
|
||||
name: httpd
|
||||
state: restarted
|
||||
|
||||
# RECORD HTTPD OCSP STATUS
|
||||
|
||||
# Store the NSS OCSP upgrade state
|
||||
|
||||
- name: Store NSS OCSP upgrade state
|
||||
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
|
||||
args:
|
||||
stdin: |
|
||||
from ipaserver.install import sysupgrade
|
||||
sysupgrade.set_upgrade_state("httpd", "{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}", True)
|
||||
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
|
||||
|
||||
# Store the SSL OCSP upgrade state
|
||||
|
||||
- name: Store SSL OCSP upgrade state
|
||||
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
|
||||
args:
|
||||
stdin: |
|
||||
from ipaserver.install import sysupgrade
|
||||
sysupgrade.set_upgrade_state("httpd", "{{ ipasmartcard_server_vars.OCSP_DIRECTIVE }}", True)
|
||||
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
|
||||
|
||||
# check whether PKINIT is configured on the master
|
||||
|
||||
- name: Enable PKINIT
|
||||
ansible.builtin.command: ipa-pkinit-manage enable
|
||||
|
||||
# Enable OK-AS-DELEGATE flag on the HTTP principal
|
||||
# This enables smart card login to WebUI
|
||||
|
||||
- name: Enable OK-AS-DELEGATE flag on the HTTP principal
|
||||
ipaservice:
|
||||
name: "HTTP/{{ ipaserver_hostname | default(ansible_facts['fqdn']) }}"
|
||||
ok_to_auth_as_delegate: yes
|
||||
|
||||
# HTTPD IFP
|
||||
|
||||
- block:
|
||||
|
||||
# Allow Apache to access SSSD IFP
|
||||
|
||||
- name: Allow Apache to access SSSD IFP
|
||||
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
|
||||
args:
|
||||
stdin: |
|
||||
import SSSDConfig
|
||||
from ipaclient.install.client import sssd_enable_ifp
|
||||
from ipaplatform.paths import paths
|
||||
c = SSSDConfig.SSSDConfig()
|
||||
c.import_config()
|
||||
sssd_enable_ifp(c, allow_httpd=True)
|
||||
c.write(paths.SSSD_CONF)
|
||||
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
|
||||
|
||||
# Restart sssd
|
||||
|
||||
- name: Restart sssd
|
||||
ansible.builtin.service:
|
||||
name: sssd
|
||||
state: restarted
|
||||
|
||||
when: ipasmartcard_server_vars.allow_httpd_ifp
|
||||
|
||||
# Ensure /etc/sssd/pki exists
|
||||
|
||||
- block:
|
||||
- name: Ensure /etc/sssd/pki exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/sssd/pki
|
||||
state: directory
|
||||
mode: 0711
|
||||
|
||||
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
|
||||
ansible.builtin.file:
|
||||
path: /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
state: absent
|
||||
|
||||
when: ipasmartcard_server_vars.USE_AUTHSELECT
|
||||
|
||||
# Upload smartcard CA certificates to systemwide db
|
||||
|
||||
- name: Upload smartcard CA certificates to systemwide db
|
||||
ansible.builtin.script: ipasmartcard_server_add_ca_to_systemwide_db.sh
|
||||
"{{ item }}"
|
||||
"{{ ipasmartcard_server_vars.NSS_DB_DIR }}"
|
||||
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
|
||||
|
||||
# Newer version of sssd use OpenSSL and read the CA certs
|
||||
# from /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
|
||||
- name: Add CA certs to /etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
ansible.builtin.script: ipasmartcard_server_add_ca_to_sssd_auth_ca_db.sh
|
||||
"{{ item }}"
|
||||
/etc/sssd/pki/sssd_auth_ca_db.pem
|
||||
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
|
||||
when: ipasmartcard_server_vars.USE_AUTHSELECT
|
||||
|
||||
# Install smartcard signing CA certs
|
||||
|
||||
- name: Install smartcard signing CA certs
|
||||
ansible.builtin.command: ipa-cacert-manage install "{{ item }}" -t CT,C,C
|
||||
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
|
||||
|
||||
# Update ipa CA certificate store
|
||||
|
||||
- name: Update ipa CA certificate store
|
||||
ansible.builtin.command: ipa-certupdate
|
||||
|
||||
# Restart krb5kdc
|
||||
|
||||
- name: Restart krb5kdc
|
||||
ansible.builtin.service:
|
||||
name: krb5kdc
|
||||
state: restarted
|
||||
|
||||
### ALWAYS ###
|
||||
|
||||
always:
|
||||
- name: kdestroy
|
||||
ansible.builtin.command: kdestroy -A
|
||||
2
roles/ipasmartcard_server/vars/default.yml
Normal file
2
roles/ipasmartcard_server/vars/default.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
ipasmartcard_server_bindutils_packages: [ "bind-utils" ]
|
||||
Reference in New Issue
Block a user