diff --git a/plugins/modules/podman_login.py b/plugins/modules/podman_login.py index 25bdb8d9..963e17f2 100644 --- a/plugins/modules/podman_login.py +++ b/plugins/modules/podman_login.py @@ -39,7 +39,6 @@ password: description: - Password for the registry server. - required: True type: str registry: description: @@ -59,7 +58,6 @@ username: description: - Username for the registry server. - required: True type: str executable: description: @@ -67,6 +65,11 @@ 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""" @@ -81,16 +84,24 @@ 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): + certdir, tlsverify, username, password, secret): command = [executable, 'login'] changed = False @@ -99,6 +110,8 @@ def login(module, executable, registry, authfile, 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) @@ -146,15 +159,19 @@ def main(): executable=dict(type='str', default='podman'), registry=dict(type='str'), authfile=dict(type='path'), - username=dict(type='str', required=True), - password=dict(type='str', required=True, no_log=True), + 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=True, - required_together=( - ['username', 'password'], - ) + required_by={ + 'password': 'username', + }, + mutually_exclusive=[ + ['password', 'secret'], + ], ) registry = module.params['registry'] @@ -163,10 +180,23 @@ def main(): 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) + certdir, tlsverify, username, password, secret) results = { "changed": changed, diff --git a/tests/integration/targets/podman_login/tasks/main.yml b/tests/integration/targets/podman_login/tasks/main.yml index 37c13a6e..4f77cc25 100644 --- a/tests/integration/targets/podman_login/tasks/main.yml +++ b/tests/integration/targets/podman_login/tasks/main.yml @@ -1,8 +1,19 @@ - name: Test podman_login block: + - name: Discover podman version + shell: podman version | grep "^Version:" | awk {'print $2'} + register: podman_v + + - name: Set podman version fact + set_fact: + podman_version: "{{ podman_v.stdout | string }}" + + - name: Set podman version fact to gt than 4.7.0 if so + set_fact: + podman_version_gt470: "{{ podman_version is version('4.7.0', '>=') }}" - name: Print podman version - command: podman version + debug: var=podman_v.stdout - name: Logout from docker if it exists command: docker logout @@ -35,6 +46,19 @@ that: - loginf is failed + - name: Ensure we catch exception from not specifying password or secret + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + username: foo + registry: docker.io + register: loginf2 + ignore_errors: true + + - name: Check login from just username + assert: + that: + - loginf2 is failed + - name: Login to registry.fedoraproject.org containers.podman.podman_login: executable: "{{ test_executable | default('podman') }}" @@ -48,3 +72,65 @@ assert: that: - login is not failed + + - name: Create a secret to login with + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: foo + data: bar + when: podman_version_gt470 + + - name: Login using secret foo + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + username: foo + secret: foo + registry: registry.fedoraproject.org + when: podman_version_gt470 + register: loginsecret + ignore_errors: true + + - name: Check login with secret + assert: + that: + - loginsecret is not failed + when: podman_version_gt470 + + - name: Login just using secret foo - implies username foo + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + secret: foo + registry: registry.fedoraproject.org + when: podman_version_gt470 + register: loginsecret2 + ignore_errors: true + + - name: Check login with just secret + assert: + that: + - loginsecret2 is not failed + when: podman_version_gt470 + + - name: Login just using both secret and passsword - should fail + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + username: foo + secret: foo + password: bar + registry: registry.fedoraproject.org + when: podman_version_gt470 + register: loginsecret3 + ignore_errors: true + + - name: Ensure failure specifying both secret and password + assert: + that: + - loginsecret3 is failed + when: podman_version_gt470 + + - name: Remove the foo secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: foo + state: absent + when: podman_version_gt470