Turbot custom resources in CloudFormation
Turbot Guardrails Resources can be managed as Custom Resources in CloudFormation. Managing Turbot Guardrails through CloudFormation supports a wide range of scenarios like: managing Turbot Guardrails Resource Groups and Policies, managing Turbot Guardrails Policies (particularly exceptions) in code with the AWS Resources, and automatic cleanup of Turbot-modified resources to prevent CloudFormation conflicts.
Overview
Turbot Guardrails Resources can be managed as Custom Resources in CloudFormation.
Managing Turbot Guardrails through CloudFormation supports a wide range of scenarios like:
- Managing Turbot Guardrails Resource Groups and Policies.
- Managing Turbot Guardrails Policies (particularly exceptions) in code with the AWS Resources.
- Automatic cleanup of Turbot-modified resources to prevent CloudFormation conflicts.
Turbot Guardrails Custom Resources use Turbot APIs
Internally, Turbot Guardrails Custom Resources are implemented as API calls to Turbot Guardrails. All aspects of authentication, data validation and audit trail logging are identical.
Authentication
Turbot Guardrails Custom Resources are implemented as API calls to Turbot Guardrails. Each Turbot Guardrails Resource must specify a Turbot Guardrails Access Key and Secret Key pair for authentication.
The basic format is:
MyTurbotResource: Type: "Custom::Turbot{ResourceType}" Properties: Turbot: AccessKey: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx SecretKey: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
Typically this will be implemented through Parameters:
MyTurbotResource: Type: "Custom::Turbot{ResourceType}" Properties: Turbot: AccessKey: !Ref TurbotAccessKey SecretKey: !Ref TurbotSecretKey
Note: CloudFormation does not pass any information to the Custom Resource about the AWS identity running the CloudFormation stack. As such, the only identity information available to Turbot Guardrails is provided by the authentication information passed in the Custom Resource definition.
Resource Data, API Endpoints and Field Name Format
The Custom Resource defines the data that will be used for Turbot Guardrails API calls related to the resource type. For example, a TurbotPolicy
resource will work with the /api/{apiVersion}/resources/{resourceUrn}/policies
endpoints for CREATE, GET, PATCH and DELETE.
Generally, valid resource data is defined by the CREATE endpoint - please refer to the appropriate API documentation for full details.
Data fields for Turbot Guardrails APIs are always defined in camel case and start with a lower case letter (e.g. resourceUrn
). CloudFormation resources are typically defined in camel case and start with an upper case letter (e.g. ResourceUrn
). To make Turbot Guardrails resources consistent with CloudFormation format, Turbot Guardrails accepts either format for fields and will automatically convert them to start with lower case. For example, using either resourceUrn
or ResourceUrn
in the Custom Resource makes no difference - both are passed to the API as resourceUrn
.
ARN to URN Conversion
It's common to use both AWS resources (defined by ARNs) and Turbot Guardrails resources (defined by URNs) in the same CloudFormation stack. Turbot Guardrails makes this easy by allowing ARNs to be passed in Turbot Guardrails URN fields. For example, the following is valid:
ResourceUrn: !GetAtt TestRole.Arn
Output from Turbot Guardrails Custom Resources
Turbot Guardrails Custom Resources generally return the same results as the underlying API call. The result is not converted to uppercase camel, but always returned exactly as defined in the API (lowercase camel).
ServiceToken for Custom Resources
Custom Resources in CloudFormation must specify a ServiceToken
, defining the handler for the resource. Turbot Guardrails Resources can be used from CloudFormation stacks in any region of any Turbot-managed AWS account. The ServiceToken
is always set to be:
ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler'
Turbot Guardrails Custom Resources
Resource Group
MyPatchingRG: Type: "Custom::TurbotResourceGroup" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } Id: my-patching-rg Title: My Patching Resource Group ResourceUrn: "urn:turbot:c1:abc" Description: I am a RG to enforce patching.
Policy
EnforcePatchManagement: Type: "Custom::TurbotPolicy" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } ResourceUrn: !GetAtt MyRG.urn Requirement: MUST Name: "AWS:EC2:InstancePatchManagement" Value: "Enforce: Enabled with Target Patch Group" Notes: | Always use the patch group defined in AWS > EC2 > Instance Target Patch Group. This ensures a common patch baseline across all servers unless they have been explicitly granted an exception.
Resource Group Attachment
Attach a resource group to a resource. The resource group will be attached to the end of the list of resource groups for the resource.
PatchMyServer: Type: "Custom::TurbotResourceGroupAttachment" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } ResourceUrn: !GetAtt MyServer.Arn ResourceGroupUrn: !GetAtt MyPatchingRG.urn
Shadow
CloudFormation expects to manage the complete configuration and lifecycle of resources. Changes made outside CloudFormation often result in failure of further updates or deletions to the original stack.
In contrast, Turbot Guardrails is designed to detect and automatically correct the configuration of resources. For example, new IAM Roles may have lockdown policies added to them by Turbot Guardrails. Unfortunately, these changes can then cause the original CloudFormation stack to fail when operating on the IAM Role.
Turbot Guardrails Shadow resources provide a simple mechanism to resolve this conflict. When an AWS resource has dependencies managed by Turbot Guardrails, a Shadow should be created as a dependency. During deletion, the Shadow is deleted first which provides Turbot Guardrails with the opportunity to cleanup any dependencies before the AWS resource deletion is attempted.
TestRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: root PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: "*" Resource: "*" RoleName: test_role
TestRoleShadow: Type: "Custom::TurbotShadow" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } resourceArn: !GetAtt TestRole.Arn
Directory
dir: Type: "Custom::TurbotDirectory" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } ResourceUrn: "urn:turbot:dev:aau" Id: dir02 Type: turbot Title: Dir 02 Description: "My test dir #02." UrnTemplate: "urn:turbot:::profile:turbot:" LoginNameTemplate: | - default: ""
Lookup
test: Type: "Custom::TurbotLookup" Properties: ServiceToken: !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:turbot_aws_api_handler' Turbot: { AccessKey: !Ref TurbotAccessKey, SecretKey: !Ref TurbotSecretKey } ResourceUrn: "arn:aws:iam::123456789012:role/test_role_1"
Contact us to learn more about managing Turbot Guardrails through Custom Resources in CloudFormation, or to understand how Turbot Guardrails can automate networking, operations, security, and compliance for your organization. Schedule a demo to see Turbot Guardrails in action.