Skip to content

IAM-åtkomstpolicyer ​

En åtkomstpolicy beviljar eller nekar en maskinprincipal — en API-nyckel eller en Workload Identity-bindning — behörighet att anropa Frostmoln-API:et. Den är Frostmolns motsvarighet till en AWS IAM-policy, GCP IAM eller Azure RBAC, men skriven i Frostmolns egen vokabulär.

En policy låter dig uttrycka minsta behörighet som en platt scope-lista inte kan: en enskild operation i stället för hela compute:write, en resurs, ett käll-IP-intervall, ett tidsfönster — och explicit neka. Till exempel: en CI-nyckel som får skapa instanser men aldrig ta bort dem; en Terraform-nyckel som bara fungerar från ditt kontorsnät; en SDK-nyckel som bara får röra resurser taggade env=staging.

Människor får sina rättigheter från organisationsroller — se Organisationsmedlemmar & roller för de fyra rollerna, ägarskapet och hur tenants, grupper och guardrails kombineras. Denna sida handlar om maskin-spåret.

Vem författar policyer ​

Åtkomstpolicyer styr maskinprincipaler, men de författas av en människa inloggad med OIDC (portalen, fm-CLI:t efter fm login, eller Terraform med en OIDC-backad provider). En API-nyckel eller ett workload-identity-token kan inte skapa, ändra eller koppla en policy — styrplanet kan aldrig låsas ute av en policy det själv omfattas av. Detta är avsiktligt: även en deny *-policy på din egen nyckel går att återställa, eftersom du åtgärdar den som människa.

Så fungerar utvärderingen ​

Utvärderingen är default-deny:

  1. Om någon deny-regel matchar nekas begäran — ett explicit deny vinner alltid, oavsett regelordning eller vilken policy det kom från.
  2. Annars, om någon allow-regel matchar, tillåts begäran.
  3. Annars nekas begäran (implicit deny).

En begäran matchar en regel när dess operation matchar en av regelns operations, dess mål-FRN matchar en av regelns targets, och alla regelns constraints håller.

Policydokumentet ​

En policy är ett JSON-dokument: en schemaVersion och en lista av rules.

json
{
  "schemaVersion": "1",
  "rules": [
    {
      "name": "compute-read-only",
      "access": "allow",
      "operations": ["compute:instances:read", "compute:instances:list"],
      "targets": ["frn:compute:*:*:instances/*"]
    }
  ]
}

Varje regel har dessa fält:

FältObligatorisktVärde
namenejEn läsbar etikett för regeln. Fritext; påverkar inte utvärderingen.
accessjaallow eller deny.
operationsjaIcke-tom lista av operationsmönster (se Operationer).
targetsjaIcke-tom lista av FRN-mönster (se Mål — FRN).
constraintsnejExtra villkor som måste hålla (se Villkor).

schemaVersion är strängen "1". Schemat är append-only och versionshanterat som resten av plattformskontraktet — nya funktioner läggs till, aldrig döps om eller tas bort, så en policy du skriver idag fortsätter fungera.

Operationer ​

En operation namnger en åtgärd i formatet service:resource:action, till exempel compute:instances:create eller storage:volumes:delete. Varje segment tar emot jokertecknet *, och jokertecken kollapsar på varje nivå:

  • compute:instances:create — en exakt operation
  • compute:instances:* — varje åtgärd på compute-instanser
  • compute:* — varje compute-operation
  • *:*:delete — varje delete, över alla tjänster

Mängden konkreta operationer är en serverägd, append-only-katalog — hårdkoda den inte, eftersom den växer över tid. Hämta den aktuella katalogen:

bash
fm iam catalog                 # all operations
fm iam catalog --filter compute   # only those containing "compute"

eller över HTTP:

bash
curl -H "Authorization: Bearer $TOKEN" \
  https://api.frostmoln.cloud/api/v1/tenants/$TENANT_ID/iam/catalog
# → { "operations": ["billing:invoices:create", "compute:instances:create", ... ] }

Portalens policybyggare presenterar samma katalog som en väljare.

Mål — FRN ​

Mål matchas mot ett Frostmoln Resource Name (FRN) — plattformens resursnamnschema, analogt med ett AWS ARN:

frn:<service>:<region>:<tenant>:<type>/<id>

I en regels targets skriver du FRN-mönster, med * för att jokerteckna vilket segment som helst:

  • * — matchar varje resurs (använd sparsamt)
  • frn:compute:*:*:instances/* — vilken compute-instans som helst, denna tenants
  • frn:storage:*:*:volumes/* — vilken volym som helst, denna tenants
  • frn:compute:*:*:instances/i-0a1b2c3d — en specifik instans

Segmentet <region> måste vara *

Regionsbegränsade policyer stöds inte ännu: en begäran bär ingen upplöst region, så ett mål som namnger en region kan inte matchas tillförlitligt. Skriv alltid * där — ett mål med något annat avvisas när du sparar policyn. Alla övriga segment fungerar som beskrivs ovan.

Segmentet <tenant> är din tenant

Låt <tenant> vara *: eftersom varje begäran bär med sig din egen tenant syftar * redan på din tenant och ingen annan. Du kan även skriva ditt eget tenant-id explicit, men ett mål som namnger en annan tenant avvisas när du sparar — det skulle aldrig kunna matchas, så regeln skulle inte ha någon effekt.

Villkor ​

Villkor lägger till förutsättningar på en regel. En regels constraints är en map med nyckel på operator, sedan på villkorsnyckel:

json
{
  "name": "read-staging-from-office",
  "access": "allow",
  "operations": ["compute:instances:read"],
  "targets": ["frn:compute:*:*:instances/*"],
  "constraints": {
    "ipInRange": { "frn:sourceIp": ["203.0.113.0/24"] },
    "equals": { "frn:resourceTag/env": "staging" }
  }
}

Villkorsnycklar ​

NyckelBetydelse
frn:regionGår inte att använda ännu. En begäran bär ingen upplöst region, så nyckeln kan aldrig lösas upp: ett allow som använder den beviljar aldrig, och ett deny som använder den fyras i varje region. Utelämna den.
frn:sourceIpAnroparens käll-IP.
frn:tenantTenant-id:t.
frn:principalTypePrincipalens typ: api_key eller workload_identity.
frn:currentTimeBegärans tidpunkt (för before/after).
frn:requestTag/<k>Värdet på request-taggen <k>.
frn:resourceTag/<k>Värdet på taggen <k> på målresursen.

Operatorer och värdeformer ​

OperatorVärdeformAnteckningar
equalsen enskild strängExakt matchning.
notEqualsen enskild strängNegerad exakt matchning.
likeen enskild strängGlob-matchning (jokertecken *).
ipInRangeen lista av CIDR-strängarAnvänds med frn:sourceIp.
beforeen enskild RFC3339-tidsstämpelAnvänds med frn:currentTime.
afteren enskild RFC3339-tidsstämpelAnvänds med frn:currentTime.

ipInRange är den enda operatorn som tar en lista; varje annan operator tar en enskild skalär sträng. En okänd nyckel eller operator, eller ett värde ett villkor inte kan resolva vid begärans tidpunkt, failar closed — villkoret håller inte (så ett allow beviljar inte), och ett deny fyras fortfarande.

⚠️ Ett villkor på ett deny smalnar av det ​

Detta är det enskilt viktigaste att få rätt. Villkor tillämpas på samma sätt på allow- och deny-regler: en regel matchar bara när dess villkor håller. Så ett villkor på en deny-regel gör att neket fyras endast när villkoret är definitivt sant — vilket lämnar operationen tillåten närhelst villkoret är definitivt falskt. (Ett olöst eller okänt villkor fyrar ändå neket — fail-closed.)

  • För att förbjuda en operation ovillkorligt, skriv en deny-regel utan villkor.
  • För att begränsa en beviljning (till ett käll-IP, ett tidsfönster, en resurstagg), lägg villkoret på allow-regeln.
json
{
  "schemaVersion": "1",
  "rules": [
    {
      "name": "create-read-from-office",
      "access": "allow",
      "operations": ["compute:instances:create", "compute:instances:read"],
      "targets": ["frn:compute:*:*:instances/*"],
      "constraints": { "ipInRange": { "frn:sourceIp": ["203.0.113.0/24"] } }
    },
    {
      "name": "never-delete",
      "access": "deny",
      "operations": ["compute:instances:delete"],
      "targets": ["*"]
    }
  ]
}

allow är nätverksbegränsat av sitt villkor; deny är ovillkorligt, så delete är förbjudet alltid. Ett villkor på det deny skulle ha tillåtit deletes närhelst villkoret var falskt.

Författa en policy ​

Författa i portalen, med fm-CLI:t eller med Terraform. En policy skrivs en gång och kopplas sedan till en eller flera principaler.

Portal ​

Öppna IAM → Access Policies, välj New policy och använd den guidade byggaren — välj operationer från katalogen, lägg till mål och villkor, och använd den inbyggda testaren för att kontrollera en begäran innan du sparar. Öppna sedan en principal (API-nyckel eller workload identity) och koppla policyn.

fm CLI ​

bash
# Create from a file, stdin, or inline JSON
fm iam policy create --name ci-compute-operator --document @policy.json
cat policy.json | fm iam policy create --name ci-compute-operator --document -

# List / inspect / update / delete
fm iam policy list
fm iam policy get <policy-id>
fm iam policy update <policy-id> --document @policy.json
fm iam policy delete <policy-id>

# Attach to a principal (api_key | workload_identity | group)
fm iam policy attach <policy-id> --type api_key --id <key-id>
fm iam policy detach <policy-id> --type api_key --id <key-id>

Terraform ​

Komponera dokumentet med datakällan frostmoln_iam_policy_document (inbyggd vokabulär — rule / access / operations / targets / constraint), skapa sedan policyn och koppla den:

hcl
data "frostmoln_iam_policy_document" "ci" {
  # Restrict the grant with a constraint on the ALLOW rule.
  rule {
    name       = "create-read-from-office"
    access     = "allow"
    operations = ["compute:instances:create", "compute:instances:read"]
    targets    = ["frn:compute:*:*:instances/*"]

    constraint {
      operator = "ipInRange"
      key      = "frn:sourceIp"
      values   = ["203.0.113.0/24"]
    }
  }

  # Forbid delete unconditionally — a deny with NO constraint.
  rule {
    name       = "never-delete"
    access     = "deny"
    operations = ["compute:instances:delete"]
    targets    = ["*"]
  }
}

resource "frostmoln_iam_policy" "ci" {
  name        = "ci-compute-operator"
  description = "CI: create/read compute from the office network, never delete"
  document    = data.frostmoln_iam_policy_document.ci.json
}

resource "frostmoln_iam_policy_attachment" "ci_key" {
  policy_id     = frostmoln_iam_policy.ci.id
  attachee_type = "api_key" # or "workload_identity" / "group"
  attachee_id   = frostmoln_api_key.ci.id
}

ipInRange tar en lista av CIDR:er; varje annan operators values är ett enskilt element. Datakällan avvisar en lista med flera värden på någon annan operator.

Grupper ​

För att koppla samma policy till flera principaler, skapa en grupp, lägg till principaler i den och koppla policyn till gruppen:

bash
fm iam group create --name ci-keys
fm iam group member add <group-id> --type api_key --id <key-id>
fm iam policy attach <policy-id> --type group --id <group-id>

En medlem är en api_key eller en workload_identity; en policy kopplas till en api_key, en workload_identity eller en group.

För att ge samma policyer till människor i stället för nycklar, se Medlemsgrupper nedan.

Medlemsgrupper ​

Grupperna ovan samlar maskinprincipaler. Medlemsgrupper samlar människor: en jourgrupp eller ett team av dataansvariga kan anläggas för att ärva principer om lägsta möjliga behörighet som grupp, i stället för att en skräddarsydd roll skapas per person. De talar samma vokabulär som alla åtkomstpolicyer på denna sida — operationer, FRN-mål, villkor — och de kopplar samma delade policydokument som maskingrupperna ovan använder.

Registrerade, ännu inte verkställda för personer

Medlemsgrupper hör till hela organisationen i stället för till en enskild tenant: en organisations ägare eller administratör hanterar dem.

I den här versionen registreras de policyer du kopplar till en medlemsgrupp, men de konsulteras inte ännu när en persons anrop utvärderas — inget i dem får effekt för människor ännu. Medlemmarna behåller exakt vad deras organisationsroll ger, tills utvärdering av åtkomstpolicyer för människor slås på plattformsvist; ställer du in grupperna nu går dessa beviljanden live med den omkopplaren. Maskinprincipaler påverkas inte av detta: åtkomstpolicyer på API-nycklar och arbetslastidentiteter utvärderas redan enligt beskrivningen på denna sida.

Du hittar dem under Organisationer → din organisation → Medlemsgrupper:

  1. Skapa en grupp — ett namn (unikt inom organisationen) och en valfri beskrivning. Namn kan inte ändras från portalen ännu; ta bort och skapa gruppen på nytt om du behöver ett annat.
  2. Lägg till medlemmar — välj bland organisationens medlemmar. Vilken administratör som helst kan lägga till eller ta bort valfri medlem, ägaren inkluderad; ingen kan lägga till sig själv (portalen döljer den inloggade användaren och API:t avvisar försöket ändå).
  3. Koppla delade åtkomstpolicyer — välj bland de delade policyer som författats i organisationens tenants; du kan koppla bort en när som helst. Gruppens medlemmar är anlagda att ärva allt dessa policyer tillåter, utöver vad deras organisationsroll redan ger — se nedan vad som får effekt i den här versionen. (fm och Terraform kan ännu inte författa medlemsgrupper; portalen är författarytan.)

Vad medlemsgrupper betyder för medlemmarna ​

  • Grupper lägger bara till — de tar aldrig bort. En medlem behåller sin rolls behörigheter, och varje kopplad policy utvärderas ovanpå rollen, aldrig i stället för den. Det finns ingen medlemsgruppsinställning som tar bort en medlems rollbehörigheter.
  • Ingen neka för medlemsgrupper i v1. En deny-regel i en policy som är kopplad till en medlemsgrupp begränsar inte människor, och i den här versionen ger dessa policyers allow-regler inte heller något till människor — inget kopplat till en medlemsgrupp påverkar utvärderingen för människor ännu. När ärvd behörighet blir aktiv beviljar medlemsgrupper endast additivt; uttryckliga neka-regler förblir ett maskinprincipal- fråga till en senare version. (Neka-regler på API-nycklars och arbetslastidentiteters policyer verkställs redan i dag.)
  • Inget tak vid körning. Om två kopplade policyer båda tillåter en operation har en medlem den; det finns ingen körtidskontroll i stil med »gruppen får aldrig överskrida den administratörs behörigheter som kopplade den«. Skyddet ligger per dokument vid kopplingstillfället: en koppling som överskrider den kopplande administratörens egna behörigheter avvisas.
  • Inget att applicera. Portalen har ingen knapp för att applicera eller verkställa — plattformen styr när ärvd behörighet får effekt, och (när den är aktiv för människor) når en ändring en medlem vid dennas nästa tokenvalidering: senast vid den aktuella sessionens nästa tokenförnyelse.
  • Medlemskapet är beständigt. Medlemskapet överlever rolländringar och pausningar: byter du någons organisationsroll följer deras gruppmedlemskap med. (En pausad medlem erhåller ingen behörighet alls medan de är pausade, oavsett vad deras grupper säger — men raden finns kvar i listan, så gå igenom den vid nedgradering eller pausning.) Att ta bort någon från organisationen stänger också av deras åtkomst.
  • Att ta bort en grupp raderar dess registrerade medlemskap och policykopplingar för alla i den — medlemskap kaskadas och kopplingarna tas bort, så när ärvd behörighet är aktiv förlorar dess medlemmar omedelbart det gruppen hade gett.

Skyddsregler ​

Medlemsgrupper lägger till behörighet; skyddsregler tar den från bordet. En skyddsregel fäster en policy som innehåller enbart nekningsregler på organisationsnivå — eller på en enhet i organisationens enhetsstruktur — och dess nekningsregler binder sedan alla under kopplingspunkten, ägaren inkluderad. Det är golvformen företagsstyrning efterfrågar: "ingen roll, inget bidrag, ingen gruppjustering kan låta någon läsa dessa resurser eller radera dessa tjänster." Endast plattformens egen personal undgår en skyddsregel, med design.

Registrerade banor, ännu inte verkställda för personer

Skyddsregler delar medlemsgruppernas hållning: de kopplas och lagras i dag, och vad en skyddsregel gör för en persons anrop följer samma plattomfattande omkoppling som väcker utvärdering av åtkomstpolicyer för personer — samma som medlemsgruppsavsnittet ovan väntar på. Tills den slår om i din miljö förändrar en kopplad skyddsregel ingenting för någon; när den gör det träder nekingen i kraft vid medlemmens nästa tokenvalidering. Maskinprincipaler (API-nycklar, arbetsidentiteter) binds aldrig av skyddsregler — det här är en personaxel.

Hitta dem under Organisationer → din organisation → Skyddsregler (samma ägare-eller-admin-tröskel som medlemsgrupper):

  1. Koppla en skyddsregel — välj omfattningen (Organisation binder alla; en enhet binder allt i dess gren av enhetsträdet) och fäst en policy som innehåller enbart nekningsregler. Ett dokument med tillståndsregler avslås — en skyddsregel får aldrig tyst bevilja.
  2. Koppla bort — den enda sanktionerade vägen att ta bort ett golv. Den granskningsloggas med aktörens namn, och medlemmarnas token löses om utan den vid nästa validering.

Vad skyddsregler betyder i praktiken ​

  • Nekning vinner, punkt. En skyddsregels neking slår grupppolicyer, custom- roller, förvalda roller och läsåtkomst. Ägarens täckande * ger inget som en skyddsregel förbjuder.
  • Författandet vägrar konflikter innan de existerar. Plattformen vägrar (GUARDRAIL_CONFLICT) en skyddsregel som överlappar något organisationen redan beviljat via en grupp eller ett skräddarsydd roll — och vägrar, i andra riktningen, en gruppkoppling eller rolleditering som skulle krocka med en stående skyddsregel. Avslaget namnger operationen; att minska beviljningen (eller koppla bort skyddsregeln, vilket i sig granskningsloggas) är återvägen. Plattformen är medvetet överförsiktig här: en neking fäst vid en enda exakt resurs kan vägra en bredare beviljning i samma familj tills du delar dokumentet.
  • Det fästa dokumentet är låst. Medan en policy är fäst som skyddsregel kan den inte redigeras eller tas bort via den ordinarie policynytan (GUARDRAIL_PINNED) — en tyst redigering vore en tyst lättnad. Koppla bort först, redigera sedan; en organisationsenhet med en fäst skyddsregel kan heller inte raderas.
  • Enheter följer sin koppling. En skyddsregel fäst på en enhet når varje tenant inuti den — att flytta en tenant frågar inget och ändrar inget på pappret, men det som binder den vid nästa tokenvalidering är vad enhetsträdet nu säger.
  • Endast metadata. Fliken skyddsregler visar själva kopplingen — nivå, enhet, policy-id — aldrig policyns innehåll; reglerna ligger kvar på policyns egen yta.

Egenutformade roller ​

Utöver de fyra inbjudningspresets (visare, medlem, fakturering, administratör) kan en organisation bära egenutformade roller: namngivna behörighetsuppsättningar ur samma family:action-katalog som alla åtkomstpolicyer på denna sida. Dessa roller skapas i dag via roll-API:t (POST /tenants/{tenant_id}/roles — portalens väljare listar dem, den skapar dem inte ännu).

Egenutformade roller som inbjudningsplatser. När organisationen har egenutformade roller erbjuder inbjudningsdialogens rollväljare dem jämte presets. En sådan roll refereras till med sitt id, måste tillhöra din egen organisation och kontrolleras om igen då inbjudan accepteras. Två tak skyddar beviljandet:

  • En administratör kan bara bevilja en uppsättning hen själv innehar — såväl vid skapandet av rollen som vid inbjudan till den. En roll bredare än beviljarens vägras (ROLE_EXCEEDS_PERMISSIONS).
  • Ägarens * täcker allt, så en ägare kan alltid förse någon med vilken roll som helst i organisationen.

Vad en egenutformad roll innebär för innehavaren. Rollens uppsättning reser med tokens precis som en presets gör. Där utvärdering för människor är påslagen — samma plattformsomkopplare som medlemsgrupperna ovan väntar på — är det rollens uppsättning motorn väger; tills dess ändras inget för deras resursanrop. Egenutformade roller är alltid nivå 0 i förvaltningsstegen: de kan inte beviljas eller ändras via medlemsförvaltningen (endast inbjudningsflödet placerar någon i dem), men en medlem som innehar en är fortfarande fullt åtkomlig för borttagning, avstängning, återupptagning och nedgradering — de inneslutningsverb en organisationsadministratör redan har.

Testa innan du sparar ​

En felförfattad policy har verkliga tänder i produktion, så testa den först. Testaren (portalbyggaren, eller fm iam simulate) kör ett kandidatdokument mot en hypotetisk begäran och returnerar allow eller deny — den persisterar eller upprätthåller aldrig något:

bash
fm iam simulate --document @policy.json \
  --operation compute:instances:delete --target '*'
# → deny

fm iam simulate --document @policy.json \
  --operation compute:instances:read --target 'frn:compute:*:*:instances/*' \
  --source-ip 203.0.113.10
# → allow

Flaggor för villkorskontext: --source-ip, --tenant, --principal-type, --request-tag key=value, --resource-tag key=value. Ett utelämnat villkorsfält behandlas som unresolved / fail-closed, precis som i produktion. (--region finns också, men frn:region går inte att använda ännu — se Villkorsnycklar.)

Migrera från scopes ​

Dina befintliga API-nyckel-scopes (compute:read, storage:write, …) fungerar fortfarande — varje äldre scope utvärderas som en likvärdig syntetiserad allow- policy, så det finns noll påtvingad migrering. compute:read beter sig som ett allow över compute read/list-operationerna på frn:compute:*.

Du migrerar en nyckel till en riktig policy med minsta behörighet när du vill ha något scopes inte kan uttrycka. Till exempel att ersätta ett brett compute:write-scope:

compute:write beviljar create och update och delete på varje compute- resurs, från var som helst. En ersättning med minsta behörighet kan vara:

json
{
  "schemaVersion": "1",
  "rules": [
    {
      "name": "create-and-update-from-office",
      "access": "allow",
      "operations": [
        "compute:instances:create",
        "compute:instances:update",
        "compute:instances:read",
        "compute:instances:list"
      ],
      "targets": ["frn:compute:*:*:instances/*"],
      "constraints": { "ipInRange": { "frn:sourceIp": ["203.0.113.0/24"] } }
    },
    {
      "name": "never-delete",
      "access": "deny",
      "operations": ["compute:instances:delete"],
      "targets": ["*"]
    }
  ]
}

Steg:

  1. Författa policyn (ovan) och testa den med fm iam simulate mot de operationer din arbetsbelastning faktiskt utför.
  2. Koppla den till nyckeln.
  3. Smalna av scopen på nyckeln (policyn är additiv; både den syntetiserade scope-policyn och din kopplade policy utvärderas, och varje explicit deny vinner). Ta bort det breda compute:write-scopet när den kopplade policyn täcker det nyckeln behöver.
  4. Kör fm iam simulate igen (eller följ nyckeln i portalen) för att bekräfta att beviljningarna och nekningarna är vad du förväntar dig.

Eftersom ett explicit deny åsidosätter varje allow håller regeln never-delete ovan även medan det äldre scopet fortfarande finns kvar — ett säkert sätt att strama åt en nyckel innan du är klar med att ta bort dess scopes.