VpcFactory.java
package com.cloudforgeci.api.network;
import com.cloudforgeci.api.core.annotation.BaseFactory;
import com.cloudforgeci.api.core.rules.AwsConfigRule;
import com.cloudforge.core.annotation.DeploymentContext;
import com.cloudforge.core.annotation.SystemContext;
import com.cloudforge.core.enums.NetworkMode;
import com.cloudforge.core.enums.RuntimeType;
import com.cloudforge.core.enums.SecurityProfile;
import com.cloudforge.core.enums.TopologyType;
import software.amazon.awscdk.services.ec2.*;
import software.constructs.Construct;
import java.util.List;
import java.util.logging.Logger;
/**
* Factory for creating VPC (Virtual Private Cloud) infrastructure.
*
* <p>This factory creates AWS VPCs with configurable subnet configurations
* and NAT gateways based on the network mode setting. It uses annotation-based
* context injection for clean, maintainable code.</p>
*
* <p><strong>Compliance Coverage:</strong></p>
* <ul>
* <li>SOC2-CC6.6-VPC: Network segmentation and boundary protection</li>
* <li>SOC2-CC7.2-FlowLogs: Network monitoring via VPC Flow Logs</li>
* <li>HIPAA ยง164.312(e)(1): Technical safeguards for network transmission</li>
* <li>PCI-DSS Req 1.1: Network documentation and segmentation</li>
* <li>PCI-DSS Req 1.3: Prohibit direct public access to cardholder data environment</li>
* <li>GDPR Art. 32: Security of processing (network isolation)</li>
* </ul>
*
* <p><strong>Network Configurations:</strong></p>
* <ul>
* <li><strong>public-no-nat:</strong> Creates VPC with public subnets only, no NAT gateways (unless security profile requires them)</li>
* <li><strong>private-with-nat:</strong> Creates VPC with public and private subnets, NAT gateways based on security profile</li>
* <li><strong>Security profiles:</strong> Automatically determine NAT gateway count based on topology, runtime, and security requirements</li>
* </ul>
*
* <p><strong>Subnet Configuration:</strong></p>
* <ul>
* <li><strong>Public subnets:</strong> For resources that need direct internet access</li>
* <li><strong>Private subnets:</strong> For resources that use NAT gateway for outbound access</li>
* <li><strong>CIDR:</strong> /24 masks for both public and private subnets</li>
* </ul>
*
* <p><strong>Features:</strong></p>
* <ul>
* <li>Centralized NAT gateway configuration via security profiles</li>
* <li>Automatic NAT gateway count determination based on topology, runtime, and security requirements</li>
* <li>Flow logs integration (when configured)</li>
* <li>Multi-AZ deployment (2 availability zones)</li>
* <li>Annotation-based context injection</li>
* </ul>
*
* <p><strong>Example Usage:</strong></p>
* <pre>{@code
* VpcFactory factory = new VpcFactory(scope, "JenkinsVPC");
* factory.create();
*
* // Access created VPC
* Vpc vpc = ctx.vpc.get().orElseThrow();
* }</pre>
*
* @author CloudForgeCI
* @since 1.0.0
* @see BaseFactory
* @see com.cloudforgeci.api.core.DeploymentContext#networkMode()
* @see com.cloudforgeci.api.core.SystemContext#flowlogs
*/
public final class VpcFactory extends BaseFactory {
private static final Logger LOG = Logger.getLogger(VpcFactory.class.getName());
@SystemContext("topology")
private TopologyType topology;
@SystemContext("runtime")
private RuntimeType runtime;
@DeploymentContext("networkMode")
private NetworkMode networkMode;
public VpcFactory(Construct scope, String id) {
super(scope, id);
}
/**
* Creates the VPC infrastructure.
*
* <p>This method creates a VPC with appropriate subnet configuration and NAT gateways
* based on the network mode setting. It also integrates flow logs if they are
* configured in the system context.</p>
*
* <p>The created VPC is stored in the SystemContext for use by other factories.</p>
*
* @see #createVpc()
* @see com.cloudforgeci.api.core.SystemContext#vpc
* @see com.cloudforgeci.api.core.SystemContext#flowlogs
*/
@Override
public void create() {
// Create VPC with basic configuration
Vpc vpc = createVpc();
// Register AWS Config rules for VPC network segmentation compliance
ctx.requireConfigRule(AwsConfigRule.EC2_INSTANCES_IN_VPC);
ctx.requireConfigRule(AwsConfigRule.VPC_DEFAULT_SG_CLOSED);
ctx.requireConfigRule(AwsConfigRule.RESTRICTED_SSH);
// Add flow logs if configured
// NOTE: Read from ctx.flowlogs.get() directly rather than using injected field,
// because FlowLogFactory.create() may have set the value after VpcFactory was constructed
if (ctx.flowlogs.get().isPresent()) {
vpc.addFlowLog("VpcFlowlog", ctx.flowlogs.get().get());
ctx.requireConfigRule(AwsConfigRule.VPC_FLOW_LOGS_ENABLED);
LOG.info("VPC Flow Logs enabled with options: " + ctx.flowlogs.get().get());
} else {
if (config.getSecurityProfile() == SecurityProfile.PRODUCTION) {
LOG.warning("VPC Flow Logs disabled for PRODUCTION - will fail CDK-nag VPC7");
} else {
LOG.info("VPC Flow Logs disabled for " + config.getSecurityProfile());
}
}
// Store VPC in SystemContext
ctx.vpc.set(vpc);
}
private Vpc createVpc() {
// Get NAT gateway count from security profile configuration
// This encapsulates all logic for topology, runtime, security, and network mode
int natGateways = config.getNatGatewayCount(topology, runtime, networkMode);
return Vpc.Builder.create(this, "Vpc")
.maxAzs(2)
.vpcName(getNode().getId() + "Vpc")
.natGateways(natGateways)
.subnetConfiguration(List.of(
SubnetConfiguration.builder()
.name("public")
.subnetType(SubnetType.PUBLIC)
.cidrMask(24)
.build(),
SubnetConfiguration.builder()
.name("private")
.subnetType(SubnetType.PRIVATE_WITH_EGRESS)
.cidrMask(24)
.build()
))
.build();
}
}