Skip to content

Feat/iga enforcement - #100

Open
apauthnull wants to merge 75 commits into
authsec-stagingfrom
feat/iga-enforcement
Open

apauthnull wants to merge 75 commits into
authsec-stagingfrom
feat/iga-enforcement

Conversation

@apauthnull

Copy link
Copy Markdown
Contributor

Description

Changes

Testing

  • Unit tests pass (go test -short ./tests/unit/)
  • go vet ./... clean
  • Manual testing (describe below)
  • Add label run-integration to this PR to trigger integration tests in CI (requires a live DB)

Checklist

  • Code follows the project's style guidelines
  • Self-reviewed the diff
  • No secrets or credentials committed
  • Updated documentation if needed
  • Added/updated tests for new behaviour

amanpd7 and others added 30 commits October 23, 2026 14:06
…erves (AS-118)

Since 2e081fa the Microsoft callback sent the browser, with the onboarding
session id in the URL, to any verified custom domain of the workspace that
started the flow. Verification proves DNS control, not that AuthSec serves
the host. A workspace admin could start onboarding from their own domain,
send the authorize URL to another company's Global Admin, receive the
session id on their host and connect that tenant into their workspace.

The return origin is now the configured UI origin or the workspace's own
domain under TENANT_DOMAIN_SUFFIX. TestAzureReturnOriginIsTheWorkspacesOwn
now refuses a verified custom domain (it accepted one before).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…and allows (AS-119..121)

AS-119: a block that ended restored every assignment it had removed, even
while another block on the principal still needed them gone -- an edited
policy's new version (which found nothing left to record) or a second
policy. It now hands them to that block, which restores them when it ends;
an approved row holding handed assignments ends through expiring. The
write-ahead appends to revoked atomically instead of rewriting it.

AS-120: a block and an allow on the same principal and overlapping scopes
are refused in preview (azure_policy_conflict); a block never records
AuthSec's own allow assignments, which it would have restored as standing
access.

AS-121: outside storage a block matched only management actions, leaving
data roles (Key Vault Secrets User, ...) while the policy read active. "all"
now removes roles with data actions in the provider; read/write/delete with
such a role is refused (azure_data_access_unclassified) until the service is
mapped.

Tests: TestAccessPolicyAzureOverlappingBlocks, TestAccessPolicyAzureBlockAndAllow,
TestAccessPolicyAzureNonStorageData (each fails on the old code).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…restores first (AS-122, AS-123)

AS-122: a block's restore retried forever when Azure could never accept it
(the principal deleted in Entra, the role or resource gone), so the policy
stayed "ending" and could not be deleted. Such an assignment is now skipped,
recorded (NotRestored op, state reason) and the row ends. Transient errors
still retry and keep the policy undeletable.

AS-123: a block whose deploy failed after an earlier attempt had removed
assignments went straight to failed, leaving them removed. It now restores
them, then ends failed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The IaC-only remedy named /iga/policy/setup and the owner/eligibility ones
/iga/policy/findings, both removed from the console when policy setup moved
onto the connection pages. They now name the connection's IaC tab and the
role's identity page. Slack's links keep /iga/policy/setup/notifications,
which the console forwards to a connection's Notifications tab (UI change).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r keys (AS-125)

TestPhase3ForeignKeyCatalogGuard failed on its table count since 137 and
144 added iga_gov_access_policy_version and iga_gov_azure_access, and the
Fatalf stopped it before the key checks. With the count at 59 those checks
run: 144's connector_id and identity_account_id are listed as
iga_gov_temp_grant's are (a record of what was changed in the cloud,
written from the workspace's own rows under RLS), and both tables'
created_by as user references.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…AS-126)

ConnectCustom proved each subscription with two ARM reads (the subscription,
then the app's role assignments) one at a time inside the 105s connect
budget, so a tenant with a few dozen subscriptions timed out. The reads now
run 4 at a time, as the managed flow's do, in customSubscriptionReads; the
results and the over-privileged warning keep the subscriptions' order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Since the switch removal (2784c81) new enforcement bindings were offered
template v2 regardless, so a server whose R2 schema (061) had not verified
asked customers for v2's wider IAM rights it could not use. v2 now follows
the R2 gate (schema verified), as it followed IGA_POLICY_R2 before; v1
otherwise. The enforcement lab installs a verified R2 gate (and the
process-wide policy gate R2 reads).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Before access documents go through a per-service target (DynamoDB tables
next), pin what S3 produces today. TestAccessGolden builds nine S3 cases
through AccessDocument and AccessSentence and checks each document's
bytes (testdata/golden/access.s3.*.json, sha256sum gives the hash), its
hash, the actions and resources returned and the preview sentence
(testdata/access_golden_hashes.json). Cases: block read of a folder, of a
60-character folder (partial list guard), block write of a folder, block
all of the whole bucket without an end, block all of a folder, allow read
of the bucket, allow write with a start, allow read+write+delete of a
folder, and block read in aws-us-gov. Rewrite only on purpose:
go test ./internal/igagov -run TestAccessGolden -update-access.

TestAccessPolicyLifecycle now checks the preview warnings exactly, codes
and messages in order: block of a folder, allow, block of a long folder,
block of writes. No production code changes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…through them

Access policies named S3 throughout internal/igagov/access.go. A resource
type is now a target (AWSAccessTarget: the parsed ARN, its statements,
preview notes and sentence) registered in AccessKinds(), and
BuildAccessDocument adds the effect and window and does the canonical form,
size limit and hash for every type. S3Target is the first target; the S3
goldens pinned in 71a413a are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…AWS target

plan() resolves an AWS resource with igagov.ParseAWSAccessTarget instead of
the S3 parser, takes the preview notes and other_paths from the target, and
the view is built from it. The view gains resource_type (s3_bucket,
azure_resource, ...; kind stays the Discovery row's kind) and region (set
when the ARN names one). S3 and Azure behaviour is otherwise unchanged: the
lifecycle test pins the exact warnings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A block denies the chosen item actions on the table and everything under it,
plus the other ways to the same data: for read the stream, export to S3,
restore from backup or point in time, AWS Backup jobs, Kinesis streaming,
cross-account replicas, every PartiQL write, and writes that ask for the
item back (ReturnValues); for delete, DeleteTable and TTL changes; for
read, write and all, creating a replica in any region (checked on the
replica's ARN, not the table's). An allow grants item access only, on the
table and its indexes (DescribeTable with read); without read, no PartiQL
and no ReturnValues.

Checked against the AWS Service Authorization Reference for DynamoDB; the
points it cannot settle fail safe, and the write-whose-condition-fails
read-back (no IAM key exists) is a preview note. Expected documents are
written by hand in the test, with parse cases, notes, and properties over
every access combination (size and deployment-row limits, no widening on
allow, no escalation).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A Discovery row that points at one DynamoDB table (the table, an index, a
stream, ...) can be the resource of an access policy. A table's ARN names
its account, so it is placed by it rather than by which scans saw it: a
block may name a table in another account (an identity Deny works there),
an allow only one in the role's own account (resource_other_account), and
a row no current scan supports is refused (resource_not_current). Patterns
and global-table ARNs are refused with a message saying so. Capabilities
list the access types (policy.access_policies.resource_types).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pace

Preview through an index row (document equals the target's, exact notes),
create, apply, view fields, re-apply after a detach, edit to an allow, end;
the refusals (prefix, pattern, global table, cross-account allow, stale
row, allow all) on preview and create; a cross-account block is accepted;
another workspace's table row and policy are 404.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t read it as SQL

"UPDATE and DELETE" in a preview note looked like an UPDATE of a table
named "and" to scripts/ci-iga-isolation-check.sh (TestIsolationCheckPassesOnThisTree).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… "Reader denied" (AS-126)

Any failed read while proving a subscription was recorded as
permission_denied, so a timeout or throttling told the admin to assign a
Reader role their app may already hold, and the connector carried
auth_refused. A passing failure (azureTransient) is now not_checked: the
connector records a timeout or throttled error saying to verify again, and
the connect result warns with the subscriptions' names.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…it ends (AS-129)

A failed row is terminal and never worked again, and End, Pause and Delete
skip it, so an access-policy deployment that failed after attaching (a
re-apply that found AuthSec's document rewritten outside AuthSec, an
attach refused after the create) left its policy on the role. Such a row
now goes through the removal and ends failed with its reason kept.

Removing a policy that holds versions AuthSec did not write retried every
30 minutes forever. Once it is detached and used by nothing else it is
left for its owner and recorded as drift (document_changed), so removal
finishes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… (AS-130)

"${" starts a policy variable in IAM's 2012-10-17 language, so a folder
named a${aws:username}/ matched each caller's own name. The object ARN and
every s3:prefix value now write "$" as "${$}".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…xt check (AS-131)

The active check and the re-apply wrote "WHERE state = active" without
looking at the result, then re-scheduled the 10-minute check. When End or
Pause moved the row meanwhile (they pull forward only a queued job, not a
running one), removal waited up to 10 minutes, and a re-apply in flight put
the policy back on the role for that time. Those writes now require the row
still active; otherwise the job reruns at once for its new state.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ck is drift, not active (AS-132)

The 10-minute check of an active Azure block ignored access the principal
gained later at a broader scope (a subscription-wide role): AuthSec cannot
remove it from one resource, so the block no longer held while the policy
read "active". The check now records drift azure_inherited_access with the
scopes in the reason (the policy reads drift), emits one drifted event, and
clears it once the broader assignment is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…133)

The Azure access schedule returned nothing while R2 was unavailable, so an
allow past its end kept its role assignment: Azure assignments have no
expiry of their own, unlike AWS documents bounded by aws:CurrentTime. The
schedule now still queues rows that are ending or past their end, and the
handler does removals only (no deploys or checks) until R2 is back.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d description (AS-134)

SpecOf, what an Azure block records to restore, kept the condition but not
its version or the description, so a restore wrote a different assignment.
Both are now read from ARM and put back. AS-135 (PIM activations restored
as permanent assignments) is recorded open: it needs a live tenant.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ed, not applying (AS-136)

Azure rows wait approved until their start, which the status read as
applying. An approved row before its start now counts as scheduled. The
provider column of an access policy's iga_gov_policy row stays aws (the
family's, 049 admits nothing else); a comment says so (AS-137).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…se, Resume and Delete

The staging review found cross-workspace coverage only for Get, End,
Events and List. Edit, Pause, Resume and Delete on another workspace's
policy answer 404 and leave it as it was; a preview or create naming
another workspace's role is refused as not found without showing it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ow (AS-138, part)

The R1a audit walker exempted the access-policy routes since they began
serving. TestAccessPolicyRoutesAudited calls create, edit, pause, resume,
end and delete over HTTP as the console does and asserts each audit_events
row; the walker now points at it. The 21 R2/R3 routes stay listed as not
yet asserted (their handlers do return an audited record on success).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… deletes (AS-139)

Azure has no built-in role for blob write alone: an allow of write or delete
assigns Storage Blob Data Contributor, which also reads and deletes. The
preview now says what else the role allows, as it already did for
Contributor.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… azure_access (AS-140)

VerifyAzureAccessSchema looked for the table only. A job-kind CHECK
re-created without azure_access (as 133 once dropped R2's kinds, AS-115)
would refuse every Azure deployment's job while Azure policies read
available. It now requires the CHECK to admit the kind, as R2's check does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… (AS-141)

A role at IAM's default quota of 10 managed policies was refused, though
accounts may raise it to 20 and AuthSec cannot read the account's quota.
From 10 the preview warns (quota_may_be_reached); if AWS refuses the
attach, the failed deployment is removed (AS-129). At 20, the most IAM
allows, it is still refused before anything is written.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… policies (AS-142)

Status is worked out per policy, so the list reads the workspace's policies
and filters in memory, capped at 1000 with no sign it stopped. ListPage
reports truncated (meta.truncated) when more than 1000 match the search;
List keeps its shape.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
amanpd7 and others added 30 commits October 24, 2026 11:24
An allow on a block-only type is refused (access_policy_invalid) in
preview, create and edit. A secret's name is checked against ListSecrets
of the latest published scan of its own account: a complete scan that
does not list it refuses with resource_not_current (a partial ARN such as
prod/db-backup reads as prod/db, and a secret scheduled for deletion is
not listed); without a complete scan the preview warns
existence_not_verified. Capabilities list block_only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A data plane for microsoft.cognitiveservices/accounts (and its
deployments): read is every inference call and the stored data, write
and delete the data plane's files, fine-tunes, assistants, responses,
batches and deployments; every level hands out account keys. An allow
assigns Cognitive Services OpenAI User or Contributor (GUIDs and action
names checked against Microsoft's built-in roles and operations pages),
warning what OpenAI User allows beyond read. An account without a custom
subdomain takes keys only and is refused (azure_ai_keys_only); one that
also takes keys is warned (azure_ai_keys_also). Other data planes of an
AI Services account (Speech, Language...) stay unclassified unless the
block is all.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A block denies the parameter's ARN; read also denies
GetParametersByPath on the root and every path above it, because AWS
authorizes a listing on the path only (a role denied /a/b can list /a
recursively and read it), and warns that listing those paths is refused.
Read includes GetParameterHistory (it returns the current value) and
tags. Allow is refused, as for Secrets Manager; the block-only refusal
names the type's noun.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(AS-159)

The service reference lists Put/DeleteResourcePolicy on parameters:
sharing a parameter with another account hands its value on, as for a
Secrets Manager secret.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…k only (step 6, AS-160)

Three block-only types, action tables from the AWS service reference
(servicereference.us-east-1.amazonaws.com):
- a model, picked through its foundation-model ARN or a system
  inference profile of it: denied in every region with the profiles that
  route to it, plus InvokeModel on * held to bedrock:ModelArn (application
  profiles and prompt routers); read is calling it, write building on it,
  delete is refused (nothing to delete);
- a Bedrock agent: every alias and version;
- an AgentCore runtime: the runtime and every endpoint.
Discovery already finds agents and runtimes as workloads, which IAM
policies seldom name one by one: the resolver now accepts a Bedrock agent
or AgentCore runtime by its workload id (ARN from its recognition key,
placed by the workload's support rows), in previews, policies and views.
A document's field error (access) keeps its field.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… Event Hubs (step 7, AS-161)

Data planes for storage queues (messages), tables (entities), file
shares (SMB roles), Service Bus and Event Hubs namespaces and entities
(receive is read, send is write; delete refused; an allow names one of
them: no built-in role sends and receives without managing the
namespace). A storage account block now covers every data service of the
account and every way to a key or SAS (listKeys, listAccountSas,
listServiceSas); an allow on the account stays blobs and says so.
Role GUIDs and action names checked against Microsoft's built-in roles
and permissions pages.

Fixes on the way: a plane's data prefix decides which roles can reach it
(a blob role on the account no longer counts on a queue), wildcard data
actions (Microsoft.Storage/*) count; the auth-mode read goes to the
top-level resource, so an OpenAI deployment, a search index or a Service
Bus queue reads its parent's settings instead of being refused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(step 8, AS-162)

Action tables from the AWS service reference:
- Lambda: a block covers the function, its versions and aliases; read is
  invoking, the code and the configuration, and every hand-off of
  invoking (resource policy, function URL). An allow covers invoking
  only. A function URL with auth type NONE takes no IAM: the preview
  reads the function's resource policy from the last complete scan of
  its account and warns function_url_public.
- KMS keys (block only): read decrypts and grants, write encrypts, signs
  and administers, delete destroys (deletion, disabling, imported
  material). A multi-Region key is denied in every Region.
- SQS: block every level and its hand-offs; allow the message actions
  of each level (never purge, delete queue or policy).
- SNS: block subscribing, publishing, deleting and hand-offs; an allow
  covers publishing only.
The latest-complete-scan lookup is shared with the secret check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eps 7-8, AS-161, AS-162)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
access_policies.types lists every AWS type with its service, noun,
prefix, whether it is block only, the levels a block may name and the
levels an allow may name (AccessKindViews), so the console reads them
from the server instead of repeating them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A sweep was given generation MAX+1 on arrival, so an older snapshot that
arrived later was projected as the newest reading and ended grants a
newer sweep had confirmed. A snapshot whose sweep_started_at is not after
the last non-failed sweep of its source and cluster is now refused whole
with 409 sweep_stale (not retryable). Docs: the Kubernetes enforcement
prerequisites and what remains (K-2, K-3, instruction kinds).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s check it (AS-160)

AWS's inference-profile prerequisites show a global cross-Region profile
checking arn:aws:bedrock:::foundation-model/<model> (no Region); the
block now denies that ARN explicitly instead of relying on the Region
wildcard. Whether application profiles and prompt routers are also
checked on the model is not settled by AWS's documentation; the preview
now says so (app_profiles_unverified).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rite (AS-156)

Checked against Microsoft's permissions page: Microsoft.KeyVault/vaults/
secrets/write is a management action that sets a secret's value through
ARM, so a role holding it (Contributor, Key Vault Contributor) could still
write secrets under a write or delete block. It now counts with the key
actions; a broader assignment holding it is reported as inherited access.
Every Azure role GUID and data action in the planes now matches Microsoft's
built-in roles and permissions pages.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An access policy may name a Kubernetes Role or ClusterRole (by its graph
id) and ServiceAccounts. A block takes each ServiceAccount out of every
binding of the role that names it, through the in-cluster agent, and
puts it back into the same binding at the end:
- migration 146: iga_gov_k8s_access (one row per ServiceAccount and
  binding, RLS), job kind k8s_access, instruction kinds
  remove_binding_subject / restore_binding_subject, and
  discovery_sources.enforcement_bindings (the agent's own switch,
  reported on the enforcement-plan poll as bindings=);
- the k8s_access job queues the instruction in its own workspace
  transaction, waits for the agent's result (the binding's uid), checks
  every 10 minutes whether a later sweep shows the subject back (drift:
  removed again), and restores with the recorded uid (a deleted or
  re-created binding is reported, not touched);
- only all access, block only; refused: an agent that may not change
  bindings, a ServiceAccount with no binding of the role, a second live
  block on the same subject and binding; another workspace's role is 404;
- views, list (provider=k8s), status and ending include the rows;
  capabilities report access_policies.k8s.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the subject out of (AS-165)

The agent names a binding's uid only when it actually removed the
subject. When a later removal (drift) is the one that took it out, or
the binding was re-created meanwhile, the row now keeps that uid, so the
end restores into the binding the subject really came out of.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…_id)

What the console picks as a Kubernetes access policy's resource: the
role a ServiceAccount holds a binding of.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-138)

TestP3R2R3RoutesAudited calls the 21 routes over HTTP on the
access-policy lab: temporary grants (request, approve, revoke, reject),
session revocations (request, approve, lift, reject), runtime policies
(create, approve, new version, reject, withdraw, AgentCore push through
a fake), holds (approve, reject a held decision), settings, routing
proofs and broker roles, each with its audit_events row. The R1a walker
now names that test as their coverage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ith the reasons

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A block removed an assignment Privileged Identity Management had
activated (or one with an end date) and restored it at the end as a
permanent assignment: standing access the principal never had. Before
removing, AuthSec now reads the principal's roleAssignmentScheduleInstances
(api 2020-10-01, $filter=assignedTo, shapes from Microsoft's REST
reference): the preview refuses such an assignment
(azure_time_bound_assignment); one activated while the block is on is
left in place and recorded as drift; PIM that cannot be read is a preview
warning and makes the job wait rather than risk it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ace (AS-155)

The rollout waited 5 minutes and any timeout rolled back, killing a
long migration mid-way and putting the old code on a half-migrated
schema. It now waits 20 minutes, and only a new pod that restarted (or a
failed verification) triggers the automatic rollback; a timeout with no
crash fails the deploy for a human to decide. The pre-migration dump now
refuses to start unless the PostgreSQL volume has at least the
database's size free, since the dumps share that volume.

Not pushed: deploy.yml runs on push to authsec-staging.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Staging's PR #98 added an Azure data-plane table (AI Search, Key Vault,
Service Bus, Event Hubs) under the same names as this branch's fuller one
in services/iga_gov_access_azure_planes.go. Resolution:
- keep this branch's table; drop the duplicate type, table, lookup,
  azureActions addition and per-type note from iga_gov_access_azure.go;
- adopt #98's allow of read and write on Service Bus / Event Hubs:
  Data Owner (bothRole), with a preview warning that it also manages
  the namespace (this branch had refused it);
- role constants: this branch's plus #98's two Data Owner roles;
- #98's unit tests adapted where this branch deliberately differs (a
  storage account block covers every data service and SAS path; a mapped
  type's read is its data and key actions, not the management read); its
  integration test runs unchanged;
- docs/PROGRESS.md keeps both histories.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Azure and Kubernetes access-policy schema checks queried pg_constraint
from iga_* files, which the IGA isolation check refuses. They now call
repositories.ConstraintAdmits, next to the other catalog helpers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
iga_gov_k8s_access is the 60th Phase 3 table. Its created_by, connector_id
and identity_account_id are listed as iga_gov_azure_access's are;
instruction_id is a bare uuid because provisioning_instructions has no
(workspace_id, id) key to reference.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants