Beispiel #1
0
def main():
    argument_spec = keycloak_argument_spec()

    composites_spec = dict(name=dict(type='str', required=True),
                           clientId=dict(type='str'))
    meta_args = dict(
        realm=dict(type='str', default='master'),
        name=dict(type='str', required=True),
        description=dict(type='str', default=None),
        composite=dict(type='bool', default=False),
        clientRole=dict(type='bool', default=False),
        containerId=dict(type='str', required=False),
        composites=dict(type='list',
                        elements='dict',
                        default=[],
                        options=composites_spec),
        state=dict(choices=["absent", "present"], default='present'),
        force=dict(type='bool', default=False),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', role={}, composites=None)

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    force = module.params.get('force')
    newComposites = None

    # Create representation for the new role
    newRoleRepresentation = {}
    newRoleRepresentation["name"] = module.params.get('name')
    if module.params.get('description') is not None:
        newRoleRepresentation["description"] = module.params.get('description')
    newRoleRepresentation["composite"] = module.params.get('composite')
    newRoleRepresentation["clientRole"] = module.params.get('clientRole')
    newRoleRepresentation["containerId"] = module.params.get(
        'containerId') if module.params.get(
            'containerId') is not None else realm
    if module.params.get('composites') is not None:
        newComposites = module.params.get('composites')

    changed = False

    # Search the role on Keycloak server.
    roleRepresentation = kc.search_realm_role_by_name(
        name=newRoleRepresentation["name"], realm=realm)
    if roleRepresentation == {}:  # If role does not exists
        if (state == 'present'):  # If desired state is present
            # Create Role
            kc.create_realm_role(newRoleRepresentation=newRoleRepresentation,
                                 realm=realm)
            # Create composites
            kc.create_or_update_realm_role_composites(
                newComposites=newComposites,
                newRoleRepresentation=newRoleRepresentation,
                realm=realm)
            # Get created role
            roleRepresentation = kc.get_realm_role(
                name=newRoleRepresentation["name"], realm=realm)
            # Get created composites
            composites = kc.get_realm_role_composites_with_client_id(
                name=newRoleRepresentation["name"], realm=realm)
            changed = True
            result['role'] = roleRepresentation
            result['composites'] = composites
        elif state == 'absent':  # If desired state is absent
            result["msg"] = "Realm role %s is absent in realm %s" % (
                newRoleRepresentation["name"], realm)

    else:  # If role already exists
        if (state == 'present'):  # If desired state is present
            if force:  # If force option is true
                # Delete the existing role
                kc.delete_realm_role(name=roleRepresentation["name"],
                                     realm=realm)
                # Create role again
                kc.create_realm_role(
                    newRoleRepresentation=newRoleRepresentation, realm=realm)
                changed = True
            else:  # If force option is false
                # Compare roles
                if not (isDictEquals(
                        newRoleRepresentation,
                        roleRepresentation)):  # If new role introduce changes
                    # Update the role
                    kc.update_realm_role(
                        newRoleRepresentation=newRoleRepresentation,
                        realm=realm)
                    changed = True
            # Manage composites
            if kc.create_or_update_realm_role_composites(
                    newComposites=newComposites,
                    newRoleRepresentation=newRoleRepresentation,
                    realm=realm):
                changed = True
            # Get created role
            roleRepresentation = kc.get_realm_role(
                name=newRoleRepresentation["name"], realm=realm)
            # Get composites
            composites = kc.get_realm_role_composites_with_client_id(
                name=newRoleRepresentation["name"], realm=realm)
            result["role"] = roleRepresentation
            result["composites"] = composites
        elif state == 'absent':  # If desired state is absent
            # Delete role
            kc.delete_realm_role(name=newRoleRepresentation["name"],
                                 realm=realm)
            changed = True
            result["msg"] = "Realm role %s is deleted in realm %s" % (
                newRoleRepresentation["name"], realm)
    result['changed'] = changed
    module.exit_json(**result)
Beispiel #2
0
def main():
    argument_spec = keycloak_argument_spec()
    config_spec = dict(
        vendor=dict(type='list', elements='str', choices=['ad', 'tivoli', 'edirectory', 'rhds', 'other']),
        usernameLDAPAttribute=dict(type='list', elements='str'),
        editMode=dict(type='list', elements='str', choices=['READ_ONLY', 'WRITABLE', 'UNSYNCED']),
        rdnLDAPAttribute=dict(type='list', elements='str'),
        uuidLDAPAttribute=dict(type='list', elements='str'),
        userObjectClasses=dict(type='list', elements='str'),
        connectionUrl=dict(type='list', elements='str'),
        usersDn=dict(type='list', elements='str'),
        authType=dict(type='list', elements='str', choices=['simple', 'none']),
        bindDn=dict(type='list', elements='str'),
        bindCredential=dict(type='list', elements='str'),
        changedSyncPeriod=dict(type='list', elements='str'),
        fullSyncPeriod=dict(type='list', elements='str'),
        pagination=dict(type='list', elements='str', choices=['true', 'false']),
        connectionPooling=dict(type='list', elements='str', choices=['true', 'false']),
        cachePolicy=dict(type='list', elements='str', choices=['DEFAULT', 'EVICT_DAILY', 'EVICT_WEEKLY', 'MAX_LIFESPAN', 'NO_CACHE']),
        useKerberosForPasswordAuthentication=dict(type='list', elements='str', choices=['true', 'false']),
        allowKerberosAuthentication=dict(type='list', elements='str', choices=['true', 'false']),
        importEnabled=dict(type='list', elements='str', choices=['true', 'false']),
        syncRegistrations=dict(type='list', elements='str', choices=['true', 'false']),
        searchScope=dict(type='list', elements='str', choices=['1', '2']),
        priority=dict(type='list', elements='int'),
        validatePasswordPolicy=dict(type='list', elements='str', choices=['true', 'false']),
        batchSizeForSync=dict(type='list', elements='str')
    )
    ldapstoragemapper_spec = {
        "ldap.attribute": {'type': 'list', 'elements': 'str'},
        "is.mandatory.in.ldap": {'type': 'list', 'elements': 'str', 'choices': ['true', 'false']},
        "read.only": {'type': 'list', 'elements': 'str', 'choices': ['true', 'false']},
        "user.model.attribute": {'type': 'list', 'elements': 'str'},
        "always.read.value.from.ldap": {'type': 'list', 'elements': 'str', 'choices': ['true', 'false']},
        'mode': {'type': 'list', 'elements': 'str', 'choices': ['LDAP_ONLY', 'READ_ONLY', 'IMPORT']},
        "membership.attribute.type": {'type': 'list', 'elements': 'str', 'choices': ['DN', 'UID']},
        "user.roles.retrieve.strategy": {'type': 'list', 'elements': 'str', 'choices': [
            'LOAD_GROUPS_BY_MEMBER_ATTRIBUTE',
            'GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE',
            'LOAD_GROUPS_BY_MEMBER_ATTRIBUTE_RECURSIVELY'
        ]},
        'group.name.ldap.attribute': {'type': 'list', 'elements': 'str'},
        'membership.ldap.attribute': {'type': 'list', 'elements': 'str'},
        'membership.user.ldap.attribute': {'type': 'list', 'elements': 'str'},
        'memberof.ldap.attribute': {'type': 'list', 'elements': 'str'},
        'preserve.group.inheritance': {'type': 'list', 'elements': 'str', 'choices': ['true', 'false']},
        'groups.dn': {'type': 'list', 'elements': 'str'},
        'group.object.classes': {'type': 'list', 'elements': 'str'},
        'drop.non.existing.groups.during.sync': {'type': 'list', 'elements': 'str', 'choices': ['true', 'false']}
    }
    subcomponents_config_spec = {
        "name": {"type": "str"},
        "providerId": {"type": "str", "choices": ['user-attribute-ldap-mapper', 'group-ldap-mapper']},
        "config": {"type": "dict", "options": ldapstoragemapper_spec}
    }
    subcomponents_spec = {
        "org.keycloak.storage.ldap.mappers.LDAPStorageMapper": {'type': 'list', 'elements': 'dict', 'options': subcomponents_config_spec}
    }
    meta_args = dict(
        id=dict(type='str'),
        name=dict(type='str', required=True),
        realm=dict(type='str', required=True),
        providerId=dict(
            choices=[
                "ldap",
                "allowed-client-templates",
                "trusted-hosts",
                "allowed-protocol-mappers",
                "max-clients",
                "scope",
                "consent-required",
                "rsa-generated"],
            required=True),
        providerType=dict(
            choices=[
                "org.keycloak.storage.UserStorageProvider",
                "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy",
                "org.keycloak.keys.KeyProvider",
                "authenticatorConfig",
                "requiredActions"],
            required=True),
        parentId=dict(type='str'),
        config=dict(type='dict', options=config_spec),
        subComponents=dict(type='dict', options=subcomponents_spec),
        syncUserStorage=dict(choices=["triggerFullSync", "triggerChangedUsersSync"]),
        syncLdapMappers=dict(choices=["fedToKeycloak", "keycloakToFed"]),
        state=dict(choices=["absent", "present"], default='present'),
        force=dict(type='bool', default=False),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', diff={}, component='', subComponents='')

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    force = module.params.get('force')

    # Create a representation from module parameters
    newComponent = {}
    newComponent["id"] = module.params.get('id')
    newComponent["name"] = module.params.get('name')
    newComponent["providerId"] = module.params.get('providerId')
    newComponent["providerType"] = module.params.get('providerType')
    newComponent["parentId"] = module.params.get('parentId') if module.params.get('parentId') is not None else realm
    newComponent["config"] = remove_arguments_with_value_none(module.params.get("config").copy())
    newSubComponents = remove_arguments_with_value_none(module.params.get("subComponents").copy())
    syncUserStorage = module.params.get('syncUserStorage') if module.params.get('syncUserStorage') is not None else "no"
    syncLdapMappers = module.params.get('syncLdapMappers') if module.params.get('syncLdapMappers') is not None else "no"

    changed = False

    component = kc.get_component_by_name_provider_and_parent(
        name=newComponent["name"],
        provider_type=newComponent["providerType"],
        provider_id=newComponent["providerId"],
        parent_id=newComponent["parentId"],
        realm=realm)

    if component == {}:  # If component does not exist
        if (state == 'present'):  # If desired stat is present
            # Create the component and it's sub-components
            component = kc.create_component(
                newComponent=newComponent,
                newSubComponents=newSubComponents,
                syncLdapMappers=syncLdapMappers,
                realm=realm)
            subComponents = kc.get_all_sub_components(parent_id=component["id"], realm=realm)
            if syncUserStorage != 'no':  # If user synchronization is needed
                kc.sync_user_storage(component_id=component['id'], action=syncUserStorage, realm=realm)
                result['component'] = component
            changed = True
            result['component'] = component
            result['subComponents'] = subComponents
            result['changed'] = changed
        elif state == 'absent':  # Id desired state is absent, return absent and do nothing.
            result['msg'] = newComponent["name"] + ' absent'
            result['component'] = newComponent
            result['changed'] = changed

    else:  # If component already exist
        if (state == 'present'):  # if desired state is present
            if force:  # If force option is true
                # Delete the existing component
                kc.delete_component(component_id=component["id"], realm=realm)
                changed = True
                # Re-create the component.
                component = kc.create_component(newComponent=newComponent, newSubComponents=newSubComponents, syncLdapMappers=syncLdapMappers, realm=realm)
            else:  # If force option is false
                # Copy existing id in new component
                newComponent['id'] = component['id']
                newComponent['parentId'] = component['parentId']
                excludes = []
                # Compare the new component with the existing
                excludes.append("bindCredential")
                if not isDictEquals(newComponent, component, excludes):  # If the component need to be changed
                    # Update the component
                    component = kc.update_component(newComponent=newComponent, realm=realm)
                    changed = True
                # Update sub components
                if kc.update_sub_components(component=newComponent, newSubComponents=newSubComponents, syncLdapMappers=syncLdapMappers, realm=realm):
                    changed = True
            if syncUserStorage != 'no':  # If user synchronization is needed
                kc.sync_user_storage(component_id=component['id'], action=syncUserStorage, realm=realm)

            result['component'] = component
            result['subComponents'] = kc.get_all_sub_components(parent_id=component["id"], realm=realm)
            result['changed'] = changed

        elif state == 'absent':  # if desired state is absent
            # Delete the component
            kc.delete_component(component_id=component['id'], realm=realm)
            changed = True
            result['msg'] = newComponent["name"] + ' deleted'
            result['changed'] = changed

    module.exit_json(**result)
Beispiel #3
0
def main():
    argument_spec = keycloak_argument_spec()
    idpconfig_spec = {
        "openIdConfigurationUrl": {
            "type": "str"
        },
        "clientId": {
            "type": "str"
        },
        "clientSecret": {
            "type": "str"
        },
        "clientAuthMethod": {
            "type":
            "str",
            "choices": [
                "client_secret_post", "client_secret_basic",
                "client_secret_jwt", "private_key_jwt"
            ],
            "default":
            "client_secret_post"
        },
        "disableUserInfo": {
            "type": "str",
            "default": "false",
            "choices": ["true", "false"]
        },
        "defaultScope": {
            "type": "str"
        },
        "guiOrder": {
            "type": "int"
        },
        "backchannelSupported": {
            "type": "str",
            "default": "true",
            "choices": ["true", "false"]
        }
    }
    mapperconfig_args = {
        "claim": {
            "type": "str"
        },
        "user.attribute": {
            "type": "str"
        },
        "claim.value": {
            "type": "str"
        },
        "role": {
            "type": "str"
        }
    }
    mapper_spec = {
        "name": {
            "type": "str"
        },
        "identityProviderMapper": {
            "type": "str",
            "choices":
            ["oidc-user-attribute-idp-mapper", "oidc-role-idp-mapper"]
        },
        "config": {
            "type": "dict",
            "options": mapperconfig_args
        }
    }
    meta_args = dict(
        realm=dict(type='str', default='master'),
        alias=dict(type='str', required=True),
        displayName=dict(type='str'),
        providerId=dict(type='str', default='oidc'),
        enabled=dict(type='bool', default=True),
        updateProfileFirstLoginMode=dict(type='str'),
        trustEmail=dict(type='bool'),
        storeToken=dict(type='bool', default=True),
        addReadTokenRoleOnCreate=dict(type='bool'),
        authenticateByDefault=dict(type='bool'),
        firstBrokerLoginFlowAlias=dict(type='str'),
        postBrokerLoginFlowAlias=dict(type='str'),
        linkOnly=dict(type='bool', default=False),
        config=dict(type='dict', options=idpconfig_spec),
        mappers=dict(type='list', elements='dict', options=mapper_spec),
        state=dict(choices=["absent", "present"], default='present'),
        force=dict(type='bool', default=False),
    )

    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', idp={}, mappers=[])

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    force = module.params.get('force')
    changed = False
    # Créer un représentation du realm recu en paramètres
    newIdPRepresentation = {}
    newIdPRepresentation["alias"] = module.params.get('alias')
    if module.params.get('displayName') is not None:
        newIdPRepresentation["displayName"] = module.params.get('displayName')
    newIdPRepresentation["providerId"] = module.params.get('providerId')
    newIdPRepresentation["enabled"] = module.params.get('enabled')
    if module.params.get('updateProfileFirstLoginMode') is not None:
        newIdPRepresentation[
            "updateProfileFirstLoginMode"] = module.params.get(
                'updateProfileFirstLoginMode')
    if module.params.get('trustEmail') is not None:
        newIdPRepresentation["trustEmail"] = module.params.get('trustEmail')
    if module.params.get('storeToken') is not None:
        newIdPRepresentation["storeToken"] = module.params.get('storeToken')
    if module.params.get('addReadTokenRoleOnCreate') is not None:
        newIdPRepresentation["addReadTokenRoleOnCreate"] = module.params.get(
            'addReadTokenRoleOnCreate')
    if module.params.get("authenticateByDefault") is not None:
        newIdPRepresentation["authenticateByDefault"] = module.params.get(
            'authenticateByDefault')
    if module.params.get('firstBrokerLoginFlowAlias') is not None:
        newIdPRepresentation["firstBrokerLoginFlowAlias"] = module.params.get(
            'firstBrokerLoginFlowAlias')
    if module.params.get('postBrokerLoginFlowAlias') is not None:
        newIdPRepresentation["postBrokerLoginFlowAlias"] = module.params.get(
            'postBrokerLoginFlowAlias')

    newIdPConfig = None
    if module.params.get('config') is not None:
        newIdPConfig = remove_arguments_with_value_none(
            module.params.get('config'))
        if 'openIdConfigurationUrl' in newIdPConfig:
            del (newIdPConfig['openIdConfigurationUrl'])

    if 'providerId' in newIdPRepresentation and newIdPRepresentation[
            "providerId"] == 'google' and 'userIp' in module.params.get(
                "config"):
        newIdPConfig["userIp"] = module.params.get("config")["userIp"]

    newIdPMappers = remove_arguments_with_value_none(
        module.params.get('mappers'))

    if newIdPConfig is not None:
        if (module.params.get('config') is not None
                and 'openIdConfigurationUrl' in module.params.get('config')
                and module.params.get("config")['openIdConfigurationUrl']
                is not None):
            kc.add_idp_endpoints(
                newIdPConfig,
                module.params.get("config")['openIdConfigurationUrl'])
        newIdPRepresentation["config"] = newIdPConfig

    # Search the Idp on Keycloak server.
    # By its alias
    idPRepresentation = kc.search_idp_by_alias(
        alias=newIdPRepresentation["alias"], realm=realm)

    if idPRepresentation == {}:  # IdP does not exist on Keycloak server
        if (state == 'present'):  # If desired state is present
            # Create IdP
            changed = True
            idPRepresentation = kc.create_idp(
                newIdPRepresentation=newIdPRepresentation, realm=realm)
            result["idp"] = idPRepresentation
            if newIdPMappers is not None and len(newIdPMappers) > 0:
                kc.create_or_update_idp_mappers(
                    alias=newIdPRepresentation["alias"],
                    idPMappers=newIdPMappers,
                    realm=realm)
            mappersRepresentation = kc.get_idp_mappers(
                alias=newIdPRepresentation["alias"], realm=realm)
            result["mappers"] = mappersRepresentation
        else:  # Sinon, le status est absent
            result["msg"] = newIdPRepresentation["alias"] + ' absent'
    else:  # if IdP already exists
        alias = idPRepresentation['alias']
        if (state == 'present'):  # if desired state is present
            if force:  # If force option is true
                # Delete all idp's mappers
                kc.delete_all_idp_mappers(alias=alias, realm=realm)
                # Delete the existing IdP
                kc.delete_idp(alias=alias, realm=realm)
                # Re-create the IdP
                idPRepresentation = kc.create_idp(
                    newIdPRepresentation=newIdPRepresentation, realm=realm)
                changed = True
            else:  # if force option is false
                # Compare the new Idp with the existing IdP
                if (not isDictEquals(
                        newIdPRepresentation, idPRepresentation,
                    ["clientSecret", "openIdConfigurationUrl", "mappers"]) or
                    ("config" in newIdPRepresentation
                     and "clientSecret" in newIdPRepresentation["config"]
                     and newIdPRepresentation["config"]["clientSecret"]
                     is not None)):
                    # If they are different
                    # Create an updated representation of the IdP
                    updatedIdP = copy.deepcopy(idPRepresentation)
                    updatedIdP.update(newIdPRepresentation)
                    if "config" in newIdPRepresentation and newIdPRepresentation[
                            "config"] is not None:
                        updatedConfig = idPRepresentation["config"]
                        updatedConfig.update(newIdPRepresentation["config"])
                        updatedIdP["config"] = updatedConfig
                    # Update the IdP
                    idPRepresentation = kc.update_idp(
                        newIdPRepresentation=updatedIdP, realm=realm)
                    changed = True
            if newIdPMappers is not None and len(newIdPMappers) > 0:
                if kc.create_or_update_idp_mappers(
                        alias=newIdPRepresentation["alias"],
                        idPMappers=newIdPMappers,
                        realm=realm):
                    changed = True
            mappersRepresentation = kc.get_idp_mappers(
                alias=newIdPRepresentation["alias"], realm=realm)
            result["idp"] = idPRepresentation
            result["mappers"] = mappersRepresentation
        else:  # If desired state is absent
            # Delete all idp's mappers
            kc.delete_all_idp_mappers(alias=alias, realm=realm)
            # Delete the existing IdP
            kc.delete_idp(alias=alias, realm=realm)
            changed = True
            result["msg"] = 'IdP %s is deleted' % (alias)

    result["changed"] = changed
    module.exit_json(**result)
Beispiel #4
0
def main():
    argument_spec = keycloak_argument_spec()

    client_role_spec = dict(
        clientId=dict(type='str', required=True),
        roles=dict(type='list', elements='str', required=True),
    )
    meta_args = dict(
        realm=dict(type='str', default='master'),
        self=dict(type='str'),
        id=dict(type='str'),
        username=dict(type='str', required=True),
        firstName=dict(type='str'),
        lastName=dict(type='str'),
        email=dict(type='str'),
        enabled=dict(type='bool', default=True),
        emailVerified=dict(type='bool', default=False),
        federationLink=dict(type='str'),
        serviceAccountClientId=dict(type='str'),
        attributes=dict(type='dict'),
        access=dict(type='dict'),
        clientRoles=dict(type='list',
                         elements='dict',
                         default=[],
                         options=client_role_spec),
        realmRoles=dict(type='list', elements='str', default=[]),
        groups=dict(type='list', elements='str', default=[]),
        disableableCredentialTypes=dict(type='list',
                                        elements='str',
                                        default=[]),
        requiredActions=dict(type='list', elements='str', default=[]),
        credentials=dict(type='list', elements='dict', default=[]),
        federatedIdentities=dict(type='list', elements='str', default=[]),
        clientConsents=dict(type='list', elements='dict', default=[]),
        origin=dict(type='str'),
        state=dict(choices=["absent", "present"], default='present'),
        force=dict(type='bool', default=False),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', user={})

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    force = module.params.get('force')
    # Create a representation of the user received in parameters
    newUserRepresentation = {}
    newUserClientRolesRepresentation = {}
    newUserRepresentation["username"] = module.params.get('username')
    if module.params.get('self') is not None:
        newUserRepresentation["self"] = module.params.get('self')
    if module.params.get('id') is not None:
        newUserRepresentation["id"] = module.params.get('id')
    newUserRepresentation["enabled"] = module.params.get('enabled')
    newUserRepresentation["emailVerified"] = module.params.get('emailVerified')
    if module.params.get('firstName') is not None:
        newUserRepresentation["firstName"] = module.params.get('firstName')
    if module.params.get('lastName') is not None:
        newUserRepresentation["lastName"] = module.params.get('lastName')
    if module.params.get('email') is not None:
        newUserRepresentation["email"] = module.params.get('email')
    if module.params.get('federationLink') is not None:
        newUserRepresentation["federationLink"] = module.params.get(
            'federationLink')
    if module.params.get('serviceAccountClientId') is not None:
        newUserRepresentation["serviceAccountClientId"] = module.params.get(
            'serviceAccountClientId')
    if module.params.get('origin') is not None:
        newUserRepresentation["origin"] = module.params.get('origin')
    if module.params.get('credentials') is not None:
        newUserRepresentation["credentials"] = module.params.get('credentials')
    if module.params.get('disableableCredentialTypes') is not None:
        newUserRepresentation[
            "disableableCredentialTypes"] = module.params.get(
                'disableableCredentialTypes')
    if module.params.get('federatedIdentities') is not None:
        newUserRepresentation["federatedIdentities"] = module.params.get(
            'federatedIdentities')
    if module.params.get('requiredActions') is not None:
        newUserRepresentation["requiredActions"] = module.params.get(
            'requiredActions')
    if module.params.get('clientConsents') is not None:
        newUserRepresentation["clientConsents"] = module.params.get(
            'clientConsents')
    if module.params.get('attributes') is not None:
        newUserRepresentation["attributes"] = module.params.get('attributes')
    if module.params.get('access') is not None:
        newUserRepresentation["access"] = module.params.get('access')
    if module.params.get('clientRoles') is not None:
        newUserClientRolesRepresentation["clientRoles"] = module.params.get(
            'clientRoles')
    if module.params.get('realmRoles') is not None:
        newUserRepresentation["realmRoles"] = module.params.get('realmRoles')
    if module.params.get('groups') is not None:
        newUserRepresentation["groups"] = module.params.get('groups')

    changed = False
    userRepresentation = kc.search_user_by_username(
        username=newUserRepresentation["username"], realm=realm)

    if userRepresentation == {}:  # The user does not exist
        # Create the user
        if (state == 'present'):  # If state is present
            # Create the user
            userRepresentation = kc.create_user(
                newUserRepresentation=newUserRepresentation, realm=realm)
            # Add user ID to new representation
            newUserRepresentation['id'] = userRepresentation["id"]
            # Assign roles to user
            kc.assing_roles_to_user(
                user_id=newUserRepresentation["id"],
                userRealmRoles=newUserRepresentation['realmRoles'],
                userClientRoles=newUserClientRolesRepresentation[
                    'clientRoles'],
                realm=realm)
            # set user groups
            kc.update_user_groups_membership(
                newUserRepresentation=newUserRepresentation, realm=realm)
            # Get the updated user realm roles
            userRepresentation["realmRoles"] = kc.get_user_realm_roles(
                user_id=userRepresentation["id"], realm=realm)
            # Get the user clientRoles
            userRepresentation["clientRoles"] = kc.get_user_client_roles(
                user_id=userRepresentation["id"], realm=realm)
            # Get the user groups
            userRepresentation["groups"] = kc.get_user_groups(
                user_id=userRepresentation["id"], realm=realm)
            changed = True
            result["user"] = userRepresentation
        elif state == 'absent':  # Otherwise, the status is absent
            result["msg"] = 'User %s is absent' % (
                newUserRepresentation["username"])

    else:  # the user already exists
        if (state == 'present'):  # if desired state is present
            if force:  # If the force option is set to true
                # Delete the existing user
                kc.delete_user(user_id=userRepresentation["id"], realm=realm)
                changed = True
                # Recreate the user
                userRepresentation = kc.create_user(
                    newUserRepresentation=newUserRepresentation, realm=realm)
                # Add user ID to new representation
                newUserRepresentation['id'] = userRepresentation["id"]
            else:  # If the force option is false
                excludes = [
                    "access", "notBefore", "createdTimestamp", "totp",
                    "credentials", "disableableCredentialTypes", "realmRoles",
                    "clientRoles", "groups", "clientConsents",
                    "federatedIdentities", "requiredActions"
                ]
                # Add user ID to new representation
                newUserRepresentation['id'] = userRepresentation["id"]
                # Compare users
                if not (
                        isDictEquals(newUserRepresentation, userRepresentation,
                                     excludes)
                ):  # If the new user does not introduce a change to the existing user
                    # Update the user
                    userRepresentation = kc.update_user(
                        newUserRepresentation=newUserRepresentation,
                        realm=realm)
                    changed = True
            # Assign roles to user
            if kc.assing_roles_to_user(
                    user_id=newUserRepresentation["id"],
                    userRealmRoles=newUserRepresentation['realmRoles'],
                    userClientRoles=newUserClientRolesRepresentation[
                        'clientRoles'],
                    realm=realm):
                changed = True
            # set user groups
            if kc.update_user_groups_membership(
                    newUserRepresentation=newUserRepresentation, realm=realm):
                changed = True
            # Get the updated user realm roles
            userRepresentation["realmRoles"] = kc.get_user_realm_roles(
                user_id=userRepresentation["id"], realm=realm)
            # Get the user clientRoles
            userRepresentation["clientRoles"] = kc.get_user_client_roles(
                user_id=userRepresentation["id"], realm=realm)
            # Get the user groups
            userRepresentation["groups"] = kc.get_user_groups(
                user_id=userRepresentation["id"], realm=realm)
            result["user"] = userRepresentation
        elif state == 'absent':  # Status is absent
            # Delete user
            kc.delete_user(user_id=userRepresentation['id'], realm=realm)
            result["msg"] = 'User %s deleted' % (userRepresentation['id'])
            changed = True

    result['changed'] = changed
    module.exit_json(**result)
Beispiel #5
0
def main():
    """
    Module execution

    :return:
    """
    argument_spec = keycloak_argument_spec()
    meta_args = dict(
        state=dict(default='present', choices=['present', 'absent']),
        realm=dict(default='master'),
        id=dict(type='str'),
        name=dict(type='str'),
        attributes=dict(type='dict'),
        path=dict(type='str'),
        attributes_list=dict(type='list', elements='dict'),
        realmRoles=dict(type='list', elements='str'),
        clientRoles=dict(type='list', elements='dict'),
        syncLdapMappers=dict(type='bool', default=False),
        force=dict(type='bool', default=False),
    )

    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=([['id', 'name']]))

    result = dict(changed=False, msg='', diff={}, group='')

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    gid = module.params.get('id')
    name = module.params.get('name')
    attributes = module.params.get('attributes')
    # Add attribute received as a list to the attributes dict
    kc.add_attributes_list_to_attributes_dict(
        module.params.get('attributes_list'), attributes)
    syncLdapMappers = module.params.get('syncLdapMappers')
    groupRealmRoles = module.params.get('realmRoles')
    groupClientRoles = module.params.get('clientRoles')
    force = module.params.get('force')

    before_group = None  # current state of the group, for merging.

    # Synchronize LDAP group to Keycloak if syncLdapMappers is true
    if syncLdapMappers:
        kc.sync_ldap_groups("fedToKeycloak", realm=realm)
    # does the group already exist?
    if gid is None:
        before_group = kc.get_group_by_name(name, realm=realm)
    else:
        before_group = kc.get_group_by_groupid(gid, realm=realm)

    before_group = {} if before_group is None else before_group

    # attributes in Keycloak have their values returned as lists
    # via the API. attributes is a dict, so we'll transparently convert
    # the values to lists.
    if attributes is not None:
        for key, val in module.params['attributes'].items():
            module.params['attributes'][key] = [
                val
            ] if not isinstance(val, list) else val
    excludes = [
        'state', 'realm', 'force', 'attributes_list', 'realmRoles',
        'clientRoles', 'syncLdapMappers'
    ]
    group_params = [
        x for x in module.params
        if x not in list(keycloak_argument_spec().keys()) +
        excludes and module.params.get(x) is not None
    ]
    # build a changeset
    changeset = {}
    for param in group_params:
        new_param_value = module.params.get(param)
        old_value = before_group[param] if param in before_group else None
        if new_param_value != old_value:
            changeset[camel(param)] = new_param_value

    # prepare the new group
    updated_group = before_group.copy()
    updated_group.update(changeset)

    # if before_group is none, the group doesn't exist.
    if before_group == {}:
        if state == 'absent':
            # nothing to do.
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['msg'] = 'Group does not exist; doing nothing.'
            result['group'] = dict()
            module.exit_json(**result)

        # for 'present', create a new group.
        result['changed'] = True
        if name is None:
            module.fail_json(
                msg='name must be specified when creating a new group')

        if module._diff:
            result['diff'] = dict(before='', after=updated_group)

        if module.check_mode:
            module.exit_json(**result)

        # do it for real!
        kc.create_group(updated_group, realm=realm)
        # Assing roles to group
        kc.assing_roles_to_group(groupRepresentation=updated_group,
                                 groupRealmRoles=groupRealmRoles,
                                 groupClientRoles=groupClientRoles,
                                 realm=realm)
        # Sync Keycloak groups to User Storages if syncLdapMappers is true
        if syncLdapMappers:
            kc.sync_ldap_groups("keycloakToFed", realm=realm)

        after_group = kc.get_group_by_name(name, realm)

        result['group'] = after_group
        result['msg'] = 'Group {name} has been created with ID {id}'.format(
            name=after_group['name'], id=after_group['id'])

    else:
        if state == 'present':
            # no changes
            if updated_group == before_group and not force:
                result['changed'] = False
                result['group'] = updated_group
                result['msg'] = "No changes required to group {name}.".format(
                    name=before_group['name'])
                module.exit_json(**result)

            # update the existing group
            result['changed'] = True

            if module._diff:
                result['diff'] = dict(before=before_group, after=updated_group)

            if module.check_mode:
                module.exit_json(**result)

            if force:
                # delete for real
                gid = before_group['id']
                kc.delete_group(groupid=gid, realm=realm)
                # remove id
                del (updated_group['id'])
                if "realmRoles" in updated_group:
                    del (updated_group['realmRoles'])
                if "clientRoles" in updated_group:
                    del (updated_group['clientRoles'])

                # create it again
                kc.create_group(updated_group, realm=realm)
            else:
                # do the update
                kc.update_group(updated_group, realm=realm)
            # Assing roles to group
            kc.assing_roles_to_group(groupRepresentation=updated_group,
                                     groupRealmRoles=groupRealmRoles,
                                     groupClientRoles=groupClientRoles,
                                     realm=realm)
            # Sync Keycloak groups to User Storages if syncLdapMappers is true
            if syncLdapMappers:
                kc.sync_ldap_groups("keycloakToFed", realm=realm)

            if force:
                after_group = kc.get_group_by_name(name, realm)
            else:
                after_group = kc.get_group_by_groupid(updated_group['id'],
                                                      realm=realm)

            result['group'] = after_group
            result['msg'] = "Group {id} has been updated".format(
                id=after_group['id'])

            module.exit_json(**result)

        elif state == 'absent':
            result['group'] = dict()

            if module._diff:
                result['diff'] = dict(before=before_group, after='')

            if module.check_mode:
                module.exit_json(**result)

            # delete for real
            gid = before_group['id']
            kc.delete_group(groupid=gid, realm=realm)
            # Sync Keycloak groups to User Storages if syncLdapMappers is true
            if syncLdapMappers:
                kc.sync_ldap_groups("keycloakToFed", realm=realm)

            result['changed'] = True
            result['msg'] = "Group {name} has been deleted".format(
                name=before_group['name'])

            module.exit_json(**result)

    module.exit_json(**result)
Beispiel #6
0
def main():
    argument_spec = keycloak_argument_spec()
    smtp_spec = {
        "replyToDisplayName": {
            "type": "str"
        },
        "starttls": {
            "type": "str",
            "choices": ["true", "false"],
            "default": "false"
        },
        "auth": {
            "type": "str",
            "choices": ["true", "false"],
            "default": "false"
        },
        "port": {
            "type": "str",
            "default": "25"
        },
        "host": {
            "type": "str"
        },
        "replyTo": {
            "type": "str"
        },
        "from": {
            "type": "str"
        },
        "fromDisplayName": {
            "type": "str"
        },
        "envelopeFrom": {
            "type": "str"
        },
        "ssl": {
            "type": "str",
            "choices": ["true", "false"],
            "default": "false"
        },
        "user": {
            "type": "str"
        },
        "password": {
            "type": "str",
            "no_log": True
        }
    }
    eventconfig_spec = {
        "eventsEnabled": {
            "type": "bool"
        },
        "eventsListeners": {
            "type": "list",
            "elements": "str"
        },
        "adminEventsEnabled": {
            "type": "bool"
        },
        "adminEventsDetailsEnabled": {
            "type": "bool"
        },
        "eventsExpiration": {
            "type": "int"
        },
        "enabledEventTypes": {
            "type":
            "list",
            "elements":
            "str",
            "choices": [
                "SEND_RESET_PASSWORD", "UPDATE_TOTP", "REMOVE_TOTP",
                "REVOKE_GRANT", "LOGIN_ERROR", "CLIENT_LOGIN",
                "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR",
                "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION",
                "UPDATE_PROFILE_ERROR", "IMPERSONATE", "LOGIN",
                "UPDATE_PASSWORD_ERROR", "REGISTER", "LOGOUT",
                "CLIENT_REGISTER", "UPDATE_PASSWORD",
                "FEDERATED_IDENTITY_LINK_ERROR", "CLIENT_DELETE",
                "IDENTITY_PROVIDER_FIRST_LOGIN", "VERIFY_EMAIL",
                "CLIENT_DELETE_ERROR", "CLIENT_LOGIN_ERROR",
                "REMOVE_FEDERATED_IDENTITY_ERROR", "EXECUTE_ACTIONS",
                "SEND_IDENTITY_PROVIDER_LINK_ERROR", "SEND_VERIFY_EMAIL",
                "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY",
                "IDENTITY_PROVIDER_POST_LOGIN", "UPDATE_EMAIL",
                "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "LOGOUT_ERROR",
                "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "UPDATE_PROFILE",
                "FEDERATED_IDENTITY_LINK", "CLIENT_REGISTER_ERROR",
                "SEND_VERIFY_EMAIL_ERROR", "SEND_IDENTITY_PROVIDER_LINK",
                "RESET_PASSWORD", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR",
                "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE",
                "IDENTITY_PROVIDER_POST_LOGIN_ERROR",
                "CUSTOM_REQUIRED_ACTION_ERROR", "UPDATE_TOTP_ERROR",
                "CODE_TO_TOKEN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR"
            ]
        }
    }
    meta_args = dict(
        accessCodeLifespan=dict(type='int', default=60),
        accessCodeLifespanLogin=dict(type='int', default=1800),
        accessCodeLifespanUserAction=dict(type='int', default=300),
        accountTheme=dict(type="str"),
        accessTokenLifespan=dict(type='int', default=300),
        accessTokenLifespanForImplicitFlow=dict(type='int', default=900),
        actionTokenGeneratedByAdminLifespan=dict(type='int', default=43200),
        actionTokenGeneratedByUserLifespan=dict(type='int', default=300),
        adminTheme=dict(type="str"),
        attributes=dict(type='dict', default=None),
        browserSecurityHeaders=dict(type='dict', default=None),
        browserFlow=dict(type='str', default="browser"),
        bruteForceProtected=dict(type='bool', default=False),
        clientAuthenticationFlow=dict(type='str', default="clients"),
        defaultLocale=dict(type="str"),
        defaultRoles=dict(type='list',
                          elements='str',
                          default=["offline_access", "uma_authorization"]),
        directGrantFlow=dict(type='str', default="direct grant"),
        displayName=dict(type='str', required=True, aliases=['name']),
        displayNameHtml=dict(type='str', required=True, aliases=['namehtml']),
        duplicateEmailsAllowed=dict(type='bool', default=False),
        editUsernameAllowed=dict(type='bool', default=False),
        emailTheme=dict(type="str"),
        enabled=dict(type='bool', default=True),
        eventsConfig=dict(type='dict', options=eventconfig_spec),
        failureFactor=dict(type='int', default=30),
        force=dict(type='bool', default=False),
        internationalizationEnabled=dict(type="bool"),
        loginTheme=dict(type="str"),
        loginWithEmailAllowed=dict(type='bool', default=True),
        maxDeltaTimeSeconds=dict(type='int', default=43200),
        maxFailureWaitSeconds=dict(type='int', default=900),
        minimumQuickLoginWaitSeconds=dict(type='int', default=60),
        notBefore=dict(type='int', default=0),
        offlineSessionIdleTimeout=dict(type='int', default=2592000),
        otpPolicyAlgorithm=dict(type='str', default="HmacSHA1"),
        otpPolicyDigits=dict(type='int', default=6),
        otpPolicyInitialCounter=dict(type='int', default=0),
        otpPolicyLookAheadWindow=dict(type='int', default=1),
        otpPolicyPeriod=dict(type='int', default=30),
        otpPolicyType=dict(type='str', default="totp"),
        passwordPolicy=dict(type='str', default="hashIterations(20000)"),
        permanentLockout=dict(type='bool', default=False),
        quickLoginCheckMilliSeconds=dict(type='int', default=1000),
        realm=dict(type='str', default='master'),
        registrationAllowed=dict(type='bool', default=False),
        registrationEmailAsUsername=dict(type='bool', default=False),
        registrationFlow=dict(type='str', default="registration"),
        rememberMe=dict(type='bool', default=False),
        requiredCredentials=dict(type='list',
                                 elements='str',
                                 default=["password"]),
        resetCredentialsFlow=dict(type='str', default="reset credentials"),
        resetPasswordAllowed=dict(type='bool', default=False),
        revokeRefreshToken=dict(type='bool', default=False),
        smtpServer=dict(type='dict', default={}, options=smtp_spec),
        sslRequired=dict(type='str', default="external"),
        ssoSessionIdleTimeout=dict(type='int', default=1800),
        ssoSessionMaxLifespan=dict(type='int', default=36000),
        state=dict(choices=["absent", "present"], default='present'),
        supportedLocales=dict(type="list", elements="str"),
        verifyEmail=dict(type='bool', default=False),
        waitIncrementSeconds=dict(type='int', default=60),
    )

    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', realm={}, eventsConfig={})

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    #    defaultAttributes = dict(
    #        _browser_header=dict(
    #            contentSecurityPolicy=dict(type='unicode', default="frame-src 'self'"),
    #            xContentTypeOptions=dict(type='unicode', default="nosniff"),
    #            xFrameOptions=dict(type='unicode', default="SAMEORIGIN"),
    #            xRobotsTag=dict(type='unicode', default="none"),
    #            xXSSProtection=dict(type='unicode', default="1; mode=block")
    #        ),
    #        actionTokenGeneratedByAdminLifespan=dict(type='int', default=43200),
    #        actionTokenGeneratedByUserLifespan=dict(type='int', default=300),
    #        displayName=dict(type='unicode', default=module.params.get('name')),
    #        displayNameHtml=dict(type='unicode', default=module.params.get('namehtml')),
    #    )
    #    defaultBrowserSecurityHeaders = dict(
    #        contentSecurityPolicy=dict(type='unicode', default="frame-src 'self'"),
    #        xContentTypeOptions=dict(type='unicode', default="nosniff"),
    #        xFrameOptions=dict(type='unicode', default="SAMEORIGIN"),
    #        xRobotsTag=dict(type='unicode', default="none"),
    #        xXSSProtection=dict(type='unicode', default="1; mode=block")
    #    )

    state = module.params.get('state')
    force = module.params.get('force')

    # Create a realm representation form module parameters
    newRealmRepresentation = {}
    newRealmRepresentation["id"] = module.params.get('realm')
    newRealmRepresentation["realm"] = module.params.get('realm')
    newRealmRepresentation["displayName"] = module.params.get('displayName')
    newRealmRepresentation["displayNameHtml"] = module.params.get(
        'displayNameHtml')
    if module.params.get("loginTheme") is not None:
        newRealmRepresentation["loginTheme"] = module.params.get("loginTheme")
    if module.params.get("adminTheme") is not None:
        newRealmRepresentation["adminTheme"] = module.params.get("adminTheme")
    if module.params.get("emailTheme") is not None:
        newRealmRepresentation["emailTheme"] = module.params.get("emailTheme")
    if module.params.get("accountTheme") is not None:
        newRealmRepresentation["accountTheme"] = module.params.get(
            "accountTheme")
    newRealmRepresentation["accessCodeLifespan"] = module.params.get(
        'accessCodeLifespan')
    newRealmRepresentation["accessCodeLifespanLogin"] = module.params.get(
        'accessCodeLifespanLogin')
    newRealmRepresentation["accessCodeLifespanUserAction"] = module.params.get(
        'accessCodeLifespanUserAction')
    newRealmRepresentation[
        "actionTokenGeneratedByAdminLifespan"] = module.params.get(
            'actionTokenGeneratedByAdminLifespan')
    newRealmRepresentation[
        "actionTokenGeneratedByUserLifespan"] = module.params.get(
            'actionTokenGeneratedByUserLifespan')
    newRealmRepresentation["notBefore"] = module.params.get('notBefore')
    newRealmRepresentation["revokeRefreshToken"] = module.params.get(
        'revokeRefreshToken')
    newRealmRepresentation["accessTokenLifespan"] = module.params.get(
        'accessTokenLifespan')
    newRealmRepresentation[
        "accessTokenLifespanForImplicitFlow"] = module.params.get(
            'accessTokenLifespanForImplicitFlow')
    newRealmRepresentation["ssoSessionIdleTimeout"] = module.params.get(
        'ssoSessionIdleTimeout')
    newRealmRepresentation["ssoSessionMaxLifespan"] = module.params.get(
        'ssoSessionMaxLifespan')
    newRealmRepresentation["offlineSessionIdleTimeout"] = module.params.get(
        'offlineSessionIdleTimeout')
    newRealmRepresentation["enabled"] = module.params.get('enabled')
    newRealmRepresentation["sslRequired"] = module.params.get('sslRequired')
    newRealmRepresentation["registrationAllowed"] = module.params.get(
        'registrationAllowed')
    newRealmRepresentation["registrationEmailAsUsername"] = module.params.get(
        'registrationEmailAsUsername')
    newRealmRepresentation["rememberMe"] = module.params.get('rememberMe')
    newRealmRepresentation["verifyEmail"] = module.params.get('verifyEmail')
    newRealmRepresentation["loginWithEmailAllowed"] = module.params.get(
        'loginWithEmailAllowed')
    newRealmRepresentation["duplicateEmailsAllowed"] = module.params.get(
        'duplicateEmailsAllowed')
    newRealmRepresentation["resetPasswordAllowed"] = module.params.get(
        'resetPasswordAllowed')
    newRealmRepresentation["editUsernameAllowed"] = module.params.get(
        'editUsernameAllowed')
    newRealmRepresentation["bruteForceProtected"] = module.params.get(
        'bruteForceProtected')
    newRealmRepresentation["permanentLockout"] = module.params.get(
        'permanentLockout')
    newRealmRepresentation["maxFailureWaitSeconds"] = module.params.get(
        'maxFailureWaitSeconds')
    newRealmRepresentation["minimumQuickLoginWaitSeconds"] = module.params.get(
        'minimumQuickLoginWaitSeconds')
    newRealmRepresentation["waitIncrementSeconds"] = module.params.get(
        'waitIncrementSeconds')
    newRealmRepresentation["quickLoginCheckMilliSeconds"] = module.params.get(
        'quickLoginCheckMilliSeconds')
    newRealmRepresentation["maxDeltaTimeSeconds"] = module.params.get(
        'maxDeltaTimeSeconds')
    newRealmRepresentation["failureFactor"] = module.params.get(
        'failureFactor')
    newRealmRepresentation["defaultRoles"] = module.params.get('defaultRoles')
    newRealmRepresentation["requiredCredentials"] = module.params.get(
        'requiredCredentials')
    newRealmRepresentation["passwordPolicy"] = module.params.get(
        'passwordPolicy')
    newRealmRepresentation["otpPolicyType"] = module.params.get(
        'otpPolicyType')
    newRealmRepresentation["otpPolicyAlgorithm"] = module.params.get(
        'otpPolicyAlgorithm')
    newRealmRepresentation["otpPolicyInitialCounter"] = module.params.get(
        'otpPolicyInitialCounter')
    newRealmRepresentation["otpPolicyDigits"] = module.params.get(
        'otpPolicyDigits')
    newRealmRepresentation["otpPolicyLookAheadWindow"] = module.params.get(
        'otpPolicyLookAheadWindow')
    newRealmRepresentation["otpPolicyPeriod"] = module.params.get(
        'otpPolicyPeriod')
    newRealmRepresentation["smtpServer"] = remove_arguments_with_value_none(
        module.params.get('smtpServer'))
    if module.params.get("supportedLocales") is not None:
        if module.params.get("internationalizationEnabled") is not None:
            newRealmRepresentation[
                "internationalizationEnabled"] = module.params.get(
                    "internationalizationEnabled")
        else:
            newRealmRepresentation["internationalizationEnabled"] = True
        newRealmRepresentation["supportedLocales"] = module.params.get(
            "supportedLocales")
        if module.params.get("defaultLocale") is not None:
            newRealmRepresentation["defaultLocale"] = module.params.get(
                "defaultLocale")
    else:
        newRealmRepresentation["internationalizationEnabled"] = False
    newRealmRepresentation["browserFlow"] = module.params.get('browserFlow')
    newRealmRepresentation["registrationFlow"] = module.params.get(
        'registrationFlow')
    newRealmRepresentation["directGrantFlow"] = module.params.get(
        'directGrantFlow')
    newRealmRepresentation["resetCredentialsFlow"] = module.params.get(
        'resetCredentialsFlow')
    newRealmRepresentation["clientAuthenticationFlow"] = module.params.get(
        'clientAuthenticationFlow')
    if module.params.get("eventsExpiration") is not None:
        newRealmRepresentation["eventsExpiration"] = module.params.get(
            'eventsExpiration')
    # Read Events configuration for the Realm
    newEventsConfig = remove_arguments_with_value_none(
        module.params.get("eventsConfig"))
    if module.params.get("browserSecurityHeaders") is not None:
        newRealmRepresentation["browserSecurityHeaders"] = module.params.get(
            "browserSecurityHeaders")

    changed = False
    # Find realm on Keycloak server
    realmRepresentation = kc.search_realm(
        realm=newRealmRepresentation["realm"])
    if realmRepresentation == {}:  # Realm does not exist
        if (state == 'present'):  # If desired state is present
            # Create the realm
            result["realm"] = kc.create_realm(
                newRealmRepresentation=newRealmRepresentation)
            if newEventsConfig is not None:
                eventsConfig = kc.update_realm_events_config(
                    realm=newRealmRepresentation["realm"],
                    newEventsConfig=newEventsConfig)
                result["eventsConfig"] = eventsConfig
            changed = True
        else:  # if desired state is absent
            result['msg'] = 'Realm %s is absent' % (
                newRealmRepresentation["realm"])

    else:  # Realm already exists
        if (state == 'present'):  # If desired state is present
            if force:  # If force option is true
                # Delete the existing realm
                kc.delete_realm(newRealmRepresentation["realm"])
                # Create realm
                realmRepresentation = kc.create_realm(
                    newRealmRepresentation=newRealmRepresentation)
                changed = True
            else:  # If force option is false
                # Compare realms
                if not isDictEquals(newRealmRepresentation, realmRepresentation
                                    ):  # If new realm introduces changes
                    # Update REALM
                    realmRepresentation = kc.update_realm(
                        newRealmRepresentation=newRealmRepresentation)
                    changed = True
                else:
                    realmRepresentation = kc.get_realm(
                        realm=newRealmRepresentation["realm"])
            if newEventsConfig is not None:  # If there is event configuration
                # Get the existing events config
                eventsConfig = kc.get_realm_events_config(
                    realm=newRealmRepresentation["realm"])
                if not isDictEquals(newEventsConfig,
                                    eventsConfig):  # If realm needs changed
                    # Update event config
                    eventsConfig = kc.update_realm_events_config(
                        realm=newRealmRepresentation["realm"],
                        newEventsConfig=newEventsConfig)
                result["eventsConfig"] = eventsConfig
            result["realm"] = realmRepresentation
        else:  # If desired state is absent
            # Delete Realm
            kc.delete_realm(newRealmRepresentation["realm"])
            changed = True
            result["msg"] = 'Realm %s deleted' % (
                newRealmRepresentation["realm"])
    result["changed"] = changed
    module.exit_json(**result)
Beispiel #7
0
def main():
    """
    Module execution

    :return:
    """
    argument_spec = keycloak_argument_spec()

    protmapper_spec = dict(
        consentRequired=dict(type='bool'),
        consentText=dict(type='str'),
        id=dict(type='str'),
        name=dict(type='str'),
        protocol=dict(type='str', choices=['openid-connect', 'saml']),
        protocolMapper=dict(type='str'),
        config=dict(type='dict'),
        state=dict(type='str',
                   choices=['absent', 'present'],
                   default='present'),
    )
    clientrolecomposites_spec = dict(
        name=dict(type='str'),
        id=dict(type='str'),
    )
    clientroles_spec = dict(
        name=dict(type='str'),
        description=dict(type='str'),
        composite=dict(type='bool'),
        composites=dict(type='list',
                        elements='dict',
                        options=clientrolecomposites_spec),
        state=dict(type='str',
                   choices=['absent', 'present'],
                   default='present'),
    )
    realmscopemappings_spec = dict(name=dict(type='str'),
                                   state=dict(type='str',
                                              choices=['absent', 'present'],
                                              default='present'))
    clientrolescopemappings_spec = dict(name=dict(type='str'),
                                        state=dict(
                                            type='str',
                                            choices=['absent', 'present'],
                                            default='present'))
    clientsscopemappings_spec = dict(id=dict(type='str'),
                                     roles=dict(
                                         type='list',
                                         elements='dict',
                                         options=clientrolescopemappings_spec))
    scopemappings_spec = dict(realm=dict(type='list',
                                         elements='dict',
                                         options=realmscopemappings_spec),
                              clients=dict(type='list',
                                           elements='dict',
                                           options=clientsscopemappings_spec))
    meta_args = dict(
        state=dict(default='present', choices=['present', 'absent']),
        realm=dict(type='str', default='master'),
        id=dict(type='str'),
        client_id=dict(type='str', aliases=['clientId']),
        name=dict(type='str'),
        description=dict(type='str'),
        root_url=dict(type='str', aliases=['rootUrl']),
        admin_url=dict(type='str', aliases=['adminUrl']),
        base_url=dict(type='str', aliases=['baseUrl']),
        surrogate_auth_required=dict(type='bool',
                                     aliases=['surrogateAuthRequired']),
        enabled=dict(type='bool'),
        client_authenticator_type=dict(type='str',
                                       choices=['client-secret', 'client-jwt'],
                                       aliases=['clientAuthenticatorType']),
        secret=dict(type='str', no_log=True),
        registration_access_token=dict(type='str',
                                       aliases=['registrationAccessToken']),
        default_roles=dict(type='list',
                           elements='str',
                           aliases=['defaultRoles']),
        redirect_uris=dict(type='list',
                           elements='str',
                           aliases=['redirectUris']),
        web_origins=dict(type='list', elements='str', aliases=['webOrigins']),
        not_before=dict(type='int', aliases=['notBefore']),
        bearer_only=dict(type='bool', aliases=['bearerOnly']),
        consent_required=dict(type='bool', aliases=['consentRequired']),
        standard_flow_enabled=dict(type='bool',
                                   aliases=['standardFlowEnabled']),
        implicit_flow_enabled=dict(type='bool',
                                   aliases=['implicitFlowEnabled']),
        direct_access_grants_enabled=dict(
            type='bool', aliases=['directAccessGrantsEnabled']),
        service_accounts_enabled=dict(type='bool',
                                      aliases=['serviceAccountsEnabled']),
        authorization_services_enabled=dict(
            type='bool', aliases=['authorizationServicesEnabled']),
        public_client=dict(type='bool', aliases=['publicClient']),
        frontchannel_logout=dict(type='bool', aliases=['frontchannelLogout']),
        protocol=dict(type='str',
                      choices=['openid-connect', 'saml'],
                      default='openid-connect'),
        attributes=dict(type='dict'),
        full_scope_allowed=dict(type='bool', aliases=['fullScopeAllowed']),
        node_re_registration_timeout=dict(
            type='int', aliases=['nodeReRegistrationTimeout']),
        registered_nodes=dict(type='dict', aliases=['registeredNodes']),
        client_template=dict(type='str', aliases=['clientTemplate']),
        use_template_config=dict(type='bool', aliases=['useTemplateConfig']),
        use_template_scope=dict(type='bool', aliases=['useTemplateScope']),
        use_template_mappers=dict(type='bool', aliases=['useTemplateMappers']),
        protocol_mappers=dict(type='list',
                              elements='dict',
                              options=protmapper_spec,
                              aliases=['protocolMappers']),
        authorization_settings=dict(type='dict',
                                    aliases=['authorizationSettings']),
        client_roles=dict(type='list',
                          elements='dict',
                          options=clientroles_spec,
                          aliases=['clientRoles', 'roles']),
        scope_mappings=dict(type='dict',
                            aliases=['scopeMappings'],
                            options=scopemappings_spec),
        force=dict(type='bool', default=False),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=([['client_id', 'id']]))

    result = dict(changed=False,
                  msg='',
                  diff={},
                  proposed={},
                  existing={},
                  end_state={},
                  clientSecret='')
    connection_header = {}
    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    cid = module.params.get('id')
    state = module.params.get('state')

    # convert module parameters to client representation parameters (if they belong in there)
    client_params = [
        x for x in module.params
        if x not in list(keycloak_argument_spec().keys()) +
        ['state', 'realm', 'url', 'force'] and module.params.get(x) is not None
    ]
    keycloak_argument_spec().keys()
    # See whether the client already exists in Keycloak
    if cid is None:
        before_client = kc.get_client_by_clientid(
            module.params.get('client_id'), realm=realm)
        if before_client is not None:
            cid = before_client['id']
    else:
        before_client = kc.get_client_by_id(cid, realm=realm)

    if before_client is None:
        before_client = dict()

    # Build a proposed changeset from parameters given to this module
    changeset = dict()

    for client_param in client_params:
        new_param_value = module.params.get(client_param)

        # some lists in the Keycloak API are sorted, some are not.
        if isinstance(new_param_value, list):
            if client_param in ['attributes']:
                try:
                    new_param_value = sorted(new_param_value)
                except TypeError:
                    pass
        # Unfortunately, the ansible argument spec checker introduces variables with null values when
        # they are not specified
        if client_param == 'protocol_mappers':
            new_param_value = [
                dict((k, v) for k, v in x.items() if x[k] is not None)
                for x in new_param_value
            ]

        if client_param == 'roles':
            client_param = 'client_roles'
        changeset[camel(client_param)] = new_param_value

    newClientScopeMappings = {}
    newClientScopeRealm = {}
    newClientScopeClients = {}
    if module.params.get('scope_mappings') is not None:
        newClientScopeMappings["scope_mappings"] = module.params.get(
            'scope_mappings')
        if newClientScopeMappings["scope_mappings"]["realm"] is not None:
            newClientScopeRealm["realmRoles"] = newClientScopeMappings[
                "scope_mappings"]["realm"]
        if newClientScopeMappings["scope_mappings"]["clients"] is not None:
            newClientScopeClients["clientRoles"] = newClientScopeMappings[
                "scope_mappings"]["clients"]

    # Whether creating or updating a client, take the before-state and merge the changeset into it
    updated_client = before_client.copy()
    updated_client.update(changeset)

    result['proposed'] = sanitize_cr(changeset)
    result['existing'] = sanitize_cr(before_client)

    # If the client does not exist yet, before_client is still empty
    if before_client == dict():
        if state == 'absent':
            # do nothing and exit
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['msg'] = 'Client does not exist, doing nothing.'
            module.exit_json(**result)

        # create new client
        result['changed'] = True
        if 'clientId' not in updated_client:
            module.fail_json(
                msg='client_id needs to be specified when creating a new client'
            )

        if module._diff:
            result['diff'] = dict(before='', after=sanitize_cr(updated_client))

        if module.check_mode:
            module.exit_json(**result)

        kc.create_client(updated_client, realm=realm)
        after_client = kc.get_client_by_clientid(updated_client['clientId'],
                                                 realm=realm)

        result['end_state'] = sanitize_cr(after_client)
        client_secret = kc.get_client_secret_by_id(after_client['id'],
                                                   realm=realm)
        if client_secret is not None:
            result['clientSecret'] = client_secret

        if module.params.get('scope_mappings') is not None:
            kc.assing_scope_roles_to_client(
                client_id=after_client['id'],
                clientScopeRealmRoles=newClientScopeRealm["realmRoles"],
                clientScopeClientRoles=newClientScopeClients["clientRoles"],
                realm=realm)
            result['changed'] = True
        result[
            'msg'] = 'Client %s has been created.' % updated_client['clientId']
        module.exit_json(**result)
    else:
        if state == 'present':
            # update existing client
            result['changed'] = True
            if module.check_mode:
                # We can only compare the current client with the proposed updates we have
                if module._diff:
                    result['diff'] = dict(before=sanitize_cr(before_client),
                                          after=sanitize_cr(updated_client))
                result['changed'] = (before_client != updated_client)

                module.exit_json(**result)

            kc.update_client(cid, updated_client, realm=realm)

            after_client = kc.get_client_by_id(cid, realm=realm)
            client_secret = kc.get_client_secret_by_id(cid, realm=realm)

            if client_secret is not None:
                result['clientSecret'] = client_secret
            if before_client == after_client:
                result['changed'] = False
            if module._diff:
                result['diff'] = dict(before=sanitize_cr(before_client),
                                      after=sanitize_cr(after_client))

            if module.params.get('scope_mappings') is not None:
                result['changed'] = kc.assing_scope_roles_to_client(
                    client_id=after_client['id'],
                    clientScopeRealmRoles=newClientScopeRealm["realmRoles"],
                    clientScopeClientRoles=newClientScopeClients[
                        "clientRoles"],
                    realm=realm)

            result['end_state'] = sanitize_cr(after_client)

            result['msg'] = 'Client %s has been updated.' % updated_client[
                'clientId']
            module.exit_json(**result)
        else:
            # Delete existing client
            result['changed'] = True
            if module._diff:
                result['diff']['before'] = sanitize_cr(before_client)
                result['diff']['after'] = ''

            if module.check_mode:
                module.exit_json(**result)

            kc.delete_client(cid, realm=realm)
            result['proposed'] = dict()
            result['end_state'] = dict()
            result['msg'] = 'Client %s has been deleted.' % before_client[
                'clientId']
            module.exit_json(**result)

    module.exit_json(**result)
def main():
    """
    Module execution

    :return:
    """
    argument_spec = keycloak_argument_spec()

    protmapper_spec = dict(
        consentRequired=dict(type='bool'),
        consentText=dict(type='str'),
        id=dict(type='str'),
        name=dict(type='str'),
        protocol=dict(type='str', choices=['openid-connect', 'saml']),
        protocolMapper=dict(type='str'),
        config=dict(type='dict'),
    )

    meta_args = dict(
        realm=dict(type='str', default='master'),
        state=dict(default='present', choices=['present', 'absent']),
        id=dict(type='str'),
        name=dict(type='str'),
        description=dict(type='str'),
        protocol=dict(type='str', choices=['openid-connect', 'saml']),
        attributes=dict(type='dict'),
        full_scope_allowed=dict(type='bool'),
        protocol_mappers=dict(type='list',
                              elements='dict',
                              options=protmapper_spec),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=([['id', 'name']]))

    result = dict(changed=False,
                  msg='',
                  diff={},
                  proposed={},
                  existing={},
                  end_state={})

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))
    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    cid = module.params.get('id')

    # convert module parameters to client representation parameters (if they belong in there)
    clientt_params = [
        x for x in module.params if x not in [
            'state', 'auth_keycloak_url', 'auth_client_id', 'auth_realm',
            'auth_client_secret', 'auth_username', 'auth_password',
            'validate_certs', 'realm'
        ] and module.params.get(x) is not None
    ]

    # See whether the client template already exists in Keycloak
    if cid is None:
        before_clientt = kc.get_client_template_by_name(
            module.params.get('name'), realm=realm)
        if before_clientt is not None:
            cid = before_clientt['id']
    else:
        before_clientt = kc.get_client_template_by_id(cid, realm=realm)

    if before_clientt is None:
        before_clientt = dict()

    result['existing'] = before_clientt

    # Build a proposed changeset from parameters given to this module
    changeset = dict()

    for clientt_param in clientt_params:
        # lists in the Keycloak API are sorted
        new_param_value = module.params.get(clientt_param)
        if isinstance(new_param_value, list):
            try:
                new_param_value = sorted(new_param_value)
            except TypeError:
                pass
        changeset[camel(clientt_param)] = new_param_value

    # Whether creating or updating a client, take the before-state and merge the changeset into it
    updated_clientt = before_clientt.copy()
    updated_clientt.update(changeset)

    result['proposed'] = changeset

    # If the client template does not exist yet, before_client is still empty
    if before_clientt == dict():
        if state == 'absent':
            # do nothing and exit
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['msg'] = 'Client template does not exist, doing nothing.'
            module.exit_json(**result)

        # create new client template
        result['changed'] = True
        if 'name' not in updated_clientt:
            module.fail_json(
                msg='name needs to be specified when creating a new client')

        if module._diff:
            result['diff'] = dict(before='', after=updated_clientt)

        if module.check_mode:
            module.exit_json(**result)

        kc.create_client_template(updated_clientt, realm=realm)
        after_clientt = kc.get_client_template_by_name(updated_clientt['name'],
                                                       realm=realm)

        result['end_state'] = after_clientt

        result[
            'msg'] = 'Client template %s has been created.' % updated_clientt[
                'name']
        module.exit_json(**result)
    else:
        if state == 'present':
            # update existing client template
            result['changed'] = True
            if module.check_mode:
                # We can only compare the current client template with the proposed updates we have
                if module._diff:
                    result['diff'] = dict(before=before_clientt,
                                          after=updated_clientt)

                module.exit_json(**result)

            kc.update_client_template(cid, updated_clientt, realm=realm)

            after_clientt = kc.get_client_template_by_id(cid, realm=realm)
            if before_clientt == after_clientt:
                result['changed'] = False
            if module._diff:
                result['diff'] = dict(before=before_clientt,
                                      after=after_clientt)
            result['end_state'] = after_clientt

            result[
                'msg'] = 'Client template %s has been updated.' % updated_clientt[
                    'name']
            module.exit_json(**result)
        else:
            # Delete existing client
            result['changed'] = True
            if module._diff:
                result['diff']['before'] = before_clientt
                result['diff']['after'] = ''

            if module.check_mode:
                module.exit_json(**result)

            kc.delete_client_template(cid, realm=realm)
            result['proposed'] = dict()
            result['end_state'] = dict()
            result[
                'msg'] = 'Client template %s has been deleted.' % before_clientt[
                    'name']
            module.exit_json(**result)

    module.exit_json(**result)
def main():
    """
    Module execution
    :returm:
    """
    argument_spec = keycloak_argument_spec()
    meta_args = dict(
        realm=dict(type='str', required=True),
        alias=dict(type='str', required=True),
        providerId=dict(type='str'),
        copyFrom=dict(type='str'),
        authenticationExecutions=dict(type='list', elements='dict'),
        state=dict(choices=["absent", "present"], default='present'),
        force=dict(type='bool', default=False),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = dict(changed=False, msg='', flow={})
    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)
    realm = module.params.get('realm')
    state = module.params.get('state')
    force = module.params.get('force')

    newAuthenticationRepresentation = {}
    newAuthenticationRepresentation["alias"] = module.params.get("alias")
    newAuthenticationRepresentation["copyFrom"] = module.params.get("copyFrom")
    newAuthenticationRepresentation["providerId"] = module.params.get(
        "providerId")
    newAuthenticationRepresentation[
        "authenticationExecutions"] = module.params.get(
            "authenticationExecutions")

    changed = False

    authenticationRepresentation = kc.get_authentication_flow_by_alias(
        alias=newAuthenticationRepresentation["alias"], realm=realm)

    if authenticationRepresentation == {}:  # Authentication flow does not exist
        if (state == 'present'):  # If desired state is prenset
            # If copyFrom is defined, create authentication flow from a copy
            if "copyFrom" in newAuthenticationRepresentation and newAuthenticationRepresentation[
                    "copyFrom"] is not None:
                authenticationRepresentation = kc.copy_auth_flow(
                    config=newAuthenticationRepresentation, realm=realm)
            else:  # Create an empty authentication flow
                authenticationRepresentation = kc.create_empty_auth_flow(
                    config=newAuthenticationRepresentation, realm=realm)
            # If the authentication still not exist on the server, raise an exception.
            if authenticationRepresentation is None:
                result[
                    'msg'] = "Authentication just created not found: " + str(
                        newAuthenticationRepresentation)
                module.fail_json(**result)
            # Configure the executions for the flow
            kc.create_or_update_executions(
                config=newAuthenticationRepresentation, realm=realm)
            changed = True
            # Get executions created
            executionsRepresentation = kc.get_executions_representation(
                config=newAuthenticationRepresentation, realm=realm)
            if executionsRepresentation is not None:
                authenticationRepresentation[
                    "authenticationExecutions"] = executionsRepresentation
            result['changed'] = changed
            result['flow'] = authenticationRepresentation
        elif state == 'absent':  # If desired state is absent.
            result[
                'msg'] = newAuthenticationRepresentation["alias"] + ' absent'
    else:  # The authentication flow already exist
        if (state == 'present'):  # if desired state is present
            if force:  # If force option is true
                # Delete the actual authentication flow
                kc.delete_authentication_flow_by_id(
                    id=authenticationRepresentation["id"], realm=realm)
                changed = True
                # If copyFrom is defined, create authentication flow from a copy
                if "copyFrom" in newAuthenticationRepresentation and newAuthenticationRepresentation[
                        "copyFrom"] is not None:
                    authenticationRepresentation = kc.copy_auth_flow(
                        config=newAuthenticationRepresentation, realm=realm)
                else:  # Create an empty authentication flow
                    authenticationRepresentation = kc.create_empty_auth_flow(
                        config=newAuthenticationRepresentation, realm=realm)
                # If the authentication still not exist on the server, raise an exception.
                if authenticationRepresentation is None:
                    result[
                        'msg'] = "Authentication just created not found: " + str(
                            newAuthenticationRepresentation)
                    result['changed'] = changed
                    module.fail_json(**result)
            # Configure the executions for the flow
            if kc.create_or_update_executions(
                    config=newAuthenticationRepresentation, realm=realm):
                changed = True
            # Get executions created
            executionsRepresentation = kc.get_executions_representation(
                config=newAuthenticationRepresentation, realm=realm)
            if executionsRepresentation is not None:
                authenticationRepresentation[
                    "authenticationExecutions"] = executionsRepresentation
            result['flow'] = authenticationRepresentation
            result['changed'] = changed
        elif state == 'absent':  # If desired state is absent
            # Delete the authentication flow alias.
            kc.delete_authentication_flow_by_id(
                id=authenticationRepresentation["id"], realm=realm)
            changed = True
            result[
                'msg'] = 'Authentication flow: ' + newAuthenticationRepresentation[
                    'alias'] + ' id: ' + authenticationRepresentation[
                        "id"] + ' is deleted'
            result['changed'] = changed

    module.exit_json(**result)