Skip to content

feat(adaudit-module): identity aliases — group accounts from different sources into one person - #3006

Merged
AlexSanchez-bit merged 10 commits into
release/v12.0.0from
feature/ad-audit-identity-alias
Oct 30, 2026
Merged

AlexSanchez-bit merged 10 commits into
release/v12.0.0from
feature/ad-audit-identity-alias

Conversation

@JocLRojas

Copy link
Copy Markdown
Contributor

Description

A person usually has several accounts across different sources: an O365 login, a Windows machine, a Linux server, an AWS key. Until now the User Auditor showed each of them as a separate person, so analysts had to keep the connections in their heads.

This change adds identities: a name an admin can attach to any account in the user inventory. Once two accounts share an identity, the UI can show them as the same person, filter the list by that person, and search accounts by the identity name.

Everything is manual. The system never guesses connections on its own — an admin looks at the accounts and decides. Accounts are never modified or merged; an identity is just a label on top of them, and removing it never touches the accounts.

Issue

#2989

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

🛑 AI review — Sensitive area, extra care recommended

This PR touches critical paths or introduces changes the model cannot judge with sufficient confidence. Review carefully before merging.

🛑 architecture (silas-1.7-pro) — high/critical — please review

Summary: Tier 3: DB migrations, permission grants, and identity alias schema introduce production risk, tenant-scoping gaps, and split GORM/SQL schema ownership.

  • high backend/migrations/000005_identity_alias.up.sql:6 — SQL migration assumes GORM AutoMigrate has already created identity_alias and identity_alias_assignment; schema ownership is split and the migration is not self-contained for production. Create the tables in SQL or make the dependency explicit and order-safe.
  • high backend/modules/adaudit/repository/identity_alias_pg.go:40 — IdentityAlias.Create omits TenantID and List/Get/Users/Delete/Assign/Unassign do not explicitly filter by tenant_id. If tenant scoping is not applied by a global GORM middleware, this allows cross-tenant reads/writes. Pass the authenticated tenant and scope all queries.
  • high backend/migrations/000006_adaudit_write_for_user_writers.up.sql:5 — Data migration grants adaudit.write to every role holding users.write, broadening authorization and making the down migration lossy because it cannot reconstruct prior grants. Use explicit role grants or a reversible mapping table.
  • medium backend/migrations/000004_adaudit_write.up.sql:9 — role_permission insert hardcodes a role UUID and assumes that role exists; a missing or renamed role will fail or silently skip the grant. Select the role by stable name or guard the insert.
  • medium backend/database/migrations.go:72 — Adding GORM models while SQL migrations add indexes/FKs splits schema management between AutoMigrate and versioned SQL. Define one source of truth for these tables or document the required AutoMigrate-before-SQL sequence.
  • medium backend/modules/adaudit/repository/identity_alias_pg.go:100 — Delete's in-use check locks assignment rows, not the alias row, so a concurrent Assign can race between the count and alias delete. Lock the IdentityAlias row or rely on FK failure with retry.
  • low backend/modules/adaudit/handler/identity_alias.go:150 — PUT /users/:id/identity uses an empty identityId to unassign while PATCH also unassigns, creating an ambiguous write contract. Make unassign explicit (null body or dedicated endpoint) and keep PUT idempotent for assignment only.
  • low backend/modules/adaudit/repository/identity_alias_pg.go:28 — escapeLike is defined in the identity repository but used by ad_user repository; move it to a shared SQL helper if LIKE escaping is reused across modules.
  • low backend/modules/adaudit/repository/ad_user_pg.go:246 — List changes the repository/usecase return type from domain.ADUser to dto.UserRow and joins identity tables in the hot list query; ensure this internal contract change is intentional and does not leak DTOs into other layers.

🛑 bugs (silas-1.7-pro) — high/critical — please review

Summary: IdentityAlias.Create omits TenantID (zero UUID inserted) and all IdentityAlias queries lack tenant scoping, breaking multi-tenancy and allowing cross-tenant access.

  • high backend/modules/adaudit/repository/identity_alias_pg.go:39 — pgIdentityRepository.Create builds domain.IdentityAlias{Name, CreatedBy} without setting TenantID. The field is not null with no DB default, so the zero UUID (00000000-0000-0000-0000-000000000000) is inserted. Consequences: (1) the unique index idx_identity_alias_tenant_name on (tenant_id, lower(name)) enforces name uniqueness across ALL tenants since they all share tenant_id=0; (2) List/Get/Users/Delete have no tenant WHERE clause, so every tenant sees and can mutate every identity. Reproduce: two tenants each POST /ad-audit/identities with the same name — the second gets 409 even though they are different tenants.
  • high backend/modules/adaudit/repository/identity_alias_pg.go:47 — pgIdentityRepository.List queries Model(&domain.IdentityAlias{}) with no tenant filter. Combined with the zero-TenantID insert above, any authenticated user with adaudit.read can enumerate identity aliases belonging to other tenants. The same missing tenant scope applies to Get (line ~70), Users (line ~80), and Delete (line ~96). Reproduce: tenant A creates an identity; tenant B calls GET /ad-audit/identities and sees it.

🛑 security (silas-1.7-pro) — high/critical — please review

Summary: New authorization/permission changes require review; low-impact race condition in identity alias deletion.

  • low backend/modules/adaudit/repository/identity_alias_pg.go:114 — Delete's in-use check locks assignment rows, not the alias row; a concurrent Assign can insert after the count and be cascade-deleted, causing a lost assignment. Lock the identity_alias row (SELECT ... FOR UPDATE) or recheck after deletion.

🔴 go-deps — pending updates

🔍 Discovered 31 Go projects

📦 Dependencies with updates available:

  📁 ./agent:
     - github.com/threatwinds/go-sdk: v1.1.28 → v1.1.38
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./tools/rulecheck:
     - github.com/threatwinds/go-sdk: v1.1.31 → v1.1.38

  📁 ./agent-manager:
     - github.com/threatwinds/go-sdk: v1.1.31 → v1.1.38
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./collectors/forwarder:
     - github.com/threatwinds/go-sdk: v1.1.31 → v1.1.38
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./collectors/as400:
     - github.com/threatwinds/go-sdk: v1.1.31 → v1.1.38
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./collectors/utmstack:
     - github.com/threatwinds/go-sdk: v1.1.31 → v1.1.38
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./installer:
     - github.com/cloudfoundry/gosigar: v1.3.128 → v1.3.130

  📁 ./backend:
     - github.com/aws/aws-sdk-go-v2/config: v1.33.11 → v1.33.12
     - github.com/aws/aws-sdk-go-v2/credentials: v1.20.11 → v1.20.12
     - github.com/aws/aws-sdk-go-v2/service/sts: v1.51.5 → v1.51.6
     - github.com/crowdstrike/gofalcon: v0.23.0 → v0.24.0
     - google.golang.org/api: v0.309.0 → v0.310.0
     - google.golang.org/grpc: v1.84.0 → v1.85.0

  📁 ./plugins/aws:
     - github.com/aws/aws-sdk-go-v2: v1.47.4 → v1.47.5
     - github.com/aws/aws-sdk-go-v2/config: v1.33.11 → v1.33.12
     - github.com/aws/aws-sdk-go-v2/credentials: v1.20.11 → v1.20.12
     - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs: v1.90.2 → v1.90.3

  📁 ./plugins/gcp:
     - google.golang.org/api: v0.309.0 → v0.310.0

  📁 ./plugins/crowdstrike:
     - github.com/crowdstrike/gofalcon: v0.23.0 → v0.24.0

  📁 ./log-input:
     - google.golang.org/grpc: v1.84.0 → v1.85.0

❌ Please update dependencies before merging.

@AlexSanchez-bit AlexSanchez-bit linked an issue Oct 30, 2026 that may be closed by this pull request
1 of 2 tasks
@AlexSanchez-bit
AlexSanchez-bit merged commit 2bd2860 into release/v12.0.0 Oct 30, 2026
1 check passed
@AlexSanchez-bit
AlexSanchez-bit deleted the feature/ad-audit-identity-alias branch October 30, 2026 15:56
@github-project-automation github-project-automation Bot moved this to ✅ Done in UTMStack OSS Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

adduser labeling on user-auditor Adds support for cloud identity providers so the user-auditor module can track user lifecycle events.

2 participants