265 lines
8.6 KiB
Python
265 lines
8.6 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright: (c) 2019, Kevin Breit (@kbreit) <kevin.breit@kevinbreit.net>
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
__metaclass__ = type
|
|
|
|
ANSIBLE_METADATA = {
|
|
'metadata_version': '1.1',
|
|
'status': ['preview'],
|
|
'supported_by': 'community'
|
|
}
|
|
|
|
DOCUMENTATION = r'''
|
|
---
|
|
module: meraki_mx_malware
|
|
short_description: Manage Malware Protection in the Meraki cloud
|
|
description:
|
|
- Fully configure malware protection in a Meraki environment.
|
|
notes:
|
|
- Some of the options are likely only used for developers within Meraki.
|
|
options:
|
|
state:
|
|
description:
|
|
- Specifies whether object should be queried, created/modified, or removed.
|
|
choices: [absent, present, query]
|
|
default: query
|
|
type: str
|
|
net_name:
|
|
description:
|
|
- Name of network which configuration is applied to.
|
|
aliases: [network]
|
|
type: str
|
|
net_id:
|
|
description:
|
|
- ID of network which configuration is applied to.
|
|
type: str
|
|
allowed_urls:
|
|
description:
|
|
- List of URLs to whitelist.
|
|
type: list
|
|
elements: dict
|
|
suboptions:
|
|
url:
|
|
description:
|
|
- URL string to allow.
|
|
type: str
|
|
comment:
|
|
description:
|
|
- Human readable information about URL.
|
|
type: str
|
|
allowed_files:
|
|
description:
|
|
- List of files to whitelist.
|
|
type: list
|
|
elements: dict
|
|
suboptions:
|
|
sha256:
|
|
description:
|
|
- 256-bit hash of file.
|
|
type: str
|
|
aliases: [ hash ]
|
|
comment:
|
|
description:
|
|
- Human readable information about file.
|
|
type: str
|
|
mode:
|
|
description:
|
|
- Enabled or disabled state of malware protection.
|
|
choices: [disabled, enabled]
|
|
type: str
|
|
|
|
author:
|
|
- Kevin Breit (@kbreit)
|
|
extends_documentation_fragment: cisco.meraki.meraki
|
|
'''
|
|
|
|
EXAMPLES = r'''
|
|
- name: Enable malware protection
|
|
meraki_malware:
|
|
auth_key: abc123
|
|
state: present
|
|
org_name: YourOrg
|
|
net_name: YourNet
|
|
mode: enabled
|
|
delegate_to: localhost
|
|
|
|
- name: Set whitelisted url
|
|
meraki_malware:
|
|
auth_key: abc123
|
|
state: present
|
|
org_name: YourOrg
|
|
net_name: YourNet
|
|
mode: enabled
|
|
allowed_urls:
|
|
- url: www.ansible.com
|
|
comment: Ansible
|
|
- url: www.google.com
|
|
comment: Google
|
|
delegate_to: localhost
|
|
|
|
- name: Set whitelisted file
|
|
meraki_malware:
|
|
auth_key: abc123
|
|
state: present
|
|
org_name: YourOrg
|
|
net_name: YourNet
|
|
mode: enabled
|
|
allowed_files:
|
|
- sha256: e82c5f7d75004727e1f3b94426b9a11c8bc4c312a9170ac9a73abace40aef503
|
|
comment: random zip
|
|
delegate_to: localhost
|
|
|
|
- name: Get malware settings
|
|
meraki_malware:
|
|
auth_key: abc123
|
|
state: query
|
|
org_name: YourNet
|
|
net_name: YourOrg
|
|
delegate_to: localhost
|
|
'''
|
|
|
|
RETURN = r'''
|
|
data:
|
|
description: List of administrators.
|
|
returned: success
|
|
type: complex
|
|
contains:
|
|
mode:
|
|
description: Mode to enable or disable malware scanning.
|
|
returned: success
|
|
type: str
|
|
sample: enabled
|
|
allowed_files:
|
|
description: List of files which are whitelisted.
|
|
returned: success
|
|
type: complex
|
|
contains:
|
|
sha256:
|
|
description: sha256 hash of whitelisted file.
|
|
returned: success
|
|
type: str
|
|
sample: e82c5f7d75004727e1f3b94426b9a11c8bc4c312a9170ac9a73abace40aef503
|
|
comment:
|
|
description: Comment about the whitelisted entity
|
|
returned: success
|
|
type: str
|
|
sample: TPS report
|
|
allowed_urls:
|
|
description: List of URLs which are whitelisted.
|
|
returned: success
|
|
type: complex
|
|
contains:
|
|
url:
|
|
description: URL of whitelisted site.
|
|
returned: success
|
|
type: str
|
|
sample: site.com
|
|
comment:
|
|
description: Comment about the whitelisted entity
|
|
returned: success
|
|
type: str
|
|
sample: Corporate HQ
|
|
'''
|
|
|
|
from ansible.module_utils.basic import AnsibleModule, json
|
|
from ansible_collections.cisco.meraki.plugins.module_utils.network.meraki.meraki import MerakiModule, meraki_argument_spec
|
|
|
|
|
|
def main():
|
|
# define the available arguments/parameters that a user can pass to
|
|
# the module
|
|
|
|
urls_arg_spec = dict(url=dict(type='str'),
|
|
comment=dict(type='str'),
|
|
)
|
|
|
|
files_arg_spec = dict(sha256=dict(type='str', aliases=['hash']),
|
|
comment=dict(type='str'),
|
|
)
|
|
|
|
argument_spec = meraki_argument_spec()
|
|
argument_spec.update(state=dict(type='str', choices=['absent', 'present', 'query'], default='query'),
|
|
net_name=dict(type='str', aliases=['network']),
|
|
net_id=dict(type='str'),
|
|
mode=dict(type='str', choices=['enabled', 'disabled']),
|
|
allowed_urls=dict(type='list', default=None, elements='dict', options=urls_arg_spec),
|
|
allowed_files=dict(type='list', default=None, elements='dict', options=files_arg_spec),
|
|
)
|
|
|
|
# the AnsibleModule object will be our abstraction working with Ansible
|
|
# this includes instantiation, a couple of common attr would be the
|
|
# args/params passed to the execution, as well as if the module
|
|
# supports check mode
|
|
module = AnsibleModule(argument_spec=argument_spec,
|
|
supports_check_mode=True,
|
|
)
|
|
meraki = MerakiModule(module, function='malware')
|
|
|
|
meraki.params['follow_redirects'] = 'all'
|
|
|
|
query_url = {'malware': '/networks/{net_id}/appliance/security/malware'}
|
|
update_url = {'malware': '/networks/{net_id}/appliance/security/malware'}
|
|
|
|
meraki.url_catalog['get_one'].update(query_url)
|
|
meraki.url_catalog['update'] = update_url
|
|
|
|
org_id = meraki.params['org_id']
|
|
if org_id is None:
|
|
org_id = meraki.get_org_id(meraki.params['org_name'])
|
|
net_id = meraki.params['net_id']
|
|
if net_id is None:
|
|
nets = meraki.get_nets(org_id=org_id)
|
|
net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets)
|
|
|
|
# Check for argument completeness
|
|
if meraki.params['state'] == 'present':
|
|
if meraki.params['allowed_files'] is not None or meraki.params['allowed_urls'] is not None:
|
|
if meraki.params['mode'] is None:
|
|
meraki.fail_json(msg="mode must be set when allowed_files or allowed_urls is set.")
|
|
|
|
# Assemble payload
|
|
if meraki.params['state'] == 'present':
|
|
payload = dict()
|
|
if meraki.params['mode'] is not None:
|
|
payload['mode'] = meraki.params['mode']
|
|
if meraki.params['allowed_urls'] is not None:
|
|
payload['allowedUrls'] = meraki.params['allowed_urls']
|
|
if meraki.params['allowed_files'] is not None:
|
|
payload['allowedFiles'] = meraki.params['allowed_files']
|
|
|
|
if meraki.params['state'] == 'query':
|
|
path = meraki.construct_path('get_one', net_id=net_id)
|
|
data = meraki.request(path, method='GET')
|
|
if meraki.status == 200:
|
|
meraki.result['data'] = data
|
|
elif meraki.params['state'] == 'present':
|
|
path = meraki.construct_path('get_one', net_id=net_id)
|
|
original = meraki.request(path, method='GET')
|
|
if meraki.is_update_required(original, payload):
|
|
if meraki.module.check_mode is True:
|
|
meraki.generate_diff(original, payload)
|
|
original.update(payload)
|
|
meraki.result['data'] = original
|
|
meraki.result['changed'] = True
|
|
meraki.exit_json(**meraki.result)
|
|
path = meraki.construct_path('update', net_id=net_id)
|
|
data = meraki.request(path, method='PUT', payload=json.dumps(payload))
|
|
if meraki.status == 200:
|
|
meraki.generate_diff(original, data)
|
|
meraki.result['data'] = data
|
|
meraki.result['changed'] = True
|
|
else:
|
|
meraki.result['data'] = original
|
|
|
|
# in the event of a successful module execution, you will want to
|
|
# simple AnsibleModule.exit_json(), passing the key/value results
|
|
meraki.exit_json(**meraki.result)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|