Security Architecture
Overview
Security is fundamental to AWS Lens's design. This document describes the comprehensive security controls, compliance frameworks, and best practices implemented to protect customer data and ensure platform integrity.
Security Principles
1. Defense in Depth
Multiple layers of security controls to protect against various threat vectors
2. Least Privilege
Users and systems granted minimum permissions necessary for their functions
3. Zero Trust
Never trust, always verify - authentication and authorization at every layer
4. Encryption Everywhere
Data encrypted in transit and at rest using industry-standard algorithms
5. Audit Everything
Comprehensive logging and monitoring of all security-relevant events
Security Layers
Network Security
DDoS Protection
AWS Shield Standard (Included, always-on):
- Protection against common DDoS attacks
- Network and transport layer protection (Layer 3/4)
- Automatic inline mitigation
AWS Shield Advanced (Optional for enterprise):
- Advanced DDoS attack protection
- Application layer protection (Layer 7)
- 24/7 DDoS Response Team (DRT)
- Cost protection (refund for scaling costs during attack)
Web Application Firewall (WAF)
WAF Rules Deployed:
| Rule | Type | Action | Purpose |
|---|---|---|---|
| AWS Managed - Core Rule Set | Managed | Block | OWASP Top 10 protections |
| AWS Managed - Known Bad Inputs | Managed | Block | Known attack patterns |
| AWS Managed - SQL Database | Managed | Block | SQL injection prevention |
| Custom - Rate Limiting | Custom | Block | 1000 requests per 5 minutes per IP |
| Custom - IP Allowlist | Custom | Allow | Whitelisted corporate IPs |
| Custom - Geographic Block | Custom | Block | High-risk countries (optional) |
VPC Security Architecture
Security Group Rules (Principle of Least Privilege):
ALB Security Group:
Inbound:
- Port 443 (HTTPS) from 0.0.0.0/0
- Port 80 (HTTP) from 0.0.0.0/0 (redirects to 443)
Outbound:
- Port 8080 (HTTP) to Application Security Group
Application Security Group:
Inbound:
- Port 8080 (HTTP) from ALB Security Group
Outbound:
- Port 3306 (MySQL) to Database Security Group
- Port 6379 (Redis) to Redis Security Group
- Port 27017 (MongoDB) to MongoDB Security Group
- Port 443 (HTTPS) to 0.0.0.0/0 (for API calls to AWS services, Snowflake)
Database Security Group:
Inbound:
- Port 3306 (MySQL) from Application Security Group ONLY
Outbound:
- NONE (databases should not initiate outbound connections)
Network Access Control Lists (NACLs)
Stateless firewall rules for subnet-level protection:
Public Subnet NACL:
Inbound:
- Allow: 80, 443 from 0.0.0.0/0
- Allow: Ephemeral ports (1024-65535) from 0.0.0.0/0
- Deny: All other traffic
Outbound:
- Allow: All traffic to 0.0.0.0/0
Private Subnet NACL:
Inbound:
- Allow: All traffic from VPC CIDR (10.0.0.0/16)
- Deny: All traffic from 0.0.0.0/0
Outbound:
- Allow: All traffic to VPC CIDR (10.0.0.0/16)
- Allow: 443 to 0.0.0.0/0 (for AWS API calls)
Encryption
Encryption in Transit
TLS Configuration:
| Connection | Protocol | Cipher Suites | Certificate |
|---|---|---|---|
| User → CloudFront | TLS 1.3 | Modern ciphers only | ACM (*.cloudkeeper.com) |
| CloudFront → ALB | TLS 1.2+ | Modern ciphers only | ACM (internal) |
| ALB → ECS | HTTP | N/A (VPC internal) | N/A |
| ECS → RDS | TLS 1.2 | AES-256, AES-128 | AWS RDS CA |
| ECS → Redis | TLS 1.2 | AES-256 | ElastiCache managed |
| ECS → Snowflake | TLS 1.2 | AES-256 | Snowflake CA |
Cipher Suites (Modern Only):
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
Disabled (Weak Ciphers):
- All SSLv3
- TLS 1.0
- TLS 1.1
- All RC4 ciphers
- All DES/3DES ciphers
Encryption at Rest
Encryption Status by Service:
| Service | Encryption | Algorithm | Key Management | Customer-Managed Key Support |
|---|---|---|---|---|
| RDS MySQL | Enabled | AES-256 | AWS KMS | ✅ Yes |
| ElastiCache Redis | Enabled | AES-256 | AWS KMS | ✅ Yes |
| S3 Buckets | Enabled | AES-256 | AWS KMS | ✅ Yes |
| EBS Volumes | Enabled | AES-256 | AWS KMS | ✅ Yes |
| Snowflake | Enabled | AES-256 | Snowflake-managed | ❌ No (Snowflake limitation) |
| CloudWatch Logs | Enabled | AES-256 | AWS KMS | ✅ Yes |
| Backups (S3) | Enabled | AES-256 | AWS KMS | ✅ Yes |
Key Management
Key Rotation:
- Automatic Rotation: Enabled for all AWS KMS keys (annual rotation)
- Manual Rotation: Supported for customer-managed keys
- Rotation Frequency: Every 365 days
Key Permissions (Principle of Least Privilege):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow use of the key for RDS",
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "rds.us-east-1.amazonaws.com"
}
}
}
]
}
Authentication & Authorization
Authentication Architecture
JSON Web Tokens (JWT)
Token Structure:
{
"header": {
"alg": "RS256",
"typ": "JWT"
},
"payload": {
"sub": "user-12345",
"email": "user@example.com",
"org_id": "org-67890",
"roles": ["FinOps", "Viewer"],
"permissions": ["costs:read", "reports:read"],
"iat": 1730000000,
"exp": 1730000900
},
"signature": "..."
}
Token Security:
- Algorithm: RS256 (RSA with SHA-256)
- Key Size: 2048-bit RSA keys
- Expiry: 15 minutes (access token), 7 days (refresh token)
- Storage: httpOnly, secure cookies (cannot be accessed by JavaScript)
- Signing Key: Rotated every 90 days
Role-Based Access Control (RBAC)
Role Definitions:
| Role | Permissions | Use Case |
|---|---|---|
| Administrator | All permissions | IT administrators, platform owners |
| FinOps Manager | Cost management, reporting, recommendations | FinOps teams, cloud cost managers |
| Analyst | Read costs, create reports | Finance analysts, data analysts |
| Viewer | Read-only access to dashboards | Executives, business stakeholders |
| Custom Roles | User-defined permissions | Organization-specific needs |
Permission Matrix:
| Permission | Admin | FinOps | Analyst | Viewer |
|---|---|---|---|---|
| View costs | ✅ | ✅ | ✅ | ✅ |
| Create reports | ✅ | ✅ | ✅ | ❌ |
| Schedule reports | ✅ | ✅ | ❌ | ❌ |
| Acknowledge recommendations | ✅ | ✅ | ❌ | ❌ |
| Manage users | ✅ | ❌ | ❌ | ❌ |
| Configure settings | ✅ | ❌ | ❌ | ❌ |
| Export data | ✅ | ✅ | ✅ | ❌ |
Multi-Tenancy & Data Isolation
Isolation Mechanisms:
-
Application-Level:
- Every query filtered by
organization_id - JWT contains
org_idclaim - Middleware enforces organization context
- Every query filtered by
-
Database-Level:
- Row-level security policies
- Separate encryption keys per tenant (optional)
- Audit logging per organization
-
Storage-Level:
- S3 bucket prefix per organization:
s3://lens-data/org-12345/ - Encryption keys per organization
- Access policies prevent cross-tenant access
- S3 bucket prefix per organization:
Access to Customer AWS Accounts
Cross-Account IAM Role
IAM Role Policy (Read-Only):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadCostAndUsageReports",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::customer-cur-bucket",
"arn:aws:s3:::customer-cur-bucket/*"
]
},
{
"Sid": "ReadCostExplorerData",
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage",
"ce:GetCostForecast",
"ce:GetReservationUtilization",
"ce:GetSavingsPlansUtilization"
],
"Resource": "*"
},
{
"Sid": "ReadResourceMetadata",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"rds:DescribeDBInstances",
"s3:GetBucketTagging",
"organizations:DescribeOrganization",
"organizations:ListAccounts"
],
"Resource": "*"
},
{
"Sid": "OptionalCloudWatchMetrics",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics"
],
"Resource": "*"
}
]
}
Trust Policy (External ID Protection):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id-12345"
},
"IpAddress": {
"aws:SourceIp": [
"52.1.2.3/32",
"54.5.6.7/32"
]
}
}
}
]
}
External ID (Confused Deputy Prevention):
- Unique per customer
- 32-character random string
- Prevents AWS Lens from accessing wrong customer's data
- Stored securely in AWS Lens database
Application Security
OWASP Top 10 Mitigation
| Vulnerability | Mitigation | Implementation |
|---|---|---|
| A01: Broken Access Control | RBAC + JWT validation | Every API call checks permissions |
| A02: Cryptographic Failures | TLS 1.3, AES-256 | All data encrypted in transit and at rest |
| A03: Injection | Parameterized queries | No string concatenation in SQL |
| A04: Insecure Design | Threat modeling | Architecture reviews, pen testing |
| A05: Security Misconfiguration | Infrastructure as Code | Terraform with security checks |
| A06: Vulnerable Components | Dependency scanning | Snyk/Dependabot, automated updates |
| A07: Authentication Failures | Strong auth + MFA | JWT + SAML/OAuth + MFA support |
| A08: Data Integrity Failures | Code signing, checksums | Signed artifacts, hash verification |
| A09: Logging Failures | Comprehensive logging | CloudWatch, audit logs, SIEM |
| A10: SSRF | Network isolation | VPC, security groups, no outbound from data tier |
Input Validation
Validation Rules:
// Example: Cost query validation
@Valid
public class CostQueryRequest {
@NotNull
@Past(message = "Start date must be in the past")
private LocalDate startDate;
@NotNull
@Future(message = "End date must be in the future or today")
private LocalDate endDate;
@Pattern(regexp = "^[A-Za-z0-9_-]+$", message = "Invalid account ID format")
private String accountId;
@Size(min = 1, max = 100)
@ValidEnum(enumClass = GroupBy.class)
private String groupBy;
// Parameterized query prevents SQL injection
@Query("SELECT * FROM costs WHERE account_id = :accountId AND date BETWEEN :startDate AND :endDate")
List<Cost> findCosts(@Param("accountId") String accountId,
@Param("startDate") LocalDate start,
@Param("endDate") LocalDate end);
}
Output Encoding
XSS Prevention:
- HTML encoding for all user-generated content
- Content Security Policy (CSP) headers
- React's built-in XSS protection (JSX escaping)
CSP Header:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.cloudkeeper.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.cloudkeeper.com;
font-src 'self';
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
Monitoring & Incident Response
Security Monitoring
Security Alerts:
| Event | Severity | Alert Channel | Auto-Remediation |
|---|---|---|---|
| Failed login attempts (>5 in 5 min) | Medium | Lock account after 10 attempts | |
| Privilege escalation attempt | Critical | PagerDuty | Block user, notify admin |
| Unauthorized AWS API call | High | PagerDuty + Email | Revoke IAM role session |
| Unusual data transfer volume | Medium | None (human review) | |
| GuardDuty finding | High | PagerDuty | Depends on finding type |
| WAF rule violation spike | Medium | Slack | Automatic IP block (WAF) |
Audit Logging
CloudTrail (AWS API Calls):
{
"eventTime": "2025-10-26T10:30:00Z",
"eventName": "AssumeRole",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDAI...",
"arn": "arn:aws:iam::123456789:user/lens-service"
},
"requestParameters": {
"roleArn": "arn:aws:iam::customer-account:role/LensAccessRole",
"externalId": "unique-external-id-12345"
},
"responseElements": {
"credentials": {
"accessKeyId": "ASIA...",
"expiration": "2025-10-26T11:30:00Z"
}
},
"sourceIPAddress": "52.1.2.3"
}
Application Audit Log:
{
"timestamp": "2025-10-26T10:30:00.123Z",
"event_type": "user.login",
"user_id": "user-12345",
"organization_id": "org-67890",
"ip_address": "203.0.113.45",
"user_agent": "Mozilla/5.0...",
"mfa_used": true,
"login_method": "saml",
"result": "success"
}
Retention Periods:
- CloudTrail logs: 7 years (compliance requirement)
- Application logs: 1 year
- VPC Flow Logs: 90 days
- ALB Access Logs: 90 days
Compliance & Certifications
SOC 2 Type II
Trust Services Criteria:
| Criterion | Implementation |
|---|---|
| Security | Multi-layer defense, encryption, access controls |
| Availability | Multi-AZ, auto-scaling, disaster recovery |
| Processing Integrity | Input validation, data integrity checks |
| Confidentiality | Encryption, data isolation, NDA enforcement |
| Privacy | GDPR compliance, data residency options |
Annual Audit: Third-party audit by certified CPA firm
GDPR Compliance
Data Protection Measures:
- Data Minimization: Only collect necessary data
- Right to Access: API for users to download their data
- Right to Erasure: Delete user data on request (30-day process)
- Data Portability: Export data in standard formats (JSON, CSV)
- Data Residency: EU region deployment option (eu-west-1)
- Breach Notification: 72-hour notification process
Data Processing Agreement (DPA):
- Available for enterprise customers
- Defines roles (Controller vs Processor)
- Sub-processor list maintained
HIPAA (Optional)
For healthcare customers:
- Business Associate Agreement (BAA): Available
- Encryption: All PHI encrypted (already implemented)
- Access Controls: RBAC + audit logging (already implemented)
- Breach Notification: HIPAA-compliant process
Penetration Testing
Annual Pen Test
Scope:
- External penetration test (Internet-facing services)
- Internal network penetration test (if applicable)
- Application-layer security testing
- Social engineering (optional)
Process:
- Third-party security firm engaged (annual)
- Test environment provided (staging)
- 2-week engagement
- Findings report delivered
- Remediation plan created
- Re-test after 30 days
Recent Findings (Example):
- 2024 Pen Test: 0 critical, 2 high, 5 medium, 10 low
- All high/medium issues remediated within 30 days
Bug Bounty Program
Scope:
- Web application: https://app.cloudkeeper.com
- API: https://api.cloudkeeper.com
- Mobile app (future)
Rewards:
- Critical (RCE, SQL injection): $5,000 - $10,000
- High (XSS, CSRF): $1,000 - $5,000
- Medium (Info disclosure): $500 - $1,000
- Low: $100 - $500
Out of Scope:
- DDoS attacks
- Social engineering
- Physical security
Security Best Practices
For Customers
1. AWS Account Security:
- Enable MFA on root account
- Use strong IAM policies
- Rotate access keys regularly
- Enable CloudTrail logging
2. AWS Lens Access:
- Use SSO instead of username/password
- Enable MFA for all users
- Follow least privilege (assign minimal role)
- Review user access quarterly
3. Data Protection:
- Enable customer-managed encryption keys (optional)
- Review audit logs regularly
- Set up budget alerts
- Tag resources properly
For AWS Lens Team
1. Development:
- Security code reviews
- Dependency scanning (Snyk)
- SAST/DAST in CI/CD
- Threat modeling for new features
2. Operations:
- Principle of least privilege
- MFA for production access
- Change management process
- Incident response playbooks
3. Monitoring:
- 24/7 security monitoring
- Regular security training
- Quarterly access reviews
- Annual penetration testing
Incident Response Plan
Response Phases
Severity Levels:
| Severity | Definition | Response Time | Examples |
|---|---|---|---|
| Critical (P0) | Data breach, service down | 15 minutes | Customer data exposed |
| High (P1) | Significant security risk | 1 hour | Privilege escalation found |
| Medium (P2) | Moderate security risk | 4 hours | Brute force attacks detected |
| Low (P3) | Minor security issue | 24 hours | Info disclosure (low impact) |
Response Team:
- Security Lead (on-call 24/7)
- Engineering Lead
- Product Manager
- Legal/Compliance (for data breaches)
- PR/Communications (for public disclosure)
Next Steps
Related Documentation
- Solution Architecture - High-level architecture
- Physical Architecture - Infrastructure details
- Integration Points - Integration security
Security Resources
- Security Policy: Contact security@cloudkeeper.com
- Vulnerability Disclosure: security@cloudkeeper.com (PGP key available)
- Customer Security Guide: Available in dashboard
- Compliance Documents: SOC 2, DPA available on request
This security architecture reflects current controls as of October 2025. Security is a continuous process - new threats emerge, and defenses evolve accordingly.