diff --git a/README.md b/README.md index 0351399..6d62d03 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,19 @@ Comment in these badges if they apply to the repository. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [accessors\_read\_write](#input\_accessors\_read\_write) | List of accessors that are allowed to read & write. | `list(string)` | `[]` | no | +| [access\_points](#input\_access\_points) | List of access points to create. |
map(object({
posix_user = optional(object({
gid = number
uid = number
secondary_gids = optional(list(number))
}))
root_directory = optional(object({
path = string
creation_info = optional(object({
owner_gid = number
owner_uid = number
permissions = string
}))
}))
})) | `{}` | no |
+| [aws\_iam\_principals](#input\_aws\_iam\_principals) | AWS IAM principals which will be allowed to access the file system via the EFS policy. | `list(string)` | `[]` | no |
| [bypass\_policy\_lockout\_safety\_check](#input\_bypass\_policy\_lockout\_safety\_check) | A flag to indicate whether to bypass the aws\_efs\_file\_system\_policy lockout safety check. | `bool` | `false` | no |
+| [enable\_customer\_managed\_kms](#input\_enable\_customer\_managed\_kms) | If enabled, will create a customer managed KMS key for at-rest encryption. | `bool` | `false` | no |
| [enable\_enhanced\_backups](#input\_enable\_enhanced\_backups) | Enable enhanced backups. | `bool` | `false` | no |
| [encrypted](#input\_encrypted) | If true, the disk will be encrypted. | `bool` | `true` | no |
+| [enforce\_read\_only\_default](#input\_enforce\_read\_only\_default) | Enforce read-only access to the file system. Identity-based policies can override these default permissions. | `bool` | `false` | no |
+| [enforce\_transit\_encryption](#input\_enforce\_transit\_encryption) | Enforce in-transit encryption for all clients. | `bool` | `true` | no |
+| [kms\_key\_id](#input\_kms\_key\_id) | The ARN of the AWS KMS to encrypt the file system. Defaults to the AWS managed KMS key. | `string` | `null` | no |
| [name](#input\_name) | The name of the file system. | `string` | n/a | yes |
| [performance\_mode](#input\_performance\_mode) | The file system performance mode. Can be either `generalPurpose` or `maxIO`. | `string` | `"generalPurpose"` | no |
+| [prevent\_anonymous\_access](#input\_prevent\_anonymous\_access) | Prevent anonymous access to the file system. | `bool` | `false` | no |
+| [prevent\_root\_access\_default](#input\_prevent\_root\_access\_default) | Prevent root access to the file system. Identity-based policies can override these default permissions. | `bool` | `false` | no |
| [private\_subnets](#input\_private\_subnets) | A list of private subnets inside the VPC. | `list(string)` | n/a | yes |
| [provisioned\_throughput\_in\_mibps](#input\_provisioned\_throughput\_in\_mibps) | The throughput, measured in MiB/s, that you want to provision for the file system. | `number` | `0` | no |
| [security\_groups](#input\_security\_groups) | A list of security group IDs to associate with the file system. | `list(string)` | n/a | yes |
@@ -78,12 +85,12 @@ Comment in these badges if they apply to the repository.
## Resources
-- resource.aws_efs_file_system.main (main.tf#1)
-- resource.aws_efs_file_system_policy.main (main.tf#44)
-- resource.aws_efs_mount_target.main (main.tf#37)
-- resource.random_uuid.main (main.tf#52)
-- data source.aws_caller_identity.current (data.tf#1)
-- data source.aws_iam_policy_document.main (data.tf#3)
+- resource.aws_efs_access_point.main (main.tf#44)
+- resource.aws_efs_file_system.main (main.tf#3)
+- resource.aws_efs_file_system_policy.main (main.tf#37)
+- resource.aws_efs_mount_target.main (main.tf#28)
+- resource.random_uuid.main (main.tf#1)
+- data source.aws_iam_policy_document.main (data.tf#1)
# Examples
### Basic Example
diff --git a/data.tf b/data.tf
index 6f3e52e..ca68e27 100644
--- a/data.tf
+++ b/data.tf
@@ -1,28 +1,50 @@
-data "aws_caller_identity" "current" {}
-
data "aws_iam_policy_document" "main" {
- statement {
- sid = "Allow Access to EFS"
- effect = "Allow"
- resources = [aws_efs_file_system.main.arn]
-
- actions = [
- "elasticfilesystem:ClientMount",
- "elasticfilesystem:ClientWrite",
- ]
-
- condition {
- test = "Bool"
- variable = "aws:SecureTransport"
- values = ["true"]
+ dynamic "statement" {
+ for_each = [true]
+
+ content {
+ sid = "AccessRules"
+ resources = [aws_efs_file_system.main.arn]
+ effect = "Allow"
+
+ principals {
+ type = "AWS"
+ identifiers = var.aws_iam_principals
+ }
+
+ actions = compact([
+ !var.prevent_root_access_default ? "elasticfilesystem:ClientRootAccess" : null,
+ !var.enforce_read_only_default ? "elasticfilesystem:ClientWrite" : null,
+ !var.prevent_anonymous_access ? "elasticfilesystem:ClientMount" : null,
+ ])
+
+ condition {
+ test = "Bool"
+ variable = "elasticfilesystem:AccessedViaMountTarget"
+ values = ["true"]
+ }
}
+ }
+
+ dynamic "statement" {
+ for_each = var.enforce_transit_encryption ? [true] : []
+
+ content {
+ sid = "EnforceInTransitEncryption"
+ resources = [aws_efs_file_system.main.arn]
+ effect = "Deny"
+ actions = ["*"]
+
+ principals {
+ type = "AWS"
+ identifiers = ["*"]
+ }
- principals {
- type = "AWS"
- identifiers = concat(
- ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"],
- var.accessors_read_write
- )
+ condition {
+ test = "Bool"
+ variable = "aws:SecureTransport"
+ values = ["false"]
+ }
}
}
}
diff --git a/main.tf b/main.tf
index c245d3d..54dc61a 100644
--- a/main.tf
+++ b/main.tf
@@ -1,21 +1,15 @@
-resource "aws_efs_file_system" "main" {
+resource "random_uuid" "main" {}
- # Creation token
+resource "aws_efs_file_system" "main" {
creation_token = random_uuid.main.result
# Encryption
- encrypted = var.encrypted
-
- # KMS
- kms_key_id = module.kms.key_arn
+ encrypted = var.encrypted
+ kms_key_id = var.enable_customer_managed_kms ? module.kms[0].key_arn : var.kms_key_id
- # Performance Mode
- performance_mode = var.performance_mode
-
- # Throughput mode
- throughput_mode = var.throughput_mode
-
- # Throughput provision
+ # Performance
+ performance_mode = var.performance_mode
+ throughput_mode = var.throughput_mode
provisioned_throughput_in_mibps = var.provisioned_throughput_in_mibps
lifecycle_policy {
@@ -26,17 +20,16 @@ resource "aws_efs_file_system" "main" {
transition_to_primary_storage_class = var.transition_to_primary_storage_class
}
- tags = merge(
- var.tags,
- {
- "Name" = var.name
- }
- )
+ tags = merge(var.tags, {
+ "Name" = var.name
+ })
}
resource "aws_efs_mount_target" "main" {
- count = length(var.private_subnets)
- file_system_id = aws_efs_file_system.main.id
+ count = length(var.private_subnets)
+
+ file_system_id = aws_efs_file_system.main.id
+
security_groups = var.security_groups
subnet_id = var.private_subnets[count.index]
}
@@ -44,12 +37,47 @@ resource "aws_efs_mount_target" "main" {
resource "aws_efs_file_system_policy" "main" {
file_system_id = aws_efs_file_system.main.id
+ policy = data.aws_iam_policy_document.main.json
bypass_policy_lockout_safety_check = var.bypass_policy_lockout_safety_check
-
- policy = data.aws_iam_policy_document.main.json
}
-resource "random_uuid" "main" {}
+resource "aws_efs_access_point" "main" {
+ for_each = var.access_points
+
+ file_system_id = aws_efs_file_system.main.id
+
+ dynamic "posix_user" {
+ for_each = each.value.posix_user != null ? [each.value.posix_user] : []
+
+ content {
+ uid = posix_user.value.uid
+ gid = posix_user.value.gid
+ secondary_gids = posix_user.value.secondary_gids
+ }
+ }
+
+ dynamic "root_directory" {
+ for_each = each.value.root_directory != null ? [each.value.root_directory] : []
+
+ content {
+ path = root_directory.value.path
+
+ dynamic "creation_info" {
+ for_each = root_directory.value.creation_info != null ? [root_directory.value.creation_info] : []
+
+ content {
+ owner_uid = creation_info.value.owner_uid
+ owner_gid = creation_info.value.owner_gid
+ permissions = creation_info.value.permissions
+ }
+ }
+ }
+ }
+
+ tags = merge(var.tags, {
+ "Name" = "${var.name}-${each.key}"
+ })
+}
module "backup" {
count = var.enable_enhanced_backups ? 1 : 0
@@ -60,16 +88,18 @@ module "backup" {
vault_name = var.name
backup_name = var.name
- resources = [
- aws_efs_file_system.main.arn
- ]
+ service = "efs"
+ resources = [aws_efs_file_system.main.arn]
- service = "efs"
+ tags = var.tags
}
module "kms" {
+ count = var.enable_customer_managed_kms ? 1 : 0
+
source = "geekcell/kms/aws"
version = ">= 1.0.0, < 2.0.0"
alias = format("alias/efs/%s", var.name)
+ tags = var.tags
}
diff --git a/variables.tf b/variables.tf
index 1b1878b..bb95891 100644
--- a/variables.tf
+++ b/variables.tf
@@ -24,6 +24,18 @@ variable "encrypted" {
type = bool
}
+variable "kms_key_id" {
+ description = "The ARN of the AWS KMS to encrypt the file system. Defaults to the AWS managed KMS key."
+ default = null
+ type = string
+}
+
+variable "enable_customer_managed_kms" {
+ description = "If enabled, will create a customer managed KMS key for at-rest encryption."
+ default = false
+ type = bool
+}
+
variable "name" {
description = "The name of the file system."
type = string
@@ -69,8 +81,54 @@ variable "transition_to_primary_storage_class" {
type = string
}
-variable "accessors_read_write" {
+variable "access_points" {
+ default = {}
+ description = "List of access points to create."
+ type = map(object({
+ posix_user = optional(object({
+ gid = number
+ uid = number
+ secondary_gids = optional(list(number))
+ }))
+
+ root_directory = optional(object({
+ path = string
+
+ creation_info = optional(object({
+ owner_gid = number
+ owner_uid = number
+ permissions = string
+ }))
+ }))
+ }))
+}
+
+variable "aws_iam_principals" {
+ description = "AWS IAM principals which will be allowed to access the file system via the EFS policy."
default = []
- description = "List of accessors that are allowed to read & write."
type = list(string)
}
+
+variable "prevent_root_access_default" {
+ description = "Prevent root access to the file system. Identity-based policies can override these default permissions."
+ default = false
+ type = bool
+}
+
+variable "enforce_read_only_default" {
+ description = "Enforce read-only access to the file system. Identity-based policies can override these default permissions."
+ default = false
+ type = bool
+}
+
+variable "prevent_anonymous_access" {
+ description = "Prevent anonymous access to the file system."
+ default = false
+ type = bool
+}
+
+variable "enforce_transit_encryption" {
+ description = "Enforce in-transit encryption for all clients."
+ default = true
+ type = bool
+}