This is a SAM template for an Automated policy orchestrator - Below is an explanation of how to deploy the template and build the Step Function state machine:
.
├── README.MD <-- This instructions file
├── src
│ └── askUser <-- Source code for askUser lambda function
│ └── PolicyChangeApprove <-- Source code for PolicyChangeApprove lambda function
│ └── RecieveUserAPI <-- Source code for RecieveUserAPI lambda function
│ └── RevertPolicy <-- Source code for RevertPolicy lambda function
│ └── ValidatePolicy <-- Source code for ValidatePolicy lambda function
├── template.yaml <-- SAM template
├── package.json <-- SAM package
├── padpolicy.json <-- Example policy document
Follow the instructions below in order to deploy from this repository: Clone this repo to your local machine.
Firstly, we need a S3 bucket
where we can upload our Lambda functions packaged as ZIP before we deploy anything - If you don't have a S3 bucket to store code artifacts then this is a good time to create one:
aws s3 mb s3://BUCKET_NAME
sam build && sam package \
--output-template-file package.yaml \
--s3-bucket BUCKET_NAME
Next, the following command will create a Cloudformation Stack and deploy your SAM resources.
sam deploy \
--template-file package.yaml \
--stack-name sam-app \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides EmailAddress={YOUR-EMAIL-ADDRESS}
Navigate to the Step Functions console and click on edit.
All states will be defined insite States{}
object:
{
"Comment": "Defect detection state machine",
"StartAt": "ModifyState",
"States": {
}
}
Re-structures the input data into a more usable format:
"ModifyState": {
"Type": "Pass",
"Parameters": {
"policy.$": "$.detail.requestParameters.policyDocument",
"accountId.$": "$.detail.userIdentity.accountId",
"region.$": "$.region",
"policyMeta.$":"$.detail.responseElements.policy"
},
"ResultPath": "$",
"Next": "ValidatePolicy"
},
Invokes the ValidatePolicy Lambda that checks the new policy document against the restricted actions:
"ValidatePolicy": {
"Type": "Task",
"ResultPath":"$.taskresult",
"Resource": "{Replace-This-With-ValidatePolicy-Arn}",
"Next": "ChooseAction"
},
Creates a new default version of the policy with only Log permissions and deletes previously created policy version:
"TempRemove": {
"Type": "Task",
"ResultPath":"$.taskresult",
"Resource": "{Replace-This-With-{RevertPolicy-Arn}",
"Next": "AskUser"
},
Choice state, branches depending on input from ValidatePolicy step:
"ChooseAction": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.taskresult.action",
"StringEquals": "remedy",
"Next": "TempRemove"
},
{
"Variable": "$.taskresult.action",
"StringEquals": "alert",
"Next": "AllowWithNotification"
}
],
"Default": "AllowWithNotification"
},
No restricted actions detected, user is still notified of change (via SNS email) then executions ends:
"AllowWithNotification": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "{Replace-This-With-{AlertTopic-Arn}",
"Subject": "Policy change detected!",
"Message.$": "$.taskresult.message"
},
"End": true
},
Restricted action detected, send approval email to user via SNS, with taskToken that initiates the callback pattern:
"AskUser":{
"Type": "Task",
"Resource":"arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters":{
"FunctionName":"askUser",
"Payload":{
"token.$":"$$.Task.Token"
}
},
"ResultPath":"$.taskresult",
"Next": "usersChoice"
},
Branch based on user's approval/deny action:
"usersChoice": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.taskresult.action",
"StringEquals": "delete",
"Next": "denied"
},
{
"Variable": "$.taskresult.action",
"StringEquals": "allow",
"Next": "approved"
}
],
"Default": "denied"
},
User denied policy creation, end execution with no further action:
"denied": {
"Type": "Pass",
"End":true
},
Restore initial policy document by creating as a new version:
"approved": {
"Type": "Task",
"Resource": "{Replace-This-With-{PolicyChangerApproveARN}",
"TimeoutSeconds": 3600,
"End": true
}
Use the AWS CLI to create a new policy. An example policy document has been included in this repository named badpolicy.json
.
aws iam create-policy --policy-name my-bad-policy --policy-document file://badpolicy.json
In order to delete our Serverless Application recently deployed you can use the following AWS CLI Command:
aws cloudformation delete-stack --stack-name sam-app
Here are a few things you can try to get more acquainted with building serverless applications using SAM:
- Uncomment state machine definition
template.js
- Enable step-through debugging docs for supported runtimes
Next, you can use AWS Serverless Application Repository to deploy ready to use Apps that go beyond hello world samples and learn how authors developed their applications: AWS Serverless Application Repository main page
All commands used throughout this document
# create a bucket
aws s3 mb s3://BUCKET_NAME
# Build and package application
sam build && sam package \
--output-template-file package.yaml \
--s3-bucket BUCKET_NAME
Next, the following command will create a Cloudformation Stack and deploy your SAM resources.
# Deploy SAM application
sam deploy \
--template-file package.yaml \
--stack-name sam-app \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides EmailAddress={YOUR-EMAIL-ADDRESS}
# Creating a new Policy
aws iam create-policy --policy-name my-bad-policy --policy-document file://badpolicy.json