diff --git a/test/integration/targets/subversion/aliases b/test/integration/targets/subversion/aliases index 9f1e971c1f0..03b9643497c 100644 --- a/test/integration/targets/subversion/aliases +++ b/test/integration/targets/subversion/aliases @@ -1,4 +1,3 @@ -setup/always/setup_passlib shippable/posix/group2 skip/macos destructive diff --git a/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml b/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml index 9be43b4c256..f86cf59b669 100644 --- a/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml +++ b/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml @@ -1,8 +1,18 @@ --- -- name: stop apache after tests - shell: "kill -9 $(cat '{{ subversion_server_dir }}/apache.pid')" +- name: stop apache after tests - non Red Hat + shell: apachectl -k stop -f {{ subversion_server_dir }}/subversion.conf + when: ansible_os_family not in ['RedHat'] + +- name: stop apache after tests - Red Hat + shell: "kill $(cat '{{ subversion_server_dir }}/apache.pid')" + when: ansible_os_family in ['RedHat'] - name: remove tmp subversion server dir file: path: '{{ subversion_server_dir }}' state: absent + +- name: remove tmp subversion checkout dir + file: + path: '{{ subversion_test_dir }}' + state: absent diff --git a/test/integration/targets/subversion/roles/subversion/tasks/setup.yml b/test/integration/targets/subversion/roles/subversion/tasks/setup.yml index 3cf5af56ee4..61ddeef79be 100644 --- a/test/integration/targets/subversion/roles/subversion/tasks/setup.yml +++ b/test/integration/targets/subversion/roles/subversion/tasks/setup.yml @@ -45,11 +45,7 @@ creates: '{{ subversion_server_dir }}/{{ subversion_repo_name }}' - name: add test user to htpasswd for Subversion site - htpasswd: - path: '{{ subversion_server_dir }}/svn-auth-users' - name: '{{ subversion_username }}' - password: '{{ subversion_password }}' - state: present + command: htpasswd -bc {{ subversion_server_dir + '/svn-auth-users' | quote }} {{ subversion_username | quote }} {{ subversion_password | quote }} - name: apply ownership for all SVN directories file: @@ -62,11 +58,11 @@ command: apachectl -k start -f {{ subversion_server_dir }}/subversion.conf async: 3600 # We kill apache manually in the clean up phase poll: 0 - when: ansible_os_family not in ['RedHat', 'Alpine'] + when: ansible_os_family not in ['RedHat'] # On Red Hat based OS', we can't use apachectl to start up own instance, just use the raw httpd - name: start test Apache SVN site - Red Hat command: httpd -k start -f {{ subversion_server_dir }}/subversion.conf async: 3600 # We kill apache manually in the clean up phase poll: 0 - when: ansible_os_family in ['RedHat', 'Alpine'] + when: ansible_os_family in ['RedHat'] diff --git a/test/integration/targets/subversion/vars/Alpine.yml b/test/integration/targets/subversion/vars/Alpine.yml index ce071fdd1c5..e224c13c495 100644 --- a/test/integration/targets/subversion/vars/Alpine.yml +++ b/test/integration/targets/subversion/vars/Alpine.yml @@ -3,5 +3,7 @@ subversion_packages: - subversion - mod_dav_svn - apache2-webdav +- apache2-utils +- apache2-ctl apache_user: apache apache_group: apache diff --git a/test/support/integration/plugins/modules/htpasswd.py b/test/support/integration/plugins/modules/htpasswd.py deleted file mode 100644 index 98088d9690c..00000000000 --- a/test/support/integration/plugins/modules/htpasswd.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2013, Nimbis Services, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import annotations - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = """ -module: htpasswd -version_added: "1.3" -short_description: manage user files for basic authentication -description: - - Add and remove username/password entries in a password file using htpasswd. - - This is used by web servers such as Apache and Nginx for basic authentication. -options: - path: - required: true - aliases: [ dest, destfile ] - description: - - Path to the file that contains the usernames and passwords - name: - required: true - aliases: [ username ] - description: - - User name to add or remove - password: - required: false - description: - - Password associated with user. - - Must be specified if user does not exist yet. - crypt_scheme: - required: false - choices: ["apr_md5_crypt", "des_crypt", "ldap_sha1", "plaintext"] - default: "apr_md5_crypt" - description: - - Encryption scheme to be used. As well as the four choices listed - here, you can also use any other hash supported by passlib, such as - md5_crypt and sha256_crypt, which are linux passwd hashes. If you - do so the password file will not be compatible with Apache or Nginx - state: - required: false - choices: [ present, absent ] - default: "present" - description: - - Whether the user entry should be present or not - create: - required: false - type: bool - default: "yes" - description: - - Used with C(state=present). If specified, the file will be created - if it does not already exist. If set to "no", will fail if the - file does not exist -notes: - - "This module depends on the I(passlib) Python library, which needs to be installed on all target systems." - - "On Debian, Ubuntu, or Fedora: install I(python-passlib)." - - "On RHEL or CentOS: Enable EPEL, then install I(python-passlib)." -requirements: [ passlib>=1.6 ] -author: "Ansible Core Team" -extends_documentation_fragment: files -""" - -EXAMPLES = """ -# Add a user to a password file and ensure permissions are set -- htpasswd: - path: /etc/nginx/passwdfile - name: janedoe - password: '9s36?;fyNp' - owner: root - group: www-data - mode: 0640 - -# Remove a user from a password file -- htpasswd: - path: /etc/apache2/passwdfile - name: foobar - state: absent - -# Add a user to a password file suitable for use by libpam-pwdfile -- htpasswd: - path: /etc/mail/passwords - name: alex - password: oedu2eGh - crypt_scheme: md5_crypt -""" - - -import os -import tempfile -import traceback -from ansible.module_utils.compat.version import LooseVersion -from ansible.module_utils.basic import AnsibleModule, missing_required_lib -from ansible.module_utils.common.text.converters import to_native - -PASSLIB_IMP_ERR = None -try: - from passlib.apache import HtpasswdFile, htpasswd_context - from passlib.context import CryptContext - import passlib -except ImportError: - PASSLIB_IMP_ERR = traceback.format_exc() - passlib_installed = False -else: - passlib_installed = True - -apache_hashes = ["apr_md5_crypt", "des_crypt", "ldap_sha1", "plaintext"] - - -def create_missing_directories(dest): - destpath = os.path.dirname(dest) - if not os.path.exists(destpath): - os.makedirs(destpath) - - -def present(dest, username, password, crypt_scheme, create, check_mode): - """ Ensures user is present - - Returns (msg, changed) """ - if crypt_scheme in apache_hashes: - context = htpasswd_context - else: - context = CryptContext(schemes=[crypt_scheme] + apache_hashes) - if not os.path.exists(dest): - if not create: - raise ValueError('Destination %s does not exist' % dest) - if check_mode: - return ("Create %s" % dest, True) - create_missing_directories(dest) - if LooseVersion(passlib.__version__) >= LooseVersion('1.6'): - ht = HtpasswdFile(dest, new=True, default_scheme=crypt_scheme, context=context) - else: - ht = HtpasswdFile(dest, autoload=False, default=crypt_scheme, context=context) - if getattr(ht, 'set_password', None): - ht.set_password(username, password) - else: - ht.update(username, password) - ht.save() - return ("Created %s and added %s" % (dest, username), True) - else: - if LooseVersion(passlib.__version__) >= LooseVersion('1.6'): - ht = HtpasswdFile(dest, new=False, default_scheme=crypt_scheme, context=context) - else: - ht = HtpasswdFile(dest, default=crypt_scheme, context=context) - - found = None - if getattr(ht, 'check_password', None): - found = ht.check_password(username, password) - else: - found = ht.verify(username, password) - - if found: - return ("%s already present" % username, False) - else: - if not check_mode: - if getattr(ht, 'set_password', None): - ht.set_password(username, password) - else: - ht.update(username, password) - ht.save() - return ("Add/update %s" % username, True) - - -def absent(dest, username, check_mode): - """ Ensures user is absent - - Returns (msg, changed) """ - if LooseVersion(passlib.__version__) >= LooseVersion('1.6'): - ht = HtpasswdFile(dest, new=False) - else: - ht = HtpasswdFile(dest) - - if username not in ht.users(): - return ("%s not present" % username, False) - else: - if not check_mode: - ht.delete(username) - ht.save() - return ("Remove %s" % username, True) - - -def check_file_attrs(module, changed, message): - - file_args = module.load_file_common_arguments(module.params) - if module.set_fs_attributes_if_different(file_args, False): - - if changed: - message += " and " - changed = True - message += "ownership, perms or SE linux context changed" - - return message, changed - - -def main(): - arg_spec = dict( - path=dict(required=True, aliases=["dest", "destfile"]), - name=dict(required=True, aliases=["username"]), - password=dict(required=False, default=None, no_log=True), - crypt_scheme=dict(required=False, default="apr_md5_crypt"), - state=dict(required=False, default="present"), - create=dict(type='bool', default='yes'), - - ) - module = AnsibleModule(argument_spec=arg_spec, - add_file_common_args=True, - supports_check_mode=True) - - path = module.params['path'] - username = module.params['name'] - password = module.params['password'] - crypt_scheme = module.params['crypt_scheme'] - state = module.params['state'] - create = module.params['create'] - check_mode = module.check_mode - - if not passlib_installed: - module.fail_json(msg=missing_required_lib("passlib"), exception=PASSLIB_IMP_ERR) - - # Check file for blank lines in effort to avoid "need more than 1 value to unpack" error. - try: - f = open(path, "r") - except IOError: - # No preexisting file to remove blank lines from - f = None - else: - try: - lines = f.readlines() - finally: - f.close() - - # If the file gets edited, it returns true, so only edit the file if it has blank lines - strip = False - for line in lines: - if not line.strip(): - strip = True - break - - if strip: - # If check mode, create a temporary file - if check_mode: - temp = tempfile.NamedTemporaryFile() - path = temp.name - f = open(path, "w") - try: - [f.write(line) for line in lines if line.strip()] - finally: - f.close() - - try: - if state == 'present': - (msg, changed) = present(path, username, password, crypt_scheme, create, check_mode) - elif state == 'absent': - if not os.path.exists(path): - module.exit_json(msg="%s not present" % username, - warnings="%s does not exist" % path, changed=False) - (msg, changed) = absent(path, username, check_mode) - else: - module.fail_json(msg="Invalid state: %s" % state) - - check_file_attrs(module, changed, msg) - module.exit_json(msg=msg, changed=changed) - except Exception as e: - module.fail_json(msg=to_native(e)) - - -if __name__ == '__main__': - main()