From bcadcbdf2e718a154720baad8a741078fda40636 Mon Sep 17 00:00:00 2001 From: Bas Meijer Date: Thu, 30 Nov 2023 15:33:07 +0100 Subject: [PATCH] Example of API use for configuration. --- .../artifactory_config/defaults/main.yml | 31 ++++ .../artifactory_config/handlers/main.yml | 8 + .../roles/artifactory_config/tasks/main.yml | 154 ++++++++++++++++++ .../roles/artifactory_config/tasks/verify.yml | 115 +++++++++++++ .../artifactory.config.import.yml.j2 | 79 +++++++++ .../templates/permissions.json.j2 | 13 ++ .../templates/remote_repos.yml.j2 | 17 ++ .../templates/repo_user.json.j2 | 14 ++ 8 files changed, 431 insertions(+) create mode 100644 Ansible/examples/roles/artifactory_config/defaults/main.yml create mode 100644 Ansible/examples/roles/artifactory_config/handlers/main.yml create mode 100644 Ansible/examples/roles/artifactory_config/tasks/main.yml create mode 100644 Ansible/examples/roles/artifactory_config/tasks/verify.yml create mode 100644 Ansible/examples/roles/artifactory_config/templates/artifactory.config.import.yml.j2 create mode 100644 Ansible/examples/roles/artifactory_config/templates/permissions.json.j2 create mode 100644 Ansible/examples/roles/artifactory_config/templates/remote_repos.yml.j2 create mode 100644 Ansible/examples/roles/artifactory_config/templates/repo_user.json.j2 diff --git a/Ansible/examples/roles/artifactory_config/defaults/main.yml b/Ansible/examples/roles/artifactory_config/defaults/main.yml new file mode 100644 index 00000000..73776c8d --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/defaults/main.yml @@ -0,0 +1,31 @@ +--- +# Run checks +verify_state: true +# Proxy +artifactory_proxy_host: '' +artifactory_proxy_port: '' +# admin account for API use +artifactory_admin_username: admin +artifactory_admin_password: password + +repo_users: + - username: rpm + password: 'Changeit1+' + - username: maven + password: 'Changeit2-' +artifactory_delete_anonymous: false + +# For 'remote_repos.yml.j2' template +repo_upstream: + - key: nginx + url: https://nginx.org/packages/rhel/ + type: rpm + - key: postgresql + url: https://download.postgresql.org/pub/repos/yum/ + type: rpm + - key: docker-ce-stable + url: https://download.docker.com/linux/centos/8/x86_64/stable/ + type: rpm + - key: kubernetes + url: https://packages.cloud.google.com/yum/ + type: rpm diff --git a/Ansible/examples/roles/artifactory_config/handlers/main.yml b/Ansible/examples/roles/artifactory_config/handlers/main.yml new file mode 100644 index 00000000..80921fe3 --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/handlers/main.yml @@ -0,0 +1,8 @@ +--- + +- name: Restart Artifactory + ansible.builtin.systemd: + name: artifactory + state: restarted + daemon_reload: true + diff --git a/Ansible/examples/roles/artifactory_config/tasks/main.yml b/Ansible/examples/roles/artifactory_config/tasks/main.yml new file mode 100644 index 00000000..db729a1d --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/tasks/main.yml @@ -0,0 +1,154 @@ +--- + +- name: Artifactory Bootstrap YAML File + tags: + - config + ansible.builtin.template: + src: artifactory.config.import.yml.j2 + dest: /opt/jfrog/artifactory/var/etc/artifactory/artifactory.config.import.yml + mode: '0644' + notify: Restart Artifactory + +- name: Allow token creation + tags: + - access + ansible.builtin.blockinfile: + path: /opt/jfrog/artifactory/var/etc/access/access.config.latest.yml + block: | + token: + default-expiry: 31536000 + allow-basic-auth: true + insertbefore: 'federation:' + owner: artifactory + group: artifactory + mode: '640' + register: access_config + +- name: Enable access config change + tags: + - access + when: access_config.changed | bool # noqa no-handler + ansible.builtin.command: | + mv /opt/jfrog/artifactory/var/etc/access/access.config.latest.yml \ + /opt/jfrog/artifactory/var/etc/access/access.config.import.yml + changed_when: true + notify: Restart Artifactory + +- name: Restart artifactory + tags: + - config + - access + ansible.builtin.meta: flush_handlers + +- name: Make sure artifactory is up and running + tags: + - config + - access + - users + - token + - repos + ansible.builtin.uri: + url: http://127.0.0.1:8082/router/api/v1/system/health + timeout: 130 + status_code: 200 + register: result + until: result is succeeded + retries: 25 + delay: 5 + when: + - not ansible_check_mode + +- name: Configure remote repositories + tags: + - repos + ansible.builtin.uri: + body: "{{ lookup('ansible.builtin.template', 'remote_repos.yml.j2') }}" + force_basic_auth: true + headers: + Content-Type: application/yaml + method: PATCH + url: http://127.0.0.1:8081/artifactory/api/system/configuration + url_username: "{{ artifactory_admin_username }}" + url_password: "{{ artifactory_admin_password }}" + +- name: Create access token + tags: + - token + - users + - permissions + ansible.builtin.uri: + body: "scope=applied-permissions/admin&expires_in=3600" + body_format: form-urlencoded + force_basic_auth: true + method: POST + status_code: + - 200 + url: http://localhost:8082/access/api/v1/tokens + url_username: "{{ artifactory_admin_username }}" + url_password: "{{ artifactory_admin_password }}" + register: token_request + no_log: true + +- name: Set access_token + tags: + - token + - users + - permissions + ansible.builtin.set_fact: + access_token: "{{ token_request.json.access_token }}" + no_log: true + +- name: Create users + tags: + - users + ansible.builtin.uri: + body: "{{ lookup('template', 'repo_user.json.j2') }}" + body_format: json + headers: + Authorization: Bearer {{ access_token }} + Content-Type: application/json + method: POST + status_code: + - 201 + - 409 + url: http://localhost:8082/access/api/v2/users + with_items: + - "{{ repo_users }}" + no_log: false + +- name: Delete anonymous permission + when: artifactory_delete_anonymous | bool + tags: + - permissions + ansible.builtin.uri: + headers: + Authorization: Bearer {{ access_token }} + Content-Type: application/json + method: DELETE + status_code: + - 200 + - 404 + url: "http://127.0.0.1:8082/artifactory/api/v2/security/permissions/{{ item }}" + loop: + - Anything + - Any+Remote + +- name: Configure permission + tags: + - permissions + ansible.builtin.uri: + body: "{{ lookup('ansible.builtin.template', 'permissions.json.j2') }}" + body_format: json + headers: + Authorization: Bearer {{ access_token }} + Content-Type: application/json + method: PUT + url: "http://127.0.0.1:8082/artifactory/api/v2/security/permissions/{{ item.name }}" + loop: + - name: RPMS + dict: "{{ repo_upstream }}" + +- name: Verify state + when: verify_state | bool + ansible.builtin.include_tasks: + file: verify.yml diff --git a/Ansible/examples/roles/artifactory_config/tasks/verify.yml b/Ansible/examples/roles/artifactory_config/tasks/verify.yml new file mode 100644 index 00000000..3e0284cb --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/tasks/verify.yml @@ -0,0 +1,115 @@ +--- + +- name: Gather package facts + ansible.builtin.package_facts: + +- name: Assert packages are installed + ansible.builtin.assert: + quiet: true + that: + - "'nginx' in ansible_facts.packages" + - "'python3-psycopg2' in ansible_facts.packages" + +- name: Gather service facts + ansible.builtin.service_facts: + +- name: Assert that services are running + ansible.builtin.assert: + quiet: true + that: + - ansible_facts.services['crond.service'].status == 'enabled' + - ansible_facts.services['crond.service'].state == 'running' + - ansible_facts.services['nginx.service'].status == 'enabled' + - ansible_facts.services['nginx.service'].state == 'running' + - ansible_facts.services['postgresql-13.service'].status == 'enabled' + - ansible_facts.services['postgresql-13.service'].state == 'running' + +- name: Check TLSv1.2 termination + ansible.builtin.uri: + ciphers: TLSv1.2 + url: "https://{{ server_name }}/" + method: HEAD + return_content: false + register: web + +- name: Verify other ports are listening + ansible.builtin.wait_for: + port: "{{ item }}" + state: started + timeout: 10 + loop: + - 5432 + - 8082 + +- name: Make sure artifactory is up and running + ansible.builtin.uri: + url: http://127.0.0.1:8082/router/api/v1/system/health + timeout: 130 + status_code: 200 + register: result + until: result is succeeded + retries: 25 + delay: 5 + when: + - not ansible_check_mode + +- name: Create access token + ansible.builtin.uri: + body: "scope=applied-permissions/admin&expires_in=18000" + body_format: form-urlencoded + force_basic_auth: true + method: POST + status_code: + - 200 + url: http://localhost:8082/access/api/v1/tokens + url_username: "{{ artifactory_admin_username }}" + url_password: "{{ artifactory_admin_password }}" + register: token_request + no_log: true + +- name: Set access_token + ansible.builtin.set_fact: + access_token: "{{ token_request.json.access_token }}" + no_log: true + +- name: Get users + ansible.builtin.uri: + headers: + Authorization: Bearer {{ access_token }} + method: GET + status_code: + - 200 + url: http://localhost:8082/access/api/v2/users + register: users + no_log: true + +- name: Display users + ansible.builtin.debug: + msg: "{{ users.json.users }}" + +- name: List permissions + tags: + - permissions + ansible.builtin.uri: + headers: + Authorization: Bearer {{ access_token }} + method: GET + url: "http://127.0.0.1:8082/artifactory/api/v2/security/permissions" + register: permission_list + no_log: false + +- name: Get permissions + ansible.builtin.uri: + headers: + Authorization: Bearer {{ access_token }} + method: GET + url: "{{ item.uri }}" + with_items: "{{ permission_list.json }}" + register: permissions + +- name: Display permissions + ansible.builtin.debug: + msg: "{{ item.json }}" + loop: "{{ permissions.results }}" + loop_control: + label: "{{ item.json.name }}" diff --git a/Ansible/examples/roles/artifactory_config/templates/artifactory.config.import.yml.j2 b/Ansible/examples/roles/artifactory_config/templates/artifactory.config.import.yml.j2 new file mode 100644 index 00000000..f7ab63f4 --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/templates/artifactory.config.import.yml.j2 @@ -0,0 +1,79 @@ +--- +version: 1 +## This file is complementary to the JFrog Artifactory startup wizard, and may be used to specify the initial basic +## settings for a new Artifactory installation, namely: +## * License Key(s) +## * Base URL +## * Proxy +## * Default repositories +## +## +## HOW TO USE THIS FILE: +## +## To import these settings when bootstrapping Artifactory, save this file as artifactory.config.import.yml under Artifactory’s /etc folder +## Artifactory will load this file if all of the following conditions are met: +## - no repositories have been created +## - a proxy has not been set up, or you did set up a proxy externally, but did not configure proxy setup through this file +## - the base URL has not been set up, or you did set up the base URL externally, but did not configure the base URL setup through this file +## - Artifactory has not been activated with a license, or Artifactory has been activated with a license, and you did not specify a license in this file +## +## To have any of these parameters automatically configured when you bootstrap an Artifactory instance using this file, +## simply uncomment the relevant sections below, and where required, provide values. + +################################################################################## +# General Configurations # +################################################################################## +GeneralConfiguration: +## License key to import in onboarding + licenseKey : "{{ artifactory_license | default('') }}" + +## Setup the Artifactory base URL +## For more information about the Artifactory base URL, please refer to +## https://www.jfrog.com/confluence/display/RTF/Configuring+Artifactory#ConfiguringArtifactory-GeneralSettings +## Uncomment the line below to set the Artifactory base URL + baseUrl : "https://{{ server_name | default(ansible_fqdn) }}" + +## Configure proxies for artifactory +## For more information on configuring a proxy in Artifactory, please refer to +## https://www.jfrog.com/confluence/display/RTF/Managing+Proxies +## Uncomment the lines below to setup a proxy +{% if https_proxy is defined %} + + proxies : + - key : "proxy" + host : "{{ artifactory_proxy_host }}" + port : "{{ artifactory_proxy_port }}" +{% if artifactory_proxy_user is defined %} + userName : "{{ artifactory_proxy_user }}" + password : "{{ artifactory_proxy_password }}" +{% endif %} + platformDefault : true +# services: "jfxr, jfrt" ## (Optional field. Comma separated string of services, options are: jfrt, jfmc, jfxr, jfds) +# - key : "proxy2" +# ... +{% endif %} + +################################################################################## +# Onboarding Configurations # +################################################################################## +OnboardingConfiguration: +## Uncomment the package types for which you want to create default repositories + repoTypes : +# - bower +# - cocoapods +# - composer +# - conan +# - debian + - docker +# - gems +# - gitlfs +# - gradle +# - ivy + - maven +# - npm +# - nuget +# - opkg + - pypi +# - rpm +# - sbt +# - vagrant diff --git a/Ansible/examples/roles/artifactory_config/templates/permissions.json.j2 b/Ansible/examples/roles/artifactory_config/templates/permissions.json.j2 new file mode 100644 index 00000000..35471909 --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/templates/permissions.json.j2 @@ -0,0 +1,13 @@ +{ + "name" : "{{ item.name }}", + "repo" : { + "actions" : { + "users" : { + "{{ item.dict[0].type }}" : [ "read", "annotate", "write" ] + } + }, + "repositories" : [ {% for r in item.dict %}"{{ r.key }}"{% if not loop.last %},{% endif %}{% endfor %} ], + "include-patterns" : [ "**" ], + "exclude-patterns" : [ ] + } +} diff --git a/Ansible/examples/roles/artifactory_config/templates/remote_repos.yml.j2 b/Ansible/examples/roles/artifactory_config/templates/remote_repos.yml.j2 new file mode 100644 index 00000000..0ed3f636 --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/templates/remote_repos.yml.j2 @@ -0,0 +1,17 @@ +remoteRepositories: +{% for r in repo_upstream %} + {{ r.key }}: + type: {{ r.type }} + repoLayout: simple-default + url: "{{ r.url }}/{{ r.key }}/" + propertySets: + - artifactory + contentSynchronisation: + enabled: true + statistics: + enabled: true + properties: + enabled: true + source: + originAbsenceDetection: true +{% endfor %} diff --git a/Ansible/examples/roles/artifactory_config/templates/repo_user.json.j2 b/Ansible/examples/roles/artifactory_config/templates/repo_user.json.j2 new file mode 100644 index 00000000..a6dc4e7c --- /dev/null +++ b/Ansible/examples/roles/artifactory_config/templates/repo_user.json.j2 @@ -0,0 +1,14 @@ +{ + "username": "{{ item.username }}", + "password": "{{ item.password }}", + "email": "noreply@example.com", + "groups": [ + "readers" + ], + "realm": "internal", + "status": "enabled", + "admin": false, + "profile_updatable": true, + "internal_password_disabled": false, + "disable_ui_access": false +}