@startuml diagram-network

!define AzurePuml https://raw.githubusercontent.com/travisnielsen/Azure-PlantUML/themesupport/dist

' Theme
!includeurl AzurePuml/themes/blueprint.puml

' Azure Services
!includeurl AzurePuml/Compute/AzureVirtualMachine.puml
!includeurl AzurePuml/Compute/AzureFunction.puml
!includeurl AzurePuml/Management/AzureSubscription.puml
!includeurl AzurePuml/Networking/AzureBastion.puml
!includeurl AzurePuml/Networking/AzureFirewall.puml
!includeurl AzurePuml/Networking/AzureVirtualNetwork.puml
!includeurl AzurePuml/Networking/AzureSubnet.puml
!includeurl AzurePuml/Networking/AzureExpressRoute.puml
!includeurl AzurePuml/Networking/AzureRouteTable.puml
!includeurl AzurePuml/Networking/AzureApplicationGateway.puml
!includeurl AzurePuml/Networking/AzureDNS.puml
!includeurl AzurePuml/Networking/AzureIPAddressSpace.puml
!includeurl AzurePuml/Networking/AzureNAT.puml
!includeurl AzurePuml/Networking/AzureNSG.puml
!includeurl AzurePuml/Networking/AzurePrivateLink.puml
!includeurl AzurePuml/Networking/AzurePrivateLinkHub.puml
!includeurl AzurePuml/Networking/AzurePrivateLinkService.puml
!includeurl AzurePuml/Networking/AzureVPNGateway.puml
!includeurl AzurePuml/Storage/AzureStorage.puml

LAYOUT_LEFT_RIGHT

TITLE: Network Topology
' skinparam TitleFontSize 35

AzureVirtualNetwork(vnetIslanda, "workload a", "10.10.0.0/20") {

    together {
        AzureDNS(privateZone1, "a-storage-dns", "Private DNS Zone", "privatelink.blob.core.windows.net")
        AzureDNS(privateZone2, "a-eventhub-dns", "Private DNS Zone", "privatelink.blob.core.windows.net")
        AzureDNS(privateZone3, "a-appservice-dns", "Private DNS Zone", "privatelink.blob.core.windows.net")
    }
    together {
        AzureSubnet(vnetIslandtUtil, "utility", "", "") {
            AzureNSG(islandUtilNsg, "util-nsg", "", "")
            AzureRouteTable(islandUtilUdr, "island-util-routes", "", "")
            AzureVirtualMachine(vmutil, "utility server", "", "")
            islandUtilNsg -[hidden]- islandUtilUdr
            islandUtilUdr -[hidden]- vmutil
        }
        AzureSubnet(vnetIslandPrivateEndpoints, "services", "", "") {
            AzureNSG(islandPrivateEndpointsNsg, "privatelink-nsg", "", "")
            AzurePrivateLink(islandPrivateEndpoints, "private endpoints", "", "")
            islandPrivateEndpointsNsg -[hidden]- islandPrivateEndpoints
        }
        AzureSubnet(vnetIslandIntegration, "integration-func-a", "", "") {
            AzureNSG(islandFuncANsg, "integration-nsg", "", "")
            AzureRouteTable(islandFuncAUdr, "integration-routes", "", "")
            AzureIPAddressSpace(islandFuncAIntegration, "Function App instances", "")
            islandFuncANsg -[hidden]- islandFuncAUdr
            islandFuncAUdr -[hidden]- islandFuncAIntegration
        }
    }

    privateZone1 -[hidden]-> vnetIslandtUtil

}

together {
    AzureVirtualNetwork(vnetIslandb, "workload b", "10.10.0.0/20") {
    }

    AzureVirtualNetwork(vnetIslandc, "workload c", "10.10.0.0/20") {
    }
}

vnetIslanda ---[hidden]d-> vnetIslandb
vnetIslanda ---[hidden]d-> vnetIslandc

AzureVirtualNetwork(vnetBridge, "bridge", "10.10.0.0/20") {
    AzureSubnet(vnetBridgeAzFw, "FirewallSubnet", "", "") {
        AzureFirewall(bridgefw, "Bridge Firewall", "", "Deny egress (default)")
    }
    AzureSubnet(vnetBridgeBastion, "BastionSubnet", "", "") {
        AzureBastion(bastion, "SSH / RDP Proxy", "", "")
    }
    AzureSubnet(vnetBridgeAppGw, "web-publish", "", "") {

    }

}

AzureVirtualNetwork(vnetHub, "hub", "10.10.0.0/20") {
    AzureSubnet(vnetHubFirewall, "FirewallSubnet", "", "") {
        AzureFirewall(hubfw, "Hub Firewall", "", "Deny egress (default)")
    }

    AzureSubnet(vnetHubDns, "infra", "", "") {
        AzureNSG(vnetHubNsgDns, "dns-nsg", "", "")
        AzureVirtualMachine(vmdns, "DNS Servers", "", "")
        vnetHubNsgDns -[hidden]d- vmdns
    }
}

AzureVirtualNetwork(vnetSpoke, "spoke", "10.20.0.0/20") {

    AzureSubnet(vnetSpokeApp, "app", "", "") {
        AzureNSG(vnetSpokeNsgApp, "app-nsg", "", "")
        AzureVirtualMachine(spokeApp1, "App Server", "", "")
        vnetSpokeNsgApp -[hidden]d-> spokeApp1
    }

    ' AzureVirtualMachine(vm, "Utility Servers", "", "Allow SSH / RDP from Bastion subnet")
    ' AzureRouteTable(udr1, "User Defined Route", "Force egress to hub", "0.0.0.0 to AZFW")
    ' AzurePrivateLink(azsvcLink, "Azure Services", "", "Inbound connections")
    ' AzureRouteTable(udr2, "User Defined Route", "Force egress to hub", "0.0.0.0 to AZFW")
}

vnetIslanda ----- vnetBridge
vnetIslandb ----- vnetBridge
vnetIslandc ----- vnetBridge
vnetBridge ---- vnetHub
vnetHub ----- vnetSpoke

' bastion -[#d33682]-> vm: "<color:#d33682>RDP/SSH"
' vnetHub -[#268bd2]-- vnetSpoke: "<color:#268bd2><size:18>VNET\n<color:#268bd2><size:18>Peering"
' AzureNSG(nsgs, "Traffic Segmentation", "1 per subnet", "Deny outbound Internet\nExplicit inbound allow")
' AzureStorage(adls, "Data Lake", "Standard SKU", "Source data")
' azsvcLink -[#859900]-> adls: "<color:#859900>Private Link"
' AzureFunction(functions, "Functions", "Premium Plan", "Private storage account for service (preview)")
' azsvcLink -[#859900]-> functions: "<color:#859900>Private Link"
' subFuncInt <-[#2aa198]- functions: "<color:#2aa198>VNET Integration (outbound)"


@end