From 870d263f27f31b2eacd35ead066a26151d438808 Mon Sep 17 00:00:00 2001 From: zanejohnson-azure Date: Fri, 10 Jul 2026 15:00:54 -0700 Subject: [PATCH 1/5] docs(internal): add rp-auto-onboarding linked access check summary Team brief on the ama-logs linked access check: what it is in ama-logs scope, why it's needed, why/whether/how it can be removed, with impact broken down by auth path (legacy shared-key vs managed-identity). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../linked-access-check-summary.md | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md diff --git a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md new file mode 100644 index 0000000000..eed5dd0a0f --- /dev/null +++ b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md @@ -0,0 +1,154 @@ +# Linked Access Check for ama-logs — What It Is & Can We Remove It + +*Short, shareable overview, organized as five questions: (1) what the linked +access check is in the scope of ama-logs, (2) why it is needed now, (3) why we +want to remove it, (4) whether we can remove it, and (5) how it can be removed.* + +--- + +## 1. What is it, in the scope of ama-logs? + +**Linked access check** = an ARM manifest rule that ties a write on **one** +resource to the caller's permission over a **different** resource named in the +request body. + +For ama-logs enabling, the caller makes an ARM call to write a **cluster**, and +the call includes a workspace ID. So ARM enforces: + +> When you `PUT` a cluster with a workspace ID in the body, you must **already +> have permission on that workspace** — otherwise ARM returns **403** before +> aks-rp ever runs. + +**What it actually checks:** the gate is defined as **four** linked-access-check +records. All four share the same **trigger** (`actionName` = +`Microsoft.ContainerService/managedClusters/write`) and the same **body +property** (`linkedProperty` = +`properties.addonProfiles.omsagent.config.logAnalyticsWorkspaceResourceID`), and +differ only in the **linked action** (`linkedAction`) they demand. + +A single qualifying `PUT` fires **all four**, and the caller must hold **every** +linked action on the target workspace — any miss → 403: + +| # | linkedAction (caller must hold on the workspace) | What it authorizes | +| --- | --- | --- | +| 1 | `Microsoft.OperationalInsights/workspaces/sharedkeys/read` | read the workspace **shared keys** — for the **legacy shared-key** path (the key the RP fetches) | +| 2 | `Microsoft.OperationalInsights/workspaces/read` | read the workspace | +| 3 | `Microsoft.OperationsManagement/solutions/write` | install the legacy **ContainerInsights OMS solution** (a **write**) | +| 4 | `Microsoft.OperationsManagement/solutions/read` | read legacy OMS solution state | + +**Notes on the four:** +- **#1 is specific to the legacy (shared-key) ama-logs path** — it gates the + workspace key that the RP will fetch. On the managed-identity path no shared + key is used, so this action isn't functionally exercised. +- **#3 and #4 are also legacy artifacts** — `Microsoft.OperationsManagement/solutions/*` + is the old **OMS "solutions"** model, where Container Insights + installed a `ContainerInsights(workspace)` *solution* on the workspace. This is + **not** part of the MSI path. +- So three of the four checks (#1, #3, #4) exist to support **legacy onboarding**; +- #2 (`workspaces/read`) is generic. +- **#3 is a write** — so a pure workspace *Reader* is not enough to pass the + gate; onboarding needs a write-capable role on the workspace side. + +**Scope of linked property:** this gate is attached **only to the omsagent addonProfile +path**. The newer **azureMonitorProfile** onboarding surface has **no linked +access check at all** today — so the check as it exists is entirely a +**legacy-omsagent** construct. + +--- + +## 2. Why is it needed now for ama-logs? + +After ARM forwards the request, aks-rp fetches the workspace's **shared key** +using its **own first-party identity (service principal)** — *not* the caller's +identity. Because the RP acts as itself, nothing downstream re-checks whether the +*caller* was allowed to use that workspace. + +➡️ **The linked access check is the only place the caller's workspace permission +is verified.** Remove it with nothing else changing, and any caller who can +create a cluster could point it at a workspace they don't own and have the RP +pull that workspace's key for them. + +#1, #3, and #4 are **only on the legacy shared-key path** — that's the path that +fetches a key. The azureMonitorProfile (managed-identity) path has no linked +access check and uses managed identity instead of a shared key. + +#2 is a general read permission, this guards that user can not use a workspace id that the user has no read permission to when enabling ama-logs. + +--- + +## 3. Why do we want to remove it? + +1. The linked access check feature is **not supported during new region build** (⚠️ **TO BE CONFIRMED**). +2. The **legacy path of ama-logs is retiring**, so there is no need to keep the + linked access check in ARM, at least #1, #3, and #4. + +--- + +## 4. Can we remove it? + +### Impact of removing it — by auth path + +The two ama-logs auth paths are affected very differently, because only the +legacy path actually relies on this gate: + +**Legacy (shared-key) path — high impact:** +- Today the linked access check is the **only** place the caller's workspace + permission is verified. After ARM, aks-rp fetches the workspace **shared key** + as the **RP's own identity**, not the caller's. +- Remove the check with nothing else in place, and any caller who can `PUT` a + cluster could point it at a **workspace they don't own** and have the RP fetch + and inject that workspace's shared key into their cluster — i.e. a + **shared-key exfiltration** risk. This path **cannot** lose the check without a + replacement caller-side permission enforcement. + +**Managed-identity (MSI) path — low impact:** +- On the MSI path no shared key is fetched (the RP skips the key fetch), so the + `sharedkeys/read` check (#1) isn't functionally exercised, and the legacy OMS + `solutions/*` checks (#3/#4) don't apply either — for these three the gate is + effectively **over-gating** this path today. +- **#2 (`workspaces/read`) is the exception** — it still does real work on the + MSI path: it's the caller's read-permission guard on the workspace, and it + applies regardless of auth path (it stops a caller associating a workspace they + can't even read). +- Removing the check here means a caller could **associate** a cluster to a + workspace they don't own, but **no key is issued** — workspace authentication + still requires the cluster's managed identity + a **DCR association**, which is + a **separate RBAC grant** the caller does not obtain via this `PUT`. So the + impact is **"associate-to-unowned-workspace only,"** not secret exposure. + + +Therefore, +For #1, #3, and #4: +1. The **legacy path of ama-logs is fully retired**. +Or, +2. **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. + +For #2: +⚠️ **[TO BE DISCUSSED]** Depending on whether we allow a user associate any workspace id. +If not, we need keep it. If we remove it, we need **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. + + +--- + +## 5. How can we remove it? + +- The linked access check lives in the **Microsoft.ContainerService ARM manifest + source** (not in aks-rp code). Removal = deleting/relaxing those four manifest + entries on the omsagent property. +- It is a static manifest change; aks-rp code is unchanged by the removal itself. + +--- + +## Bottom line + +The linked access check is a **front-door permission gate** whose real weight is +on the **legacy shared-key path**, where aks-rp fetches the workspace key as the +**RP's identity, not the caller's** — making the gate the only caller-side +workspace check. On the **MSI path** it is largely redundant (no key is fetched; +DCR/managed-identity is granted separately). So any plan to remove it must keep a +caller-permission enforcement for the **legacy** path, while the **MSI** path can +tolerate removal with only an associate-to-unowned-workspace effect. + +--- + +*Read-only research summary. No repo or manifest files were modified.* From 269cae782c5232c0de5121f0c7db830ae7c49eb5 Mon Sep 17 00:00:00 2001 From: zanejohnson-azure Date: Wed, 15 Jul 2026 11:18:34 -0700 Subject: [PATCH 2/5] docs(internal): sync linked access check summary with updated brief Retitle to '...Can & How We Remove It' and pull latest edits from the source team brief. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../linked-access-check-summary.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md index eed5dd0a0f..734b55672b 100644 --- a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md +++ b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md @@ -1,8 +1,8 @@ -# Linked Access Check for ama-logs — What It Is & Can We Remove It +# Linked Access Check for ama-logs — What It Is & Can & How We Remove It -*Short, shareable overview, organized as five questions: (1) what the linked +\*Short, shareable overview, organized as five questions: (1) what the linked access check is in the scope of ama-logs, (2) why it is needed now, (3) why we -want to remove it, (4) whether we can remove it, and (5) how it can be removed.* +want to remove it, (4) whether we can remove it, and (5) how it can be removed.\* --- @@ -15,14 +15,14 @@ request body. For ama-logs enabling, the caller makes an ARM call to write a **cluster**, and the call includes a workspace ID. So ARM enforces: -> When you `PUT` a cluster with a workspace ID in the body, you must **already -> have permission on that workspace** — otherwise ARM returns **403** before +> When you `PUT` a cluster with a workspace ID in the body, you must \*\*already +> have permission on that workspace\*\* — otherwise ARM returns **403** before > aks-rp ever runs. **What it actually checks:** the gate is defined as **four** linked-access-check records. All four share the same **trigger** (`actionName` = -`Microsoft.ContainerService/managedClusters/write`) and the same **body -property** (`linkedProperty` = +`Microsoft.ContainerService/managedClusters/write`) and the same \*\*body +property\*\* (`linkedProperty` = `properties.addonProfiles.omsagent.config.logAnalyticsWorkspaceResourceID`), and differ only in the **linked action** (`linkedAction`) they demand. @@ -49,9 +49,9 @@ linked action on the target workspace — any miss → 403: - **#3 is a write** — so a pure workspace *Reader* is not enough to pass the gate; onboarding needs a write-capable role on the workspace side. -**Scope of linked property:** this gate is attached **only to the omsagent addonProfile -path**. The newer **azureMonitorProfile** onboarding surface has **no linked -access check at all** today — so the check as it exists is entirely a +**Scope of linked property:** this gate is attached \*\*only to the omsagent addonProfile +path\*\*. The newer **azureMonitorProfile** onboarding surface has \*\*no linked +access check at all\*\* today — so the check as it exists is entirely a **legacy-omsagent** construct. --- @@ -63,8 +63,8 @@ using its **own first-party identity (service principal)** — *not* the caller' identity. Because the RP acts as itself, nothing downstream re-checks whether the *caller* was allowed to use that workspace. -➡️ **The linked access check is the only place the caller's workspace permission -is verified.** Remove it with nothing else changing, and any caller who can +➡️ \*\*The linked access check is the only place the caller's workspace permission +is verified.\*\* Remove it with nothing else changing, and any caller who can create a cluster could point it at a workspace they don't own and have the RP pull that workspace's key for them. @@ -132,8 +132,8 @@ If not, we need keep it. If we remove it, we need **aks-rp can support the same ## 5. How can we remove it? -- The linked access check lives in the **Microsoft.ContainerService ARM manifest - source** (not in aks-rp code). Removal = deleting/relaxing those four manifest +- The linked access check lives in the \*\*Microsoft.ContainerService ARM manifest + source\*\* (not in aks-rp code). Removal = deleting/relaxing those four manifest entries on the omsagent property. - It is a static manifest change; aks-rp code is unchanged by the removal itself. From 5a2af7dd79faae4b8a95631d4569a67f6acc75c0 Mon Sep 17 00:00:00 2001 From: zanejohnson-azure Date: Wed, 15 Jul 2026 11:21:31 -0700 Subject: [PATCH 3/5] docs(internal): unescape multi-line bold markers in linked access check summary The synced brief had backslash-escaped '**' on bold spans that wrap across a line break, which renders as literal asterisks on GitHub. Restore proper bold; title change retained. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../linked-access-check-summary.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md index 734b55672b..48430b4734 100644 --- a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md +++ b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md @@ -1,8 +1,8 @@ # Linked Access Check for ama-logs — What It Is & Can & How We Remove It -\*Short, shareable overview, organized as five questions: (1) what the linked +*Short, shareable overview, organized as five questions: (1) what the linked access check is in the scope of ama-logs, (2) why it is needed now, (3) why we -want to remove it, (4) whether we can remove it, and (5) how it can be removed.\* +want to remove it, (4) whether we can remove it, and (5) how it can be removed.* --- @@ -15,14 +15,14 @@ request body. For ama-logs enabling, the caller makes an ARM call to write a **cluster**, and the call includes a workspace ID. So ARM enforces: -> When you `PUT` a cluster with a workspace ID in the body, you must \*\*already -> have permission on that workspace\*\* — otherwise ARM returns **403** before +> When you `PUT` a cluster with a workspace ID in the body, you must **already +> have permission on that workspace** — otherwise ARM returns **403** before > aks-rp ever runs. **What it actually checks:** the gate is defined as **four** linked-access-check records. All four share the same **trigger** (`actionName` = -`Microsoft.ContainerService/managedClusters/write`) and the same \*\*body -property\*\* (`linkedProperty` = +`Microsoft.ContainerService/managedClusters/write`) and the same **body +property** (`linkedProperty` = `properties.addonProfiles.omsagent.config.logAnalyticsWorkspaceResourceID`), and differ only in the **linked action** (`linkedAction`) they demand. @@ -49,9 +49,9 @@ linked action on the target workspace — any miss → 403: - **#3 is a write** — so a pure workspace *Reader* is not enough to pass the gate; onboarding needs a write-capable role on the workspace side. -**Scope of linked property:** this gate is attached \*\*only to the omsagent addonProfile -path\*\*. The newer **azureMonitorProfile** onboarding surface has \*\*no linked -access check at all\*\* today — so the check as it exists is entirely a +**Scope of linked property:** this gate is attached **only to the omsagent addonProfile +path**. The newer **azureMonitorProfile** onboarding surface has **no linked +access check at all** today — so the check as it exists is entirely a **legacy-omsagent** construct. --- @@ -63,8 +63,8 @@ using its **own first-party identity (service principal)** — *not* the caller' identity. Because the RP acts as itself, nothing downstream re-checks whether the *caller* was allowed to use that workspace. -➡️ \*\*The linked access check is the only place the caller's workspace permission -is verified.\*\* Remove it with nothing else changing, and any caller who can +➡️ **The linked access check is the only place the caller's workspace permission +is verified.** Remove it with nothing else changing, and any caller who can create a cluster could point it at a workspace they don't own and have the RP pull that workspace's key for them. @@ -132,8 +132,8 @@ If not, we need keep it. If we remove it, we need **aks-rp can support the same ## 5. How can we remove it? -- The linked access check lives in the \*\*Microsoft.ContainerService ARM manifest - source\*\* (not in aks-rp code). Removal = deleting/relaxing those four manifest +- The linked access check lives in the **Microsoft.ContainerService ARM manifest + source** (not in aks-rp code). Removal = deleting/relaxing those four manifest entries on the omsagent property. - It is a static manifest change; aks-rp code is unchanged by the removal itself. From 3f523256ce8bb72caa9fd78e8e2e5c9d4b2924b3 Mon Sep 17 00:00:00 2001 From: zanejohnson-azure Date: Wed, 15 Jul 2026 15:38:04 -0700 Subject: [PATCH 4/5] docs(internal): sync linked access check summary with materially updated brief Add TL;DR two-group table; reframe #2 (workspaces/read) as the caller-side mirror of the workspace GET aks-rp does on both paths to inject the workspace GUID; mark preferred removal options; add MSI config-chunk GUID self-derivation detail; firm up Q3 region-build wording. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../linked-access-check-summary.md | 90 +++++++++++++++---- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md index 48430b4734..66ecfc2ddd 100644 --- a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md +++ b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md @@ -6,6 +6,18 @@ want to remove it, (4) whether we can remove it, and (5) how it can be removed.* --- +## TL;DR + +The omsagent linked access check is **four ANDed checks**. They fall into two +groups with different removal conditions: + +| Check(s) | What it gates | Paths affected | Removal condition | +|---|---|---|---| +| **#1, #3, #4** — `sharedkeys/read`, `solutions/write`, `solutions/read` | Legacy shared-key + OMS-solutions onboarding (the workspace **key** aks-rp fetches and the ContainerInsights solution) | **Legacy only** (not exercised on MSI) | Remove when **either** (a) the legacy shared-key path of ama-logs is **fully retired** *(**preferred**)*, **or** (b) **aks-rp performs the same checks on behalf of the user**. | +| **#2** — `workspaces/read` | Caller's read guard on the workspace; mirrors the workspace **GET** aks-rp does (**both** paths) to read the workspace **GUID** (`CustomerID`) injected into the ama-logs helm chart | **Both** legacy and MSI | Remove when **either** (a) we **do not inject the customer's workspace ID into our telemetry** — feasible on **MSI**, where the agent can self-derive the GUID from its local DCR config chunks (see Q4), but **not** on legacy shared-key onboarding — **or** (b) **aks-rp performs the same read check on behalf of the user** *(**preferred** — supportable once ama-logs integrates **OBO** in aks-rp)*. | + +--- + ## 1. What is it, in the scope of ama-logs? **Linked access check** = an ARM manifest rule that ties a write on **one** @@ -44,8 +56,12 @@ linked action on the target workspace — any miss → 403: is the old **OMS "solutions"** model, where Container Insights installed a `ContainerInsights(workspace)` *solution* on the workspace. This is **not** part of the MSI path. -- So three of the four checks (#1, #3, #4) exist to support **legacy onboarding**; -- #2 (`workspaces/read`) is generic. +- So three of the four checks (#1, #3, #4) exist to support **legacy onboarding**. +- **#2 (`workspaces/read`) applies to both paths** — it's the caller's read guard + on the workspace, and it mirrors the workspace **GET** aks-rp itself does (on both + legacy and MSI paths) to read the workspace **GUID** (`CustomerID`) that gets + injected into the ama-logs helm chart. So #2 is the only check that does real work + on the MSI path. - **#3 is a write** — so a pure workspace *Reader* is not enough to pass the gate; onboarding needs a write-capable role on the workspace side. @@ -64,9 +80,9 @@ identity. Because the RP acts as itself, nothing downstream re-checks whether th *caller* was allowed to use that workspace. ➡️ **The linked access check is the only place the caller's workspace permission -is verified.** Remove it with nothing else changing, and any caller who can -create a cluster could point it at a workspace they don't own and have the RP -pull that workspace's key for them. +is verified** (see Q4 for the per-path impact). Remove it with nothing else +changing, and any caller who can create a cluster could point it at a workspace +they don't own and have the RP pull that workspace's key for them. #1, #3, and #4 are **only on the legacy shared-key path** — that's the path that fetches a key. The azureMonitorProfile (managed-identity) path has no linked @@ -74,13 +90,27 @@ access check and uses managed identity instead of a shared key. #2 is a general read permission, this guards that user can not use a workspace id that the user has no read permission to when enabling ama-logs. +**What #2 (`workspaces/read`) actually enables in aks-rp:** aks-rp itself performs +a workspace **GET** (`workspaces/read`) — on **both** the legacy and MSI paths — to +read the workspace's `CustomerID` (the workspace GUID). That GUID is stored as the +omsagent addon config `WorkspaceID` and injected into the **ama-logs helm chart** so +the agent knows which workspace to send data to. The RP does this GET with its +**own first-party identity**; linked-access-check #2 is the caller-side mirror, +enforcing that the user who issued the PUT also has read on that same workspace. +This is why #2 is the one check that does real work on the MSI path. +(Source: `putmanagedclusterasync_addon.go` → `getLogAnalyticsWorkspaceInfo` — +workspace GET → `customerID` → `AddonConfigOmsWorkspaceID`; `oms_agent.go` helm +values → `WorkspaceID`.) + --- ## 3. Why do we want to remove it? -1. The linked access check feature is **not supported during new region build** (⚠️ **TO BE CONFIRMED**). -2. The **legacy path of ama-logs is retiring**, so there is no need to keep the - linked access check in ARM, at least #1, #3, and #4. +1. The linked access check does not work during **region build**. During region + build, the workspace is not yet available, so we need to bootstrap from a + workspace in another GA region — and **cross-region linked access check is not + supported**. +2. The **legacy path of ama-logs is retiring**, so there is no need to keep the linked access check in ARM, at least #1, #3, and #4. --- @@ -119,13 +149,34 @@ legacy path actually relies on this gate: Therefore, For #1, #3, and #4: -1. The **legacy path of ama-logs is fully retired**. +1. The **legacy path of ama-logs is fully retired**. *(**preferred**)* Or, 2. **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. For #2: -⚠️ **[TO BE DISCUSSED]** Depending on whether we allow a user associate any workspace id. -If not, we need keep it. If we remove it, we need **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. +#2 (`workspaces/read`) backs **two** things: (a) aks-rp reading the workspace +**GUID** (`CustomerID`) to inject into the ama-logs helm chart, and (b) the +caller-side permission guard on the workspace (ama-logs telemetry onboarding). +It can be removed when **either**: +1. we **do not inject the customer's workspace ID into our telemetry**, **or** +2. **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. *(**preferred** — supportable once ama-logs integrates **OBO** in aks-rp)* + +**More on option (a) — can the agent obtain the workspace ID itself?** +For **MSI-onboarded** clusters, **yes**: the ama-logs agent can self-derive the +workspace GUID from the **DCR config chunks** that `mdsd` fetches from AMCS at +runtime (using the agent's own MSI/AAD token), cached locally in the container at +`/etc/mdsd.d/config-cache/configchunks/*.json`. Modern DCR config has no literal +`workspaceId` field — the GUID is embedded in the **ODS channel** the data routes +to: `channels[].endpoint = https://.ods.opinsights.azure.com` (and +`sendToChannels -> "ods-"`). So on MSI, aks-rp would **not** need to inject +the workspace ID — the agent already has it via the DCR-issued channel config. +- **Caveat — MSI only.** This relies on the AMCS/DCR path, which is the MSI/AAD + onboarding path. **Legacy shared-key** onboarding does **not** use AMCS/DCR + chunks; there the workspace ID still comes from the `WSID` secret/env that + aks-rp injects, so option (a) does **not** cover the legacy path. +- Verified: the GUID extracted from the DCR chunk matched the pod's onboarded + `/etc/omsagent-secret/WSID`. *(Source: sibling investigation — + `mdsd-workspaceid-from-configchunks.md`.)* --- @@ -141,13 +192,16 @@ If not, we need keep it. If we remove it, we need **aks-rp can support the same ## Bottom line -The linked access check is a **front-door permission gate** whose real weight is -on the **legacy shared-key path**, where aks-rp fetches the workspace key as the -**RP's identity, not the caller's** — making the gate the only caller-side -workspace check. On the **MSI path** it is largely redundant (no key is fetched; -DCR/managed-identity is granted separately). So any plan to remove it must keep a -caller-permission enforcement for the **legacy** path, while the **MSI** path can -tolerate removal with only an associate-to-unowned-workspace effect. +The linked access check is a **front-door permission gate**. Its legacy-specific +weight (#1, #3, #4) is on the **shared-key path**, where aks-rp fetches the +workspace key as the **RP's identity, not the caller's** — making the gate the only +caller-side check for that key. **#2 (`workspaces/read`) is different**: it applies +to **both** paths and mirrors the workspace **GET** aks-rp performs to read the +workspace **GUID** (`CustomerID`) it injects into the ama-logs helm chart, so on the +**MSI path #2 still does real work** (the legacy checks #1/#3/#4 do not). Any plan to +remove it must therefore (a) keep caller-permission enforcement for the **legacy** +shared-key path, and (b) for #2, either stop injecting the customer's workspace ID +into our telemetry, or have aks-rp enforce the same read check on behalf of the user. --- From 60ae7759a13450af59faec2f1ca57cc2e5b986f7 Mon Sep 17 00:00:00 2001 From: zanejohnson-azure Date: Wed, 15 Jul 2026 15:46:22 -0700 Subject: [PATCH 5/5] docs(internal): reframe check #2 as single-purpose GUID-injection mirror Correctness fix: #2 (workspaces/read) is the caller-side mirror of the workspace GET aks-rp does to read the GUID (CustomerID) it injects into the ama-logs helm chart. Drops the earlier 'read guard / association guard' framing that overstated #2 as a standalone access-control guard. Aligned across TL;DR, Q1, Q2, and both Q4 blocks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../linked-access-check-summary.md | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md index 66ecfc2ddd..b88afd779c 100644 --- a/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md +++ b/Documentation/Internal/Projects/rp-auto-onboarding/linked-access-check-summary.md @@ -14,7 +14,7 @@ groups with different removal conditions: | Check(s) | What it gates | Paths affected | Removal condition | |---|---|---|---| | **#1, #3, #4** — `sharedkeys/read`, `solutions/write`, `solutions/read` | Legacy shared-key + OMS-solutions onboarding (the workspace **key** aks-rp fetches and the ContainerInsights solution) | **Legacy only** (not exercised on MSI) | Remove when **either** (a) the legacy shared-key path of ama-logs is **fully retired** *(**preferred**)*, **or** (b) **aks-rp performs the same checks on behalf of the user**. | -| **#2** — `workspaces/read` | Caller's read guard on the workspace; mirrors the workspace **GET** aks-rp does (**both** paths) to read the workspace **GUID** (`CustomerID`) injected into the ama-logs helm chart | **Both** legacy and MSI | Remove when **either** (a) we **do not inject the customer's workspace ID into our telemetry** — feasible on **MSI**, where the agent can self-derive the GUID from its local DCR config chunks (see Q4), but **not** on legacy shared-key onboarding — **or** (b) **aks-rp performs the same read check on behalf of the user** *(**preferred** — supportable once ama-logs integrates **OBO** in aks-rp)*. | +| **#2** — `workspaces/read` | Backs the workspace **GET** aks-rp does (**both** paths) to read the workspace **GUID** (`CustomerID`) injected into the ama-logs helm chart | **Both** legacy and MSI | Remove when **either** (a) we **do not inject the customer's workspace ID into our telemetry** — feasible on **MSI**, where the agent can self-derive the GUID from its local DCR config chunks (see Q4), but **not** on legacy shared-key onboarding — **or** (b) **aks-rp performs the same read check on behalf of the user** *(**preferred** — supportable once ama-logs integrates **OBO** in aks-rp)*. | --- @@ -57,11 +57,11 @@ linked action on the target workspace — any miss → 403: installed a `ContainerInsights(workspace)` *solution* on the workspace. This is **not** part of the MSI path. - So three of the four checks (#1, #3, #4) exist to support **legacy onboarding**. -- **#2 (`workspaces/read`) applies to both paths** — it's the caller's read guard - on the workspace, and it mirrors the workspace **GET** aks-rp itself does (on both - legacy and MSI paths) to read the workspace **GUID** (`CustomerID`) that gets - injected into the ama-logs helm chart. So #2 is the only check that does real work - on the MSI path. +- **#2 (`workspaces/read`) applies to both paths** — it mirrors the workspace + **GET** aks-rp itself does (on both legacy and MSI paths) to read the workspace + **GUID** (`CustomerID`) that gets injected into the ama-logs helm chart. That + GUID retrieval-and-injection is its purpose, and it's why #2 is the only check + that does real work on the MSI path. - **#3 is a write** — so a pure workspace *Reader* is not enough to pass the gate; onboarding needs a write-capable role on the workspace side. @@ -88,7 +88,9 @@ they don't own and have the RP pull that workspace's key for them. fetches a key. The azureMonitorProfile (managed-identity) path has no linked access check and uses managed identity instead of a shared key. -#2 is a general read permission, this guards that user can not use a workspace id that the user has no read permission to when enabling ama-logs. +#2 mirrors the workspace **GET** aks-rp performs to read the workspace GUID; it +requires that the caller has read on the workspace that aks-rp is about to read on +their behalf when enabling ama-logs. **What #2 (`workspaces/read`) actually enables in aks-rp:** aks-rp itself performs a workspace **GET** (`workspaces/read`) — on **both** the legacy and MSI paths — to @@ -136,10 +138,11 @@ legacy path actually relies on this gate: `sharedkeys/read` check (#1) isn't functionally exercised, and the legacy OMS `solutions/*` checks (#3/#4) don't apply either — for these three the gate is effectively **over-gating** this path today. -- **#2 (`workspaces/read`) is the exception** — it still does real work on the - MSI path: it's the caller's read-permission guard on the workspace, and it - applies regardless of auth path (it stops a caller associating a workspace they - can't even read). +- **#2 (`workspaces/read`) is the exception** — it still applies on the MSI path. + Its purpose here is to mirror the workspace **GET** aks-rp performs (on both + paths) to read the workspace **GUID** (`CustomerID`) that it injects into the + ama-logs helm chart. So on MSI, #2 exists specifically to back that GUID + retrieval-and-injection, not a broader association guard. - Removing the check here means a caller could **associate** a cluster to a workspace they don't own, but **no key is issued** — workspace authentication still requires the cluster's managed identity + a **DCR association**, which is @@ -154,9 +157,9 @@ Or, 2. **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. For #2: -#2 (`workspaces/read`) backs **two** things: (a) aks-rp reading the workspace -**GUID** (`CustomerID`) to inject into the ama-logs helm chart, and (b) the -caller-side permission guard on the workspace (ama-logs telemetry onboarding). +#2 (`workspaces/read`) exists for a **single** purpose: aks-rp reads the workspace +**GUID** (`CustomerID`) and injects it into the ama-logs helm chart, and #2 is the +caller-side mirror of that read. It can be removed when **either**: 1. we **do not inject the customer's workspace ID into our telemetry**, **or** 2. **aks-rp can support the same functions** that the linked access check does **on behalf of the user**. *(**preferred** — supportable once ama-logs integrates **OBO** in aks-rp)*