Ejemplo n.º 1
0
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)),
    }
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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'
Ejemplo n.º 5
0
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']}")
Ejemplo n.º 6
0
 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()
Ejemplo n.º 7
0
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'
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
def lambda_handler(event, context):
    body = parse_qs(event['body'])
    print(body)
    # TODO: timeout control
    return Slack.server_response(200, body=command_main(body))
Ejemplo n.º 10
0
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'])
Ejemplo n.º 11
0
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})
Ejemplo n.º 12
0
                             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)