Skip to content

Commit

Permalink
Update roles to support separate access for users vs services (#24)
Browse files Browse the repository at this point in the history
Update roles to support seperate acces for users vs services

In order to finer grained permissions to customer environments, access
via services and access via SN support engineers in being seperated.

For most customers, this will be a simple update of the role, for
customers that require more specific access restrictions, a list of
roles will be provided

Additionally, a small feature allow for principal ids to be checked is
added, which is used in special cases

Finally, for testing, this adding a test suffix to make it easy to run
multiple versions and bumps the version in prep of deploy
  • Loading branch information
Addison Higham authored Jun 14, 2023
1 parent 63a9eb6 commit f4a8401
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 25 deletions.
106 changes: 83 additions & 23 deletions modules/aws/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ locals {
allowed_iam_policies = join(", ", formatlist("\"%s\"", distinct(concat(local.additional_iam_policy_arns, local.default_allowed_iam_policies))))
arn_like_vpcs = formatlist("\"arn:%s:ec2:%s:%s:vpc/%s\"", local.aws_partition, var.region, local.account_id, var.vpc_allowed_ids)
arn_like_vpcs_str = format("[%s]", join(",", local.arn_like_vpcs))
assume_conditions = concat(local.external_id, local.source_identity)
assume_conditions = concat(local.external_id, local.source_identity, local.principal_check)
support_assume_conditions = concat(local.external_id, local.source_identity)
aws_partition = data.aws_partition.current.partition
build_r53_arns = [for i, v in var.hosted_zone_allowed_ids : format("\"arn:%s:route53:::hostedzone/%s\"", local.aws_partition, v)]
ebs_kms_key_arn = length(var.ebs_kms_key_arns) > 0 ? var.ebs_kms_key_arns : [data.aws_kms_key.ebs_default.arn]
Expand All @@ -54,6 +55,7 @@ locals {
r53_zone_arns = format("[%s]", join(",", local.build_r53_arns))
s3_kms_key_arn = length(var.s3_kms_key_arns) > 0 ? var.s3_kms_key_arns : [data.aws_kms_key.s3_default.arn]
source_identity = (length(var.source_identities) > 0 ? [{ test : var.source_identity_test, variable : "sts:SourceIdentity", values : var.source_identities }] : [])
principal_check = (length(var.streamnative_principal_ids) > 0 ? [{ test : "StringLike", variable : "aws:PrincipalArn", values : var.streamnative_principal_ids }] : [])
tag_set = merge({ Vendor = "StreamNative", SNVersion = var.sn_policy_version }, var.tags)

default_allowed_iam_policies = compact([
Expand Down Expand Up @@ -107,13 +109,71 @@ data "aws_iam_policy_document" "streamnative_control_plane_access" {
}
}

data "aws_iam_policy_document" "streamnative_bootstrap_access" {
statement {
sid = "AllowStreamNativeVendorAccess"
effect = "Allow"
actions = ["sts:AssumeRole"]

principals {
type = "AWS"
identifiers = var.streamnative_vendor_access_role_arns
}
dynamic "condition" {
for_each = local.assume_conditions
content {
test = condition.value["test"]
values = condition.value["values"]
variable = condition.value["variable"]
}
}
}

statement {
sid = "AllowStreamNativeEngineerAccess"
effect = "Allow"
actions = ["sts:AssumeRole"]

principals {
type = "AWS"
identifiers = var.streamnative_support_access_role_arns
}
dynamic "condition" {
for_each = local.support_assume_conditions
content {
test = condition.value["test"]
values = condition.value["values"]
variable = condition.value["variable"]
}
}
}

statement {
sid = "AllowStreamNativeControlPlaneAccess"
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]

principals {
type = "Federated"
identifiers = [
"accounts.google.com"
]
}
condition {
test = "StringEquals"
values = [var.streamnative_google_account_id]
variable = "accounts.google.com:aud"
}
}
}

######
#-- Create the IAM Permission Boundary used by all StreamNative
#-- IAM Resources. This restricts what type of access we have
#-- within your AWS Account and is applied to all our IAM Roles
######
resource "aws_iam_policy" "permission_boundary" {
name = "StreamNativeCloudPermissionBoundary"
name = "StreamNativeCloudPermissionBoundary${var.test_suffix}"
description = "This policy sets the permission boundary for StreamNative's vendor access. It defines the limits of what StreamNative can do within this AWS account."
path = "/StreamNative/"
policy = templatefile("${path.module}/files/permission_boundary_iam_policy.json.tpl",
Expand All @@ -134,28 +194,28 @@ resource "aws_iam_policy" "permission_boundary" {
######
resource "aws_iam_role" "bootstrap_role" {
count = var.create_bootstrap_role ? 1 : 0
name = "StreamNativeCloudBootstrapRole"
name = "StreamNativeCloudBootstrapRole${var.test_suffix}"
description = "This role is used to bootstrap the StreamNative Cloud within the AWS account. It is limited in scope to the attached policy and also the permission boundary."
assume_role_policy = data.aws_iam_policy_document.streamnative_vendor_access.json
assume_role_policy = data.aws_iam_policy_document.streamnative_bootstrap_access.json
path = "/StreamNative/"
permissions_boundary = aws_iam_policy.permission_boundary.arn
tags = local.tag_set
}

resource "aws_iam_policy" "bootstrap_policy" {
count = var.create_bootstrap_role ? 1 : 0
name = "StreamNativeCloudBootstrapPolicy"
name = "StreamNativeCloudBootstrapPolicy${var.test_suffix}"
description = "This policy sets the minimum amount of permissions needed by the StreamNativeCloudBootstrapRole to bootstrap the StreamNative Cloud deployment."
path = "/StreamNative/"
policy = templatefile("${path.module}/files/bootstrap_role_iam_policy.json.tpl",
{
account_id = local.account_id
region = var.region
vpc_ids = local.arn_like_vpcs_str
bucket_pattern = var.s3_bucket_pattern
cluster_pattern = var.eks_cluster_pattern
partition = local.aws_partition
r53_zone_arns = local.r53_zone_arns
account_id = local.account_id
region = var.region
vpc_ids = local.arn_like_vpcs_str
bucket_pattern = var.s3_bucket_pattern
cluster_pattern = var.eks_cluster_pattern
partition = local.aws_partition
r53_zone_arns = local.r53_zone_arns
})
tags = local.tag_set
}
Expand All @@ -172,7 +232,7 @@ resource "aws_iam_role_policy_attachment" "bootstrap_policy" {
#-- of the managed deployment.
######
resource "aws_iam_policy" "management_role" {
name = "StreamNativeCloudManagementPolicy"
name = "StreamNativeCloudManagementPolicy${var.test_suffix}"
description = "This policy sets the limits for the management role needed for StreamNative's vendor access."
path = "/StreamNative/"
policy = templatefile("${path.module}/files/management_role_iam_policy.json.tpl",
Expand All @@ -185,7 +245,7 @@ resource "aws_iam_policy" "management_role" {
}

resource "aws_iam_role" "management_role" {
name = "StreamNativeCloudManagementRole"
name = "StreamNativeCloudManagementRole${var.test_suffix}"
description = "This role is used by StreamNative for the day to day management of the StreamNative Cloud deployment."
assume_role_policy = data.aws_iam_policy_document.streamnative_control_plane_access.json
path = "/StreamNative/"
Expand All @@ -202,7 +262,7 @@ resource "aws_iam_role_policy_attachment" "management_role" {
#-- Creates the IAM Policies used by EKS Cluster add-on services
######
resource "aws_iam_policy" "runtime_policy" {
name = "StreamNativeCloudRuntimePolicy"
name = "StreamNativeCloudRuntimePolicy${var.test_suffix}"
description = "This policy defines almost all used by StreamNative cluster components"
path = "/StreamNative/"
policy = templatefile("${path.module}/files/runtime_iam_policy.json.tpl",
Expand All @@ -216,7 +276,7 @@ resource "aws_iam_policy" "runtime_policy" {
}

resource "aws_iam_policy" "alb_policy" {
name = "StreamNativeCloudLBPolicy"
name = "StreamNativeCloudLBPolicy${var.test_suffix}"
description = "The AWS policy as defined by https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.1/docs/install/iam_policy.json"
path = "/StreamNative/"
policy = templatefile("${path.module}/files/aws_lb_controller_iam_policy.json.tpl",
Expand Down Expand Up @@ -244,13 +304,13 @@ resource "local_file" "bootstrap_policy" {
count = var.write_policy_files ? 1 : 0
content = templatefile("${path.module}/files/bootstrap_role_iam_policy.json.tpl",
{
account_id = local.account_id
region = var.region
vpc_ids = local.arn_like_vpcs_str
bucket_pattern = var.s3_bucket_pattern
cluster_pattern = var.eks_cluster_pattern
partition = local.aws_partition
r53_zone_arns = local.r53_zone_arns
account_id = local.account_id
region = var.region
vpc_ids = local.arn_like_vpcs_str
bucket_pattern = var.s3_bucket_pattern
cluster_pattern = var.eks_cluster_pattern
partition = local.aws_partition
r53_zone_arns = local.r53_zone_arns
})
filename = "bootstrap_policy.json"
}
Expand Down
22 changes: 20 additions & 2 deletions modules/aws/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ variable "s3_bucket_pattern" {
}

variable "sn_policy_version" {
default = "3.1.1"
default = "3.2.0"
description = "The value of SNVersion tag"
type = string
}
Expand All @@ -94,7 +94,19 @@ variable "streamnative_google_account_id" {

variable "streamnative_vendor_access_role_arns" {
default = ["arn:aws:iam::311022431024:role/cloud-manager"]
description = "A list ARNs provided by StreamNative that enable us to work with the Vendor Access Roles created by this module (StreamNativeCloudBootstrapRole, StreamNativeCloudManagementRole). This is how StreamNative is granted access into your AWS account, and should typically be the default value unless directed otherwise."
description = "A list ARNs provided by StreamNative that enable us to work with the Vendor Access Roles created by this module (StreamNativeCloudBootstrapRole, StreamNativeCloudManagementRole). This is how StreamNative is granted access into your AWS account, and should typically be the default value unless directed otherwise. This arns are used *only* for automations."
type = list(string)
}

variable "streamnative_support_access_role_arns" {
default = ["arn:aws:iam::311022431024:role/cloud-support-general"]
description = "A list ARNs provided by StreamNative that enable streamnative support engineers access the StreamNativeCloudBootstrapRole. This is used only in some initial provisioning and in case of on-call support."
type = list(string)
}

variable "streamnative_principal_ids" {
default = []
description = "When set, this applies an additional check for certain StreamNative principals to futher restrict access to which services / users can access an account."
type = list(string)
}

Expand All @@ -104,6 +116,12 @@ variable "tags" {
type = map(string)
}

variable "test_suffix" {
default = ""
description = "Used in testing to apply us to apply multiple versions of the role"
type = string
}

variable "vpc_allowed_ids" {
default = ["*"]
description = "Allows for further scoping down policy for allowed VPC"
Expand Down

0 comments on commit f4a8401

Please sign in to comment.