Skip to content

Commit

Permalink
feat: support registry_username and registry_password
Browse files Browse the repository at this point in the history
Feature: Add support for specifying registry password globally or on
a per-spec basis.

Reason: Some registries require authentication for access.

Result: Users can use the podman role to manage containers with
images in registries which require authentication.

QE: There is a new test tests_auth_and_security.yml
The password is "podman_password".  The logs should *not* contain
this string.

Signed-off-by: Rich Megginson <[email protected]>
  • Loading branch information
richm committed Apr 12, 2024
1 parent 3d02eb7 commit e1f1727
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .ostree/packages-testing.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
httpd-tools
skopeo
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,20 @@ a newer version. For example, if you attempt to manage quadlet or secrets with
podman 4.3 or earlier, the role will fail with an error. If you want the role to
be skipped instead, use `podman_fail_if_too_old: false`.

### podman_registry_username

String - default is unset - username to use to authenticate to the registry. You
must also set `podman_registry_password`. You can override this on a per-spec
basis with `registry_username`. The use of `container_image_user` was
unsupported and is deprecated.

### podman_registry_password

String - default is unset - password to use to authenticate to the registry. You
must also set `podman_registry_username`. You can override this on a per-spec
basis with `registry_password`. The use of `container_image_password` was
unsupported and is deprecated.

## Variables Exported by the Role

### podman_version
Expand Down
8 changes: 8 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@ podman_continue_if_pull_fails: false
# If true, if a pull attempt fails, it will be retried according
# to the default Ansible `until` behavior.
podman_pull_retry: false

# username to use to authenticate to the registry
# override by specifying registry_username on a per-spec basis
podman_registry_username: "{{ container_image_user | d('') }}"

# password to use to authenticate to the registry
# override by specifying registry_password on a per-spec basis
podman_registry_password: "{{ container_image_password | d('') }}"
7 changes: 5 additions & 2 deletions tasks/create_update_kube_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
containers.podman.podman_image:
name: "{{ item }}"
force: true
username: "{{ container_image_user | default(omit) }}"
password: "{{ container_image_password | default(omit) }}"
username: "{{ __podman_registry_username
if __podman_registry_username | length > 0 else omit }}"
password: "{{ __podman_registry_password
if __podman_registry_password | length > 0 else omit }}"
register: __podman_image_updated
when: __podman_pull_image | bool
until: __podman_image_updated is success
Expand All @@ -63,6 +65,7 @@
selectattr('image', 'defined') | map(attribute='image') | list
if 'initContainers' in __podman_kube['spec']
else [] }}"
no_log: true

- name: Check the kubernetes yaml file
stat:
Expand Down
7 changes: 5 additions & 2 deletions tasks/create_update_quadlet_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
containers.podman.podman_image:
name: "{{ item }}"
force: true
username: "{{ container_image_user | default(omit) }}"
password: "{{ container_image_password | default(omit) }}"
username: "{{ __podman_registry_username
if __podman_registry_username | length > 0 else omit }}"
password: "{{ __podman_registry_password
if __podman_registry_password | length > 0 else omit }}"
register: __podman_image_updated
when: __podman_pull_image | bool
until: __podman_image_updated is success
Expand All @@ -38,6 +40,7 @@
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
loop: "{{ __podman_images | unique | list }}"
no_log: true

- name: Ensure the quadlet directory is present
file:
Expand Down
14 changes: 13 additions & 1 deletion tasks/handle_kube_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
vars:
__del_params: "^(kube_file_src|kube_file_content|run_as_user|run_as_group|\
systemd_unit_scope|activate_systemd_unit|pull_image|\
continue_if_pull_fails)$"
continue_if_pull_fails|registry_username|registry_password)$"

- name: Set per-container variables part 1
set_fact:
Expand Down Expand Up @@ -105,6 +105,18 @@
if __podman_kube_file
else __podman_kube_path ~ '/' ~ __podman_kube_name ~ '.yml' }}"

- name: Set per-container variables part 6
set_fact:
__podman_registry_username: "{{
__podman_kube_spec_item['registry_username']
if 'registry_username' in __podman_kube_spec_item
else podman_registry_username }}"
__podman_registry_password: "{{
__podman_kube_spec_item['registry_password']
if 'registry_password' in __podman_kube_spec_item
else podman_registry_password }}"
no_log: true

- name: Get service name using systemd-escape
command: >-
systemd-escape --template [email protected]
Expand Down
14 changes: 13 additions & 1 deletion tasks/handle_quadlet_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
vars:
__del_params: "^(file_src|file_content|file|run_as_user|run_as_group|\
systemd_unit_scope|name|type|state|activate_systemd_unit|template_src|\
pull_image|continue_if_pull_fails)$"
pull_image|continue_if_pull_fails|registry_username|registry_password)$"

- name: Set per-container variables part 1
set_fact:
Expand Down Expand Up @@ -202,6 +202,18 @@
if __podman_kube
and podman_create_host_directories else [] }}"

- name: Set per-container variables part 6
set_fact:
__podman_registry_username: "{{
__podman_quadlet_spec_item['registry_username']
if 'registry_username' in __podman_quadlet_spec_item
else podman_registry_username }}"
__podman_registry_password: "{{
__podman_quadlet_spec_item['registry_password']
if 'registry_password' in __podman_quadlet_spec_item
else podman_registry_password }}"
no_log: true

- name: Cleanup quadlets
include_tasks: cleanup_quadlet_spec.yml
when: __podman_state == "absent"
Expand Down
2 changes: 2 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,14 @@
loop: "{{ podman_kube_specs }}"
loop_control:
loop_var: __podman_kube_spec_item
no_log: true

- name: Handle Quadlet specifications
include_tasks: handle_quadlet_spec.yml
loop: "{{ podman_quadlet_specs }}"
loop_control:
loop_var: __podman_quadlet_spec_item
no_log: true

- name: Cancel linger
include_tasks: cancel_linger.yml
Expand Down
11 changes: 11 additions & 0 deletions tests/tasks/cleanup_registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: MIT
---
- name: Destroy registry container
command: podman rm -f podman_registry
changed_when: true

- name: Cleanup paths
file:
path: "{{ item }}"
state: absent
loop: "{{ __podman_cleanup_paths }}"
138 changes: 138 additions & 0 deletions tests/tasks/setup_registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# SPDX-License-Identifier: MIT
# set up a local registry for testing auth and tls
# https://github.com/containers/podman/blob/d65f3996dd263eb875be623d1164ce7e9cbdc3bf/test/system/helpers.registry.bash
---
- name: Create a temporary directory
tempfile:
prefix: lsr_
suffix: _podman
state: directory
register: __podman_registry_tempfile

- name: Set authdir
set_fact:
__podman_registry_authdir: "{{ __podman_registry_tempfile.path ~ '/auth' }}"
__podman_test_authfile: "{{ __podman_registry_tempfile.path ~ '/auth/auth.json' }}"

- name: Create authdir
file:
path: "{{ __podman_registry_authdir }}"
state: directory
mode: "0700"

- name: Generate certificates for registry
include_role:
name: fedora.linux_system_roles.certificate
vars:
certificate_requests:
- name: podman_registry
dns: ["localhost", "127.0.0.1"]
ca: self-sign
certificate_test_mode: true
certificate_test_remove_files: true

- name: Write cert for registry
copy:
content: "{{ certificate_test_certs['podman_registry']['cert_content'] }}"
dest: "{{ __podman_registry_authdir ~ '/registry_cert.crt' }}"
mode: "0600"

- name: Write key for registry
copy:
content: "{{ certificate_test_certs['podman_registry']['key_content'] }}"
dest: "{{ __podman_registry_authdir ~ '/registry_key.pem' }}"
mode: "0600"

- name: Create cert dir for registry
file:
path: /etc/containers/certs.d/localhost:5000
state: directory
mode: "0755"

- name: Write CA cert for registry
copy:
content: "{{ certificate_test_certs['podman_registry']['ca_content'] }}"
dest: /etc/containers/certs.d/localhost:5000/ca.crt
mode: "0644"

- name: Ensure test packages
package:
name: [httpd-tools, skopeo]
state: present

- name: Write user and password
shell: >-
htpasswd -Bbn {{ __podman_test_username | quote }}
{{ __podman_test_password | quote }} >
{{ __podman_registry_authdir ~ '/htpasswd' }}
changed_when: true
no_log: true

- name: Create auth.json file
copy:
content: |
{
"auths": {
"localhost:5000": {
"auth": "{{ __auth }}"
}
}
}
dest: "{{ __podman_test_authfile }}"
mode: "0600"
vars:
__auth: "{{ (__podman_test_username ~ ':' ~ __podman_test_password) |
b64encode }}"
no_log: true

- name: Set paths for cleanup
set_fact:
__podman_cleanup_paths:
- /etc/containers/certs.d/localhost:5000
- "{{ __podman_registry_tempfile.path }}"

# # In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
# echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" > $AUTHDIR/htpasswd-plaintext

- name: Start registry
command: >-
podman run -d -p 127.0.0.1:5000:5000 --name podman_registry
-v {{ __podman_registry_authdir }}:/auth:Z -e REGISTRY_AUTH=htpasswd
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/registry_cert.crt
-e REGISTRY_HTTP_TLS_KEY=/auth/registry_key.pem
quay.io/libpod/registry:2.8.2
changed_when: true

- name: Wait for port
wait_for:
port: 5000

- name: Wait for readiness
command: podman logs podman_registry
changed_when: false
register: __podman_log
until: __podman_log.stderr is search("listening on .*:5000")

- name: Convert test image names into local registry names
set_fact:
podman_local_test_images: "{{ __podman_test_images |
map('regex_replace', '^quay[.]io', 'localhost:5000') | list }}"

- name: Push test images into local registry
shell: >-
podman pull {{ item.key }};
podman push --authfile="{{ __podman_test_authfile }}"
{{ item.key }} docker://{{ item.value }}
loop: "{{
dict(__podman_test_images | zip(podman_local_test_images)) |
dict2items | list }}"
changed_when: true

- name: Verify test images in local registry
command: >-
skopeo inspect --authfile="{{ __podman_test_authfile }}"
docker://{{ item }}
changed_when: false
loop: "{{ podman_local_test_images }}"
Loading

0 comments on commit e1f1727

Please sign in to comment.