Ejemplo n.º 1
0
    def _connect(self):
        """ Obtains an access_token and saves it for use in API accesses
        """
        self.baseurl = self.module.params.get('auth_keycloak_url')
        self.validate_certs = self.module.params.get('validate_certs')

        auth_url = URL_TOKEN.format(url=self.baseurl, realm=self.module.params.get('auth_realm'))

        payload = {'grant_type': 'password',
                   'client_id': self.module.params.get('auth_client_id'),
                   'client_secret': self.module.params.get('auth_client_secret'),
                   'username': self.module.params.get('auth_username'),
                   'password': self.module.params.get('auth_password')}

        # Remove empty items, for instance missing client_secret
        payload = dict((k, v) for k, v in payload.items() if v is not None)

        try:
            r = json.load(open_url(auth_url, method='POST',
                                   validate_certs=self.validate_certs, data=urlencode(payload)))
        except ValueError as e:
            self.module.fail_json(msg='API returned invalid JSON when trying to obtain access token from %s: %s'
                                      % (auth_url, str(e)))
        except Exception as e:
            self.module.fail_json(msg='Could not obtain access token from %s: %s'
                                      % (auth_url, str(e)))

        if 'access_token' in r:
            self.token = r['access_token']
            self.restheaders = {'Authorization': 'Bearer ' + self.token,
                                'Content-Type': 'application/json'}

        else:
            self.module.fail_json(msg='Could not obtain access token from %s' % auth_url)
Ejemplo n.º 2
0
def send_msg_v1(module, token, room, msg_from, msg, msg_format='text',
                color='yellow', notify=False, api=MSG_URI_V1):
    '''sending message to hipchat v1 server'''

    params = {}
    params['room_id'] = room
    params['from'] = msg_from[:15]  # max length is 15
    params['message'] = msg
    params['message_format'] = msg_format
    params['color'] = color
    params['api'] = api
    params['notify'] = int(notify)

    url = api + MSG_URI_V1 + "?auth_token=%s" % (token)
    data = urlencode(params)

    if module.check_mode:
        # In check mode, exit before actually sending the message
        module.exit_json(changed=False)

    response, info = fetch_url(module, url, data=data)
    if info['status'] == 200:
        return response.read()
    else:
        module.fail_json(msg="failed to send message, return status=%s" % str(info['status']))
Ejemplo n.º 3
0
    def get_dns_records(self,zone_name=None,type=None,record=None,value=''):
        if not zone_name:
            zone_name = self.zone
        if not type:
            type = self.type
        if not record:
            record = self.record
        # necessary because None as value means to override user
        # set module value
        if (not value) and (value is not None):
            value = self.value

        zone_id = self._get_zone_id()
        api_call = '/zones/{0}/dns_records'.format(zone_id)
        query = {}
        if type:
            query['type'] = type
        if record:
            query['name'] = record
        if value:
            query['content'] = value
        if query:
            api_call += '?' + urlencode(query)

        records,status = self._cf_api_call(api_call)
        return records
Ejemplo n.º 4
0
def post_sendgrid_api(module, username, password, from_address, to_addresses,
        subject, body, api_key=None, cc=None, bcc=None, attachments=None,
        html_body=False, from_name=None, headers=None):

    if not HAS_SENDGRID:
        SENDGRID_URI = "https://api.sendgrid.com/api/mail.send.json"
        AGENT = "Ansible"
        data = {'api_user': username, 'api_key':password,
                'from':from_address, 'subject': subject, 'text': body}
        encoded_data = urlencode(data)
        to_addresses_api = ''
        for recipient in to_addresses:
            recipient = to_bytes(recipient, errors='surrogate_or_strict')
            to_addresses_api += '&to[]=%s' % recipient
        encoded_data += to_addresses_api

        headers = { 'User-Agent': AGENT,
                'Content-type': 'application/x-www-form-urlencoded',
                'Accept': 'application/json'}
        return fetch_url(module, SENDGRID_URI, data=encoded_data, headers=headers, method='POST')
    else:

        if api_key:
            sg = sendgrid.SendGridClient(api_key)
        else:
            sg = sendgrid.SendGridClient(username, password)

        message = sendgrid.Mail()
        message.set_subject(subject)

        for recip in to_addresses:
            message.add_to(recip)

        if cc:
            for recip in cc:
                message.add_cc(recip)
        if bcc:
            for recip in bcc:
                message.add_bcc(recip)

        if headers:
            message.set_headers(headers)

        if attachments:
            for f in attachments:
                name = os.path.basename(f)
                message.add_attachment(name, f)

        if from_name:
            message.set_from('%s <%s.' % (from_name, from_address))
        else:
            message.set_from(from_address)

        if html_body:
            message.set_html(body)
        else:
            message.set_text(body)

        return sg.send(message)
Ejemplo n.º 5
0
 def get_zones(self,name=None):
     if not name:
         name = self.zone
     param = ''
     if name:
         param = '?' + urlencode({'name' : name})
     zones,status = self._cf_api_call('/zones' + param)
     return zones
Ejemplo n.º 6
0
def checkID(module, params):

    data = urlencode(params)
    full_uri = API_BASE + API_ACTIONS['status'] + data
    req, info = fetch_url(module, full_uri)
    result = req.read()
    jsonresult = json.loads(result)
    req.close()
    return jsonresult
Ejemplo n.º 7
0
 def authenticate(self, github_token):
     """
     Retrieve an authentication token
     """
     url = '%s/tokens/' % self.baseurl
     args = urlencode({"github_token": github_token})
     resp = open_url(url, data=args, validate_certs=self._validate_certs, method="POST")
     data = json.loads(to_text(resp.read(), errors='surrogate_or_strict'))
     return data
Ejemplo n.º 8
0
def pauseMonitor(module, params):

    params['monitorStatus'] = 0
    data = urlencode(params)
    full_uri = API_BASE + API_ACTIONS['editMonitor'] + data
    req, info = fetch_url(module, full_uri)
    result = req.read()
    jsonresult = json.loads(result)
    req.close()
    return jsonresult['stat']
Ejemplo n.º 9
0
 def add_secret(self, source, github_user, github_repo, secret):
     url = "%s/notification_secrets/" % self.baseurl
     args = urlencode({
         "source": source,
         "github_user": github_user,
         "github_repo": github_repo,
         "secret": secret
     })
     data = self.__call_galaxy(url, args=args)
     return data
def get_plugin_info(module, plugin_manager_url, intellij_home, plugin_id):

    build_number = get_build_number(module, intellij_home)

    params = {'action': 'download', 'build': build_number, 'id': plugin_id}

    query_params = urlencode(params)

    url = '%s?%s' % (plugin_manager_url, query_params)
    for _ in range(0, 3):
        resp, info = fetch_url(
            module, url, method='HEAD', timeout=3, follow_redirects=False)
        if resp is not None:
            resp.close()
        status_code = info['status']
        if status_code == 404:
            module.fail_json(msg='Unable to find plugin "%s" for build "%s"' % (
                plugin_id, build_number))
        if status_code > -1 and status_code < 400:
            break
        # 3 retries 5 seconds appart
        time.sleep(5)

    if status_code == -1 or status_code >= 400:
        module.fail_json(msg='Error querying url "%s": %s' % (url, info['msg']))

    location = info.get('location')
    if location is None:
        location = info.get('Location')
    if location is None:
        module.fail_json(msg='Unsupported HTTP response for: %s (status=%s)' % (
            url, status_code))

    plugin_url = location

    jar_pattern = re.compile(r'/(?P<file_name>[^/]+\.jar)(?:\?.*)$')
    jar_matcher = jar_pattern.search(plugin_url)

    if jar_matcher:
        file_name = jar_matcher.group('file_name')
    else:
        versioned_pattern = re.compile(
            r'(?P<plugin_id>[0-9]+)/(?P<update_id>[0-9]+)/(?P<file_name>[^/]+)(?:\?.*)$'
        )

        versioned_matcher = versioned_pattern.search(plugin_url)
        if versioned_matcher:
            file_name = '%s-%s-%s' % (versioned_matcher.group('plugin_id'),
                                      versioned_matcher.group('update_id'),
                                      versioned_matcher.group('file_name'))
        else:
            hash_object = hashlib.sha256(plugin_url)
            file_name = '%s-%s.zip' % (plugin_id, hash_object.hexdigest())

    return plugin_url, file_name
Ejemplo n.º 11
0
    def _pm_query(self, action, msg):
        url = "%s/pluginManager/plugin/%s/%s" % (
            self.params['url'], self.params['name'], action)
        data = urlencode(self.crumb)

        # Send the request
        self._get_url_data(
            url,
            msg_status="Plugin not found. %s" % url,
            msg_exception="%s has failed." % msg,
            data=data)
Ejemplo n.º 12
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            script=dict(required=True, type="str"),
            url=dict(required=False, type="str", default="http://localhost:8080"),
            validate_certs=dict(required=False, type="bool", default=True),
            user=dict(required=False, type="str", default=None),
            password=dict(required=False, no_log=True, type="str", default=None),
            timeout=dict(required=False, type="int", default=10),
            args=dict(required=False, type="dict", default=None)
        )
    )

    if module.params['user'] is not None:
        if module.params['password'] is None:
            module.fail_json(msg="password required when user provided", output='')
        module.params['url_username'] = module.params['user']
        module.params['url_password'] = module.params['password']
        module.params['force_basic_auth'] = True

    if module.params['args'] is not None:
        from string import Template
        try:
            script_contents = Template(module.params['script']).substitute(module.params['args'])
        except KeyError as err:
            module.fail_json(msg="Error with templating variable: %s" % err, output='')
    else:
        script_contents = module.params['script']

    headers = {}
    if is_csrf_protection_enabled(module):
        crumb = get_crumb(module)
        headers = {crumb['crumbRequestField']: crumb['crumb']}

    resp, info = fetch_url(module,
                           module.params['url'] + "/scriptText",
                           data=urlencode({'script': script_contents}),
                           headers=headers,
                           method="POST",
                           timeout=module.params['timeout'])

    if info["status"] != 200:
        module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"], output='')

    result = to_native(resp.read())

    if 'Exception:' in result and 'at java.lang.Thread' in result:
        module.fail_json(msg="script failed with stacktrace:\n " + result, output='')

    module.exit_json(
        output=result,
    )
Ejemplo n.º 13
0
def update_qsl(url, params):
    ''' Add or update a URL query string '''

    if HAS_URLPARSE:
        url_parts = list(urlparse(url))
        query = dict(parse_qsl(url_parts[4]))
        query.update(params)
        url_parts[4] = urlencode(query)
        return urlunparse(url_parts)
    elif '?' in url:
        return url + '&' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
    else:
        return url + '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
Ejemplo n.º 14
0
    def query(self, resource, method, data=None):
        url = self.baseurl + resource
        if data and not isinstance(data, string_types):
            data = urlencode(data)

        response, info = fetch_url(self.module, url, data=data, method=method, headers=self._headers())
        if info['status'] not in (200, 201, 204):
            self.module.fail_json(msg="%s returned %s, with body: %s" % (url, info['status'], info['msg']))

        try:
            return json.load(response)
        except Exception:
            return {}
Ejemplo n.º 15
0
def vmware_path(datastore, datacenter, path):
    ''' Constructs a URL path that VSphere accepts reliably '''
    path = "/folder/%s" % path.lstrip("/")
    # Due to a software bug in vSphere, it fails to handle ampersand in datacenter names
    # The solution is to do what vSphere does (when browsing) and double-encode ampersands, maybe others ?
    datacenter = datacenter.replace('&', '%26')
    if not path.startswith("/"):
        path = "/" + path
    params = dict( dsName = datastore )
    if datacenter:
        params["dcPath"] = datacenter
    params = urlencode(params)
    return "%s?%s" % (path, params)
Ejemplo n.º 16
0
def do_request(module, url, params, headers=None):
    data = urlencode(params)
    if headers is None:
        headers = dict()
    headers = dict(headers, **{
        'User-Agent': 'Ansible/typetalk module',
    })
    r, info = fetch_url(module, url, data=data, headers=headers)
    if info['status'] != 200:
        exc = ConnectionError(info['msg'])
        exc.code = info['status']
        raise exc
    return r
Ejemplo n.º 17
0
def do_notify_grove(module, channel_token, service, message, url=None, icon_url=None):
    my_url = BASE_URL % (channel_token,)

    my_data = dict(service=service, message=message)
    if url is not None:
        my_data['url'] = url
    if icon_url is not None:
        my_data['icon_url'] = icon_url

    data = urlencode(my_data)
    response, info = fetch_url(module, my_url, data=data)
    if info['status'] != 200:
        module.fail_json(msg="failed to send notification: %s" % info['msg'])
Ejemplo n.º 18
0
    def __init__(self, module):
        self.module = module
        self.hostname        = module.params['name']
        self.rack            = module.params['rack']
        self.rank            = module.params['rank']
        self.appliance       = module.params['appliance']
        self.prim_intf       = module.params['prim_intf']
        self.prim_intf_ip    = module.params['prim_intf_ip']
        self.network         = module.params['network']
        self.prim_intf_mac   = module.params['prim_intf_mac']
        self.endpoint        = module.params['stacki_endpoint']

        auth_creds  = {'USERNAME': module.params['stacki_user'],
                       'PASSWORD': module.params['stacki_password']}

        # Get Initial CSRF
        cred_a = self.do_request(self.module, self.endpoint, method="GET")
        cookie_a = cred_a.headers.get('Set-Cookie').split(';')
        init_csrftoken = None
        for c in cookie_a:
            if "csrftoken" in c:
                init_csrftoken = c.replace("csrftoken=", "")
                init_csrftoken = init_csrftoken.rstrip("\r\n")
                break

        # Make Header Dictionary with initial CSRF
        header = {'csrftoken': init_csrftoken, 'X-CSRFToken': init_csrftoken,
                  'Content-type': 'application/x-www-form-urlencoded', 'Cookie': cred_a.headers.get('Set-Cookie')}

        # Endpoint to get final authentication header
        login_endpoint = self.endpoint + "/login"

        # Get Final CSRF and Session ID
        login_req = self.do_request(self.module, login_endpoint, headers=header,
                                    payload=urlencode(auth_creds), method='POST')

        cookie_f = login_req.headers.get('Set-Cookie').split(';')
        csrftoken = None
        for f in cookie_f:
            if "csrftoken" in f:
                csrftoken = f.replace("csrftoken=", "")
            if "sessionid" in f:
                sessionid = c.split("sessionid=", 1)[-1]
                sessionid = sessionid.rstrip("\r\n")

        self.header = {'csrftoken': csrftoken,
                       'X-CSRFToken': csrftoken,
                       'sessionid': sessionid,
                       'Content-type': 'application/json',
                       'Cookie': login_req.headers.get('Set-Cookie')}
Ejemplo n.º 19
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            token=dict(required=True, no_log=True),
            app_name=dict(required=False),
            application_id=dict(required=False),
            changelog=dict(required=False),
            description=dict(required=False),
            revision=dict(required=False),
            user=dict(required=False),
            appname=dict(required=False),
            environment=dict(required=False),
            validate_certs = dict(default='yes', type='bool'),
        ),
        required_one_of=[['app_name', 'application_id']],
        supports_check_mode=True
    )

    # build list of params
    params = {}
    if module.params["app_name"] and module.params["application_id"]:
        module.fail_json(msg="only one of 'app_name' or 'application_id' can be set")

    if module.params["app_name"]:
        params["app_name"] = module.params["app_name"]
    elif module.params["application_id"]:
        params["application_id"] = module.params["application_id"]
    else:
        module.fail_json(msg="you must set one of 'app_name' or 'application_id'")

    for item in [ "changelog", "description", "revision", "user", "appname", "environment" ]:
        if module.params[item]:
            params[item] = module.params[item]

    # If we're in check mode, just exit pretending like we succeeded
    if module.check_mode:
        module.exit_json(changed=True)

    # Send the data to NewRelic
    url = "https://rpm.newrelic.com/deployments.xml"
    data = urlencode(params)
    headers = {
        'x-api-key': module.params["token"],
    }
    response, info = fetch_url(module, url, data=data, headers=headers)
    if info['status'] in (200, 201):
        module.exit_json(changed=True)
    else:
        module.fail_json(msg="unable to update newrelic: %s" % info['msg'])
Ejemplo n.º 20
0
    def rpc(self, action, params):
        """Make a call to the LogicMonitor RPC library
        and return the response"""
        self.module.debug("Running LogicMonitor.rpc")

        param_str = urlencode(params)
        creds = urlencode(
            {"c": self.company,
                "u": self.user,
                "p": self.password})

        if param_str:
            param_str = param_str + "&"

        param_str = param_str + creds

        try:
            url = ("https://" + self.company + "." + self.lm_url +
                   "/rpc/" + action + "?" + param_str)

            # Set custom LogicMonitor header with version
            headers = {"X-LM-User-Agent": self.__version__}

            # Set headers
            f = open_url(url, headers=headers)

            raw = f.read()
            resp = json.loads(raw)
            if resp["status"] == 403:
                self.module.debug("Authentication failed.")
                self.fail(msg="Error: " + resp["errmsg"])
            else:
                return raw
        except IOError as ioe:
            self.fail(msg="Error: Exception making RPC call to " +
                          "https://" + self.company + "." + self.lm_url +
                          "/rpc/" + action + "\nException" + to_native(ioe))
Ejemplo n.º 21
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            token=dict(required=True),
            environment=dict(required=True),
            revision=dict(required=True),
            user=dict(required=False),
            rollbar_user=dict(required=False),
            comment=dict(required=False),
            url=dict(
                required=False,
                default='https://api.rollbar.com/api/1/deploy/'
            ),
            validate_certs=dict(default='yes', type='bool'),
        ),
        supports_check_mode=True
    )

    if module.check_mode:
        module.exit_json(changed=True)

    params = dict(
        access_token=module.params['token'],
        environment=module.params['environment'],
        revision=module.params['revision']
    )

    if module.params['user']:
        params['local_username'] = module.params['user']

    if module.params['rollbar_user']:
        params['rollbar_username'] = module.params['rollbar_user']

    if module.params['comment']:
        params['comment'] = module.params['comment']

    url = module.params.get('url')

    try:
        data = urlencode(params)
        response, info = fetch_url(module, url, data=data)
    except Exception as e:
        module.fail_json(msg='Unable to notify Rollbar: %s' % to_native(e), exception=traceback.format_exc())
    else:
        if info['status'] == 200:
            module.exit_json(changed=True)
        else:
            module.fail_json(msg='HTTP result code: %d connecting to %s' % (info['status'], url))
Ejemplo n.º 22
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            token=dict(required=True, no_log=True),
            environment=dict(required=True),
            user=dict(required=False),
            repo=dict(required=False),
            revision=dict(required=False),
            url=dict(required=False, default='https://api.honeybadger.io/v1/deploys'),
            validate_certs=dict(default='yes', type='bool'),
        ),
        supports_check_mode=True
    )

    params = {}

    if module.params["environment"]:
        params["deploy[environment]"] = module.params["environment"]

    if module.params["user"]:
        params["deploy[local_username]"] = module.params["user"]

    if module.params["repo"]:
        params["deploy[repository]"] = module.params["repo"]

    if module.params["revision"]:
        params["deploy[revision]"] = module.params["revision"]

    params["api_key"] = module.params["token"]

    url = module.params.get('url')

    # If we're in check mode, just exit pretending like we succeeded
    if module.check_mode:
        module.exit_json(changed=True)

    try:
        data = urlencode(params)
        response, info = fetch_url(module, url, data=data)
    except Exception as e:
        module.fail_json(msg='Unable to notify Honeybadger: %s' % to_native(e), exception=traceback.format_exc())
    else:
        if info['status'] == 201:
            module.exit_json(changed=True)
        else:
            module.fail_json(msg="HTTP result code: %d connecting to %s" % (info['status'], url))
Ejemplo n.º 23
0
    def _post(self, api_call, data=None):
        if data is not None:
            data = urlencode(data)

        resp, info = fetch_url(self._module,
                               API_URL+api_call,
                               headers = self._auth_header,
                               method='POST',
                               data=data)

        if info['status'] == 201:
            return json.loads(resp.read())
        elif info['status'] == 204:
            return None
        else:
            self._module.fail_json(msg='Failure while calling the cloudscale.ch API with POST for '
                                       '"%s": %s' % (api_call, info['body']))
Ejemplo n.º 24
0
    def send_msg_v1(self, msg, msg_format='text', color='yellow', notify=False):
        """Method for sending a message to HipChat"""

        params = {}
        params['room_id'] = self.room
        params['from'] = self.from_name[:15]  # max length is 15
        params['message'] = msg
        params['message_format'] = msg_format
        params['color'] = color
        params['notify'] = int(self.allow_notify and notify)

        url = ('%s?auth_token=%s' % (self.API_V1_URL, self.token))
        try:
            response = open_url(url, data=urlencode(params))
            return response.read()
        except Exception as ex:
            self._display.warning('Could not submit message to hipchat: {0}'.format(ex))
Ejemplo n.º 25
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            token=dict(required=True, no_log=True),
            environment=dict(required=True),
            user=dict(required=False),
            repo=dict(required=False),
            revision=dict(required=False),
            url=dict(required=False, default='https://api.airbrake.io/deploys.txt'),
            validate_certs=dict(default='yes', type='bool'),
        ),
        supports_check_mode=True
    )

    # build list of params
    params = {}

    if module.params["environment"]:
        params["deploy[rails_env]"] = module.params["environment"]

    if module.params["user"]:
        params["deploy[local_username]"] = module.params["user"]

    if module.params["repo"]:
        params["deploy[scm_repository]"] = module.params["repo"]

    if module.params["revision"]:
        params["deploy[scm_revision]"] = module.params["revision"]

    params["api_key"] = module.params["token"]

    url = module.params.get('url')

    # If we're in check mode, just exit pretending like we succeeded
    if module.check_mode:
        module.exit_json(changed=True)

    # Send the data to airbrake
    data = urlencode(params)
    response, info = fetch_url(module, url, data=data)
    if info['status'] == 200:
        module.exit_json(changed=True)
    else:
        module.fail_json(msg="HTTP result code: %d connecting to %s" % (info['status'], url))
Ejemplo n.º 26
0
    def run(self, priority, msg):
        ''' Do, whatever it is, we do. '''

        url = '%s/1/messages.json' % (self.base_uri)

        # parse config
        options = dict(user=self.user,
                token=self.token,
                priority=priority,
                message=msg)
        data = urlencode(options)

        headers = { "Content-type": "application/x-www-form-urlencoded"}
        r, info = fetch_url(self.module, url, method='POST', data=data, headers=headers)
        if info['status'] != 200:
            raise Exception(info)

        return r.read()
Ejemplo n.º 27
0
 def create_import_task(self, github_user, github_repo, reference=None, role_name=None):
     """
     Post an import request
     """
     url = '%s/imports/' % self.baseurl
     args = {
         "github_user": github_user,
         "github_repo": github_repo,
         "github_reference": reference if reference else ""
     }
     if role_name:
         args['alternate_role_name'] = role_name
     elif github_repo.startswith('ansible-role'):
         args['alternate_role_name'] = github_repo[len('ansible-role') + 1:]
     data = self.__call_galaxy(url, args=urlencode(args))
     if data.get('results', None):
         return data['results']
     return data
Ejemplo n.º 28
0
    def http_request(self, api_endpoint, data_json=None):
        data_josn = {} if data_json is None else data_json

        request_url = self._nsc_protocol + '://' + self._nsc_host + self._nitro_base_url + api_endpoint

        data_json = urlencode(data_json)
        if not len(data_json):
            data_json = None

        auth = base64.b64encode(to_bytes('%s:%s' % (self._nsc_user, self._nsc_pass)).replace('\n', '').strip())
        headers = {
            'Authorization': 'Basic %s' % auth,
            'Content-Type': 'application/x-www-form-urlencoded',
        }

        response, info = fetch_url(self.module, request_url, data=data_json, headers=headers)

        return json.load(response)
Ejemplo n.º 29
0
def post_twilio_api(module, account_sid, auth_token, msg, from_number,
                    to_number, media_url=None):
    URI = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json" \
        % (account_sid,)
    AGENT = "Ansible"

    data = {'From': from_number, 'To': to_number, 'Body': msg}
    if media_url:
        data['MediaUrl'] = media_url
    encoded_data = urlencode(data)

    headers = {'User-Agent': AGENT,
               'Content-type': 'application/x-www-form-urlencoded',
               'Accept': 'application/json',
               }

    # Hack module params to have the Basic auth params that fetch_url expects
    module.params['url_username'] = account_sid.replace('\n', '')
    module.params['url_password'] = auth_token.replace('\n', '')

    return fetch_url(module, URI, data=encoded_data, headers=headers)
Ejemplo n.º 30
0
def send_msg(module):
    failed = list()
    responses = dict()
    msg = {
        'api_key': module.params.get('api_key'),
        'api_secret': module.params.get('api_secret'),
        'from': module.params.get('src'),
        'text': module.params.get('msg')
    }
    for number in module.params.get('dest'):
        msg['to'] = number
        url = "%s?%s" % (NEXMO_API, urlencode(msg))

        headers = dict(Accept='application/json')
        response, info = fetch_url(module, url, headers=headers)
        if info['status'] != 200:
            failed.append(number)
            responses[number] = dict(failed=True)

        try:
            responses[number] = json.load(response)
        except:
            failed.append(number)
            responses[number] = dict(failed=True)
        else:
            for message in responses[number]['messages']:
                if int(message['status']) != 0:
                    failed.append(number)
                    responses[number] = dict(failed=True, **responses[number])

        if failed:
            msg = 'One or messages failed to send'
        else:
            msg = ''

        module.exit_json(failed=bool(failed), msg=msg, changed=False,
                         responses=responses)
Ejemplo n.º 31
0
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        correlation_search_name=dict(required=True, type="str"),
        description=dict(required=True, type="str"),
        state=dict(choices=["present", "absent"], required=True),
        security_domain=dict(
            choices=[
                "access", "endpoint", "network", "threat", "identity", "audit"
            ],
            required=False,
            default="threat",
        ),
        severity=dict(
            choices=[
                "informational", "low", "medium", "high", "critical", "unknown"
            ],
            required=False,
            default="high",
        ),
        default_owner=dict(required=False, type="str"),
        default_status=dict(
            choices=[
                "unassigned",
                "new",
                "in progress",
                "pending",
                "resolved",
                "closed",
            ],
            required=False,
            default="",
        ),
        drill_down_name=dict(required=False, type="str"),
        drill_down_search=dict(required=False, type="str"),
        drill_down_earliest_offset=dict(required=False,
                                        type="str",
                                        default="$info_min_time$"),
        drill_down_latest_offset=dict(required=False,
                                      type="str",
                                      default="$info_max_time$"),
        investigation_profiles=dict(required=False, type="str"),
        next_steps=dict(required=False, type="list", default=[]),
        recommended_actions=dict(required=False, type="list", default=[]),
        asset_extraction=dict(
            required=False,
            type="list",
            default=["src", "dest", "dvc", "orig_host"],
            choices=["src", "dest", "dvc", "orig_host"],
        ),
        identity_extraction=dict(
            required=False,
            type="list",
            default=["user", "src_user"],
            choices=["user", "src_user"],
        ),
    )

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

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state"],
    )

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".
        format(quote_plus(module.params["correlation_search_name"])))

    # Have to custom craft the data here because they overload the saved searches
    # endpoint in the rest api and we want to hide the nuance from the user
    request_post_data = {}

    # FIXME  need to figure out how to properly support these, the possible values appear to
    #       be dynamically created based on what the search is indexing
    # request_post_data['action.notable.param.extract_assets'] = '[\"src\",\"dest\",\"dvc\",\"orig_host\"]'
    # request_post_data['action.notable.param.extract_identities'] = [\"src_user\",\"user\"]
    if module.params["next_steps"]:
        if len(module.params["next_steps"]) == 1:
            next_steps = "[[action|{0}]]".format(
                module.params["next_steps"][0])
        else:
            next_steps = ""
            for next_step in module.params["next_steps"]:
                if next_steps:
                    next_steps += "\n[[action|{0}]]".format(next_step)
                else:
                    next_steps = "[[action|{0}]]".format(next_step)

        # NOTE: version:1 appears to be hard coded when you create this via the splunk web UI
        #       but I don't know what it is/means because there's no docs on it
        next_steps_dict = {"version": 1, "data": next_steps}
        request_post_data["action.notable.param.next_steps"] = json.dumps(
            next_steps_dict)

    if module.params["recommended_actions"]:
        if len(module.params["recommended_actions"]) == 1:
            request_post_data[
                "action.notable.param.recommended_actions"] = module.params[
                    "recommended_actions"][0]
        else:
            request_post_data[
                "action.notable.param.recommended_actions"] = ",".join(
                    module.params["recommended_actions"])

    request_post_data["action.notable.param.rule_description"] = module.params[
        "description"]
    request_post_data["action.notable.param.rule_title"] = module.params[
        "name"]
    request_post_data["action.notable.param.security_domain"] = module.params[
        "security_domain"]
    request_post_data["action.notable.param.severity"] = module.params[
        "severity"]
    request_post_data["action.notable.param.asset_extraction"] = module.params[
        "asset_extraction"]
    request_post_data[
        "action.notable.param.identity_extraction"] = module.params[
            "identity_extraction"]

    # NOTE: this field appears to be hard coded when you create this via the splunk web UI
    #       but I don't know what it is/means because there's no docs on it
    request_post_data["action.notable.param.verbose"] = "0"

    if module.params["default_owner"]:
        request_post_data[
            "action.notable.param.default_owner"] = module.params[
                "default_owner"]

    if module.params["default_status"]:
        request_post_data[
            "action.notable.param.default_status"] = module.params[
                "default_status"]

    if query_dict:
        request_post_data["search"] = query_dict["entry"][0]["content"][
            "search"]
        if "actions" in query_dict["entry"][0]["content"]:
            if query_dict["entry"][0]["content"]["actions"] == "notable":
                pass
            elif (len(query_dict["entry"][0]["content"]["actions"].split(","))
                  > 0 and "notable"
                  not in query_dict["entry"][0]["content"]["actions"]):
                request_post_data["actions"] = (
                    query_dict["entry"][0]["content"]["actions"] + ", notable")
            else:
                request_post_data["actions"] = "notable"
    else:
        module.fail_json(msg="Unable to find correlation search: {0}",
                         splunk_data=splunk_data)

    if module.params["state"] == "present":
        needs_change = False
        for arg in request_post_data:
            if arg in query_dict["entry"][0]["content"]:
                if to_text(query_dict["entry"][0]["content"][arg]) != to_text(
                        request_post_data[arg]):
                    needs_change = True
        if not needs_change:
            module.exit_json(changed=False,
                             msg="Nothing to do.",
                             splunk_data=query_dict)
        if module.check_mode and needs_change:
            module.exit_json(
                changed=True,
                msg="A change would have been made if not in check mode.",
                splunk_data=query_dict,
            )
        if needs_change:
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}"
                .format(quote_plus(module.params["correlation_search_name"])),
                data=urlencode(request_post_data),
            )
            module.exit_json(
                changed=True,
                msg="{0} updated.".format(
                    module.params["correlation_search_name"]),
                splunk_data=splunk_data,
            )

    if module.params["state"] == "absent":
        # FIXME - need to figure out how to clear the action.notable.param fields from the api endpoint
        module.exit_json(
            changed=True,
            msg="Deleted {0}.".format(module.params["name"]),
            splunk_data=splunk_data,
        )
        for arg in request_post_data:
            if arg in query_dict["entry"][0]["content"]:
                needs_change = True
                del query_dict["entry"][0]["content"][arg]
        if not needs_change:
            module.exit_json(changed=False,
                             msg="Nothing to do.",
                             splunk_data=query_dict)
        if module.check_mode and needs_change:
            module.exit_json(
                changed=True,
                msg="A change would have been made if not in check mode.",
                splunk_data=query_dict,
            )
        if needs_change:
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}"
                .format(quote_plus(module.params["correlation_search_name"])),
                data=urlencode(request_post_data),
            )
            module.exit_json(
                changed=True,
                msg="{0} updated.".format(
                    module.params["correlation_search_name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False,
                     msg="Nothing to do.",
                     splunk_data=query_dict)
Ejemplo n.º 32
0
 def get_url(self, url, params=None):
     if params:
         return self.api_version + url + '?' + urlencode(params)
     else:
         return self.api_version + url
Ejemplo n.º 33
0
    def make_request(self, method, endpoint, *args, **kwargs):
        # In case someone is calling us directly; make sure we were given a method, let's not just assume a GET
        if not method:
            raise Exception("The HTTP method must be defined")

        # Make sure we start with /api/vX
        if not endpoint.startswith("/"):
            endpoint = "/{0}".format(endpoint)
        if not endpoint.startswith("/api/"):
            endpoint = "/api/v2{0}".format(endpoint)
        if not endpoint.endswith('/') and '?' not in endpoint:
            endpoint = "{0}/".format(endpoint)

        # Extract the headers, this will be used in a couple of places
        headers = kwargs.get('headers', {})

        # Authenticate to Tower (if we don't have a token and if not already done so)
        if not self.oauth_token and not self.authenticated:
            # This method will set a cookie in the cookie jar for us and also an oauth_token
            self.authenticate(**kwargs)
        if self.oauth_token:
            # If we have a oauth token, we just use a bearer header
            headers['Authorization'] = 'Bearer {0}'.format(self.oauth_token)

        # Update the URL path with the endpoint
        self.url = self.url._replace(path=endpoint)

        if method in ['POST', 'PUT', 'PATCH']:
            headers.setdefault('Content-Type', 'application/json')
            kwargs['headers'] = headers
        elif kwargs.get('data'):
            self.url = self.url._replace(query=urlencode(kwargs.get('data')))

        data = None  # Important, if content type is not JSON, this should not be dict type
        if headers.get('Content-Type', '') == 'application/json':
            data = dumps(kwargs.get('data', {}))

        try:
            response = self.session.open(method,
                                         self.url.geturl(),
                                         headers=headers,
                                         validate_certs=self.verify_ssl,
                                         follow_redirects=True,
                                         data=data)
        except (SSLValidationError) as ssl_err:
            self.fail_json(
                msg=
                "Could not establish a secure connection to your host ({1}): {0}."
                .format(self.url.netloc, ssl_err))
        except (ConnectionError) as con_err:
            self.fail_json(
                msg=
                "There was a network error of some kind trying to connect to your host ({1}): {0}."
                .format(self.url.netloc, con_err))
        except (HTTPError) as he:
            # Sanity check: Did the server send back some kind of internal error?
            if he.code >= 500:
                self.fail_json(
                    msg=
                    'The host sent back a server error ({1}): {0}. Please check the logs and try again later'
                    .format(self.url.path, he))
            # Sanity check: Did we fail to authenticate properly?  If so, fail out now; this is always a failure.
            elif he.code == 401:
                self.fail_json(
                    msg=
                    'Invalid Tower authentication credentials for {0} (HTTP 401).'
                    .format(self.url.path))
            # Sanity check: Did we get a forbidden response, which means that the user isn't allowed to do this? Report that.
            elif he.code == 403:
                self.fail_json(
                    msg="You don't have permission to {1} to {0} (HTTP 403).".
                    format(self.url.path, method))
            # Sanity check: Did we get a 404 response?
            # Requests with primary keys will return a 404 if there is no response, and we want to consistently trap these.
            elif he.code == 404:
                if kwargs.get('return_none_on_404', False):
                    return None
                self.fail_json(
                    msg='The requested object could not be found at {0}.'.
                    format(self.url.path))
            # Sanity check: Did we get a 405 response?
            # A 405 means we used a method that isn't allowed. Usually this is a bad request, but it requires special treatment because the
            # API sends it as a logic error in a few situations (e.g. trying to cancel a job that isn't running).
            elif he.code == 405:
                self.fail_json(
                    msg=
                    "The Tower server says you can't make a request with the {0} method to this endpoing {1}"
                    .format(method, self.url.path))
            # Sanity check: Did we get some other kind of error?  If so, write an appropriate error message.
            elif he.code >= 400:
                # We are going to return a 400 so the module can decide what to do with it
                page_data = he.read()
                try:
                    return {'status_code': he.code, 'json': loads(page_data)}
                # JSONDecodeError only available on Python 3.5+
                except ValueError:
                    return {'status_code': he.code, 'text': page_data}
            elif he.code == 204 and method == 'DELETE':
                # A 204 is a normal response for a delete function
                pass
            else:
                self.fail_json(
                    msg="Unexpected return code when calling {0}: {1}".format(
                        self.url.geturl(), he))
        except (Exception) as e:
            self.fail_json(
                msg=
                "There was an unknown error when trying to connect to {2}: {0} {1}"
                .format(type(e).__name__, e, self.url.geturl()))
        finally:
            self.url = self.url._replace(query=None)

        if not self.version_checked:
            # In PY2 we get back an HTTPResponse object but PY2 is returning an addinfourl
            # First try to get the headers in PY3 format and then drop down to PY2.
            try:
                tower_type = response.getheader('X-API-Product-Name', None)
                tower_version = response.getheader('X-API-Product-Version',
                                                   None)
            except Exception:
                tower_type = response.info().getheader('X-API-Product-Name',
                                                       None)
                tower_version = response.info().getheader(
                    'X-API-Product-Version', None)

            if self._COLLECTION_TYPE not in self.collection_to_version or self.collection_to_version[
                    self._COLLECTION_TYPE] != tower_type:
                self.warn(
                    "You are using the {0} version of this collection but connecting to {1}"
                    .format(self._COLLECTION_TYPE, tower_type))
            elif self._COLLECTION_VERSION != tower_version:
                self.warn(
                    "You are running collection version {0} but connecting to tower version {1}"
                    .format(self._COLLECTION_VERSION, tower_version))
            self.version_checked = True

        response_body = ''
        try:
            response_body = response.read()
        except (Exception) as e:
            self.fail_json(msg="Failed to read response body: {0}".format(e))

        response_json = {}
        if response_body and response_body != '':
            try:
                response_json = loads(response_body)
            except (Exception) as e:
                self.fail_json(
                    msg="Failed to parse the response json: {0}".format(e))

        if PY2:
            status_code = response.getcode()
        else:
            status_code = response.status
        return {'status_code': status_code, 'json': response_json}
Ejemplo n.º 34
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            token=dict(required=False, no_log=True),
            project_id=dict(required=False, no_log=True),
            project_key=dict(required=False, no_log=True),
            environment=dict(required=True),
            user=dict(required=False),
            repo=dict(required=False),
            revision=dict(required=False),
            url=dict(required=False,
                     default='https://api.airbrake.io/api/v4/projects/'),
            validate_certs=dict(default='yes', type='bool'),
        ),
        supports_check_mode=True,
        required_together=[('project_id', 'project_key')],
        mutually_exclusive=[('project_id', 'token')],
    )

    # Build list of params
    params = {}

    # If we're in check mode, just exit pretending like we succeeded
    if module.check_mode:
        module.exit_json(changed=True)

    if module.params["token"]:
        if module.params["environment"]:
            params["deploy[rails_env]"] = module.params["environment"]

        if module.params["user"]:
            params["deploy[local_username]"] = module.params["user"]

        if module.params["repo"]:
            params["deploy[scm_repository]"] = module.params["repo"]

        if module.params["revision"]:
            params["deploy[scm_revision]"] = module.params["revision"]

        module.deprecate(
            "Parameter 'token' is deprecated in 2.10. Please remove it and use 'project_id' and 'project_key' instead",
            version='2.14')

        params["api_key"] = module.params["token"]

        # Allow sending to Airbrake compliant v2 APIs
        if module.params["url"] == 'https://api.airbrake.io/api/v4/projects/':
            url = 'https://api.airbrake.io/deploys.txt'
        else:
            url = module.params["url"]

        # Send the data to airbrake
        data = urlencode(params)
        response, info = fetch_url(module, url, data=data)

    if module.params["project_id"] and module.params["project_key"]:
        if module.params["environment"]:
            params["environment"] = module.params["environment"]

        if module.params["user"]:
            params["username"] = module.params["user"]

        if module.params["repo"]:
            params["repository"] = module.params["repo"]

        if module.params["revision"]:
            params["revision"] = module.params["revision"]

        # Build deploy url
        url = module.params.get('url') + module.params[
            "project_id"] + '/deploys?key=' + module.params["project_key"]
        json_body = module.jsonify(params)

        # Build header
        headers = {'Content-Type': 'application/json'}

        # Notify Airbrake of deploy
        response, info = fetch_url(module,
                                   url,
                                   data=json_body,
                                   headers=headers,
                                   method='POST')

    if info['status'] == 200 or info['status'] == 201:
        module.exit_json(changed=True)
    else:
        module.fail_json(msg="HTTP result code: %d connecting to %s" %
                         (info['status'], url))
Ejemplo n.º 35
0
def post_sendgrid_api(module,
                      username,
                      password,
                      from_address,
                      to_addresses,
                      subject,
                      body,
                      api_key=None,
                      cc=None,
                      bcc=None,
                      attachments=None,
                      html_body=False,
                      from_name=None,
                      headers=None):

    if not HAS_SENDGRID:
        SENDGRID_URI = "https://api.sendgrid.com/api/mail.send.json"
        AGENT = "Ansible"
        data = {
            'api_user': username,
            'api_key': password,
            'from': from_address,
            'subject': subject,
            'text': body
        }
        encoded_data = urlencode(data)
        to_addresses_api = ''
        for recipient in to_addresses:
            if isinstance(recipient, unicode):
                recipient = recipient.encode('utf-8')
            to_addresses_api += '&to[]=%s' % recipient
        encoded_data += to_addresses_api

        headers = {
            'User-Agent': AGENT,
            'Content-type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        }
        return fetch_url(module,
                         SENDGRID_URI,
                         data=encoded_data,
                         headers=headers,
                         method='POST')
    else:

        if api_key:
            sg = sendgrid.SendGridClient(api_key)
        else:
            sg = sendgrid.SendGridClient(username, password)

        message = sendgrid.Mail()
        message.set_subject(subject)

        for recip in to_addresses:
            message.add_to(recip)

        if cc:
            for recip in cc:
                message.add_cc(recip)
        if bcc:
            for recip in bcc:
                message.add_bcc(recip)

        if headers:
            message.set_headers(headers)

        if attachments:
            for f in attachments:
                name = os.path.basename(f)
                message.add_attachment(name, f)

        if from_name:
            message.set_from('%s <%s.' % (from_name, from_address))
        else:
            message.set_from(from_address)

        if html_body:
            message.set_html(body)
        else:
            message.set_text(body)

        return sg.send(message)
Ejemplo n.º 36
0
 def _delete_profile(self):
     url = '/1.0/profiles/{0}'.format(self.name)
     if self.project:
         url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
     self.client.do('DELETE', url)
     self.actions.append('delete')
def get_plugin_info(module, plugin_manager_url, intellij_home, plugin_id):

    build_number = get_build_number(module, intellij_home)

    params = {'action': 'download', 'build': build_number, 'id': plugin_id}

    query_params = urlencode(params)

    url = '%s?%s' % (plugin_manager_url, query_params)
    for _ in range(0, 3):
        resp, info = fetch_url(module,
                               url,
                               method='HEAD',
                               timeout=3,
                               follow_redirects=False)
        if resp is not None:
            resp.close()
        status_code = info['status']
        if status_code == 404:
            module.fail_json(msg='Unable to find plugin "%s" for build "%s"' %
                             (plugin_id, build_number))
        if status_code > -1 and status_code < 400:
            break
        # 3 retries 5 seconds appart
        time.sleep(5)

    if status_code == -1 or status_code >= 400:
        module.fail_json(msg='Error querying url "%s": %s' %
                         (url, info['msg']))

    location = info.get('location')
    if location is None:
        location = info.get('Location')
    if location is None:
        module.fail_json(msg='Unsupported HTTP response for: %s (status=%s)' %
                         (url, status_code))

    if location.startswith('http'):
        plugin_url = location
    else:
        plugin_url = urljoin(plugin_manager_url, location)

    jar_pattern = re.compile(r'/(?P<file_name>[^/]+\.jar)(?:\?.*)$')
    jar_matcher = jar_pattern.search(plugin_url)

    if jar_matcher:
        file_name = jar_matcher.group('file_name')
    else:
        versioned_pattern = re.compile(
            r'(?P<plugin_id>[0-9]+)/(?P<update_id>[0-9]+)/'
            r'(?P<file_name>[^/]+)(?:\?.*)$')

        versioned_matcher = versioned_pattern.search(plugin_url)
        if versioned_matcher:
            file_name = '%s-%s-%s' % (versioned_matcher.group('plugin_id'),
                                      versioned_matcher.group('update_id'),
                                      versioned_matcher.group('file_name'))
        else:
            hash_object = hashlib.sha256(plugin_url)
            file_name = '%s-%s.zip' % (plugin_id, hash_object.hexdigest())

    return plugin_url, file_name
Ejemplo n.º 38
0
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        description=dict(required=True, type="str"),
        state=dict(choices=["present", "absent", "enabled", "disabled"],
                   required=True),
        search=dict(required=True, type="str"),
        app=dict(type="str",
                 required=False,
                 default="SplunkEnterpriseSecuritySuite"),
        ui_dispatch_context=dict(type="str", required=False),
        time_earliest=dict(type="str", required=False, default="-24h"),
        time_latest=dict(type="str", required=False, default="now"),
        cron_schedule=dict(type="str", required=False, default="*/5 * * * *"),
        scheduling=dict(
            type="str",
            required=False,
            default="real-time",
            choices=["real-time", "continuous"],
        ),
        schedule_window=dict(type="str", required=False, default="0"),
        schedule_priority=dict(
            type="str",
            required=False,
            default="Default",
            choices=["Default", "Higher", "Highest"],
        ),
        trigger_alert_when=dict(
            type="str",
            required=False,
            default="number of events",
            choices=[
                "number of events",
                "number of results",
                "number of hosts",
                "number of sources",
            ],
        ),
        trigger_alert_when_condition=dict(
            type="str",
            required=False,
            default="greater than",
            choices=[
                "greater than",
                "less than",
                "equal to",
                "not equal to",
                "drops by",
                "rises by",
            ],
        ),
        trigger_alert_when_value=dict(type="str", required=False,
                                      default="10"),
        throttle_window_duration=dict(type="str", required=False),
        throttle_fields_to_group_by=dict(type="str", required=False),
        suppress_alerts=dict(type="bool", required=False, default=False),
    )

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
    if module.params["state"] in ["present", "enabled"]:
        module_disabled_state = False
    else:
        module_disabled_state = True
    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state"],
    )

    try:
        query_dict = splunk_request.get_by_path(
            "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}"
            .format(quote_plus(module.params["name"])))
    except HTTPError as e:
        # the data monitor doesn't exist
        query_dict = {}

    # Have to custom craft the data here because they overload the saved searches
    # endpoint in the rest api and we want to hide the nuance from the user
    request_post_data = {}
    request_post_data["name"] = module.params["name"]
    request_post_data["action.correlationsearch.enabled"] = "1"
    request_post_data["is_scheduled"] = True
    request_post_data["dispatch.rt_backfill"] = True
    request_post_data["action.correlationsearch.label"] = module.params["name"]
    request_post_data["description"] = module.params["description"]
    request_post_data["search"] = module.params["search"]
    request_post_data["request.ui_dispatch_app"] = module.params["app"]
    if module.params["ui_dispatch_context"]:
        request_post_data["request.ui_dispatch_context"] = module.params[
            "ui_dispatch_context"]
    request_post_data["dispatch.earliest_time"] = module.params[
        "time_earliest"]
    request_post_data["dispatch.latest_time"] = module.params["time_latest"]
    request_post_data["cron_schedule"] = module.params["cron_schedule"]
    if module.params["scheduling"] == "real-time":
        request_post_data["realtime_schedule"] = True
    else:
        request_post_data["realtime_schedule"] = False
    request_post_data["schedule_window"] = module.params["schedule_window"]
    request_post_data["schedule_priority"] = module.params[
        "schedule_priority"].lower()
    request_post_data["alert_type"] = module.params["trigger_alert_when"]
    request_post_data["alert_comparator"] = module.params[
        "trigger_alert_when_condition"]
    request_post_data["alert_threshold"] = module.params[
        "trigger_alert_when_value"]
    request_post_data["alert.suppress"] = module.params["suppress_alerts"]
    request_post_data["disabled"] = module_disabled_state

    if module.params["state"] in ["present", "enabled", "disabled"]:
        if query_dict:
            needs_change = False
            for arg in request_post_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(
                            query_dict["entry"][0]["content"][arg]) != to_text(
                                request_post_data[arg]):
                        needs_change = True
            if not needs_change:
                module.exit_json(changed=False,
                                 msg="Nothing to do.",
                                 splunk_data=query_dict)
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                # FIXME - need to find a reasonable way to deal with action.correlationsearch.enabled
                del request_post_data[
                    "name"]  # If this is present, splunk assumes we're trying to create a new one wit the same name
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}"
                    .format(quote_plus(module.params["name"])),
                    data=urlencode(request_post_data),
                )
                module.exit_json(changed=True,
                                 msg="{0} updated.",
                                 splunk_data=splunk_data)
        else:
            # Create it
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches",
                data=urlencode(request_post_data),
            )
            module.exit_json(changed=True,
                             msg="{0} created.",
                             splunk_data=splunk_data)

    elif module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "services/saved/searches/{0}".format(
                    quote_plus(module.params["name"])))
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False,
                     msg="Nothing to do.",
                     splunk_data=query_dict)
Ejemplo n.º 39
0
def main():

    argspec = dict(
        state=dict(
            required=False,
            choices=["present", "absent", "enabled", "disable"],
            default="present",
            type="str",
        ),
        connection_host=dict(
            required=False, choices=["ip", "dns", "none"], default="ip", type="str"
        ),
        host=dict(required=False, type="str", default=None),
        index=dict(required=False, type="str", default=None),
        name=dict(required=True, type="str"),
        protocol=dict(required=True, type="str", choices=["tcp", "udp"]),
        queue=dict(
            required=False,
            type="str",
            choices=["parsingQueue", "indexQueue"],
            default="parsingQueue",
        ),
        rawTcpDoneTimeout=dict(required=False, type="int", default=10),
        restrictToHost=dict(required=False, type="str", default=None),
        ssl=dict(required=False, type="bool", default=None),
        source=dict(required=False, type="str", default=None),
        sourcetype=dict(required=False, type="str", default=None),
        datatype=dict(required=False, choices=["cooked", "raw"], default="raw"),
    )

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

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state", "datatype", "protocol"],
    )
    # This is where the splunk_* args are processed
    request_data = splunk_request.get_data()

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
            quote_plus(module.params["protocol"]),
            quote_plus(module.params["datatype"]),
            quote_plus(module.params["name"]),
        )
    )

    if module.params["state"] in ["present", "enabled", "disabled"]:
        _data = splunk_request.get_data()
        if module.params["state"] in ["present", "enabled"]:
            _data["disabled"] = False
        else:
            _data["disabled"] = True
        if query_dict:
            needs_change = False
            for arg in request_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(query_dict["entry"][0]["content"][arg]) != to_text(
                        request_data[arg]
                    ):
                        needs_change = True
            if not needs_change:
                module.exit_json(
                    changed=False, msg="Nothing to do.", splunk_data=query_dict
                )
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
                        quote_plus(module.params["protocol"]),
                        quote_plus(module.params["datatype"]),
                        quote_plus(module.params["name"]),
                        data=urlencode(_data),
                    )
                )
            if module.params["state"] in ["present", "enabled"]:
                module.exit_json(
                    changed=True, msg="{0} updated.", splunk_data=splunk_data
                )
            else:
                module.exit_json(
                    changed=True, msg="{0} disabled.", splunk_data=splunk_data
                )
        else:
            # Create it
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/search/data/inputs/{0}/{1}".format(
                    quote_plus(module.params["protocol"]),
                    quote_plus(module.params["datatype"]),
                ),
                data=urlencode(_data),
            )
            module.exit_json(changed=True, msg="{0} created.", splunk_data=splunk_data)
    elif module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
                    quote_plus(module.params["protocol"]),
                    quote_plus(module.params["datatype"]),
                    quote_plus(module.params["name"]),
                )
            )
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False, msg="Nothing to do.", splunk_data={})
Ejemplo n.º 40
0
    def restmethod(self, *args, **kwargs):
        """Do the hard work of making the request here"""

        # gather named path parameters and do substitution on the URL
        if self.parameters:
            path_parameters = {}
            body_parameters = {}
            query_parameters = {}
            for x in self.parameters:
                expected_location = x.get("in")
                key_name = x.get("name", None)
                key_value = kwargs.get(key_name, None)
                if expected_location == "path" and key_name and key_value:
                    path_parameters.update({key_name: key_value})
                elif expected_location == "body" and key_name and key_value:
                    body_parameters.update({key_name: key_value})
                elif expected_location == "query" and key_name and key_value:
                    query_parameters.update({key_name: key_value})

            if len(body_parameters.keys()) >= 1:
                body_parameters = body_parameters.get(
                    list(body_parameters.keys())[0])
            else:
                body_parameters = None
        else:
            path_parameters = {}
            query_parameters = {}
            body_parameters = None

        # This will fail if we have not set path parameters with a KeyError
        url = self.url.format(**path_parameters)
        if query_parameters:
            # modify the URL to add path parameters
            url = url + "?" + urlencode(query_parameters)

        try:
            if body_parameters:
                body_parameters_json = json.dumps(body_parameters)
                response = self.session.request.open(method=self.method,
                                                     url=url,
                                                     data=body_parameters_json)
            else:
                response = self.session.request.open(method=self.method,
                                                     url=url)
            request_error = False
        except HTTPError as e:
            # An HTTPError has the same methods available as a valid response from request.open
            response = e
            request_error = True

        # Return the result if JSON and success ({} for empty responses)
        # Raise an exception if there was a failure.
        try:
            result_code = response.getcode()
            result = json.loads(response.read())
        except ValueError:
            result = {}

        if result or result == {}:
            if result_code and result_code < 400:
                return result
            else:
                raise RestOperationException(result)

        # Raise a generic RestOperationException if this fails
        raise RestOperationException({
            "status":
            result_code,
            "errors": [{
                "message": "REST Operation Failed"
            }]
        })
Ejemplo n.º 41
0
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        state=dict(choices=["present", "absent"], required=True),
        blacklist=dict(required=False, type="str", default=None),
        check_index=dict(required=False, type="bool", default=False),
        check_path=dict(required=False, type="bool", default=None),
        crc_salt=dict(required=False, type="str", default=None),
        disabled=dict(required=False, type="bool", default=False),
        followTail=dict(required=False, type="bool", default=False),
        host=dict(required=False, type="str", default=None),
        host_segment=dict(required=False, type="int", default=None),
        host_regex=dict(required=False, type="str", default=None),
        ignore_older_than=dict(required=False, type="str", default=None),
        index=dict(required=False, type="str", default=None),
        recursive=dict(required=False, type="bool", default=False),
        rename_source=dict(required=False, type="str", default=None),
        sourcetype=dict(required=False, type="str", default=None),
        time_before_close=dict(required=False, type="int", default=None),
        whitelist=dict(required=False, type="str", default=None),
    )

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

    # map of keys for the splunk REST API that aren't pythonic so we have to
    # handle the substitutes
    keymap = {
        "check_index": "check-index",
        "check_path": "check-path",
        "crc_salt": "crc-salt",
        "ignore_older_than": "ignore-older-than",
        "rename_source": "rename-source",
        "time_before_close": "time-before-close",
    }

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        keymap=keymap,
        not_rest_data_keys=["state"],
    )
    # This is where the splunk_* args are processed
    request_data = splunk_request.get_data()

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
            quote_plus(module.params["name"])))

    if module.params["state"] == "present":
        if query_dict:
            needs_change = False
            for arg in request_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(
                            query_dict["entry"][0]["content"][arg]) != to_text(
                                request_data[arg]):
                        needs_change = True
            if not needs_change:
                module.exit_json(changed=False,
                                 msg="Nothing to do.",
                                 splunk_data=query_dict)
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
                        quote_plus(module.params["name"])))
                module.exit_json(changed=True,
                                 msg="{0} updated.",
                                 splunk_data=splunk_data)
        else:
            # Create it
            _data = splunk_request.get_data()
            _data["name"] = module.params["name"]
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/search/data/inputs/monitor",
                data=urlencode(_data))
            module.exit_json(changed=True,
                             msg="{0} created.",
                             splunk_data=splunk_data)

    if module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
                    quote_plus(module.params["name"])))
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False,
                     msg="Nothing to do.",
                     splunk_data=query_dict)
Ejemplo n.º 42
0
    def install(self):
        changed = False
        plugin_file = ('%s/plugins/%s.jpi' %
                       (self.params['jenkins_home'], self.params['name']))

        if not self.is_installed and self.params['version'] in [
                None, 'latest'
        ]:
            if not self.module.check_mode:
                # Install the plugin (with dependencies)
                install_script = (
                    'd = Jenkins.instance.updateCenter.getPlugin("%s")'
                    '.deploy(); d.get();' % self.params['name'])

                if self.params['with_dependencies']:
                    install_script = (
                        'Jenkins.instance.updateCenter.getPlugin("%s")'
                        '.getNeededDependencies().each{it.deploy()}; %s' %
                        (self.params['name'], install_script))

                script_data = {'script': install_script}
                script_data.update(self.crumb)
                data = urlencode(script_data)

                # Send the installation request
                r = self._get_url_data(
                    "%s/scriptText" % self.url,
                    msg_status="Cannot install plugin.",
                    msg_exception="Plugin installation has failed.",
                    data=data)

                hpi_file = '%s/plugins/%s.hpi' % (self.params['jenkins_home'],
                                                  self.params['name'])

                if os.path.isfile(hpi_file):
                    os.remove(hpi_file)

            changed = True
        else:
            # Check if the plugin directory exists
            if not os.path.isdir(self.params['jenkins_home']):
                self.module.fail_json(
                    msg="Jenkins home directory doesn't exist.")

            md5sum_old = None
            if os.path.isfile(plugin_file):
                # Make the checksum of the currently installed plugin
                with open(plugin_file, 'rb') as md5_plugin_fh:
                    md5_plugin_content = md5_plugin_fh.read()
                md5sum_old = hashlib.md5(md5_plugin_content).hexdigest()

            if self.params['version'] in [None, 'latest']:
                # Take latest version
                plugin_url = (
                    "%s/latest/%s.hpi" %
                    (self.params['updates_url'], self.params['name']))
            else:
                # Take specific version
                plugin_url = ("{0}/download/plugins/"
                              "{1}/{2}/{1}.hpi".format(
                                  self.params['updates_url'],
                                  self.params['name'], self.params['version']))

            if (self.params['updates_expiration'] == 0
                    or self.params['version'] not in [None, 'latest']
                    or md5sum_old is None):

                # Download the plugin file directly
                r = self._download_plugin(plugin_url)

                # Write downloaded plugin into file if checksums don't match
                if md5sum_old is None:
                    # No previously installed plugin
                    if not self.module.check_mode:
                        self._write_file(plugin_file, r)

                    changed = True
                else:
                    # Get data for the MD5
                    data = r.read()

                    # Make new checksum
                    md5sum_new = hashlib.md5(data).hexdigest()

                    # If the checksum is different from the currently installed
                    # plugin, store the new plugin
                    if md5sum_old != md5sum_new:
                        if not self.module.check_mode:
                            self._write_file(plugin_file, data)

                        changed = True
            elif self.params['version'] == 'latest':
                # Check for update from the updates JSON file
                plugin_data = self._download_updates()

                try:
                    with open(plugin_file, 'rb') as sha1_plugin_fh:
                        sha1_plugin_content = sha1_plugin_fh.read()
                    sha1_old = hashlib.sha1(sha1_plugin_content)
                except Exception as e:
                    self.module.fail_json(
                        msg="Cannot calculate SHA1 of the old plugin.",
                        details=to_native(e))

                sha1sum_old = base64.b64encode(sha1_old.digest())

                # If the latest version changed, download it
                if sha1sum_old != to_bytes(plugin_data['sha1']):
                    if not self.module.check_mode:
                        r = self._download_plugin(plugin_url)
                        self._write_file(plugin_file, r)

                    changed = True

        # Change file attributes if needed
        if os.path.isfile(plugin_file):
            params = {'dest': plugin_file}
            params.update(self.params)
            file_args = self.module.load_file_common_arguments(params)

            if not self.module.check_mode:
                # Not sure how to run this in the check mode
                changed = self.module.set_fs_attributes_if_different(
                    file_args, changed)
            else:
                # See the comment above
                changed = True

        return changed
Ejemplo n.º 43
0
    def __init__(self, module):
        self.module = module
        self.hostname = module.params['name']
        self.rack = module.params['rack']
        self.rank = module.params['rank']
        self.appliance = module.params['appliance']
        self.prim_intf = module.params['prim_intf']
        self.prim_intf_ip = module.params['prim_intf_ip']
        self.network = module.params['network']
        self.prim_intf_mac = module.params['prim_intf_mac']
        self.endpoint = module.params['stacki_endpoint']

        auth_creds = {
            'USERNAME': module.params['stacki_user'],
            'PASSWORD': module.params['stacki_password']
        }

        # Get Initial CSRF
        cred_a = self.do_request(self.module, self.endpoint, method="GET")
        cookie_a = cred_a.headers.get('Set-Cookie').split(';')
        init_csrftoken = None
        for c in cookie_a:
            if "csrftoken" in c:
                init_csrftoken = c.replace("csrftoken=", "")
                init_csrftoken = init_csrftoken.rstrip("\r\n")
                break

        # Make Header Dictionary with initial CSRF
        header = {
            'csrftoken': init_csrftoken,
            'X-CSRFToken': init_csrftoken,
            'Content-type': 'application/x-www-form-urlencoded',
            'Cookie': cred_a.headers.get('Set-Cookie')
        }

        # Endpoint to get final authentication header
        login_endpoint = self.endpoint + "/login"

        # Get Final CSRF and Session ID
        login_req = self.do_request(self.module,
                                    login_endpoint,
                                    headers=header,
                                    payload=urlencode(auth_creds),
                                    method='POST')

        cookie_f = login_req.headers.get('Set-Cookie').split(';')
        csrftoken = None
        for f in cookie_f:
            if "csrftoken" in f:
                csrftoken = f.replace("csrftoken=", "")
            if "sessionid" in f:
                sessionid = c.split("sessionid=", 1)[-1]
                sessionid = sessionid.rstrip("\r\n")

        self.header = {
            'csrftoken': csrftoken,
            'X-CSRFToken': csrftoken,
            'sessionid': sessionid,
            'Content-type': 'application/json',
            'Cookie': login_req.headers.get('Set-Cookie')
        }
Ejemplo n.º 44
0
def main():
    """
    Module execution

    :return:
    """
    argument_spec = keycloak_argument_spec()

    config_spec = dict(
        allowKerberosAuthentication=dict(type='bool', default=False),
        allowPasswordAuthentication=dict(type='bool'),
        authType=dict(type='str', choices=['none', 'simple'], default='none'),
        batchSizeForSync=dict(type='int', default=1000),
        bindCredential=dict(type='str', no_log=True),
        bindDn=dict(type='str'),
        cachePolicy=dict(type='str', choices=['DEFAULT', 'EVICT_DAILY', 'EVICT_WEEKLY', 'MAX_LIFESPAN', 'NO_CACHE'], default='DEFAULT'),
        changedSyncPeriod=dict(type='int', default=-1),
        connectionPooling=dict(type='bool', default=True),
        connectionPoolingAuthentication=dict(type='str', choices=['none', 'simple', 'DIGEST-MD5']),
        connectionPoolingDebug=dict(type='str'),
        connectionPoolingInitSize=dict(type='int'),
        connectionPoolingMaxSize=dict(type='int'),
        connectionPoolingPrefSize=dict(type='int'),
        connectionPoolingProtocol=dict(type='str'),
        connectionPoolingTimeout=dict(type='int'),
        connectionTimeout=dict(type='int'),
        connectionUrl=dict(type='str'),
        customUserSearchFilter=dict(type='str'),
        debug=dict(type='bool'),
        editMode=dict(type='str', choices=['READ_ONLY', 'WRITABLE', 'UNSYNCED']),
        enabled=dict(type='bool', default=True),
        evictionDay=dict(type='str'),
        evictionHour=dict(type='str'),
        evictionMinute=dict(type='str'),
        fullSyncPeriod=dict(type='int', default=-1),
        importEnabled=dict(type='bool', default=True),
        kerberosRealm=dict(type='str'),
        keyTab=dict(type='str', no_log=False),
        maxLifespan=dict(type='int'),
        pagination=dict(type='bool', default=True),
        priority=dict(type='int', default=0),
        rdnLDAPAttribute=dict(type='str'),
        readTimeout=dict(type='int'),
        searchScope=dict(type='str', choices=['1', '2'], default='1'),
        serverPrincipal=dict(type='str'),
        startTls=dict(type='bool', default=False),
        syncRegistrations=dict(type='bool', default=False),
        trustEmail=dict(type='bool', default=False),
        updateProfileFirstLogin=dict(type='bool'),
        useKerberosForPasswordAuthentication=dict(type='bool', default=False),
        usePasswordModifyExtendedOp=dict(type='bool', default=False, no_log=False),
        useTruststoreSpi=dict(type='str', choices=['always', 'ldapsOnly', 'never'], default='ldapsOnly'),
        userObjectClasses=dict(type='str'),
        usernameLDAPAttribute=dict(type='str'),
        usersDn=dict(type='str'),
        uuidLDAPAttribute=dict(type='str'),
        validatePasswordPolicy=dict(type='bool', default=False),
        vendor=dict(type='str'),
    )

    mapper_spec = dict(
        id=dict(type='str'),
        name=dict(type='str'),
        parentId=dict(type='str'),
        providerId=dict(type='str'),
        providerType=dict(type='str'),
        config=dict(type='dict'),
    )

    meta_args = dict(
        config=dict(type='dict', options=config_spec),
        state=dict(type='str', default='present', choices=['present', 'absent']),
        realm=dict(type='str', default='master'),
        id=dict(type='str'),
        name=dict(type='str'),
        provider_id=dict(type='str', aliases=['providerId'], choices=['ldap', 'kerberos']),
        provider_type=dict(type='str', aliases=['providerType'], default='org.keycloak.storage.UserStorageProvider'),
        parent_id=dict(type='str', aliases=['parentId']),
        mappers=dict(type='list', elements='dict', options=mapper_spec),
    )

    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=([['id', 'name'],
                                             ['token', 'auth_realm', 'auth_username', 'auth_password']]),
                           required_together=([['auth_realm', 'auth_username', 'auth_password']]))

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

    # Obtain access token, initialize API
    try:
        connection_header = get_token(module.params)
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

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

    # Keycloak API expects config parameters to be arrays containing a single string element
    if config is not None:
        module.params['config'] = dict((k, [str(v).lower() if not isinstance(v, str) else v])
                                       for k, v in config.items() if config[k] is not None)

    if mappers is not None:
        for mapper in mappers:
            if mapper.get('config') is not None:
                mapper['config'] = dict((k, [str(v).lower() if not isinstance(v, str) else v])
                                        for k, v in mapper['config'].items() if mapper['config'][k] is not None)

    # Filter and map the parameters names that apply
    comp_params = [x for x in module.params
                   if x not in list(keycloak_argument_spec().keys()) + ['state', 'realm', 'mappers'] and
                   module.params.get(x) is not None]

    # See if it already exists in Keycloak
    if cid is None:
        found = kc.get_components(urlencode(dict(type='org.keycloak.storage.UserStorageProvider', parent=realm, name=name)), realm)
        if len(found) > 1:
            module.fail_json(msg='No ID given and found multiple user federations with name `{name}`. Cannot continue.'.format(name=name))
        before_comp = next(iter(found), None)
        if before_comp is not None:
            cid = before_comp['id']
    else:
        before_comp = kc.get_component(cid, realm)

    if before_comp is None:
        before_comp = {}

    # if user federation exists, get associated mappers
    if cid is not None:
        before_comp['mappers'] = sorted(kc.get_components(urlencode(dict(parent=cid)), realm), key=lambda x: x.get('name'))

    # Build a proposed changeset from parameters given to this module
    changeset = {}

    for param in comp_params:
        new_param_value = module.params.get(param)
        old_value = before_comp[camel(param)] if camel(param) in before_comp else None
        if param == 'mappers':
            new_param_value = [dict((k, v) for k, v in x.items() if x[k] is not None) for x in new_param_value]
        if new_param_value != old_value:
            changeset[camel(param)] = new_param_value

    # special handling of mappers list to allow change detection
    if module.params.get('mappers') is not None:
        if module.params['provider_id'] == 'kerberos':
            module.fail_json(msg='Cannot configure mappers for Kerberos federations.')
        for change in module.params['mappers']:
            change = dict((k, v) for k, v in change.items() if change[k] is not None)
            if change.get('id') is None and change.get('name') is None:
                module.fail_json(msg='Either `name` or `id` has to be specified on each mapper.')
            if cid is None:
                old_mapper = {}
            elif change.get('id') is not None:
                old_mapper = kc.get_component(change['id'], realm)
                if old_mapper is None:
                    old_mapper = {}
            else:
                found = kc.get_components(urlencode(dict(parent=cid, name=change['name'])), realm)
                if len(found) > 1:
                    module.fail_json(msg='Found multiple mappers with name `{name}`. Cannot continue.'.format(name=change['name']))
                if len(found) == 1:
                    old_mapper = found[0]
                else:
                    old_mapper = {}
            new_mapper = old_mapper.copy()
            new_mapper.update(change)
            if new_mapper != old_mapper:
                if changeset.get('mappers') is None:
                    changeset['mappers'] = list()
                changeset['mappers'].append(new_mapper)

    # Prepare the desired values using the existing values (non-existence results in a dict that is save to use as a basis)
    desired_comp = before_comp.copy()
    desired_comp.update(changeset)

    result['proposed'] = sanitize(changeset)
    result['existing'] = sanitize(before_comp)

    # Cater for when it doesn't exist (an empty dict)
    if not before_comp:
        if state == 'absent':
            # Do nothing and exit
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['changed'] = False
            result['end_state'] = {}
            result['msg'] = 'User federation does not exist; doing nothing.'
            module.exit_json(**result)

        # Process a creation
        result['changed'] = True

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

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

        # create it
        desired_comp = desired_comp.copy()
        updated_mappers = desired_comp.pop('mappers', [])
        after_comp = kc.create_component(desired_comp, realm)

        for mapper in updated_mappers:
            if mapper.get('id') is not None:
                kc.update_component(mapper, realm)
            else:
                if mapper.get('parentId') is None:
                    mapper['parentId'] = after_comp['id']
                mapper = kc.create_component(mapper, realm)

        after_comp['mappers'] = updated_mappers
        result['end_state'] = sanitize(after_comp)

        result['msg'] = "User federation {id} has been created".format(id=after_comp['id'])
        module.exit_json(**result)

    else:
        if state == 'present':
            # Process an update

            # no changes
            if desired_comp == before_comp:
                result['changed'] = False
                result['end_state'] = sanitize(desired_comp)
                result['msg'] = "No changes required to user federation {id}.".format(id=cid)
                module.exit_json(**result)

            # doing an update
            result['changed'] = True

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

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

            # do the update
            desired_comp = desired_comp.copy()
            updated_mappers = desired_comp.pop('mappers', [])
            kc.update_component(desired_comp, realm)
            after_comp = kc.get_component(cid, realm)

            for mapper in updated_mappers:
                if mapper.get('id') is not None:
                    kc.update_component(mapper, realm)
                else:
                    if mapper.get('parentId') is None:
                        mapper['parentId'] = desired_comp['id']
                    mapper = kc.create_component(mapper, realm)

            after_comp['mappers'] = updated_mappers
            result['end_state'] = sanitize(after_comp)

            result['msg'] = "User federation {id} has been updated".format(id=cid)
            module.exit_json(**result)

        elif state == 'absent':
            # Process a deletion
            result['changed'] = True

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

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

            # delete it
            kc.delete_component(cid, realm)

            result['end_state'] = {}

            result['msg'] = "User federation {id} has been deleted".format(id=cid)

    module.exit_json(**result)
Ejemplo n.º 45
0
def main():

    module = AnsibleModule(argument_spec=dict(
        token=dict(required=True, no_log=True),
        msg=dict(required=True),
        type=dict(required=True, choices=["inbox", "chat"]),
        external_user_name=dict(required=False),
        from_address=dict(required=False),
        source=dict(required=False),
        subject=dict(required=False),
        from_name=dict(required=False),
        reply_to=dict(required=False),
        project=dict(required=False),
        tags=dict(required=False),
        link=dict(required=False),
        validate_certs=dict(default='yes', type='bool'),
    ),
                           supports_check_mode=True)

    type = module.params["type"]
    token = module.params["token"]
    if type == 'inbox':
        url = "https://api.flowdock.com/v1/messages/team_inbox/%s" % (token)
    else:
        url = "https://api.flowdock.com/v1/messages/chat/%s" % (token)

    params = {}

    # required params
    params['content'] = module.params["msg"]

    # required params for the 'chat' type
    if module.params['external_user_name']:
        if type == 'inbox':
            module.fail_json(
                msg="external_user_name is not valid for the 'inbox' type")
        else:
            params['external_user_name'] = module.params["external_user_name"]
    elif type == 'chat':
        module.fail_json(
            msg="external_user_name is required for the 'chat' type")

    # required params for the 'inbox' type
    for item in ['from_address', 'source', 'subject']:
        if module.params[item]:
            if type == 'chat':
                module.fail_json(msg="%s is not valid for the 'chat' type" %
                                 item)
            else:
                params[item] = module.params[item]
        elif type == 'inbox':
            module.fail_json(msg="%s is required for the 'inbox' type" % item)

    # optional params
    if module.params["tags"]:
        params['tags'] = module.params["tags"]

    # optional params for the 'inbox' type
    for item in ['from_name', 'reply_to', 'project', 'link']:
        if module.params[item]:
            if type == 'chat':
                module.fail_json(msg="%s is not valid for the 'chat' type" %
                                 item)
            else:
                params[item] = module.params[item]

    # If we're in check mode, just exit pretending like we succeeded
    if module.check_mode:
        module.exit_json(changed=False)

    # Send the data to Flowdock
    data = urlencode(params)
    response, info = fetch_url(module, url, data=data)
    if info['status'] != 200:
        module.fail_json(msg="unable to send msg: %s" % info['msg'])

    module.exit_json(changed=True, msg=module.params["msg"])
Ejemplo n.º 46
0
def post_sendgrid_api(module, username, password, from_address, to_addresses,
                      subject, body, api_key=None, cc=None, bcc=None, attachments=None,
                      html_body=False, from_name=None, headers=None):

    if not HAS_SENDGRID:
        SENDGRID_URI = "https://api.sendgrid.com/api/mail.send.json"
        AGENT = "Ansible"
        data = {'api_user': username, 'api_key': password,
                'from': from_address, 'subject': subject, 'text': body}
        encoded_data = urlencode(data)
        to_addresses_api = ''
        for recipient in to_addresses:
            recipient = to_bytes(recipient, errors='surrogate_or_strict')
            to_addresses_api += '&to[]=%s' % recipient
        encoded_data += to_addresses_api

        headers = {'User-Agent': AGENT,
                   'Content-type': 'application/x-www-form-urlencoded',
                   'Accept': 'application/json'}
        return fetch_url(module, SENDGRID_URI, data=encoded_data, headers=headers, method='POST')
    else:
        # Remove this check when adding Sendgrid API v3 support
        if LooseVersion(sendgrid.version.__version__) > LooseVersion("1.6.22"):
            module.fail_json(msg="Please install sendgrid==1.6.22 or lower since module uses Sendgrid V2 APIs.")

        if api_key:
            sg = sendgrid.SendGridClient(api_key)
        else:
            sg = sendgrid.SendGridClient(username, password)

        message = sendgrid.Mail()
        message.set_subject(subject)

        for recip in to_addresses:
            message.add_to(recip)

        if cc:
            for recip in cc:
                message.add_cc(recip)
        if bcc:
            for recip in bcc:
                message.add_bcc(recip)

        if headers:
            message.set_headers(headers)

        if attachments:
            for f in attachments:
                name = os.path.basename(f)
                message.add_attachment(name, f)

        if from_name:
            message.set_from('%s <%s.' % (from_name, from_address))
        else:
            message.set_from(from_address)

        if html_body:
            message.set_html(body)
        else:
            message.set_text(body)

        return sg.send(message)
Ejemplo n.º 47
0
def main():

    argspec = dict(state=dict(
        required=False,
        choices=['present', 'absent', 'enabled', 'disable'],
        default='present',
        type='str'),
                   connection_host=dict(required=False,
                                        choices=['ip', 'dns', 'none'],
                                        default='none',
                                        type='str'),
                   host=dict(required=False, type='str', default=None),
                   index=dict(required=False, type='str', default=None),
                   name=dict(required=True, type='str'),
                   protocol=dict(required=True,
                                 type='str',
                                 choices=['tcp', 'udp']),
                   queue=dict(required=False,
                              type='str',
                              choices=['parsingQueue', 'indexQueue'],
                              default='parsingQueue'),
                   rawTcpDoneTimeout=dict(required=False,
                                          type='int',
                                          default=10),
                   restrictToHost=dict(required=False,
                                       type='str',
                                       default=None),
                   ssl=dict(required=False, type='bool', default=None),
                   source=dict(required=False, type='str', default=None),
                   sourcetype=dict(required=False, type='str', default=None),
                   datatype=dict(required=False,
                                 choices=["cooked", "raw"],
                                 default="raw"))

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

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=['state', 'datatype', 'protocol'])
    # This is where the splunk_* args are processed
    request_data = splunk_request.get_data()

    query_dict = splunk_request.get_by_path(
        'servicesNS/nobody/search/data/inputs/{0}/{1}/{2}'.format(
            quote_plus(module.params['protocol']),
            quote_plus(module.params['datatype']),
            quote_plus(module.params['name']),
        ))

    if module.params['state'] in ['present', 'enabled', 'disabled']:
        _data = splunk_request.get_data()
        if module.params['state'] in ['present', 'enabled']:
            _data['disabled'] = False
        else:
            _data['disabled'] = True
        if query_dict:
            needs_change = False
            for arg in request_data:
                if arg in query_dict['entry'][0]['content']:
                    if to_text(
                            query_dict['entry'][0]['content'][arg]) != to_text(
                                request_data[arg]):
                        needs_change = True
            if not needs_change:
                module.exit_json(changed=False,
                                 msg="Nothing to do.",
                                 splunk_data=query_dict)
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict)
            if needs_change:
                splunk_data = splunk_request.create_update(
                    'servicesNS/nobody/search/data/inputs/{0}/{1}/{2}'.format(
                        quote_plus(module.params['protocol']),
                        quote_plus(module.params['datatype']),
                        quote_plus(module.params['name']),
                        data=urlencode(_data)))
            if module.params['state'] in ['present', 'enabled']:
                module.exit_json(changed=True,
                                 msg="{0} updated.",
                                 splunk_data=splunk_data)
            else:
                module.exit_json(changed=True,
                                 msg="{0} disabled.",
                                 splunk_data=splunk_data)
        else:
            # Create it
            splunk_data = splunk_request.create_update(
                'servicesNS/nobody/search/data/inputs/{0}/{1}'.format(
                    quote_plus(module.params['protocol']),
                    quote_plus(module.params['datatype']),
                ),
                data=urlencode(_data))
            module.exit_json(changed=True,
                             msg="{0} created.",
                             splunk_data=splunk_data)
    elif module.params['state'] == 'absent':
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                'servicesNS/nobody/search/data/inputs/{0}/{1}/{2}'.format(
                    quote_plus(module.params['protocol']),
                    quote_plus(module.params['datatype']),
                    quote_plus(module.params['name']),
                ))
            module.exit_json(changed=True,
                             msg="Deleted {0}.".format(module.params['name']),
                             splunk_data=splunk_data)

    module.exit_json(changed=False, msg="Nothing to do.", splunk_data={})
Ejemplo n.º 48
0
 def _get_profile_json(self):
     url = '/1.0/profiles/{0}'.format(self.name)
     if self.project:
         url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
     return self.client.do('GET', url, ok_error_codes=[404])
Ejemplo n.º 49
0
    def intersight_call(self,
                        http_method="",
                        resource_path="",
                        query_params=None,
                        body=None,
                        moid=None,
                        name=None):
        """
        Invoke the Intersight API

        :param resource_path: intersight resource path e.g. '/ntp/Policies'
        :param query_params: dictionary object with query string parameters as key/value pairs
        :param body: dictionary object with intersight data
        :param moid: intersight object moid
        :param name: intersight object name
        :return: json http response object
        """

        target_host = urlparse(self.host).netloc
        target_path = urlparse(self.host).path
        query_path = ""
        method = http_method.upper()
        bodyString = ""

        # Verify an accepted HTTP verb was chosen
        if (method not in ['GET', 'POST', 'PATCH', 'DELETE']):
            raise ValueError(
                'Please select a valid HTTP verb (GET/POST/PATCH/DELETE)')

        # Verify the resource path isn't empy & is a valid <str> object
        if (resource_path != "" and not (resource_path, str)):
            raise TypeError(
                'The *resource_path* value is required and must be of type "<str>"'
            )

        # Verify the query parameters isn't empy & is a valid <dict> object
        if (query_params is not None and not isinstance(query_params, dict)):
            raise TypeError(
                'The *query_params* value must be of type "<dict>"')

        # Verify the body isn't empy & is a valid <dict> object
        if (body is not None and not isinstance(body, dict)):
            raise TypeError('The *body* value must be of type "<dict>"')

        # Verify the MOID is not null & of proper length
        if (moid is not None and len(moid.encode('utf-8')) != 24):
            raise ValueError('Invalid *moid* value!')

        # Check for query_params, encode, and concatenate onto URL
        if query_params:
            query_path = "?" + urlencode(query_params).replace('+', '%20')

        # Handle PATCH/DELETE by Object "name" instead of "moid"
        if (method == "PATCH" or method == "DELETE"):
            if moid is None:
                if name is not None:
                    if isinstance(name, str):
                        moid = self.get_moid_by_name(resource_path, name)
                    else:
                        raise TypeError(
                            'The *name* value must be of type "<str>"')
                else:
                    raise ValueError(
                        'Must set either *moid* or *name* with "PATCH/DELETE!"'
                    )

        # Check for moid and concatenate onto URL
        if moid is not None:
            resource_path += "/" + moid

        # Check for GET request to properly form body
        if method != "GET":
            bodyString = json.dumps(body)

        # Concatenate URLs for headers
        target_url = self.host + resource_path + query_path
        request_target = method + " " + target_path + resource_path + query_path

        # Get the current GMT Date/Time
        cdate = get_gmt_date()

        # Generate the body digest
        body_digest = get_sha256_digest(bodyString)
        b64_body_digest = b64encode(body_digest.digest())

        # Generate the authorization header
        auth_header = {
            'Date': cdate,
            'Host': target_host,
            'Digest': "SHA-256=" + b64_body_digest.decode('ascii')
        }

        string_to_sign = prepare_str_to_sign(request_target, auth_header)
        b64_signed_msg = self.get_rsasig_b64encode(string_to_sign)
        auth_header = self.get_auth_header(auth_header, b64_signed_msg)

        # Generate the HTTP requests header
        request_header = {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'Host': '{0}'.format(target_host),
            'Date': '{0}'.format(cdate),
            'Digest': 'SHA-256={0}'.format(b64_body_digest.decode('ascii')),
            'Authorization': '{0}'.format(auth_header),
        }

        response, info = fetch_url(self.module,
                                   target_url,
                                   data=bodyString,
                                   headers=request_header,
                                   method=method,
                                   use_proxy=self.module.params['use_proxy'])

        return response, info
Ejemplo n.º 50
0
def main():
    argument_spec = dict(
        server_ip=dict(type='str', required=True),
        port=dict(type='str', default='main', choices=['main', 'kvm']),
        state=dict(type='str',
                   default='present',
                   choices=['present', 'absent']),
        whitelist_hos=dict(type='bool'),
        rules=dict(type='dict',
                   options=dict(input=dict(
                       type='list',
                       elements='dict',
                       options=dict(
                           name=dict(type='str'),
                           ip_version=dict(type='str',
                                           required=True,
                                           choices=['ipv4', 'ipv6']),
                           dst_ip=dict(type='str'),
                           dst_port=dict(type='str'),
                           src_ip=dict(type='str'),
                           src_port=dict(type='str'),
                           protocol=dict(type='str'),
                           tcp_flags=dict(type='str'),
                           action=dict(type='str',
                                       required=True,
                                       choices=['accept', 'discard']),
                       )), )),
        update_timeout=dict(type='int', default=30),
        wait_for_configured=dict(type='bool', default=True),
        wait_delay=dict(type='int', default=10),
        timeout=dict(type='int', default=180),
    )
    argument_spec.update(HETZNER_DEFAULT_ARGUMENT_SPEC)
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    # Sanitize input
    module.params['status'] = 'active' if (module.params['state']
                                           == 'present') else 'disabled'
    if module.params['rules'] is None:
        module.params['rules'] = {}
    if module.params['rules'].get('input') is None:
        module.params['rules']['input'] = []

    server_ip = module.params['server_ip']

    # https://robot.your-server.de/doc/webservice/en.html#get-firewall-server-ip
    url = "{0}/firewall/{1}".format(BASE_URL, server_ip)
    if module.params['wait_for_configured']:
        try:
            result, error = fetch_url_json_with_retries(
                module,
                url,
                check_done_callback=firewall_configured,
                check_done_delay=module.params['wait_delay'],
                check_done_timeout=module.params['timeout'],
            )
        except CheckDoneTimeoutException as dummy:
            module.fail_json(
                msg='Timeout while waiting for firewall to be configured.')
    else:
        result, error = fetch_url_json(module, url)
        if not firewall_configured(result, error):
            module.fail_json(
                msg=
                'Firewall configuration cannot be read as it is not configured.'
            )

    full_before = result['firewall']
    if not full_before.get('rules'):
        full_before['rules'] = create_default_rules_object()
    before = restrict_firewall_config(full_before)

    # Build wanted (after) state and compare
    after = dict(before)
    changed = False
    changed |= update(before, after, module.params, 'port')
    changed |= update(before, after, module.params, 'status')
    changed |= update(before, after, module.params, 'whitelist_hos')
    after['rules'] = create_default_rules_object()
    if module.params['status'] == 'active':
        for ruleset in RULES:
            changed |= update_rules(before, after, module.params, ruleset)

    # Update if different
    construct_result = True
    construct_status = None
    if changed and not module.check_mode:
        # https://robot.your-server.de/doc/webservice/en.html#post-firewall-server-ip
        url = "{0}/firewall/{1}".format(BASE_URL, server_ip)
        headers = {"Content-type": "application/x-www-form-urlencoded"}
        data = dict(after)
        data['whitelist_hos'] = str(data['whitelist_hos']).lower()
        del data['rules']
        for ruleset in RULES:
            encode_rule(data, ruleset, after)
        result, error = fetch_url_json(
            module,
            url,
            method='POST',
            timeout=module.params['update_timeout'],
            data=urlencode(data),
            headers=headers,
        )
        if module.params['wait_for_configured'] and not firewall_configured(
                result, error):
            try:
                result, error = fetch_url_json_with_retries(
                    module,
                    url,
                    check_done_callback=firewall_configured,
                    check_done_delay=module.params['wait_delay'],
                    check_done_timeout=module.params['timeout'],
                    skip_first=True,
                )
            except CheckDoneTimeoutException as e:
                result, error = e.result, e.error
                module.warn(
                    'Timeout while waiting for firewall to be configured.')

        full_after = result['firewall']
        if not full_after.get('rules'):
            full_after['rules'] = create_default_rules_object()
        construct_status = full_after['status']
        if construct_status != 'in process':
            # Only use result if configuration is done, so that diff will be ok
            after = restrict_firewall_config(full_after)
            construct_result = False

    if construct_result:
        # Construct result (used for check mode, and configuration still in process)
        full_after = dict(full_before)
        for k, v in after.items():
            if k != 'rules':
                full_after[k] = after[k]
        if construct_status is not None:
            # We want 'in process' here
            full_after['status'] = construct_status
        full_after['rules'] = dict()
        for ruleset in RULES:
            full_after['rules'][ruleset] = after['rules'][ruleset]

    module.exit_json(
        changed=changed,
        diff=dict(
            before=before,
            after=after,
        ),
        firewall=full_after,
    )
Ejemplo n.º 51
0
def update_qs(params):
    ''' Append key-value pairs to self.filter_string '''
    accepted_params = dict((k, v) for (k, v) in params.items() if v is not None)
    return '?' + urlencode(accepted_params)
Ejemplo n.º 52
0
 def get_urlencoded_data(self):
     return urlencode(self.get_data())
Ejemplo n.º 53
0
 def encode_url_params(self, params):
     """Encodes key value pairs for URL"""
     return "?{0}".format(urlencode(params))