Normalize additional identifier casing BED-9100 - #204
Conversation
…created recursion methods in utils.go due to it having deep nested groupId and userId
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe models now uppercase additional identifiers, names, tenant fields, managed identity values, and nested policy keys during JSON serialization. New custom marshaling and tests preserve source object values. ChangesJSON normalization
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@models/utils.go`:
- Around line 116-124: Update the JSON decoding flow before upperDecodedKeys to
use a json.Decoder configured with UseNumber instead of json.Unmarshal,
preserving numeric values under non-targeted keys when the normalized structure
is re-encoded. Keep the existing error propagation and targeted-key processing
unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5017089b-0b95-4aa6-8626-ba1ee895f8e8
📒 Files selected for processing (25)
models/app-fic.gomodels/app-role-assignments.gomodels/app.gomodels/automation-account.gomodels/azure/descendant-info.gomodels/container-registry.gomodels/device.gomodels/function-app.gomodels/group.gomodels/key-vault.gomodels/logic-app.gomodels/managed-cluster.gomodels/marshal_test.gomodels/mgmt-group.gomodels/role-assignments.gomodels/role-management-policy-assignment.gomodels/role.gomodels/service-principal.gomodels/storage-account.gomodels/storage-container.gomodels/subscription.gomodels/tenant.gomodels/user.gomodels/utils.gomodels/web-app.go
…gured with UseNumber()
Summary
Extends the identifier normalization introduced in BED-8944 (
7092bc6) to cover the remaining node identifiers, nested identifiers, and human-readable names emitted by AzureHound models. The goal is to normalize (uppercase) every value at the source so that BloodHound / BHE does not need to normalize on ingest.All normalization is done in each model's
MarshalJSONusing the non-mutatingtype Alias T; a := Alias(s)pattern — the source structs are never modified.Motivation and Context
Resolves: BED-9100
What changed
Top-level node identifiers now uppercased
AZTenant.id(ARM path, e.g./tenants/...) —tenant.gosubscriptionId—subscription.godeviceId—device.goappIdonAppFICsandAppRoleAssignment—app-fic.go,app-role-assignments.goroleDefinitionIdon unified role assignments —role-assignments.godisplayNamenormalized wherever it is a node propertyapp.go,device.go,group.go,role.go,service-principal.go,subscription.go,tenant.go,user.gomgmt-group.go(properties.displayName),azure/descendant-info.go(properties.displayName)Nested identifiers normalized
identity.tenantId(managed identity) — viaUpperManagedIdentityinutils.goproperties.tenantId—key-vault.go,mgmt-group.goproperties.accessPolicies[].objectId/.applicationId/.tenantIdinkey-vault.goproperties.nodeResourceGroupon managed clusters —managed-cluster.gogroupId/userIdinside rawpolicy.rules—role-management-policy-assignment.govia new recursiveUpperRawJSONKeyshelper inutils.goHuman-readable names normalized (new scope, to remove all ingest-side work)
tenantName—app-fic.go,app.go,device.go,group.go,role.go,service-principal.go,user.goresourceGroupName—automation-account.go,container-registry.go,function-app.go,logic-app.go,storage-account.go,storage-container.go,web-app.goMissing
MarshalJSONmethods addedStorageAccountandStorageContainerhad noMarshalJSONat all; added ones mirroring their siblings (uppercasingid,subscriptionId,resourceGroupId,resourceGroupName,storageAccountId,tenantId, and identity).New utility helpers (
models/utils.go)UpperManagedIdentitynow also uppercasesTenantId(in addition toPrincipalId).UpperRawJSONKeys(raw, keys...)— recursively uppercases string values under the named keys at any depth in a raw JSON blob (non-mutating). Used for the deeply nested RoleManagementPolicyAssignment approver IDs.upperDecodedKeys(value, targeted)and a small namedtargetKeysset type for clear membership checks.OmitEmptyUpper(top-levelidplus empty entry stripping).Intentionally NOT normalized
AppRoleAssignment.id— a case-sensitive base64url token, not a GUID; uppercasing would corrupt it.UnifiedRoleAssignment.id(directory role assignment id) — also a case-sensitive base64url Graph token. An earlier revision uppercased this by mistake; it has been reverted and a regression test now guards its original casing.appRoleIdon app role assignments — a permission discriminator matched against lowercase app-role-template GUID constants during ingest (the same category asroleDefinitionId). Uppercasing it would break edge creation, so it is deliberately left in its canonical lowercaseuuid.UUIDform.PrincipalId(uuid.UUID) on unified role assignments — emitted uppercased via the raw path since the typed field cannot hold an uppercased string.Testing
models/marshal_test.go— comprehensive unit tests added/updated for every new normalization (top-level, nested, raw-JSON, and thetenantName/resourceGroupNamenames), plus regression guards asserting the case-sensitive base64url ids (AppRoleAssignment.id,UnifiedRoleAssignment.id) and the lowercase-matchedappRoleIdare preserved as-is.go build ./...,go vet ./...,go test ./...— all pass.output.json(52,289 records, 56 kinds): node splitting eliminated (0 ids appear in more than one casing), every targeted edge endpoint is 100% uppercased with zero lowercase stragglers, and the case-sensitive base64url ids /appRoleIdremain in their original casing. A depth-agnostic sweep fortenantName/resourceGroupNamealso reports a clean pass. Re-run after theutils.goreadability refactor produced byte-identical output, confirming that change is behavior-preserving.Summary by CodeRabbit
Enhancements
Tests