From f877822c2dd155640062a442bba7d1addd4eb70b Mon Sep 17 00:00:00 2001 From: Lenka Segura Date: Feb 02 2023 06:53:12 +0000 Subject: [PATCH 1/2] Add tasks from communishift --- diff --git a/roles/fas2discourseconfig/defaults/main.yml b/roles/fas2discourseconfig/defaults/main.yml index 0bc6b5c..f6b8124 100644 --- a/roles/fas2discourseconfig/defaults/main.yml +++ b/roles/fas2discourseconfig/defaults/main.yml @@ -1,2 +1,6 @@ --- # defaults file for Fas2discourseConfig +fas2discourse_keytab_path: "/etc/fas2discourse" +fas2discourse_principal: "fas2discourse/fas2discourse.hostname@FEDORAPROJECT.ORG" +f2d_namespace: "fas2discourse-operator" +f2d_secret: "fas2discourse-operator-k8s-secret" diff --git a/roles/fas2discourseconfig/tasks/kerberos_auth.yml b/roles/fas2discourseconfig/tasks/kerberos_auth.yml new file mode 100644 index 0000000..3b834dd --- /dev/null +++ b/roles/fas2discourseconfig/tasks/kerberos_auth.yml @@ -0,0 +1,4 @@ +--- +# tasks file for Fas2Discourse +- name: Authorize with kinit + shell: kinit -k -t "{{ fas2discourse_keytab_path }}/fas2discourse-keytab" -l 3600 {{ fas2discourse_principal }} diff --git a/roles/fas2discourseconfig/tasks/main.yml b/roles/fas2discourseconfig/tasks/main.yml index 1a10545..ee885de 100644 --- a/roles/fas2discourseconfig/tasks/main.yml +++ b/roles/fas2discourseconfig/tasks/main.yml @@ -1,2 +1,6 @@ --- # tasks file for Fas2discourseConfig + +- include_tasks: kerberos_auth.yml +- include_tasks: retrieve_ipa_groups.yml +- include_tasks: sync_group_membership.yml diff --git a/roles/fas2discourseconfig/tasks/retrieve_ipa_groups.yml b/roles/fas2discourseconfig/tasks/retrieve_ipa_groups.yml new file mode 100644 index 0000000..11fb50f --- /dev/null +++ b/roles/fas2discourseconfig/tasks/retrieve_ipa_groups.yml @@ -0,0 +1,20 @@ +--- +# tasks file for fas2discourse + +- name: Retrieve fasjson group/user data based on pattern supplied + fas2discourse_retrieve_fasjson_data: + keytab_path: "{{ fas2discourse_keytab_path }}" + principal: "{{ fas2discourse_principal }}" + group_name_pattern: "{{ fas2discourse_group_regex_pattern }}" + register: fasjson_response + +- name: Set fact + set_fact: + fas2discourse_fasjson_response: "{{ fasjson_response }}" +#- name: Prints the groups +# ansible.builtin.debug: +# msg: +# - "Groups found: {{ fas2discourse_fasjson_response['matched_groups'] }}" + +#- name: Write groups to json file +# copy: content="{{ fas2discourse_fasjson_response['matched_groups'] }}" dest=/tmp/groups.json diff --git a/roles/fas2discourseconfig/tasks/sync_group_membership.yml b/roles/fas2discourseconfig/tasks/sync_group_membership.yml new file mode 100644 index 0000000..6de3990 --- /dev/null +++ b/roles/fas2discourseconfig/tasks/sync_group_membership.yml @@ -0,0 +1,29 @@ +--- +# tasks file for Fas2Discourse + +- k8s_info: + api_version: v1 + kind: Secret + namespace: "{{ cao_namespace }}" + name: "{{ cao_secret }}" + register: cao_secret_yaml + +- set_fact: + cao_secret: "{{ cao_secret_yaml.resources[0] | from_yaml }}" +- set_fact: + fas2discourse_ocp_api_token: "{{ cao_secret.data['fas2discourse-ocp-api-token'] | b64decode }}" +- set_fact: + fas2discourse_ocp_api_host: "{{ cao_secret.data['fas2discourse-ocp-api-host'] | b64decode }}" + +- name: Sync user membership between IPA and Openshift Groups + community.okd.k8s: + api_key: "{{ fas2discourse_ocp_api_token }}" + host: "{{ fas2discourse_ocp_api_host }}" + state: present + definition: + apiVersion: user.openshift.io/v1 + kind: Group + metadata: + name: "{{ item['groupname'] }}-admins" + users: "{{ item['groupmembers'] | default([]) }}" + with_items: "{{ fas2discourse_fasjson_response['matched_groups'] }}" From 8f5ae589948cc9ee0a85eb85da07cc9e19bc8fb5 Mon Sep 17 00:00:00 2001 From: Lenka Segura Date: Feb 07 2023 09:50:00 +0000 Subject: [PATCH 2/2] Add python module to library --- diff --git a/roles/fas2discourseconfig/library/fas2discourse_retrieve_fasjson_data.py b/roles/fas2discourseconfig/library/fas2discourse_retrieve_fasjson_data.py new file mode 100644 index 0000000..e98aaeb --- /dev/null +++ b/roles/fas2discourseconfig/library/fas2discourse_retrieve_fasjson_data.py @@ -0,0 +1,190 @@ +#!/usr/bin/python + +# Copyright: (c) 2018, Terry Jones +# GNU General Public License v3.0+ (see COPYING or +# https://www.gnu.org/licenses/gpl-3.0.txt) + +import json +import requests + +from ansible.module_utils.basic import AnsibleModule +from requests_kerberos import HTTPKerberosAuth + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: fas2discourse_retrieve_fasjson_data + +short_description: Retrieve fasjson group and user data. + +version_added: "0.0.1" + +description: This module retrieves fasjson group and users data which match +the groups in discourse. + +options: + keytab_path: + description: This is the location on disk where the kerberos keytab is stored. + required: true + type: str + principal: + description: The is the kerberos principal. + required: true + type: str + discourse_groups: + description: These are the groups retrieved from the discouse. + required: true + type: str + +author: + - David Kirwan (dkirwan@redhat.com) + - Lenka Segura (lsegura@redhat.com) + - Patrik Polakovic (ppolakov@redhat.com) +""" + +EXAMPLES = r""" +- name: Retrieve fasjson group/user data based on the discourse groups + fas2discourse_retrieve_fasjson_data: + keytab_path: "{{ fas2discourse_keytab }}" + principal: "{{ fas2discourse_principal }}" + discourse_groups: "{{ discourse_groups }}" + register: fas2discourse_fasjson_response +""" + +RETURN = r""" +# These are examples of possible return values, and in general should use other names for return +# values. +matched_groups: + description: The groups and their users which match the discourse groups. + type: str + returned: always + sample: +[ + { + "group_name": "yyy", + "group_members": [ + "uuu", + "iii", + "eee", + "zqq" + ] + }, + { + "group_name": "abc", + "group_members": [ + "xyc", + "cyz", + "xxx", + "zzz" + ] + } +] + +msg: + description: The output message that the module generates. + type: str + returned: always + sample: 'Successfully retrieved groups and their users from fasjson.' +""" + + +# Helper function to create the http requests +def get_http_client(keytab_path, principal): + try: + kerberos_auth = HTTPKerberosAuth(principal=principal) + except Exception as e: + print("Error trying to authenticate with Kerberos", e) + raise + session = requests.Session() + session.auth = kerberos_auth + return session + + +# Helper function to retrieve fasjson groups +def get_groups(http_client): + response = http_client.get("%sgroups/" % ("https://fasjson.fedoraproject.org/v1/")) + if response.ok: + return response.json() + + +# Helper function to retrieve fasjson group members +def get_group_members(http_client, groupname): + response = http_client.get( + "%sgroups/%s/members/" % ("https://fasjson.fedoraproject.org/v1/", groupname) + ) + if response.ok: + return response.json() + + +def run_module(): + # define available arguments/parameters a user can pass to the module + module_args = dict( + keytab_path=dict(type="str", required=True), + principal=dict(type="str", required=True), + discourse_groups=dict(type="str", required=True), + ) + + # seed the result dict in the object + # we primarily care about changed and state + # changed is if this module effectively modified the target + # state will include any data that you want your module to pass back + # for consumption, for example, in a subsequent task + result = dict(changed=False, original_message="", message="") + + # the AnsibleModule object will be our abstraction working with Ansible + # this includes instantiation, a couple of common attr would be the + # args/params passed to the execution, as well as if the module + # supports check mode + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) + + # if the user is working with this module in only check mode we do not + # want to make any changes to the environment, just return the current + # state with no modifications + if module.check_mode: + module.exit_json(**result) + + # manipulate or modify the state as needed (this is going to be the + # part where your module will do what it needs to do) + keytab_path = module.params["keytab_path"] + principal = module.params["principal"] +# discourse_groups = module.params["discourse_groups"] + # let's hardcode the discourse groups for the moment + discourse_groups = ["council", "moderators", "design", "magazine_editors", "community-blog", "pgm-team"] + + try: + http_client = get_http_client(keytab_path, principal) + groups_response = get_groups(http_client) + + fas2discourse_groups = [] + for v in groups_response["result"]: + if v["groupname"] in discourse_groups: + group = {"groupname": v["groupname"], "groupmembers": []} + + group_member_res = get_group_members(http_client, v["groupname"]) + # print(json.dumps(group_member_res)) + + for v in group_member_res["result"]: + group["groupmembers"].append(v["username"]) + fas2discourse_groups.append(group) + # print(v["groupname"]) + + # print(json.dumps(fas2discourse_groups)) + + result["matched_groups"] = json.dumps(fas2discourse_groups) + result["changed"] = True + result["msg"] = "Successfully retrieved groups and their users from fasjson." + except Exception: + raise + + # in the event of a successful module execution, you will want to + # simple AnsibleModule.exit_json(), passing the key/value results + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main()