Add Policy ARM resource for CognitiveServices (2026-05-15-preview)#43974
Conversation
Add account-level Policy resource for controlling sandbox egress traffic. Targets existing 2026-05-15-preview API version per RP team guidance. - Policy.tsp: PolicyResource + CRUD operations (get, createOrUpdate, delete, list) - models.tsp: PolicyType, PolicyMode, PolicyDefaultAction, PolicyRuleAction, PolicyRuleType, PolicyRuleMatch, PolicyRule, PolicyProperties, PolicyListResult - 4 example files for account-level Policy operations - Generated swagger updated Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Next Steps to Merge✅ All automated merging requirements have been met! To get your PR merged, see aka.ms/azsdk/specreview/merge.Comment generated by summarize-checks workflow run. |
API Change CheckAPIView identified API level changes in this PR and created the following API reviews
Comment generated by After APIView workflow run. |
|
Model-design questions before this ships in preview: 1. 2. 3. 4. 5. 6. Name pattern 7. Unused Items 3, 4, and 5 are contract-level — preferable to resolve before the preview goes out. 1, 2, 6 are renames/scope decisions that get more expensive after release. 7 is a cleanup. |
…ules
- Rename PolicyResource → NetworkPolicyResource (avoids collision with existing Policy* types)
- Rename AccountPolicies → AccountNetworkPolicies interface
- Change segment from /policies to /networkPolicies
- Add discriminated NetworkPolicyRuleAction with Allow, Deny, Transform, Rewrite action types
- Transform: header operations (Add/Remove/Overwrite), extensible
- Rewrite: host + port rewriting, extensible
- Add read-only systemRules for server-populated infrastructure allowlist
- Make defaultAction required (security-critical)
- Document match semantics (DNS wildcard for host, URI prefix with * for path)
- Expand name pattern from {2,32} to {2,62}
- Remove unused Project.tsp import
- Address all 7 review comments from Fareed on PR Azure#43974
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nrichments - Rename all NetworkPolicy* types, models, interfaces, and examples to AgentGuardrails* - Flatten action payload: headers[] and rewrite directly on AgentGuardrailsRuleAction (removed transformConfig/rewriteConfig wrappers) - Add secret reference models: AgentGuardrailsSecretRef, AgentGuardrailsManagedIdentityRef, AgentGuardrailsHeaderValueRef, AgentGuardrailsManagedIdentityType - Make header value write-only (@secret + @visibility(Create, Update)) to prevent credential leakage on GET - Rename header operations: Add->Insert, Overwrite->Set for clarity - Enrich rewrite target: add scheme, path, keep targetPort - Fix Audit mode comment: dry-run for Deny only; Transform/Rewrite still execute - Add Transform (secretRef) and Rewrite (managedIdentityRef) JSON examples Based on Evan's feedback on PR Azure#43974. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Typespec validation is failing, can be fixed by adding @secret to secretKey in AgentGuardrailsSecretRef |
|
There are orphaned example files from the renames, those will need to be deleted |
|
Swagger will need recompilation with tsx compile |
- Add @secret to AgentGuardrailsSecretRef.secretKey (fixes TypeSpec validation) - Delete orphaned AccountPolicy/ and AccountNetworkPolicy/ example files - Recompile swagger with AgentGuardrails naming Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
All addressed in commit b2a9423: 1. 2. Transform/Rewrite on FQDN — These action types are retained per Evan/Chetan's guidance for future rule types. Server will return 400 when combined with 3. 4. 5. Match semantics documented — 6. Name pattern — Expanded from 7. Unused Additionally:
|
|
@microsoft-github-policy-service agree company="Microsoft" |
There was a problem hiding this comment.
should this file be named AgentGuardrails instead?
| * The action to take when this rule matches, including the action type and any | ||
| * type-specific configuration (headers for Transform, rewrite target for Rewrite). | ||
| */ | ||
| action?: AgentGuardrailsRuleAction; |
There was a problem hiding this comment.
agentguardrailsRuleAction is optional, what happens when no action is defined?
| } | ||
|
|
||
| /** | ||
| * Where a Rewrite action sends matched traffic. At least one field must be set. |
There was a problem hiding this comment.
this comment says at least one field must be set but all the files in agentguardrailsrewritetarget are optional
Per RAI team decision (PR Platform-ResourceProvider#16147771), egress guardrails are no longer a standalone ARM resource. Instead, they are a nested egressPolicy property on the existing RaiPolicyProperties model, following the same extension pattern as contentFilters and customBlocklists. Changes: - Remove Policy.tsp (standalone AgentGuardrailsResource and CRUD ops) - Remove import from main.tsp - Replace all AgentGuardrails* types with RaiEgress* types in models.tsp - Add egressPolicy?: RaiEgressPolicyConfig to RaiPolicyProperties - Add PutRaiPolicyWithEgress.json example showing egress within RaiPolicy - Remove all AccountAgentGuardrails example files (source + generated) - Recompile swagger The RaiEgress* types align 1:1 with the backend C# contract (RaiEgressPolicyConfig, RaiEgressRule, RaiEgressRuleAction, etc.) from the RP team's PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| "host": "*.internal.contoso.com" | ||
| }, | ||
| "action": { | ||
| "actionType": "Transform", |
There was a problem hiding this comment.
Can we add an example with rewrite action type too.
|
Reviewed the swagger against the backend service PR (Platform-ResourceProvider #16147771, branch Contract divergences (swagger vs. backend)1. 2. ARM modeling best practices (lint passes, but worth addressing)3. Example coverage4. Item 1 is the main item to resolve before merge; item 2 is a small spec/code reconciliation. The rest are non-blocking improvements. |
| } | ||
| } | ||
| ], | ||
| "systemRules": [ |
There was a problem hiding this comment.
Does this need to go to the user ? I was under the impression that Agent Service will be injecting these and these won't be in the ARM resource. Or are we adding it in the ARM resource.
|
|
||
| /** | ||
| * Rules are evaluated and logged but not enforced. A would-be Deny is logged but traffic | ||
| * is still forwarded, allowing customers to preview policy impact without breaking traffic. |
There was a problem hiding this comment.
Can we add that transform and rewrite will still be performed too. Basically this applies only to deny.
- Audit mode doc: clarify Transform/Rewrite still apply, only Deny is suppressed - RewriteTarget doc: clarify server-side 400 validation for empty target - Example: add Rewrite rule with scheme/host/path/targetPort + header - Example: rewrite rule appears in request, 200, and 201 response bodies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
The RP redacts the write-only header |
Per agreement with Chetan: remove the user/system rules distinction. All rules live in one ordered list. System rules can be added later if needed (easier to add than rollback). - Remove systemRules property from RaiEgressPolicyConfig model - Remove systemRules from example response bodies - Recompile swagger Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove RaiEgressManagedIdentityType union, ManagedIdentityRef.type, ManagedIdentityRef.identityResourceId, and RewriteTarget.targetPort. These fields cannot be enforced end-to-end today because the ADC client SDK (v26.61.0) does not expose Type/IdentityResourceId on EgressPolicyManagedIdentityRef, and has no Port on EgressPolicyRuleAction. The system-assigned managed identity is used implicitly when type is omitted. Fields will be re-added when ADC ships SDK support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| "scheme": "https", | ||
| "host": "api-v2.internal.contoso.com", | ||
| "path": "/v2/{path}", | ||
| "targetPort": 8443 |
| "managedIdentityRef": { | ||
| "resource": "https://internal.contoso.com/.default", | ||
| "format": "Bearer {value}", | ||
| "type": "SystemAssigned" |
Re-ran tsp compile to update cognitiveservices.json and the PutRaiPolicyWithEgress.json example. Removes type/targetPort that were manually edited but left stale in the generated output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| "managedIdentityRef": { | ||
| "resource": "https://internal.contoso.com/.default", | ||
| "format": "Bearer {value}", | ||
| "type": "SystemAssigned" |
There was a problem hiding this comment.
The generated resource-manager artifacts look out of sync with the source. This example still has type here, and the swagger schema (cognitiveservices.json) still defines type and identityResourceId on RaiEgressManagedIdentityRef, even though models.tsp and the source example dropped them. Looks like tsp wasn't recompiled after the model change. Re-running the generator should bring the swagger and generated examples back in line.
| "scheme": "https", | ||
| "host": "api-v2.internal.contoso.com", | ||
| "path": "/v2/{path}", | ||
| "targetPort": 8443 |
There was a problem hiding this comment.
Same regeneration gap as the managed-identity type note: targetPort is still here and in the swagger's RaiEgressRewriteTarget, though models.tsp and the source example removed it. A tsp recompile should clear both.
| { | ||
| "operation": "Set", | ||
| "name": "X-Forwarded-Host", | ||
| "value": "legacy-api.contoso.com" |
There was a problem hiding this comment.
value is write-only in models.tsp (@visibility(Lifecycle.Create, Lifecycle.Update)), so it should not appear in a response body. It is in the 200 response here and the 201 response (around line 223). Recommend dropping value from the response bodies and keeping it only in the request.
| "rewrite": { | ||
| "scheme": "https", | ||
| "host": "api-v2.internal.contoso.com", | ||
| "path": "/v2/{path}" |
There was a problem hiding this comment.
/v2/{path} uses a {path} placeholder that isn't described in the RaiEgressRewriteTarget.path doc (which only says the original path is kept when omitted). Could we document the templating tokens, or drop the placeholder from the example? Also worth confirming ADC supports path templating on rewrite.
|
Small thing on the PR description: the title and summary describe a standalone |
…ict scheme 1. ruleType: made required (only Fqdn supported today) 2. defaultAction: made optional, server defaults to Deny (fail-closed) 3. scheme: restricted to RaiEgressScheme union (http/https only) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion doc 1. Remove 'value' from response bodies (write-only per @visibility) 2. Replace '/v2/{path}' with '/v2/' — no path templating support 3. Clarify defaultAction doc: deny only affects unmatched traffic; transform/rewrite rules are always applied to matched traffic 4. Regenerated swagger and examples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
c1c5f28
into
Azure:swagger-agent/CogSvc-2026-05-15-preview-typespec
Summary
Add account-level Policy ARM resource to CognitiveServices for controlling sandbox egress traffic. This PR targets the existing
2026-05-15-previewAPI version branch per RP team guidance from Fareed.Changes
New files
Policy.tsp— PolicyResource model + CRUD operations (get, createOrUpdate, delete, list)examples/2026-05-15-preview/AccountPolicy/— 4 example JSON filesModified files
main.tsp— Added Policy.tsp importmodels.tsp— Added Policy unions and models:PolicyType(Egress)PolicyMode(Enforced, Audit)PolicyDefaultAction(Allow, Deny)PolicyRuleAction(Allow, Deny, Transform, Rewrite)PolicyRuleType(Fqdn)PolicyRuleMatch,PolicyRule,PolicyProperties,PolicyListResultDesign decisions
Related PRs