mirror of
https://github.com/SigNoz/signoz.git
synced 2026-08-25 22:10:54 +01:00
#### Description
- Moves the endpoints to `/api/v2/auth_domains` and removes the
`/api/v1/domains` routes — the request/response shapes changed, so they
live behind new paths instead of breaking v1 in place.
- Restructures the auth domain payload: `config` is now a `{kind, spec}`
discriminated envelope (same pattern as `RuleThresholdData` /
`EvaluationEnvelope`), replacing the old `ssoType` discriminator with
`samlConfig` / `googleAuthConfig` / `oidcConfig` sibling fields;
`ssoEnabled` and `roleMapping` move to the root as `enabled` and
`roleMapping`.
- Renames the provider kind `google_auth` → `google`, and the SAML keys
to metadata-consistent ones: `samlEntity` → `entityId`, `samlIdp` →
`location`, `samlCert` → `certificate`.
- Migrates the persisted documents too: a new sqlmigration rewrites
`auth_domain.data` into `{enabled, config: {kind, spec}, roleMapping}`,
so all legacy-shape code (storable twins, `google_auth` translation,
per-kind conversion switches) is deleted; the remaining per-kind wiring
lives in a single variant registry that `UnmarshalJSON`,
`JSONSchemaOneOf` and the discriminator mapping derive from.
- `AuthDomain` exposes the domain shape (`Enabled()`, `Kind()`,
`Config()`, `RoleMapping()`, typed spec accessors) instead of the
persisted document; `config` presence is enforced explicitly on
Postable/Updatable (the old PUT path never enforced it and could poison
a row).
- Secret fields (`clientSecret`, `serviceAccountJson`) are `format:
password` in the schema, and `GoogleConfig` loses the unused
`redirectURI` (the migration strips it from persisted documents).
- Frontend: regenerated client is a clean discriminated union; both
directions of the envelope↔form translation live in
`CreateEdit.utils.ts` with an explicit kind→provider mapping (no
cross-enum casts).
- The generated OpenAPI spec carries a real `discriminator`; the
kind/spec envelope pattern itself is documented generically in #12494,
and this PR only keeps the auth domain worked example in `types.md` in
step with the refactored types.
- Updates the google authn integration tests (#12486) to the new API,
and adds parametrized POST→GET roundtrip cases pinning the response
contract per kind (server-side defaulting, role-name normalization, null
maps) plus enforcement-toggle update coverage.
#### Issues closed by this PR
Closes SigNoz/platform-pod#2268
#### Additional Information
- Breaking change: `/api/v1/domains` is gone; the resource is now
`/api/v2/auth_domains` with the new shape. Login and SSO callback flows
are behaviorally unchanged, and existing rows are migrated in place at
startup.
- The `AuthNProvider` rename also surfaces in `/api/v2/sessions/context`
responses (`provider: "google"`) — the login page only consumes the
callback `url` — and in the reported stats key, which changes from
`authdomain.google_auth.count` to `authdomain.google.count`.
- Verified: `make go-test`, Go lint, frontend jest suites for
AuthDomain, `pnpm build`, `pnpm tsgo --noEmit`, and the full
`callbackauthn` domain suites (17 tests: roundtrip pins, the enforcement
toggle, and the google E2E flows) against a container rebuilt from this
branch — including a live run of the data migration over legacy-format
rows.
97 lines
2.8 KiB
Go
97 lines
2.8 KiB
Go
package implauthdomain
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/SigNoz/signoz/pkg/authn"
|
|
"github.com/SigNoz/signoz/pkg/authz"
|
|
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
)
|
|
|
|
type module struct {
|
|
store authtypes.AuthDomainStore
|
|
authNs map[authtypes.AuthNProvider]authn.AuthN
|
|
authz authz.AuthZ
|
|
}
|
|
|
|
func NewModule(store authtypes.AuthDomainStore, authNs map[authtypes.AuthNProvider]authn.AuthN, authz authz.AuthZ) authdomain.Module {
|
|
return &module{store: store, authNs: authNs, authz: authz}
|
|
}
|
|
|
|
func (module *module) Create(ctx context.Context, domain *authtypes.AuthDomain) error {
|
|
if err := module.validateRoleMapping(ctx, domain); err != nil {
|
|
return err
|
|
}
|
|
|
|
return module.store.Create(ctx, domain)
|
|
}
|
|
|
|
func (module *module) Get(ctx context.Context, id valuer.UUID) (*authtypes.AuthDomain, error) {
|
|
return module.store.Get(ctx, id)
|
|
}
|
|
|
|
func (module *module) GetAuthNProviderInfo(ctx context.Context, domain *authtypes.AuthDomain) *authtypes.AuthNProviderInfo {
|
|
if callbackAuthN, ok := module.authNs[domain.Kind()].(authn.CallbackAuthN); ok {
|
|
return callbackAuthN.ProviderInfo(ctx, domain)
|
|
}
|
|
return &authtypes.AuthNProviderInfo{}
|
|
}
|
|
|
|
func (module *module) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*authtypes.AuthDomain, error) {
|
|
return module.store.GetByOrgIDAndID(ctx, orgID, id)
|
|
}
|
|
|
|
func (module *module) GetByNameAndOrgID(ctx context.Context, name string, orgID valuer.UUID) (*authtypes.AuthDomain, error) {
|
|
return module.store.GetByNameAndOrgID(ctx, name, orgID)
|
|
}
|
|
|
|
func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error {
|
|
return module.store.Delete(ctx, orgID, id)
|
|
}
|
|
|
|
func (module *module) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*authtypes.AuthDomain, error) {
|
|
return module.store.ListByOrgID(ctx, orgID)
|
|
}
|
|
|
|
func (module *module) Update(ctx context.Context, domain *authtypes.AuthDomain) error {
|
|
if err := module.validateRoleMapping(ctx, domain); err != nil {
|
|
return err
|
|
}
|
|
|
|
return module.store.Update(ctx, domain)
|
|
}
|
|
|
|
func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
|
domains, err := module.store.ListByOrgID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stats := make(map[string]any)
|
|
|
|
for _, domain := range domains {
|
|
key := "authdomain." + domain.Kind().StringValue() + ".count"
|
|
if value, ok := stats[key]; ok {
|
|
stats[key] = value.(int64) + 1
|
|
} else {
|
|
stats[key] = int64(1)
|
|
}
|
|
}
|
|
|
|
stats["authdomain.count"] = len(domains)
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
func (module *module) validateRoleMapping(ctx context.Context, domain *authtypes.AuthDomain) error {
|
|
roleNames := domain.RoleMapping().RoleNames()
|
|
if len(roleNames) == 0 {
|
|
return nil
|
|
}
|
|
|
|
_, err := module.authz.ListByOrgIDAndNames(ctx, domain.StorableAuthDomain().OrgID, roleNames)
|
|
return err
|
|
}
|