def lambda_handler()

in code/fms/fms-mimic-shield-protect-route53-hosted-zones/lambda/index.py [0:0]


def lambda_handler(event, context):
  responseData = {}
  try:
    #List of Hosted Zones
    hostedZones = (r53_paginator.paginate().build_full_result())['HostedZones']
    logger.debug(hostedZones)
    #List of Shield Protected Resources
    shieldProtected = (shield_paginator.paginate().build_full_result())['Protections']
    logger.debug(shieldProtected)
  except botocore.exceptions.ClientError as error:
    logger.error(error.response['Error']['Message'])
    if 'RequestType' in event:
      responseData['Error'] = error.response['Error']
      cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "PaginateFailed")

    return (error.response['Error']['Message'])

  protectedArns = []
  protectionIdList = {}
  #Build a list of just resource ARN's for Shield Protected resouces
  for s in shieldProtected:
      protectedArns.append(s['ResourceArn'])
      protectionIdList[s['ResourceArn']] = s['Id']
  #If no hosted zones exist, stop gracefully now
  if hostedZones == []:
      logger.info("No Hosted Zones")
      return ()
  else:
      #For each Hosted Zone
      for zone in hostedZones:
          logger.info(zone)
          zoneId = zone['Id'].split('/')[2]
          zoneArn = "arn:aws:route53:::hostedzone/" + zoneId
          try:
            r = r53_client.list_tags_for_resources(
              ResourceType='hostedzone',
              ResourceIds=[
                  zoneId
                  ])
          except botocore.exceptions.ClientError as error:
            logger.error(error.response['Error']['Message'])
            if 'RequestType' in event:
              responseData['Error'] = error.response['Error']
              cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "ListTagsFailed")

            return (error.response['Error']['Message'])
          #Check resource tags vs. checkTags as include/exclude logic
          tagResults = tag_check(r['ResourceTagSets'][0]['Tags'])
          #If the hosted Zone is current Shield Protected
          isProtected = zoneArn in protectedArns
          #If tags match and it isn't protected
          if tagResults == True and isProtected == False:
              logger.info ("Not protected and should be")
              try:
                shield_client.create_protection(
                    Name=zoneId,
                    ResourceArn=zoneArn)
              except botocore.exceptions.ClientError as error:
                logger.error(error.response['Error']['Message'])
                if 'RequestType' in event:
                  responseData['Error'] = error.response['Error']
                  cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "ShieldCreateProtectionFailed")
                return (error.response['Error']['Message'])
          #If tags do not match requirements and it is Shield protected
          elif tagResults == False and isProtected == True:
              logger.info ("Protected and should not be")
              protectionId = protectionIdList['zoneArn']
              try:
                shield_client.delete_protection(
                    ProtectionId=protectionId)
              except botocore.exceptions.ClientError as error:
                logger.error(error.response['Error']['Message'])
                if 'RequestType' in event:
                  responseData['Error'] = error.response['Error']
                  cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "ShieldDeleteProtectionFailed")
                return (error.response['Error']['Message'])
          #The other possible results require no change/action for this resource
          #Is passed check tags and is already protected
          #Did not pass check tags and is not protected
          else:
              logger.info("No change to protection needed")
      #Signal CFN if this is a create, or update
      if 'RequestType' in event:
        cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")