From fddeda204968a251cf90f0e3c2f1ae26f4e04173 Mon Sep 17 00:00:00 2001 From: Aditya Honkalas Date: Tue, 29 Nov 2022 03:19:45 -0800 Subject: [PATCH] Request header identity provider test automation Signed-off-by: Aditya Honkalas --- README.md | 2 +- examples/all.yaml | 8 + ...request_header_identity_provider_vars.yaml | 9 + playbooks/main.yml | 3 + .../request-header-identity-provider.yml | 6 + .../README.md | 65 +++++++ .../defaults/main.yml | 9 + .../tasks/main.yml | 161 ++++++++++++++++++ 8 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 examples/request_header_identity_provider_vars.yaml create mode 100644 playbooks/request-header-identity-provider.yml create mode 100644 playbooks/roles/request-header-identity-provider/README.md create mode 100644 playbooks/roles/request-header-identity-provider/defaults/main.yml create mode 100644 playbooks/roles/request-header-identity-provider/tasks/main.yml diff --git a/README.md b/README.md index 6f7d9b54..4ac0b010 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ This repository consists of additional ansible playbooks for the following: 1. Run File Integrity Operator and e2e 1. Configure and test IPA identity provider 1. Enable monitoring for user-defined projects - +1. Configure and test Request-Header identity provider ## Assumptions: diff --git a/examples/all.yaml b/examples/all.yaml index 3e4239fb..7d39dcce 100644 --- a/examples/all.yaml +++ b/examples/all.yaml @@ -21,6 +21,14 @@ user_defined_app_name: "prometheus-example-app" # User defined app name user_defined_namespace: "test-namespace" # User defined namespace service_monitor_name: "prometheus-example-app-monitor" # User defined name for ServiceMonitor object name +# Request-header identity provider vars +request_header_provider: false # Set true to enable the test execution +request_header_user_display_name: "Default User" # User's full name to be displayed e.g. "John Doe" +request_header_username: "rh-user" # Username to be attached in the request header e.g. "jdoe" +ca_cert_configmap: "cert-auth-configmap" # Name for a ConfigMap object containing CA certificate bundle +request_header_cr_name: "request-header-provider" # Name for a identity provider custom resource object +request_header_user_role: "cluster-reader" # Role based permission to be assigned to the new user e.g. ["admin", "basic-user", "cluster-admin", "cluster-status", "cluster-reader", "edit", "self-provisioner", "view"] + ## ocp-e2e vars e2e_tests_enabled: false e2e_tests_dir: /tmp/openshift_ws diff --git a/examples/request_header_identity_provider_vars.yaml b/examples/request_header_identity_provider_vars.yaml new file mode 100644 index 00000000..b3013ff0 --- /dev/null +++ b/examples/request_header_identity_provider_vars.yaml @@ -0,0 +1,9 @@ +--- + +# Request-header identity provider vars +request_header_provider: false # Set true to enable the test execution +request_header_user_display_name: "Default User" # User's full name to be displayed e.g. "John Doe" +request_header_username: "rh-user" # Username to be attached in the request header e.g. "jdoe" +ca_cert_configmap: "cert-auth-configmap" # Name for a ConfigMap object containing CA certificate bundle +request_header_cr_name: "request-header-provider" # Name for a identity provider custom resource object +request_header_user_role: "cluster-reader" # Role based permission to be assigned to the new user e.g. ["admin", "basic-user", "cluster-admin", "cluster-status", "cluster-reader", "edit", "self-provisioner", "view"] diff --git a/playbooks/main.yml b/playbooks/main.yml index 68bcaef2..897d3ae3 100644 --- a/playbooks/main.yml +++ b/playbooks/main.yml @@ -83,3 +83,6 @@ - import_playbook: monitoring-user-defined-projects.yml when: enable_user_defined_project_monitoring is defined and enable_user_defined_project_monitoring +- import_playbook: request-header-identity-provider.yml + when: request_header_provider is defined and request_header_provider + diff --git a/playbooks/request-header-identity-provider.yml b/playbooks/request-header-identity-provider.yml new file mode 100644 index 00000000..6526cd4a --- /dev/null +++ b/playbooks/request-header-identity-provider.yml @@ -0,0 +1,6 @@ +--- + +- name: Request-header identity provider test + hosts: bastion + roles: + - request-header-identity-provider diff --git a/playbooks/roles/request-header-identity-provider/README.md b/playbooks/roles/request-header-identity-provider/README.md new file mode 100644 index 00000000..ded6ecf6 --- /dev/null +++ b/playbooks/roles/request-header-identity-provider/README.md @@ -0,0 +1,65 @@ +Request header identity provider test +===================================== + +A request header is an identity provider method to identify users from request header values, such as `X-Remote-User`. It is typically used in combination with an authenticating proxy, which sets the request header value. + +This ansible role will configure request header as an identity provider to authenticate users with cluster OAUTH server and grants *"cluster-reader"* as a default user role permission. + + + +Requirements +------------ + - Running OCP 4.x cluster is needed. + - Access to the cluster with the cluster-admin role. + +Dependencies +------------ + - None + + +Role Variables +-------------- + +| Variable | Required | Default | Comments | +|-----------------------------------|----------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| request_header_provider | no | false | Set to true to enable request header test execution | +| request_header_user_display_name | no | Default User | User's full name to be sent in a request header, if undefined default user display name will be set | +| request_header_username | no | rh-user | Username to be sent in a request header, if undefined default username will be set | +| ca_configmap_name | no | cert-auth-configmap | User defined name for CA configmap object, if undefined default name will be set to the CA certificate configmap | +| request_header_cr_name | no | request-header-provider | User defined name for identity provider CR object, if undefined default name will be set to the provider CR object | +| request_header_user_role | no | cluster-reader | User role permission to be granted to the newly created user. the possible role permission can be `"admin", "basic-user", "cluster-admin", "cluster-status", "cluster-reader", "edit", "self-provisioner", "view"`, if empty default user role will be assigned | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +Example Playbook +---------------- +``` +--- +- name: Configuring request header identity provider + hosts: bastion + roles: + - ocp-request-header-identity-provider +``` + + +Steps to run the playbook +------------------------- + + - Copy `ocp4-playbooks-extras/examples/inventory` file to the home or working directory and modify to add a remote host + - Copy the `ocp4-playbooks-extras/examples/all.yaml` to the home or working directory and set the role variables for `roles/request-header-identity-provider` with the custom inputs. Enable the role execution by setting `request-header-provider` to `true`. + - To execute the playbook run the below sample command + + +Sample Command +--------------- + +ansible-playbook -i inventory -e @all.yaml ~/ocp4-playbooks-extras/playbooks/main.yml + + +License +------- +See LICENCE.txt + +Author Information +------------------ +Aditya.Honkalas@ibm.com diff --git a/playbooks/roles/request-header-identity-provider/defaults/main.yml b/playbooks/roles/request-header-identity-provider/defaults/main.yml new file mode 100644 index 00000000..3c049dab --- /dev/null +++ b/playbooks/roles/request-header-identity-provider/defaults/main.yml @@ -0,0 +1,9 @@ +--- + +# Request-header identity provider vars with default values +request_header_provider: false +request_header_user_display_name: "Default User" +request_header_username: "rh-user" +ca_cert_configmap: "cert-auth-configmap" +request_header_cr_name: "request-header-provider" +request_header_user_role: "cluster-reader" diff --git a/playbooks/roles/request-header-identity-provider/tasks/main.yml b/playbooks/roles/request-header-identity-provider/tasks/main.yml new file mode 100644 index 00000000..83e8a6ed --- /dev/null +++ b/playbooks/roles/request-header-identity-provider/tasks/main.yml @@ -0,0 +1,161 @@ +--- + +# request header auth provider tasks module + +- name: Login to the cluster as a system-admin + shell: oc login -u system:admin + +- name: Cleanup block to delete the old identities and users + block: + - name: Get the existing identities + shell: oc get identity --no-headers | awk '{print $1}' + register: old_identities + + - name: Get the existing users associated with these providers + shell: oc get user --no-headers | awk '{print $1}' + register: old_users + + - name: Delete the existing identities + k8s: + state: absent + kind: Identity + name: "{{ item }}" + api_version: user.openshift.io/v1 + loop: "{{ old_identities.stdout_lines }}" + + - name: Delete the existing users + k8s: + state: absent + kind: User + name: "{{ item }}" + api_version: user.openshift.io/v1 + loop: "{{ old_users.stdout_lines }}" + +- name: Create a sub-directory ~/certs + file: + path: ~/certs + state: directory + mode: 0755 + +- name: Extract a ca certificate to provide along with request headers + shell: "oc extract -n openshift-config cm/admin-kubeconfig-client-ca --confirm" + args: + chdir: ~/certs + +- name: Check if CA configmap exists for {{ ca_cert_configmap }} + shell: "oc get configmap {{ ca_cert_configmap }} -n openshift-config --no-headers | wc -l" + register: ca_configmap_exists + +- name: Create a CA configmap + shell: "oc create configmap {{ ca_cert_configmap }} --from-file=ca.crt=ca-bundle.crt -n openshift-config" + args: + chdir: ~/certs + when: ca_configmap_exists.stdout|int == 0 + +- name: Update a OAUTH cluster CR with request header provider configuration + k8s: + state: present + apply: yes + definition: + apiVersion: config.openshift.io/v1 + kind: OAuth + metadata: + name: cluster + spec: + identityProviders: + - name: "{{ request_header_cr_name }}" + mappingMethod: claim + type: RequestHeader + requestHeader: + challengeURL: "https://www.example.com/challenging-proxy/oauth/authorize?${query}" + loginURL: "https://www.example.com/login-proxy/oauth/authorize?${query}" + ca: + name: "{{ ca_cert_configmap }}" + headers: + - X-Remote-User + - SSO-User + emailHeaders: + - X-Remote-User-Email + nameHeaders: + - X-Remote-User-Display-Name + preferredUsernameHeaders: + - X-Remote-User-Login + +- name: Delay to get pods reinitialised + wait_for: + timeout: 180 + +- name: Wait until pods get in the Running state + shell: "oc get pods -n openshift-authentication --no-headers | grep -v Running | wc -l" + retries: 10 + delay: 30 + register: pods_in_running + until: pods_in_running.stdout|int == 0 + ignore_errors: yes + +- name: Prepare client certificate and key for extracted ca + block: + - name: Extract the current kubeconfig for client certificate and key + shell: "oc config view --context admin --minify --raw > current.kubeconfig" + args: + chdir: ~/certs + + - name: Obtain the client certificate from the kubeconfig + shell: grep client-certificate-data current.kubeconfig | grep -Eo "[^ ]+$" | base64 -d > client.crt + args: + chdir: ~/certs + + - name: Extract the key for client certificate obtained in previous step + shell: grep client-key-data current.kubeconfig | grep -Eo "[^ ]+$" | base64 -d > client.key + args: + chdir: ~/certs + +- name: Extract the OAUTH server route path + k8s_info: + api_version: route.openshift.io/v1 + kind: Route + name: oauth-openshift + namespace: openshift-authentication + register: oauthroutepath + +- name: Trigger HTTP request to proxy auth endpoint with the request headers containing user details + shell: | + curl -k -I --cert ./client.crt --key ./client.key \ + -H "SSO-User: {{ request_header_username }}" -H "X-Remote-User-Display-Name: {{ request_header_user_display_name }}" \ + "https://{{ OAUTH_ROUTE_HOST }}/oauth/authorize?response_type=token&client_id=openshift-challenging-client" \ + | grep -oP "sha256~[a-zA-Z0-9\-\_\~]+" + args: + chdir: ~/certs + warn: false + vars: + OAUTH_ROUTE_HOST: "{{ oauthroutepath.resources[0].spec.host }}" + environment: + KUBECONFIG: "/root/openstack-upi/auth/kubeconfig" + register: oauth_access_token + +- name: Check the created identity + shell: oc get identity + register: get_oc_identity_output + +- debug: + msg: "{{ get_oc_identity_output.stdout_lines }}" + +- name: Login to the cluster with newly added user + shell: "oc login --token {{ oauth_access_token.stdout.strip('\"') }}" + register: login_output + +- debug: + msg: "{{ login_output.stdout_lines }}" + +- name: Check the current logged-in user + shell: oc whoami + register: current_logged_in_user + +- debug: + msg: "{{ current_logged_in_user.stdout_lines }}" + +- name: Switch back again to system-admin user + shell: oc login -u system:admin + +- name: Grant the role permission to the newly created user + shell: "oc adm policy add-cluster-role-to-user {{ request_header_user_role }} {{ request_header_user_display_name }}"