portfolio-optimiser/docs/2026-08-18-vurdering-azure-omdoeping.md
Kjell Tore Guttormsen 4cf8c4f6ba feat(gate): pakke-gaten leser INNHOLDET, ikke bare filnavn + vurdering av Azure-omdøping
ORDRE 20260818T103716Z-251212929. To deler.

DEL 2 - innholds-gapet (TDD, red-first MÅLT):
Hver eksisterende gate i test_handover_package_loadbearing.py leser arkiv-MEDLEMSNAVN.
Ingen leste hva medlemmene SIER - som er nøyaktig hvorfor ressursgruppe, ressurs,
prosjekt og vertsnavn nådde en ekstern organisasjon i 14:24-bygget uten at én av 869
tester merket det.

RED FIRST, mot ekte data: gate-kroppen kjørt mot den LEVERTE zip-en gir 7 funn
(vertsnavnet + seks /Users-stier), mot `git archive 77076b9` gir den 8. Den finner
altså det som faktisk lakk, før den brukes til å påstå at HEAD er ren.

Gaten er en NEKTELSE, aldri et filter: den fjerner ingenting fra arkivet, den sier at
treet ikke er leveringsklart. Pakka forblir `git archive HEAD` - kø-(p) intakt.
Mønstrene bor i ÉN liste, hver rad med sin egen kjent-positive prøve, og hver prøve er
BYGGET VED KONKATENERING så fila ikke matcher seg selv (verifisert: 0 funn i egen kilde
- ellers hadde eneste fiks vært et hull i gaten der en hemmelighet kan gjemme seg).
Aksept-lista er selv gatet: en oppføring som ikke lenger nås er drift og felles.

MÅLT, seks mutasjoner - fem røde, én uten diskriminerende kraft:
- detach scanneren               -> 1 rød (leaked-kontrollen)
- aksept-lista sluker ekte vert  -> 2 røde
- ødelegg vertsnavn-regexen      -> 2 røde
- foreldet aksept-oppføring      -> 1 rød (minimalitets-kontrollen)
- koordinat tilbake i HEAD       -> 1 rød, gaten ALENE
- fjern nevner-asserten          -> 0 røde (kontroll, ikke søm - uttalt)

Nevner: 325 medlemmer lest, 1 hoppet over (sqlite-binær). 873 passed / 5 skipped.

ÆRLIGHETS-GRENSE, uttalt i koden: gaten fanger STRUKTUR. Vertsnavnet har en form;
ressursgruppe og prosjekt er fri tekst uten form, og ble i august bare oppdaget fordi
de sto i samme tabell som verten. Å lukke det gapet krever en navneliste - den andre
kopien av eksponeringsregelen, som er dét pakkas `git archive HEAD`-form finnes for å
forby.

DEL 1 - vurdering av omdøping (ingenting rørt i Azure):
docs/2026-08-18-vurdering-azure-omdoeping.md. Anbefaling: IKKE døp om. Lekkasjen ga
MÅLRETTING, ikke tilgang, og målrettingen kan ikke trekkes tilbake - navnene ligger i
publisert historikk og i en zip hos en tredjepart. Omdøping finnes dessuten ikke som
operasjon: et custom subdomain KAN IKKE endres (Learn), så det er riving + gjenoppbygging
i sju steg. Det ene tiltaket som faktisk fjerner en autorisasjonsvei Entra ikke dekker er
`disableLocalAuth` + nøkkelregenerering. Beslutningen er operatørens; valgene står med
konsekvenser, ikke som konklusjon.

PREMISS KORRIGERT (Verifiseringsloven ansikt 3): ordren sa koordinatene sto i repoet og
at tre /Users/ktg-stier lå på open/main. Målt på 6d2837f: 0 og 0 - 241b50d og 6d2837f
lukket begge. Premisset var sant da ordren ble skrevet (10:37Z) og sluttet å være det
13:03/13:20. Ingen begrunnet aksept-oppføring var derfor nødvendig for sti-klassen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01964PUr46mfnxWtMw23AnVD
2026-08-18 13:42:02 +02:00

12 KiB

Vurdering: skal Azure-ressursene døpes om?

Bestilt av ordre 20260818T103716Z-251212929 (fra .claude). Leveransen er en vurdering, ikke en omdøping — ingenting i Azure er rørt. Beslutningen er operatørens.

Alt under er enten målt i dette repoet eller verifisert mot Microsoft Learn. Der noe ikke er verifisert, står det. Kildene er listet i §6.

1. Hva røper koordinatene faktisk?

Koordinatene som nådde en ekstern organisasjon 14.08 (i dist/portfolio-optimiser-foundry-1.1.0.zip, bygget 14:24):

Verdi Type
<resource-group> ressursgruppe (ARM-planet)
<resource> Foundry-ressurs = custom subdomain (DNS)
<project> prosjekt (ARM + data-plan-sti)
eastus region
https://<resource>.services.ai.azure.com/api/projects/<project> prosjekt-endepunkt

De literale navnene er byttet mot plassholdere her, samme form som DEPLOY.md, auth-oppskriften og måleprotokollen etter 241b50d. Dokumentet handler om hva navnene er, ikke om hvilke de var — og innholds-gaten i tests/test_handover_package_loadbearing.py avviste førsteutkastet som bar dem.

Utledbart uansett — ikke lekket av oss:

  • At det er en AIServices-ressurs med prosjekter. URL-formen …/api/projects/<project> ER den dokumenterte Foundry-prosjekt-endepunkt-formen. Enhver som ser en slik URL vet ressurstypen.
  • Modell, versjon og deployment-navn (gpt-4.1-mini, 2025-04-14, GlobalStandard). Offentlig katalog-nomenklatur.
  • Rolle-GUID-en 53ca6127-db72-4b80-b1b0-d745d6d5456d. Azures offentlige innebygde role definition id for Foundry User, identisk i hver tenant. Den står i Learn-dokumentasjonen. Den er ikke en koordinat, og skal ikke plassholdes.
  • At vertsnavnet i det hele tatt er et globalt, gjettbart navnerom. Custom subdomain ligger under ett felles DNS-navnerom, og navnet er unikt på tvers av alle kunder — så eksistensen av et gitt navn kan enhver bekrefte ved å slå det opp. Lekkasjen fjernet gjettingen, ikke muligheten.

Kun kjent fordi navnene lekket:

  • Ressursgruppenavnet. Det finnes ikke i DNS og ikke i noen data-plan-URL. Det er rent ARM-plan-informasjon.
  • Regionen (eastus). Ikke utledbar fra vertsnavnet for *.services.ai.azure.com.
  • Prosjektnavnet (<project>) — det står riktignok i endepunkts-URL-en, men URL-en er selv en del av lekkasjen.
  • Koblingen mellom dem. Det operativt verdifulle er ikke ett navn, men at ressursgruppe, ressurs, prosjekt, region og rolle-scope kommer som ett ferdig sett.

Kort: dette er rekognoseringsinformasjon om ARM-planet. Det er ikke nøkler, og det er ikke tenant-id eller abonnements-id — ingen av de to sto i dokumentet (målt: 0 treff på /subscriptions/<guid> i hele treet og i den leverte pakka).

2. Hva skal til for å misbruke dem?

Det Entra faktisk stopper

Et kall mot prosjekt-endepunktet krever både et gyldig Entra-token for scopet https://ai.azure.com/.default og en RBAC-tildeling på ressurs- eller prosjekt-scope. Microsofts egen feilkode-tabell skiller de to: 401 = manglende/utløpt token, 403 = manglende rolletildeling. Å kjenne adressen gir altså i seg selv null inferens-tilgang.

Token-basert auth krever dessuten et custom subdomain — regionale endepunkter støtter ikke Entra i det hele tatt. Vi bruker custom subdomain, altså er Entra-stien tilgjengelig.

Det Entra ikke stopper

  1. Nøkkelbasert auth, hvis den er på. Entra blir eneste autorisasjonsmetode først når disableLocalAuth er satt til true — det er en eksplisitt handling (Azure Policy på abonnement/ressursgruppe, disableLocalAuth i ARM/Bicep, eller Set-AzCognitiveServicesAccount -DisableLocalAuth $true). Er den ikke satt, finnes det nøkler som omgår Entra fullstendig. Ikke verifisert for denne ressursen: az cognitiveservices account create-kommandoen i måleprotokollen (docs/2026-08-14-fase1b-forste-levende-kjoring.md §0) ba ikke om det, og om abonnementet har policyen er ukjent herfra. Dette er den ene sjekken som faktisk endrer risikobildet — se §4. Merk også at avslåing ikke slår inn momentant: endringen skjer i kontrollplanet med én gang, men gatewayen kan godta tidligere gyldige nøkler til cachen oppdateres — typisk minutter, opptil flere timer. Og allerede utdelte nøkler må regenereres separat; å slå av lokal auth tilbakekaller dem ikke.
  2. Målrettet phishing og consent-phishing. Koordinatene gjør en henvendelse troverdig — avsender kan navngi ressursgruppe, ressurs og prosjekt riktig. Entra beskytter identiteten, ikke overtalelsen. Dette er den mest realistiske misbruksveien for denne typen lekkasje.
  3. Kvote- og kostnadsmisbruk ved kompromittert identitet. Kvote tildeles per abonnement, per region, per modell og deployment-type, i tokens-per-minutt, og deles av alle deployments av samme modell i samme region i abonnementet. En misbrukt identitet med Foundry User på dette prosjektet spiser altså av en pott som er felles, og kan strupe andre deployments av samme modell i samme abonnement — ikke bare denne. Forbruket faktureres.
  4. Nettverksflaten. publicNetworkAccess er en egenskap som må settes til Disabled for å stenge den offentlige inngangen. Er den ikke det, er endepunktet nåbart fra internett — det var sant før lekkasjen også. Forskjellen er at adressen nå er kjent, ikke at den ble nåbar.

Ikke verifisert: om et uautentisert kall skiller et eksisterende prosjektnavn fra et ikke-eksisterende (altså om <project> kan bekreftes uten token). Det ville krevd et faktisk kall mot en fremmed ressurs, og det er ikke gjort.

3. Hva koster omdøping?

I repoet: null

Målt på 6d2837f (= open/main = origin/main), nevner 327 sporede filer:

Sted Treff på de tre literale navnene
Sporet tre (kode, tester, docs, env.template) 0
Usporet deck docs/presentasjon-portfolio-optimiser.html 0
shared/ (subtree) 0

De 18 gjenværende linjene med services.ai.azure.com er plassholderformen (<resource>.), wildcard-formen (*.) eller testdummies (x., platform., wrong.). env.template bærer variabelnavn, aldri verdier. Omdøping krever altså ingen redigering i repoet241b50d gjorde allerede den jobben.

I historikken og i den leverte pakka: kan ikke tilbakekalles

  • Git-historikken: 3 linjer i 1 fil, i 3 commits (5bd8e1c, bb4807a, 241b50d). Publisert på open/main. Ordren forbyr å skrive om historikken, og vei B ble alt avvist 18.08.
  • Den leverte pakka: 4 linjer, hos en tredjepart siden 14.08. En omdøping i Azure gjør ikke det usett.

I Azure: en full riving og gjenoppbygging

Et custom subdomain kan ikke endres. Microsoft er eksplisitt: navnet kan ikke endres etter at det er opprettet og knyttet til ressursen, og for å gjenbruke et navn må den eksisterende ressursen slettes. «Omdøping» finnes derfor ikke som operasjon — det er:

  1. opprett ny AIServices-ressurs med nytt subdomain (+ --allow-project-management)
  2. opprett nytt prosjekt
  3. redeploy gpt-4-1-mini (ny kvotetildeling i regionen)
  4. tildel Foundry User på nytt prosjekt-scope
  5. oppdater PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT og PORTFOLIO_MODEL_MAP lokalt
  6. slett — og purge — den gamle ressursen (purge krever Contributor på abonnements-scope)
  7. re-kjør stigen i måleprotokollen §1 for å bevise at auth/RBAC/endepunkt fortsatt komponerer

Ikke verifisert: om det gamle subdomain-navnet holdes reservert en periode etter sletting slik App Service og API Management gjør (anti-subdomain-takeover). Learn dokumenterer den mekanismen for de tjenestene, men ikke for Foundry-/Cognitive Services-subdomener. Ikke anta at navnet frigis — og ikke anta at det er låst.

4. Anbefaling — og hva hvert valg koster

Anbefalingen er: ikke døp om. Fjern i stedet den ene veien som ikke går gjennom Entra, og gjør misbruk synlig.

Begrunnelsen er at omdøping løser feil problem. Det lekkasjen ga en motpart er målretting, ikke tilgang. Og målrettingen kan ikke trekkes tilbake: navnene ligger i publisert git-historikk og i en zip hos en tredjepart. En omdøping ville altså kjøpt at dagens ressurs ikke er den som ble navngitt — ikke at navngivingen forsvinner. Det er en reell, men liten gevinst, og den betales med en full riving av det eneste levende Foundry-oppsettet prosjektet har.

Valg A — behold navnene, herd oppsettet (anbefalt).

  • Sjekk DisableLocalAuth på ressursen. Er den ikke true: regenerer begge nøklene og sett den. Dette er den eneste tiltaket som fjerner en autorisasjonsvei Entra ikke dekker.
  • Sjekk at rolletildelingen står på prosjekt-scope og ikke bredere, og vurder Foundry Agent Consumer framfor Foundry User dersom kjøringene bare gjør inferens.
  • Sett et kostnadsvarsel på abonnementet og hold TPM-tildelingen på deploymentet lav. Kvotemisbruk blir da både begrenset og synlig.
  • Konsekvens: måleprotokollen forblir reproduserbar, ingen ny kjøring må betales, og navnene fortsetter å stå i historikken — som de ville gjort uansett.

Valg B — riv og bygg opp igjen med et intetsigende navn.

  • Kjøper: at et navn en motpart eventuelt sitter og venter på, ikke lenger peker på noe levende.
  • Koster: de sju stegene i §3, ny betalt verifiseringskjøring, og at docs/2026-08-14-fase1b-forste-levende-kjoring.md beskriver et oppsett som ikke finnes lenger.
  • Kjøper ikke: at navnene forsvinner fra historikken eller fra den leverte pakka.
  • Velg denne hvis vurderingen er at ressursgruppe- og prosjektnavnet i seg selv er sensitivt i organisasjonssammenheng — det er en vurdering operatøren kan gjøre og ikke jeg.

Valg C — gjør begge. Herdingen i A er verdt å gjøre uansett hvilket av A og B som velges; B uten A etterlater den samme nøkkel-veien åpen på en ny ressurs.

5. Hva denne vurderingen ikke dekker

  • Ingenting i Azure er inspisert. Alle utsagn om denne ressursens faktiske konfigurasjon (disableLocalAuth, publicNetworkAccess, rolle-scope) er markert som uverifiserte over.
  • Innholds-gaten fanger vertsnavnet, ikke ressursgruppe- og prosjektnavnet. Et vertsnavn har en struktur (<label>.services.ai.azure.com); en ressursgruppe heter hva som helst. De to andre navnene ble bare oppdaget fordi de sto i samme tabell som verten. En gate kan ikke lukke det gapet uten en navneliste, og en navneliste er den andre kopien av eksponeringsregelen.
  • Ordre-teksten sa at koordinatene fortsatt sto i repoet. Det er ikke tilfelle per 6d2837f — målt, se §3. Premisset var riktig da ordren ble skrevet (10:37Z) og sluttet å være det 13:03.

6. Kilder

Alle verifisert 18.08.2026 mot Microsoft Learn:

  • Custom subdomain kan ikke endres; må slette ressursen for å gjenbruke navnet — learn.microsoft.com/azure/ai-services/cognitive-services-custom-subdomains
  • Entra-auth krever custom subdomain; 401 vs 403; scope https://ai.azure.com/.defaultlearn.microsoft.com/azure/foundry/concepts/authentication-authorization-foundry
  • disableLocalAuth er en eksplisitt handling; propagering minutter til timer; nøkler må regenereres separat — learn.microsoft.com/azure/ai-services/disable-local-auth
  • Rolle-id 53ca6127-db72-4b80-b1b0-d745d6d5456d = Foundry User, offentlig og lik i hver tenant; Foundry Agent Consumer som minste-privilegium for ren inferens — learn.microsoft.com/azure/foundry/concepts/rbac-foundry
  • Kvote per abonnement/region/modell/deployment-type i TPM; deles av deployments i samme region — learn.microsoft.com/azure/foundry/openai/how-to/quota
  • publicNetworkAccess / disableLocalAuth som ARM-egenskaper — learn.microsoft.com/azure/templates/microsoft.cognitiveservices/accounts
  • Anti-subdomain-takeover-reservasjon (dokumentert for App Service / API Management, ikke for Cognitive Services) — learn.microsoft.com/azure/security/fundamentals/subdomain-takeover