def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(
        uuid=dict(type='str', required=True),
        state=dict(type='str', required=True, choices=['absent', 'query']),
        provider=dict(type='dict', options=TETRATION_PROVIDER_SPEC)
    )

    # Create the return object
    result = {
        'object': None,
        'changed': False
    }

    module = AnsibleModule(
        argument_spec=module_args
    )

    tet_module = TetrationApiModule(module)

    response = None
    route = f"{TETRATION_API_SENSORS}/{module.params['uuid']}"
    if module.params['state'] == 'query':
        response = tet_module.run_method('GET', route)
    elif module.params['state'] == 'absent':
        response = tet_module.run_method('DELETE', route)
        result['changed'] is True

    result['object'] = response

    module.exit_json(**result)
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(app_id=dict(type='str', required=False),
                       app_name=dict(type='str', required=False),
                       is_primary=dict(type='bool', required=False),
                       is_enforcing=dict(type='bool', required=False),
                       return_details=dict(type='bool',
                                           required=False,
                                           default=False),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    result = {'changed': False, 'object': {}, 'objects': [], 'items_found': 0}

    module = AnsibleModule(argument_spec=module_args,
                           mutually_exclusive=[
                               ['app_id', 'app_name'],
                               ['app_id', 'is_primary'],
                               ['app_id', 'is_enforcing'],
                           ])

    tet_module = TetrationApiModule(module)
    if module.params['app_id']:
        route = f"{TETRATION_API_APPLICATIONS}/{module.params['app_id']}"
        if module.params['return_details']:
            route = f"{route}/details"
        app_response = tet_module.run_method('GET', route)
        result['object'] = app_response
        if app_response:
            result['items_found'] = 1
    else:
        all_apps_response = tet_module.run_method('GET',
                                                  TETRATION_API_APPLICATIONS)

        for app in all_apps_response:
            if module.params['app_name'] and module.params[
                    'app_name'] not in app['name']:
                continue
            if module.params['is_primary'] is not None and module.params[
                    'is_primary'] != app['primary']:
                continue
            if module.params['is_enforcing'] is not None and module.params[
                    'is_enforcing'] != app['enforement_enabled']:
                continue

            if module.params['return_details']:
                route = f"{TETRATION_API_APPLICATIONS}/{app['id']}/details"
                details = tet_module.run_method('GET', route)
                result['objects'].append(details)
            else:
                result['objects'].append(app)

        result['items_found'] = len(result['objects'])
        if result['objects']:
            result['object'] = result['objects'][0]

    module.exit_json(**result)
Ejemplo n.º 3
0
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(fully_qualified_name=dict(type='str', required=False),
                       scope_id=dict(type='str', required=False),
                       short_name=dict(type='str', required=False),
                       only_dirty=dict(type='bool',
                                       required=False,
                                       default=False),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    result = {'changed': False, 'object': {}, 'objects': [], 'qty_found': 0}

    module = AnsibleModule(
        argument_spec=module_args,
        required_one_of=[
            ['fully_qualified_name', 'scope_id', 'short_name'],
        ],
        mutually_exclusive=[
            ['fully_qualified_name', 'scope_id', 'short_name'],
        ])

    tet_module = TetrationApiModule(module)
    all_scopes_response = tet_module.run_method('GET', TETRATION_API_SCOPES)

    if module.params['fully_qualified_name']:
        to_find = module.params['fully_qualified_name']
        found_scopes = [s for s in all_scopes_response if s['name'] == to_find]
        if module.params['only_dirty']:
            found_scopes = [s for s in found_scopes if s['dirty'] is True]
        result['objects'] = found_scopes
        result['qty_found'] = len(found_scopes)
        if found_scopes:
            result['object'] = found_scopes[0]
    elif module.params['scope_id']:
        to_find = module.params['scope_id']
        found_scopes = [s for s in all_scopes_response if s['id'] == to_find]
        if module.params['only_dirty']:
            found_scopes = [s for s in found_scopes if s['dirty'] is True]
        result['objects'] = found_scopes
        result['qty_found'] = len(found_scopes)
        if found_scopes:
            result['object'] = found_scopes[0]
    elif module.params['short_name']:
        to_find = module.params['short_name']
        found_scopes = [
            s for s in all_scopes_response if to_find in s['short_name']
        ]
        if module.params['only_dirty']:
            found_scopes = [s for s in found_scopes if s['dirty'] is True]
        result['objects'] = found_scopes
        result['qty_found'] = len(found_scopes)
        if found_scopes:
            result['object'] = found_scopes[0]

    module.exit_json(**result)
def main():
    module_args = dict(
        app_id=dict(type='str', required=True),
        version=dict(type='str', required=True),
        policy_action=dict(type='str', required=False, choices=['ALLOW', 'DENY']),
        state=dict(required=True, choices=['update', 'query']),
        provider=dict(type='dict', options=TETRATION_PROVIDER_SPEC)
    )

    module = AnsibleModule(
        argument_spec=module_args,
        required_if=[
            ['state', 'update', ['policy_action']]
        ]
    )

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': None,
    }

    route = f"{TETRATION_API_APPLICATIONS}/{module.params['app_id']}/catch_all"
    get_payload = {
        'version': module.params['version'],
    }

    existing_policy = tet_module.run_method('GET', route, req_payload=get_payload)

    # Valid inputs are the version number or the version number prefixed with the letter `v`
    # this next step creates all possible versions for comparision
    possible_versions = [module.params['version'], f"v{module.params['version']}"]
    if existing_policy['version'] not in possible_versions:
        module.fail_json(msg="The application id and policy entered do not exist")

    if module.params['state'] == 'update':
        payload = {
            'version': module.params['version'],
            'policy_action': module.params['policy_action']
        }

        if existing_policy['action'] != module.params['policy_action']:
            result['changed'] = True

        api_results = tet_module.run_method('PUT', route, req_payload=payload)

        result['object'] = api_results
    else:
        result['object'] = existing_policy

    # Return result
    module.exit_json(**result)
def main():
    ''' Main entry point for module execution
    '''
    # Module specific spec
    module_args = dict(root_scope_name=dict(type='str', required=True),
                       ip_address=dict(type='str', required=False),
                       ip_subnet=dict(type='str', required=False),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(argument_spec=module_args,
                           required_one_of=[['ip_address', 'ip_subnet']])

    # These are all elements we put in our return JSON object for clarity
    result = {
        "object": None,
        "changed": False,
    }

    # Verify a valid IP address was passed in
    ip_object = ""

    if module.params['ip_address']:
        try:
            ip_object = str(ip_address(module.params['ip_address']))
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 Address entered.  Value entered: {module.params['ip_address']}"
            module.fail_json(msg=error_message)

    # Verify a valid IP subnet was passed in
    if module.params['ip_subnet']:
        try:
            ip_object = str(ip_network(module.params['ip_subnet']))
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 subnet entered.  Value entered: {module.params['ip_subnet']}"
            module.fail_json(msg=error_message)

    tet_module = TetrationApiModule(module)

    route = f"{TETRATION_API_INVENTORY_TAG}/{module.params['root_scope_name']}/search"
    params = {'ip': ip_object}

    result['object'] = tet_module.run_method('GET', route, params=params)

    return module.exit_json(**result)
def main():
    ''' Main entry point for module execution
    '''
    # Module specific spec
    module_args = dict(root_scope_name=dict(type='str', required=True),
                       attribute=dict(type='str', required=False),
                       state=dict(type='str',
                                  required=True,
                                  choices=['absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(argument_spec=module_args,
                           required_if=[['state', 'absent', ['attribute']]])

    # These are all elements we put in our return JSON object for clarity
    tet_module = TetrationApiModule(module)
    result = {
        "object": None,
        "changed": False,
    }

    route = f"{TETRATION_COLUMN_NAMES}/{module.params['root_scope_name']}"
    current_headers = tet_module.run_method('GET', route)

    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------
    if module.params['state'] == 'query':
        result['object'] = current_headers
    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------
    elif module.params['state'] == 'absent':
        if module.params['attribute'] in current_headers:
            delete_route = f"{route}/{module.params['attribute']}"
            result['object'] = tet_module.run_method('DELETE', delete_route)
            result['changed'] = True
        else:
            result['object'] = current_headers
    module.exit_json(**result)
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(root_app_scope_id=dict(type='str', required=True),
                       sync=dict(type='bool', required=False, default=False),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    result = dict(
        changed=False,
        object={},
    )

    module = AnsibleModule(argument_spec=module_args,
                           supports_check_mode=False)

    tet_module = TetrationApiModule(module)
    all_scopes_response = tet_module.run_method('GET', TETRATION_API_SCOPES)
    all_scopes_lookup = {s['id']: s['short_name'] for s in all_scopes_response}

    if module.params['root_app_scope_id'] and module.params[
            'root_app_scope_id'] not in all_scopes_lookup.keys():
        error_message = "`root_app_scope_id` passed into the module does not exist."
        module.fail_json(msg=error_message,
                         searched_scope=module.params['root_app_scope_id'])

    req_payload = {
        'root_app_scope_id': module.params['root_app_scope_id'],
        'sync': module.params['sync']
    }

    route = f"{TETRATION_API_SCOPES}/commit_dirty"
    response = tet_module.run_method('POST', route, req_payload=req_payload)

    result['object'] = response
    result['changed'] = True

    module.exit_json(**result)
def main():
    # Main entry point for module execution

    # Module specific spec
    module_args = dict(profile_name=dict(type='str', required=False),
                       profile_id=dict(type='str', required=False),
                       filter_id=dict(type='str', required=False),
                       filter_name=dict(type='str', required=False),
                       state=dict(default='present',
                                  choices=['present', 'absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(argument_spec=module_args,
                           required_one_of=[
                               ['profile_name', 'profile_id'],
                               ['filter_id', 'filter_name'],
                           ],
                           mutually_exclusive=[
                               ['profile_name', 'profile_id'],
                               ['filter_id', 'filter_name'],
                           ])

    # These are all elements we put in our return JSON object for clarity
    tet_module = TetrationApiModule(module)
    result = {
        'changed': False,
        'object': {},
    }

    # =========================================================================
    # Get current state of the object
    config_profiles = tet_module.run_method(
        'GET', TETRATION_API_AGENT_CONFIG_PROFILES)
    config_profiles_and_ids = {c['name']: c['id'] for c in config_profiles}

    profile_id = None
    if module.params['profile_id'] in config_profiles_and_ids.values():
        profile_id = module.params['profile_id']
    elif module.params['profile_name'] in config_profiles_and_ids.keys():
        profile_name = module.params['profile_name']
        profile_id = config_profiles_and_ids[profile_name]

    if not profile_id:
        if module.params['profile_id']:
            module.fail_json(
                msg=
                f"Unable to find existing profile id: {module.params['profile_id']}"
            )
        else:
            module.fail_json(
                msg=
                f"Unable to find existing profile named: {module.params['profile_name']}"
            )

    # Get the existing API Scopes and Inventory Filters to verify the filter parameters passed in
    existing_app_scopes = tet_module.run_method('GET', TETRATION_API_SCOPES)

    # Build a lookup object for the app scopes
    app_scope_name_to_scope_id = {
        s['name']: s['id']
        for s in existing_app_scopes
    }

    # Build the inventory filter dict but check for duplicate entries and report them if found
    existing_inventory_filters = tet_module.run_method(
        'GET', TETRATION_API_INVENTORY_FILTER)

    inv_filter_name_to_filter_id = {}
    duplicate_values = []
    for i in existing_inventory_filters:
        name = i['name']
        inv_id = i['id']
        if inv_id is None:  # If the API returns an ID of None, this code won't work
            module.fail_json(msg='An ID returned had a value of `None`')

        if inv_filter_name_to_filter_id.get(
                name) is None:  # Does the ID exist in the new dict
            inv_filter_name_to_filter_id[name] = inv_id
        else:
            duplicate_values.append(name)

    if duplicate_values:
        duplicate_values = set(duplicate_values)
        module.fail_json(msg=(
            'The Tetration Server has multiple inventory filters with the same name.  '
            f'This is not supported with this module.  Duplicate names are: {duplicate_values}'
        ))

    filter_id = None

    if module.params['filter_id']:
        # Verify the ID is a valid api scope or an inventory filter
        if module.params['filter_id'] in app_scope_name_to_scope_id.values():
            filter_id = module.params['filter_id']
        elif module.params['filter_id'] in inv_filter_name_to_filter_id.values(
        ):
            filter_id = module.params['filter_id']
    elif module.params['filter_name']:
        # Verify the ID is a valid api scope or an inventory filter
        filter_name = module.params['filter_name']
        if app_scope_name_to_scope_id.get(filter_name):
            filter_id = app_scope_name_to_scope_id[filter_name]
        elif inv_filter_name_to_filter_id.get(filter_name):
            filter_id = inv_filter_name_to_filter_id[filter_name]

    if filter_id is None:
        module.fail_json(msg='The provided filter name or id is invalid')

    # Get the current config intents
    existing_intents = tet_module.run_method(
        'GET', TETRATION_API_AGENT_CONFIG_INTENTS)

    intent_to_find = {
        'inventory_config_profile_id': profile_id,
        'inventory_filter_id': filter_id
    }

    existing_intent = None
    for intent in existing_intents:
        if tet_module.is_subset(intent_to_find, intent):
            existing_intent = intent

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':
        new_object = {
            'inventory_config_profile_id': profile_id,
            'inventory_filter_id': filter_id
        }

        if not existing_intent:
            result['object'] = tet_module.run_method(
                'POST',
                TETRATION_API_AGENT_CONFIG_INTENTS,
                req_payload=new_object)
            result['changed'] = True
        else:
            result['object'] = existing_intent

    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------
    elif module.params['state'] in 'absent':
        if existing_intent:
            route = f"{TETRATION_API_AGENT_CONFIG_INTENTS}/{existing_intent['id']}"
            result['object'] = tet_module.run_method('DELETE', route)
            result['changed'] = True

    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------
    else:
        if existing_intent:
            result['object'] = existing_intent

    module.exit_json(**result)
Ejemplo n.º 9
0
def main():
    module_args = dict(app_name=dict(type='str', required=False),
                       app_id=dict(type='str', required=False),
                       app_scope_id=dict(type='str', required=False),
                       app_scope_name=dict(type='str', required=False),
                       description=dict(type='str', required=False),
                       alternate_query_mode=dict(type='bool',
                                                 required=False,
                                                 default=False),
                       strict_validation=dict(type='bool',
                                              required=False,
                                              default=False),
                       primary=dict(type='bool', required=False),
                       state=dict(required=True, choices=['present',
                                                          'absent']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[['app_scope_name', 'app_scope_id']],
        required_one_of=[
            ['app_name', 'app_id'],
        ],
    )

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': None,
    }

    # =========================================================================
    # Verify passed in data is accurate.
    existing_app_scope = {}
    if module.params['app_scope_id']:
        app_scope_route = f"{TETRATION_API_SCOPES}/{module.params['app_scope_id']}"
        existing_app_scope = tet_module.run_method('GET', app_scope_route)
        if not existing_app_scope:
            module.fail_json(
                msg=
                f"Unable to find existing app with the id of: {module.params['app_scope_id']}"
            )
    elif module.params['app_scope_name']:
        all_scopes = tet_module.run_method('GET', TETRATION_API_SCOPES)
        found_app_scopes = [
            scope for scope in all_scopes
            if scope['name'] == module.params['app_scope_name']
        ]
        if len(found_app_scopes) == 0:
            module.fail_json(msg=(
                "There were no app scopes that matched the name entered.  "
                f"Searched for: {module.params['app_scope_name']}"))
        elif len(found_app_scopes) > 1:
            module.fail_json(msg=(
                "There were too many app scopes that matched the name entered.  "
                f"Searched for: {module.params['app_scope_name']}"))
        existing_app_scope = found_app_scopes[0]

    existing_app = {}
    if module.params['app_id']:
        app_route = f"{TETRATION_API_APPLICATIONS}/{module.params['app_id']}"
        existing_app = tet_module.run_method('GET', app_route)
        if not existing_app:
            module.fail_json(
                msg=
                f"The App ID entered is not in the system.  Searched for: {module.params['app_id']}"
            )
    elif module.params['app_name']:
        # If we have an app_id, and it's valid, we don't care about searching for the app_id by name
        # If we don't have an app_id, then we need to find an app, but it's ok if one doesn't exist
        # because we'll then make it, or we could be verifying it's absent
        apps = tet_module.run_method('GET', TETRATION_API_APPLICATIONS)
        found_apps = [
            found for found in apps
            if found['name'] == module.params['app_name']
        ]
        if len(found_apps) > 1:
            module.fail_json(
                msg=
                f"There were too many apps that matched the name entered.  Searched for: {module.params['app_name']}"
            )
        elif len(found_apps) == 1:
            existing_app = found_apps[0]

    app_route = ""
    if existing_app:
        app_route = f"{TETRATION_API_APPLICATIONS}/{existing_app['id']}"

    # =========================================================================
    # Now enforce the desired state (present, absent)

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':
        # if the object does not exist at all, create it but verify we have all needed data first
        if not existing_app and not existing_app_scope:
            module.fail_json(msg=(
                "The application does not exist.  "
                "Must provide a Scope ID or Scope Name to create a new scope."
            ))

        if not existing_app and module.params['primary'] is None:
            module.fail_json(msg=(
                "The application does not exist.  "
                "Must provide info on if the scope is primary or not when creating a scope."
            ))

        if existing_app:
            updated_app = {
                'name': module.params['app_name'],
                'description': module.params['description'],
                'primary': module.params['primary']
            }
            if not module.params['app_name']:
                updated_app.pop('name')
            if module.params['description'] is None:
                updated_app.pop('description')
            if module.params['primary'] is None:
                updated_app.pop('primary')

            is_subset = tet_module.is_subset(updated_app, existing_app)

            if not is_subset:
                result['object'] = tet_module.run_method(
                    'PUT', app_route, req_payload=updated_app)
                result['changed'] = True
            else:
                result['object'] = existing_app
        else:
            new_app = {
                'app_scope_id': existing_app_scope['id'],
                'name': module.params['app_name'],
                'description': module.params['description'],
                'alternate_query_mode': module.params['alternate_query_mode'],
                'strict_validation': module.params['strict_validation'],
                'primary': module.params['primary']
            }

            result['object'] = tet_module.run_method(
                "POST", TETRATION_API_APPLICATIONS, req_payload=new_app)
            result['changed'] = True

    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------

    elif module.params['state'] == 'absent':
        if existing_app:
            if existing_app['enforcement_enabled']:
                module.fail_json(
                    msg=
                    'Cannot delete workspace with enforcement enabled.  Disable enforcement before deleting'
                )
            elif existing_app['primary']:
                module.fail_json(
                    msg=
                    'Cannot delete primary application.  Try making application secondary before deleting'
                )

            result['object'] = tet_module.run_method('DELETE', app_route)
            result['changed'] = True

    # Return result
    module.exit_json(**result)
Ejemplo n.º 10
0
def run_module():
    module_args = dict(
        name=dict(type='str', required=False),
        description=dict(type='str', required=False),
        app_scope_id=dict(type='str', required=False),
        id=dict(type='str', required=False),
        capability_app_scope_id=dict(type='str', required=False),
        capability_ability=dict(type='str', required=False, choices=TETRATION_API_APP_SCOPE_CAPABILITIES),
        state=dict(type='str', required=True, choices=['present', 'absent', 'query']),
        provider=dict(type='dict', options=TETRATION_PROVIDER_SPEC)
    )

    # Create the objects that will be returned
    result = {
        "object": None,
        "changed": False
    }

    result_obj = dict(
        app_scope_id=None,
        capabilities=[],
        description=None,
        id=None,
        name=None
    )

    # Creating the Ansible Module
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=False,
        required_one_of=[
            ['id', 'name']
        ],
        required_together=[
            ['capability_app_scope_id', 'capability_ability']
        ],
        required_by={
            'name': ['app_scope_id']
        }
    )

    # grant capablities (present)
    # role_id, capability app scope id, ability

    tet_module = TetrationApiModule(module)

    # Create an App Scope Name to ID Lookup Table
    all_app_scopes_response = tet_module.run_method('GET', TETRATION_API_SCOPES)
    all_app_scopes_lookup = {r['name']: r['id'] for r in all_app_scopes_response}

    # Create a Role Name - App Scope ID to Role ID Lookup Table
    # A role is uniquely identified by its name and app scope
    # Create a dict of tuples, key to look up an ID
    all_roles_response = tet_module.run_method('GET', TETRATION_API_ROLE)
    all_roles_lookup_by_name_app_id = {(r['name'], r['app_scope_id']): r['id'] for r in all_roles_response}

    # Role and App Scope Validation
    # Done here so it does not have to be done elsewhere in the module
    invalid_parameters = {}
    if module.params['app_scope_id']:
        scope_id = module.params['app_scope_id']
        if scope_id not in all_app_scopes_lookup.values():
            invalid_parameters['app_scope_id'] = scope_id
    if module.params['id']:
        role_id = module.params['id']
        if role_id not in all_roles_lookup_by_name_app_id.values():
            invalid_parameters['id'] = role_id
    if module.params['capability_app_scope_id']:
        capability_app_id = module.params['capability_app_scope_id']
        if capability_app_id not in all_app_scopes_lookup.values():
            invalid_parameters['capability_app_scope_id'] = capability_app_id

    if invalid_parameters:
        error_message = "Check the `invalid parameters` object for the invalid parameters"
        module.fail_json(msg=error_message, invalid_parameters=invalid_parameters)

    # One of these is the unique ID for the role
    role_id = module.params['id']
    name_scope_id = module.params['name'], module.params['app_scope_id']

    if module.params['state'] == 'present':
        if not role_id and name_scope_id not in all_roles_lookup_by_name_app_id.keys():
            # Role does not exist, lets add it
            req_payload = {
                'name': module.params['name'],
                'description': module.params['description'],
                'app_scope_id': module.params['app_scope_id']
            }
            response = tet_module.run_method('POST', TETRATION_API_ROLE, req_payload=req_payload)
            all_roles_lookup_by_name_app_id[name_scope_id] = response['id']
            result_obj = response
            result['changed'] = True

        else:
            # The Role exists, lets update it
            if role_id:
                route = f'{TETRATION_API_ROLE}/{role_id}'
            else:
                looked_up_role_id = all_roles_lookup_by_name_app_id[name_scope_id]
                route = f'{TETRATION_API_ROLE}/{looked_up_role_id}'
            response = tet_module.run_method('GET', route)
            req_payload = {
                'name': module.params['name'],
                'description': module.params['description'],
            }

            if module.params['name'] is None or module.params['name'] == response['name']:
                req_payload.pop('name', None)

            if module.params['name'] is None or module.params['description'] == response['description']:
                req_payload.pop('description')

            if req_payload:
                updated_response = tet_module.run_method('PUT', route, req_payload=req_payload)
                result['changed'] = True
                result_obj = updated_response
            else:
                result_obj = response

        if module.params['capability_app_scope_id']:
            # Check to see if any capabilities can be added
            if role_id:
                route = f'{TETRATION_API_ROLE}/{role_id}'
            else:
                looked_up_role_id = all_roles_lookup_by_name_app_id[name_scope_id]
                route = f'{TETRATION_API_ROLE}/{looked_up_role_id}'

            response = tet_module.run_method('GET', route)
            desired_to_add = set([(module.params['capability_app_scope_id'], module.params['capability_ability'])])

            current_capabilities = []

            # Create a set of tuples to determine if I need to the capability
            for c in response['capabilities']:
                curr_cap = c['app_scope_id'], c['ability']
                current_capabilities.append(curr_cap)
            current_capabilities = set(current_capabilities)

            to_add = desired_to_add.difference(current_capabilities)

            response['cap'] = str(to_add)

            if to_add:
                req_payload = {
                    'app_scope_id': module.params['capability_app_scope_id'],
                    'ability': module.params['capability_ability']
                }
                capability_route = f'{route}/capabilities'
                response = tet_module.run_method('POST', capability_route, req_payload=req_payload)
                result_obj['capabilities'].append(response)
                result['changed'] = True

    if module.params['state'] == 'absent':
        if module.params['id'] and module.params['name']:
            error_message = (
                'Cannot search for 2 parameters at the same time, specify either `name` or `id`'
            )
            module.fail_json(msg=error_message)

        if not role_id and name_scope_id not in all_roles_lookup_by_name_app_id.keys():
            module.exit_json(msg='That role does not exist in the system.', object={'success': True})

        if role_id:
            route = f'{TETRATION_API_ROLE}/{role_id}'
        else:
            looked_up_role_id = all_roles_lookup_by_name_app_id[name_scope_id]
            route = f'{TETRATION_API_ROLE}/{looked_up_role_id}'

        role_response = tet_module.run_method('DELETE', route)
        result_obj = role_response
        result['changed'] = True

    if module.params['state'] == 'query':
        # Confirm the user didn't try and search for 2 different values
        if module.params['id'] and module.params['name']:
            error_message = (
                'Cannot search for 2 parameters at the same time, specify either `name` or `id`'
            )
            module.fail_json(msg=error_message)

        # Confirm the role exists if searching by name and App Scope ID
        if not role_id and name_scope_id not in all_roles_lookup_by_name_app_id.keys():
            error_message = (
                'There is no role that matches the value being searched for'
            )
            module.fail_json(msg=error_message)

        if role_id:
            route = f'{TETRATION_API_ROLE}/{role_id}'
        else:
            looked_up_role_id = all_roles_lookup_by_name_app_id[name_scope_id]
            route = f'{TETRATION_API_ROLE}/{looked_up_role_id}'

        role_response = tet_module.run_method('GET', route)
        result_obj = role_response

    result['object'] = result_obj
    module.exit_json(**result)
Ejemplo n.º 11
0
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(host_name_contains=dict(type='str'),
                       host_name_is_exactly=dict(type='str'),
                       interface_ip_is_exactly=dict(type='str'),
                       interface_ip_in_network=dict(type='str'),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    # Create the return object
    result = {'object': [], 'changed': False, 'items_found': 0}

    module = AnsibleModule(argument_spec=module_args)

    tet_module = TetrationApiModule(module)

    # Verify a valid IP address was passed in
    if module.params['interface_ip_is_exactly']:
        try:
            ip_to_validate = ipaddress.ip_address(
                module.params['interface_ip_is_exactly'])
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 Address entered.  Value entered: {module.params['interface_ip_is_exactly']}"
            module.fail_json(msg=error_message)

    # Verify a valid IP network was passed in
    if module.params['interface_ip_in_network']:
        try:
            network_to_validate = ipaddress.ip_network(
                module.params['interface_ip_in_network'], strict=False)
            result['net_to_validate'] = str(network_to_validate)
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 Network entered.  Value entered: {module.params['interface_ip_in_network']}"
            module.fail_json(msg=error_message)

    response = tet_module.run_method_paginated('GET', TETRATION_API_SENSORS)

    for s in response:
        if 'deleted_at' not in s.keys():
            to_append = s
            if module.params['host_name_contains'] and module.params[
                    'host_name_contains'] not in s['host_name']:
                to_append = None
                continue
            if module.params['host_name_is_exactly'] and module.params[
                    'host_name_is_exactly'] != s['host_name']:
                to_append = None
                continue
            if module.params['interface_ip_is_exactly']:
                ip_in_interface = False
                for i in s['interfaces']:
                    try:
                        iface_addr = ipaddress.ip_address(i['ip'])
                    except ValueError:
                        iface_addr = None
                    if iface_addr == ip_to_validate:
                        ip_in_interface = True

                if not ip_in_interface:
                    to_append = None
                    continue
            if module.params['interface_ip_in_network']:
                ip_in_network = False
                for i in s['interfaces']:
                    try:
                        iface_addr = ipaddress.ip_address(i['ip'])
                    except ValueError:
                        iface_addr = None

                    if iface_addr in network_to_validate:
                        ip_in_network = True
                        # Once I find a match, no need to keep searching
                        break

                if not ip_in_network:
                    to_append = None
                    continue

            if to_append is not None:
                result['object'].append(to_append)

    result['items_found'] = len(result['object'])
    module.exit_json(**result)
def main():
    ''' Main entry point for module execution
    '''
    #
    # Module specific spec
    module_args = dict(name=dict(type='str', required=False),
                       id=dict(type='str', required=False),
                       root_app_scope_id=dict(type='str', required=False),
                       root_app_scope_name=dict(type='str', required=False),
                       allow_broadcast=dict(type='bool', required=False),
                       allow_link_local=dict(type='bool', required=False),
                       allow_multicast=dict(type='bool', required=False),
                       auto_upgrade_opt_out=dict(type='bool', required=False),
                       cpu_quota_mode=dict(type='int',
                                           required=False,
                                           choices=[0, 1, 2]),
                       cpu_quota_pct=dict(type='int', required=False),
                       cpu_quota_us=dict(type='int', required=False),
                       data_plane_disabled=dict(type='bool', required=False),
                       enable_dns=dict(type='bool', required=False),
                       enable_forensics=dict(type='bool', required=False),
                       enable_meltdown=dict(type='bool', required=False),
                       enable_pid_lookup=dict(type='bool', required=False),
                       enforcement_cpu_quota_mode=dict(type='int',
                                                       required=False,
                                                       choices=[0, 1, 2]),
                       enforcement_cpu_quota_pct=dict(type='int',
                                                      required=False),
                       enforcement_cpu_quota_us=dict(type='int',
                                                     required=False),
                       enforcement_disabled=dict(type='bool', required=False),
                       enforcement_max_rss_limit=dict(type='int',
                                                      required=False),
                       enforcement_max_rss_limit_mb=dict(type='int',
                                                         required=False),
                       forensics_cpu_quota_mode=dict(type='int',
                                                     required=False,
                                                     choices=[0, 1, 2]),
                       forensics_cpu_quota_pct=dict(type='int',
                                                    required=False),
                       forensics_cpu_quota_us=dict(type='int', required=False),
                       forensics_mem_quota_bytes=dict(type='int',
                                                      required=False),
                       forensics_mem_quota_mb=dict(type='int', required=False),
                       max_rss_limit=dict(type='int', required=False),
                       max_rss_limit_mb=dict(type='int', required=False),
                       preserve_existing_rules=dict(type='bool',
                                                    required=False),
                       state=dict(choices=['present', 'absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    # Building custom error handling to display custom error messages

    # Combine specs and include provider parameter
    module = AnsibleModule(
        argument_spec=module_args,
        required_one_of=[['root_app_scope_id', 'root_app_scope_name'],
                         ['name', 'id']],
        mutually_exclusive=[
            ['root_app_scope_id', 'root_app_scope_name'],
            ['cpu_quota_pct', 'cpu_quota_us'],
            ['enforcement_cpu_quota_pct', 'enforcement_cpu_quota_us'],
            ['forensics_cpu_quota_pct', 'forensics_cpu_quota_us'],
            ['enforcement_max_rss_limit', 'enforcement_max_rss_limit_mb'],
            ['forensics_mem_quota_bytes', 'forensics_mem_quota_mb'],
            ['max_rss_limit', 'max_rss_limit_mb'],
        ])

    if module.params['name'] == 'Default':
        module.fail_json(msg='Cannot modify the default agent profile')

    # Verify the following modules have valid inputs between 1 and 100% inclusive
    percent_params = [
        'cpu_quota_pct', 'enforcement_cpu_quota_pct', 'forensics_cpu_quota_pct'
    ]
    invalid_percent_params = validate_ranges(percent_params,
                                             module.params,
                                             low_value=1,
                                             high_value=100)
    if invalid_percent_params:
        module.fail_json(
            msg=
            f'The following params need to be between 1 and 100 inclusive: {invalid_percent_params}'
        )

    # Verify the following modules have valid inputs between 10,000 and 1,000,000 inclusive
    us_params = [
        'cpu_quota_us', 'enforcement_cpu_quota_us', 'forensics_cpu_quota_us'
    ]
    invalid_us_params = validate_ranges(us_params,
                                        module.params,
                                        low_value=10000,
                                        high_value=100000)
    if invalid_us_params:
        module.fail_json(
            msg=
            f'The following params need to be between 10,000 and 1,000,000 inclusive: {invalid_us_params}'
        )

    # Verify the following modules have valid inputs between 128 and 2048 inclusive
    mb_params = ['enforcement_max_rss_limit_mb', 'forensics_mem_quota_mb']
    invalid_mb_params = validate_ranges(mb_params,
                                        module.params,
                                        low_value=128,
                                        high_value=2048)
    if invalid_mb_params:
        module.fail_json(
            msg=
            f'The following params need to be between 128 and 2048 inclusive: {invalid_mb_params}'
        )

    # Verify the following modules have valid inputs between 200 and 2048 inclusive
    vis_mb_params = ['max_rss_limit_mb']
    invalid_vis_mb_params = validate_ranges(vis_mb_params,
                                            module.params,
                                            low_value=200,
                                            high_value=2048)
    if invalid_vis_mb_params:
        module.fail_json(
            msg=
            f'The following params need to be between 200 and 2048 inclusive: {invalid_vis_mb_params}'
        )

    # Verify the following modules have valid inputs between 134,217,728 and 2,147,483,649 inclusive
    bytes_params = ['enforcement_max_rss_limit', 'forensics_mem_quota_bytes']
    invalid_bytes_params = validate_ranges(bytes_params,
                                           module.params,
                                           low_value=134217728,
                                           high_value=2147483649)
    if invalid_bytes_params:
        module.fail_json(
            msg=
            f'The following params need to be between 134,217,728 and 2,147,483,649 inclusive: {invalid_bytes_params}'
        )

    # Verify the following modules have valid inputs between 209,715,200 and 2,147,483,649 inclusive
    vis_bytes_params = ['max_rss_limit']
    invalid_vis_bytes_params = validate_ranges(vis_bytes_params,
                                               module.params,
                                               low_value=209715200,
                                               high_value=2147483649)
    if invalid_vis_bytes_params:
        module.fail_json(
            msg=
            f'The following params need to be between 209,715,200 and 2,147,483,649 inclusive: {invalid_vis_bytes_params}'
        )

    tet_module = TetrationApiModule(module)
    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': {},
    }

    # =========================================================================
    # Get current state of the object
    app_scopes = tet_module.run_method('GET', TETRATION_API_SCOPES)
    app_scope_dict = {s['name']: s['id'] for s in app_scopes}

    existing_app_scope_id = None
    if module.params['root_app_scope_id'] in app_scope_dict.values():
        existing_app_scope_id = module.params['root_app_scope_id']
    else:
        scope_name = module.params['root_app_scope_name']
        existing_app_scope_id = app_scope_dict.get(scope_name)

    if not existing_app_scope_id:
        if module.params['app_scope_id']:
            module.fail_json(
                msg=
                f"Unable to find existing app scope id: {module.params['app_scope_id']}"
            )
        else:
            module.fail_json(
                msg=
                f"Unable to find existing app scope named: {module.params['app_scope_name']}"
            )

    existing_profiles = tet_module.run_method(
        'GET', TETRATION_API_AGENT_CONFIG_PROFILES)

    existing_profile = None

    for profile in existing_profiles:
        if module.params['id'] == profile['id']:
            existing_profile = profile
        elif module.params['name'] == profile['name']:
            existing_profile = profile

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':
        new_object = {
            'name':
            module.params['name'],
            'root_app_scope_id':
            existing_app_scope_id,
            'allow_broadcast':
            module.params['allow_broadcast'],
            'allow_link_local':
            module.params['allow_link_local'],
            'allow_multicast':
            module.params['allow_multicast'],
            'auto_upgrade_opt_out':
            module.params['auto_upgrade_opt_out'],
            'cpu_quota_mode':
            module.params['cpu_quota_mode'],
            'cpu_quota_pct':
            module.params['cpu_quota_pct'],
            'cpu_quota_us':
            module.params['cpu_quota_us'],
            'data_plane_disabled':
            module.params['data_plane_disabled'],
            'enable_dns':
            module.params['enable_dns'],
            'enable_forensics':
            module.params['enable_forensics'],
            'enable_meltdown':
            module.params['enable_meltdown'],
            'enable_pid_lookup':
            module.params['enable_pid_lookup'],
            'enforcement_cpu_quota_mode':
            module.params['enforcement_cpu_quota_mode'],
            'enforcement_cpu_quota_pct':
            module.params['enforcement_cpu_quota_pct'],
            'enforcement_cpu_quota_us':
            module.params['enforcement_cpu_quota_us'],
            'enforcement_disabled':
            module.params['enforcement_disabled'],
            'enforcement_max_rss_limit':
            module.params['enforcement_max_rss_limit'],
            'enforcement_max_rss_limit_mb':
            module.params['enforcement_max_rss_limit_mb'],
            'forensics_cpu_quota_mode':
            module.params['forensics_cpu_quota_mode'],
            'forensics_cpu_quota_pct':
            module.params['forensics_cpu_quota_pct'],
            'forensics_cpu_quota_us':
            module.params['forensics_cpu_quota_us'],
            'forensics_mem_quota_bytes':
            module.params['forensics_mem_quota_bytes'],
            'forensics_mem_quota_mb':
            module.params['forensics_mem_quota_mb'],
            'max_rss_limit':
            module.params['max_rss_limit'],
            'max_rss_limit_mb':
            module.params['max_rss_limit_mb'],
            'preserve_existing_rules':
            module.params['preserve_existing_rules'],
        }

        # Remove all the undefined parameters from the new_object
        new_object = {k: v for k, v in new_object.items() if v is not None}

        if existing_profile:
            if tet_module.is_subset(new_object, existing_profile):
                # If there is no change required to the module
                result['object'] = existing_profile
            else:
                # A change is required
                route = f"{TETRATION_API_AGENT_CONFIG_PROFILES}/{existing_profile['id']}"
                result['object'] = tet_module.run_method(
                    'PUT', route, req_payload=new_object)
                result['changed'] = True
        else:
            result['object'] = tet_module.run_method(
                'POST',
                TETRATION_API_AGENT_CONFIG_PROFILES,
                req_payload=new_object)
            result['changed'] = True

    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------
    elif module.params['state'] == 'absent':
        if existing_profile:
            route = f"{TETRATION_API_AGENT_CONFIG_PROFILES}/{existing_profile['id']}"
            result['object'] = tet_module.run_method('DELETE', route)
            result['changed'] = True
    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------
    else:
        if existing_profile:
            result['object'] = existing_profile

    module.exit_json(**result)
Ejemplo n.º 13
0
def main():
    valid_proto_names = [proto['name'] for proto in TETRATION_API_PROTOCOLS]
    valid_proto_ids = [proto['value'] for proto in TETRATION_API_PROTOCOLS]

    module_args = dict(policy_id=dict(type='str', required=True),
                       start_port=dict(type='int', required=False),
                       end_port=dict(type='int', required=False),
                       proto_id=dict(type='int',
                                     required=False,
                                     choices=valid_proto_ids),
                       proto_name=dict(type='str',
                                       required=False,
                                       choices=valid_proto_names),
                       description=dict(type='str', required=False),
                       approved=dict(type='bool', required=False),
                       exclusion_filter=dict(type='bool',
                                             required=False,
                                             default=False),
                       state=dict(required=True,
                                  choices=['present', 'absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[['proto_name', 'proto_id']],
        required_one_of=[
            ['proto_name', 'proto_id'],
        ],
        required_together=[['start_port', 'end_port']],
        required_if=[
            # Only the TCP and UDP protocols require the start and end ports
            ['proto_name', 'TCP', ['start_port', 'end_port']],
            ['proto_name', 'UDP', ['start_port', 'end_port']],
            ['proto_id', 6, ['start_port', 'end_port']],
            ['proto_id', 17, ['start_port', 'end_port']]
        ])

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': {},
    }

    # =========================================================================
    # Get current state of the object
    route = f"{TETRATION_API_APPLICATION_POLICIES}/{module.params['policy_id']}"

    existing_policy = tet_module.run_method('GET', route)
    if not existing_policy:
        module.fail_json(
            msg=
            f"Unable to find existing application policy with id: {module.params['policy_id']}"
        )

    # Convert the protocol name to a protocol id
    if module.params['proto_name']:
        proto_id_list = [
            i['value'] for i in TETRATION_API_PROTOCOLS
            if i['name'] == module.params['proto_name']
        ]
        proto_id = proto_id_list[0]
    else:
        proto_id = module.params['proto_id']

    existing_l4_params = existing_policy['l4_params']

    existing_param = find_l4_param(existing_l4_params, proto_id,
                                   module.params['start_port'],
                                   module.params['end_port'])

    # =========================================================================
    # Now enforce the desired state (present, absent, query)

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':

        # if the object does not exist at all, create it
        # deal with approved or not approved a different way
        new_object = {
            "start_port": module.params['start_port'],
            "end_port": module.params['end_port'],
            "description": module.params['description'],
            "proto": proto_id
        }

        # Remove unneeded entries
        parameters = [
            'start_port',
            'end_port',
            'description',
        ]

        for p in parameters:
            if new_object[p] is None:
                new_object.pop(p)

        # If the object does not exist, let's create it
        route = f"{TETRATION_API_APPLICATION_POLICIES}/{module.params['policy_id']}/l4_params"

        if not existing_param:
            l4_results = tet_module.run_method('POST',
                                               route,
                                               req_payload=new_object)

            new_param = find_l4_param(l4_results['l4_params'], proto_id,
                                      module.params['start_port'],
                                      module.params['end_port'])

            result['object'] = new_param
            result['changed'] = True
        else:
            result['object'] = existing_param

        if module.params['approved'] is not None:
            # If the approval status is missing, that means it's not approved
            current_approval_status = result['object'].get('approved', False)
            current_id = result['object']['id']

            if current_approval_status != module.params['approved']:
                updated_route = f"{route}/{current_id}"

                payload = {"approved": module.params['approved']}

                approval_results = tet_module.run_method('PUT',
                                                         updated_route,
                                                         req_payload=payload)

                updated_param = find_l4_param(approval_results['l4_params'],
                                              proto_id,
                                              module.params['start_port'],
                                              module.params['end_port'])

                result['object'] = updated_param
                result['changed'] = True
                # ---------------------------------
                # STATE == 'absent'
                # ---------------------------------

    elif module.params['state'] == 'absent':
        if existing_param:
            policy_id = module.params['policy_id']
            l4_param_id = existing_param['id']
            route = f"{TETRATION_API_APPLICATION_POLICIES}/{policy_id}/l4_params/{l4_param_id}"

            payload = {
                "create_exclusion_filter": module.params['exclusion_filter']
            }

            delete_results = tet_module.run_method('DELETE',
                                                   route,
                                                   req_payload=payload)

            result['changed'] = True
            result['object'] = delete_results

    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------

    elif module.params['state'] == 'query':
        result['object'] = existing_param

    # Return result
    module.exit_json(**result)
Ejemplo n.º 14
0
def run_module():
    # define available arguments/parameters a user can pass to the module
    single_filter = dict(field=dict(type='str', required=True),
                         type=dict(type='str', required=True),
                         value=dict(type='str', required=True))

    query_filter_structure = dict(filters=dict(type='list',
                                               elements='dict',
                                               options=single_filter,
                                               required=True),
                                  type=dict(type='str', required=True))

    nested_query_filter_structure = dict(filters=dict(type='list',
                                                      elements='dict',
                                                      required=True),
                                         type=dict(type='str', required=True))

    module_args = dict(name=dict(type='str', required=False),
                       id=dict(type='str', required=False),
                       query_multiple=dict(type='dict',
                                           options=query_filter_structure,
                                           required=False),
                       query_raw=dict(type='dict',
                                      options=nested_query_filter_structure,
                                      required=False),
                       query_single=dict(type='dict',
                                         options=single_filter,
                                         reqired=False),
                       app_scope_id=dict(type='str', required=False),
                       primary=dict(type='bool', required=False,
                                    default=False),
                       public=dict(type='bool', required=False, default=False),
                       state=dict(choices=['present', 'absent', 'query'],
                                  required=True),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    result = {'changed': False, 'object': {}}

    result_obj = {}

    module = AnsibleModule(
        argument_spec=module_args,
        required_one_of=[
            ['name', 'id'],
        ],
        mutually_exclusive=[['query_multiple', 'query_raw', 'query_single']],
        required_by={'name': ['app_scope_id']})

    # Get current state of the object
    tet_module = TetrationApiModule(module)

    all_scopes_response = tet_module.run_method('GET', TETRATION_API_SCOPES)
    all_scopes_lookup = {s['id'] for s in all_scopes_response}

    all_inventory_filters_response = tet_module.run_method(
        'GET', TETRATION_API_INVENTORY_FILTER)
    all_inventory_filters_lookup = {(s['name'], s['app_scope_id']): s['id']
                                    for s in all_inventory_filters_response}

    unique_inventory_filter_name = module.params['name'], module.params[
        'app_scope_id']

    # Since the query parameter data all goes into one field eventually, just extract it into
    # A value here for use later on in the module
    query_parameters = ['query_multiple', 'query_raw', 'query_single']
    extracted_query_filter = {}
    for query in query_parameters:
        if module.params[query]:
            extracted_query_filter = module.params[query]

    # Validate items that should exist do exist
    if module.params['id'] and module.params[
            'id'] not in all_inventory_filters_lookup.values():
        error_message = "`id` passed into the module does not exist."
        module.fail_json(msg=error_message,
                         searched_filter_id=module.params['id'])

    if module.params['app_scope_id'] and module.params[
            'app_scope_id'] not in all_scopes_lookup:
        error_message = "`app_scope_id` passed into the module does not exist."
        module.fail_json(msg=error_message)

    if module.params['state'] == 'present':
        if module.params[
                'id'] or unique_inventory_filter_name in all_inventory_filters_lookup.keys(
                ):
            # Object exists, going to see if updates are needed
            if module.params['id']:
                inv_filter_to_update = module.params['id']
            else:
                inv_filter_to_update = all_inventory_filters_lookup[
                    unique_inventory_filter_name]

            route = f"{TETRATION_API_INVENTORY_FILTER}/{inv_filter_to_update}"
            response = tet_module.run_method('GET', route)

            req_payload = {
                'name': None,
                'query': {},
                'app_scope_id': None,
                'primary': None,
                'public': None
            }

            # Updating the Update Object
            payload_keys = [k for k in req_payload.keys()]
            for key in payload_keys:
                if module.params.get(key) is not None and module.params[
                        key] != response[key]:
                    req_payload[key] = module.params[key]
                elif key == 'query':
                    if extracted_query_filter and extracted_query_filter != response[
                            'short_query']:
                        req_payload[key] = extracted_query_filter
                    else:
                        req_payload.pop(key)
                else:
                    req_payload.pop(key)

            if req_payload:
                update_response = tet_module.run_method(
                    'PUT', route, req_payload=req_payload)
                result['changed'] = True
                result_obj = update_response
            else:
                result_obj = response

        elif unique_inventory_filter_name not in all_inventory_filters_lookup.keys(
        ):
            # Object does not exist, going to create it
            if not extracted_query_filter:
                error_message = (
                    'In order to create a new `inventory_filter` you must also have a `query` parameter defined.'
                )
                module.fail_json(msg=error_message)

            req_payload = {
                'name': module.params['name'],
                'query': extracted_query_filter,
                'app_scope_id': module.params['app_scope_id'],
                'primary': module.params['primary'],
                'public': module.params['public']
            }
            response = tet_module.run_method('POST',
                                             TETRATION_API_INVENTORY_FILTER,
                                             req_payload=req_payload)
            result_obj = response
            result['changed'] = True

    if module.params['state'] == 'absent':
        if module.params['id']:
            delete_id = module.params['id']
        else:
            delete_id = all_inventory_filters_lookup.get(
                unique_inventory_filter_name)

        if delete_id:
            route = f"{TETRATION_API_INVENTORY_FILTER}/{delete_id}"
            response = tet_module.run_method('DELETE', route)
            result_obj = response
            result['changed'] = True

    if module.params['state'] == 'query':

        if module.params['id']:
            search_id = module.params['id']
        else:
            if unique_inventory_filter_name in all_inventory_filters_lookup.keys(
            ):
                search_id = all_inventory_filters_lookup[
                    unique_inventory_filter_name]
            else:
                search_id = None

        if search_id:
            route = f"{TETRATION_API_INVENTORY_FILTER}/{search_id}"
            response = tet_module.run_method('GET', route)
            result_obj = response

    result['object'] = result_obj

    module.exit_json(**result)
Ejemplo n.º 15
0
def main():
    module_args = dict(app_id=dict(type='str', required=True),
                       consumer_filter_id=dict(type='str', required=False),
                       consumer_filter_name=dict(type='str', required=False),
                       provider_filter_id=dict(type='str', required=False),
                       provider_filter_name=dict(type='str', required=False),
                       version=dict(type='str', required=True),
                       rank=dict(type='str',
                                 required=True,
                                 choices=['DEFAULT', 'ABSOLUTE']),
                       policy_action=dict(type='str',
                                          required=True,
                                          choices=['ALLOW', 'DENY']),
                       priority=dict(type='int', required=True),
                       state=dict(required=True,
                                  choices=['present', 'absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
        mutually_exclusive=[['consumer_filter_id', 'consumer_filter_name'],
                            ['provider_filter_id', 'provider_filter_name']],
        required_one_of=[['consumer_filter_id', 'consumer_filter_name'],
                         ['provider_filter_id', 'provider_filter_name']],
        required_if=[
            ['state', 'present', ['policy_action', 'priority']],
        ])

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': None,
    }

    # =========================================================================
    # Verify the application ID exists
    route = f"{TETRATION_API_APPLICATIONS}/{module.params['app_id']}"

    existing_app = tet_module.run_method('GET', route)

    if not existing_app:
        module.fail_json(msg='Unable to find existing application id')

    # Get the existing API Scopes and Inventory Filters to verify the consumer and provider settings
    existing_app_scopes = tet_module.run_method('GET', TETRATION_API_SCOPES)

    app_scope_name_to_scope_id = {}
    app_scope_name_to_parent_scope_id = {}

    for scope in existing_app_scopes:
        app_scope_name_to_scope_id[scope['name']] = scope['id']
        app_scope_name_to_parent_scope_id[
            scope['name']] = scope['parent_app_scope_id']

    existing_inventory_filters = tet_module.run_method(
        'GET', TETRATION_API_INVENTORY_FILTER)

    # Build the inventory filter dict but check for duplicate entries and report them if found
    inv_filter_name_to_filter_id = {}
    duplicate_values = []
    for i in existing_inventory_filters:
        name = i['name']
        inv_id = i['id']
        if inv_id is None:
            module.fail_json(msg='An ID returned had a value of `None`')

        if inv_filter_name_to_filter_id.get(name) is None:
            inv_filter_name_to_filter_id[name] = inv_id
        else:
            duplicate_values.append(name)

    if duplicate_values:
        duplicate_values = set(duplicate_values)
        module.fail_json(msg=(
            'The Tetration Server has multiple inventory filters with the same name.  '
            'This is not supported with this module.  '
            f'Duplicate names are: {duplicate_values}'))

    consumer_id = None
    provider_id = None

    if module.params['consumer_filter_id']:
        # Verify the ID is a valid api scope or an inventory filter
        if module.params[
                'consumer_filter_id'] in app_scope_name_to_scope_id.values():
            consumer_id = module.params['consumer_filter_id']
        elif module.params[
                'consumer_filter_id'] in inv_filter_name_to_filter_id.values():
            consumer_id = module.params['consumer_filter_id']
    elif module.params['consumer_filter_name']:
        # Verify the ID is a valid api scope or an inventory filter
        filter_name = module.params['consumer_filter_name']
        if app_scope_name_to_scope_id.get(filter_name):
            consumer_id = app_scope_name_to_scope_id[filter_name]
        elif inv_filter_name_to_filter_id.get(filter_name):
            consumer_id = inv_filter_name_to_filter_id[filter_name]

    if module.params['provider_filter_id']:
        # Verify the ID is a valid api scope or an inventory filter
        if module.params[
                'provider_filter_id'] in app_scope_name_to_scope_id.values():
            provider_id = module.params['provider_filter_id']
        elif module.params[
                'provider_filter_id'] in inv_filter_name_to_filter_id.values():
            provider_id = module.params['provider_filter_id']
    elif module.params['provider_filter_name']:
        # Verify the ID is a valid api scope or an inventory filter
        filter_name = module.params['provider_filter_name']
        if app_scope_name_to_scope_id.get(filter_name):
            provider_id = app_scope_name_to_scope_id[filter_name]
        elif inv_filter_name_to_filter_id.get(filter_name):
            provider_id = inv_filter_name_to_filter_id[filter_name]

    if consumer_id is None:
        module.fail_json(msg='The provided consumer name or id is invalid')

    if provider_id is None:
        module.fail_json(msg='The provided provider name or id is invalid')

    # Get the policies for the application
    if module.params['rank'] == 'ABSOLUTE':
        policy_route = f"{route}/absolute_policies"
    else:
        policy_route = f"{route}/default_policies"

    existing_policies = tet_module.run_method('GET', policy_route)

    # Now figure out if the policy defined in the module exists
    existing_policy = None
    existing_policy_id = None

    desired_unique_id = (module.params['priority'],
                         module.params['policy_action'], consumer_id,
                         provider_id)

    found_policies = []
    for policy in existing_policies:
        policy_id = (policy['priority'], policy['action'],
                     policy['consumer_filter_id'],
                     policy['provider_filter_id'])
        if policy_id == desired_unique_id:
            found_policies.append(policy)

    if len(found_policies) == 1:
        existing_policy = found_policies[0]
        existing_policy_id = found_policies[0]['id']
    elif len(found_policies) >= 2:
        module.fail_json(
            msg=("Multiple policies found with the given criteria.  "
                 "Cannot use this module if multiple policies match the "
                 "`priority`, `action`, `consumer`, and `provider` fields.  "
                 f"Duplicate policies: {found_policies}"))

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':
        if existing_policy:
            result['object'] = existing_policy
        else:
            req_payload = {
                "version": module.params['version'],
                "rank": module.params['rank'],
                "policy_action": module.params['policy_action'],
                "priority": module.params['priority'],
                "consumer_filter_id": consumer_id,
                "provider_filter_id": provider_id,
            }
            add_policy_route = f"{route}/policies"
            result['object'] = tet_module.run_method('POST',
                                                     add_policy_route,
                                                     req_payload=req_payload)
            result['changed'] = True

    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------

    elif module.params['state'] == 'absent':
        if existing_policy:
            delete_policy_route = f"{TETRATION_API_APPLICATION_POLICIES}/{existing_policy_id}"

            result['object'] = tet_module.run_method('DELETE',
                                                     delete_policy_route)
            result['changed'] = True

    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------

    elif module.params['state'] == 'query':
        result['object'] = existing_policy

    # Return result
    module.exit_json(**result)
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(app_scope_id=dict(type='str',
                                         required=False,
                                         default=''),
                       app_scope_name=dict(type='str',
                                           required=False,
                                           default=''),
                       role_ids=dict(type='list', required=False, default=[]),
                       role_names=dict(type='list', required=False,
                                       default=[]),
                       email=dict(type='str', required=True),
                       first_name=dict(type='str', required=False, default=''),
                       last_name=dict(type='str', required=False, default=''),
                       state=dict(type='str',
                                  required=True,
                                  choices=['present', 'absent', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    # Create the objects that will be returned
    result = {
        "object": None,
        "changed": False,
    }

    result_obj = dict(app_scope_id=None,
                      created_at=None,
                      disabled_at=None,
                      email=None,
                      first_name=None,
                      id=None,
                      last_name=None,
                      role_ids=[])

    # Creating the Ansible Module
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
        mutually_exclusive=[['app_scope_id', 'app_scope_name'],
                            ['role_ids', 'role_names']])

    tet_module = TetrationApiModule(module)

    # Create an App Scope Name to ID Lookup Table
    all_app_scopes_response = tet_module.run_method('GET',
                                                    TETRATION_API_SCOPES)
    all_app_scopes_lookup = {
        r['name'].upper(): r['id']
        for r in all_app_scopes_response
    }

    # Create a Role Name to ID Lookup Table
    all_roles_response = tet_module.run_method('GET', TETRATION_API_ROLE)
    all_roles_lookup = {r['name']: r['id'] for r in all_roles_response}

    # Role and App Scope Validation
    # Done here so it does not have to be done elsewhere in the module
    invalid_parameters = {}
    if module.params['app_scope_id']:
        scope_id = module.params['app_scope_id']
        if scope_id not in all_app_scopes_lookup.values():
            invalid_parameters['app_scope_id'] = scope_id
    if module.params['app_scope_name']:
        scope_name = module.params['app_scope_name']
        # case insensitive compare - all keys will be upper case.
        if scope_name.upper() not in all_app_scopes_lookup.keys():
            invalid_parameters['app_scope_name'] = scope_name
    if module.params['role_ids']:
        invalid_role_ids = [
            id for id in module.params['role_ids']
            if id not in all_roles_lookup.values()
        ]
        if invalid_role_ids:
            invalid_parameters['role_ids'] = invalid_role_ids
    if module.params['role_names']:
        invalid_role_names = [
            name for name in module.params['role_names']
            if name not in all_roles_lookup.keys()
        ]
        if invalid_role_names:
            invalid_parameters['role_names'] = invalid_role_names

    if invalid_parameters:
        error_message = "Check the `invalid parameters` object for the invalid parameters"
        module.fail_json(msg=error_message,
                         invalid_parameters=invalid_parameters)

    # The first thing we have to do is get the object.
    returned_user_object = tet_module.get_object(
        target=TETRATION_API_USER,
        params=dict(include_disabled='true'),
        filter=dict(email=module.params['email']),
    )

    if returned_user_object:
        user_id = returned_user_object['id']
    else:
        user_id = None

    # Create the user, update the user, or verify no changes needed
    if module.params['state'] == 'present':
        if returned_user_object is None:
            # User does not exist, so we're going to create it
            req_payload = {
                "first_name": "",
                "last_name": "",
                "email": "",
                "app_scope_id": "",
                "role_ids": []
            }

            # Check for required parameters when creating a user
            if not all(
                [module.params['first_name'], module.params['last_name']]):
                error_message = (
                    'The first name and last name parameters are required when '
                    'creating a new user.  '
                    'First Name: {} '
                    'Last Name: {}').format(module.params['first_name'],
                                            module.params['last_name'])
                module.fail_json(msg=error_message)

            # Now that we know the required parameters exist, update the request object
            req_payload['first_name'] = module.params['first_name']
            req_payload['last_name'] = module.params['last_name']
            req_payload['email'] = module.params['email']

            # Deal with the `app_scope` parameters
            if module.params['app_scope_name']:
                # Convert the name to a scope id
                app_scope_id = all_app_scopes_lookup.get(
                    module.params['app_scope_name'].upper())
                req_payload['app_scope_id'] = app_scope_id

            elif module.params['app_scope_id']:
                req_payload['app_scope_id'] = module.params['app_scope_id']
            else:
                # No data was provided, remove the parameter
                req_payload.pop('app_scope_id')

            # Deal with the `role` parameters
            if module.params['role_names']:
                # Convert the list of names to a list of id's
                for role_name in module.params['role_names']:
                    role_id = all_roles_lookup.get(role_name)
                    req_payload['role_ids'].append(role_id)

            elif module.params['role_ids']:
                req_payload['role_ids'] = module.params['role_ids']
            else:
                # No data was provided, remove the parameter
                req_payload.pop('role_ids')

            if module.check_mode:
                # We just document what we would have changed
                result['changed'] = True
                for k in result_obj.keys():
                    result_obj[k] = req_payload.get(k)
            else:
                method_results = tet_module.run_method('POST',
                                                       TETRATION_API_USER,
                                                       req_payload=req_payload)
                if method_results:
                    result['changed'] = True
                    for k in result_obj.keys():
                        result_obj[k] = method_results.get(k)

        elif returned_user_object is not None:

            if returned_user_object['disabled_at']:
                # Re-enable the user if it's disabled
                enable_route = f'{TETRATION_API_USER}/{user_id}/enable'
                if not module.check_mode:
                    method_results = tet_module.run_method(
                        'POST', enable_route)
                    result_obj['disabled_at'] = method_results['disabled_at']
                else:
                    result_obj['disabled_at'] = None
                result['changed'] = True

            req_payload = {
                "first_name": "",
                "last_name": "",
                "email": "",
                "app_scope_id": ""
            }

            # Set the request payload object to update the user
            if module.params['first_name'] and returned_user_object[
                    'first_name'] != module.params['first_name']:
                req_payload['first_name'] = module.params['first_name']
                result_obj['first_name'] = module.params['first_name']
                result['changed'] = True
            else:
                result_obj['first_name'] = returned_user_object['first_name']
                req_payload.pop('first_name')

            if module.params['last_name'] and returned_user_object[
                    'last_name'] != module.params['last_name']:
                req_payload['last_name'] = module.params['last_name']
                result_obj['last_name'] = module.params['last_name']
                result['changed'] = True
            else:
                result_obj['last_name'] = returned_user_object['last_name']
                req_payload.pop('last_name')

            if module.params['email'] and returned_user_object[
                    'email'] != module.params['email']:
                req_payload['email'] = module.params['email']
                result_obj['email'] = module.params['email']
                result['changed'] = True
            else:
                result_obj['email'] = returned_user_object['email']
                req_payload.pop('email')

            if module.params['app_scope_id']:
                if returned_user_object['app_scope_id'] != module.params[
                        'app_scope_id']:
                    req_payload['app_scope_id'] = module.params['app_scope_id']
                    result_obj['app_scope_id'] = module.params['app_scope_id']
                    result['changed'] = True
                else:
                    result_obj['app_scope_id'] = returned_user_object[
                        'app_scope_id']
                    req_payload.pop('app_scope_id')
            elif module.params['app_scope_name']:
                app_scope_id = all_app_scopes_lookup.get(
                    module.params['app_scope_name'])
                if returned_user_object['app_scope_id'] != app_scope_id:
                    req_payload['app_scope_id'] = app_scope_id
                    result_obj['app_scope_id'] = app_scope_id
                    result['changed'] = True
                else:
                    result_obj['app_scope_id'] = returned_user_object[
                        'app_scope_id']
                    req_payload.pop('app_scope_id')
            else:
                result_obj['app_scope_id'] = returned_user_object[
                    'app_scope_id']
                req_payload.pop('app_scope_id')

            update_route = f'{TETRATION_API_USER}/{user_id}'
            if not module.check_mode:
                method_results = tet_module.run_method('PUT',
                                                       update_route,
                                                       req_payload=req_payload)

            roles_to_add = []
            roles_to_delete = []

            if module.params['role_ids']:
                current_state = set(returned_user_object['role_ids'])
                desired_state = set(module.params['role_ids'])

                roles_to_add = list(desired_state.difference(current_state))
                roles_to_delete = list(current_state.difference(desired_state))

            elif module.params['role_names']:
                current_state = set(returned_user_object['role_ids'])
                desired_state = []
                for name in module.params['role_names']:
                    desired_state.append(all_roles_lookup[name])
                desired_state = set(desired_state)

                roles_to_add = list(desired_state.difference(current_state))
                roles_to_delete = list(current_state.difference(desired_state))

            # Set the results equal to what it is currently
            result_obj['role_ids'] = returned_user_object['role_ids']

            req_payload = {
                "role_id": None,
            }
            for role in roles_to_add:
                add_role_route = f"{TETRATION_API_USER}/{user_id}/add_role"
                req_payload['role_id'] = role
                result_obj['role_ids'].append(role)
                if not module.check_mode:
                    method_results = tet_module.run_method(
                        'PUT', add_role_route, req_payload=req_payload)
                result['changed'] = True
            for role in roles_to_delete:
                req_payload['role_id'] = role
                result_obj['role_ids'] = [
                    r for r in result_obj['role_ids'] if r != role
                ]
                remove_role_route = f"{TETRATION_API_USER}/{user_id}/remove_role"
                if not module.check_mode:
                    method_results = tet_module.run_method(
                        'DELETE', remove_role_route, req_payload=req_payload)
                result['changed'] = True

    if module.params['state'] == 'absent':
        if returned_user_object and not returned_user_object['disabled_at']:
            # If the user exists and it's not already disabled, a change will occur
            result['changed'] = True

            if not module.check_mode:
                route = f"{TETRATION_API_USER}/{user_id}"
                method_results = tet_module.run_method('DELETE', route)
                if method_results:
                    for k in result_obj.keys():
                        result_obj[k] = method_results.get(k)
            else:
                # Extracting the reqired info from what was returned from Tetration
                result_obj['app_scope_id'] = returned_user_object[
                    'app_scope_id']
                result_obj['created_at'] = returned_user_object['created_at']
                result_obj['disabled_at'] = returned_user_object['disabled_at']
                result_obj['email'] = returned_user_object['email']
                result_obj['first_name'] = returned_user_object['first_name']
                result_obj['id'] = returned_user_object['id']
                result_obj['last_name'] = returned_user_object['last_name']
                result_obj['role_ids'] = returned_user_object['role_ids']

    if module.params['state'] == 'query':
        result['changed'] = False
        if returned_user_object is not None:
            # Extracting the reqired info from what was returned from Tetration
            result_obj['app_scope_id'] = returned_user_object['app_scope_id']
            result_obj['created_at'] = returned_user_object['created_at']
            result_obj['disabled_at'] = returned_user_object['disabled_at']
            result_obj['email'] = returned_user_object['email']
            result_obj['first_name'] = returned_user_object['first_name']
            result_obj['id'] = returned_user_object['id']
            result_obj['last_name'] = returned_user_object['last_name']
            result_obj['role_ids'] = returned_user_object['role_ids']

    result['object'] = result_obj
    # in the event of a successful module execution, you will want to
    # simple AnsibleModule.exit_json(), passing the key/value results
    module.exit_json(**result)
def run_module():
    # define available arguments/parameters a user can pass to the module
    single_filter = dict(field=dict(type='str', required=True),
                         type=dict(type='str', required=True),
                         value=dict(type='str', required=True))

    query_filter_structure = dict(filters=dict(type='list',
                                               elements='dict',
                                               options=single_filter,
                                               required=True),
                                  type=dict(type='str', required=True))

    nested_query_filter_structure = dict(filters=dict(type='list',
                                                      elements='dict',
                                                      required=True),
                                         type=dict(type='str', required=True))

    module_args = dict(scope_id=dict(type='str', required=False),
                       short_name=dict(type='str', required=False),
                       description=dict(type='str', required=False),
                       query_multiple=dict(type='dict',
                                           options=query_filter_structure,
                                           required=False),
                       query_raw=dict(type='dict',
                                      options=nested_query_filter_structure,
                                      required=False),
                       query_single=dict(type='dict',
                                         options=single_filter,
                                         reqired=False),
                       parent_app_scope_id=dict(type='str', required=False),
                       policy_priority=dict(type='int', required=False),
                       state=dict(choices=['present', 'absent'],
                                  required=True),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    # Create the objects that will be returned
    result = {"object": None, "changed": False}
    result_obj = dict(child_app_scope_ids=[],
                      description=None,
                      dirty=None,
                      dirty_short_query=None,
                      id=None,
                      name=None,
                      parent_app_scope_id=None,
                      policy_priority=None,
                      query=None,
                      root_app_scope_id=None,
                      short_name=None,
                      short_query=None,
                      updated_at=None,
                      vrf_id=None)

    # Creating the Ansible Module
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
        required_one_of=[
            ['scope_id', 'short_name'],
        ],
        mutually_exclusive=[['query_multiple', 'query_raw', 'query_single']],
        required_by={'short_name': ['parent_app_scope_id']},
    )

    # Get current state of the object
    tet_module = TetrationApiModule(module)
    all_scopes_response = tet_module.run_method('GET', TETRATION_API_SCOPES)

    all_scopes_lookup = {(s['short_name'], s['parent_app_scope_id']): s['id']
                         for s in all_scopes_response}
    unique_scope_name = module.params['short_name'], module.params[
        'parent_app_scope_id']

    # Verify the passed in data is valid
    if module.params['scope_id'] and module.params[
            'scope_id'] not in all_scopes_lookup.values():
        error_message = "`scope_id` passed into the module does not exist."
        module.fail_json(msg=error_message,
                         searched_scope=module.params['scope_id'])

    if module.params['parent_app_scope_id'] and module.params[
            'parent_app_scope_id'] not in all_scopes_lookup.values():
        error_message = "`parent_app_scope_id` passed into the module does not exist."
        module.fail_json(msg=error_message)

    # Since the query parameter data all goes into one field eventually, just extract it into
    # A value here for use later on in the module
    query_parameters = ['query_multiple', 'query_raw', 'query_single']
    extracted_query_filter = {}
    for query in query_parameters:
        if module.params[query]:
            extracted_query_filter = module.params[query]

    # Implment changes as defined in the module
    if module.params['state'] == 'present':
        if module.params[
                'scope_id'] or unique_scope_name in all_scopes_lookup.keys():
            # Object exists, doing an update
            if module.params['scope_id']:
                scope_id_to_update = module.params['scope_id']
            else:
                scope_id_to_update = all_scopes_lookup[unique_scope_name]

            route = f"{TETRATION_API_SCOPES}/{scope_id_to_update}"
            response = tet_module.run_method('GET', route)

            req_payload = {
                'short_name': None,
                'short_query': {},
                'description': None,
                'parent_app_scope_id': None,
                'policy_priority': None
            }

            payload_keys = [k for k in req_payload.keys()]
            for key in payload_keys:
                if module.params.get(key) is not None and module.params[
                        key] != response[key]:
                    req_payload[key] = module.params[key]
                elif key == 'short_query':
                    if extracted_query_filter and extracted_query_filter != response[
                            'short_query']:
                        req_payload[key] = extracted_query_filter
                    else:
                        req_payload.pop(key)
                else:
                    req_payload.pop(key)

            # Updating the Update Object
            if req_payload:
                update_response = tet_module.run_method(
                    'PUT', route, req_payload=req_payload)
                result['changed'] = True
                result_obj = update_response
            else:
                result_obj = response

        elif unique_scope_name not in all_scopes_lookup.keys():
            # Creating a new object
            if not extracted_query_filter:
                error_message = (
                    'In order to create a new `scope` you must also add a query parameter.'
                )
                module.fail_json(msg=error_message)

            req_payload = {
                'short_name': module.params['short_name'],
                'short_query': extracted_query_filter,
                'description': module.params['description'],
                'parent_app_scope_id': module.params['parent_app_scope_id'],
                'policy_priority': module.params['policy_priority']
            }
            response = tet_module.run_method('POST',
                                             TETRATION_API_SCOPES,
                                             req_payload=req_payload)
            result_obj = response
            result['changed'] = True
        else:
            error_message = "An unknown error occured"
            module.fail_json(msg=error_message)
    elif module.params['state'] == 'absent':
        if module.params[
                'scope_id'] or unique_scope_name in all_scopes_lookup.keys():
            # User exists, doing an update
            if module.params['scope_id']:
                scope_id_to_delete = module.params['scope_id']
            else:
                scope_id_to_delete = all_scopes_lookup[unique_scope_name]

            route = f"{TETRATION_API_SCOPES}/{scope_id_to_delete}"
            response = tet_module.run_method('DELETE', route)

            if response.get('details'):
                error_message = "There are objects using this scope.  Review the `details` tag for more details."
                module.fail_json(msg=error_message,
                                 details=response['details'])
            else:
                result['changed'] = True
                result_obj = response

    result['object'] = result_obj
    module.exit_json(**result)
def main():
    module_args = dict(application_id=dict(type='str', required=True),
                       version=dict(type='str', required=False, default=None),
                       state=dict(required=True,
                                  choices=['enabled', 'disabled']),
                       provider=dict(type='dict',
                                     required=True,
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(argument_spec=module_args)

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {
        'changed': False,
        'object': None,
    }

    # =========================================================================
    # Get current state of the object
    app_route = f"{TETRATION_API_APPLICATIONS}/{module.params['application_id']}"
    existing_app = tet_module.run_method('GET', app_route)

    if not existing_app:
        module.fail_json(
            msg=
            f"Unable to find application with id: {module.params['application_id']}"
        )

    # ---------------------------------
    # STATE == 'enabled'
    # ---------------------------------
    if module.params['state'] == 'enabled':
        if existing_app['enforcement_enabled'] is False:
            result['changed'] = True
        elif module.params['version'] is not None and existing_app[
                'enforced_version'] != int(
                    module.params['version'].strip('p')):
            # Per the API guide, the preferred method of passing the version is `p4` for Version 4
            # But the version returned from the api is just an int.
            # This deals with passing in an int or the p for for the version
            result['changed'] = True

        if result['changed']:
            req_payload = {}
            if module.params['version']:
                req_payload['version'] = module.params['version']

            route = f"{TETRATION_API_APPLICATIONS}/{module.params['application_id']}/enable_enforce"
            result['object'] = tet_module.run_method('POST',
                                                     route,
                                                     req_payload=req_payload)

    # ---------------------------------
    # STATE == 'disabled'
    # ---------------------------------
    elif module.params['state'] == 'disabled':
        result['changed'] = existing_app['enforcement_enabled']
        if result['changed']:
            route = f"{TETRATION_API_APPLICATIONS}/{module.params['application_id']}/disable_enforce"
            result['object'] = tet_module.run_method('POST', route)

    # Return result
    module.exit_json(**result)
Ejemplo n.º 19
0
def main():
    ''' Main entry point for module execution
    '''
    # Module specific spec
    module_args = dict(attributes=dict(type='dict'),
                       ip_address=dict(type='str', required=False),
                       ip_subnet=dict(type='str', required=False),
                       root_scope_name=dict(type='str', required=True),
                       state=dict(type="str",
                                  required=True,
                                  choices=['absent', 'present', 'query']),
                       provider=dict(type='dict',
                                     options=TETRATION_PROVIDER_SPEC))

    module = AnsibleModule(argument_spec=module_args,
                           required_one_of=[['ip_address', 'ip_subnet']],
                           mutually_exclusive=[['ip_address', 'ip_subnet']],
                           required_if=[['state', 'present', ['attributes']]])

    ip_object = ''

    # Verify a valid IP address was passed in
    if module.params['ip_address']:
        try:
            ip_object = str(ip_address(module.params['ip_address']))
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 Address entered.  Value entered: {module.params['ip_address']}"
            module.fail_json(msg=error_message)

    # Verify a valid IP subnet was passed in
    if module.params['ip_subnet']:
        try:
            ip_object = str(ip_network(module.params['ip_subnet']))
        except ValueError:
            error_message = f"Invalid IPv4 or IPv6 subnet entered.  Value entered: {module.params['ip_subnet']}"
            module.fail_json(msg=error_message)

    # Throw error if state is absent and annotations passed
    if module.params['state'] == 'absent' and module.params[
            'attributes'] is not None:
        module.fail_json(
            msg=
            'attributes cannot be passed for state `absent` because all attributes are cleared'
        )

    tet_module = TetrationApiModule(module)

    # These are all elements we put in our return JSON object for clarity
    result = {"object": None, "changed": False, "tet_warnings": None}
    route = f"{TETRATION_API_INVENTORY_TAG}/{module.params['root_scope_name']}"

    # =========================================================================
    # Get current state of the object
    params = {'ip': ip_object}
    query_result = tet_module.run_method('GET', route, params=params)
    current_attributes = query_result if query_result else {}

    # ---------------------------------
    # STATE == 'present'
    # ---------------------------------
    if module.params['state'] == 'present':
        if not tet_module.is_subset(module.params['attributes'],
                                    current_attributes):
            req_payload = {
                'ip': ip_object,
                'attributes': module.params['attributes']
            }

            result['tet_warnings'] = tet_module.run_method(
                'POST', route, req_payload=req_payload)
            result['object'] = tet_module.run_method('GET',
                                                     route,
                                                     params=params)
            result['changed'] = True

        else:
            result['object'] = current_attributes

    # ---------------------------------
    # STATE == 'absent'
    # ---------------------------------
    elif module.params['state'] == 'absent':
        if current_attributes:
            req_payload = {'ip': ip_object}
            tet_module.run_method('DELETE', route, req_payload=req_payload)

            result['changed'] = True

    # ---------------------------------
    # STATE == 'query'
    # ---------------------------------
    elif module.params['state'] == 'query':
        if current_attributes:
            result['object'] = current_attributes

    module.exit_json(**result)