【AWSやってみた】Line通知でRootUserのログインを確認

2023/07/05に公開

こんな方におすすめ!!

  • 意図しないルートユーザーの使用を検知したい

これをやればどうなる?

  • ルートユーザーの不正利用を確認できる

作成ポイントと得た知識

  • ルートユーザーのログインログはバージニア北部のCloudTrailにのみ記録される。
    ⇨ そのため、今回はCloudFormationをバージニア北部に展開する必要がある

使用するAWSサービス

  • AWS CloudFormationテンプレートで作成するリソース/数
    • AWS::Events::Rule/1
    • AWS::Lambda::Function/1
    • AWS::Logs::LogGroup/1
    • AWS::IAM::Role/1
  • 手動で作成するリソース/数
    • Lambdaレイヤー/1

前提条件

手順

  1. CloudFormationスタック作成
  2. Lambdaレイヤー作成し、一部のLambda関数に付与
  3. ルートユーザーでログインしてみて、通知が来れば完了

使用するリソース

CloudFormationテンプレート

入力パラメータ

  • (必須)LineAccessToken:取得したLineNotifyのトークン
  • (必須)StockLogDays:LogGroupのログ保管期間(day)
  • (必須)LambdaRuntime:pythonのバージョン
AWSTemplateFormatVersion: '2010-09-09'
Description: Finding Root Longin Activity

Parameters:
  LineAccessToken:
    Type: String
    Default: hoge
  StockLogDays:
    Type: Number
    Default: 7
  LambdaRuntime: 
    Type: String
    Default: python3.10

Resources:

  RootLoginEventBridge:
    Type: AWS::Events::Rule
    Properties: 
      EventBusName: default
      Name: !Sub "${AWS::StackName}-EventBrige"
      Description: "Finding Root Longin Activity"
      EventPattern: 
        detail-type:
          - "AWS Console Sign In via CloudTrail"
        detail:
          userIdentity:
            type:
              - "Root"
      State: ENABLED
      Targets: 
        - Arn: !GetAtt RootLoginLambda.Arn
          Id: "RootLoginLambda"

  RootLoginLambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${AWS::StackName}-Lambda"
      Role: !GetAtt LambdaIamRole.Arn
      Runtime: !Ref LambdaRuntime
      Timeout : 10
      Environment:
        Variables:
          LINE_ACCESS_TOKEN: !Ref LineAccessToken
      Handler: index.lambda_handler
      Code:
        ZipFile: !Sub |
          import os
          import requests

          LINE_ACCESS_TOKEN = os.environ["LINE_ACCESS_TOKEN"]

          def lambda_handler(event, context) -> None:

            url = "https://notify-api.line.me/api/notify"
            headers = {"Authorization": "Bearer %s" % LINE_ACCESS_TOKEN}
            data = {'message': f'\n 【WARNING】Finding Root Longin Activity'}

            try:
              response = requests.post(url, headers=headers, data=data)
            except requests.exceptions.RequestException as e:
              print(e)
            else:
              print(response.status_code)

  RootLoginLambdaAddPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref RootLoginLambda
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt RootLoginEventBridge.Arn

            

  RootLoginLambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties: 
      LogGroupName: !Sub "/aws/lambda/${AWS::StackName}-Lambda"
      RetentionInDays: !Ref StockLogDays

 
  LambdaIamRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-LambdaIamRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-LambdaPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "ce:GetCostAndUsage"
                Resource: "*"

Lambdaレイヤー

コマンド

$ mkdir python
$ pip install -t python requests "urllib3<2"
$ zip -r9 layer.zip python

詰まった箇所

エラー1:ローカルのPythonバージョンによるエラー

Lambdaのレイヤー作成するとき、
pip install -t python requests "urllib3<2"
を打った後に出た

ERROR:root:code for hash md5 was not found.
Traceback (most recent call last):
  File "/usr/local/Cellar/python@2/2.7.14_3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/hashlib.py", line 147, in <module>
    globals()[__func_name] = __get_hash(__func_name)
....

解決策

ローカルでエラー出たらローカル環境を改善すればいいのだが、ローカルをあまりいじりたくない場合は、Cloud9を立ち上げてレイヤー用のZipファイルを作成すればいいでしょう!(私はCloud9でやりました)

Discussion