Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4bfb2527f8 | 
							
								
								
									
										1
									
								
								.ansible-freeipa.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.ansible-freeipa.metadata
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| 03f590ebf93439a08c56f8b98e61f38619309556 SOURCES/ansible-freeipa-1.9.2.tar.gz | ||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| SOURCES/ansible-freeipa-1.12.1.tar.gz | ||||
| SOURCES/ansible-freeipa-1.9.2.tar.gz | ||||
|  | ||||
							
								
								
									
										30
									
								
								SOURCES/0001-Fix-typo-in-ipapwpolicy.py.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								SOURCES/0001-Fix-typo-in-ipapwpolicy.py.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| From 1a7b279d78374598d0330718c81c93048d54dd7c Mon Sep 17 00:00:00 2001 | ||||
| From: Jacob Cutright <cutrightjm@stl.sh> | ||||
| Date: Wed, 26 Apr 2023 17:32:50 -0400 | ||||
| Subject: [PATCH] Fix typo in ipapwpolicy.py | ||||
| 
 | ||||
| The 'maxsequence' attribute was never applied as there was a typo when | ||||
| it was set. By fixing the field name, 'maxsequence' is correclty set. | ||||
| 
 | ||||
| The failure was not seen before due to missing tests. The tests will be | ||||
| added in a separate PR. | ||||
| ---
 | ||||
|  plugins/modules/ipapwpolicy.py | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/plugins/modules/ipapwpolicy.py b/plugins/modules/ipapwpolicy.py
 | ||||
| index 3a3eeed..557702f 100644
 | ||||
| --- a/plugins/modules/ipapwpolicy.py
 | ||||
| +++ b/plugins/modules/ipapwpolicy.py
 | ||||
| @@ -197,7 +197,7 @@ def gen_args(module,
 | ||||
|      if maxrepeat is not None: | ||||
|          _args["ipapwdmaxrepeat"] = maxrepeat | ||||
|      if maxsequence is not None: | ||||
| -        _args["ipapwdmaxrsequence"] = maxsequence
 | ||||
| +        _args["ipapwdmaxsequence"] = maxsequence
 | ||||
|      if dictcheck is not None: | ||||
|          if module.ipa_check_version("<", "4.9.10"): | ||||
|              # Allowed values: "TRUE", "FALSE", "" | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
							
								
								
									
										48
									
								
								SOURCES/0002-pwpolicy-test-Fix-maxsequence-test.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								SOURCES/0002-pwpolicy-test-Fix-maxsequence-test.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| From d04a12e522e4ef9d23673916afb9e57ed032c56e Mon Sep 17 00:00:00 2001 | ||||
| From: Thomas Woerner <twoerner@redhat.com> | ||||
| Date: Thu, 27 Apr 2023 09:15:09 +0200 | ||||
| Subject: [PATCH] pwpolicy test: Fix maxsequence test | ||||
| 
 | ||||
| The maxsequence test was testing maxrepeat. Therefore the typo reported | ||||
| with https://github.com/freeipa/ansible-freeipa/pull/1081 was never | ||||
| seen. | ||||
| 
 | ||||
| The test has been fixed. | ||||
| ---
 | ||||
|  tests/pwpolicy/test_pwpolicy.yml | 6 +++--- | ||||
|  1 file changed, 3 insertions(+), 3 deletions(-) | ||||
| 
 | ||||
| diff --git a/tests/pwpolicy/test_pwpolicy.yml b/tests/pwpolicy/test_pwpolicy.yml
 | ||||
| index 871406f..83f1763 100644
 | ||||
| --- a/tests/pwpolicy/test_pwpolicy.yml
 | ||||
| +++ b/tests/pwpolicy/test_pwpolicy.yml
 | ||||
| @@ -223,7 +223,7 @@
 | ||||
|        ipapwpolicy: | ||||
|          ipaadmin_password: SomeADMINpassword | ||||
|          ipaapi_context: "{{ ipa_context | default(omit) }}" | ||||
| -        maxrepeat: 4
 | ||||
| +        maxsequence: 4
 | ||||
|        register: result | ||||
|        failed_when: not result.changed or result.failed | ||||
|   | ||||
| @@ -231,7 +231,7 @@
 | ||||
|        ipapwpolicy: | ||||
|          ipaadmin_password: SomeADMINpassword | ||||
|          ipaapi_context: "{{ ipa_context | default(omit) }}" | ||||
| -        maxrepeat: 4
 | ||||
| +        maxsequence: 4
 | ||||
|        register: result | ||||
|        failed_when: result.changed or result.failed | ||||
|   | ||||
| @@ -239,7 +239,7 @@
 | ||||
|        ipapwpolicy: | ||||
|          ipaadmin_password: SomeADMINpassword | ||||
|          ipaapi_context: "{{ ipa_context | default(omit) }}" | ||||
| -        maxrepeat: 0
 | ||||
| +        maxsequence: 0
 | ||||
|        register: result | ||||
|        failed_when: not result.changed or result.failed | ||||
|   | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
| @ -0,0 +1,727 @@ | ||||
| From 6b5acd9b0c8de965d9b815f8033a2bace9dd737d Mon Sep 17 00:00:00 2001 | ||||
| From: Thomas Woerner <twoerner@redhat.com> | ||||
| Date: Wed, 22 Feb 2023 13:35:18 +0100 | ||||
| Subject: [PATCH] ipaclient: Defer creating the final krb5.conf on clients | ||||
| 
 | ||||
| A temporary krb5 configuration was used to join the domain in | ||||
| ipaclient_join. After that the final krkb5 configuration was created | ||||
| with enabled DNS discovery and used for the remainaing tasks, where also | ||||
| a connection to the IPA API was done. | ||||
| 
 | ||||
| With several servers the DNS discovery could have picked up a different | ||||
| server. If the client deployment was faster than the replication this | ||||
| could have lead to an unknown host error. | ||||
| 
 | ||||
| The issue was seen in performance testing where many simultaneous client | ||||
| enrollments have been done.. | ||||
| 
 | ||||
| The goal is to keep server affinity as long as possible within the | ||||
| deployment process: | ||||
| 
 | ||||
| The temporary krb5.conf that was used before in ipaclient_join was | ||||
| pulled out into an own module. The generated temporary krb5.conf is now | ||||
| used in ipaclient_join and also ipaclient_api. | ||||
| 
 | ||||
| The generation of the final krb5.conf is moved to the end of the | ||||
| deployment process. | ||||
| 
 | ||||
| Same as: https://pagure.io/freeipa/issue/9228 | ||||
| 
 | ||||
| The setup of certmonger has been pulled out of ipaclient_setup_nss and moved | ||||
| to the end of the process after generating the final krb5.conf as it will | ||||
| use t will only use /etc/krb5.conf. | ||||
| 
 | ||||
| Certificate issuance may fail during deployment due to using the final | ||||
| krb5.conf, but certmonger will re-try the request in this case. | ||||
| 
 | ||||
| Same as: https://pagure.io/freeipa/issue/9246 | ||||
| ---
 | ||||
|  roles/ipaclient/library/ipaclient_api.py      |   8 + | ||||
|  roles/ipaclient/library/ipaclient_join.py     |  55 ++---- | ||||
|  .../library/ipaclient_setup_certmonger.py     | 123 +++++++++++++ | ||||
|  .../ipaclient/library/ipaclient_setup_nss.py  |   4 +- | ||||
|  .../ipaclient/library/ipaclient_temp_krb5.py  | 163 ++++++++++++++++++ | ||||
|  .../library/ipaclient_test_keytab.py          |   6 + | ||||
|  roles/ipaclient/tasks/install.yml             |  69 ++++++-- | ||||
|  7 files changed, 365 insertions(+), 63 deletions(-) | ||||
|  create mode 100644 roles/ipaclient/library/ipaclient_setup_certmonger.py | ||||
|  create mode 100644 roles/ipaclient/library/ipaclient_temp_krb5.py | ||||
| 
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_api.py b/roles/ipaclient/library/ipaclient_api.py
 | ||||
| index 7d4b829..9193f60 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_api.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_api.py
 | ||||
| @@ -55,6 +55,10 @@ options:
 | ||||
|      type: bool | ||||
|      required: no | ||||
|      default: no | ||||
| +  krb_name:
 | ||||
| +    description: The krb5 config file name
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
|  author: | ||||
|      - Thomas Woerner (@t-woerner) | ||||
|  ''' | ||||
| @@ -65,6 +69,7 @@ EXAMPLES = '''
 | ||||
|      servers: ["server1.example.com","server2.example.com"] | ||||
|      domain: example.com | ||||
|      hostname: client1.example.com | ||||
| +    krb_name: /tmp/tmpkrb5.conf
 | ||||
|    register: result_ipaclient_api | ||||
|  ''' | ||||
|   | ||||
| @@ -99,6 +104,7 @@ def main():
 | ||||
|              realm=dict(required=True, type='str'), | ||||
|              hostname=dict(required=True, type='str'), | ||||
|              debug=dict(required=False, type='bool', default="false"), | ||||
| +            krb_name=dict(required=True, type='str'),
 | ||||
|          ), | ||||
|          supports_check_mode=False, | ||||
|      ) | ||||
| @@ -110,9 +116,11 @@ def main():
 | ||||
|      realm = module.params.get('realm') | ||||
|      hostname = module.params.get('hostname') | ||||
|      debug = module.params.get('debug') | ||||
| +    krb_name = module.params.get('krb_name')
 | ||||
|   | ||||
|      host_principal = 'host/%s@%s' % (hostname, realm) | ||||
|      os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE | ||||
| +    os.environ['KRB5_CONFIG'] = krb_name
 | ||||
|   | ||||
|      ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT) | ||||
|      if 40500 <= NUM_VERSION < 40590: | ||||
| diff --git a/roles/ipaclient/library/ipaclient_join.py b/roles/ipaclient/library/ipaclient_join.py
 | ||||
| index 5d41a54..68379ea 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_join.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_join.py
 | ||||
| @@ -46,10 +46,6 @@ options:
 | ||||
|      type: list | ||||
|      elements: str | ||||
|      required: yes | ||||
| -  domain:
 | ||||
| -    description: Primary DNS domain of the IPA deployment
 | ||||
| -    type: str
 | ||||
| -    required: yes
 | ||||
|    realm: | ||||
|      description: Kerberos realm name of the IPA deployment | ||||
|      type: str | ||||
| @@ -58,10 +54,6 @@ options:
 | ||||
|      description: Fully qualified name of this host | ||||
|      type: str | ||||
|      required: yes | ||||
| -  kdc:
 | ||||
| -    description: The name or address of the host running the KDC
 | ||||
| -    type: str
 | ||||
| -    required: yes
 | ||||
|    basedn: | ||||
|      description: The basedn of the IPA server (of the form dc=example,dc=com) | ||||
|      type: str | ||||
| @@ -102,6 +94,10 @@ options:
 | ||||
|      description: Turn on extra debugging | ||||
|      type: bool | ||||
|      required: no | ||||
| +  krb_name:
 | ||||
| +    description: The krb5 config file name
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
|  author: | ||||
|      - Thomas Woerner (@t-woerner) | ||||
|  ''' | ||||
| @@ -111,27 +107,25 @@ EXAMPLES = '''
 | ||||
|  - name: Join IPA in force mode with maximum 5 kinit attempts | ||||
|    ipaclient_join: | ||||
|      servers: ["server1.example.com","server2.example.com"] | ||||
| -    domain: example.com
 | ||||
|      realm: EXAMPLE.COM | ||||
| -    kdc: server1.example.com
 | ||||
|      basedn: dc=example,dc=com | ||||
|      hostname: client1.example.com | ||||
|      principal: admin | ||||
|      password: MySecretPassword | ||||
|      force_join: yes | ||||
|      kinit_attempts: 5 | ||||
| +    krb_name: /tmp/tmpkrb5.conf
 | ||||
|   | ||||
|  # Join IPA to get the keytab using ipadiscovery return values | ||||
|  - name: Join IPA | ||||
|    ipaclient_join: | ||||
|      servers: "{{ ipadiscovery.servers }}" | ||||
| -    domain: "{{ ipadiscovery.domain }}"
 | ||||
|      realm: "{{ ipadiscovery.realm }}" | ||||
| -    kdc: "{{ ipadiscovery.kdc }}"
 | ||||
|      basedn: "{{ ipadiscovery.basedn }}" | ||||
|      hostname: "{{ ipadiscovery.hostname }}" | ||||
|      principal: admin | ||||
|      password: MySecretPassword | ||||
| +    krb_name: /tmp/tmpkrb5.conf
 | ||||
|  ''' | ||||
|   | ||||
|  RETURN = ''' | ||||
| @@ -147,9 +141,9 @@ import tempfile
 | ||||
|  from ansible.module_utils.basic import AnsibleModule | ||||
|  from ansible.module_utils.ansible_ipa_client import ( | ||||
|      setup_logging, check_imports, | ||||
| -    SECURE_PATH, sysrestore, paths, options, configure_krb5_conf,
 | ||||
| -    realm_to_suffix, kinit_keytab, GSSError, kinit_password, NUM_VERSION,
 | ||||
| -    get_ca_cert, get_ca_certs, errors, run
 | ||||
| +    SECURE_PATH, sysrestore, paths, options, realm_to_suffix, kinit_keytab,
 | ||||
| +    GSSError, kinit_password, NUM_VERSION, get_ca_cert, get_ca_certs, errors,
 | ||||
| +    run
 | ||||
|  ) | ||||
|   | ||||
|   | ||||
| @@ -157,10 +151,8 @@ def main():
 | ||||
|      module = AnsibleModule( | ||||
|          argument_spec=dict( | ||||
|              servers=dict(required=True, type='list', elements='str'), | ||||
| -            domain=dict(required=True, type='str'),
 | ||||
|              realm=dict(required=True, type='str'), | ||||
|              hostname=dict(required=True, type='str'), | ||||
| -            kdc=dict(required=True, type='str'),
 | ||||
|              basedn=dict(required=True, type='str'), | ||||
|              principal=dict(required=False, type='str'), | ||||
|              password=dict(required=False, type='str', no_log=True), | ||||
| @@ -170,6 +162,7 @@ def main():
 | ||||
|              force_join=dict(required=False, type='bool'), | ||||
|              kinit_attempts=dict(required=False, type='int', default=5), | ||||
|              debug=dict(required=False, type='bool'), | ||||
| +            krb_name=dict(required=True, type='str'),
 | ||||
|          ), | ||||
|          supports_check_mode=False, | ||||
|      ) | ||||
| @@ -179,11 +172,9 @@ def main():
 | ||||
|      setup_logging() | ||||
|   | ||||
|      servers = module.params.get('servers') | ||||
| -    domain = module.params.get('domain')
 | ||||
|      realm = module.params.get('realm') | ||||
|      hostname = module.params.get('hostname') | ||||
|      basedn = module.params.get('basedn') | ||||
| -    kdc = module.params.get('kdc')
 | ||||
|      force_join = module.params.get('force_join') | ||||
|      principal = module.params.get('principal') | ||||
|      password = module.params.get('password') | ||||
| @@ -192,6 +183,7 @@ def main():
 | ||||
|      ca_cert_file = module.params.get('ca_cert_file') | ||||
|      kinit_attempts = module.params.get('kinit_attempts') | ||||
|      debug = module.params.get('debug') | ||||
| +    krb_name = module.params.get('krb_name')
 | ||||
|   | ||||
|      if password is not None and keytab is not None: | ||||
|          module.fail_json(msg="Password and keytab cannot be used together") | ||||
| @@ -199,12 +191,10 @@ def main():
 | ||||
|      if password is None and admin_keytab is None: | ||||
|          module.fail_json(msg="Password or admin_keytab is needed") | ||||
|   | ||||
| -    client_domain = hostname[hostname.find(".") + 1:]
 | ||||
|      nolog = tuple() | ||||
|      env = {'PATH': SECURE_PATH} | ||||
|      fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) | ||||
|      host_principal = 'host/%s@%s' % (hostname, realm) | ||||
| -    sssd = True
 | ||||
|   | ||||
|      options.ca_cert_file = ca_cert_file | ||||
|      options.principal = principal | ||||
| @@ -215,19 +205,6 @@ def main():
 | ||||
|      changed = False | ||||
|      already_joined = False | ||||
|      try: | ||||
| -        (krb_fd, krb_name) = tempfile.mkstemp()
 | ||||
| -        os.close(krb_fd)
 | ||||
| -        configure_krb5_conf(
 | ||||
| -            cli_realm=realm,
 | ||||
| -            cli_domain=domain,
 | ||||
| -            cli_server=servers,
 | ||||
| -            cli_kdc=kdc,
 | ||||
| -            dnsok=False,
 | ||||
| -            filename=krb_name,
 | ||||
| -            client_domain=client_domain,
 | ||||
| -            client_hostname=hostname,
 | ||||
| -            configure_sssd=sssd,
 | ||||
| -            force=False)
 | ||||
|          env['KRB5_CONFIG'] = krb_name | ||||
|          ccache_dir = tempfile.mkdtemp(prefix='krbcc') | ||||
|          ccache_name = os.path.join(ccache_dir, 'ccache') | ||||
| @@ -336,27 +313,17 @@ def main():
 | ||||
|                           paths.IPA_DNS_CCACHE, | ||||
|                           config=krb_name, | ||||
|                           attempts=kinit_attempts) | ||||
| -            env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
 | ||||
|          except GSSError as e: | ||||
|              # failure to get ticket makes it impossible to login and | ||||
|              # bind from sssd to LDAP, abort installation | ||||
|              module.fail_json(msg="Failed to obtain host TGT: %s" % e) | ||||
|   | ||||
|      finally: | ||||
| -        try:
 | ||||
| -            os.remove(krb_name)
 | ||||
| -        except OSError:
 | ||||
| -            module.fail_json(msg="Could not remove %s" % krb_name)
 | ||||
|          if ccache_dir is not None: | ||||
|              try: | ||||
|                  os.rmdir(ccache_dir) | ||||
|              except OSError: | ||||
|                  pass | ||||
| -        if os.path.exists(krb_name + ".ipabkp"):
 | ||||
| -            try:
 | ||||
| -                os.remove(krb_name + ".ipabkp")
 | ||||
| -            except OSError:
 | ||||
| -                module.fail_json(msg="Could not remove %s.ipabkp" % krb_name)
 | ||||
|   | ||||
|      module.exit_json(changed=changed, | ||||
|                       already_joined=already_joined) | ||||
| diff --git a/roles/ipaclient/library/ipaclient_setup_certmonger.py b/roles/ipaclient/library/ipaclient_setup_certmonger.py
 | ||||
| new file mode 100644 | ||||
| index 0000000..5c81b40
 | ||||
| --- /dev/null
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_setup_certmonger.py
 | ||||
| @@ -0,0 +1,123 @@
 | ||||
| +# -*- coding: utf-8 -*-
 | ||||
| +
 | ||||
| +# Authors:
 | ||||
| +#   Thomas Woerner <twoerner@redhat.com>
 | ||||
| +#
 | ||||
| +# Based on ipa-client-install code
 | ||||
| +#
 | ||||
| +# Copyright (C) 2017-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: ipaclient_setup_certmonger
 | ||||
| +short_description: Setup certmonger for IPA client
 | ||||
| +description: Setup certmonger for IPA client
 | ||||
| +options:
 | ||||
| +  realm:
 | ||||
| +    description: Kerberos realm name of the IPA deployment
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  hostname:
 | ||||
| +    description: Fully qualified name of this host
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  subject_base:
 | ||||
| +    description: |
 | ||||
| +      The certificate subject base (default O=<realm-name>).
 | ||||
| +      RDNs are in LDAP order (most specific RDN first).
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  ca_enabled:
 | ||||
| +    description: Whether the Certificate Authority is enabled or not
 | ||||
| +    type: bool
 | ||||
| +    required: yes
 | ||||
| +  request_cert:
 | ||||
| +    description: Request certificate for the machine
 | ||||
| +    type: bool
 | ||||
| +    required: yes
 | ||||
| +author:
 | ||||
| +    - Thomas Woerner (@t-woerner)
 | ||||
| +'''
 | ||||
| +
 | ||||
| +EXAMPLES = '''
 | ||||
| +- name: Setup certmonger for IPA client
 | ||||
| +  ipaclient_setup_certmonger:
 | ||||
| +    realm: EXAMPLE.COM
 | ||||
| +    hostname: client1.example.com
 | ||||
| +    subject_base: O=EXAMPLE.COM
 | ||||
| +    ca_enabled: true
 | ||||
| +    request_cert: false
 | ||||
| +'''
 | ||||
| +
 | ||||
| +RETURN = '''
 | ||||
| +'''
 | ||||
| +
 | ||||
| +from ansible.module_utils.basic import AnsibleModule
 | ||||
| +from ansible.module_utils.ansible_ipa_client import (
 | ||||
| +    setup_logging, check_imports,
 | ||||
| +    options, sysrestore, paths, ScriptError, configure_certmonger
 | ||||
| +)
 | ||||
| +
 | ||||
| +
 | ||||
| +def main():
 | ||||
| +    module = AnsibleModule(
 | ||||
| +        argument_spec=dict(
 | ||||
| +            realm=dict(required=True, type='str'),
 | ||||
| +            hostname=dict(required=True, type='str'),
 | ||||
| +            subject_base=dict(required=True, type='str'),
 | ||||
| +            ca_enabled=dict(required=True, type='bool'),
 | ||||
| +            request_cert=dict(required=True, type='bool'),
 | ||||
| +        ),
 | ||||
| +        supports_check_mode=False,
 | ||||
| +    )
 | ||||
| +
 | ||||
| +    module._ansible_debug = True
 | ||||
| +    check_imports(module)
 | ||||
| +    setup_logging()
 | ||||
| +
 | ||||
| +    cli_realm = module.params.get('realm')
 | ||||
| +    hostname = module.params.get('hostname')
 | ||||
| +    subject_base = module.params.get('subject_base')
 | ||||
| +    ca_enabled = module.params.get('ca_enabled')
 | ||||
| +
 | ||||
| +    fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
 | ||||
| +
 | ||||
| +    options.request_cert = module.params.get('request_cert')
 | ||||
| +    options.hostname = hostname
 | ||||
| +
 | ||||
| +    try:
 | ||||
| +        configure_certmonger(fstore, subject_base, cli_realm, hostname,
 | ||||
| +                             options, ca_enabled)
 | ||||
| +
 | ||||
| +    except ScriptError as e:
 | ||||
| +        module.fail_json(msg=str(e))
 | ||||
| +
 | ||||
| +    module.exit_json(changed=True)
 | ||||
| +
 | ||||
| +
 | ||||
| +if __name__ == '__main__':
 | ||||
| +    main()
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_setup_nss.py b/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| index 3dc0dcc..240bc76 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| @@ -177,7 +177,7 @@ from ansible.module_utils.ansible_ipa_client import (
 | ||||
|      options, sysrestore, paths, ansible_module_get_parsed_ip_addresses, | ||||
|      api, errors, create_ipa_nssdb, ipautil, ScriptError, CLIENT_INSTALL_ERROR, | ||||
|      get_certs_from_ldap, DN, certstore, x509, logger, certdb, | ||||
| -    CalledProcessError, tasks, client_dns, configure_certmonger, services,
 | ||||
| +    CalledProcessError, tasks, client_dns, services,
 | ||||
|      update_ssh_keys, save_state, configure_ldap_conf, configure_nslcd_conf, | ||||
|      configure_openldap_conf, hardcode_ldap_server, getargspec, NUM_VERSION, | ||||
|      serialization | ||||
| @@ -350,8 +350,6 @@ def main():
 | ||||
|   | ||||
|          if not options.on_master: | ||||
|              client_dns(cli_server[0], hostname, options) | ||||
| -            configure_certmonger(fstore, subject_base, cli_realm, hostname,
 | ||||
| -                                 options, ca_enabled)
 | ||||
|   | ||||
|          if hasattr(paths, "SSH_CONFIG_DIR"): | ||||
|              ssh_config_dir = paths.SSH_CONFIG_DIR | ||||
| diff --git a/roles/ipaclient/library/ipaclient_temp_krb5.py b/roles/ipaclient/library/ipaclient_temp_krb5.py
 | ||||
| new file mode 100644 | ||||
| index 0000000..cbe652c
 | ||||
| --- /dev/null
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_temp_krb5.py
 | ||||
| @@ -0,0 +1,163 @@
 | ||||
| +# -*- coding: utf-8 -*-
 | ||||
| +
 | ||||
| +# Authors:
 | ||||
| +#   Thomas Woerner <twoerner@redhat.com>
 | ||||
| +#
 | ||||
| +# Based on ipa-client-install code
 | ||||
| +#
 | ||||
| +# Copyright (C) 2017-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: ipaclient_temp_krb5
 | ||||
| +short_description:
 | ||||
| +  Create temporary krb5 configuration.
 | ||||
| +description:
 | ||||
| +  Create temporary krb5 configuration for deferring the creation of the final
 | ||||
| +  krb5.conf on clients
 | ||||
| +options:
 | ||||
| +  servers:
 | ||||
| +    description: Fully qualified name of IPA servers to enroll to
 | ||||
| +    type: list
 | ||||
| +    elements: str
 | ||||
| +    required: yes
 | ||||
| +  domain:
 | ||||
| +    description: Primary DNS domain of the IPA deployment
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  realm:
 | ||||
| +    description: Kerberos realm name of the IPA deployment
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  hostname:
 | ||||
| +    description: Fully qualified name of this host
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  kdc:
 | ||||
| +    description: The name or address of the host running the KDC
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
| +  on_master:
 | ||||
| +    description: Whether the configuration is done on the master or not
 | ||||
| +    type: bool
 | ||||
| +    required: no
 | ||||
| +    default: no
 | ||||
| +author:
 | ||||
| +    - Thomas Woerner (@t-woerner)
 | ||||
| +'''
 | ||||
| +
 | ||||
| +EXAMPLES = '''
 | ||||
| +# Test IPA with local keytab
 | ||||
| +- name: Test IPA in force mode with maximum 5 kinit attempts
 | ||||
| +  ipaclient_test_keytab:
 | ||||
| +    servers: ["server1.example.com","server2.example.com"]
 | ||||
| +    domain: example.com
 | ||||
| +    realm: EXAMPLE.COM
 | ||||
| +    kdc: server1.example.com
 | ||||
| +    hostname: client1.example.com
 | ||||
| +
 | ||||
| +# Test IPA with ipadiscovery return values
 | ||||
| +- name: Join IPA
 | ||||
| +  ipaclient_test_keytab:
 | ||||
| +    servers: "{{ ipadiscovery.servers }}"
 | ||||
| +    domain: "{{ ipadiscovery.domain }}"
 | ||||
| +    realm: "{{ ipadiscovery.realm }}"
 | ||||
| +    kdc: "{{ ipadiscovery.kdc }}"
 | ||||
| +    hostname: "{{ ipadiscovery.hostname }}"
 | ||||
| +'''
 | ||||
| +
 | ||||
| +RETURN = '''
 | ||||
| +krb_name:
 | ||||
| +  description: The krb5 config file name
 | ||||
| +  returned: always
 | ||||
| +  type: str
 | ||||
| +'''
 | ||||
| +
 | ||||
| +import os
 | ||||
| +import tempfile
 | ||||
| +
 | ||||
| +from ansible.module_utils.basic import AnsibleModule
 | ||||
| +from ansible.module_utils.ansible_ipa_client import (
 | ||||
| +    setup_logging, check_imports, configure_krb5_conf
 | ||||
| +)
 | ||||
| +
 | ||||
| +
 | ||||
| +def main():
 | ||||
| +    module = AnsibleModule(
 | ||||
| +        argument_spec=dict(
 | ||||
| +            servers=dict(required=True, type='list', elements='str'),
 | ||||
| +            domain=dict(required=True, type='str'),
 | ||||
| +            realm=dict(required=True, type='str'),
 | ||||
| +            hostname=dict(required=True, type='str'),
 | ||||
| +            kdc=dict(required=True, type='str'),
 | ||||
| +            on_master=dict(required=False, type='bool', default=False),
 | ||||
| +        ),
 | ||||
| +        supports_check_mode=False,
 | ||||
| +    )
 | ||||
| +
 | ||||
| +    module._ansible_debug = True
 | ||||
| +    check_imports(module)
 | ||||
| +    setup_logging()
 | ||||
| +
 | ||||
| +    servers = module.params.get('servers')
 | ||||
| +    domain = module.params.get('domain')
 | ||||
| +    realm = module.params.get('realm')
 | ||||
| +    hostname = module.params.get('hostname')
 | ||||
| +    kdc = module.params.get('kdc')
 | ||||
| +    client_domain = hostname[hostname.find(".") + 1:]
 | ||||
| +
 | ||||
| +    krb_name = None
 | ||||
| +    # Create temporary krb5 configuration
 | ||||
| +    try:
 | ||||
| +        (krb_fd, krb_name) = tempfile.mkstemp()
 | ||||
| +        os.close(krb_fd)
 | ||||
| +        configure_krb5_conf(
 | ||||
| +            cli_realm=realm,
 | ||||
| +            cli_domain=domain,
 | ||||
| +            cli_server=servers,
 | ||||
| +            cli_kdc=kdc,
 | ||||
| +            dnsok=False,
 | ||||
| +            filename=krb_name,
 | ||||
| +            client_domain=client_domain,
 | ||||
| +            client_hostname=hostname,
 | ||||
| +            configure_sssd=True,
 | ||||
| +            force=False)
 | ||||
| +    except Exception as ex:
 | ||||
| +        if krb_name:
 | ||||
| +            try:
 | ||||
| +                os.remove(krb_name)
 | ||||
| +            except OSError:
 | ||||
| +                module.fail_json(msg="Could not remove %s" % krb_name)
 | ||||
| +        module.fail_json(
 | ||||
| +            msg="Failed to create temporary krb5 configuration: %s" % str(ex))
 | ||||
| +
 | ||||
| +    module.exit_json(changed=False,
 | ||||
| +                     krb_name=krb_name)
 | ||||
| +
 | ||||
| +
 | ||||
| +if __name__ == '__main__':
 | ||||
| +    main()
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_test_keytab.py b/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| index 3f1c69d..3bebeea 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| @@ -244,6 +244,12 @@ def main():
 | ||||
|                  os.remove(krb_name) | ||||
|              except OSError: | ||||
|                  module.fail_json(msg="Could not remove %s" % krb_name) | ||||
| +            if os.path.exists(krb_name + ".ipabkp"):
 | ||||
| +                try:
 | ||||
| +                    os.remove(krb_name + ".ipabkp")
 | ||||
| +                except OSError:
 | ||||
| +                    module.fail_json(
 | ||||
| +                        msg="Could not remove %s.ipabkp" % krb_name)
 | ||||
|   | ||||
|      module.exit_json(changed=False, | ||||
|                       krb5_keytab_ok=krb5_keytab_ok, | ||||
| diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml
 | ||||
| index fa33f89..1b889d0 100644
 | ||||
| --- a/roles/ipaclient/tasks/install.yml
 | ||||
| +++ b/roles/ipaclient/tasks/install.yml
 | ||||
| @@ -239,12 +239,19 @@
 | ||||
|        hostname: "{{ result_ipaclient_test.hostname }}" | ||||
|      when: not ipaclient_on_master | bool | ||||
|   | ||||
| -  - name: Install - Join IPA
 | ||||
| -    ipaclient_join:
 | ||||
| +  - name: Install - Create temporary krb5 configuration
 | ||||
| +    ipaclient_temp_krb5:
 | ||||
|        servers: "{{ result_ipaclient_test.servers }}" | ||||
|        domain: "{{ result_ipaclient_test.domain }}" | ||||
|        realm: "{{ result_ipaclient_test.realm }}" | ||||
| +      hostname: "{{ result_ipaclient_test.hostname }}"
 | ||||
|        kdc: "{{ result_ipaclient_test.kdc }}" | ||||
| +    register: result_ipaclient_temp_krb5
 | ||||
| +
 | ||||
| +  - name: Install - Join IPA
 | ||||
| +    ipaclient_join:
 | ||||
| +      servers: "{{ result_ipaclient_test.servers }}"
 | ||||
| +      realm: "{{ result_ipaclient_test.realm }}"
 | ||||
|        basedn: "{{ result_ipaclient_test.basedn }}" | ||||
|        hostname: "{{ result_ipaclient_test.hostname }}" | ||||
|        force_join: "{{ ipaclient_force_join | default(omit) }}" | ||||
| @@ -255,6 +262,7 @@
 | ||||
|        admin_keytab: "{{ ipaadmin_keytab if ipaadmin_keytab is defined and not ipaclient_use_otp | bool else omit }}" | ||||
|        # ca_cert_file: "{{ ipaclient_ca_cert_file | default(omit) }}" | ||||
|        kinit_attempts: "{{ ipaclient_kinit_attempts | default(omit) }}" | ||||
| +      krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
|      register: result_ipaclient_join | ||||
|      when: not ipaclient_on_master | bool and | ||||
|            (not result_ipaclient_test_keytab.krb5_keytab_ok or | ||||
| @@ -323,26 +331,13 @@
 | ||||
|            "{{ ipassd_no_krb5_offline_passwords | ||||
|                | default(ipasssd_no_krb5_offline_passwords) }}" | ||||
|   | ||||
| -    - name: Install - Configure krb5 for IPA realm
 | ||||
| -      ipaclient_setup_krb5:
 | ||||
| -        realm: "{{ result_ipaclient_test.realm }}"
 | ||||
| -        domain: "{{ result_ipaclient_test.domain }}"
 | ||||
| -        servers: "{{ result_ipaclient_test.servers }}"
 | ||||
| -        kdc: "{{ result_ipaclient_test.kdc }}"
 | ||||
| -        dnsok: "{{ result_ipaclient_test.dnsok }}"
 | ||||
| -        client_domain: "{{ result_ipaclient_test.client_domain }}"
 | ||||
| -        hostname: "{{ result_ipaclient_test.hostname }}"
 | ||||
| -        sssd: "{{ result_ipaclient_test.sssd }}"
 | ||||
| -        force: "{{ ipaclient_force }}"
 | ||||
| -        # on_master: "{{ ipaclient_on_master }}"
 | ||||
| -      when: not ipaclient_on_master | bool
 | ||||
| -
 | ||||
|      - name: Install - IPA API calls for remaining enrollment parts | ||||
|        ipaclient_api: | ||||
|          servers: "{{ result_ipaclient_test.servers }}" | ||||
|          realm: "{{ result_ipaclient_test.realm }}" | ||||
|          hostname: "{{ result_ipaclient_test.hostname }}" | ||||
|          # debug: yes | ||||
| +        krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
|        register: result_ipaclient_api | ||||
|   | ||||
|      - name: Install - Fix IPA ca | ||||
| @@ -412,6 +407,36 @@
 | ||||
|          domain: "{{ result_ipaclient_test.domain }}" | ||||
|          nisdomain: "{{ ipaclient_nisdomain | default(omit) }}" | ||||
|        when: not ipaclient_no_nisdomain | bool | ||||
| +
 | ||||
| +    - name: Remove temporary krb5.conf
 | ||||
| +      ansible.builtin.file:
 | ||||
| +        path: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
| +        state: absent
 | ||||
| +      when: result_ipaclient_temp_krb5.krb_name is defined
 | ||||
| +
 | ||||
| +    - name: Install - Configure krb5 for IPA realm
 | ||||
| +      ipaclient_setup_krb5:
 | ||||
| +        realm: "{{ result_ipaclient_test.realm }}"
 | ||||
| +        domain: "{{ result_ipaclient_test.domain }}"
 | ||||
| +        servers: "{{ result_ipaclient_test.servers }}"
 | ||||
| +        kdc: "{{ result_ipaclient_test.kdc }}"
 | ||||
| +        dnsok: "{{ result_ipaclient_test.dnsok }}"
 | ||||
| +        client_domain: "{{ result_ipaclient_test.client_domain }}"
 | ||||
| +        hostname: "{{ result_ipaclient_test.hostname }}"
 | ||||
| +        sssd: "{{ result_ipaclient_test.sssd }}"
 | ||||
| +        force: "{{ ipaclient_force }}"
 | ||||
| +        # on_master: "{{ ipaclient_on_master }}"
 | ||||
| +      when: not ipaclient_on_master | bool
 | ||||
| +
 | ||||
| +    - name: Install - Configure certmonger
 | ||||
| +      ipaclient_setup_certmonger:
 | ||||
| +        realm: "{{ result_ipaclient_test.realm }}"
 | ||||
| +        hostname: "{{ result_ipaclient_test.hostname }}"
 | ||||
| +        subject_base: "{{ result_ipaclient_api.subject_base }}"
 | ||||
| +        ca_enabled: "{{ result_ipaclient_api.ca_enabled }}"
 | ||||
| +        request_cert: "{{ ipaclient_request_cert }}"
 | ||||
| +      when: not ipaclient_on_master | bool
 | ||||
| +
 | ||||
|    always: | ||||
|    - name: Install - Restore original admin password if overwritten by OTP | ||||
|      no_log: yes | ||||
| @@ -423,3 +448,15 @@
 | ||||
|      ansible.builtin.file: | ||||
|        path: "/etc/ipa/.dns_ccache" | ||||
|        state: absent | ||||
| +
 | ||||
| +  - name: Remove temporary krb5.conf
 | ||||
| +    ansible.builtin.file:
 | ||||
| +      path: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
| +      state: absent
 | ||||
| +    when: result_ipaclient_temp_krb5.krb_name is defined
 | ||||
| +
 | ||||
| +  - name: Remove temporary krb5.conf backup
 | ||||
| +    ansible.builtin.file:
 | ||||
| +      path: "{{ result_ipaclient_temp_krb5.krb_name }}.ipabkp"
 | ||||
| +      state: absent
 | ||||
| +    when: result_ipaclient_temp_krb5.krb_name is defined
 | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
| @ -0,0 +1,152 @@ | ||||
| From 0ec89eb53cf8771b34528ec210b2614370d9b662 Mon Sep 17 00:00:00 2001 | ||||
| From: Thomas Woerner <twoerner@redhat.com> | ||||
| Date: Thu, 23 Mar 2023 18:13:08 +0100 | ||||
| Subject: [PATCH] ipaclient: ipaclient_setup_nss also needs krb_name parameter | ||||
| 
 | ||||
| With the fix to defer creating the final krb5.conf on clients a bug has | ||||
| been introduced with ipaclient_setup_nss: The krb_name parameter that | ||||
| points to the temporary krb5 configuration was not added to the module. | ||||
| 
 | ||||
| With a properly configured DNS (like for example IPA DNS) the krb TXT | ||||
| records have been present in the DNS configuration. These have been used | ||||
| automatically as a fallback and broke server affinity for the client. | ||||
| Without the TXT records creating the IPA NSS database failed with | ||||
|  "Cannot find KDC for realm ..". | ||||
| 
 | ||||
| The krb_name parameter has been added to ipaclient_setup_nss and is also | ||||
| properly set in tasks/install.yml. | ||||
| ---
 | ||||
|  roles/ipaclient/library/ipaclient_setup_nss.py | 8 ++++++++ | ||||
|  roles/ipaclient/tasks/install.yml              | 1 + | ||||
|  2 files changed, 9 insertions(+) | ||||
| 
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_setup_nss.py b/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| index 74ca9d4..0e8c658 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_setup_nss.py
 | ||||
| @@ -152,6 +152,10 @@ options:
 | ||||
|        The dist of nss_ldap or nss-pam-ldapd files if sssd is disabled | ||||
|      required: yes | ||||
|      type: dict | ||||
| +  krb_name:
 | ||||
| +    description: The krb5 config file name
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
|  author: | ||||
|      - Thomas Woerner (@t-woerner) | ||||
|  ''' | ||||
| @@ -167,6 +171,7 @@ EXAMPLES = '''
 | ||||
|      subject_base: O=EXAMPLE.COM | ||||
|      principal: admin | ||||
|      ca_enabled: yes | ||||
| +    krb_name: /tmp/tmpkrb5.conf
 | ||||
|  ''' | ||||
|   | ||||
|  RETURN = ''' | ||||
| @@ -218,6 +223,7 @@ def main():
 | ||||
|              no_krb5_offline_passwords=dict(required=False, type='bool'), | ||||
|              no_dns_sshfp=dict(required=False, type='bool', default=False), | ||||
|              nosssd_files=dict(required=True, type='dict'), | ||||
| +            krb_name=dict(required=True, type='str'),
 | ||||
|          ), | ||||
|          supports_check_mode=False, | ||||
|      ) | ||||
| @@ -268,6 +274,8 @@ def main():
 | ||||
|      options.sssd = not options.no_sssd | ||||
|      options.no_ac = False | ||||
|      nosssd_files = module.params.get('nosssd_files') | ||||
| +    krb_name = module.params.get('krb_name')
 | ||||
| +    os.environ['KRB5_CONFIG'] = krb_name
 | ||||
|   | ||||
|      # pylint: disable=invalid-name | ||||
|      CCACHE_FILE = paths.IPA_DNS_CCACHE | ||||
| diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml
 | ||||
| index 662f09a..1dc6fdf 100644
 | ||||
| --- a/roles/ipaclient/tasks/install.yml
 | ||||
| +++ b/roles/ipaclient/tasks/install.yml
 | ||||
| @@ -382,6 +382,7 @@
 | ||||
|                | default(ipasssd_no_krb5_offline_passwords) }}" | ||||
|          no_dns_sshfp: "{{ ipaclient_no_dns_sshfp }}" | ||||
|          nosssd_files: "{{ result_ipaclient_test.nosssd_files }}" | ||||
| +        krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
|   | ||||
|      - name: Install - Configure SSH and SSHD | ||||
|        ipaclient_setup_ssh: | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
| From 10d072a8c42e6aa91485661d02b31f79bcc89fc0 Mon Sep 17 00:00:00 2001 | ||||
| From: Thomas Woerner <twoerner@redhat.com> | ||||
| Date: Fri, 24 Mar 2023 12:40:32 +0100 | ||||
| Subject: [PATCH] ipaclient: ipaclient_fix_ca also needs krb_name parameter | ||||
| 
 | ||||
| With the fix to defer creating the final krb5.conf on clients a bug has | ||||
| been introduced with ipaclient_fix_ca: The krb_name parameter that | ||||
| points to the temporary krb5 configuration was not added to the module | ||||
| 
 | ||||
| Without this the server affinity is broken for allow_repair and additionally | ||||
| ipaclient_fix_ca could fail if krb5 configuration needs to be repraied | ||||
| and also CA needs to be fixed. | ||||
| 
 | ||||
| The krb_name parameter has been added to ipaclient_fix_ca and is also | ||||
| properly set in tasks/install.yml. | ||||
| ---
 | ||||
|  roles/ipaclient/library/ipaclient_fix_ca.py | 8 ++++++++ | ||||
|  roles/ipaclient/tasks/install.yml           | 1 + | ||||
|  2 files changed, 9 insertions(+) | ||||
| 
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_fix_ca.py b/roles/ipaclient/library/ipaclient_fix_ca.py
 | ||||
| index 238b316..ede8d56 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_fix_ca.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_fix_ca.py
 | ||||
| @@ -54,6 +54,10 @@ options:
 | ||||
|        the host entry will not be changed on the server | ||||
|      type: bool | ||||
|      required: yes | ||||
| +  krb_name:
 | ||||
| +    description: The krb5 config file name
 | ||||
| +    type: str
 | ||||
| +    required: yes
 | ||||
|  author: | ||||
|      - Thomas Woerner (@t-woerner) | ||||
|  ''' | ||||
| @@ -65,6 +69,7 @@ EXAMPLES = '''
 | ||||
|      realm: EXAMPLE.COM | ||||
|      basedn: dc=example,dc=com | ||||
|      allow_repair: yes | ||||
| +    krb_name: /tmp/tmpkrb5.conf
 | ||||
|  ''' | ||||
|   | ||||
|  RETURN = ''' | ||||
| @@ -87,6 +92,7 @@ def main():
 | ||||
|              realm=dict(required=True, type='str'), | ||||
|              basedn=dict(required=True, type='str'), | ||||
|              allow_repair=dict(required=True, type='bool'), | ||||
| +            krb_name=dict(required=True, type='str'),
 | ||||
|          ), | ||||
|      ) | ||||
|   | ||||
| @@ -98,6 +104,8 @@ def main():
 | ||||
|      realm = module.params.get('realm') | ||||
|      basedn = module.params.get('basedn') | ||||
|      allow_repair = module.params.get('allow_repair') | ||||
| +    krb_name = module.params.get('krb_name')
 | ||||
| +    os.environ['KRB5_CONFIG'] = krb_name
 | ||||
|   | ||||
|      env = {'PATH': SECURE_PATH} | ||||
|      fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) | ||||
| diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml
 | ||||
| index 1dc6fdf..7ff2c39 100644
 | ||||
| --- a/roles/ipaclient/tasks/install.yml
 | ||||
| +++ b/roles/ipaclient/tasks/install.yml
 | ||||
| @@ -346,6 +346,7 @@
 | ||||
|          realm: "{{ result_ipaclient_test.realm }}" | ||||
|          basedn: "{{ result_ipaclient_test.basedn }}" | ||||
|          allow_repair: "{{ ipaclient_allow_repair }}" | ||||
| +        krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
 | ||||
|        when: not ipaclient_on_master | bool and | ||||
|              result_ipaclient_test_keytab.krb5_keytab_ok and | ||||
|              not result_ipaclient_test_keytab.ca_crt_exists | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
| @ -0,0 +1,74 @@ | ||||
| From bfeefaf454e3e705e509ed13b2e650ddfd487fa2 Mon Sep 17 00:00:00 2001 | ||||
| From: Thomas Woerner <twoerner@redhat.com> | ||||
| Date: Wed, 8 Feb 2023 13:38:12 +0100 | ||||
| Subject: [PATCH] ipaclient: Fix allow_repair with removed krb5.conf and DNS | ||||
|  lookup | ||||
| 
 | ||||
| The test in ipaclient_test_keytab is at first trying to use an existing | ||||
| krb5.conf to test if the host keytab can be used. With working DNS lookup | ||||
| an absent krb5.conf is not reported as an error as DNS lookup is | ||||
| silently used instead. | ||||
| 
 | ||||
| A temporary krb5.conf is now used in this test that forces to deactivate | ||||
| DNS lookups and also to load /etc/krb5.conf. A missing krb5.conf is now | ||||
| detected properly as the kinit call fails now properly. Thanks to Julien | ||||
| Rische for this proposal. | ||||
| 
 | ||||
| ipaclient_test_keytab is now properly returning the state of usable or | ||||
| not usable krb5.conf in krb5_conf_ok. This fixes the handling of this | ||||
| case later on in the role. | ||||
| ---
 | ||||
|  .../library/ipaclient_test_keytab.py          | 27 +++++++++++++++++-- | ||||
|  1 file changed, 25 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/roles/ipaclient/library/ipaclient_test_keytab.py b/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| index a86b237..3f1c69d 100644
 | ||||
| --- a/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| +++ b/roles/ipaclient/library/ipaclient_test_keytab.py
 | ||||
| @@ -159,11 +159,29 @@ def main():
 | ||||
|      ca_crt_exists = os.path.exists(paths.IPA_CA_CRT) | ||||
|      env = {'PATH': SECURE_PATH, 'KRB5CCNAME': paths.IPA_DNS_CCACHE} | ||||
|   | ||||
| -    # First try: Validate krb5 keytab with system krb5 configuraiton
 | ||||
| +    # First try: Validate with temporary test krb5.conf that forces
 | ||||
| +    # 1) no DNS lookups and
 | ||||
| +    # 2) to load /etc/krb5.conf:
 | ||||
| +    #
 | ||||
| +    # [libdefaults]
 | ||||
| +    # dns_lookup_realm = false
 | ||||
| +    # dns_lookup_kdc = false
 | ||||
| +    # include /etc/krb5.conf
 | ||||
| +    #
 | ||||
|      try: | ||||
| +        (krb_fd, krb_name) = tempfile.mkstemp()
 | ||||
| +        os.close(krb_fd)
 | ||||
| +        content = "\n".join([
 | ||||
| +            "[libdefaults]",
 | ||||
| +            "dns_lookup_realm = false",
 | ||||
| +            "dns_lookup_kdc = false",
 | ||||
| +            "include /etc/krb5.conf"
 | ||||
| +        ])
 | ||||
| +        with open(krb_name, "w") as outf:
 | ||||
| +            outf.write(content)
 | ||||
|          kinit_keytab(host_principal, paths.KRB5_KEYTAB, | ||||
|                       paths.IPA_DNS_CCACHE, | ||||
| -                     config=paths.KRB5_CONF,
 | ||||
| +                     config=krb_name,
 | ||||
|                       attempts=kinit_attempts) | ||||
|          krb5_keytab_ok = True | ||||
|          krb5_conf_ok = True | ||||
| @@ -177,6 +195,11 @@ def main():
 | ||||
|              pass | ||||
|      except GSSError: | ||||
|          pass | ||||
| +    finally:
 | ||||
| +        try:
 | ||||
| +            os.remove(krb_name)
 | ||||
| +        except OSError:
 | ||||
| +            module.fail_json(msg="Could not remove %s" % krb_name)
 | ||||
|   | ||||
|      # Second try: Validate krb5 keytab with temporary krb5 | ||||
|      # configuration | ||||
| -- 
 | ||||
| 2.39.2 | ||||
| 
 | ||||
| @ -7,11 +7,21 @@ | ||||
| 
 | ||||
| Summary: Roles and playbooks to deploy FreeIPA servers, replicas and clients | ||||
| Name: ansible-freeipa | ||||
| Version: 1.12.1 | ||||
| Release: 1%{?dist} | ||||
| Version: 1.9.2 | ||||
| Release: 3%{?dist}.alma | ||||
| URL: https://github.com/freeipa/ansible-freeipa | ||||
| License: GPL-3.0-or-later | ||||
| License: GPLv3+ | ||||
| Source: https://github.com/freeipa/ansible-freeipa/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz | ||||
| Patch1: ansible-freeipa-1.9.2-paclient-Fix-allow_repair-with-removed-krb5.conf-an_RHBZ#2189235.patch | ||||
| Patch2: ansible-freeipa-1.9.2-ipaclient-Defer-creating-the-final-krb5.conf-on-clients_RHBZ#2189238.patch | ||||
| Patch3: ansible-freeipa-1.9.2-ipaclient-Defer-krb5-configuration-fix_RHBZ#2189238.patch | ||||
| 
 | ||||
| # Patches was generated from upstream commits: | ||||
| # https://github.com/freeipa/ansible-freeipa/commit/d04a12e522e4ef9d23673916afb9e57ed032c56e | ||||
| # https://github.com/freeipa/ansible-freeipa/commit/1a7b279d78374598d0330718c81c93048d54dd7c | ||||
| Patch1001: 0001-Fix-typo-in-ipapwpolicy.py.patch | ||||
| Patch1002: 0002-pwpolicy-test-Fix-maxsequence-test.patch | ||||
| 
 | ||||
| BuildArch: noarch | ||||
| 
 | ||||
| %description | ||||
| @ -35,7 +45,6 @@ Features | ||||
| - Modules for automount key management | ||||
| - Modules for automount location management | ||||
| - Modules for automount map management | ||||
| - Modules for certificate management | ||||
| - Modules for config management | ||||
| - Modules for delegation management | ||||
| - Modules for dns config management | ||||
| @ -48,11 +57,7 @@ Features | ||||
| - Modules for hbacsvcgroup management | ||||
| - Modules for host management | ||||
| - Modules for hostgroup management | ||||
| - Modules for idoverridegroup management | ||||
| - Modules for idoverrideuser management | ||||
| - Modules for idp management | ||||
| - Modules for idrange management | ||||
| - Modules for idview management | ||||
| - Modules for location management | ||||
| - Modules for netgroup management | ||||
| - Modules for permission management | ||||
| @ -90,7 +95,7 @@ Supported Distributions | ||||
| Requirements | ||||
| 
 | ||||
|   Controller | ||||
|   - Ansible version: 2.13+ | ||||
|   - Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection) | ||||
| 
 | ||||
|   Node | ||||
|   - Supported FreeIPA version (see above) | ||||
| @ -118,6 +123,12 @@ to get the needed requrements to run the tests. | ||||
| %prep | ||||
| %setup -q | ||||
| # Do not create backup files with patches | ||||
| %patch1 -p1 | ||||
| %patch2 -p1 | ||||
| %patch3 -p1 | ||||
| 
 | ||||
| %patch1001 -p1 | ||||
| %patch1002 -p1 | ||||
| 
 | ||||
| # Fix python modules and module utils: | ||||
| # - Remove shebang | ||||
| @ -125,14 +136,12 @@ to get the needed requrements to run the tests. | ||||
| for i in roles/ipa*/library/*.py roles/ipa*/module_utils/*.py plugins/*/*.py; | ||||
| do | ||||
|     sed -i '1{/\/usr\/bin\/python*/d;}' $i | ||||
|     sed -i '1{/\/usr\/bin\/env python*/d;}' $i | ||||
|     chmod a-x $i | ||||
| done | ||||
| 
 | ||||
| for i in utils/*.py utils/new_module utils/changelog utils/ansible-doc-test; | ||||
| do | ||||
|     sed -i '{s@/usr/bin/python*@%{python}@}' $i | ||||
|     sed -i '{s@/usr/bin/env python*@%{python}@}' $i | ||||
| done | ||||
| 
 | ||||
| 
 | ||||
| @ -183,98 +192,14 @@ cp -rp tests %{buildroot}%{_datadir}/ansible-freeipa/ | ||||
| %{_datadir}/ansible-freeipa/requirements-tests.txt | ||||
| 
 | ||||
| %changelog | ||||
| * Mon Feb 12 2024 Thomas Woerner <twoerner@redhat.com> - 1.12.1-1 | ||||
| - Update to version 1.12.1 | ||||
|   https://github.com/freeipa/ansible-freeipa/releases/tag/v1.12.1 | ||||
|   Resolves: RHEL-13746 | ||||
| - ipauser module lacks the "rename" field. | ||||
|   Resolves: RHEL-4963 | ||||
| - Add missing support for rename in ipagroup module | ||||
|   Resolves: RHEL-13759 | ||||
| - The IDP module does not support the modification of IDP options | ||||
|   Resolves: RHEL-17955 | ||||
| - The IDP module does not support resetting IDP options | ||||
|   Resolves: RHEL-17958 | ||||
| - ipauser is not idempotent when random is defined | ||||
|   Resolves: RHEL-4934 | ||||
| - ipasudorule: Allow setting groups for runasuser | ||||
|   Resolves: RHEL-19129 | ||||
| - Idempotency fixes | ||||
|   Resolves: RHEL-13755 | ||||
| - ipadnszone: Add support for per-zone privilege delegation | ||||
|   Resolves: RHEL-19133 | ||||
| - Handle data type or empty string in module_utils | ||||
|   Resolves: RHEL-19135 | ||||
| - ipa-server installation failing | ||||
|   Resolves: RHEL-23633 | ||||
| * Wed Aug 09 2023 Eduard Abdullin <eabdullin@almalinux.org> - 1.9.2-3.alma | ||||
| - Apply 0001-Fix-typo-in-ipapwpolicy.py.patch and 0002-pwpolicy-test-Fix-maxsequence-test.patch patches | ||||
| 
 | ||||
| * Tue Nov 28 2023 Thomas Woerner <twoerner@redhat.com> - 1.12.0-2 | ||||
| - Fix test_pwpolicy for https://pagure.io/freeipa/issue/9297 | ||||
|   Related: RHEL-13746 | ||||
| 
 | ||||
| * Mon Nov 27 2023 Thomas Woerner <twoerner@redhat.com> - 1.12.0-1 | ||||
| - Update to version 1.12.0 | ||||
|   https://github.com/freeipa/ansible-freeipa/releases/tag/v1.12.0 | ||||
|   Resolves: RHEL-13746 | ||||
| - New idoverridegroup management module. | ||||
|   Resolves: RHEL-16935 | ||||
| - New idoverrideuser management module. | ||||
|   Resolves: RHEL-16941 | ||||
| - New idview management module. | ||||
|   Resolves: RHEL-16933 | ||||
| - New idp management module. | ||||
|   Resolves: RHEL-16938 | ||||
| - idoverride{user,group}: Fix delete_continue with state absent | ||||
|   Resolves: RHEL-16682 | ||||
| 
 | ||||
| * Mon Jul 24 2023 Thomas Woerner <twoerner@redhat.com> - 1.11.1-1 | ||||
| - Update to version 1.11.1 | ||||
|   https://github.com/freeipa/ansible-freeipa/releases/tag/v1.11.1 | ||||
|   Resolves: RHBZ#2170371 | ||||
| - ipaautomountmap: add support for indirect maps | ||||
|   Resolves: RHBZ#2050158 | ||||
| - ipauser: Add support to modify GECOS field | ||||
|   Resolves: RHBZ#2168022 | ||||
| - ipauser: Add support for parameter "street" | ||||
|   Resolves: RHBZ#2215532 | ||||
| - ipauser: Add support for SMB attributes | ||||
|   Resolves: RHBZ#2215534 | ||||
| - ipauser: Support for External IdP attributes | ||||
|   Resolves: RHBZ#2215539 | ||||
| - Fix handling of ipapwpolicy attributes usercheck and dictcheck | ||||
|   Resolves: RHBZ#2215543 | ||||
| - Update authtypes authind | ||||
|   Resolves: RHBZ#2215540 | ||||
| 
 | ||||
| * Mon Jun 12 2023 Thomas Woerner <twoerner@redhat.com> - 1.11.0-1 | ||||
| - Update to version 1.11.0 | ||||
|   https://github.com/freeipa/ansible-freeipa/releases/tag/v1.11.0 | ||||
|   Resolves: RHBZ#2170371 | ||||
| - Multiple service management | ||||
|   Resolves: RHBZ#2175769 | ||||
| - New ipacert module | ||||
|   Resolves: RHBZ#2127906 | ||||
| - Fix maxsequence handling in ipapwpolicy module | ||||
|   Resolves: RHBZ#2214295 | ||||
| 
 | ||||
| * Wed Apr  5 2023 Thomas Woerner <twoerner@redhat.com> - 1.10.0-1 | ||||
| - Update to version 1.10.0 | ||||
|   https://github.com/freeipa/ansible-freeipa/releases/tag/v1.10.0 | ||||
|   Resolves: RHBZ#2170371 | ||||
| - ipareplica/server: Enable removal from domain with undeployment | ||||
|   Resolves: RHBZ#2127901 | ||||
| - ipagroup: Allow multiple group management | ||||
|   Resolves: RHBZ#2175762 | ||||
| - ipaserver: Allow deployments with random serial numbers | ||||
|   Resolves: RHBZ#2127904 | ||||
| - ipagroup: Fix ensuring external group members (without trust-ad) | ||||
|   Resolves: RHBZ#2183820 | ||||
| - ipaclient: Add subid option to select the sssd profile with-subid | ||||
|   Resolves: RHBZ#2175766 | ||||
| * Mon Apr 24 2023 Thomas Woerner <twoerner@redhat.com> - 1.9.2-2 | ||||
| - ipaclient: Fix allow_repair with removed krb5.conf and DNS lookup | ||||
|   Resolves: RHBZ#1759785 | ||||
| - ipaclient: Keep server affinity while deploying as long as possible | ||||
|   Resolves: RHBZ#2175755 | ||||
|   Resolves: RHBZ#2189235 | ||||
| - ipaclient: Defer creating the final krb5.conf on clients | ||||
|   Resolves: RHBZ#2189238 | ||||
| 
 | ||||
| * Tue Jan 31 2023 Thomas Woerner <twoerner@redhat.com> - 1.9.2-1 | ||||
| - Update to version 1.9.2 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user