mirror of
https://github.com/ghndrx/terraform-foundation.git
synced 2026-02-10 06:45:06 +00:00
feat: Terraform Foundation - AWS Landing Zone
Enterprise-grade multi-tenant AWS cloud foundation. Modules: - GitHub OIDC for keyless CI/CD authentication - IAM account settings and security baseline - AWS Config Rules for compliance - ABAC (Attribute-Based Access Control) - SCPs (Service Control Policies) Features: - Multi-account architecture - Cost optimization patterns - Security best practices - Comprehensive documentation Tech: Terraform, AWS Organizations, IAM Identity Center
This commit is contained in:
248
terraform/modules/github-oidc/variables.tf
Normal file
248
terraform/modules/github-oidc/variables.tf
Normal file
@@ -0,0 +1,248 @@
|
||||
################################################################################
|
||||
# GitHub OIDC Module - Variables
|
||||
# With AWS/Terraform/Security Best Practices Validation
|
||||
################################################################################
|
||||
|
||||
variable "create_provider" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Create the OIDC provider. Set false if already exists in account."
|
||||
}
|
||||
|
||||
variable "provider_arn" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Existing OIDC provider ARN (required if create_provider = false)"
|
||||
|
||||
validation {
|
||||
condition = var.provider_arn == "" || can(regex("^arn:aws:iam::[0-9]{12}:oidc-provider/", var.provider_arn))
|
||||
error_message = "Provider ARN must be a valid IAM OIDC provider ARN."
|
||||
}
|
||||
}
|
||||
|
||||
variable "github_org" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "GitHub organization. If set, prepended to repos that don't include org."
|
||||
|
||||
validation {
|
||||
condition = var.github_org == "" || can(regex("^[a-zA-Z0-9][a-zA-Z0-9-]*$", var.github_org))
|
||||
error_message = "GitHub org must be alphanumeric with hyphens (no leading hyphen)."
|
||||
}
|
||||
}
|
||||
|
||||
variable "name_prefix" {
|
||||
type = string
|
||||
default = "github"
|
||||
description = "Prefix for IAM role names"
|
||||
|
||||
validation {
|
||||
condition = can(regex("^[a-zA-Z][a-zA-Z0-9-_]*$", var.name_prefix))
|
||||
error_message = "Name prefix must start with letter, contain only alphanumeric, hyphens, underscores."
|
||||
}
|
||||
}
|
||||
|
||||
variable "path" {
|
||||
type = string
|
||||
default = "/github-actions/"
|
||||
description = "IAM path for roles (enables easier permission boundaries)"
|
||||
|
||||
validation {
|
||||
condition = can(regex("^/[a-zA-Z0-9/_-]*/$", var.path))
|
||||
error_message = "IAM path must start and end with /, contain only alphanumeric, /, -, _."
|
||||
}
|
||||
}
|
||||
|
||||
variable "permissions_boundary" {
|
||||
type = string
|
||||
default = null
|
||||
description = "ARN of permissions boundary to attach to roles (RECOMMENDED for defense-in-depth)"
|
||||
|
||||
validation {
|
||||
condition = var.permissions_boundary == null || can(regex("^arn:aws:iam::[0-9]{12}:policy/", var.permissions_boundary))
|
||||
error_message = "Permissions boundary must be a valid IAM policy ARN."
|
||||
}
|
||||
}
|
||||
|
||||
variable "require_permissions_boundary" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Require a permissions boundary to be set (security guardrail)"
|
||||
}
|
||||
|
||||
variable "max_session_hours_limit" {
|
||||
type = number
|
||||
default = 4
|
||||
description = "Maximum allowed session duration in hours (caps role max_session_hours)"
|
||||
|
||||
validation {
|
||||
condition = var.max_session_hours_limit >= 1 && var.max_session_hours_limit <= 12
|
||||
error_message = "Max session hours must be between 1 and 12."
|
||||
}
|
||||
}
|
||||
|
||||
variable "deny_wildcard_repos" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Deny roles that allow all repos (*). Set false only if using workflow_ref restriction."
|
||||
}
|
||||
|
||||
variable "roles" {
|
||||
type = map(object({
|
||||
# Repository configuration
|
||||
repos = list(string) # GitHub repos (owner/repo or just repo if github_org set)
|
||||
branches = optional(list(string), []) # Branch restrictions (empty = all branches)
|
||||
tags = optional(list(string), []) # Tag restrictions (e.g., ["v*", "release-*"])
|
||||
environments = optional(list(string), []) # GitHub environment restrictions
|
||||
|
||||
# Event type restrictions
|
||||
pull_request = optional(bool, false) # Allow from pull_request events
|
||||
workflow_ref = optional(string, "") # Restrict to specific reusable workflow
|
||||
|
||||
# IAM configuration
|
||||
policy_arns = optional(list(string), []) # Managed policy ARNs to attach
|
||||
inline_policy = optional(string, "") # Inline policy JSON
|
||||
policy_statements = optional(list(object({ # Policy statements to generate
|
||||
sid = optional(string, "")
|
||||
effect = optional(string, "Allow")
|
||||
actions = list(string)
|
||||
resources = list(string)
|
||||
conditions = optional(list(object({
|
||||
test = string
|
||||
variable = string
|
||||
values = list(string)
|
||||
})), [])
|
||||
})), [])
|
||||
|
||||
# Session configuration
|
||||
max_session_hours = optional(number, 1) # Maximum session duration (1-12)
|
||||
|
||||
# Extra trust conditions
|
||||
extra_conditions = optional(map(map(list(string))), {}) # Additional assume role conditions
|
||||
}))
|
||||
default = {}
|
||||
description = "Map of role configurations for GitHub Actions"
|
||||
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for k, v in var.roles : length(v.repos) > 0
|
||||
])
|
||||
error_message = "Each role must specify at least one repository."
|
||||
}
|
||||
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for k, v in var.roles : v.max_session_hours >= 1 && v.max_session_hours <= 12
|
||||
])
|
||||
error_message = "Role max_session_hours must be between 1 and 12."
|
||||
}
|
||||
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for k, v in var.roles : alltrue([
|
||||
for repo in v.repos : can(regex("^[a-zA-Z0-9][a-zA-Z0-9-_.]*/[a-zA-Z0-9][a-zA-Z0-9-_.]*$|^[a-zA-Z0-9][a-zA-Z0-9-_.]*$|^\\*$", repo))
|
||||
])
|
||||
])
|
||||
error_message = "Repository names must be valid GitHub repo format (owner/repo or repo)."
|
||||
}
|
||||
}
|
||||
|
||||
# Pre-built role templates
|
||||
variable "terraform_deploy_role" {
|
||||
type = object({
|
||||
enabled = optional(bool, false)
|
||||
repos = optional(list(string), [])
|
||||
branches = optional(list(string), ["main"])
|
||||
environments = optional(list(string), [])
|
||||
state_bucket = optional(string, "")
|
||||
state_bucket_key_prefix = optional(string, "*") # Limit to specific paths
|
||||
dynamodb_table = optional(string, "")
|
||||
allowed_services = optional(list(string), []) # Limit to specific AWS services
|
||||
denied_actions = optional(list(string), [ # Explicit denies for safety
|
||||
"iam:CreateUser",
|
||||
"iam:CreateAccessKey",
|
||||
"iam:DeleteAccountPasswordPolicy",
|
||||
"organizations:*",
|
||||
"account:*"
|
||||
])
|
||||
})
|
||||
default = {}
|
||||
description = "Pre-configured role for Terraform deployments"
|
||||
}
|
||||
|
||||
variable "ecr_push_role" {
|
||||
type = object({
|
||||
enabled = optional(bool, false)
|
||||
repos = optional(list(string), [])
|
||||
branches = optional(list(string), ["main"])
|
||||
ecr_repos = optional(list(string), []) # Specific ECR repos (no default wildcard)
|
||||
allow_create = optional(bool, false)
|
||||
allow_delete = optional(bool, false) # Explicit opt-in for delete
|
||||
})
|
||||
default = {}
|
||||
description = "Pre-configured role for ECR push operations"
|
||||
|
||||
validation {
|
||||
condition = !try(var.ecr_push_role.enabled, false) || length(try(var.ecr_push_role.ecr_repos, [])) > 0
|
||||
error_message = "ECR push role requires explicit ecr_repos list (no wildcards for security)."
|
||||
}
|
||||
}
|
||||
|
||||
variable "s3_deploy_role" {
|
||||
type = object({
|
||||
enabled = optional(bool, false)
|
||||
repos = optional(list(string), [])
|
||||
branches = optional(list(string), ["main"])
|
||||
bucket_arns = optional(list(string), [])
|
||||
allowed_prefixes = optional(list(string), ["*"]) # Limit to specific paths
|
||||
cloudfront_arns = optional(list(string), [])
|
||||
})
|
||||
default = {}
|
||||
description = "Pre-configured role for S3 static site deployments"
|
||||
|
||||
validation {
|
||||
condition = !try(var.s3_deploy_role.enabled, false) || length(try(var.s3_deploy_role.bucket_arns, [])) > 0
|
||||
error_message = "S3 deploy role requires explicit bucket_arns list."
|
||||
}
|
||||
}
|
||||
|
||||
variable "lambda_deploy_role" {
|
||||
type = object({
|
||||
enabled = optional(bool, false)
|
||||
repos = optional(list(string), [])
|
||||
branches = optional(list(string), ["main"])
|
||||
function_arns = optional(list(string), [])
|
||||
allow_create = optional(bool, false)
|
||||
allow_logs = optional(bool, true) # Allow CloudWatch Logs access
|
||||
})
|
||||
default = {}
|
||||
description = "Pre-configured role for Lambda deployments"
|
||||
|
||||
validation {
|
||||
condition = !try(var.lambda_deploy_role.enabled, false) || length(try(var.lambda_deploy_role.function_arns, [])) > 0
|
||||
error_message = "Lambda deploy role requires explicit function_arns list."
|
||||
}
|
||||
}
|
||||
|
||||
variable "enable_cloudtrail_logging" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Create CloudWatch metric alarms for OIDC role assumptions"
|
||||
}
|
||||
|
||||
variable "alarm_sns_topic_arn" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "SNS topic ARN for security alarms"
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
type = map(string)
|
||||
default = {}
|
||||
description = "Tags to apply to all resources"
|
||||
|
||||
validation {
|
||||
condition = !contains(keys(var.tags), "Name")
|
||||
error_message = "Name tag is auto-generated, do not specify in tags variable."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user