def slack_id_map(): bot = Slack() channels = bot.api('conversations.list').body users = bot.api('users.list').body return { **dict(jmespath.search('members[][id, name]', users)), **dict(jmespath.search('channels[][id, name]', channels)), }
def main(): wrapper.init_script('Slack messaging') s = Slack(logger=logger, username='******', webhook='https://hooks.slack.com/<mySpecialHook>', channel='#channel_to_post_to') s.send_alert('This is a test message') wrapper.end_script()
class Processor(BaseProcessor): async def init(self, messenger, service_name): self.messenger = messenger self.service_name = f'{service_name}:/' self.slack = Slack() self.register_routes({'slack_alerts.send': self.send}, roles=['admin']) await self.check_for_tasks() async def process(self, msg): try: logger = Logger(self.messenger, msg) await self.execute(msg, logger) except Exception: await logger.error(traceback.format_exc()) async def send(self, msg, logger): await logger.log(msg) self.slack.send_alert(msg)
def handler(event, context): logger.info(f"updating cfn-vpn stack {event['StackName']} parameter AssociateSubnets with value {event['AssociateSubnets']}") slack = Slack(username=SLACK_USERNAME) try: if event['AssociateSubnets'] == 'false': logger.info(f"terminating current vpn sessions to {event['ClientVpnEndpointId']}") ec2 = boto3.client('ec2') resp = ec2.describe_client_vpn_connections(ClientVpnEndpointId=event['ClientVpnEndpointId']) for conn in resp['Connections']: if conn['Status']['Code'] == 'active': ec2.terminate_client_vpn_connections( ClientVpnEndpointId=event['ClientVpnEndpointId'], ConnectionId=conn['ConnectionId'] ) logger.info(f"terminated session {conn['ConnectionId']}") client = boto3.client('cloudformation') logger.info(client.update_stack( StackName=event['StackName'], UsePreviousTemplate=True, Capabilities=['CAPABILITY_IAM'], Parameters=[ { 'ParameterKey': 'AssociateSubnets', 'ParameterValue': event['AssociateSubnets'] } ] )) except Exception as ex: logger.error(f"failed to start/stop client vpn", exc_info=True) if event['AssociateSubnets'] == 'true': slack.post_event(message=f"failed to associate subnets with the client vpn", state=START_FAILED, error=ex) else: slack.post_event(message=f"failed to disassociate subnets with the client vpn", state=STOP_FAILED, error=ex) return 'KO' if event['AssociateSubnets'] == 'true': slack.post_event(message=f"successfully associated subnets with the client vpn", state=START_IN_PROGRESS) else: slack.post_event(message=f"successfully disassociated subnets with the client vpn", state=STOP_IN_PROGRESS) return 'OK'
def changedEvent(result): # slack notification if 'SLACK_URL' in globals(): slack = Slack(url=SLACK_URL) slackNotification(slack, result) print(f"CHANGED: {result['name']} {result['target']}")
async def init(self, messenger, service_name): self.messenger = messenger self.service_name = f'{service_name}:/' self.slack = Slack() self.register_routes({'slack_alerts.send': self.send}, roles=['admin']) await self.check_for_tasks()
def handler(event, context): logger.info(f"auto route populator triggered with event : {event}") slack = Slack(username=SLACK_USERNAME) lookup_type = None if 'Record' in event: cidrs = dns_lookup(event['Record']) lookup_item = event['Record'] if cidrs is None: slack.post_event( message=f"failed to resolve record {event['Record']}", state=RESOLVE_FAILED) logger.info(f"dns lookup found {len(cidrs)} IP's") elif 'Cloud' in event: cidrs = cloud_lookup(event['Cloud'], event.get('Filters', [])) lookup_item = f"cloud:{event['Cloud']}" logger.info( f"cloud {event['Cloud']} lookup found {len(cidrs)} IP address ranges" ) else: logger.error("one of [ Record | Cloud ] not found in event") return 'KO' if not cidrs: logger.error(f"no cidrs found") return 'KO' client = boto3.client('ec2') # describe vpn and check if subnets are associated with the vpn response = client.describe_client_vpn_endpoints( ClientVpnEndpointIds=[event['ClientVpnEndpointId']]) if not response['ClientVpnEndpoints']: logger.error(f"endpoint not found") slack.post_error(lookup_item, FAILED, "endpoint not found") return 'KO' endpoint = response['ClientVpnEndpoints'][0] if endpoint['Status'] == 'pending-associate': logger.error(f"no subnets associated with endpoint") slack.post_error(lookup_item, FAILED, "vpn is in a stopped state") return 'KO' routes = get_routes(client, event, lookup_item) auth_rules = get_auth_rules(client, event, lookup_item) auto_limit_increase = os.environ.get('AUTO_LIMIT_INCREASE') route_limit_increase_required = False auth_rules_limit_increase_required = False for cidr in cidrs: # create route if doesn't exist for subnet in event['TargetSubnets']: if not any(route['DestinationCidr'] == cidr and route['TargetSubnet'] == subnet for route in routes): try: create_route(client, event, cidr, subnet, lookup_item) except ClientError as e: if e.response['Error'][ 'Code'] == 'ClientVpnRouteLimitExceeded': route_limit_increase_required = True logger.error( "vpn route table has reached the route limit", exc_info=True) slack.post_error( lookup_item, ROUTE_LIMIT_EXCEEDED, "vpn route table has reached the route limit") elif e.response['Error'][ 'Code'] == 'InvalidClientVpnActiveAssociationNotFound': logger.warn("no subnets are associated with the vpn", exc_info=True) slack.post_error( lookup_item, SUBNET_NOT_ASSOCIATED, "no subnets are associated with the vpn") else: logger.error( "encountered a unexpected client error when creating a route", exc_info=True) else: slack.post_event( message= f"created new route {cidr} ({lookup_item}) to target subnet {subnet}", state=NEW_ROUTE) # remove route if target subnet has changed for route in routes: if route['DestinationCidr'] == cidr and route[ 'TargetSubnet'] not in event['TargetSubnets']: delete_route(client, event['ClientVpnEndpointId'], route['TargetSubnet'], cidr) # collect all rules that matches the current cidr cidr_auth_rules = [ rule for rule in auth_rules if rule['DestinationCidr'] == cidr ] try: # create rules for newly added groups if 'Groups' in event: existing_groups = list( set(rule['GroupId'] for rule in cidr_auth_rules)) new_groups = [ group for group in event['Groups'] if group not in existing_groups ] for group in new_groups: authorize_route(client, event, cidr, lookup_item, group) # create an allow all rule elif 'Groups' not in event and not cidr_auth_rules: authorize_route(client, event, cidr, lookup_item) except ClientError as e: if e.response['Error'][ 'Code'] == 'ClientVpnAuthorizationRuleLimitExceeded': auth_rules_limit_increase_required = True logger.error("vpn has reached the authorization rule limit", exc_info=True) slack.post_event( message= f"unable add to authorization rule for route {cidr} from lookup {lookup_item}", state=AUTH_RULE_LIMIT_EXCEEDED, error="vpn has reached the authorization rule limit") continue else: logger.error( "encountered a unexpected client error when creating an auth rule", exc_info=True) # request route limit increase if route_limit_increase_required and auto_limit_increase: case_id = increase_quota(10, ROUTE_TABLE_QUOTA_CODE, event['ClientVpnEndpointId']) if case_id is not None: slack.post_event( message= f"requested an increase for the routes per vpn service quota", state=QUOTA_INCREASE_REQUEST, support_case=case_id) else: logger.info( f"routes per vpn service quota increase request pending") # request auth rule limit increase if auth_rules_limit_increase_required and auto_limit_increase: case_id = increase_quota(20, AUTH_RULE_TABLE_QUOTA_CODE, event['ClientVpnEndpointId']) if case_id is not None: slack.post_event( message= f"requested an increase for the authorization rules per vpn service quota", state=QUOTA_INCREASE_REQUEST, support_case=case_id) else: logger.info( f"authorization rules per vpn service quota increase request pending" ) # remove expired auth rules for rule in expired_auth_rules(auth_rules, cidrs, event.get('Groups', [])): logger.info( f"removing expired auth rule {rule['DestinationCidr']} for lookup {lookup_item}" ) revoke_route_auth(client, event, rule['DestinationCidr']) # remove expired routes for route in expired_routes(routes, cidrs): logger.info( f"removing expired route {route['DestinationCidr']} for lookup {lookup_item}" ) delete_route(client, event['ClientVpnEndpointId'], route['TargetSubnet'], route['DestinationCidr']) slack.post_event( message= f"removed expired route {route['DestinationCidr']} for lookup {lookup_item}", state=EXPIRED_ROUTE) return 'OK'
class Slackotron(Scribe, object): ''' Slackotron(Scribe, object) ''' bot_slack_id = slackotron_settings.BOT_SLACK_ID bot_slack_name = slackotron_settings.BOT_SLACK_NAME bot_icon_url = slackotron_settings.BOT_ICON_URL bot_icon_emoji = slackotron_settings.BOT_ICON_EMOJI try: profanity_filter_on = slackotron_settings.PROFANITY_FILTER_ON if profanity_filter_on is not False or profanity_filter_on is not True: profanity_filter_on = True except Exception: profanity_filter_on = True slack = Slack() database_manager = DatabaseManager() locker = Locker() channel_user_manager = ChannelUserManager( **{ 'slack': slack, 'database_manager': database_manager, 'profanity_filter_on': profanity_filter_on, 'bot_slack_id': bot_slack_id, 'bot_slack_name': bot_slack_name, 'bot_icon_emoji': bot_icon_emoji, 'bot_icon_url': bot_icon_url } ) plugin_manager = PluginManager( **{ 'slack': slack } ) dashboard_manager = DashboardManager() def __init__(self): self.exit = False self.info('Slackotron bot Slack name: %s' % self.bot_slack_name) def start(self): ''' start() ''' if not self.slack.api_valid() or not self.slack.auth_valid(): self.critical('Slack API and/or auth not valid! Exiting.') sys.exit() self.locker.unlock_all() self.database_manager.connect() self.database_manager.create_tables(Base) self.channel_user_manager.start() self.plugin_manager.start() self.dashboard_manager.start() self._run() def stop(self): ''' stop() ''' self.dashboard_manager.stop() self.plugin_manager.stop() self.channel_user_manager.stop() self.database_manager.disconnect() self.locker.unlock_all() time.sleep(5) self.info(self.__class__.__name__ + ' stopped.') @decorators.rabbitmq_subscribe( host=slackotron_settings.RABBITMQ_HOST_URL ) def _on_rmq_message(self, *_, **kwargs): ''' _on_rmq_message(*args, **kwargs) ''' try: rmq_message = kwargs.get('rmq_message', '{}') or '{}' rmq_message = json.loads(rmq_message) self.exit = rmq_message.get('exit', False) or False except Exception as error: self.error(error) return None def _run(self): ''' _run() ''' while not self.exit: try: self._on_rmq_message() except Exception as error: self.error(error) traceback.print_exc() continue
def lambda_handler(event, context): body = parse_qs(event['body']) print(body) # TODO: timeout control return Slack.server_response(200, body=command_main(body))
import os import json from urllib.parse import parse_qs from lib.pipeline import Pipeline from lib.slack import Slack slack = Slack(os.environ["APP_NAME"], os.environ["FAVICON_URL"]) pipeline = Pipeline(os.environ['PIPELINE_NAME']) webhook_url = os.environ["SLACK_WEBHOOK_URL"] def is_relavant(detail): return detail["state"] == "FAILED" or detail["stage"] in os.environ["FILTER_STAGES"].split(',') def listen(event, context): detail = event["detail"] if is_relavant(detail): message = slack.build_message(pipeline.revision(detail["execution-id"]), os.environ['PIPELINE_NAME'], detail) body = slack.send(webhook_url, message) else: body = "Irrelevant event received" return { "statusCode": 200, "body": body } def review(event, context): detail = event["detail"] message = slack.build_prompt(pipeline.revision(detail["execution-id"]), os.environ['PIPELINE_NAME'], detail) body = slack.send(webhook_url, message) return { "statusCode": 200, "body": body } def approve(event, context): pipeline = Pipeline(os.environ['PIPELINE_NAME'])
def main(event): # Slack Error if reason := jmespath.search('headers."X-Slack-Retry-Reason"', event): print(reason) return Slack.server_response(500, headers={'X-Slack-No-Retry': 1})
Payload=json.dumps(event).encode()) @classmethod def bot_message(cls, event): lambda_client = boto3.client('lambda') lambda_client.invoke(FunctionName='event_bot_message', InvocationType='Event', Payload=json.dumps(event).encode()) def dispatcher(cls, event, query): body = json.loads(event.get('body')) query_diverge = getattr(cls, jmespath.search(query, body) or '', None) if callable(query_diverge): return query_diverge(event) def main(event): # Slack Error if reason := jmespath.search('headers."X-Slack-Retry-Reason"', event): print(reason) return Slack.server_response(500, headers={'X-Slack-No-Retry': 1}) result = dispatcher(TypeDiverge, event, 'type') return Slack.server_response(200, body=result) def lambda_handler(event, context): print(event.get('body')) return main(event)