Når man designer ens Azure setup skal man huske følgende:

  • alle azure services er som udgangspunkt åbent for nettet

En huskeregel taget direkte fra militæret: en gev (gevær red.) er altid ladt = en azure service har altid en offentlig IP, indtil den ikke har :)

Som udgangspunkt er alt altid koblet på en offentlig IP, og der er ikke så meget man kan gøre ved det. I denne artikel bruger jeg fx storage account som eksempel, og man kan ikke fjerne den offentlige IP, man kan dog sørge for at alt trafik ikke rammer det offentlige endpoint, og man kan også sørge for kun at tillade trafik fra bestemte kilder. Mange resourcer har i dag en eller anden slags firewall, som kan spærre for adgang på forskellige måder.

Service endpoints

Med service endpoints sørger du for at trafik mellem dine resourcer som er i dit VNET, eller integreret med dem, bliver på Azures backbone.

/images/service-endpoint.svg

Billedet ovenover, består af nogle VMs, dog kan du skifte dem ud med webapps (i en ASE), ellers skal du forstille dig at dine webapps integrerer med VNET'et (plain webapps kan aldrig komme ind i VNET'et, men de kan smide trafik igennem dem … mere om det i et andet indlæg, som jeg er ved at brygge sammen: VNET primer i Azure).

Husk:

  1. en service endpoint extender og giver dig en direkte forbindelse mellem dit VNET og fx din storage account, du kan bruge, men
  2. din storage account er stadig tilgængelig over Internettet, hvilket betyder:
  3. trafikken forlader stadig dit VNET for at nå det der ligger i den anden ende af dit service endpoint
  4. Rent faktisk betyder det at din storage account stadig har en public endpoint, med en dertilhørende public IP

Læser man dokumentationen, står der følgende

Service endpoints can connect certain PaaS services directly to your private address space in Azure, so they act like they're on the same virtual network. Use your private address space to access the PaaS services directly. Adding service endpoints doesn't remove the public endpoint. It simply provides a redirection of traffic.

To enable a service endpoint, you must do the following two things:

  1. Turn off public access to the service.
  2. Add the service endpoint to a virtual network.

Så man skal endelig huske at lukke for offentlig trafik, før det er helt sikker. Et gevær har altid en IP, eller hvordan var det nu lige det var.

On the bottom line: trafikken vil stadig forlade dit VNET, og ramme dit public endpoint (læs: den public IP) på fx din storage account. Det smarte er at med service endpoints, kan din storage account identificere trafik fra dit VNET, og derved tillade trafikken fra dit VNET, mens den forkaster alt andet.

Kigger man lidt under låget (hvordan ARM templaten laves fra portalens side), kan man se, ved ikke at kræve at storage kontoen indgår i et VNET, at den har en default action i dens ACL som er sat til Allow

    "networkAcls": {
                "bypass": "AzureServices",
                "virtualNetworkRules": [],
                "ipRules": [],
                "defaultAction": "Allow"
            },

I dette tilfælde har man ikke slået udvalgte netværk til og i princippet tillader man trafik fra alle netværk, til kontoen

/images/connections.png

Slår man "Selected networks" til

/images/selectednetworks.png

Ændres ens ACL også

     "networkAcls": {
                "bypass": "AzureServices",
                "virtualNetworkRules": [],
                "ipRules": [],
                "defaultAction": "Deny"
            },

Til Deny pr default. Smider man en webapp op, som lister contents, fx

                BlobServiceClient blobServiceClient = new BlobServiceClient("DefaultEndpointsProtocol=https;AccountName=sttestendpoint1;AccountKey=hemmeligt;EndpointSuffix=core.windows.net");

                var container = blobServiceClient.GetBlobContainerClient("testcontainer");
                StringBuilder builder = new StringBuilder();

                await foreach(var item in container.GetBlobsAsync())
                {
                    builder.AppendLine(item.Name);
                }

Når ACL er sat til Deny, vil man får en HTTP 403 tilbage.

Her kan vi se hvordan service endpoints og netværkskontrol opererer på en storage konto:

  1. Alt bliver nægtet pr default via ACLs
  2. Du har stadig i princippet kun en public endpoint du rammer

Hvis jeg nu:

  1. opretter et VNET
  2. tilføjer en service endpoint til mit subnet
  3. delegerer udgående trafik fra min webapp, og til mit VNET
  4. tilføjer min subnet til tilladte networks på min storage konto

Så får jeg nu adgang til at liste de filer som ligger på min storage konto.

ACL'en på storage kontoen ser også ud som vi gerne vil have det:

    "networkAcls": {
                "bypass": "AzureServices",
                "virtualNetworkRules": [
                    {
                        "id": "/subscriptions/123/resourceGroups/rg-endpoint-test/providers/Microsoft.Network/virtualNetworks/vn-test/subnets/default",
                        "action": "Allow",
                        "state": "Succeeded"
                    }
                ],
                "ipRules": [],
                "defaultAction": "Deny"
            }

ACL'en tillader trafik fra vores subnet, og forkaster alt andet.

Laver man en nameresolving (det hedder ikke nslookup når vi snakker webapps) på blob URL'en, kan man også se at selve resolving her, faktisk stadig resolver den public IP som er tilknyttet:

/images/sandboxcmd.png

Private endpoint (drevet af et private link)

/images/linksoverview.png

Smider vi en private endpoint ind i stakken (service endpoints og private endpoints kan godt coeksisterer), så ser det pludselig anderledes ud:

  1. vores trafik bliver i vores VNET
  2. vi linker en specifik resource ind
  3. vores endpoint resolver derfor til en privat IP

Laver vi en nameresolving, kan vi også se at at IP'en ikke resolver til den offentlige IP længere

/images/resolveip.png

En af fordelene ved en privat endpoint: vores onprem, så er linket via et site-to-site eller en express route, kan nu også nå vores storage konto.

Det eneste man skal huske på, som dokumentationen også siger

If you want to restrict access to your storage account through the private endpoint only, configure the storage firewall to deny or control access through the public endpoint.

Man skal altså stadig huske at sætte ens tilladte netværk til kun at være fra det subnet som ens webapps ligger i. På den måde kan man:

  1. lukke hele internettet ude, og
  2. kun tillade trafik gennem den private IP som vores private endpoint kommer ind med

Man har altså sikret sig at:

  1. trafikken bliver i ens VNET, og
  2. ingen andre kan tilgå det

Husk: de NSG'ere som er tilknyttet det givne subnet bliver disabled, når det privat endpoint bliver provisioneret ind i subnettet.

The end(point)

Husk:

  1. service endpoints giver dig en måde at låse trafik til et givent subnet i et VNET, det sker dog stadig gennem dit public endpoint
  2. med service endpoints låser du ikke en specifik resource, som med private link, du låser dig til den givne service, og ikke en resource. Alle resourcer i dit givne subnet har adgang til fx din storage account
  3. skal dit trafik blive indenfor dit VNET, og have en intern IP, så brug private link

Skal vi skære det helt ind til benet:

  1. service endpoint: trafikken flyder ud af dit VNET, og rammer det offentlige endpoint på resourcen. Trafikken bliver tagget, så man på resourcens firewall kan tillade kun trafik fra det valgte service endpoint
  2. private link: trafikken bliver i dit VNET, og rammer den private IP på resourcen i den anden ende. Det offentlige endpoint på resorucen i den anden ende bliver ikke fjernet. Du kan bruge et service endpoint til at tagge trafikken, og derved spærre for trafik fra alt andet, end det valgte service endpoint