scim

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: May 12, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package scim implements the §6.3.1 SCIM 2.0 receiver. The registry exposes /scim/v2/Users and /scim/v2/Groups so an OIDC IdP (Okta, Entra ID, Workspace, Auth0, Keycloak) can push user and group memberships into the registry. The visibility evaluator queries scim_memberships when a layer config references a group that exists in the SCIM table.

SCIM scope shipped here:

  • Users: id, externalId, userName, emails, active.
  • Groups: id, displayName, members.
  • Filter expressions: eq, sw, co on userName / displayName.
  • Bearer token auth via PODIUM_SCIM_TOKEN.

Operations not shipped (return SCIM-conformant errors):

  • PATCH operations beyond simple add/remove members and toggle active. Most IdPs use full PUT to be safe.
  • Bulk endpoint (/Bulk).
  • Schemas / ServiceProviderConfig discovery beyond the minimum the IdP needs to validate the endpoint.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned when a SCIM resource is missing.
	ErrNotFound = errors.New("scim: not found")
	// ErrConflict is returned when uniqueness is violated (e.g.,
	// two Users with the same userName).
	ErrConflict = errors.New("scim: conflict")
	// ErrInvalidFilter signals an unsupported SCIM filter; maps
	// to SCIM error code "invalidFilter".
	ErrInvalidFilter = errors.New("scim: invalid filter")
)

Errors returned by Store implementations.

Functions

This section is empty.

Types

type FileStore

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

FileStore persists the SCIM directory to a JSON file. The in-memory `Memory` store handles read paths; mutation paths delegate to it and then persist the file atomically.

Suitable for §6.3.1 deployments with hundreds of users / groups and infrequent IdP pushes. Heavier deployments should use a SQL-backed store.

func LoadFileStore

func LoadFileStore(path string) (*FileStore, error)

LoadFileStore reads path (when present) and returns a SCIM store pre-populated with every record. Missing path yields an empty store that creates the file on the first mutation.

func (*FileStore) CreateGroup

func (f *FileStore) CreateGroup(ctx context.Context, g Group) (Group, error)

CreateGroup delegates and persists.

func (*FileStore) CreateUser

func (f *FileStore) CreateUser(ctx context.Context, u User) (User, error)

CreateUser delegates to the embedded Memory store and persists.

func (*FileStore) DeleteGroup

func (f *FileStore) DeleteGroup(ctx context.Context, id string) error

DeleteGroup delegates and persists.

func (*FileStore) DeleteUser

func (f *FileStore) DeleteUser(ctx context.Context, id string) error

DeleteUser delegates and persists.

func (*FileStore) GetGroup

func (f *FileStore) GetGroup(ctx context.Context, id string) (Group, error)

GetGroup delegates to the embedded Memory store.

func (*FileStore) GetUser

func (f *FileStore) GetUser(ctx context.Context, id string) (User, error)

GetUser delegates to the embedded Memory store.

func (*FileStore) ListGroups

func (f *FileStore) ListGroups(ctx context.Context, filter Filter) ([]Group, error)

ListGroups delegates to the embedded Memory store.

func (*FileStore) ListUsers

func (f *FileStore) ListUsers(ctx context.Context, filter Filter) ([]User, error)

ListUsers delegates to the embedded Memory store.

func (*FileStore) MembersOf

func (f *FileStore) MembersOf(ctx context.Context, groupName string) ([]string, error)

MembersOf delegates to the embedded Memory store.

func (*FileStore) ReplaceGroup

func (f *FileStore) ReplaceGroup(ctx context.Context, id string, g Group) (Group, error)

ReplaceGroup delegates and persists.

func (*FileStore) ReplaceUser

func (f *FileStore) ReplaceUser(ctx context.Context, id string, u User) (User, error)

ReplaceUser delegates and persists.

type Filter

type Filter struct {
	Attribute string // userName | displayName | active | externalId
	Operator  string // eq | sw | co | pr
	Value     string
}

Filter is the parsed §6.3.1 SCIM filter expression. Empty matches everything.

func (Filter) Match

func (f Filter) Match(attr, value string) bool

Match reports whether s passes the filter.

type Group

type Group struct {
	ID          string
	DisplayName string
	MemberIDs   []string
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

Group is the §6.3.1 group resource.

type Handler

type Handler struct {
	Store  Store
	Tokens map[string]bool // valid bearer tokens
}

Handler is the SCIM HTTP front-end. Mount under /scim/v2/.

Routes:

GET    /Users[/{id}]
POST   /Users
PUT    /Users/{id}
DELETE /Users/{id}
GET    /Groups[/{id}]
POST   /Groups
PUT    /Groups/{id}
DELETE /Groups/{id}

Auth: bearer token validated against the configured Tokens set.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

Handler implements http.Handler.

type Memory

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

Memory is an in-memory Store. Used by tests and standalone deployments that don't need SCIM persistence across restarts.

func NewMemory

func NewMemory() *Memory

NewMemory returns an empty in-memory SCIM store.

func (*Memory) CreateGroup

func (m *Memory) CreateGroup(_ context.Context, g Group) (Group, error)

CreateGroup persists g and returns its committed form.

func (*Memory) CreateUser

func (m *Memory) CreateUser(_ context.Context, u User) (User, error)

CreateUser stores u and returns the persisted form (with ID set).

func (*Memory) DeleteGroup

func (m *Memory) DeleteGroup(_ context.Context, id string) error

DeleteGroup removes the group; missing id is a no-op.

func (*Memory) DeleteUser

func (m *Memory) DeleteUser(_ context.Context, id string) error

DeleteUser removes the user; missing id is a no-op.

func (*Memory) GetGroup

func (m *Memory) GetGroup(_ context.Context, id string) (Group, error)

GetGroup returns the group or ErrNotFound.

func (*Memory) GetUser

func (m *Memory) GetUser(_ context.Context, id string) (User, error)

GetUser returns the user or ErrNotFound.

func (*Memory) ListGroups

func (m *Memory) ListGroups(_ context.Context, filter Filter) ([]Group, error)

ListGroups returns every group matching filter.

func (*Memory) ListUsers

func (m *Memory) ListUsers(_ context.Context, filter Filter) ([]User, error)

ListUsers returns every user matching filter.

func (*Memory) MembersOf

func (m *Memory) MembersOf(_ context.Context, groupName string) ([]string, error)

MembersOf returns userName values for every user in the named group. Used by the §4.6 visibility evaluator to expand `groups:` filters.

func (*Memory) ReplaceGroup

func (m *Memory) ReplaceGroup(_ context.Context, id string, g Group) (Group, error)

ReplaceGroup overwrites the stored group.

func (*Memory) ReplaceUser

func (m *Memory) ReplaceUser(_ context.Context, id string, u User) (User, error)

ReplaceUser overwrites the stored user with u (id from the path wins).

type Store

type Store interface {
	CreateUser(ctx context.Context, u User) (User, error)
	GetUser(ctx context.Context, id string) (User, error)
	ListUsers(ctx context.Context, filter Filter) ([]User, error)
	ReplaceUser(ctx context.Context, id string, u User) (User, error)
	DeleteUser(ctx context.Context, id string) error

	CreateGroup(ctx context.Context, g Group) (Group, error)
	GetGroup(ctx context.Context, id string) (Group, error)
	ListGroups(ctx context.Context, filter Filter) ([]Group, error)
	ReplaceGroup(ctx context.Context, id string, g Group) (Group, error)
	DeleteGroup(ctx context.Context, id string) error

	// MembersOf returns the SCIM userNames of every user in the
	// named group. Used by the visibility evaluator to expand
	// `groups:` filters in layer config.
	MembersOf(ctx context.Context, groupName string) ([]string, error)
}

Store is the SPI implementations satisfy.

type User

type User struct {
	ID         string
	ExternalID string
	UserName   string
	Email      string
	Active     bool
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

User is the §6.3.1 user resource. The fields mirror the SCIM 2.0 core schema but only carry what the visibility evaluator needs.

Jump to

Keyboard shortcuts

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