-
Notifications
You must be signed in to change notification settings - Fork 0
feat(k8s/tofu): add IAM agent-permissions OpenTofu module #193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
7afd03b
feat(k8s/tofu): add IAM agent-permissions OpenTofu module
c129ebd
refactor(k8s/tofu): remove AVP policy from agent-permissions module
d93c510
refactor(k8s/tofu): move agent-permissions module to k8s/specs/tofu
bde6d91
Update locals.tf
davidf-null 52e7a68
feat(k8s/tofu): allow additional roles in permissions trust policy
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| data "aws_caller_identity" "current" {} | ||
| data "aws_region" "current" {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| locals { | ||
| # Module identifier | ||
| iam_module_name = "iam" | ||
|
|
||
| # Whether resources are created | ||
| iam_create = var.iam_create_role | ||
|
|
||
| # Derived names (overridable via variables) | ||
| permissions_role_name = var.permissions_role_name != "" ? var.permissions_role_name : "nullplatform-${var.cluster_name}-agent-permissions-role" | ||
| policies_name_prefix = var.policies_name_prefix != "" ? var.policies_name_prefix : "nullplatform_${var.cluster_name}" | ||
|
|
||
| # Primary agent role trusted by the permissions role. Defaults to the | ||
| # conventional agent role name for the cluster when not provided explicitly. | ||
| agent_role_arn = var.agent_role_arn != "" ? var.agent_role_arn : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/nullplatform-${var.cluster_name}-agent-role" | ||
|
|
||
| # Default tags applied to every IAM resource | ||
| iam_default_tags = merge(var.iam_resource_tags_json, { | ||
| ManagedBy = "nullplatform-custom-scope-role" | ||
| Module = local.iam_module_name | ||
| }) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| ################################################################################ | ||
| # IAM permissions role assumed by the nullplatform agent role | ||
| # | ||
| # Holds the actual workload policies (Route53, EKS, ELB). Its trust policy | ||
| # trusts only the agent IRSA role (plus any additional roles), so an agent's IRSA | ||
| # token cannot exercise these permissions without first assuming it (sts:AssumeRole). | ||
| # | ||
| # This is the "permissions role" half of the reference module | ||
| # tofu-modules/infrastructure/aws/iam/agent. The IRSA agent role itself is | ||
| # created once at cluster setup and is out of scope for this module. | ||
| ################################################################################ | ||
|
|
||
| resource "aws_iam_role" "nullplatform_agent_permissions" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| name = local.permissions_role_name | ||
| description = "Permissions role assumed by the nullplatform agent role" | ||
|
|
||
| assume_role_policy = jsonencode({ | ||
| Version = "2012-10-17" | ||
| Statement = [{ | ||
| Effect = "Allow" | ||
| Principal = { AWS = concat([local.agent_role_arn], var.additional_agent_role_arns) } | ||
| Action = "sts:AssumeRole" | ||
| }] | ||
|
fedemaleh marked this conversation as resolved.
|
||
| }) | ||
|
|
||
| tags = local.iam_default_tags | ||
| } | ||
|
|
||
| ################################################################################ | ||
| # Policy attachments | ||
| ################################################################################ | ||
|
|
||
| resource "aws_iam_role_policy_attachment" "permissions_route53" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| role = aws_iam_role.nullplatform_agent_permissions[0].name | ||
| policy_arn = aws_iam_policy.nullplatform_route53_policy[0].arn | ||
| } | ||
|
|
||
| resource "aws_iam_role_policy_attachment" "permissions_eks" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| role = aws_iam_role.nullplatform_agent_permissions[0].name | ||
| policy_arn = aws_iam_policy.nullplatform_eks_policy[0].arn | ||
| } | ||
|
|
||
| resource "aws_iam_role_policy_attachment" "permissions_elb" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| role = aws_iam_role.nullplatform_agent_permissions[0].name | ||
| policy_arn = aws_iam_policy.nullplatform_elb_policy[0].arn | ||
| } | ||
|
fedemaleh marked this conversation as resolved.
|
||
|
|
||
| ################################################################################ | ||
| # Route 53 IAM policy | ||
| # Manage Route 53 DNS records for service discovery. | ||
| ################################################################################ | ||
|
|
||
| resource "aws_iam_policy" "nullplatform_route53_policy" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| name = "${local.policies_name_prefix}_route53_policy" | ||
| description = "Policy for managing Route 53 DNS records" | ||
| tags = local.iam_default_tags | ||
| policy = jsonencode({ | ||
| "Version" : "2012-10-17", | ||
| "Statement" : [ | ||
| { | ||
| "Effect" : "Allow", | ||
| "Action" : [ | ||
| "route53:ChangeResourceRecordSets", | ||
| "route53:ListResourceRecordSets", | ||
| "route53:GetHostedZone", | ||
| "route53:ListHostedZones", | ||
| "route53:ListHostedZonesByName" | ||
| ], | ||
| "Resource" : [ | ||
| "arn:aws:route53:::hostedzone/*" | ||
| ], | ||
| } | ||
| ] | ||
| }) | ||
| } | ||
|
|
||
| ################################################################################ | ||
| # Elastic Load Balancing (ELB) IAM policy | ||
| # Describe and monitor load balancers and target groups. | ||
| ################################################################################ | ||
|
|
||
| resource "aws_iam_policy" "nullplatform_elb_policy" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| name = "${local.policies_name_prefix}_elb_policy" | ||
| description = "Policy for managing Elastic Load Balancing resources" | ||
| tags = local.iam_default_tags | ||
| policy = jsonencode( | ||
| { | ||
| "Version" : "2012-10-17", | ||
| "Statement" : [ | ||
| { | ||
| "Effect" : "Allow", | ||
| "Action" : [ | ||
| "elasticloadbalancing:DescribeLoadBalancers", | ||
| "elasticloadbalancing:DescribeTargetGroups" | ||
| ], | ||
| "Resource" : "*", | ||
| "Condition" : { | ||
| "StringEquals" : { | ||
| "aws:RequestedRegion" : [ | ||
| data.aws_region.current.region | ||
| ] | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| "Effect" : "Allow", | ||
| "Action" : [ | ||
| "elasticloadbalancing:DescribeTargetHealth", | ||
| "elasticloadbalancing:DescribeListeners", | ||
| "elasticloadbalancing:DescribeRules" | ||
| ], | ||
| "Resource" : [ | ||
| "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/k8s-nullplatform-*", | ||
| "arn:aws:elasticloadbalancing:*:*:targetgroup/k8s-nullplatform-*" | ||
| ], | ||
| } | ||
| ] | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| ################################################################################ | ||
| # EKS IAM policy | ||
| # Describe and list EKS cluster resources. | ||
| ################################################################################ | ||
|
|
||
| resource "aws_iam_policy" "nullplatform_eks_policy" { | ||
| count = local.iam_create ? 1 : 0 | ||
|
|
||
| name = "${local.policies_name_prefix}_eks_policy" | ||
| description = "Policy for managing EKS cluster resources" | ||
| tags = local.iam_default_tags | ||
| policy = jsonencode({ | ||
| "Version" : "2012-10-17", | ||
| "Statement" : [ | ||
| { | ||
| "Effect" : "Allow", | ||
| "Action" : [ | ||
| "eks:DescribeCluster", | ||
| "eks:ListClusters", | ||
| "eks:DescribeNodegroup", | ||
| "eks:ListNodegroups", | ||
| "eks:DescribeAddon", | ||
| "eks:ListAddons" | ||
| ], | ||
| "Resource" : [ | ||
| "arn:aws:eks:*:*:cluster/*", | ||
| "arn:aws:eks:*:*:nodegroup/*", | ||
| "arn:aws:eks:*:*:addon/*" | ||
| ], | ||
| } | ||
| ] | ||
| }) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| output "permissions_role_arn" { | ||
| description = "ARN of the permissions role assumed by the nullplatform agent role" | ||
| value = local.iam_create ? aws_iam_role.nullplatform_agent_permissions[0].arn : "" | ||
| } | ||
|
|
||
| output "permissions_role_name" { | ||
| description = "Name of the permissions role" | ||
| value = local.iam_create ? aws_iam_role.nullplatform_agent_permissions[0].name : "" | ||
| } | ||
|
|
||
| output "permissions_role_id" { | ||
| description = "ID of the permissions role" | ||
| value = local.iam_create ? aws_iam_role.nullplatform_agent_permissions[0].id : "" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| variable "agent_role_arn" { | ||
| description = "ARN of the primary nullplatform agent IRSA role allowed to assume this permissions role via sts:AssumeRole, and always a trusted principal of the role's trust policy. Defaults (when empty) to the conventional agent role for the cluster: arn:aws:iam::<account>:role/nullplatform-<cluster_name>-agent-role." | ||
| type = string | ||
| default = "" | ||
|
|
||
| validation { | ||
| condition = var.agent_role_arn == "" || can(regex("^arn:aws:iam::[0-9]{12}:role/.+", var.agent_role_arn)) | ||
| error_message = "agent_role_arn must be empty (to use the derived default) or match arn:aws:iam::<account-id>:role/<role-name>" | ||
| } | ||
| } | ||
|
|
||
| variable "additional_agent_role_arns" { | ||
| description = "Extra IAM role ARNs allowed to assume this permissions role, appended to agent_role_arn in the trust policy. Defaults to none." | ||
| type = list(string) | ||
| default = [] | ||
|
|
||
| validation { | ||
| condition = alltrue([for arn in var.additional_agent_role_arns : can(regex("^arn:aws:iam::[0-9]{12}:role/.+", arn))]) | ||
| error_message = "each additional_agent_role_arns entry must match arn:aws:iam::<account-id>:role/<role-name>" | ||
| } | ||
| } | ||
|
|
||
| variable "cluster_name" { | ||
| description = "Name of the cluster where the agent runs. Used to derive default resource names." | ||
| type = string | ||
| } | ||
|
|
||
| variable "permissions_role_name" { | ||
| description = "Override for the permissions IAM role name. Defaults to nullplatform-{cluster_name}-agent-permissions-role." | ||
| type = string | ||
| default = "" | ||
| } | ||
|
|
||
| variable "policies_name_prefix" { | ||
| description = "Override for the IAM policy name prefix. Defaults to nullplatform_{cluster_name}." | ||
| type = string | ||
| default = "" | ||
| } | ||
|
|
||
| variable "iam_create_role" { | ||
| description = "Whether to create the permissions role and its policies. When false, the module produces no resources." | ||
| type = bool | ||
| default = true | ||
| } | ||
|
|
||
| variable "iam_resource_tags_json" { | ||
| description = "Tags to apply to IAM resources created by this module." | ||
| type = map(string) | ||
| default = {} | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| terraform { | ||
| required_providers { | ||
| aws = { | ||
| source = "hashicorp/aws" | ||
| # v6+ required: the ELB policy reads data.aws_region.current.region, | ||
| # which replaced the v5 `.name` attribute. | ||
| version = ">= 6.0" | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.