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 archive77076b9` 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 -241b50dog6d2837flukket 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
199 lines
12 KiB
Markdown
199 lines
12 KiB
Markdown
# 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 repoet** — `241b50d` 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/.default` —
|
|
`learn.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`
|