IAM Policies
Important: These docs are for the outdated Jets 5 versions and below. For the latest Jets docs: docs.rubyonjets.com
Jets provides several ways to finely control the IAM policies associated with your Lambda functions. Here are the ways and their precedence:
- Function-specific IAM policy: highest precedence. Applies for the distinct Lambda function.
- Class-wide IAM policy: Applies for all Lambda functions for the class.
- Application-wide IAM policy: lowest precedence. Applies for all Lambda functions of the Jets application.
CloudFormation Controllers Build Setting
Important: In Jets v5, a single Lambda function handles all controller requests. You can only define IAM policies for all controllers in ApplicationController or in config/application.rb
.
For jobs, you have the ability to control IAM Policies at the individual Lambda function level because Jets always deploys an distinct Lambda functions for each job method.
Function specific IAM policy
class PostsController < ApplicationController
# ...
iam_policy("s3", "sns")
def show
render json: {action: "show", id: params[:id]}
end
end
Class-wide IAM policy
class PostsController < ApplicationController
class_iam_policy(
"dynamodb",
{
action: ["kinesis:*"],
effect: "Allow",
resource: "*",
}
)
end
Application-wide IAM policy
Jets.application.configure do |config|
config.iam_policy = ["logs"]
end
Controllers vs Jobs
You only have fine-grain control of function IAM Policies for Jobs, not Controllers. This is because each Job method is deployed as a separate discrete Lambda Function. Whereas, a single Lambda Function is deployed for all controllers.
IAM Policies Inheritance
IAM policies defined at lower levels of precedence inherit and include the policies from the higher levels of precedence. This is done so you do not have to duplicate your IAM policies when you only need to add simple additional permissions. For example, the default application-wide IAM policy looks something like this:
[{
action: ["logs:*"],
effect: "Allow",
resource: "arn:aws:logs:REGION:123456789:log-group:/aws/lambda/demo-dev-*",
}]
When you add a function specific IAM policy to a method:
class PostsController < ApplicationController
# ...
iam_policy("s3")
def show
render json: {action: "show", id: params[:id]}
end
end
The resulting policy for the method will look something like this:
[{
action: ["logs:*"],
effect: "Allow",
resource: "arn:aws:logs:REGION:123456789:log-group:/aws/lambda/demo-dev-*",
},{
action: ["s3:*"],
effect: "Allow",
resource: "*",
}]
So the IAM policies are additive.
Application-wide: Override but Keep Default
If you would like to override the default Application-wide IAM policy in config/application.rb
and still use the Jets default application IAM policy, then set config.iam_policy
:
Jets.application.configure do |config|
config.iam_policy = [
{
action: ["dynamodb:*"],
effect: "Allow",
resource: "arn:aws:dynamodb:#{Jets.aws.region}:#{Jets.aws.account}:table/#{Jets.project_namespace}*",
}
]
end
This adds to the Jets default application IAM policy. This is useful because the default application IAM policy is dynamically calculated depending on what the resources are being provisioned. For example, using Shared Resources will add CloudFormation read permissions.
Application-wide: Override Entirely
If you wish to override the Jets default application IAM policy entirely, then set config.default_iam_policy
:
Jets.application.configure do |config|
config.default_iam_policy = [
{
action: ["logs:*", "s3:*"],
effect: "Allow",
resource: "*",
}
]
end
Note, be careful using this advanced technique because it will override the IAM default policy entirely. It could prevent the Jets application from working right because it doesn’t have enough permissions. You must make sure that the policy has the right permissions.
IAM DSL Multiple Calls
When you call iam_policy
multiple times, it appends permissions for that specific function. Example:
iam_policy("s3")
iam_policy("sns")
The same as:
iam_policy("s3", "sns")
IAM Policy Definition Styles
You might have noticed that the above iam_policy
examples take a variety of different parameter styles. Jets allows for different IAM Policy Definition styles for your convenience. The iam_policy
takes a single parameter or list of parameters. Jets expands each parameter in the list to Policy Statements in an IAM Policy Document.
Summary of the different expansion styles:
- Simple Statement: simplest
- Statement Hash
- Full Policy Hash: most complex
It is suggested that you start off with the simplest iam_policy
definition style and use to the more complex styles when needed. Here are examples of each style with their expansion:
IAM Policy Simple Statement
iam_policy("s3", "sns")
Expands to:
Version: '2012-10-17'
Statement:
- Action:
- s3:*
Effect: Allow
Resource: "*"
- Action:
- sns:*
Effect: Allow
Resource: "*"
The notation with :*
also works: iam_policy("s3:*", "sns:*")
.
IAM Policy Statement Hash
class_iam_policy(
"dynamodb",
{
action: ["kinesis"],
effect: "Allow",
resource: "arn:aws:kinesis:#{Jets.aws.region}:#{Jets.aws.account}:stream/name*",
}
)
Expands to:
Version: '2012-10-17'
Statement:
- Action:
- dynamodb:*
Effect: Allow
Resource: "*"
- Action:
- kinesis:*
Effect: Allow
Resource: "arn:aws:kinesis:us-west-2:1234567890:stream/name*"
Note, the resource values are examples.
IAM Policy Full Policy Hash
iam_policy(
version: "2012-10-17",
statement: [{
action: ["lambda:*"],
effect: "Allow",
resource: "*"
}]
)
Expands to:
Version: '2012-10-17'
Statement:
- Action:
- lambda:*
Effect: Allow
Resource: "*"
IAM Policy Definition Expansion
What’s important to understand is that ultimately, the iam_policy
definition expands to include an IAM Policy document that looks something like this:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- s3:*
Effect: Allow
Resource: "*"
The expanded IAM Policy documents gets included into the CloudFormation template and get associated with the desired Lambda functions. More details on what a raw IAM Policy document looks like can be found at:
One Lambda For All Conrollers
For controllers, Jets builds and uses only a single Lambda Function. Hence the iam_policy
definitions cannot be applied at the individual function level. There is only a single Lambda Function.
In this case, Jets will print and warning and tell you to either use the Application-wide IAM policy in config/application.rb
. You also define your IAM policy at the ApplicationController
.
Lambda Function vs User Deploy IAM Policies
The IAM Policies docs on this page refer to the IAM policy associated with your Lambda Execution Role. These permissions control what AWS resources your Lambda functions have access to. This is different from the IAM role you use to deploy a Jets application, which is typically your IAM User permissions. If you are looking for the minimal IAM Policy to deploy a Jets application for your IAM user, check out Minimal Deploy IAM Policy.