mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-06 12:19:37 -06:00
enhancement(autoprovision): Allow to configure which claims to use for auto-provisioning user accounts
When auto-provisioning user accounts we used a fixed mapping for claims for the userinfo response to user attributes. This change introduces configuration options to defined which claims should be user for the username, display name and email address of the auto-provisioned accounts. This also removes the automatic fallback to use the 'mail' claim as the username when the 'preferred_username' claim does not exist. Fixes: #8635
This commit is contained in:
@@ -8,8 +8,8 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/staticroutes"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/store"
|
||||
chimiddleware "github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/justinas/alice"
|
||||
"github.com/oklog/run"
|
||||
@@ -18,8 +18,6 @@ import (
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/store"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
pkgmiddleware "github.com/owncloud/ocis/v2/ocis-pkg/middleware"
|
||||
@@ -39,6 +37,7 @@ import (
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/router"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/server/debug"
|
||||
proxyHTTP "github.com/owncloud/ocis/v2/services/proxy/pkg/server/http"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/staticroutes"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/userroles"
|
||||
ocisstore "github.com/owncloud/ocis/v2/services/store/pkg/store"
|
||||
@@ -227,6 +226,7 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
|
||||
backend.WithMachineAuthAPIKey(cfg.MachineAuthAPIKey),
|
||||
backend.WithOIDCissuer(cfg.OIDC.Issuer),
|
||||
backend.WithServiceAccount(cfg.ServiceAccount),
|
||||
backend.WithAutoProvisionClaims(cfg.AutoProvisionClaims),
|
||||
)
|
||||
default:
|
||||
logger.Fatal().Msgf("Invalid accounts backend type '%s'", cfg.AccountBackend)
|
||||
|
||||
@@ -24,25 +24,26 @@ type Config struct {
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GrpcClient client.Client `yaml:"-"`
|
||||
|
||||
RoleQuotas map[string]uint64 `yaml:"role_quotas"`
|
||||
Policies []Policy `yaml:"policies"`
|
||||
AdditionalPolicies []Policy `yaml:"additional_policies"`
|
||||
OIDC OIDC `yaml:"oidc"`
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
RoleAssignment RoleAssignment `yaml:"role_assignment"`
|
||||
PolicySelector *PolicySelector `yaml:"policy_selector"`
|
||||
PreSignedURL PreSignedURL `yaml:"pre_signed_url"`
|
||||
AccountBackend string `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE" desc:"Account backend the PROXY service should use. Currently only 'cs3' is possible here." introductionVersion:"pre5.0"`
|
||||
UserOIDCClaim string `yaml:"user_oidc_claim" env:"PROXY_USER_OIDC_CLAIM" desc:"The name of an OpenID Connect claim that is used for resolving users with the account backend. The value of the claim must hold a per user unique, stable and non re-assignable identifier. The availability of claims depends on your Identity Provider. There are common claims available for most Identity providers like 'email' or 'preferred_username' but you can also add your own claim." introductionVersion:"pre5.0"`
|
||||
UserCS3Claim string `yaml:"user_cs3_claim" env:"PROXY_USER_CS3_CLAIM" desc:"The name of a CS3 user attribute (claim) that should be mapped to the 'user_oidc_claim'. Supported values are 'username', 'mail' and 'userid'." introductionVersion:"pre5.0"`
|
||||
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services." introductionVersion:"pre5.0"`
|
||||
AutoprovisionAccounts bool `yaml:"auto_provision_accounts" env:"PROXY_AUTOPROVISION_ACCOUNTS" desc:"Set this to 'true' to automatically provision users that do not yet exist in the users service on-demand upon first sign-in. To use this a write-enabled libregraph user backend needs to be setup an running." introductionVersion:"pre5.0"`
|
||||
EnableBasicAuth bool `yaml:"enable_basic_auth" env:"PROXY_ENABLE_BASIC_AUTH" desc:"Set this to true to enable 'basic authentication' (username/password)." introductionVersion:"pre5.0"`
|
||||
InsecureBackends bool `yaml:"insecure_backends" env:"PROXY_INSECURE_BACKENDS" desc:"Disable TLS certificate validation for all HTTP backend connections." introductionVersion:"pre5.0"`
|
||||
BackendHTTPSCACert string `yaml:"backend_https_cacert" env:"PROXY_HTTPS_CACERT" desc:"Path/File for the root CA certificate used to validate the server’s TLS certificate for https enabled backend services." introductionVersion:"pre5.0"`
|
||||
AuthMiddleware AuthMiddleware `yaml:"auth_middleware"`
|
||||
PoliciesMiddleware PoliciesMiddleware `yaml:"policies_middleware"`
|
||||
CSPConfigFileLocation string `yaml:"csp_config_file_location" env:"PROXY_CSP_CONFIG_FILE_LOCATION" desc:"The location of the CSP configuration file." introductionVersion:"6.0"`
|
||||
RoleQuotas map[string]uint64 `yaml:"role_quotas"`
|
||||
Policies []Policy `yaml:"policies"`
|
||||
AdditionalPolicies []Policy `yaml:"additional_policies"`
|
||||
OIDC OIDC `yaml:"oidc"`
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
RoleAssignment RoleAssignment `yaml:"role_assignment"`
|
||||
PolicySelector *PolicySelector `yaml:"policy_selector"`
|
||||
PreSignedURL PreSignedURL `yaml:"pre_signed_url"`
|
||||
AccountBackend string `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE" desc:"Account backend the PROXY service should use. Currently only 'cs3' is possible here." introductionVersion:"pre5.0"`
|
||||
UserOIDCClaim string `yaml:"user_oidc_claim" env:"PROXY_USER_OIDC_CLAIM" desc:"The name of an OpenID Connect claim that is used for resolving users with the account backend. The value of the claim must hold a per user unique, stable and non re-assignable identifier. The availability of claims depends on your Identity Provider. There are common claims available for most Identity providers like 'email' or 'preferred_username' but you can also add your own claim." introductionVersion:"pre5.0"`
|
||||
UserCS3Claim string `yaml:"user_cs3_claim" env:"PROXY_USER_CS3_CLAIM" desc:"The name of a CS3 user attribute (claim) that should be mapped to the 'user_oidc_claim'. Supported values are 'username', 'mail' and 'userid'." introductionVersion:"pre5.0"`
|
||||
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services." introductionVersion:"pre5.0"`
|
||||
AutoprovisionAccounts bool `yaml:"auto_provision_accounts" env:"PROXY_AUTOPROVISION_ACCOUNTS" desc:"Set this to 'true' to automatically provision users that do not yet exist in the users service on-demand upon first sign-in. To use this a write-enabled libregraph user backend needs to be setup an running." introductionVersion:"pre5.0"`
|
||||
AutoProvisionClaims AutoProvisionClaims `yaml:"auto_provision_claims"`
|
||||
EnableBasicAuth bool `yaml:"enable_basic_auth" env:"PROXY_ENABLE_BASIC_AUTH" desc:"Set this to true to enable 'basic authentication' (username/password)." introductionVersion:"pre5.0"`
|
||||
InsecureBackends bool `yaml:"insecure_backends" env:"PROXY_INSECURE_BACKENDS" desc:"Disable TLS certificate validation for all HTTP backend connections." introductionVersion:"pre5.0"`
|
||||
BackendHTTPSCACert string `yaml:"backend_https_cacert" env:"PROXY_HTTPS_CACERT" desc:"Path/File for the root CA certificate used to validate the server’s TLS certificate for https enabled backend services." introductionVersion:"pre5.0"`
|
||||
AuthMiddleware AuthMiddleware `yaml:"auth_middleware"`
|
||||
PoliciesMiddleware PoliciesMiddleware `yaml:"policies_middleware"`
|
||||
CSPConfigFileLocation string `yaml:"csp_config_file_location" env:"PROXY_CSP_CONFIG_FILE_LOCATION" desc:"The location of the CSP configuration file." introductionVersion:"6.0"`
|
||||
|
||||
Context context.Context `yaml:"-" json:"-"`
|
||||
}
|
||||
@@ -153,6 +154,13 @@ type RoleMapping struct {
|
||||
ClaimValue string `yaml:"claim_value" desc:"The value of the 'PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM' that matches the role defined in 'role_name'."`
|
||||
}
|
||||
|
||||
// AutoProvisionClaims defines which claims from the OIDC userinfo response should be used for auto-provisioning user accounts
|
||||
type AutoProvisionClaims struct {
|
||||
Username string `yaml:"username" env:"PROXY_AUTOPROVISION_CLAIM_USERNAME" desc:"The name of the OIDC claim that holds the username." introductionVersion:"5.1"`
|
||||
Email string `yaml:"email" env:"PROXY_AUTOPROVISION_CLAIM_EMAIL" desc:"The name of the OIDC claim that holds the email." introductionVersion:"5.1"`
|
||||
DisplayName string `yaml:"display_name" env:"PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME" desc:"The name of the OIDC claim that holds the display name." introductionVersion:"5.1"`
|
||||
}
|
||||
|
||||
// PolicySelector is the toplevel-configuration for different selectors
|
||||
type PolicySelector struct {
|
||||
Static *StaticSelectorConf `yaml:"static"`
|
||||
|
||||
@@ -84,6 +84,11 @@ func DefaultConfig() *config.Config {
|
||||
UserOIDCClaim: "preferred_username",
|
||||
UserCS3Claim: "username",
|
||||
AutoprovisionAccounts: false,
|
||||
AutoProvisionClaims: config.AutoProvisionClaims{
|
||||
Username: "preferred_username",
|
||||
Email: "email",
|
||||
DisplayName: "name",
|
||||
},
|
||||
EnableBasicAuth: false,
|
||||
InsecureBackends: false,
|
||||
CSPConfigFileLocation: "",
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"go-micro.dev/v4/selector"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
|
||||
@@ -32,11 +31,12 @@ type Option func(o *Options)
|
||||
|
||||
// Options defines the available options for this package.
|
||||
type Options struct {
|
||||
logger log.Logger
|
||||
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
machineAuthAPIKey string
|
||||
oidcISS string
|
||||
serviceAccount config.ServiceAccount
|
||||
logger log.Logger
|
||||
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
machineAuthAPIKey string
|
||||
oidcISS string
|
||||
serviceAccount config.ServiceAccount
|
||||
autoProvisionClaims config.AutoProvisionClaims
|
||||
}
|
||||
|
||||
// WithLogger sets the logger option
|
||||
@@ -74,6 +74,12 @@ func WithServiceAccount(c config.ServiceAccount) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithAutoProvisionClaims(claims config.AutoProvisionClaims) Option {
|
||||
return func(o *Options) {
|
||||
o.autoProvisionClaims = claims
|
||||
}
|
||||
}
|
||||
|
||||
// NewCS3UserBackend creates a user-provider which fetches users from a CS3 UserBackend
|
||||
func NewCS3UserBackend(opts ...Option) UserBackend {
|
||||
opt := Options{}
|
||||
@@ -262,22 +268,22 @@ func (c cs3backend) isAlreadyExists(resp *http.Response) (bool, error) {
|
||||
}
|
||||
|
||||
func (c cs3backend) libregraphUserFromClaims(ctx context.Context, claims map[string]interface{}) (libregraph.User, error) {
|
||||
var ok bool
|
||||
var dn, mail, username string
|
||||
user := libregraph.User{}
|
||||
if dn, ok = claims[oidc.Name].(string); !ok {
|
||||
return user, fmt.Errorf("Missing claim '%s'", oidc.Name)
|
||||
if dn, ok := claims[c.autoProvisionClaims.DisplayName].(string); ok {
|
||||
user.SetDisplayName(dn)
|
||||
} else {
|
||||
return user, fmt.Errorf("Missing claim '%s' (displayName)", c.autoProvisionClaims.DisplayName)
|
||||
}
|
||||
if mail, ok = claims[oidc.Email].(string); !ok {
|
||||
return user, fmt.Errorf("Missing claim '%s'", oidc.Email)
|
||||
if mail, ok := claims[c.autoProvisionClaims.Email].(string); ok {
|
||||
user.SetMail(mail)
|
||||
} else {
|
||||
return user, fmt.Errorf("Missing claim '%s' (mail)", c.autoProvisionClaims.Email)
|
||||
}
|
||||
if username, ok = claims[oidc.PreferredUsername].(string); !ok {
|
||||
c.logger.Warn().Str("claim", oidc.PreferredUsername).Msg("Missing claim for username, falling back to email address")
|
||||
username = mail
|
||||
if username, ok := claims[c.autoProvisionClaims.Username].(string); ok {
|
||||
user.SetOnPremisesSamAccountName(username)
|
||||
} else {
|
||||
return user, fmt.Errorf("Missing claim '%s' (username)", c.autoProvisionClaims.Username)
|
||||
}
|
||||
user.DisplayName = &dn
|
||||
user.OnPremisesSamAccountName = &username
|
||||
user.Mail = &mail
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user