Yesterday, AWS announced a new feature for AWS SAM called Serverless Connectors. I was particularly excited about this one for two reasons.
Firstly - I often see tutorials gloss over the implementation of the principle of least privilege when it comes to identity and access management (IAM). SAM Serverless Connectors seeks to correct this by making it easy to create
AWS::IAM::ManagedPolicy resources just by defining a source resource, destination resource, and type/s of permission (e.g.
Secondly - in a meeting I had recently with the Serverless product team at AWS via the Community Builders programme, I heard that a feature to solve this problem was on the way. I was expecting that it might be something announced at re:Invent, so to receive it this early was a pleasant surprise.
All of the source code that makes up the example application detailed in this article is available on GitHub in the aws-sam-serverless-connector-demo repository.
It's worth pointing out at this stage that in order to make use of any features of AWS SAM, the serverless transform needs to be added to the top level of the CloudFormation template. This instructs the CloudFormation service to convert the conceptual
AWS::Serverless::* resources to the underlying CloudFormation resources.
In this article we'll look at three examples where a IAM managed policy is generated to grant access to a particular resource, scoped down to
Write privileges. The way that the
AWS::Serverless::Connector resource works is that a
Source needs to be specified. We'll be using a Lambda function as the source. Normally when writing an IAM policy a source wouldn't need to be specified, so this may feel a little strange. The reason for specifying the
Source is that it allows SAM to be smart and automatically attach the
AWS::IAM::ManagedPolicy that is created to the role that is created for the Lambda function. Winner!
When the Lambda function is defined, nothing out of the ordinary needs to be specified.
ExampleFunction: Type: AWS::Serverless::Function Properties: Timeout: 3 CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64
Step Functions State Machine
The first example we'll explore is if a Lambda function needs to interact with a Step Functions State Machine. The State Machine itself is defined as usual. The below snippet shows a sample
AWS::Serverless::StateMachine resource. The policies and definition are for example only, they are not relevant to the function of the Serverless Connectors released yesterday.
ExampleStateMachine: Type: AWS::Serverless::StateMachine Properties: Policies: - Version: '2012-10-17' Statement: - Effect: Allow Action: - s3:ListBucket Resource: '*' Definition: StartAt: Succeed States: Succeed: Type: Succeed
Now we get to the good stuff. To create an IAM managed policy to allow
Write access to the resource represented by the
ExampleStateMachine logical ID. By specifying
ExampleFunction as the source, the created policy will be attached to the Lambda function execution role. It is worth mentioning at this stage that
Destination don't just support the referencing another resource in the stack via a logical ID in the
Id key. Support for keys such as
Arn is also there to cover off those cases where a you may want to connect resources that aren't necessarily in the same stack.
FunctionToStateMachineConnector: Type: AWS::Serverless::Connector Properties: Source: Id: ExampleFunction Destination: Id: ExampleStateMachine Permissions: - Write
When the stack has been created, it's possible to see the policy created in the IAM console. I must say that when I heard about this feature, I was a little worried that it might be provision overly-permissive policies. I really like the fact that
Write focuses on application level permissions rather than infrastructure. For example, the
Write permissions connecting to a state machine could have granted permissions to edit or even delete the resource. I'd say the product team have pretty much hit the nail on the head here.
Version: '2012-10-17' Statement: - Action: - states:StartExecution - states:StartSyncExecution Resource: - arn:aws:states:eu-west-1:012345678901:stateMachine:ExampleStateMachine-WnEDETcG2BGX Effect: Allow - Action: - states:StopExecution Resource: - arn:aws:states:eu-west-1:012345678901:execution:ExampleStateMachine-WnEDETcG2BGX:* Effect: Allow
The next example to look at is generating permissions for
Write permissions on a DynamoDB.
ExampleTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: Id Type: String FunctionToTableConnector: Type: AWS::Serverless::Connector Properties: Source: Id: ExampleFunction Destination: Id: ExampleTable Permissions: - Write
In the code snippet below is the IAM managed policy that's generated for
Write permissions on a DynamoDB table.
Version: '2012-10-17' Statement: - Action: - dynamodb:PutItem - dynamodb:UpdateItem - dynamodb:DeleteItem - dynamodb:BatchWriteItem - dynamodb:PartiQLDelete - dynamodb:PartiQLInsert - dynamodb:PartiQLUpdate Resource: - arn:aws:dynamodb:eu-west-1:012345678901:table/serverless-connector-resource-demo-ExampleTable-G4C7DC159EJL - arn:aws:dynamodb:eu-west-1:012345678901:table/serverless-connector-resource-demo-ExampleTable-G4C7DC159EJL/index/* Effect: Allow
The final example shows how to grant
Read permissions on an S3 bucket from the Lambda function we created earlier.
ExampleBucket: Type: AWS::S3::Bucket FunctionToBucketConnector: Type: AWS::Serverless::Connector Properties: Source: Id: ExampleFunction Destination: Id: ExampleBucket Permissions: - Read
Contained in the final code snippet is the IAM managed policy that's generated for
Read permissions on a S3 bucket.
Version: '2012-10-17' Statement: - Action: - s3:GetObject - s3:GetObjectAcl - s3:GetObjectLegalHold - s3:GetObjectRetention - s3:GetObjectTorrent - s3:GetObjectVersion - s3:GetObjectVersionAcl - s3:GetObjectVersionForReplication - s3:GetObjectVersionTorrent - s3:ListBucket - s3:ListBucketMultipartUploads - s3:ListBucketVersions - s3:ListMultipartUploadParts Resource: - arn:aws:s3:::serverless-connector-resource-demo-examplebucket-97ah5qo379y1 - arn:aws:s3:::serverless-connector-resource-demo-examplebucket-97ah5qo379y1/* Effect: Allow
In summary, I'm really pleased by this new release. I believe it'll make it easier for people to learn and get started with building on AWS without creating drastically over permissive IAM policies.