Ansible is an IT automation engine for cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.


Ansible provides a faster and efficient way to automate the processes for the identification, triage, and response to security events.

In the following we will cover a simple yet effective use case: to report authentication anomaly and forbid access by temporarily suspending user's account on our Identity Management System (IdM), Apache Syncope.

In this post we're going to show how to automate the suspension of a Syncope user through an Ansible Collection.

Prerequisites

  1. ansible 2.9+

  2. python 3.6+

  3. An istance of Apache Syncope 2.1+ up and running for testing

Prepare the collection package

At first we initialize the collection and create the skeleton directory structure of our project launching this command, prefererably in a folder named ansible_collections:

$ ansible-galaxy collection init tirasa.SyncopeAnsible

Develop an Ansible plugin

Next, in the plugins folder of our collection, we have to provide a python script that will implement the actual integration with Syncope.

We've used an object-oriented approach, so at the beginning of the script we define our class and its constructor. Here we specify arguments for the Ansible module:

class SyncopeUserHandler(object):

    def __init__(self):
        self.argument_spec = dict(
            action=dict(type='str', choices=['change status'], required=True),
            adminUser=dict(type='str', required=True),
            adminPwd=dict(type='str', required=True),
            serverName=dict(type='str', required=True),
            syncopeUser=dict(type='str', required=True),
            newStatus=dict(type='str', choices=['SUSPEND', 'ACTIVATE', 'REACTIVATE'], required=True),
            changeStatusOnSyncope=dict(type='str', required=True)
        )

        self.module = AnsibleModule(
            argument_spec=self.argument_spec
        )

Then we provide the core method of our plugin, that simply sends a POST request to Syncope' REST endpoint for updating user status:

def change_user_status_rest_call(self):
        url = self.module.params['serverName'] + "/syncope/rest/users/" + self.module.params['syncopeUser'] + "/status"

        headers = {'Accept': 'application/json',
                   'Content-Type': 'application/json',
                   'Prefer': 'return-content',
                   'X-Syncope-Domain': 'Master'
                   }
        payload = {
            "operation": "ADD_REPLACE",
            "value": "org.apache.syncope.common.lib.types.StatusPatchType",
            "onSyncope": self.module.params['changeStatusOnSyncope'],
            "key": self.module.params['syncopeUser'],
            "type": self.module.params['newStatus']
        }

        admin = self.module.params['adminUser']
        password = self.module.params['adminPwd']

        result = dict(
            changed=False,
            message=''
        )

        try:
            resp = requests.post(url, headers=headers, auth=(admin, password), data=json.dumps(payload))
            resp_json = resp.json()

            if resp_json is None or resp is None or resp.status_code != 200:
                self.module.fail_json(msg="Error while changing status")
        except Exception as e:
            res = json.load(e)
            self.module.fail_json(msg=res)

        result['message'] = resp_json
        result['changed'] = True

        self.module.exit_json(**result)
        
def main():
    change_status = SyncopeUserHandler()
    change_status.change_user_status_rest_call()


if __name__ == '__main__':
    main()

Execute the plugin with a playbook

We are finally ready to write the playbook to perform the update of user status:

- name: run syncope_user_handler module
  syncope_user_handler:
    action: "change status"
    adminUser: {admin}
    adminPwd: {password}
    serverName: {server}
    syncopeUser: {userId}
    changeStatusOnSyncope: "true"
    newStatus: "SUSPEND" # REACTIVATE, ACTIVATE, SUSPEND
  register: results
- name: syncope_user_handler result message
  debug:
    msg: '{{ results }}'

If we have an Apache Syncope instance available we can easily test this playbook: first, we fill with proper values the needed arguments, then we can launch the playbook with:

$ ansible-playbook -M . ./playbook.yml

The code above is part of our Open Source Ansible Collection.

Ti è stato utile questo articolo?
Dal Blog di Tirasa
Quello che facciamo, studiamo e pensiamo tutti i giorni lo condividiamo qui.
Vai al blog >