Automating AWS Guard Duty Enrollment

Dane Fetterman
Sep 13 · 5 min read

Large enterprises with decentralized IT often contend with AWS account sprawl with InfoSec teams having limited or no insight into many of the accounts. In order to aggregate data across multiple accounts, Amazon released AWS GuardDuty.

Amazon describes GuardDuty as “a threat detection service that continuously monitors for malicious activity and unauthorized behavior to protect your AWS accounts and workloads. GuardDuty can be enabled with no software or hardware to deploy or maintain.”

Unfortunately, AWS doesn’t offer a feature (as of September 2019) to automatically enable GuardDuty on a member account and associate it with a master account.

As a workaround to this, I wrote GuardDuty Signup, a handful of easily deployed python scripts to enroll a member account in AWS Guard Duty on a master account. The scripts run as Lambda functions, kicked off by a Step Function that lives behind API Gateway. So, with a single API command, you can enroll a new member AWS account into Guard Duty on a master account.

I expected the GuardDuty enrollment to be very complicated, however, it’s only the standard level of AWS complicated.

To write GuardDuty Signup, I started by reading through Amazon’s documentation on how enrollment is supposed to work. I found Managing AWS Accounts in Amazon GuardDuty to be the most helpful for understanding what the process is.

Once I had an understanding of the enrollment process, I took a look at the GuardDuty Boto documentation to see what I had to work with in terms of the Python SDK. I mapped out each step of the enrollment process to an available method:

Process Sketch

This is the first POC project where I’ve used Amazon Step Functions. The Step Functions kick off standard Lambda Functions based on the status of the previous step. I used step functions because I expected there to be a delay between each step and I’m cost-sensitive to long-running Lambda functions. In hindsight, there wasn’t a delay so this could have been one monolithic Lambda function.

The enrollment process that I had previously mapped out looks like the following diagram once you convert it into a Step Function:

AWS Generated Step Function Diagram

I used Serverless Framework to simplify the deploy and create all of the necessary resources in AWS with a single command. This is tested with Serverless Framework Core: 1.51.0, Plugin: 1.3.11, SDK: 2.1.0.

The resources are defined in a serverless.yml file:

service: guarddutysignup 
stage: ${opt:stage, self:provider.stage}
memberRoleName: CrossAccountManageGuardDutyRole #The name of the role that will be assumed in member accounts
name: aws
runtime: python3.6
stage: dev #default stage
env: ${self:custom.stage}
memberRoleName: ${self:custom.memberRoleName}
MasterId: Ref: AWS::AccountId region: us-east-1
.....(MORE BELOW)....

The resources that are created by the Serverless Framework and how they relate to each other can be seen in the following architecture diagram:

GuardDuty Signup Architecture Diagram, Dane Fetterman Loves Diagrams


With Serverless Framework installed, AWS CLI configured and using credentials for the master account you can deploy from a workstation using the following command:

serverless deploy --stage dev

This will create all of the resources shown in the above diagram on your AWS master account necessary for GuardDuty Signup.


Once you deploy the resources, you’ll be provided with some service information.

Within service information, it’s important to make note of the API key and the endpoint:

api keys:
GET -{MasterDetectorId}/MemberId/{MemberId}/Email/{Email}

MasterDetectorId — The Guard Duty DetectorId on your Master Account
MemberId — The AWS account number of the member account
Email — The E-mail address associated with the AWS account number of the member account.

If you were to hit the API from a command line, it would look something like this:


Super Important!

Before you can manipulate a member account, the member account needs to have a cross-account role configured. An example for configuring this is provided in the git repo. It’s not something that I’m focussing on because in my use case, I already have the ability to create cross-account roles in accounts with limited permissions.

Some Thoughts for Expanding on This

By creating an API for enrolling in GuardDuty, you could build a UI to permit self-service enrollment.

I’m ready to see the code and get started:

To get started, head on over to the Github repo at

Keep in mind that this is a POC, some of the Python scripts handle errors well, other don’t, and some of it is just ugly but it met the technical requirements, time requirements, and it works. Feel free to submit pull requests.

About: Dane Fetterman is an IT Cloud Architect in Philadelphia. He’s a fan of DevOps, Philadelphia, his family, two dogs, and two cats.

Follow us on Twitter 🐦 and Facebook 👥 and join our Facebook Group 💬.

To join our community Slack 🗣️ and read our weekly Faun topics 🗞️, click here⬇

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇


The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts

Dane Fetterman

Written by

Dane Fetterman is an IT Cloud Architect based out of Philadelphia.



The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade