Back to blog
Security & Complianceintermediate

HIPAA on AWS: Rules, Business Associate Agreements & Covered Services

Understand HIPAA compliance on AWS — what PHI is, which AWS services are HIPAA-eligible, how to sign a BAA, and the technical safeguards every healthcare application must implement.

LearnixoApril 17, 202610 min read
HIPAAAWSHealthcarePHIComplianceSecurityBAA
Share:š•
AWS

What is HIPAA?

HIPAA (Health Insurance Portability and Accountability Act, 1996) is US federal law governing how Protected Health Information (PHI) is used, stored, and transmitted. Non-compliance penalties range from $100 to $1.9M per violation category per year.

Who must comply: | Entity | Examples | |--------|---------| | Covered Entities | Hospitals, clinics, health insurance companies, pharmacies | | Business Associates (BA) | Cloud providers, software vendors, billing services — anyone who handles PHI on behalf of a covered entity | | Subcontractors | Any vendor a BA uses who also touches PHI |

As a software developer building healthcare apps, your company is almost certainly a Business Associate.


What is PHI?

Protected Health Information is individually identifiable health information — any data that can link a person to their health condition or medical care.

The 18 HIPAA Identifiers

Any of these, when combined with health information, creates PHI:

  1. Names
  2. Geographic data (anything smaller than a state — addresses, ZIP codes, county)
  3. Dates (birth dates, admission dates, discharge dates, death dates)
  4. Phone numbers
  5. Fax numbers
  6. Email addresses
  7. Social Security Numbers
  8. Medical record numbers
  9. Health plan beneficiary numbers
  10. Account numbers
  11. Certificate/license numbers
  12. Vehicle identifiers and serial numbers (VINs)
  13. Device identifiers and serial numbers
  14. Web URLs
  15. IP addresses
  16. Biometric identifiers (fingerprints, voice prints)
  17. Full-face photographs and comparable images
  18. Any other unique identifying number or code

Rule of thumb: If you can figure out who the patient is from the data, it's PHI. Encrypt it, audit access to it, and delete it on schedule.


The HIPAA Security Rule: Technical Safeguards

The Security Rule specifies technical controls for electronic PHI (ePHI):

| Safeguard | Requirement | |-----------|------------| | Access Controls | Assign unique user IDs, automatic logoff, encryption/decryption | | Audit Controls | Record and examine access and activity | | Integrity | Protect ePHI from improper alteration or destruction | | Transmission Security | Encrypt ePHI in transit (TLS 1.2+) |


AWS and the Business Associate Agreement (BAA)

AWS is a Business Associate. Before you can store or process PHI on AWS, you must sign a BAA with Amazon.

Signing the AWS BAA

  1. Go to AWS Artifact in the AWS Console
  2. Navigate to Agreements → AWS Business Associate Addendum
  3. Accept the agreement

The BAA covers your entire AWS account. You sign it once — it applies to all covered services in that account.

Critical: The BAA only covers HIPAA-eligible AWS services. Using non-covered services for PHI violates the BAA. AWS publishes the full list at aws.amazon.com/compliance/hipaa-eligible-services-reference.

HIPAA-Eligible AWS Services (Key Ones)

| Service | Use Case | |---------|---------| | Amazon EC2 | Application servers, managed EC2 workloads | | Amazon RDS | PostgreSQL, MySQL, SQL Server databases | | Amazon Aurora | High-performance managed SQL | | Amazon DynamoDB | NoSQL, key-value and document storage | | Amazon S3 | File storage (medical images, documents, exports) | | Amazon S3 Glacier | Long-term archival | | Amazon ECS / EKS | Container orchestration | | AWS Lambda | Serverless compute | | Amazon API Gateway | HTTP API endpoints | | Amazon SQS | Message queuing | | Amazon SNS | Notifications and pub/sub | | Amazon SES | Sending email (e.g., appointment confirmations) | | AWS KMS | Key management for encryption | | AWS Secrets Manager | Secret storage | | AWS CloudTrail | API audit logging | | Amazon CloudWatch | Logs, metrics, alarms | | AWS WAF | Web application firewall | | Amazon Cognito | User authentication | | Amazon Comprehend Medical | Clinical NLP | | Amazon HealthLake | FHIR-compliant data store |

Services NOT Covered by the BAA

  • Amazon CloudFront (at time of writing — check current list)
  • AWS AppSync (check current list)
  • Free-tier services generally

Always check the official AWS list before using a service for PHI. The list is updated as AWS adds HIPAA coverage.


Architectural Boundaries: What Counts as PHI in Your System

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                        PHI Boundary                              │
│                                                                  │
│  Patient name + DOB + diagnosis → PHI                           │
│  Patient name + appointment date → PHI                          │
│  Appointment ID alone → NOT PHI (no individual link)            │
│  IP address + health forum post → PHI                           │
│  De-identified stats → NOT PHI (if Safe Harbor method applied)  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Core Technical Requirements

1. Encryption at Rest

All ePHI at rest must be encrypted. AWS provides this through KMS:

HCL
# Terraform: RDS with KMS encryption
resource "aws_kms_key" "rds" {
  description             = "RDS PHI encryption key"
  deletion_window_in_days = 30
  enable_key_rotation     = true   # Annual rotation

  tags = { Purpose = "phi-encryption" }
}

resource "aws_db_instance" "postgres" {
  identifier        = "hipaa-prod-db"
  engine            = "postgres"
  engine_version    = "16"
  instance_class    = "db.t3.medium"
  allocated_storage = 100
  storage_encrypted = true          # Encryption at rest
  kms_key_id        = aws_kms_key.rds.arn

  backup_retention_period   = 35    # Minimum 7 days; 35 for compliance
  deletion_protection       = true
  skip_final_snapshot       = false
  final_snapshot_identifier = "hipaa-prod-final-snapshot"

  # Enhanced monitoring for audit evidence
  monitoring_interval = 60
  monitoring_role_arn = aws_iam_role.rds_monitoring.arn
}

# S3 for medical documents
resource "aws_s3_bucket_server_side_encryption_configuration" "phi" {
  bucket = aws_s3_bucket.phi_documents.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.s3.arn
    }
    bucket_key_enabled = true
  }
}

2. Encryption in Transit

All PHI transmission must be over TLS 1.2 or higher:

HCL
# Enforce TLS on S3 bucket
resource "aws_s3_bucket_policy" "enforce_tls" {
  bucket = aws_s3_bucket.phi_documents.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "DenyNonTLS"
      Effect    = "Deny"
      Principal = "*"
      Action    = "s3:*"
      Resource  = ["${aws_s3_bucket.phi_documents.arn}/*"]
      Condition = {
        Bool = { "aws:SecureTransport" = "false" }
      }
    }]
  })
}

# API Gateway: only TLS 1.2+
resource "aws_api_gateway_domain_name" "api" {
  domain_name              = "api.healthcare.example.com"
  regional_certificate_arn = aws_acm_certificate.api.arn
  security_policy          = "TLS_1_2"
}

3. Access Controls: Minimum Necessary

Only allow access to PHI that is required to perform a specific function:

HCL
# IAM policy: Lambda can only access specific RDS and S3 paths
data "aws_iam_policy_document" "phi_access" {
  # Only read patient records — no admin operations
  statement {
    actions = [
      "rds-data:ExecuteStatement",
      "rds-data:BatchExecuteStatement"
    ]
    resources = [aws_rds_cluster.postgres.arn]
  }

  # Only access PHI documents bucket with specific prefix
  statement {
    actions   = ["s3:GetObject", "s3:PutObject"]
    resources = ["${aws_s3_bucket.phi_documents.arn}/patients/*"]
  }

  # KMS decrypt/encrypt for the specific key only
  statement {
    actions = ["kms:Decrypt", "kms:GenerateDataKey"]
    resources = [aws_kms_key.phi.arn]
  }
}

4. Audit Logging with CloudTrail

HIPAA requires audit logs of all PHI access:

HCL
# CloudTrail: log all S3 PHI access
resource "aws_cloudtrail" "phi_access" {
  name                          = "phi-access-trail"
  s3_bucket_name                = aws_s3_bucket.cloudtrail_logs.id
  include_global_service_events = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true   # Detect tampered logs
  kms_key_id                    = aws_kms_key.cloudtrail.arn

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type   = "AWS::S3::Object"
      values = ["${aws_s3_bucket.phi_documents.arn}/"]
    }
  }

  # DynamoDB PHI access
  advanced_event_selector {
    name = "DynamoDB PHI Data Events"
    field_selector {
      field  = "eventCategory"
      equals = ["Data"]
    }
    field_selector {
      field  = "resources.ARN"
      starts_with = [aws_dynamodb_table.patients.arn]
    }
  }
}

5. Automatic Logoff and Session Management

C#
// .NET: HIPAA-compliant session timeout (15 minutes max)
builder.Services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
    options.SlidingExpiration = false;   // No extensions — hard timeout
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.HttpOnly = true;
    options.Cookie.SameSite = SameSiteMode.Strict;
});

Network Architecture: Defense in Depth

Internet
    │
    ā–¼
AWS WAF (block common attacks)
    │
    ā–¼
Application Load Balancer (TLS termination, access logs)
    │
    ā–¼
Private Subnet: Application Servers (ECS/Lambda)
    │
    ā–¼
Private Subnet: RDS PostgreSQL (no public access)
    │
    ā–¼
Private Subnet: ElastiCache Redis (sessions, cache)

All traffic: VPC Security Groups + NACLs
No public IP on any database
NAT Gateway for outbound only
HCL
# VPC with no public subnets for PHI resources
resource "aws_vpc" "hipaa" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = { Name = "hipaa-vpc", HIPAA = "true" }
}

# RDS subnet group — private subnets only
resource "aws_db_subnet_group" "private" {
  name       = "hipaa-db-private"
  subnet_ids = aws_subnet.private[*].id
}

# Security group: RDS only accepts traffic from app layer
resource "aws_security_group" "rds" {
  name   = "hipaa-rds-sg"
  vpc_id = aws_vpc.hipaa.id

  ingress {
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.app.id]   # Only from app SG
  }

  egress {
    from_port = 0; to_port = 0; protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Monitoring and Breach Detection

HCL
# CloudWatch alarm: unusual access patterns
resource "aws_cloudwatch_metric_alarm" "phi_access_spike" {
  alarm_name          = "phi-unusual-access-volume"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "NumberOfObjects"
  namespace           = "AWS/S3"
  period              = 300
  statistic           = "Sum"
  threshold           = 1000   # Alert if >1000 S3 objects accessed in 5min
  alarm_description   = "Unusual PHI access volume — potential breach"
  alarm_actions       = [aws_sns_topic.security_alerts.arn]
}

# GuardDuty for threat detection (recommended for HIPAA)
resource "aws_guardduty_detector" "main" {
  enable = true

  datasources {
    s3_logs { enable = true }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes { enable = true }
      }
    }
  }
}

HIPAA Compliance Checklist

Technical Safeguards

  • [ ] All ePHI encrypted at rest (KMS keys with annual rotation)
  • [ ] All ePHI encrypted in transit (TLS 1.2 minimum)
  • [ ] Unique user IDs — no shared accounts
  • [ ] 15-minute automatic session timeout
  • [ ] Audit logs of all PHI access (CloudTrail, application logs)
  • [ ] Audit logs retained 6 years, tamper-evident
  • [ ] Emergency access procedure documented
  • [ ] Minimum necessary access enforced (IAM least privilege)

Operational Safeguards

  • [ ] BAA signed with AWS
  • [ ] BAA signed with all other vendors who touch PHI
  • [ ] Workforce training records maintained
  • [ ] Access termination procedure documented
  • [ ] Incident response plan (60-day breach notification window)
  • [ ] Disaster recovery tested annually
  • [ ] Risk assessment conducted and documented

AWS Specific

  • [ ] Only HIPAA-eligible AWS services used for PHI
  • [ ] CloudTrail enabled in all regions
  • [ ] AWS Config enabled for compliance monitoring
  • [ ] GuardDuty enabled for threat detection
  • [ ] VPC flow logs enabled
  • [ ] No PHI in CloudFront logs, Route 53 logs (check current BAA coverage)
  • [ ] MFA enabled for all AWS console access

Common Mistakes

Mistake 1: Storing PHI in CloudWatch Logs without thinking Application logs often contain PHI (patient IDs, names in error messages). Sanitise logs before they're emitted, or encrypt the CloudWatch log group with KMS.

Mistake 2: PHI in URL query strings Query strings appear in CloudFront/ALB access logs. GET /patients?name=alice&dob=1990-01-01 is a PHI leak. Use POST body or path params where possible.

Mistake 3: Assuming AWS is responsible for compliance AWS provides compliant infrastructure. Your application must implement access controls, audit logging, and encryption. Shared responsibility model — AWS secures the cloud, you secure what's in it.

Mistake 4: Not testing PHI deletion HIPAA requires a minimum retention of 6 years. But when the retention period ends, you must be able to prove data was deleted. Test your deletion workflows.


Summary

| Requirement | AWS Solution | |-------------|-------------| | Encryption at rest | KMS + RDS encryption, S3 SSE-KMS | | Encryption in transit | ACM certificates, TLS policy on API GW | | Audit logging | CloudTrail data events + CloudWatch | | Access control | IAM least privilege, Security Groups | | Breach detection | GuardDuty, CloudWatch anomaly alarms | | Compliance evidence | AWS Config, CloudTrail log integrity | | BAA | AWS Artifact → Business Associate Addendum |

Next up: PHI Encryption — At-Rest and In-Transit on AWS with column-level encryption.

Enjoyed this article?

Explore the Security & Compliance learning path for more.

Found this helpful?

Share:š•

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.