{
 "Conditions": {
  "CheckForUsEast1": {
   "Fn::Equals": [
    {
     "Ref": "AWS::Region"
    },
    "us-east-1"
   ]
  }
 },
 "Description": "DoiT RootGuard Stackset: This template creates the necessary client side parts to capture root user related events.",
 "Metadata": {
  "LastUpdated": "01/04/2025 11:38:37",
  "UpdatedBy": "jens@doit.com",
  "Version": "2b3663c2afcca97a11bad782ee89c9bc929f9d8c"
 },
 "Parameters": {
  "apiToken": {
   "Description": "The API token used to access DoiT rootguard API.",
   "Type": "String"
  },
  "endpoint": {
   "Default": "https://api.rootguard.doit.com/v1/*",
   "Description": "The API endpoint used to access DoiT rootguard API.",
   "Type": "String"
  }
 },
 "Resources": {
  "DoiTRootGuardAPI": {
   "Condition": "CheckForUsEast1",
   "Properties": {
    "ConnectionArn": {
     "Fn::GetAtt": [
      "DoiTRootGuardConnection",
      "Arn"
     ]
    },
    "Description": "Calling DoiT rootguard with API key x-api-key",
    "HttpMethod": "POST",
    "InvocationEndpoint": {
     "Ref": "endpoint"
    }
   },
   "Type": "AWS::Events::ApiDestination"
  },
  "DoiTRootGuardConnection": {
   "Properties": {
    "AuthParameters": {
     "ApiKeyAuthParameters": {
      "ApiKeyName": "x-api-key",
      "ApiKeyValue": {
       "Ref": "apiToken"
      }
     }
    },
    "AuthorizationType": "API_KEY",
    "Description": "Connection used to connect to Doit rootguard"
   },
   "Type": "AWS::Events::Connection"
  },
  "DoiTRootGuardEventSchedulerRole": {
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": [
        "sts:AssumeRole"
       ],
       "Condition": {
        "StringEquals": {
         "aws:SourceAccount": {
          "Ref": "AWS::AccountId"
         }
        }
       },
       "Effect": "Allow",
       "Principal": {
        "Service": [
         "scheduler.amazonaws.com"
        ]
       }
      }
     ],
     "Version": "2012-10-17"
    },
    "Path": "/",
    "Policies": [
     {
      "PolicyDocument": {
       "Statement": [
        {
         "Action": [
          "lambda:InvokeFunction"
         ],
         "Effect": "Allow",
         "Resource": [
          {
           "Fn::GetAtt": [
            "DoiTRootGuardHealthcheckLambda",
            "Arn"
           ]
          },
          {
           "Fn::Join": [
            ":",
            [
             {
              "Fn::GetAtt": [
               "DoiTRootGuardHealthcheckLambda",
               "Arn"
              ]
             },
             "*"
            ]
           ]
          }
         ]
        }
       ],
       "Version": "2012-10-17"
      },
      "PolicyName": "DoiT-RootGuard-LambdaInvoke"
     }
    ],
    "RoleName": "DoiT-RootGuard-Event-Scheduler"
   },
   "Type": "AWS::IAM::Role"
  },
  "DoiTRootGuardEventsRole": {
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": [
        "sts:AssumeRole"
       ],
       "Effect": "Allow",
       "Principal": {
        "Service": [
         "events.amazonaws.com"
        ]
       }
      }
     ],
     "Version": "2012-10-17"
    },
    "Path": "/",
    "Policies": [
     {
      "PolicyDocument": {
       "Statement": [
        {
         "Action": [
          "events:InvokeApiDestination"
         ],
         "Effect": "Allow",
         "Resource": {
          "Fn::GetAtt": [
           "DoiTRootGuardAPI",
           "Arn"
          ]
         }
        }
       ],
       "Version": "2012-10-17"
      },
      "PolicyName": "DoiT-RootGuard-ApiInvoke"
     }
    ],
    "RoleName": "DoiT-RootGuard-Events"
   },
   "Type": "AWS::IAM::Role"
  },
  "DoiTRootGuardEventsRule": {
   "Properties": {
    "Description": "Watch for events created by root user",
    "EventPattern": {
     "detail": {
      "$or": [
       {
        "userIdentity": {
         "type": [
          "Root"
         ]
        }
       },
       {
        "eventName": [
         "PutContactInformation",
         "DeleteAlternateContact",
         "PutAlternateContact"
        ],
        "eventSource": [
         "account.amazonaws.com"
        ]
       },
       {
        "eventName": [
         "SetContactAddress",
         "SetDefaultPaymentMethod",
         "SetAdditionalContacts",
         "SetAccountPreferences",
         "AWSPaymentPortalService.ValidatePaymentInstrumentOperation"
        ],
        "eventSource": [
         "billingconsole.amazonaws.com"
        ]
       },
       {
        "eventName": [
         "CreatePaymentInstrument"
        ],
        "eventSource": [
         "aws-payment-encryption.amazonaws.com"
        ]
       },
       {
        "eventName": [
         "Preferences_CreatePaymentProfile",
         "Preferences_UpdatePaymentProfile",
         "Instruments_Create",
         "Instruments_Update"
        ],
        "eventSource": [
         "payments.amazonaws.com"
        ]
       },
       {
        "eventName": [
         "DeleteTaxRegistration"
        ],
        "eventSource": [
         "tax.amazonaws.com"
        ]
       },
       {
        "eventName": [
         "CreateCustomerCase",
         "PreviewTaxRegistrationChange"
        ],
        "eventSource": [
         "taxconsole.amazonaws.com"
        ]
       }
      ]
     },
     "detail-type": [
      "AWS API Call via CloudTrail",
      "AWS Console Sign In via CloudTrail",
      "AWS Console Action via CloudTrail"
     ]
    },
    "Name": "DoiT-RootGuard-EventsRule",
    "State": "ENABLED",
    "Targets": [
     {
      "Arn": {
       "Fn::GetAtt": [
        "DoiTRootGuardAPI",
        "Arn"
       ]
      },
      "HttpParameters": {
       "PathParameterValues": [
        "events"
       ]
      },
      "Id": "DoitRootGuardEventsTarget",
      "RoleArn": {
       "Fn::GetAtt": [
        "DoiTRootGuardEventsRole",
        "Arn"
       ]
      }
     }
    ]
   },
   "Type": "AWS::Events::Rule"
  },
  "DoiTRootGuardHealthcheckLambda": {
   "Properties": {
    "Architectures": [
     "arm64"
    ],
    "Code": {
     "ZipFile": {
      "Fn::Join": [
       "",
       [
        "import json\n",
        "import boto3\n",
        "from datetime import datetime\n",
        "\n",
        "def checkcloudtrail():\n",
        "    client= boto3.client('cloudtrail')\n",
        "    paginator = client.get_paginator('list_trails')\n",
        "    response = paginator.paginate().build_full_result()\n",
        "    trail_status = 'inactive'\n",
        "    for trail in response['Trails']:\n",
        "        response = client.get_trail_status(Name=trail['TrailARN'])\n",
        "        if response['IsLogging']:\n",
        "            trail_status = 'active'\n",
        "    return trail_status\n",
        "\n",
        "def lambda_handler(event, context):\n",
        "    account_id = boto3.client('sts').get_caller_identity().get('Account')\n",
        "    trail_status = checkcloudtrail()\n",
        "    event = {\n",
        "                'Time': datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n",
        "                'Source': 'doit.rootguard',\n",
        "                'DetailType': 'DoiT RootGuard Healthcheck',\n",
        "                'Detail': json.dumps({\n",
        "                    'EventName': 'Healthcheck',\n",
        "                    'EventSource': 'rootguard.doit.com',\n",
        "                    'CloudtrailStatus': trail_status,\n",
        "                    'AccountId': account_id\n",
        "                }),\n",
        "            }\n",
        "    print(\"Event: \", event)\n",
        "    response = boto3.client('events').put_events(\n",
        "        Entries=[ event ])\n",
        "    print(\"Response: \", response)\n"
       ]
      ]
     }
    },
    "Description": "DoiT Healthcheck lambda is used to watch Cloudtrail status.",
    "FunctionName": "DoiT-Rootguard-Healthcheck",
    "Handler": "index.lambda_handler",
    "LoggingConfig": {
     "LogGroup": "/DoiT/lambda/DoiT-Rootguard-Healthcheck"
    },
    "MemorySize": 512,
    "Role": {
     "Fn::GetAtt": [
      "DoiTRootGuardHealthcheckLambdaExecutionRole",
      "Arn"
     ]
    },
    "Runtime": "python3.13"
   },
   "Type": "AWS::Lambda::Function"
  },
  "DoiTRootGuardHealthcheckLambdaExecutionRole": {
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": [
        "sts:AssumeRole"
       ],
       "Effect": "Allow",
       "Principal": {
        "Service": [
         "lambda.amazonaws.com"
        ]
       }
      }
     ],
     "Version": "2012-10-17"
    },
    "Path": "/",
    "Policies": [
     {
      "PolicyDocument": {
       "Statement": [
        {
         "Action": "logs:CreateLogGroup",
         "Effect": "Allow",
         "Resource": {
          "Fn::Join": [
           ":",
           [
            "arn",
            "aws",
            "logs",
            {
             "Ref": "AWS::Region"
            },
            {
             "Ref": "AWS::AccountId"
            },
            "*"
           ]
          ]
         }
        },
        {
         "Action": [
          "logs:CreateLogStream",
          "logs:PutLogEvents"
         ],
         "Effect": "Allow",
         "Resource": [
          {
           "Fn::Join": [
            ":",
            [
             "arn",
             "aws",
             "logs",
             {
              "Ref": "AWS::Region"
             },
             {
              "Ref": "AWS::AccountId"
             },
             "log-group",
             "/DoiT/lambda/DoiT-Rootguard-Healthcheck",
             "*"
            ]
           ]
          }
         ]
        },
        {
         "Action": [
          "cloudtrail:ListTrails",
          "cloudtrail:GetTrailStatus"
         ],
         "Effect": "Allow",
         "Resource": "*"
        },
        {
         "Action": "events:PutEvents",
         "Effect": "Allow",
         "Resource": [
          {
           "Fn::Join": [
            ":",
            [
             "arn",
             "aws",
             "events",
             {
              "Ref": "AWS::Region"
             },
             {
              "Ref": "AWS::AccountId"
             },
             "event-bus/default"
            ]
           ]
          }
         ]
        }
       ],
       "Version": "2012-10-17"
      },
      "PolicyName": "DoiT-Healthcheck"
     }
    ],
    "RoleName": "DoiT-RootGuard-Healthcheck-LambdaExecution"
   },
   "Type": "AWS::IAM::Role"
  },
  "DoiTRootGuardHealthcheckLambdaLoggroup": {
   "Properties": {
    "LogGroupName": "/DoiT/lambda/DoiT-Rootguard-Healthcheck",
    "RetentionInDays": 30
   },
   "Type": "AWS::Logs::LogGroup"
  },
  "DoiTRootGuardHealthcheckSchedule": {
   "Properties": {
    "FlexibleTimeWindow": {
     "MaximumWindowInMinutes": "30",
     "Mode": "FLEXIBLE"
    },
    "Name": "DoiT-RootGuard-Healthcheck",
    "ScheduleExpression": "rate(6 hours)",
    "Target": {
     "Arn": {
      "Fn::GetAtt": [
       "DoiTRootGuardHealthcheckLambda",
       "Arn"
      ]
     },
     "RoleArn": {
      "Fn::GetAtt": [
       "DoiTRootGuardEventSchedulerRole",
       "Arn"
      ]
     }
    }
   },
   "Type": "AWS::Scheduler::Schedule"
  },
  "DoiTRootGuardMonitoringRule": {
   "Properties": {
    "Description": "Watch for events created by DoiT monitoring",
    "EventPattern": {
     "detail": {
      "EventName": [
       "Healthcheck"
      ],
      "EventSource": [
       "rootguard.doit.com"
      ]
     },
     "detail-type": [
      "DoiT RootGuard Healthcheck"
     ]
    },
    "Name": "DoiT-RootGuard-MonitoringRule",
    "State": "ENABLED",
    "Targets": [
     {
      "Arn": {
       "Fn::GetAtt": [
        "DoiTRootGuardAPI",
        "Arn"
       ]
      },
      "HttpParameters": {
       "PathParameterValues": [
        "monitoring"
       ]
      },
      "Id": "DoitRootGuardMonitoringTarget",
      "RoleArn": {
       "Fn::GetAtt": [
        "DoiTRootGuardEventsRole",
        "Arn"
       ]
      }
     }
    ]
   },
   "Type": "AWS::Events::Rule"
  }
 }
}
