예제 #1
0
#!/usr/bin/env python

import requests
import os
import time
from relay_sdk import Interface, Dynamic as D

relay = Interface()

apiURL = relay.get(D.connection.apiURL)
apiKey = relay.get(D.connection.apiKey)

timeStart = round(time.time() * 1000)
try:
    timeStart = int(relay.get(D.time.start))
except requests.exceptions.HTTPError:
    pass

timeEnd = timeStart
try:
    timeEnd = int(relay.get(D.time.end))
except requests.exceptions.HTTPError:
    pass

if timeEnd < timeStart:
    timeEnd = timeStart

payload = {
    'text': relay.get(D.text),
    'time': timeStart,
    'timeEnd': timeEnd,
예제 #2
0
#!/usr/bin/env python

from azure.identity import ClientSecretCredential
from azure.mgmt.compute import ComputeManagementClient
from relay_sdk import Interface, Dynamic as D
import logging

logging.basicConfig(level=logging.WARNING)

relay = Interface()

credentials = ClientSecretCredential(
    client_id=relay.get(D.azure.connection.clientID),
    client_secret=relay.get(D.azure.connection.secret),
    tenant_id=relay.get(D.azure.connection.tenantID)
)
subscription_id=relay.get(D.azure.connection.subscriptionID)
compute_client = ComputeManagementClient(credentials, subscription_id)

# Getting resource ids & options
resource_ids = None
wait = False 

try:
  resource_ids = relay.get(D.resourceIDs)
except:
  print('No Resource IDs found. Exiting.')
  exit

try:
  wait = relay.get(D.waitForDeletion)
예제 #3
0
import logging
import json

from relay_sdk import Interface, WebhookServer
from quart import Quart, request

relay = Interface()
app = Quart('incident-event-received')

logging.getLogger().setLevel(logging.INFO)


@app.route('/', methods=['POST'])
async def handler():
    if request.headers.get('X-Webhook-Id') is None:
        return {'message': 'not a valid PagerDuty event'}, 400, {}

    payload = await request.get_json(force=True)
    logging.info("Received the following webhook payload: \n%s",
                 json.dumps(payload, indent=4))

    for message in payload.get('messages', []):
        if message['event'] not in [
                'incident.trigger',
                #'incident.acknowledge',
                #'incident.unacknowledge',
                'incident.resolve',
                #'incident.assign',
                #'incident.escalate',
                #'incident.delegate',
                #'incident.annotate',
#!/usr/bin/env python

# File: filter-instances.py 
# Description: This is an example script that you can author or modify that retrieves 
#              a list of instances from the Relay Interface (in the form of parameters)
#              and filters the instances that are untagged. It then sets the output
#              variable `instanceIDs` to the list of instances that are untagged. 
# Inputs:
#   - instances - List of instances to evaluate 
# Outputs:
#   - instanceIDs - list of instance IDs to stop in the next step

from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_stop = []
to_keep = []

instances = filter(lambda i: i['State']['Name'] == 'running', relay.get(D.instances))
for instance in instances:
    try:
        if instance['Tags'] is None: 
            to_stop.append(instance['InstanceId'])
        else:
            to_keep.append(instance['InstanceId'])
    except Exception as e:
            print('\nEC2 instance {0} not considered for termination because of a processing error: {1}'.format(instance['InstanceId'], e))

print('\nFound {} instances (with tags) to keep:'.format(len(to_keep)))
print(*[instance_id for instance_id in to_keep], sep = "\n") 
예제 #5
0
#!/usr/bin/env python
from functools import partial

import boto3
from relay_sdk import Interface, Dynamic as D

relay = Interface()

session_token = None
try:
    session_token = relay.get(D.aws.connection.sessionToken)
except:
    pass

sess = boto3.Session(aws_access_key_id=relay.get(D.aws.connection.accessKeyID),
                     aws_secret_access_key=relay.get(
                         D.aws.connection.secretAccessKey),
                     aws_session_token=session_token)
s3 = sess.client('s3')
bucketName = relay.get(D.name)

try:
    response = s3.delete_bucket(Bucket=bucketName)
    print("Deleting bucket {}", bucketName)
except Exception as e:
    print(e)
예제 #6
0
#!/usr/bin/env python

from azure.identity import ClientSecretCredential
from azure.mgmt.network import NetworkManagementClient
from relay_sdk import Interface, Dynamic as D
import logging

logging.basicConfig(level=logging.WARNING)

relay = Interface()

credentials = ClientSecretCredential(
    client_id=relay.get(D.azure.connection.clientID),
    client_secret=relay.get(D.azure.connection.secret),
    tenant_id=relay.get(D.azure.connection.tenantID))
subscription_id = relay.get(D.azure.connection.subscriptionID)
network_client = NetworkManagementClient(credentials, subscription_id)

output_list = []  # Output list
resources = []  # List of resources

# If resource group is specified, use that
rg = ''
try:
    rg = relay.get(D.resourceGroup)
except:
    pass

if (rg):
    resources = network_client.network_interfaces.list(rg)
예제 #7
0
#!/usr/bin/env python
from relay_sdk import Interface, Dynamic as D


relay = Interface()

to_modify = []
to_do_nothing = []

encryptionConfigurations = relay.get(D.encryptionConfigurations)

for bucket in encryptionConfigurations.keys():
    # If the encryption configuration of a bucket is none, bucket is unencrypted. Adding these to list of buckets to encrypt. 
    if encryptionConfigurations[bucket] == None:
        to_modify.append(bucket)
    else:
        to_do_nothing.append(bucket)

print("\nFound {} bucket(s) that are encrypted:".format(len(to_do_nothing)))
print(*[bucket for bucket in to_do_nothing], sep = "\n")

print("\nFound {} bucket(s) that are NOT encrypted:".format(len(to_modify)))
print(*[bucket for bucket in to_modify], sep = "\n")

print('\nSetting output variable `buckets` with list of {} bucket(s) that are NOT encrypted.'.format(len(to_modify)))
relay.outputs.set('buckets', to_modify)
예제 #8
0
        exit(1)

    # TODO: How to validate all the required data is present here?
    service_account_info = slice(
        json.loads(
            relay.get(D.google.service_account_info)['serviceAccountKey']),
        service_account_info_keys)

    credentials = service_account.Credentials.from_service_account_info(
        service_account_info)
    compute = googleapiclient.discovery.build("compute",
                                              "v1",
                                              credentials=credentials)

    for instance in instances:
        if isinstance(instance, dict):
            do_start_instance(compute,
                              project_id=credentials.project_id,
                              zone=zone,
                              name=instance["name"])
        else:
            do_start_instance(compute,
                              project_id=credentials.project_id,
                              zone=zone,
                              name=instance)


if __name__ == "__main__":
    relay = Interface()
    start_instances(relay.get(D.instances))
예제 #9
0
#!/usr/bin/env python

# File: filter-loadbalancers.py
# Description: This is an example script that you can author or modify that retrieves
#              a list of Azure Network Interfaces and filters the ones that are unused e.g.
#              no VM configuration.
# Inputs:
#   - networkInterfaces - list of Azure NICs
# Outputs:
#   - resourceIDs - list of Azure Virtual Machine resource IDs to be terminated in the subsequent step

from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_terminate = []
to_keep = []

nics = relay.get(D.networkInterfaces)
for nic in nics:
    if 'virtual_machine' in nic.keys():
        to_keep.append(nic['id'])
    else:
        to_terminate.append(nic['id'])
        continue

print('\nFound {} Network Interfaces that are used:'.format(len(to_keep)))
print(*[i for i in to_keep], sep="\n")

print('\nFound {} Network Interfaces that are NOT used:'.format(
    len(to_terminate)))
예제 #10
0
        exit(1)

    # TODO: How to validate all the required data is present here?
    service_account_info = slice(
        json.loads(
            relay.get(D.google.service_account_info)['serviceAccountKey']),
        service_account_info_keys)

    credentials = service_account.Credentials.from_service_account_info(
        service_account_info)
    compute = googleapiclient.discovery.build("compute",
                                              "v1",
                                              credentials=credentials)

    for disk in disks:
        if isinstance(disk, dict):
            do_delete_disk(compute,
                           project_id=credentials.project_id,
                           zone=zone,
                           name=disk["name"])
        else:
            do_delete_disk(compute,
                           project_id=credentials.project_id,
                           zone=zone,
                           name=disk)


if __name__ == "__main__":
    relay = Interface()
    delete_disks(relay.get(D.disks))
#!/usr/bin/env python

# File: filter-key-pairs.py
# Description: This is an example script that you can author or modify that retrieves
#              a list of key pairs from the Relay Interface (in the form of parameters)
#              and filters the key pairs that are unused. It then sets the output
#              variable `keypairs` to the list of key pairs that are unused.
# Inputs:
#   - keyPairs - List of keyPairs to evaluate
#   - instances - List of instances to compare against
# Outputs:
#   - keyPairNames - list of key pair names

from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_delete = []
to_keep = []

all_keyPairs = list(map(lambda i: i['KeyName'], relay.get(D.keyPairs)))
used_keyPairs = list(map(lambda i: i['KeyName'], relay.get(D.instances)))

for key in all_keyPairs:
    if key in used_keyPairs:
        to_keep.append(key)
    else:
        to_delete.append(key)

print('\nFound {} used key pairs:'.format(len(to_keep)))
print(*[key for key in to_keep], sep="\n")
예제 #12
0
    table_keys = [
        "id",
        "selfLink",
        "tableReference",
        "description",
        "schema",
        #"labels", #TODO do we want this?
        "creationTime",
        "location",
    ]

    return slice(result, table_keys)


if __name__ == "__main__":
    relay = Interface()

    credentials = get_credentials(relay.get(D.google.connection))
    project = get_or_default(D.google.project, credentials.project_id)
    dataset_id = relay.get(D.dataset_id)
    name = relay.get(D.name)
    description = get_or_default(D.description, None)
    schema = get_or_default(D.schema, None)

    if not project:
        print(
            "Missing `google.project` parameter on step configuration and no project was found in the connection."
        )
        sys.exit(1)
    if not dataset_id:
        print("Missing `dataset_id` parameter on step configuration.")
예제 #13
0
#!/usr/bin/env python
# extracts an incident's id, given its friendly name

import requests, os, base64
from relay_sdk import Interface, Dynamic as D

relay = Interface()

# build up the request from workflow parameters
url = relay.get(D.connection.url) + '/rest/api/3/user/search'

headers = {'Accept': 'application/json'}

userEmail = relay.get(D.userEmail)
params = {'query': userEmail}

r = requests.get(url,
                 headers=headers,
                 params=params,
                 auth=(relay.get(D.connection.username),
                       relay.get(D.connection.password)))

r.raise_for_status()

print('Sent query to JIRA, got response: ', r.text, "\n\n")

response = r.json()

user_id = 'not_found'

# Caveat: the response will be an array of user objects, but
#!/usr/bin/env python
# posts an update to a firehydrant.io incident timeline from relay

import requests, os
from relay_sdk import Interface, Dynamic as D

relay = Interface()

apiKey = relay.get(D.apiKey)
incidentID = relay.get(D.incidentID)
message = relay.get(D.message)

eventPayload = {'body': message}

headers = {"Authorization": apiKey}

url = 'https://api.firehydrant.io/v1/incidents/' + str(incidentID) + "/notes"

r = requests.post(url, headers=headers, json=eventPayload)

print('Emitted event to FireHydrant API, got response: ', r.text)

r.raise_for_status()
예제 #15
0
    ]

    return_result = slice(result, return_keys)

    # Align naming with expected values
    return_result['permissions'] = return_result['includedPermissions']
    return_result.pop('includedPermissions', None)

    print("Converted Result:")
    print(return_result)

    return return_result


if __name__ == "__main__":
    relay = Interface()

    credentials = get_credentials(relay.get(D.google.connection))
    project = get_or_default(D.google.project, credentials.project_id)
    name = relay.get(D.name)
    title = get_or_default(D.title, name)
    description = get_or_default(D.description, None)
    permissions = relay.get(D.permissions)

    if not name:
        print("Missing `name` parameter on step configuration.")
        sys.exit(1)
    if not project:
        print(
            "Missing `google.project` parameter on step configuration and no project was found in the connection."
        )
예제 #16
0
            binding["members"].remove(member)

    return set_policy(crm_service, project_id, policy)


def get_or_default(path, default=None):
    try:
        return relay.get(path)
    except requests.exceptions.HTTPError as err:
        if err.response.status_code == 422:
            return default
        raise


if __name__ == "__main__":
    relay = Interface()

    credentials = get_credentials(relay.get(D.google.connection))
    project = get_or_default(D.google.project, credentials.project_id)
    role = relay.get(D.role)
    members = relay.get(D.members)
    condition = get_or_default(D.condition, None)

    if not project:
        print(
            "Missing `google.project` parameter on step configuration and no project was found in the connection."
        )
        sys.exit(1)
    if not role:
        print("Missing `role` parameter on step configuration.")
        sys.exit(1)
예제 #17
0
#!/usr/bin/env python
import pysnow
from relay_sdk import Interface, Dynamic as D

relay = Interface()

# Create client object
host = relay.get(D.servicenow.connection.host)
user = relay.get(D.servicenow.connection.user)
password = relay.get(D.servicenow.connection.password)

c = None
try:
    c = pysnow.Client(host=host, user=user, password=password)
except:
    print('ERROR: Failed to authenticate to ServiceNow. Exiting.') 
    exit(1)

# Define an incident table resource
incident = c.resource(api_path='/table/incident')

# Set the payload
new_incident = {
    'short_description': relay.get(D.shortDescription),
    'description': relay.get(D.description),
    'priority': relay.get(D.priority),
    'impact': relay.get(D.impact),
    'state': relay.get(D.state)
}

# Create a new incident record
#!/usr/bin/env python

# File: filter-instances.py
# Description: This is an example script that you can author or modify that retrieves
#              a list of instances from the Relay Interface (in the form of parameters)
#              and filters the instances that are untagged. It then sets the output
#              variable `instanceIDs` to the list of instances that are untagged.
# Inputs:
#   - instances - List of instances to evaluate
# Outputs:
#   - instanceIDs - list of instance IDs to stop in the next step

from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_stop = []
to_keep = []

instances = filter(lambda i: i['State']['Name'] == 'running',
                   relay.get(D.instances))
if len(instances) == 0:
    print("No instances found!")
    exit(1)

for instance in instances:
    try:
        if instance['Tags'] is None:
            to_stop.append(instance['InstanceId'])
        else:
            to_keep.append(instance['InstanceId'])
#!/usr/bin/env python

# File: filter-volumes.py
# Description: This is an example script that you can author or modify that retrieves
#              a list of Volumes from the Relay Interface (in the form of parameters)
#              and filters the volumes that are unattached. It then sets the output
#              variable `volumeIDs` to the list of EBS volumes that are unattached.
# Inputs:
#   - volumes - list of EBS volumes
# Outputs:
#   - volumeids - list of EBS volume ids to be terminated in the subsequent step

from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_terminate = []

# Filtering volumes with no attachments
volumes = filter(lambda i: len(i['Attachments']) == 0, relay.get(D.volumes))
for volume in volumes:
    try:
        to_terminate.append(volume['VolumeId'])
        print('Terminating EBS volume {0} with no attachments'.format(
            volume['VolumeId']))
    except Exception as e:
        print(
            'EBS volume {0} not considered for termination because of a processing error: {1}'
            .format(volume['VolumeId'], e))

if len(to_terminate) == 0:
예제 #20
0
#!/usr/bin/env python

from sys import exit
from urllib.parse import quote

from pdpyras import APISession
from relay_sdk import Interface, Dynamic as D

relay = Interface()

token = relay.get(D.connection.accessToken)
session = APISession(token)

user_id = relay.get(D.userID)
if user_id is None:
    exit("A userID is required, but none was set")

admin_key = relay.get(D.connection.accessToken)
session = APISession(admin_key)

# https://2.python-requests.org/en/master/api/#requests.Session.request
# eg https://api.pagerduty.com/users/PHNH11G
response = session.request("get", "https://api.pagerduty.com/users/" + quote(user_id))
response.raise_for_status()

data = response.json()

for output, prop in {
    'name': 'name',
    'email': 'email',
    'description': 'description',
예제 #21
0
#!/usr/bin/env python

import requests
import os
import time
from relay_sdk import Interface, Dynamic as D

relay = Interface()

apiURL = relay.get(D.connection.apiURL)
apiKey = relay.get(D.connection.apiKey)

params = {'type': 'dash-db'}

try:
    tags = relay.get(D.tags)
    params['tag'] = tags
except requests.exceptions.HTTPError:
    pass

print("Query params: ", params)

r = requests.get(apiURL + '/search',
                 headers={'Authorization': 'Bearer ' + apiKey},
                 params=params)

print('Emitted event to Grafana API, got response: ', r.text)

relay.outputs.set('response', r.json())

r.raise_for_status()
예제 #22
0
        exit(1)

    # TODO: How to validate all the required data is present here?
    service_account_info = slice(
        json.loads(
            relay.get(D.google.service_account_info)['serviceAccountKey']),
        service_account_info_keys)

    credentials = service_account.Credentials.from_service_account_info(
        service_account_info)
    compute = googleapiclient.discovery.build("compute",
                                              "v1",
                                              credentials=credentials)

    for instance in instances:
        if isinstance(instance, dict):
            do_delete_instance(compute,
                               project_id=credentials.project_id,
                               zone=zone,
                               name=instance["name"])
        else:
            do_delete_instance(compute,
                               project_id=credentials.project_id,
                               zone=zone,
                               name=instance)


if __name__ == "__main__":
    relay = Interface()
    delete_instances(relay.get(D.instances))
#!/usr/bin/env python
# queries the slack api with the email address and gets back a user id

import os
import sys
from relay_sdk import Interface, Dynamic as D
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

relay = Interface()

api_token = relay.get(D.connection.apiToken)
email_address = relay.get(D.email)

try:
    client = WebClient(api_token)
    client.auth_test()
except SlackApiError as e:
    sys.stderr.write('Unable to authenticate with Slack')
    exit(1)

try:
    response = client.users_lookupByEmail(email=email_address)

    if response and response['user']:
        relay.outputs.set("memberID", response['user']['id'])
except SlackApiError as e:
    sys.stderr.write('The error return from the Slack API is: ' +
                     e.response["error"])
    exit(1)
예제 #24
0
#!/usr/bin/env python
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import (Mail, Cc, Bcc)
from relay_sdk import Interface, Dynamic as D

relay = Interface()

def coerce_to_list(data):
  return data if isinstance(data, list) else [data]

api_key = relay.get(D.sendgrid.connection.apiKey)

from_address = relay.get("from")
subject = relay.get(D.subject)
to_address = coerce_to_list(relay.get(D.to))

cc_addresses = None

try:
  cc_addresses = coerce_to_list(relay.get(D.cc))
except:
  pass

bcc_addresses = None

try:
  bcc_addresses = coerce_to_list(relay.get(D.bcc))
except:
  pass

text = None
예제 #25
0
import boto3
from relay_sdk import Interface, Dynamic as D


def snapshot_to_dict(ec2, snapshot):
    shape = ec2.meta.client.meta.service_model.shape_for('Snapshot')
    attrs = snapshot.meta.resource_model.get_attributes(shape)

    d = {}
    for mapped, (name, shape) in attrs.items():
        d[name] = getattr(snapshot, mapped)

    return d


relay = Interface()

session_token = None
try:
    session_token = relay.get(D.aws.connection.sessionToken)
except:
    pass

sess = boto3.Session(aws_access_key_id=relay.get(D.aws.connection.accessKeyID),
                     aws_secret_access_key=relay.get(
                         D.aws.connection.secretAccessKey),
                     region_name=relay.get(D.aws.region),
                     aws_session_token=session_token)

owner_ids = "self"
예제 #26
0
#!/usr/bin/env python
from relay_sdk import Interface, Dynamic as D

relay = Interface()

to_modify = []
to_do_nothing = []

bucketACLs = relay.get(D.bucketACLs)

for bucketName in bucketACLs.keys():
    public_bucket = False

    # If the URI of the grant is "http://acs/amazonaws.com/groups/global/AllUsers" and the permission contains "WRITE_ACP", adding to list to remediate.
    for grant in bucketACLs[bucketName]:
        if grant['Grantee']['Type'] == "Group" and grant['Grantee'][
                'URI'] == "http://acs.amazonaws.com/groups/global/AllUsers" and "WRITE_ACP" in str(
                    grant['Permission']):
            public_bucket = True
        else:
            continue

    if public_bucket:
        to_modify.append(bucketName)
    else:
        to_do_nothing.append(bucketName)

print("\nFound {} bucket(s) that DON'T have public WRITE_ACP permissions:".
      format(len(to_do_nothing)))
print(*[bucket for bucket in to_do_nothing], sep="\n")
예제 #27
0
#!/usr/bin/env python
from relay_sdk import Interface, Dynamic as D

relay = Interface()

if __name__ == '__main__':
    to_terminate = []
    print('Disk to be terminated:')
    disks = relay.get(D.disks)
    for disk in disks:
        if "users" not in disk.keys():
            print(disk.get('name'))
            to_terminate.append(disk)

    print('Found {} disks that are unattached'.format(len(to_terminate)))
    print('Setting output `disks` to list of {} disks to terminate'.format(
        len(to_terminate)))

    relay.outputs.set('disks', to_terminate)
예제 #28
0
#!/usr/bin/env python
import re
from jinja2 import Template
from relay_sdk import Interface, Dynamic as D

relay = Interface()

modules = relay.get(D.modules)
repositories = relay.get(D.repositories)
unmarked = relay.get(D.unmarked)
incomplete = relay.get(D.incomplete)

tag_module = []
badge_supported = []
badge_unsupported = []
source_field_problem = []

for mod in modules:
    try:
        reponame = re.search('github\.com[/:]puppetlabs\/([\w-]*)',
                             mod['metadata']['source']).group(1)
        repo = next(x for x in repositories if x['name'] == reponame)

        if not 'module' in repo['topics']:
            tag_module.append(repo)

        if mod['endorsement'] != 'supported' and 'supported' in repo['topics']:
            badge_supported.append(mod)

        if mod['endorsement'] == 'supported' and not 'supported' in repo[
                'topics']:
예제 #29
0
#!/usr/bin/env python

# File: get-http-status.py
# Description: This example script makes a request to a URL and sets its status
#              a the output. The status can be used in subsequent steps to
#              perform different bits of logic in a workflow.

from urllib.request import urlopen

from relay_sdk import Interface, Dynamic as D

relay = Interface()


def get_http_status(url):
    try:
        with urlopen(url) as response:
            return str(response.status)
    except:
        # empty string indicates something bad happened.
        return ""


if __name__ == '__main__':
    url = None
    try:
        url = relay.get(D.url)
    except:
        print('No URL was configured. Exiting.')
        exit(1)
예제 #30
0
#!/usr/bin/env python
import boto3
from relay_sdk import Interface, Dynamic as D

relay = Interface()

session_token = None
try:
    session_token = relay.get(D.aws.connection.sessionToken)
except:
    pass

sess = boto3.Session(aws_access_key_id=relay.get(D.aws.connection.accessKeyID),
                     aws_secret_access_key=relay.get(
                         D.aws.connection.secretAccessKey),
                     region_name=relay.get(D.aws.region),
                     aws_session_token=session_token)

elbv2 = sess.client('elbv2')

elb_arns = []  # List of Load Balancers to look for target groups under
all_target_groups = []  # List of target groups by ELB
get_all = False  # Get all groups if no ELBs are specified

try:
    loadbalancers = relay.get(D.loadbalancers)
    elb_arns = [i["LoadBalancerArn"] for i in loadbalancers]
except:
    try:
        elb_arns = relay.get(D.loadbalancerARNs)
    except: