mirror of
https://github.com/coder/coder.git
synced 2025-07-08 11:39:50 +00:00
* chore: implement organization and site wide role sync in idpsync * chore: remove old role sync, insert new idpsync package
94 lines
2.8 KiB
Go
94 lines
2.8 KiB
Go
package enidpsync
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/golang-jwt/jwt/v4"
|
|
"github.com/google/uuid"
|
|
"golang.org/x/xerrors"
|
|
|
|
"cdr.dev/slog"
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/idpsync"
|
|
"github.com/coder/coder/v2/coderd/runtimeconfig"
|
|
"github.com/coder/coder/v2/coderd/util/slice"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
func (e EnterpriseIDPSync) RoleSyncEntitled() bool {
|
|
return e.entitlements.Enabled(codersdk.FeatureUserRoleManagement)
|
|
}
|
|
|
|
func (e EnterpriseIDPSync) OrganizationRoleSyncEnabled(ctx context.Context, db database.Store, orgID uuid.UUID) (bool, error) {
|
|
if !e.RoleSyncEntitled() {
|
|
return false, nil
|
|
}
|
|
roleSyncSettings, err := e.Role.Resolve(ctx, e.Manager.OrganizationResolver(db, orgID))
|
|
if err != nil {
|
|
if xerrors.Is(err, runtimeconfig.ErrEntryNotFound) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
return roleSyncSettings.Field != "", nil
|
|
}
|
|
|
|
func (e EnterpriseIDPSync) SiteRoleSyncEnabled() bool {
|
|
if !e.RoleSyncEntitled() {
|
|
return false
|
|
}
|
|
return e.AGPLIDPSync.SiteRoleField != ""
|
|
}
|
|
|
|
func (e EnterpriseIDPSync) ParseRoleClaims(ctx context.Context, mergedClaims jwt.MapClaims) (idpsync.RoleParams, *idpsync.HTTPError) {
|
|
if !e.RoleSyncEntitled() {
|
|
return e.AGPLIDPSync.ParseRoleClaims(ctx, mergedClaims)
|
|
}
|
|
|
|
var claimRoles []string
|
|
if e.AGPLIDPSync.SiteRoleField != "" {
|
|
var err error
|
|
// TODO: Smoke test this error for org and site
|
|
claimRoles, err = e.AGPLIDPSync.RolesFromClaim(e.AGPLIDPSync.SiteRoleField, mergedClaims)
|
|
if err != nil {
|
|
rawType := mergedClaims[e.AGPLIDPSync.SiteRoleField]
|
|
e.Logger.Error(ctx, "oidc claims user roles field was an unknown type",
|
|
slog.F("type", fmt.Sprintf("%T", rawType)),
|
|
slog.F("field", e.AGPLIDPSync.SiteRoleField),
|
|
slog.F("raw_value", rawType),
|
|
slog.Error(err),
|
|
)
|
|
// TODO: Determine a static page or not
|
|
return idpsync.RoleParams{}, &idpsync.HTTPError{
|
|
Code: http.StatusInternalServerError,
|
|
Msg: "Login disabled until site wide OIDC config is fixed",
|
|
Detail: fmt.Sprintf("Roles claim must be an array of strings, type found: %T. Disabling role sync will allow login to proceed.", rawType),
|
|
RenderStaticPage: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
siteRoles := append([]string{}, e.SiteDefaultRoles...)
|
|
for _, role := range claimRoles {
|
|
if mappedRoles, ok := e.SiteRoleMapping[role]; ok {
|
|
if len(mappedRoles) == 0 {
|
|
continue
|
|
}
|
|
// Mapped roles are added to the list of roles
|
|
siteRoles = append(siteRoles, mappedRoles...)
|
|
continue
|
|
}
|
|
// Append as is.
|
|
siteRoles = append(siteRoles, role)
|
|
}
|
|
|
|
return idpsync.RoleParams{
|
|
SyncEntitled: e.RoleSyncEntitled(),
|
|
SyncSiteWide: e.SiteRoleSyncEnabled(),
|
|
SiteWideRoles: slice.Unique(siteRoles),
|
|
MergedClaims: mergedClaims,
|
|
}, nil
|
|
}
|