All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.io.cloudshiftdev.awscdklib.network.securenetwork.RouterProvider.kt Maven / Gradle / Ivy

There is a newer version: 10.1.0
Show newest version
package io.cloudshiftdev.awscdklib.network.securenetwork

import io.cloudshiftdev.awscdk.services.ec2.NatProvider
import io.cloudshiftdev.awscdk.services.ec2.RouterType
import io.cloudshiftdev.awscdk.services.ec2.Subnet
import io.cloudshiftdev.awscdk.services.ec2.SubnetSelection
import io.cloudshiftdev.awscdk.services.ec2.Vpc
import io.cloudshiftdev.awscdk.services.ec2.VpcProps
import io.cloudshiftdev.awscdklib.core.address
import io.cloudshiftdev.awscdklib.network.CidrBlock
import io.cloudshiftdev.awscdklib.network.firewall.FirewallPolicy
import io.cloudshiftdev.awscdklib.network.firewall.NetworkFirewall
import io.cloudshiftdev.awscdklib.network.firewall.StatelessStandardAction

public interface RouterProvider {
    public fun create(vpc: Vpc)
}

internal interface NatGatewayConfigurer {
    fun configure(props: VpcProps.Builder)
}

internal abstract class BaseRouterProvider(protected val routerSubnet: SubnetSelection) :
    RouterProvider

internal class NatRouterProvider(
    routerSubnet: SubnetSelection,
    private val natGatewayCount: Int,
    private val natProvider: NatProvider
) : BaseRouterProvider(routerSubnet), NatGatewayConfigurer {

    override fun configure(props: VpcProps.Builder) {
        props.apply {
            natGateways(natGatewayCount)
            natGatewaySubnets(routerSubnet)
            natGatewayProvider(natProvider)
        }
    }

    override fun create(vpc: Vpc) {
        // nothing to do, we use the vpc-provided NAT gateway creation
    }
}

internal class EgressNetworkFirewallRouterProvider(
    routerSubnet: SubnetSelection,
    private val egressSubnets: List,
    private val ingressSubnets: List,
) : BaseRouterProvider(routerSubnet) {
    override fun create(vpc: Vpc) {

        val firewallPolicy =
            FirewallPolicy(
                scope = vpc,
                id = "FirewallPolicy",
                // TODO: make these configurable
                statelessDefaultActions = listOf(StatelessStandardAction.PASS),
                statelessFragmentDefaultActions = listOf(StatelessStandardAction.PASS)
            )

        val firewall =
            NetworkFirewall(
                scope = vpc,
                id = "NetworkFirewall",
                vpc = vpc,
                subnetMappings = routerSubnet,
                firewallName = "Firewall",
                firewallPolicy = firewallPolicy
            )

        val protectedSubnets =
            egressSubnets.flatMap { vpc.selectSubnets(it).subnets() }.map { it as Subnet }
        val ingress =
            ingressSubnets.flatMap { vpc.selectSubnets(it).subnets() }.map { it as Subnet }

        data class AzRouteInfo(
            val az: String,
            val endpointId: String,
            val protectedSubnets: List,
            val ingressSubnets: List
        )

        val azMap = firewall.availabilityZoneEndpointMap

        val azRouteInfo =
            azMap.entries.map { azEntry ->
                AzRouteInfo(
                    az = azEntry.key,
                    endpointId = azEntry.value,
                    protectedSubnets =
                        protectedSubnets.filter { it.availabilityZone() == azEntry.key },
                    ingressSubnets = ingress.filter { it.availabilityZone() == azEntry.key }
                )
            }
        azRouteInfo.forEach { routeInfo ->
            routeInfo.protectedSubnets.forEach { protectedSubnet ->

                // forward flow from protected subnet to firewall
                protectedSubnet.addRoute("NetworkFirewallEgressRoute") {
                    routerId(routeInfo.endpointId)
                    routerType(RouterType.VPC_ENDPOINT)
                    enablesInternetConnectivity(true)
                    destinationCidrBlock(CidrBlock.allIPv4().toString())
                }

                // reverse flow back from NAT gateway to firewall
                routeInfo.ingressSubnets.forEach { ingressSubnet ->
                    ingressSubnet.addRoute(
                        "NetworkFirewallIngressRoute${protectedSubnet.address}"
                    ) {
                        routerId(routeInfo.endpointId)
                        routerType(RouterType.VPC_ENDPOINT)
                        enablesInternetConnectivity(true)
                        destinationCidrBlock(protectedSubnet.ipv4CidrBlock())
                    }
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy