iam

package
v1.786.220 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package iam is the admin cockpit's typed reader for the Hanzo IAM management surface (/v1/iam/get-*). IAM runs as its own deployment (not fused into this binary), so these are HTTP calls, not Go method dispatch. Every call REPLAYS THE CALLER'S OWN credential (session cookie + Authorization), so IAM authorizes the read as the same principal the gateway already validated as a SuperAdmin. admin adds NO service credential of its own here: it never widens what the caller could read directly, and IAM's own IsSuperAdmin gate stays the second line of defense.

The reads split two orthogonal ways: TYPED domain reads the cockpit folds into its own rows — Orgs/Users (paginated lists), Org/User (one row), SetUser (the one write) — and a generic verbatim List the cockpit forwards field-for-field (roles, applications, audit records). An unwired IAM (no base) is not Ready and every read reports the honest not-configured error.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client reads the IAM management surface (/v1/iam/get-*) on behalf of a verified SuperAdmin caller.

func New

func New(base string) *Client

New builds an IAM client for base (empty base → not Ready).

func (*Client) List

func (c *Client) List(ctx context.Context, cr Creds, path string, q url.Values) (List, error)

List calls an IAM get-* endpoint and returns the raw data array + data2 total — the verbatim-forward primitive (roles, applications, audit records reach the operator field-for-field). A non-ok envelope is an error (surfaced honestly to the operator).

func (*Client) Org

func (c *Client) Org(ctx context.Context, cr Creds, id string) (Org, error)

Org fetches ONE organization row (GET /v1/iam/get-organization?id=owner/name) as the typed Org subset the scoped read panels fold over. Replays the caller's own credential, so IAM authorizes the read as the same validated principal — a non-super caller can only ever read their OWN org this way (the second line of the tenant-scope defense). Best-effort by design: the scoped-orgs fan-in tolerates an error and falls back to a name-only row.

func (*Client) Orgs

func (c *Client) Orgs(ctx context.Context, cr Creds, q url.Values) (List, error)

Orgs lists organizations (GET /v1/iam/get-organizations).

func (*Client) Ready

func (c *Client) Ready() bool

Ready reports whether an IAM endpoint is wired on this deployment.

func (*Client) SetUser

func (c *Client) SetUser(ctx context.Context, cr Creds, id string, user map[string]any) error

SetUser writes a full user object back (POST /v1/iam/update-user?id=owner/name). The caller's replayed credential is a VALIDATED SuperAdmin, whom IAM's CheckPermissionForUpdateUser admits to set privileged fields (isForbidden) on any user — a tenant/org-admin is refused by IAM itself, so this can never be abused to suspend across a boundary the caller couldn't already cross. admin adds no service credential of its own; IAM re-checks IsSuperAdmin.

func (*Client) User

func (c *Client) User(ctx context.Context, cr Creds, id string) (map[string]any, error)

User fetches ONE user as its FULL wire object (GET /v1/iam/get-user?id= owner/name), preserving every field. The suspend/reactivate action reads the whole object, flips isForbidden, and writes it back — update-user REPLACES the row, so operating on the full object (not a typed subset) is what keeps every other field intact. Replays the caller's own credential, so IAM authorizes the read as the same validated SuperAdmin.

func (*Client) Users

func (c *Client) Users(ctx context.Context, cr Creds, q url.Values) (List, error)

Users lists users (GET /v1/iam/get-users).

type Creds

type Creds struct {
	Cookie string
	Auth   string
}

Creds is the caller's replayed authorization context: the raw Cookie header and Authorization bearer captured off the inbound request. IAM authenticates exactly as it does for the browser (credentials: 'include').

type List

type List struct {
	Rows  json.RawMessage
	Total int
}

List is a decoded paginated read: the raw rows and the backend total.

type Org

type Org struct {
	Owner       string `json:"owner"`
	Name        string `json:"name"`
	DisplayName string `json:"displayName"`
	CreatedTime string `json:"createdTime"`
}

Org is the IAM Organization subset the aggregators fold over.

type User

type User struct {
	Owner          string `json:"owner"`
	Name           string `json:"name"`
	Email          string `json:"email"`
	DisplayName    string `json:"displayName"`
	Tag            string `json:"tag"`
	CreatedTime    string `json:"createdTime"`
	LastSigninTime string `json:"lastSigninTime"`
	IsAdmin        bool   `json:"isAdmin"`
	IsForbidden    bool   `json:"isForbidden"`
	AccessKey      string `json:"accessKey"`
}

User is the IAM User subset mapped into OperatorUser. AccessKey is decoded ONLY to derive API-key PRESENCE (hasApiKey) for the customer detail — its VALUE is never surfaced in any admin response (the hk- key is a credential, not a display field), so no secret leaves this binary.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL