#!/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,
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" try: relay.get(D.ownerIDs) except: print("No owner ids provided. Defaulting to: ", owner_ids)
#!/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)
# 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") print('\nFound {} instances without tags to stop:'.format(len(to_stop))) print(*[instance_id for instance_id in to_stop], sep = "\n")
#!/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)
#!/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)
#!/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)
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))
# 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))) print(*[i for i in to_terminate], sep="\n") print(
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))
# 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") print('\nFound {} unused key pairs:'.format(len(to_delete))) print(*[key for key in to_delete], sep="\n") print(
"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.") sys.exit(1) if not name:
#!/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()
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." ) sys.exit(1) if not permissions:
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) if not members: print("Missing `members` parameter on step configuration.")
#!/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
# 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']) except Exception as e: print( '\nEC2 instance {0} not considered for termination because of a processing error: {1}' .format(instance['InstanceId'], e))
# 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: print('No volumes to terminate! Exiting.') exit() else: relay.outputs.set('volumeIDs', to_terminate)
#!/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',
#!/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()
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)
#!/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
#!/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), region_name=relay.get(D.aws.region), aws_session_token=session_token) ec2 = sess.client('ec2') print("Deleted the following key pairs:\n") for key in relay.get(D.keyPairNames): print(key) ec2.delete_key_pair(KeyName=key)
#!/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")
#!/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)
#!/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']:
# 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) relay.outputs.set('status', get_http_status(url))
#!/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: