diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c2ddb1..6454e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,3 +20,8 @@ * v1.5 -- 20210226 - module: add iam-general-policies + +* v1.5.1 -- 20210302 + - iam-general-policies + - add `managed_policies` for AWS managed policy references + - change `policies` to `custom_policies` diff --git a/common/version.tf b/common/version.tf index 6830365..34b1108 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "1.5" + _module_version = "1.5.1" } diff --git a/iam-general-policies/README.md b/iam-general-policies/README.md new file mode 100644 index 0000000..d3ccbc2 --- /dev/null +++ b/iam-general-policies/README.md @@ -0,0 +1,73 @@ +# aws-inf-setup :: iam-general-policies + +# Usage +Here is a simple example, the one most commonly expected to be used. + +```hcl +module "general" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//iam-general-policies" +} +``` + +This one can be used if you need to customize stuff, though really, the defaults are all built +for a reason, and deployment code (i.e., Ansible) will expect these defaults to be used in +variable file generation. + +```hcl +module "general_full" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//iam-general-policies" + + # optional + account_alias = "do2-govcloud" + + # flowlogs is generally not needed and not recommended + component_tags = { + "s3" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} +``` + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| aws | n/a | + +## Modules + +No Modules. + +## Resources + +| Name | +|------| +| [aws_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | +| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | +| [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| account\_alias | AWS Account Alias | `string` | `""` | no | +| account\_id | AWS Account ID (default will pull from current user) | `string` | `""` | no | +| component\_tags | Additional tags for Components (policy) | `map(map(string))` |
{
"policy": {}
} | no |
+| override\_prefixes | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
+| tags | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| custom\_policies | Custom Policies |
+| custom\_policy\_documents | Custom Policy Documents (no IAM policy) |
+| managed\_policies | AWS Managed Policy name to ARN mapping |
diff --git a/iam-general-policies/custom_policies.tf b/iam-general-policies/custom_policies.tf
new file mode 100644
index 0000000..99f5d11
--- /dev/null
+++ b/iam-general-policies/custom_policies.tf
@@ -0,0 +1,49 @@
+locals {
+ policies = {
+ "manage_keys" = {
+ name = "manage-access-keys"
+ path = "/"
+ description = "Manage self access keys"
+ policy = data.aws_iam_policy_document.manage_keys.json
+ create_policy = true
+ }
+ "manage_credentials" = {
+ name = "manage-credentials"
+ path = "/"
+ description = "Manage self access keys and password"
+ policy = data.aws_iam_policy_document.manage_credentials.json
+ create_policy = true
+ }
+ "deny_billing" = {
+ name = "deny-billing"
+ path = "/"
+ description = "Policy to deny access to billing and cost allocation"
+ policy = data.aws_iam_policy_document.deny_billing.json
+ create_policy = true
+ }
+ "ec2_assume" = {
+ name = "ec2_assume"
+ description = "Policy document for EC2 sts:assumerole (instance role)"
+ policy = data.aws_iam_policy_document.ec2_assume.json
+ create_policy = false
+ }
+ "sts_assume" = {
+ name = "sts_assume"
+ description = "Policy document for sts:assume"
+ policy = data.aws_iam_policy_document.sts_assume.json
+ create_policy = false
+ }
+ "root_assume" = {
+ name = "root_assume"
+ description = "Policy document for sts:assume root"
+ policy = data.aws_iam_policy_document.root_assume.json
+ create_policy = false
+ }
+ "lambda_assume" = {
+ name = "lambda_assume"
+ description = "Policy document for sts:assume lambda"
+ policy = data.aws_iam_policy_document.lambda_assume.json
+ create_policy = false
+ }
+ }
+}
diff --git a/iam-general-policies/data.tf b/iam-general-policies/data.tf
new file mode 120000
index 0000000..995624d
--- /dev/null
+++ b/iam-general-policies/data.tf
@@ -0,0 +1 @@
+../common/data.tf
\ No newline at end of file
diff --git a/iam-general-policies/defaults.tf b/iam-general-policies/defaults.tf
new file mode 120000
index 0000000..a5556ac
--- /dev/null
+++ b/iam-general-policies/defaults.tf
@@ -0,0 +1 @@
+../common/defaults.tf
\ No newline at end of file
diff --git a/iam-general-policies/main.tf b/iam-general-policies/main.tf
new file mode 100644
index 0000000..d85fac5
--- /dev/null
+++ b/iam-general-policies/main.tf
@@ -0,0 +1,81 @@
+/*
+* # aws-inf-setup :: iam-general-policies
+*
+* # Usage
+* Here is a simple example, the one most commonly expected to be used.
+*
+* ```hcl
+* module "general" {
+* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//iam-general-policies"
+* }
+* ```
+*
+* This one can be used if you need to customize stuff, though really, the defaults are all built
+* for a reason, and deployment code (i.e., Ansible) will expect these defaults to be used in
+* variable file generation.
+*
+* ```hcl
+* module "general_full" {
+* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//iam-general-policies"
+*
+* # optional
+* account_alias = "do2-govcloud"
+*
+* # flowlogs is generally not needed and not recommended
+* component_tags = {
+* "s3" = {
+* "SpecialTag1" = "something"
+* "SpecialTag2" = "somethingElse"
+* }
+* }
+* }
+* ```
+*/
+
+locals {
+ account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id
+ account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew"
+
+ base_tags = {
+ "Organization" = "census:aditcio:csvd"
+ "boc:tf_module_version" = local._module_version
+ "boc:created_by" = "terraform"
+ }
+}
+
+# "{key}" = {
+# name = "manage-access-keys"
+# path = "/"
+# description = "Manage self access keys"
+# policy = data.aws_iam_policy_document.manage_keys.json
+# create_policy = true
+# }
+
+locals {
+ iam_policies = { for k, v in local.custom_policies : k => v if(v["create_policy"] == true && v["policy"] != "") }
+ out_policies = { for k, v in local.iam_policies : k => {
+ "name" = v["name"]
+ "path" = v["path"]
+ "description" = v["description"]
+ "policy" = v["policy"]
+ "create_policy" = v["create_policy"]
+ "policy_arn" = aws_iam_polic.general[k]
+ }
+ }
+}
+
+# see custom_policies.tf for local.custom_policies
+resource "aws_iam_policy" "general" {
+ for_each = local.iam_policies
+ name = format("%vinf-%v", lookup(local._prefixes, "policy", ""), each.value["name"])
+ path = lookup(each.value, "path", "/")
+ description = lookup(each.value, "description", "${each.key} policy")
+ policy = each.value["policy"]
+
+ # tags = merge(
+ # var.tags,
+ # local.base_tags,
+ # lookup(var.component_tags, "policy", {}),
+ # map("Name",format("%vinf-%v", lookup(local._prefixes, "policy", ""), each.value["name"]))
+ # )
+}
diff --git a/iam-general-policies/managed_policies.tf b/iam-general-policies/managed_policies.tf
new file mode 100644
index 0000000..1b30b40
--- /dev/null
+++ b/iam-general-policies/managed_policies.tf
@@ -0,0 +1,26 @@
+locals {
+ managed_policies = {
+ "AdministratorAccess" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "AdministratorAccess")
+ }
+ "ReadOnlyAccess" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "ReadOnlyAccess")
+ }
+ "AmazonVPCFullAccess" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "AmazonVPCFullAccess")
+ }
+ "AWSSupportAccess" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "AWSSupportAccess")
+ }
+ "CloudWatchAWSSupportAccess" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "CloudWatchAWSSupportAccess")
+ }
+
+ "Billing" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "job-function/Billing")
+ }
+ "NetworkAdministrator" = {
+ arn = format("arn:%v:iam::aws:policy/%v", data.aws_arn.current.partition, "job-function/NetworkAdministrator")
+ }
+ }
+}
diff --git a/iam-general-policies/outputs.tf b/iam-general-policies/outputs.tf
new file mode 100644
index 0000000..851de96
--- /dev/null
+++ b/iam-general-policies/outputs.tf
@@ -0,0 +1,34 @@
+# name = {
+# arn
+# }
+
+output "managed_policies" {
+ description = "AWS Managed Policy name to ARN mapping"
+ values = local.managed_policies
+}
+
+# name = {
+# name
+# path
+# description
+# policy (document)
+# create_policy
+# policy_arn
+# }
+
+output "custom_policies" {
+ description = "Custom Policies"
+ values = local.out_poicies
+}
+
+# name = {
+# name
+# description
+# policy (document)
+# create_policy
+# }
+
+output "custom_policy_documents" {
+ description = "Custom Policy Documents (no IAM policy)"
+ values = { for k, v in local.custom_policies : k => v if(v["create_policy"] == false && v["policy"] != "") }
+}
diff --git a/iam-general-policies/policy_data.tf b/iam-general-policies/policy_data.tf
new file mode 100644
index 0000000..a9d1285
--- /dev/null
+++ b/iam-general-policies/policy_data.tf
@@ -0,0 +1,120 @@
+#---
+# iam policies
+#---
+data "aws_iam_policy_document" "manage_keys" {
+ statement {
+ sid = "ManageOwnAccessKeys"
+ effect = "Allow"
+ resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, "*")]
+ # resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, local.account_id) ]
+ # resources = ["arn:${data.aws_arn.current.partition}:iam::*:user/$${aws:username}"]
+ actions = [
+ "iam:CreateAccessKey",
+ "iam:DeleteAccessKey",
+ "iam:GetAccessKeyLastUsed",
+ "iam:GetUser",
+ "iam:ListAccessKeys",
+ "iam:UpdateAccessKey",
+ ]
+ }
+}
+
+data "aws_iam_policy_document" "manage_credentials" {
+ statement {
+ sid = "ManageOwnAccessKeys"
+ effect = "Allow"
+ resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, "*")]
+ # resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, local.account_id) ]
+ # resources = ["arn:${data.aws_arn.current.partition}:iam::*:user/$${aws:username}"]
+ actions = [
+ "iam:CreateAccessKey",
+ "iam:DeleteAccessKey",
+ "iam:GetAccessKeyLastUsed",
+ "iam:GetUser",
+ "iam:ListAccessKeys",
+ "iam:UpdateAccessKey",
+ ]
+ }
+ statement {
+ sid = "ManageOwnPasswordGet"
+ effect = "Allow"
+ resources = ["*"]
+ actions = ["iam:GetAccountPasswordPolicy"]
+ }
+ statement {
+ sid = "ManageOwnPasswordChange"
+ effect = "Allow"
+ resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, "*")]
+ # resources = [format("arn:%v:iam::%v:user/$${aws:username}", data.aws_arn.current.partition, local.account_id) ]
+ # resources = ["arn:${data.aws_arn.current.partition}:iam::*:user/$${aws:username}"]
+ actions = ["iam:ChangePassword"]
+ }
+}
+
+data "aws_iam_policy_document" "deny_billing" {
+ statement {
+ sid = "DenyCensusBillingAndCostManagement"
+ effect = "Deny"
+ resources = ["*"]
+
+ actions = [
+ "aws-portal:*",
+ ]
+ }
+}
+
+
+#---
+# sts (for roles)
+#---
+data "aws_iam_policy_document" "ec2_assume" {
+ statement {
+ sid = "AWSEC2AssumeRole"
+ effect = "Allow"
+ actions = ["sts:AssumeRole"]
+
+ principals {
+ type = "Service"
+ identifiers = ["ec2.amazonaws.com"]
+ }
+ }
+}
+
+data "aws_iam_policy_document" "sts_assume" {
+ statement {
+ sid = "STSAssumeRole"
+ effect = "Allow"
+ actions = ["sts:AssumeRole"]
+ resources = ["*"]
+ }
+}
+
+data "aws_iam_policy_document" "root_assume" {
+ statement {
+ sid = "STSAssumeRole"
+ effect = "Allow"
+ actions = ["sts:AssumeRole"]
+
+ principals {
+ type = "AWS"
+ identifiers = [format("arn:%v:iam::%v:root", data.aws_arn.current.partition, local.account_id)]
+ # identifiers = ["arn:${data.aws_arn.current.partition}:iam::${local.account_id}:root"]
+ }
+ }
+}
+
+#----
+# STS: lambda assume
+#---
+data "aws_iam_policy_document" "lambda_assume" {
+ statement {
+ sid = "LambdaAssumeRole"
+ effect = "Allow"
+ actions = ["sts:AssumeRole"]
+
+ principals {
+ type = "Service"
+ identifiers = ["lambda.amazonaws.com"]
+ }
+ }
+}
diff --git a/iam-general-policies/prefixes.tf b/iam-general-policies/prefixes.tf
new file mode 120000
index 0000000..7e265d5
--- /dev/null
+++ b/iam-general-policies/prefixes.tf
@@ -0,0 +1 @@
+../common/prefixes.tf
\ No newline at end of file
diff --git a/iam-general-policies/variables.common.tf b/iam-general-policies/variables.common.tf
new file mode 120000
index 0000000..7439ed8
--- /dev/null
+++ b/iam-general-policies/variables.common.tf
@@ -0,0 +1 @@
+../common/variables.common.tf
\ No newline at end of file
diff --git a/iam-general-policies/variables.tf b/iam-general-policies/variables.tf
new file mode 100644
index 0000000..ba9024d
--- /dev/null
+++ b/iam-general-policies/variables.tf
@@ -0,0 +1,20 @@
+## variable "bucket_name" {
+## description = "VPC Flow Logs S3 bucket name"
+## type = string
+## # default = "inf-flowlogs-{{ tf_account }}-{{ region }}"
+## # default = "inf-flowlogs-{{ tf_account }}"
+## default = ""
+## }
+##
+## variable "bucket_name_prefix" {
+## # description = "VPC Flow Logs S3 bucket prefix, prepended to the AWS account ID and region to make the bucket name."
+## description = "VPC Flow Logs S3 bucket prefix, prepended to the AWS account ID to make the bucket name."
+## type = string
+## default = "inf-flowlogs"
+## }
+
+variable "component_tags" {
+ description = "Additional tags for Components (policy)"
+ type = map(map(string))
+ default = { "policy" = {} }
+}
diff --git a/iam-general-policies/version.tf b/iam-general-policies/version.tf
new file mode 120000
index 0000000..b83c5b7
--- /dev/null
+++ b/iam-general-policies/version.tf
@@ -0,0 +1 @@
+../common/version.tf
\ No newline at end of file