# ═══════════════════════════════════════════════════════════════════════════ # Terraform: aamos-ledger # Mål: Reproducerbar infrastruktur för bokföringsmotorn # ═══════════════════════════════════════════════════════════════════════════ terraform { required_version = ">= 1.5" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } # TODO: Konfigurera remote state (S3 + DynamoDB) # backend "s3" { # bucket = "aamos-terraform-state" # key = "aamos-ledger/terraform.tfstate" # region = "eu-north-1" # encrypt = true # dynamodb_table = "terraform-locks" # } } provider "aws" { region = var.aws_region default_tags { tags = { Project = "aamos-ledger" ManagedBy = "terraform" Environment = var.environment } } } # ═══════════════════════════════════════════════════════════════════════════ # Variabler # ═══════════════════════════════════════════════════════════════════════════ variable "aws_region" { description = "AWS-region" type = string default = "eu-north-1" } variable "environment" { description = "Miljö (staging/production)" type = string default = "staging" validation { condition = contains(["staging", "production"], var.environment) error_message = "Miljön måste vara staging eller production." } } variable "instance_type" { description = "EC2-instansstorlek" type = string default = "t4g.medium" } # ═══════════════════════════════════════════════════════════════════════════ # Datakällor # ═══════════════════════════════════════════════════════════════════════════ data "aws_vpc" "default" { default = true } data "aws_subnets" "default" { filter { name = "vpc-id" values = [data.aws_vpc.default.id] } } # ═══════════════════════════════════════════════════════════════════════════ # Secrets Manager — INTE i klartext # ═══════════════════════════════════════════════════════════════════════════ resource "aws_secretsmanager_secret" "ledger_jwt" { name = "aamos-ledger/${var.environment}/jwt-secret" description = "JWT-signeringsnyckel för aamos-ledger" recovery_window_in_days = 7 tags = { Rotation = "true" } } resource "aws_secretsmanager_secret" "ledger_internal" { name = "aamos-ledger/${var.environment}/internal-token" description = "Service-to-service token för aamos-ledger" recovery_window_in_days = 7 } resource "aws_secretsmanager_secret" "ledger_db" { name = "aamos-ledger/${var.environment}/database-url" description = "Databasanslutning för aamos-ledger" recovery_window_in_days = 7 } resource "aws_secretsmanager_secret" "ledger_redis" { name = "aamos-ledger/${var.environment}/redis-url" description = "Redis-anslutning för aamos-ledger" recovery_window_in_days = 7 } # ═══════════════════════════════════════════════════════════════════════════ # IAM — Minimala rättigheter # ═══════════════════════════════════════════════════════════════════════════ resource "aws_iam_role" "ledger_ec2" { name = "aamos-ledger-${var.environment}-ec2" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] }) } resource "aws_iam_role_policy" "ledger_secrets" { name = "aamos-ledger-${var.environment}-secrets" role = aws_iam_role.ledger_ec2.id policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = [ "secretsmanager:GetSecretValue" ] Resource = [ aws_secretsmanager_secret.ledger_jwt.arn, aws_secretsmanager_secret.ledger_internal.arn, aws_secretsmanager_secret.ledger_db.arn, aws_secretsmanager_secret.ledger_redis.arn ] }] }) } resource "aws_iam_instance_profile" "ledger" { name = "aamos-ledger-${var.environment}" role = aws_iam_role.ledger_ec2.name } # ═══════════════════════════════════════════════════════════════════════════ # Security Group # ═══════════════════════════════════════════════════════════════════════════ resource "aws_security_group" "ledger" { name_prefix = "aamos-ledger-${var.environment}-" vpc_id = data.aws_vpc.default.id ingress { from_port = 3250 to_port = 3250 protocol = "tcp" cidr_blocks = ["10.0.0.0/8"] # TODO: Begränsa till ALB/NLB description = "aamos-ledger API" } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] description = "All outbound traffic" } lifecycle { create_before_destroy = true } } # ═══════════════════════════════════════════════════════════════════════════ # EC2-instans # ═══════════════════════════════════════════════════════════════════════════ resource "aws_instance" "ledger" { ami = data.aws_ami.amazon_linux_2023.id instance_type = var.instance_type iam_instance_profile = aws_iam_instance_profile.ledger.name vpc_security_group_ids = [aws_security_group.ledger.id] user_data = base64encode(templatefile("${path.module}/user-data.sh", { environment = var.environment secrets_arn = aws_secretsmanager_secret.ledger_jwt.arn })) tags = { Name = "aamos-ledger-${var.environment}" } # TODO: Lägg till EBS-kryptering # TODO: Lägg till CloudWatch övervakning } # ═══════════════════════════════════════════════════════════════════════════ # Outputs # ═══════════════════════════════════════════════════════════════════════════ output "instance_id" { description = "EC2-instans-ID" value = aws_instance.ledger.id } output "instance_ip" { description = "Privat IP-adress" value = aws_instance.ledger.private_ip } output "secrets_arns" { description = "ARN för Secrets Manager" value = { jwt = aws_secretsmanager_secret.ledger_jwt.arn internal = aws_secretsmanager_secret.ledger_internal.arn db = aws_secretsmanager_secret.ledger_db.arn redis = aws_secretsmanager_secret.ledger_redis.arn } }