예제 #1
0
def main_function(event, context):
    name = kms_decrypted("IGNORE_QUEUE")
    region = kms_decrypted("REGION", "ap-northeast-1")
    sqs = boto3.client('sqs', region_name=region)
    url = sqs.get_queue_url(QueueName=name)
    url = url["QueueUrl"]
    print_json({"type": "SQS", "message": "Search Message", "queue": name})
    while (True):
        result = sqs.receive_message(QueueUrl=url,
                                     MaxNumberOfMessages=10,
                                     VisibilityTimeout=30,
                                     WaitTimeSeconds=20,
                                     AttributeNames=["All"],
                                     MessageAttributeNames=["SystemAlertId"])
        if "Messages" not in result:
            break
        if len(result["Messages"]) == 0:
            break
        print_json({
            "type": "lambda",
            "message": "Lambdaを再帰呼出しします",
            "payload": result
        })
        if lambda_tools.aws_request_id == "debug":
            lambda_handler(result, context)
        else:
            invoke(result)
예제 #2
0
def set_ignore_queue(message):
    body = json.loads(message)
    name = kms_decrypted("IGNORE_QUEUE")
    system_alert_id = body["SystemAlertId"]
    region = kms_decrypted("REGION", "ap-northeast-1")
    sqs = boto3.resource('sqs', region_name=region)
    try:
        queue = sqs.get_queue_by_name(QueueName=name)
    except Exception as e:
        queue = sqs.create_queue(QueueName=name)
    queue.set_attributes(Attributes={
        'ReceiveMessageWaitTimeSeconds': '20',
        'VisibilityTimeout': '30'
    })
    print_json({
        "type": "SQS",
        "message": "Send Message",
        "queue": name,
        "payload": message
    })
    result = queue.send_message(MessageBody=message,
                                MessageAttributes={
                                    "SystemAlertId": {
                                        "StringValue": system_alert_id,
                                        'DataType': 'String'
                                    }
                                })
    message_id = result["MessageId"]
    return message_id
예제 #3
0
def remove_message(message_id, system_alert_id):
    """
    @brief      指定したMessageIdとSystemAlertIdに合致するSQSメッセージの削除
    @params[in] message_id      SQSのメッセージId
    @params[in] system_alert_id Azure SentinelのアラートID
    """
    name = kms_decrypted("IGNORE_QUEUE")
    region = kms_decrypted("REGION", "ap-northeast-1")
    sqs = boto3.resource('sqs', region_name=region)
    queue = sqs.get_queue_by_name(QueueName=name)
    id = None
    recipt_handle = None
    print_json({
       "type": "SQS",
       "message": "Search Message",
       "queue": name,
       "message_id": message_id,
    })
    while(True):
        result = queue.receive_messages(
            MaxNumberOfMessages=10,
            VisibilityTimeout=3,
            WaitTimeSeconds=20,
            MessageAttributeNames=["SystemAlertId"]
        )
        if len(result) == 0:
            break
        for msg in result:
            if message_id != msg.message_id:
                continue
            said = msg.message_attributes.get("SystemAlertId", None)
            if said is None:
                continue
            if system_alert_id != said["StringValue"]:
                continue

            receipt_handle = msg.receipt_handle
            print_json({
                "type": "SQS",
                "message": "Delete Message",
                'message_id': message_id,
                'receipt_handle': receipt_handle
            })
            response = queue.delete_messages(Entries=[{
                'Id': message_id,
                'ReceiptHandle': receipt_handle
            }])
            return True
    return False
예제 #4
0
def answer_false(event, action):
    value = action["value"]
    value = json.loads(value)
    print_json({
        "type": "Slack",
        "message": "Interactive Event Value",
        "value": value,
    })
    message = event["message"]
    alert_id = value["SystemAlertId"]
    user = event["user"],
    channel_id = event["container"]["channel_id"]
    blocks = message["blocks"]
    blocks[2] = {
        "type": "section",
        "block_id": "reason",
        "fields": [
            {"type": "mrkdwn", "text": "*応答*"},
            {"type": "mrkdwn", "text": "心当たりがない"},
            {"type": "mrkdwn", "text": "*応答ユーザー*"},
            {"type": "mrkdwn", "text": user[0]["username"]}
        ]
    }
    set_status(alert_id, False)
    slack_api_token = kms_decrypted("SLACK_API_TOKEN")
    slack_chat = Slack.Chat(token=slack_api_token)
    post_args = {
        "channel": channel_id,
        "text": message["text"],
        "ts": message["ts"],
        "blocks": blocks,
    }
    slack_chat.update_message(**post_args)
예제 #5
0
def box_create_user_folder(name: str):
    box_folder_id = kms_decrypted("BOX_FOLDER_ID")
    response = box_folder.items(folder_id=box_folder_id, fields=["name"])
    tree = objectpath.Tree(response)
    query = '$..entries[@.type is "folder" and @.name is "{}"].id'
    query = query.format(name)
    dt = list(tree.execute(query))
    if len(dt) > 0:
        return dt.pop()
    else:
        response = box_folder.create(name, box_folder_id, fields=["id"])
        return response["id"]
예제 #6
0
def google_uploader(file, stream, length, event):
    name = file["name"]
    mime = file["mimetype"]
    buf = io.BytesIO(stream.read())
    # Google Drive用メタデータ作成
    metadata = GSuite.Drive.Metadata()
    metadata.name = name
    metadata.writersCanShare = True
    parent_id = kms_decrypted("GSUITE_PARENT_ID")
    metadata.parents = [parent_id]
    print_json({
        "type": "lambda",
        "message": "Slack上のFileをGoogle Driveにアップロードします",
        "name": name,
        "size": length
    })
    # Google Driveにアップロード
    file = gdrive.insert(
        metadata=metadata,
        file_stream=buf,
        original_mime_type=mime,
        fields='id, webViewLink, permissions'
    )
    print_json({
        "type": "lambda",
        "message": "Slack上のFileをGoogle Driveにアップロードしました",
        "name": name,
        "size": length
    })
    link = file.get("webViewLink")
    id = file.get("id")
    pids = file["permissions"]
    perm = {}
    perm["type"] = "domain"
    perm['role'] = 'reader'
    perm['domain'] = kms_decrypted("GSUITE_DOMAIN")
    gdrive_permission.create(file_id=id, permission=perm)
    link = file.get("webViewLink")
    return id, name, link
예제 #7
0
def set_status(system_alert_id, status, message: str = None):
    """
    @brief      Logic Appにステータスを送信
    @params[in] system_alert_id     Azure SentinelのSystem Alert Id
    @params[in] status              ユーザー応答結果
    @n                              True : 意図している
    @n                              False: 覚えがない
    @params[in] message             理由テキスト
    """
    url = kms_decrypted("LOGIC_APP_URL")
    method = "POST"
    headers = {"Content-Type": "application/json"}
    data = {
        "SystemAlertId": system_alert_id,
        "UserResult": 0 if status else 1,
    }
    if message is not None:
        data["UserMessage"] = message
    ret = {
        "type": "Logic App",
        "id": system_alert_id,
        "payload": data,
        "status": status
    }
    data = json.dumps(data).encode("utf-8")
    request = urllib.request.Request(
        url, data=data, method=method, headers=headers
    )
    with urllib.request.urlopen(request) as response:
        result = False
        ret["result"] = {
            "status": response.status,
            "reason": response.reason,
            "message": response.msg
        }
        if response.status == 200:
            result = True
            expires = response.getheader("Expires")
            if expires == "-1":
                ret["message"] = "Send Status(System Alert Id was Expired)"
            else:
                result = True
        else:
            ret["message"] = "Send Status({})".format(response.msg)
            ret["result"] = {
                "status": response.status,
                "reason": response.reason,
                "message": response.msg
            }
        print_json(ret)
        return result
예제 #8
0
def view_submission(event):
    """
    @brief      入力用Modal ViewからSubmitssion Callbackの受け取り
    @params[in] event       イベントペイロード
    @details    入力値を取得しprivate_metadataから呼出元メッセージを特定し
    @n          chat.update APIにて入力値を呼び出し元に反映します
    """
    view = event["view"]
    private_metadata = json.loads(view["private_metadata"])
    container = private_metadata["container"]
    message = private_metadata["message"]
    channel_id = container["channel_id"]
    blocks = message["blocks"]
    user = private_metadata["user"]
    action_value = private_metadata["action_value"]
    reason = view["state"]["values"]["reason_input"]["reason_text"]["value"]
    status = action_value["Status"]
    alert_id = action_value["SystemAlertId"]
    message_id = action_value["MessageId"]

    blocks[2] = {
        "type": "section",
        "block_id": "reason",
        "fields": [
            {"type": "mrkdwn", "text": "*応答*"},
            {"type": "mrkdwn", "text": "意図している"},
            {"type": "mrkdwn", "text": "*応答ユーザー*"},
            {"type": "mrkdwn", "text": user["username"]},
            {"type": "mrkdwn", "text": "*理由*"},
            {"type": "mrkdwn", "text": reason}
        ]
    }
    reason = "[{}]{}".format(user["username"], reason)
    result = set_status(alert_id, status, reason)
    if result:
        slack_api_token = kms_decrypted("SLACK_API_TOKEN")
        slack_chat = Slack.Chat(token=slack_api_token)
        post_args = {
            "channel": channel_id,
            "text": message["text"],
            "ts": message["ts"],
            "blocks": blocks,
        }
        print_json({
            "type": "Slack",
            "message": "Update Message",
            "metadata": post_args
        })
        slack_chat.update_message(**post_args)
        remove_message(message_id, alert_id)
예제 #9
0
def credential_setting():
    # Box用設定
    if "box" == upload_type:
        global box_file
        global box_folder
        logging.getLogger('boxsdk').setLevel(logging.CRITICAL)
        key_name = "/SlackUploadFileTransfer/Box"
        box_setting = lambda_tools.ssm_get_parameter(name=key_name)
        box_setting = json.loads(box_setting)
        settings = box_setting["boxAppSettings"]
        box_user = kms_decrypted("BOX_USER")
        box_folder = Box.Folder(
            client_id=settings["clientID"],
            client_secret=settings["clientSecret"],
            enterprise_id=box_setting["enterpriseID"],
            jwt_key_id=settings["appAuth"]["publicKeyID"],
            rsa_private_key_data=settings["appAuth"]["privateKey"]
        )
        box_folder.login(box_user)
        box_file = Box.File(
            client_id=settings["clientID"],
            client_secret=settings["clientSecret"],
            enterprise_id=box_setting["enterpriseID"],
            jwt_key_id=settings["appAuth"]["publicKeyID"],
            rsa_private_key_data=settings["appAuth"]["privateKey"]
        )
        box_file.login(box_user)
    # Google用設定
    if "google" == upload_type:
        global gdrive
        global gdrive_permission
        key_name = "/SlackUploadFileTransfer/GSuite"
        credential = lambda_tools.ssm_get_parameter(name=key_name)
        credential = json.loads(credential)
        gdrive = GSuite.Drive.Files(
            credential=credential,
            scopes=GSuite.Drive.SCOPES_MANAGE,
            delegate_user=credential["client_email"]
        )
        gdrive_permission = GSuite.Drive.Permissions(
            credential=credential,
            scopes=GSuite.Drive.SCOPES_MANAGE,
            delegate_user=credential["client_email"]
        )
예제 #10
0
def call_modal(event):
    """
    @brief      入力用Modal Viewの表示
    @params[in] event       イベントペイロード
    @details    メッセージ上のBlocksに表示されたボタンのaction_idが
    @n          answer_trueである場合に呼び出されます。
    @n          呼出元のBlocksのチャンネル情報とメッセージ情報を
    @n          private_metadataに格納しModal Viewを画面上に表示されます。
    """
    slack_api_token = kms_decrypted("SLACK_API_TOKEN")
    trigger_id = event["trigger_id"]
    action = event["actions"][0]
    action_value = action["value"]
    action_value = json.loads(action_value)
    data = json.dumps({
        "container": event["container"],
        "channel": event["channel"],
        "message": event["message"],
        "user": event["user"],
        "action_value": action_value
    })
    slack_views = Slack.Views(token=slack_api_token)
    view = {
        "type": "modal",
        "private_metadata": data,
        "callback_id": "modal_reason",
        "title": {"type": "plain_text", "text": "Azure Sentinel 通知"},
        "submit": {"type": "plain_text", "text": "Submit"},
        "close": {"type": "plain_text", "text": "Cancel"},
        "blocks": [{
            "type": "input",
            "block_id": "reason_input",
            "element": {
                "type": "plain_text_input", "multiline": True,
                "action_id": "reason_text"
            },
            "label": {"type": "plain_text", "text": "理由"}
        }]
    }
    slack_views.open(trigger_id, view)
예제 #11
0
def set_status(system_alert_id):
    """
    @brief      Logic Appにステータスを送信
    @params[in] system_alert_id     Azure SentinelのSystem Alert Id
    """
    url = kms_decrypted("LOGIC_APP_URL")
    method = "POST"
    headers = {"Content-Type": "application/json"}
    data = json.dumps({
        "SystemAlertId": system_alert_id,
    }).encode("utf-8")
    request = urllib.request.Request(url,
                                     data=data,
                                     method=method,
                                     headers=headers)
    with urllib.request.urlopen(request) as response:
        result = False
        ret = {
            "type": "Logic App",
            "id": system_alert_id,
        }
        if response.status == 200:
            expires = response.getheader("Expires")
            if expires == "-1":
                ret["message"] = "Send Status(System Alert Id was Expired)"
            else:
                ret["message"] = "Send Status({})".format(response.msg)
                result = True
        else:
            ret["message"] = "Send Status({})".format(response.msg)

        ret["result"] = {
            "status": response.status,
            "reason": response.reason,
            "message": response.msg
        }
    print_json(ret)
    return result
예제 #12
0
def main_function(events):
    slack_api_token = kms_decrypted("SLACK_API_TOKEN")
    slack_bot_token = kms_decrypted("SLACK_BOT_TOKEN")
    channel_id = kms_decrypted("SLACK_CHANNEL_ID")
    slack_chat = Slack.Chat(token=slack_api_token)
    for event in events:
        body = event.get("body", None)
        if body is None:
            continue
        id = set_ignore_queue(body)
        body = json.loads(body)
        username = body["Name"].replace('assumed-role/sso/', '')
        body["MessageId"] = id
        blocks = []
        blocks.append({
            "type":
            "section",
            "block_id":
            "alert",
            "text": {
                "type": "mrkdwn",
                "text": "@{}\nAzure Sentinel 警告通知".format(username)
            },
            "fields": [
                {
                    "type": "mrkdwn",
                    "text": "*アラート名*"
                },
                {
                    "type": "mrkdwn",
                    "text": body["AlertName"]
                },
                {
                    "type": "mrkdwn",
                    "text": "*アラート概要*"
                },
                {
                    "type": "mrkdwn",
                    "text": body["Description"]
                },
            ]
        })
        blocks.append({"type": "divider"})
        elements = []
        body["Status"] = True
        elements.append({
            "action_id": "answer_true",
            "type": "button",
            "text": {
                "type": "plain_text",
                "text": "意図している"
            },
            "value": json.dumps(body)
        })
        body["Status"] = False
        elements.append({
            "action_id": "answer_false",
            "type": "button",
            "text": {
                "type": "plain_text",
                "text": "心当たりがない"
            },
            "value": json.dumps(body)
        })
        blocks.append({
            "block_id": "answer",
            "type": "actions",
            "elements": elements
        })
        post_args = {
            "channel": channel_id,
            "text": "Azure Sentinel 警告通知",
            "blocks": blocks,
            "link_names": True,
            "mrkdwn": True
        }
        print_json({
            "type": "Slack",
            "message": "メッセージ送信",
            "channel-id": channel_id,
            "payload": post_args,
        })
        result = slack_chat.post_message(**post_args)
예제 #13
0
import objectpath
import Slack
import Box
import GSuite
import urllib.request
import logging
from urllib.parse import parse_qs
import lambda_tools
from lambda_tools import invoke
from lambda_tools import print_json
from lambda_tools import kms_decrypted
from lambda_tools import get_lambda_info
from lambda_tools import slack_verification


slack_token = kms_decrypted("SLACK_TOKEN")
slack_bot_token = kms_decrypted("SLACK_BOT_TOKEN")
slack_user = Slack.User(token=slack_bot_token)
slack_channel_ids = kms_decrypted("SLACK_CHANNEL_IDS", None)
if not (slack_channel_ids is None or slack_channel_ids == ""):
    slack_channel_ids = slack_channel_ids.split(",")

box_folder = None
box_file = None
gdrive = None
gdrive_permission = None
upload_type = kms_decrypted("UPLOAD_TYPE").lower()


def credential_setting():
    # Box用設定