Integration Testing for Security Controls
Integration Testing for Security Controls
Integration testing validates that security controls work correctly when deployed. While static analysis can verify encryption is configured, integration tests confirm data actually gets encrypted. These tests provide confidence that security controls function as intended in real environments.
Security control validation uses actual cloud APIs to verify configurations. Tests might attempt unauthorized access to confirm IAM policies work correctly. Network tests verify security groups block inappropriate traffic. Encryption tests ensure data remains protected at rest and in transit.
# security_integration_tests.py - Validate deployed security controls
import boto3
import pytest
from typing import Dict, Any
class TestDeployedSecurity:
@pytest.fixture(scope="class")
def aws_resources(self):
"""Fixture to get deployed AWS resources."""
return {
'ec2': boto3.client('ec2'),
's3': boto3.client('s3'),
'iam': boto3.client('iam'),
'rds': boto3.client('rds')
}
def test_s3_bucket_encryption(self, aws_resources):
"""Verify all S3 buckets have encryption enabled."""
s3 = aws_resources['s3']
response = s3.list_buckets()
for bucket in response['Buckets']:
bucket_name = bucket['Name']
# Check encryption
try:
encryption = s3.get_bucket_encryption(Bucket=bucket_name)
assert 'Rules' in encryption['ServerSideEncryptionConfiguration']
# Verify specific encryption type
rules = encryption['ServerSideEncryptionConfiguration']['Rules']
assert any(
rule.get('ApplyServerSideEncryptionByDefault', {}).get('SSEAlgorithm')
in ['AES256', 'aws:kms']
for rule in rules
)
except s3.exceptions.ServerSideEncryptionConfigurationNotFoundError:
pytest.fail(f"Bucket {bucket_name} does not have encryption enabled")
def test_security_group_restrictions(self, aws_resources):
"""Verify security groups don't allow unrestricted access."""
ec2 = aws_resources['ec2']
response = ec2.describe_security_groups()
for sg in response['SecurityGroups']:
for rule in sg.get('IpPermissions', []):
# Check for 0.0.0.0/0 access
for ip_range in rule.get('IpRanges', []):
if ip_range.get('CidrIp') == '0.0.0.0/0':
# Only allow specific ports from internet
allowed_ports = [80, 443]
from_port = rule.get('FromPort', 0)
to_port = rule.get('ToPort', 0)
assert from_port in allowed_ports and to_port in allowed_ports, \
f"Security group {sg['GroupId']} allows unrestricted access on ports {from_port}-{to_port}"
def test_iam_least_privilege(self, aws_resources):
"""Verify IAM roles follow least privilege principle."""
iam = aws_resources['iam']
# Get all roles created by IaC (tagged appropriately)
paginator = iam.get_paginator('list_roles')
for page in paginator.paginate():
for role in page['Roles']:
role_name = role['RoleName']
# Skip AWS service-linked roles
if role['Path'].startswith('/aws-service-role/'):
continue
# Check for overly permissive policies
attached_policies = iam.list_attached_role_policies(RoleName=role_name)
for policy in attached_policies['AttachedPolicies']:
if policy['PolicyArn'] == 'arn:aws:iam::aws:policy/AdministratorAccess':
pytest.fail(f"Role {role_name} has AdministratorAccess policy attached")
# Check inline policies
inline_policies = iam.list_role_policies(RoleName=role_name)
for policy_name in inline_policies['PolicyNames']:
policy_doc = iam.get_role_policy(
RoleName=role_name,
PolicyName=policy_name
)
# Verify no wildcard actions
for statement in policy_doc['PolicyDocument']['Statement']:
if statement.get('Effect') == 'Allow':
actions = statement.get('Action', [])
if isinstance(actions, str):
actions = [actions]
for action in actions:
assert not action.endswith('*'), \
f"Role {role_name} has wildcard action: {action}"
End-to-end security scenarios validate complete security workflows. Tests might simulate attack patterns to verify defenses work correctly. For example, tests could attempt SQL injection against deployed databases to confirm WAF rules block malicious requests. These comprehensive tests provide confidence in overall security posture.