DEV Community

Constantine Ukah
Constantine Ukah

Posted on

How to Secure Your AWS Web Application with Data Sovereignty, Encryption, and Availability in a Multi-Account Setup.

Introduction

As organizations move sensitive workloads to the cloud, ensuring compliance with regional data laws, availability SLAs, and strong encryption is no longer optional. In this post, I will walk through securing a web application hosted on AWS, leveraging Control Tower to structure a compliant multi-account environment.

Scenario

Imagine you have a financial or healthcare applications whose data MUST

  • Reside in a specific region or location,

  • Can't afford to be unavailable due to its function

  • Sensitive information like customers' biodata, credit/debit card information etc are stored.

  • Finally, when weekly or quarterly audit and compliance reports are required by your management or 3rd party auditors.

How do you achieve these with a single account. Hence, multi-account architecture and AWS Control Tower comes into play.

Solution Overview.

The web application will run inside the private subnets, meaning it cannot be directly accessed from the internet. Instead, traffic flows through a public Application Load Balancer (ALB), which forwards requests to EC2 instances hosted in private subnets. Outbound internet access, if needed (e.g., for package updates), is routed via a NAT Gateway.

The application is configured to listen on port 5000. However, an Nginx reverse proxy will be used to allow traffic received from the Load Balancer on port 80 while the Load Balancer would listen on port 443 from CloudFront.

The following AWS services would be used.

  • AWS Control Tower: For automated, governed multi-account setup.
  • AWS Organizations: To segment workloads into OUs (Organizational Units).
  • Service Control Policies (SCPs): To enforce the allowed regions and service boundaries.
  • AWS RAM & VPC Peering: For centralized networking across accounts.
  • Amazon S3 + AWS KMS: For encrypted data storage.
  • ALB + ACM: for TLS encryption and HTTPS access.
  • CloudFront + Route53: For scalable, globally available web access.
  • CloudTrail & Config: For centralized logging and auditing.

Multi-Account Structure

Using the AWS Control Tower, the OUs that would be created and their purposes are:

Multi-Account Structure

Image description

Enforcing Data Sovereignty

Restrict application/services usage or deployment to only the approved AWS region(s) using SCPs and then apply to the Production Organisational Unit (OU).

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRegionsOutsideN.Virginia",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Implementing End-to-End Encryption

To achieve robust end-to-end encryption, it's crucial to address both encryption at rest and encryption in transit. Configure encryption for your AWS resources, starting with customer-managed keys via AWS Key Management Service (KMS)

  • Configure a Customer-Managed Key (CMK) with AWS KMS First, you'll provision an AWS KMS Customer-Managed Key (CMK) that will be used for encrypting your data. This provides you with full control over the encryption key lifecycle.
resource "aws_kms_key" "encryp_key" {
  description             = "Encryption key for s3 bucket"
  key_usage               = "ENCRYPT_DECRYPT"
  enable_key_rotation     = true
  deletion_window_in_days = 7
}

data "aws_caller_identity" "current" {}

resource "aws_kms_key_policy" "encrypt_policy" {
  key_id = aws_kms_key.encryp_key.id
  policy = jsonencode({
    Version = "2012-10-17"
    Id      = "key-default-1"
    Statement = [
      {
        Sid    = "Allow the use of the key"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/<your delegated user>"
        },
        Action: [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
        ],
        Resource = "*"
      }
    ]
  })
}
Enter fullscreen mode Exit fullscreen mode

To ensure encryption end-to-end, then, encryption at rest and in transit must be implemented.

  • Encryption at rest ensures that your data is encrypted when it's stored in persistent storage, such as S3 buckets, databases, or EC2 volumes.

To ensure end-to-end encryption, you must implement encryption at rest for all sensitive data stores. For example, for an logging S3 bucket:

resource "aws_s3_bucket_server_side_encryption_configuration" "s3_sse_config" {
  bucket = aws_s3_bucket.s3-cloudlogs.id

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = var.key_id
      sse_algorithm     = "aws:kms"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Encryption in transit (or in-flight encryption) protects data as it moves between systems over networks. This is typically achieved using protocols like TLS/SSL. In this lab, a TLS certificate from Amazon Certificate Manager (ACM) will be attached to both the Application Load Balancer and CloudFront services with Route53 pointing to our customized domain.

Image description

Achieving High Availability

To ensure high availability of the application, we would

  • Deploy the application servers in multiple Availability zones.

  • Use Auto Scaling Groups for easy scalability.

  • Attach Application Load Balancer and CloudFront to handle even distribution of our user traffic and ensure global reach with low latency.

  • Finally, use Route53 to reroute traffic to our customized domain name.

Centralized Governance, Monitoring and Logging.

  • AWS Control Tower sets up CloudTrail and AWS Config in a Log Archive account.

  • Guardrails automatically apply mandatory SCPs and detect policy violations.

  • Use AWS Security Hub and GuardDuty in the Security account to detect threats across all accounts.

Conclusion.

Implementing a robust, compliant, and highly available web application in the cloud demands a thoughtful architectural approach. By leveraging AWS Control Tower for a governed multi-account structure, enforcing data sovereignty with SCPs, and meticulously applying end-to-end encryption and high availability patterns, organizations can confidently migrate sensitive workloads. This comprehensive strategy not only meets stringent regulatory requirements but also lays a solid foundation for secure, scalable, and auditable cloud operations.

Summary

This hands-on implementation validates my readiness to secure cloud web application with attention to reliability, security, and scalability.
Check out my github for the code and architectural diagram.

Top comments (0)