#!/usr/bin/python # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = r""" module: podman_login author: - "Jason Hiatt (@jthiatt)" - "Clemens Lange (@clelange)" - "Michael Fox (@spmfox)" short_description: Login to a container registry using podman notes: [] description: - Login to a container registry server using the podman login command If the registry is not specified, the first registry under `[registries.search]` from `registries.conf `will be used. The path of the authentication file can be overridden by the user by setting the `authfile` flag. The default path used is `${XDG_RUNTIME_DIR}/containers/auth.json`. requirements: - "Podman installed on host" options: authfile: description: - Path of the authentication file. Default is ``${XDG_RUNTIME_DIR}/containers/auth.json`` You can also override the default path of the authentication file by setting the ``REGISTRY_AUTH_FILE`` environment variable. ``export REGISTRY_AUTH_FILE=path`` type: path certdir: description: - Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. Default certificates directory is /etc/containers/certs.d. type: path password: description: - Password for the registry server. type: str registry: description: - Registry server. If the registry is not specified, the first registry under `[registries.search]` from `registries.conf` will be used. type: str tlsverify: description: - Require HTTPS and verify certificates when contacting registries. If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. type: bool username: description: - Username for the registry server. type: str executable: description: - Path to C(podman) executable if it is not in the C($PATH) on the machine running C(podman) default: 'podman' type: str secret: description: - Name of an existing C(podman) secret to use for authentication to target registry type: str """ EXAMPLES = r""" - name: Login to default registry and create ${XDG_RUNTIME_DIR}/containers/auth.json containers.podman.podman_login: username: user password: 'p4ssw0rd' - name: Login to quay.io and create ${XDG_RUNTIME_DIR}/containers/auth.json containers.podman.podman_login: username: user password: 'p4ssw0rd' registry: quay.io - name: Login to quay.io using existing secret called password containers.podman.podman_login: username: user secret: password registry: quay.io """ # noqa: F402 import hashlib import os from ansible.module_utils.basic import AnsibleModule from ansible_collections.containers.podman.plugins.module_utils.podman.common import ( LooseVersion, ) from ansible_collections.containers.podman.plugins.module_utils.podman.common import ( get_podman_version, ) def login( module, executable, registry, authfile, certdir, tlsverify, username, password, secret, ): command = [executable, "login"] changed = False if username: command.extend(["--username", username]) if password: command.extend(["--password", password]) if secret: command.extend(["--secret", secret]) if authfile: command.extend(["--authfile", authfile]) authfile = os.path.expandvars(authfile) else: authfile = os.getenv("XDG_RUNTIME_DIR", "") + "/containers/auth.json" if registry: command.append(registry) if certdir: command.extend(["--cert-dir", certdir]) if tlsverify is not None: if tlsverify: command.append("--tls-verify") else: command.append("--tls-verify=False") # Use a checksum to check if the auth JSON has changed checksum = None docker_authfile = os.path.expandvars("$HOME/.docker/config.json") # podman falls back to ~/.docker/config.json if the default authfile doesn't exist check_file = authfile if os.path.exists(authfile) else docker_authfile if os.path.exists(check_file): content = open(check_file, "rb").read() checksum = hashlib.sha256(content).hexdigest() rc, out, err = module.run_command(command) if rc != 0: if "Error: Not logged into" not in err: module.fail_json(msg="Unable to gather info for %s: %s" % (registry, err)) else: # If the command is successful, we managed to login changed = True if "Existing credentials are valid" in out: changed = False # If we have managed to calculate a checksum before, check if it has changed # due to the login if checksum: content = open(check_file, "rb").read() new_checksum = hashlib.sha256(content).hexdigest() if new_checksum == checksum: changed = False return changed, out, err def main(): module = AnsibleModule( argument_spec=dict( executable=dict(type="str", default="podman"), registry=dict(type="str"), authfile=dict(type="path"), username=dict(type="str"), password=dict(type="str", no_log=True), certdir=dict(type="path"), tlsverify=dict(type="bool"), secret=dict(type="str", no_log=False), ), supports_check_mode=False, required_by={ "password": "username", }, mutually_exclusive=[ ["password", "secret"], ], ) registry = module.params["registry"] authfile = module.params["authfile"] username = module.params["username"] password = module.params["password"] certdir = module.params["certdir"] tlsverify = module.params["tlsverify"] secret = module.params["secret"] executable = module.get_bin_path(module.params["executable"], required=True) podman_version = get_podman_version(module, fail=False) if ( (podman_version is not None) and (LooseVersion(podman_version) < LooseVersion("4.7.0")) and secret ): module.fail_json(msg="secret option may not be used with podman < 4.7.0") if username and ((not password) and (not secret)): module.fail_json(msg="Must pass either password or secret with username") changed, out, err = login( module, executable, registry, authfile, certdir, tlsverify, username, password, secret, ) results = { "changed": changed, "stdout": out, "stderr": err, } module.exit_json(**results) if __name__ == "__main__": main()