Importing an AWS account into Guardrails
Overview
Guardrails can get access to an AWS Account by one of the following ways:
- Cross-Account IAM Role (Commercial Cloud)
- IAM Role and User Access Key Pair (AWS China and AWS GovCloud)
Supported AWS Partitions
There are three account partitions that AWS offers and Guardrails supports. Valid partition names are:
aws
- Public AWS partition (Commercial)aws-cn
- AWS Chinaaws-us-gov
- AWS GovCloud
Consider that Turbot Guardrails is hosted only in AWS commercial accounts. Therefore:
- We can import AWS commercial partition accounts directly by the IAM Role only.
- To import AWS China or AWS GovCloud accounts requires an IAM User Access key pair along with the IAM Role.
Prerequisites to import AWS Commercial Account
A few steps must be completed before an account can be imported into a Guardrails workspace:
- A cross-account IAM role in the managed account. Using AWS IAM Role Delegation allows you to grant access to Guardrails without sharing security credentials like passwords or other secrets.
- The
aws
mod installed. This mod holds the resource definition for an AWS Account. Additional mods may be desired. Remember that Mods enable Guardrails to discovery and manage for various AWS services. If the mod isn't installed for a particular service, Guardrails can't see those resources. Refer to the Recommended Starting Mods for more information.
What Permissions to Grant
What permissions you grant to the Guardrails IAM role will depend on your use case(s). Guardrails will use whichever role you specify and the permissions granted to it. If you instruct Guardrails to perform some action but do not provide sufficient permissions to perform it, Guardrails will get an "Access Denied" error. Identify then resolve these errors by either adjusting permissions on the Guardrails IAM role, or by adjusting your policies. Below are some common permission sets that customers use. Choose a permission set or construct one that conforms to your requirements.
Full Remediation
- If you wish to take advantage of every AWS integration offered by Guardrails,
attach the Amazon Managed AdministratorAccess Policy:
arn:aws:iam::aws:policy/AdministratorAccess
- If you wish to take advantage of every AWS integration offered by Guardrails,
attach the Amazon Managed AdministratorAccess Policy:
Mixed Remediation
- You may choose to remediate on a select set of services
- Start with permissions required to manage event handling. Attach the
AmazonSNSFullAccess, CloudWatchFullAccess, CloudWatchEventsFullAccess, and
ReadOnlyAccess Amazon Managed Policies:
arn:aws:iam::aws:policy/ReadOnlyAccess
arn:aws:iam::aws:policy/AmazonSNSFullAccess
arn:aws:iam::aws:policy/CloudWatchEventsFullAccess
- Add additional IAM policies as desired for the target AWS service. For
example, one could add:
arn:aws:iam::aws:policy/AmazonEC2FullAccess
arn:aws:iam::aws:policy/AmazonRDSFullAccess
- Or any other custom policy that meets your requirements.
- When crafting custom policies, be aware of the AWS IAM service quotas on policy length
- Start with permissions required to manage event handling. Attach the
AmazonSNSFullAccess, CloudWatchFullAccess, CloudWatchEventsFullAccess, and
ReadOnlyAccess Amazon Managed Policies:
- You may choose to remediate on a select set of services
Read Only + Event Handlers
To get ReadOnly Access + Event Handlers, attach the
AmazonSNSFullAccess
,CloudWatchEventsFullAccess
, andReadOnlyAccess
Amazon Managed Policies:arn:aws:iam::aws:policy/ReadOnlyAccess
arn:aws:iam::aws:policy/AmazonSNSFullAccess
arn:aws:iam::aws:policy/CloudWatchEventsFullAccess
Or, to strictly limit Guardrails write access to only event handling resources, build a role with the following permissions. A convenient CloudFormation template can be found below.
- Attach the
ReadOnlyAccess
Amazon Managed Policies:arn:aws:iam::aws:policy/ReadOnlyAccess
- Create a custom policy that allows write-access to only Turbot event
handling infrastructure.
- CloudWatch Events matching:
arn:aws:events:*:${AccountId}:rule/turbot_aws_api_events*
- SNS topics and subscriptions matching:
arn:aws:sns:*:${AccountId}:turbot_aws_api_handler
arn:aws:sns:*:${AccountId}:turbot_aws_api_handler:*
- Note that the default resource prefix is
turbot_
. If changes are made to the "Event Rule Name Prefix" or "SNS Topic Name Prefix" policies, then the IAM policy must be updated to match. This is an uncommon requirement. See policy details below. - Adjust the partition from
aws
toaws-us-gov
andaws-cn
as required.
- CloudWatch Events matching:
- Attach the
Budget Permissions
- Grant permissions to allow the Budget control to get the cost usage and
forecast data:
ce:getCostForecast
ce:GetCostAndUsage
- Grant permissions to allow the Budget control to get the cost usage and
forecast data:
Cross Account Trust
The role must grant cross-account access for the Turbot Guardrails master AWS account to assume into your AWS account.
- Turbot Cloud customers, you must allow the Turbot SaaS US AWS Account ID:
287590803701
- Turbot Cloud EU customers, you must allow the Turbot SaaS EU AWS Account ID:
255798382450
- Turbot Guardrails Enterprise customers, enter the AWS Account ID of the AWS Account where you have installed the Turbot Guardrails Enterprise stacks.
External IDs
It is required that you set an External ID. There are two sources for the External ID:
- Guardrails will suggest an auto-generated External ID that is unique to your
Turbot Workspace ( e.g.
turbot:123456789012345:foo
). This autogenerated external ID must be used when "External ID Protection" is enabled. You can use the generated ID for your IAM role to prevent the confused deputy problem. For more information, check out our FAQ titled What is Guardrails AWS IAM External ID protection? - You can set the external ID to any valid external ID you prefer.
Additional External ID Considerations
- When you have External ID Protection enabled, (e.g. set to
Protected
), it will be required to use the protected format for the Workspace. - Make sure you leave Require MFA disabled on the role.
- If you are setting your own external ID, be sure it follows AWS character limits.
Role Name
Give the role a meaningful name such as turbot-service-readonly
(read only) or
turbot-service-superuser
(for full access), as well as an apt description.
Creating the Role
Using CloudFormation
To simplify setup, you can use the Turbot-provided CloudFormation template. For
EU customers, use 255798382450
.
Full AdministratorAccess
---AWSTemplateFormatVersion: "2010-09-09"Parameters: RoleName: Type: String Default: turbot-service-superuser Description: The role that Turbot uses to connect to this account
TurbotAccountId: Type: String Default: 287590803701 Description: | The AWS Account ID where Turbot is installed. This will be added to the trust policy of the role to allow access for Turbot
TurbotExternalId: Type: String NoEcho: True MinLength: 1 Description: | The AWS External ID to add to the trust policy of the Turbot role
Resources: TurbotSuperuserRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${TurbotAccountId}:root Action: - sts:AssumeRole Condition: StringEquals: sts:ExternalId: !Ref TurbotExternalId Path: /turbot/core/ ManagedPolicyArns: - "arn:aws:iam::aws:policy/AdministratorAccess" RoleName: !Ref RoleName
ReadOnly + Event Handlers
This represents the minimum privileges required for Guardrails to discover all AWS resources and configure event handlers.
AWSTemplateFormatVersion: 2010-09-09Parameters: RoleName: Type: String Default: turbot-service-readonly Description: The role that Turbot uses to connect to this account PolicyName: Type: String Default: turbot-readonly-events-sns Description: The name for the policy for SNS and Events write access. TurbotAccountId: Type: String Default: 287590803701 Description: > The AWS Account ID where Turbot is installed. This will be added to the trust policy of the role to allow access for Turbot Defaults to the Turbot US SaaS account TurbotExternalId: Type: String NoEcho: true MinLength: 1 Description: | The AWS External ID to add to the trust policy of the Turbot roleResources: TurbotReadOnlyRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: !Sub "arn:aws:iam::${TurbotAccountId}:root" Action: - "sts:AssumeRole" Condition: StringEquals: "sts:ExternalId": !Ref TurbotExternalId Path: /turbot/core/ ManagedPolicyArns: - "arn:aws:iam::aws:policy/ReadOnlyAccess" RoleName: !Ref RoleName Metadata: "AWS::CloudFormation::Designer": id: e66f3008-2c13-4544-bf72-2a69e5e5a4a9 TurbotSNSEventsPolicy: Type: "AWS::IAM::Policy" Properties: PolicyName: !Ref PolicyName Roles: - !Ref RoleName PolicyDocument: Version: 2012-10-17 Statement: - Sid: TurbotEvents Effect: Allow Action: - "events:PutEvents" - "events:EnableRule" - "events:DisableRule" - "events:PutRule" - "events:DeleteRule" - "events:PutTargets" - "events:RemoveTargets" - "events:TagResource" - "events:UntagResource" Resource: - !Sub "arn:aws:events:*:${AWS::AccountId}:rule/turbot_aws_api_events*" - Sid: TurbotSNS Effect: Allow Action: - "sns:TagResource" - "sns:UntagResource" - "sns:CreateTopic" - "sns:DeleteTopic" - "sns:SetTopicAttributes" - "sns:Publish" - "sns:Subscribe" - "sns:ConfirmSubscription" - "sns:AddPermission" - "sns:RemovePermission" - "sns:Unsubscribe" Resource: - !Sub "arn:aws:sns:*:${AWS::AccountId}:turbot_aws_api_handler" - !Sub "arn:aws:sns:*:${AWS::AccountId}:turbot_aws_api_handler:*" DependsOn: - TurbotReadOnlyRole
Using the AWS console
If you do not want to create the role with Cloudformation, you can create it manually:
Login to AWS with a privileged account and navigate to IAM > Roles in the AWS IAM Console.
Click the Create Role button.
a. Select Another AWS account for the type of trusted entity.
b. For Account ID, enter 287590803701 (The Turbot Guardrails SaaS AWS account ID) if you are a SaaS customer. This means that you are granting Guardrails access to your AWS account. If you are a Turbot GuardrailsEnterprise customer, enter the AWS Account ID where Turbot Guardrails was deployed.
c. Check Require External ID and enter an External ID. You can choose any valid external ID. You will need this ID later, when you import the account into your Guardrails workspace. Make sure you leave Require MFA disabled. Click Next: Permissions.
Select the policies to be attached to the role:
- To take advantage of every AWS integration offered by Turbot Guardrails(recommended),
attach the Amazon Managed AdministratorAccess Policy:
arn:aws:iam::aws:policy/AdministratorAccess
- To enable readonly access for Guardrails with event handler support:
- Attach the AmazonSNSFullAccess, CloudWatchFullAccess,
CloudWatchEventsFullAccess, and ReadOnlyAccess Amazon Managed Policies:
arn:aws:iam::aws:policy/ReadOnlyAccess
arn:aws:iam::aws:policy/AmazonSNSFullAccess
arn:aws:iam::aws:policy/CloudWatchEventsFullAccess
- Create a policy to grant permissions to get the cost usage and forecast
data, and attach it to the role:
ce:getCostForecast
ce:GetCostAndUsage
- Attach the AmazonSNSFullAccess, CloudWatchFullAccess,
CloudWatchEventsFullAccess, and ReadOnlyAccess Amazon Managed Policies:
- To take advantage of every AWS integration offered by Turbot Guardrails(recommended),
attach the Amazon Managed AdministratorAccess Policy:
Click Next: Tags.
If desired, add tags, then click Next: Review.
Give the role a meaningful name such as
turbot-readonly
(read only) orturbot-superuser
(for full access), as well as an apt description. Click Create Role.
Install desired mods
The aws
mod is required to import AWS accounts into a Guardrails workspace. It must be
installed before account imports can start. Ensure it is installed and the
Mod installed
control is in the green ok
state. The aws-iam
mod is highly
recommended.
Installation of additional mods will depend on the organization's control objectives. If the organization doesn't have any control objectives on a given service, don't install that service's mod. Check out our Mods recommendation page for more info on suggested mods to install.
Recommended Mods (in order of installation):
Importing an AWS Commercial account into a Guardrails folder
Importing accounts into Folders offers increased flexibility and easier management over importing directly under the Turbot level. Define a Folder hierarchy prior to import.
Importing the account via the Guardrails Console
At the main Guardrails console after logging in with
Turbot/Admin
permissions, click the purple IMPORT card in the top right.Select AWS Account on the left.
Use the Parent Resource dropdown menu to select the folder where the AWS account will be imported.
Enter the Account ID in the field.
Copy the IAM Role ARN that was created earlier and paste into the field. The IAM role must be in the account to be imported. Do the same with the IAM Role External ID.
Click import!
CMDB and Discovery controls are enabled by default and Guardrails will begin discovering the resources in your AWS account. Resources will start appearing right away, and resource discovery will continue to run in the background.
Importing the account via Terraform
#### Create the AWS > Account resource in Turbotresource "turbot_resource" "account_resource" { parent = id-of-parent-folder type = "tmod:@turbot/aws#/resource/types/account" metadata = jsonencode({ "aws" : { "accountId" : "your aws account id", // highlight-line "partition" : "aws" } }) data = jsonencode({ "Id" : "your aws account id" //highlight-line })}
#### Set the credentials (Role, external id) for the account via Turbot policies# AWS > Account > Turbot IAM Role > External IDresource "turbot_policy_setting" "turbotIamRoleExternalId" { resource = turbot_resource.account_resource.id type = "tmod:@turbot/aws#/policy/types/turbotIamRoleExternalId" value = "external id for your turbot role" //highlight-line}
# AWS > Account > Turbot IAM Roleresource "turbot_policy_setting" "turbotIamRole" { resource = turbot_resource.account_resource.id type = "tmod:@turbot/aws#/policy/types/turbotIamRole" value = "arn of your turbot role" //highlight-line}
Post Import Validation
There are a few things to check after importing an account. These criteria should be used to determine when an account is considered fully imported and "Open for Business".
Criteria for a Completed Import
- Authentication Policy Check: Verify that the AWS > Account > Turbot IAM Role policy and AWS > Account > Turbot IAM Role > External ID policy are present on the account and have the proper values.
- Permissions Check: Check that the
AWS > Account > CMDB
control has run and is in anok
state. This is the easiest place to smoke test if the Turbot IAM Role, External ID policies and assigned AWS permissions are correct. - Policy Values in TBD: Ensure that all policy values for the new account
are in
ok
orskipped
. Anyerrors
,invalid
ortbd
policy values must be resolved before considering this account properly imported.- Policy values in
tbd
state should all clear on their own. However, some may get stuck and require rerunning. - It is essential to clear policy values in
tbd
before attempting to clear controls intbd
. Clearingtbd
policies will trigger the controls that depend on them to run. Rerunning controls before their policy values are out oftbd
will waste control runs.
- Policy values in
- Controls in TBD: Ensure that all controls are in
ok
,alarm
orskipped
. Any controls intbd
,error
orinvalid
state must be resolved.- It's common to see thousands of controls in
tbd
shortly after account import. Controls intbd
state will typically all clear on their own. However, some may get stuck and require rerunning. - The
Discovery
andCMDB
controls are an essential subset of all controls for this new account.
- It's common to see thousands of controls in
- Event Handlers: If Event Handling has been enabled, ensure that the
AWS > Turbot > Event Handler
controls are in anok
state. For extra assurance, verify that theConfigured
controls for Events Rules, Event Targets, SNS Topics and SNS subscriptions are in anok
state too. If not using Event Handlers, ensure that theAWS > Turbot > Event Poller
controls are inok
and have run in the lsat minute or two.
Automation Reference
A collection of GraphQL, Terraform and Python to assist developers with integrating Guardrails into account onboarding pipelines.
- Account Import GraphQL: account_import graphql
- Account Import Terraform: account_import Terraform
- Policies Stuck in TBD: Use the
run_policies
script with this filter to rerun policy values in
tbd
:--filter "resourceId:'<ARNofAccount>' state:tbd"
- Controls Stuck in TBD: Use the
run_controls
or
run_controls_batches
scripts with this filter to rerun controls in
tbd
:--filter "resourceId:'<ARNofAccount>' state:tbd"
- Event Handler Controls not in OK: Use the Guardrails Samples
run_controls_batches
script with this filter:
--filter "resourceId:'<ARNofAccount>' controlTypeId:'tmod:@turbot/aws#/control/types/eventHandlers','tmod:@turbot/aws-sns#/control/types/topicConfigured','tmod:@turbot/aws-sns#/control/types/subscriptionConfigured','tmod:@turbot/aws-event#s/control/types/targetConfigured','tmod:@turbot/aws-events#/control/types/ruleConfigured' state:tbd,error,invalid"
Note that Terraform cannot verify anything beyond the existence and configuration of the Account resource in Turbot, along with the Turbot IAM role and External ID policies. Fully automated, lights-out account import requires additional verification steps after import.
GraphQL
Verify the value of the Turbot IAM role and External ID policy settings
There should be two items
returned: one for the Turbot IAM role setting and
one for the External ID setting. This query can be run immediately after the
account resource has been created.
query AccountAuthPolicySettings($filter: [String!]) { policySettings(filter: $filter) { items { type { uri } value } }}
variables:
{ "filter": "resourceId:'arn:aws:::<ACCOUNTID>' policyTypeId:'tmod:@turbot/aws#/policy/types/turbotIamRole','tmod:@turbot/aws#/policy/types/turbotIamRoleExternalId'"}
Account CMDB is in OK
This query can be run 30 seconds to a minute after account import. If the
Account CMDB control doesn't exist yet, Turbot will return zero items
.
query AccountCMDBState($filter: [String!]) { controls(filter: $filter) { items { state type { uri } } }}
variables:
{ "filter": "controlTypeId:'tmod:@turbot/aws#/control/types/accountCmdb' resourceId:'arn:aws:::<ACCOUNTID>'"}
Count of controls and policies in TBD, Error or Invalid
When the count for controls and policy values goes to zero, the account import is complete. Wait several minutes before running this for the first time. If polling with this query, 30 second or 1 minute intervals work well.
query Resources($filter: [String!]) { tbd_controls: controls(filter: $filter) { metadata { stats { total } } } tbd_policies: policyValues(filter: $filter) { metadata { stats { total } } }}
variables:
{ "filter": "resourceId:'arn:aws:::<ACCOUNTID>' state:tbd,error,invalid"}
Count of Event Handler and Configured controls in TBD, Error or Invalid
When the count goes to zero, all event handler resources have been successfully deployed. Wait several minutes before running this for the first time. If polling with this query, 30 second or 1 minute intervals work well.
# When the count for all data goes to zero, the account import is complete.query Resources($filter: [String!]) { event_handlers: controls(filter: $filter) { metadata { stats { total } } }}
variables:
{ "filter": "resourceId:'arn:aws:::<ACCOUNTID>' controlTypeId:'tmod:@turbot/aws#/control/types/eventHandlers','tmod:@turbot/aws-sns#/control/types/topicConfigured','tmod:@turbot/aws-sns#/control/types/subscriptionConfigured','tmod:@turbot/aws-event#s/control/types/targetConfigured','tmod:@turbot/aws-events#/control/types/ruleConfigured' state:tbd,error,invalid"}