diff options
Diffstat (limited to 'roles')
| -rw-r--r-- | roles/docker/defaults/main.yml | 2 | ||||
| -rw-r--r-- | roles/docker/meta/main.yml | 1 | ||||
| -rw-r--r-- | roles/docker/tasks/registry_auth.yml | 16 | ||||
| -rw-r--r-- | roles/docker/tasks/systemcontainer_crio.yml | 6 | ||||
| -rw-r--r-- | roles/docker/tasks/systemcontainer_docker.yml | 8 | ||||
| -rw-r--r-- | roles/lib_utils/library/docker_creds.py | 207 | ||||
| -rw-r--r-- | roles/openshift_master/defaults/main.yml | 1 | ||||
| -rw-r--r-- | roles/openshift_master/tasks/registry_auth.yml | 20 | ||||
| -rw-r--r-- | roles/openshift_node/defaults/main.yml | 1 | ||||
| -rw-r--r-- | roles/openshift_node/tasks/registry_auth.yml | 19 | ||||
| -rw-r--r-- | roles/openshift_node_upgrade/defaults/main.yml | 1 | ||||
| -rw-r--r-- | roles/openshift_node_upgrade/tasks/registry_auth.yml | 19 | 
12 files changed, 299 insertions, 2 deletions
| diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml index c086c28df..224844a06 100644 --- a/roles/docker/defaults/main.yml +++ b/roles/docker/defaults/main.yml @@ -2,6 +2,8 @@  docker_cli_auth_config_path: '/root/.docker'  openshift_docker_signature_verification: False +openshift_docker_alternative_creds: False +  # oreg_url is defined by user input.  oreg_host: "{{ oreg_url.split('/')[0] if (oreg_url is defined and '.' in oreg_url.split('/')[0]) else '' }}"  oreg_auth_credentials_replace: False diff --git a/roles/docker/meta/main.yml b/roles/docker/meta/main.yml index 62b8a2eb5..d5faae8df 100644 --- a/roles/docker/meta/main.yml +++ b/roles/docker/meta/main.yml @@ -12,3 +12,4 @@ galaxy_info:  dependencies:  - role: lib_openshift  - role: lib_os_firewall +- role: lib_utils diff --git a/roles/docker/tasks/registry_auth.yml b/roles/docker/tasks/registry_auth.yml index d05b7f2b8..2c7bc5711 100644 --- a/roles/docker/tasks/registry_auth.yml +++ b/roles/docker/tasks/registry_auth.yml @@ -12,5 +12,21 @@    delay: 5    until: openshift_docker_credentials_create_res.rc == 0    when: +  - not openshift_docker_alternative_creds | bool +  - oreg_auth_user is defined +  - (not docker_cli_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool + +# docker_creds is a custom module from lib_utils +# 'docker login' requires a docker.service running on the local host, this is an +# alternative implementation for non-docker hosts.  This implementation does not +# check the registry to determine whether or not the credentials will work. +- name: Create credentials for docker cli registry auth (alternative) +  docker_creds: +    path: "{{ docker_cli_auth_config_path }}" +    registry: "{{ oreg_host }}" +    username: "{{ oreg_auth_user }}" +    password: "{{ oreg_auth_password }}" +  when: +  - openshift_docker_alternative_creds | bool    - oreg_auth_user is defined    - (not docker_cli_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool diff --git a/roles/docker/tasks/systemcontainer_crio.yml b/roles/docker/tasks/systemcontainer_crio.yml index 1e2d64293..3fe10454d 100644 --- a/roles/docker/tasks/systemcontainer_crio.yml +++ b/roles/docker/tasks/systemcontainer_crio.yml @@ -179,3 +179,9 @@    register: start_result  - meta: flush_handlers + +# If we are using crio only, docker.service might not be available for +# 'docker login' +- include: registry_auth.yml +  vars: +    openshift_docker_alternative_creds: "{{ l_use_crio_only }}" diff --git a/roles/docker/tasks/systemcontainer_docker.yml b/roles/docker/tasks/systemcontainer_docker.yml index aa3b35ddd..84220fa66 100644 --- a/roles/docker/tasks/systemcontainer_docker.yml +++ b/roles/docker/tasks/systemcontainer_docker.yml @@ -173,6 +173,10 @@  - set_fact:      docker_service_status_changed: "{{ r_docker_systemcontainer_docker_start_result | changed }}" -- include: registry_auth.yml -  - meta: flush_handlers + +# Since docker is running as a system container, docker login will fail to create +# credentials.  Use alternate method if requiring authenticated registries. +- include: registry_auth.yml +  vars: +    openshift_docker_alternative_creds: True diff --git a/roles/lib_utils/library/docker_creds.py b/roles/lib_utils/library/docker_creds.py new file mode 100644 index 000000000..d4674845e --- /dev/null +++ b/roles/lib_utils/library/docker_creds.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# pylint: disable=missing-docstring +# +# Copyright 2017 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +#    http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base64 +import json +import os + +from ansible.module_utils.basic import AnsibleModule + + +DOCUMENTATION = ''' +--- +module: docker_creds + +short_description: Creates/updates a 'docker login' file in place of using 'docker login' + +version_added: "2.4" + +description: +    - This module creates a docker config.json file in the directory provided by 'path' +      on hosts that do not support 'docker login' but need the file present for +      registry authentication purposes of various other services. + +options: +    path: +        description: +            - This is the message to send to the sample module +        required: true +    registry: +        description: +            - This is the registry the credentials are for. +        required: true +    username: +        description: +            - This is the username to authenticate to the registry with. +        required: true +    password: +        description: +            - This is the password to authenticate to the registry with. +        required: true + +author: +    - "Michael Gugino <mgugino@redhat.com>" +''' + +EXAMPLES = ''' +# Pass in a message +- name: Place credentials in file +  docker_creds: +    path: /root/.docker +    registry: registry.example.com:443 +    username: myuser +    password: mypassword +''' + + +def check_dest_dir_exists(module, dest): +    '''Check if dest dir is present and is a directory''' +    dir_exists = os.path.exists(dest) +    if dir_exists: +        if not os.path.isdir(dest): +            msg = "{} exists but is not a directory".format(dest) +            result = {'failed': True, +                      'changed': False, +                      'msg': msg, +                      'state': 'unknown'} +            module.fail_json(**result) +        else: +            return 1 +    else: +        return 0 + + +def create_dest_dir(module, dest): +    try: +        os.makedirs(dest, mode=0o700) +    except OSError as oserror: +        result = {'failed': True, +                  'changed': False, +                  'msg': str(oserror), +                  'state': 'unknown'} +        module.fail_json(**result) + + +def load_config_file(module, dest): +    '''load the config.json in directory dest''' +    conf_file_path = os.path.join(dest, 'config.json') +    if os.path.exists(conf_file_path): +        # Try to open the file and load json data +        try: +            with open(conf_file_path) as conf_file: +                data = conf_file.read() +            jdata = json.loads(data) + +        except IOError as ioerror: +            result = {'failed': True, +                      'changed': False, +                      'msg': str(ioerror), +                      'state': 'unknown'} +            module.fail_json(**result) +        except ValueError as jsonerror: +            result = {'failed': True, +                      'changed': False, +                      'msg': str(jsonerror), +                      'state': 'unknown'} +            module.fail_json(**result) +        return jdata +    else: +        # File doesn't exist, we just return an empty dictionary. +        return {} + + +def update_config(docker_config, registry, username, password): +    '''Add our registry auth credentials into docker_config dict''' + +    # Add anything that might be missing in our dictionary +    if 'auths' not in docker_config: +        docker_config['auths'] = {} +    if registry not in docker_config['auths']: +        docker_config['auths'][registry] = {} + +    # base64 encode our username:password string +    encoded_data = base64.b64encode('{}:{}'.format(username, password)) + +    # check if the same value is already present for idempotency. +    if 'auth' in docker_config['auths'][registry]: +        if docker_config['auths'][registry]['auth'] == encoded_data: +            # No need to go further, everything is already set in file. +            return False +    docker_config['auths'][registry]['auth'] = encoded_data +    return True + + +def write_config(module, docker_config, dest): +    '''Write updated credentials into dest/config.json''' +    conf_file_path = os.path.join(dest, 'config.json') +    try: +        with open(conf_file_path, 'w') as conf_file: +            json.dump(docker_config, conf_file, indent=8) +    except IOError as ioerror: +        result = {'failed': True, +                  'changed': False, +                  'msg': str(ioerror), +                  'state': 'unknown'} +        module.fail_json(**result) + + +def run_module(): +    '''Run this module''' +    module_args = dict( +        path=dict(aliases=['dest', 'name'], required=True, type='path'), +        registry=dict(type='str', required=True), +        username=dict(type='str', required=True), +        password=dict(type='str', required=True, no_log=True) +    ) + +    module = AnsibleModule( +        argument_spec=module_args, +        supports_check_mode=False +    ) + +    # First, create our dest dir if necessary +    dest = module.params['path'] +    registry = module.params['registry'] +    username = module.params['username'] +    password = module.params['password'] + +    if not check_dest_dir_exists(module, dest): +        create_dest_dir(module, dest) +        docker_config = {} +    else: +        # We want to scrape the contents of dest/config.json +        # in case there are other registries/settings already present. +        docker_config = load_config_file(module, dest) + +    # Put the registry auth info into the config dict. +    changed = update_config(docker_config, registry, username, password) + +    if changed: +        write_config(module, docker_config, dest) + +    result = {'changed': changed} + +    module.exit_json(**result) + + +def main(): +    run_module() + + +if __name__ == '__main__': +    main() diff --git a/roles/openshift_master/defaults/main.yml b/roles/openshift_master/defaults/main.yml index a27fbae7e..97a8735ee 100644 --- a/roles/openshift_master/defaults/main.yml +++ b/roles/openshift_master/defaults/main.yml @@ -31,6 +31,7 @@ oreg_host: "{{ oreg_url.split('/')[0] if (oreg_url is defined and '.' in oreg_ur  oreg_auth_credentials_path: "{{ r_openshift_master_data_dir }}/.docker"  oreg_auth_credentials_replace: False  l_bind_docker_reg_auth: False +openshift_docker_alternative_creds: "{{ (openshift_docker_use_system_container | default(False)) or (openshift_use_crio_only | default(False)) }}"  containerized_svc_dir: "/usr/lib/systemd/system"  ha_svc_template_path: "native-cluster" diff --git a/roles/openshift_master/tasks/registry_auth.yml b/roles/openshift_master/tasks/registry_auth.yml index cde01c49e..c95f562d0 100644 --- a/roles/openshift_master/tasks/registry_auth.yml +++ b/roles/openshift_master/tasks/registry_auth.yml @@ -8,6 +8,7 @@  - name: Create credentials for registry auth    command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"    when: +  - not (openshift_docker_alternative_creds | default(False))    - oreg_auth_user is defined    - (not master_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool    register: master_oreg_auth_credentials_create @@ -18,6 +19,25 @@    - restart master api    - restart master controllers +# docker_creds is a custom module from lib_utils +# 'docker login' requires a docker.service running on the local host, this is an +# alternative implementation for non-docker hosts.  This implementation does not +# check the registry to determine whether or not the credentials will work. +- name: Create credentials for registry auth (alternative) +  docker_creds: +    path: "{{ oreg_auth_credentials_path }}" +    registry: "{{ oreg_host }}" +    username: "{{ oreg_auth_user }}" +    password: "{{ oreg_auth_password }}" +  when: +  - openshift_docker_alternative_creds | default(False) | bool +  - oreg_auth_user is defined +  - (not docker_cli_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool +  register: master_oreg_auth_credentials_create +  notify: +  - restart master api +  - restart master controllers +  # Container images may need the registry credentials  - name: Setup ro mount of /root/.docker for containerized hosts    set_fact: diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml index 0c6d8db38..95d2cdf14 100644 --- a/roles/openshift_node/defaults/main.yml +++ b/roles/openshift_node/defaults/main.yml @@ -85,6 +85,7 @@ oreg_host: "{{ oreg_url.split('/')[0] if (oreg_url is defined and '.' in oreg_ur  oreg_auth_credentials_path: "{{ openshift_node_data_dir }}/.docker"  oreg_auth_credentials_replace: False  l_bind_docker_reg_auth: False +openshift_docker_alternative_creds: "{{ (openshift_docker_use_system_container | default(False)) or (openshift_use_crio_only | default(False)) }}"  # NOTE  # r_openshift_node_*_default may be defined external to this role. diff --git a/roles/openshift_node/tasks/registry_auth.yml b/roles/openshift_node/tasks/registry_auth.yml index 5e5e4f94a..f5428867a 100644 --- a/roles/openshift_node/tasks/registry_auth.yml +++ b/roles/openshift_node/tasks/registry_auth.yml @@ -8,6 +8,7 @@  - name: Create credentials for registry auth    command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"    when: +    - not (openshift_docker_alternative_creds | default(False))      - oreg_auth_user is defined      - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool    register: node_oreg_auth_credentials_create @@ -17,6 +18,24 @@    notify:      - restart node +# docker_creds is a custom module from lib_utils +# 'docker login' requires a docker.service running on the local host, this is an +# alternative implementation for non-docker hosts.  This implementation does not +# check the registry to determine whether or not the credentials will work. +- name: Create credentials for registry auth (alternative) +  docker_creds: +    path: "{{ oreg_auth_credentials_path }}" +    registry: "{{ oreg_host }}" +    username: "{{ oreg_auth_user }}" +    password: "{{ oreg_auth_password }}" +  when: +    - openshift_docker_alternative_creds | bool +    - oreg_auth_user is defined +    - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool +  register: node_oreg_auth_credentials_create +  notify: +    - restart node +  # Container images may need the registry credentials  - name: Setup ro mount of /root/.docker for containerized hosts    set_fact: diff --git a/roles/openshift_node_upgrade/defaults/main.yml b/roles/openshift_node_upgrade/defaults/main.yml index 10b4c6977..1da434e6f 100644 --- a/roles/openshift_node_upgrade/defaults/main.yml +++ b/roles/openshift_node_upgrade/defaults/main.yml @@ -12,3 +12,4 @@ oreg_host: "{{ oreg_url.split('/')[0] if (oreg_url is defined and '.' in oreg_ur  oreg_auth_credentials_path: "{{ openshift_node_data_dir }}/.docker"  oreg_auth_credentials_replace: False  l_bind_docker_reg_auth: False +openshift_docker_alternative_creds: "{{ (openshift_docker_use_system_container | default(False)) or (openshift_use_crio_only | default(False)) }}" diff --git a/roles/openshift_node_upgrade/tasks/registry_auth.yml b/roles/openshift_node_upgrade/tasks/registry_auth.yml index 5e5e4f94a..f5428867a 100644 --- a/roles/openshift_node_upgrade/tasks/registry_auth.yml +++ b/roles/openshift_node_upgrade/tasks/registry_auth.yml @@ -8,6 +8,7 @@  - name: Create credentials for registry auth    command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"    when: +    - not (openshift_docker_alternative_creds | default(False))      - oreg_auth_user is defined      - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool    register: node_oreg_auth_credentials_create @@ -17,6 +18,24 @@    notify:      - restart node +# docker_creds is a custom module from lib_utils +# 'docker login' requires a docker.service running on the local host, this is an +# alternative implementation for non-docker hosts.  This implementation does not +# check the registry to determine whether or not the credentials will work. +- name: Create credentials for registry auth (alternative) +  docker_creds: +    path: "{{ oreg_auth_credentials_path }}" +    registry: "{{ oreg_host }}" +    username: "{{ oreg_auth_user }}" +    password: "{{ oreg_auth_password }}" +  when: +    - openshift_docker_alternative_creds | bool +    - oreg_auth_user is defined +    - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool +  register: node_oreg_auth_credentials_create +  notify: +    - restart node +  # Container images may need the registry credentials  - name: Setup ro mount of /root/.docker for containerized hosts    set_fact: | 
