At Common Fate we're big fans of authorization-as-code. Treating your authorization policies as source code means you can test and review changes using your existing tools like Terraform and GitHub. We use Cedar as the authorization-as-code framework in our product.
If you're unfamiliar with Cedar, you can check out our introductory blog post here.
We have released a Cedar Terraform Provider to make authoring Cedar policies easier in Terraform. The provider allows you to write authorization policies using HCL, Terraform's configuration syntax. Here's a simple example:
data "cedar_policyset" "example" {
policy {
effect = "permit"
annotation {
name = "advice"
value = "You can request access because you are in the Engineering team."
}
principal_in = {
type = "AWS::IDC::Group"
id = "12345-12345-12345"
}
action = {
type = "Access::Action"
id = "Request"
}
any_resource = true
when {
text = "resource.target in AWS::OrgUnit::\"ou-123\""
}
}
}
resource "commonfate_policyset" "example" {
id = "example"
text = data.cedar_policyset.example.text
}
The cedar_policyset
resource renders a Cedar policy, available as data.cedar_policyset.example.text
. Here's what the resulting policy looks like:
@advice("You can request access because you are in the Engineering team.")
permit (
principal in [AWS::IDC::Group::"12345-12345-12345"],
action == Access::Action::"Request",
resource
)
when {
resource.target in AWS::OrgUnit::"ou-123"
};
The provider allows you to use Terraform variables in your policies. For example, we can configure an on-call rotation in PagerDuty, as well as authorization policies for access workflows in one place:
resource "pagerduty_schedule" "example" {
name = "Daily Engineering Rotation"
time_zone = "America/New_York"
layer {
name = "Night Shift"
start = "2015-11-06T20:00:00-05:00"
rotation_virtual_start = "2015-11-06T20:00:00-05:00"
rotation_turn_length_seconds = 86400
users = [pagerduty_user.example.id]
restriction {
type = "daily_restriction"
start_time_of_day = "08:00:00"
duration_seconds = 32400
}
}
teams = [pagerduty_team.example.id]
}
data "cedar_policyset" "example" {
policy {
effect = "permit"
annotation {
name = "advice"
value = "Access is automatically approved because you are on-call in the ${pagerduty_schedule.example.name} rotation."
}
principal_in = {
type = "PagerDuty::OnCall"
id = pagerduty_schedule.example.id
}
action = {
type = "Access::Action"
id = "Activate"
}
any_resource = true
}
}
You can learn more about the provider here.