Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use service user for role assignment and autoprovisioning #7240

Merged
merged 4 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions changelog/unreleased/proxy-use-service-account.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Proxy uses service accounts for provisioning

The proxy service now uses a service account for provsioning task, like role
assignment and user auto-provisioning. This cleans up some technical debt that
required us to mint reva tokes inside the proxy service.

https://github.com/owncloud/ocis/pull/7240
https://github.com/owncloud/ocis/issues/5550
1 change: 1 addition & 0 deletions changelog/unreleased/service-accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Enhancement: Introduce service accounts
Introduces service accounts to avoid impersonating users in async processes

https://github.com/owncloud/ocis/pull/6427
https://github.com/owncloud/ocis/issues/5550
19 changes: 16 additions & 3 deletions ocis/pkg/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ type InsecureService struct {
Insecure bool
}

type InsecureProxyService struct {
type ProxyService struct {
OIDC InsecureProxyOIDC `yaml:"oidc"`
InsecureBackends bool `yaml:"insecure_backends"`
ServiceAccount ServiceAccount `yaml:"service_account"`
}

type InsecureProxyOIDC struct {
Expand Down Expand Up @@ -72,6 +73,10 @@ type IdmService struct {
ServiceUserPasswords ServiceUserPasswordsSettings `yaml:"service_user_passwords"`
}

type SettingsService struct {
ServiceAccountIDAdmin string `yaml:"service_account_id_admin"`
}

type FrontendService struct {
Archiver InsecureService
ServiceAccount ServiceAccount `yaml:"service_account"`
Expand Down Expand Up @@ -181,7 +186,7 @@ type OcisConfig struct {
Graph GraphService
Idp LdapBasedService
Idm IdmService
Proxy InsecureProxyService
Proxy ProxyService
Frontend FrontendService
AuthBasic AuthbasicService `yaml:"auth_basic"`
AuthBearer AuthbearerService `yaml:"auth_bearer"`
Expand All @@ -191,6 +196,7 @@ type OcisConfig struct {
Thumbnails ThumbnailService
Search Search
Audit Audit
Settings SettingsService `yaml:"settings"`
Sharing Sharing
StorageUsers StorageUsers `yaml:"storage_users"`
Notifications Notifications
Expand Down Expand Up @@ -389,6 +395,12 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
Clientlog: Clientlog{
ServiceAccount: serviceAccount,
},
Proxy: ProxyService{
ServiceAccount: serviceAccount,
},
Settings: SettingsService{
ServiceAccountIDAdmin: serviceAccount.ServiceAccountID,
},
}

if insecure {
Expand All @@ -406,11 +418,12 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
cfg.StorageUsers.Events = _insecureEvents
cfg.Nats.Nats.TLSSkipVerifyClientCert = true
cfg.Ocdav = _insecureService
cfg.Proxy = InsecureProxyService{
cfg.Proxy = ProxyService{
InsecureBackends: true,
OIDC: InsecureProxyOIDC{
Insecure: true,
},
ServiceAccount: serviceAccount,
}

cfg.Thumbnails.Thumbnail.WebdavAllowInsecure = true
Expand Down
7 changes: 4 additions & 3 deletions services/graph/pkg/middleware/requireadmin.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (

// RequireAdmin middleware is used to require the user in context to be an admin / have account management permissions
func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.Handler) http.Handler {

return func(next http.Handler) http.Handler {
l := logger.With().Str("middleware", "requireAdmin").Logger()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, ok := revactx.ContextGetUser(r.Context())
if !ok {
Expand All @@ -27,15 +27,16 @@ func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.Handler)
// get roles from context
roleIDs, ok := roles.ReadRoleIDsFromContext(r.Context())
if !ok {
logger.Debug().Str("userid", u.Id.OpaqueId).Msg("No roles in context, contacting settings service")
l.Debug().Str("userid", u.Id.OpaqueId).Msg("No roles in context, contacting settings service")
var err error
roleIDs, err = rm.FindRoleIDsForUser(r.Context(), u.Id.OpaqueId)
if err != nil {
logger.Err(err).Str("userid", u.Id.OpaqueId).Msg("failed to get roles for user")
l.Error().Err(err).Str("userid", u.Id.OpaqueId).Msg("Failed to get roles for user")
errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized")
return
}
if len(roleIDs) == 0 {
l.Error().Err(err).Str("userid", u.Id.OpaqueId).Msg("No roles assigned to user")
errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized")
return
}
Expand Down
97 changes: 0 additions & 97 deletions services/proxy/pkg/autoprovision/creator.go

This file was deleted.

11 changes: 3 additions & 8 deletions services/proxy/pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (

"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/store"
"github.com/cs3org/reva/v2/pkg/token/manager/jwt"
"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"
Expand All @@ -32,7 +31,6 @@ import (
policiessvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
storesvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/store/v0"
"github.com/owncloud/ocis/v2/services/proxy/pkg/autoprovision"
"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
"github.com/owncloud/ocis/v2/services/proxy/pkg/config/parser"
"github.com/owncloud/ocis/v2/services/proxy/pkg/logging"
Expand Down Expand Up @@ -282,14 +280,10 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
if err != nil {
logger.Fatal().Err(err).Msg("Failed to get gateway selector")
}
tokenManager, err := jwt.New(map[string]interface{}{
"secret": cfg.TokenManager.JWTSecret,
})
if err != nil {
logger.Fatal().Err(err).
Msg("Failed to create token manager")
}
autoProvsionCreator := autoprovision.NewCreator(autoprovision.WithTokenManager(tokenManager))
var userProvider backend.UserBackend
switch cfg.AccountBackend {
case "cs3":
Expand All @@ -298,7 +292,7 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
backend.WithRevaGatewaySelector(gatewaySelector),
backend.WithMachineAuthAPIKey(cfg.MachineAuthAPIKey),
backend.WithOIDCissuer(cfg.OIDC.Issuer),
backend.WithAutoProvisonCreator(autoProvsionCreator),
backend.WithServiceAccount(cfg.ServiceAccount),
)
default:
logger.Fatal().Msgf("Invalid accounts backend type '%s'", cfg.AccountBackend)
Expand All @@ -317,7 +311,8 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
userroles.WithLogger(logger),
userroles.WithRolesClaim(cfg.RoleAssignment.OIDCRoleMapper.RoleClaim),
userroles.WithRoleMapping(cfg.RoleAssignment.OIDCRoleMapper.RolesMap),
userroles.WithAutoProvisonCreator(autoProvsionCreator),
userroles.WithRevaGatewaySelector(gatewaySelector),
userroles.WithServiceAccount(cfg.ServiceAccount),
)
default:
logger.Fatal().Msgf("Invalid role assignment driver '%s'", cfg.RoleAssignment.Driver)
Expand Down
13 changes: 7 additions & 6 deletions services/proxy/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Config struct {
RoleQuotas map[string]uint64 `yaml:"role_quotas"`
Policies []Policy `yaml:"policies"`
OIDC OIDC `yaml:"oidc"`
TokenManager *TokenManager `mask:"struct" yaml:"token_manager"`
ServiceAccount ServiceAccount `yaml:"service_account"`
RoleAssignment RoleAssignment `yaml:"role_assignment"`
PolicySelector *PolicySelector `yaml:"policy_selector"`
PreSignedURL PreSignedURL `yaml:"pre_signed_url"`
Expand Down Expand Up @@ -160,11 +160,6 @@ type StaticSelectorConf struct {
Policy string `yaml:"policy"`
}

// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `mask:"password" yaml:"jwt_secret" env:"OCIS_JWT_SECRET;PROXY_JWT_SECRET" desc:"The secret to mint and validate JWT tokens."`
}

// PreSignedURL is the config for the presigned url middleware
type PreSignedURL struct {
AllowedHTTPMethods []string `yaml:"allowed_http_methods"`
Expand Down Expand Up @@ -192,3 +187,9 @@ type RegexRuleConf struct {
Match string `yaml:"match"`
Policy string `yaml:"policy"`
}

// ServiceAccount is the configuration for the used service account
type ServiceAccount struct {
ServiceAccountID string `yaml:"service_account_id" env:"OCIS_SERVICE_ACCOUNT_ID;PROXY_SERVICE_ACCOUNT_ID" desc:"The ID of the service account the service should use. See the 'auth-service' service description for more details."`
ServiceAccountSecret string `yaml:"service_account_secret" env:"OCIS_SERVICE_ACCOUNT_SECRET;PROXY_SERVICE_ACCOUNT_SECRET" desc:"The service account secret."`
}
8 changes: 0 additions & 8 deletions services/proxy/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,14 +268,6 @@ func EnsureDefaults(cfg *config.Config) {
cfg.OIDC.UserinfoCache = &config.Cache{}
}

if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil {
cfg.TokenManager = &config.TokenManager{
JWTSecret: cfg.Commons.TokenManager.JWTSecret,
}
} else if cfg.TokenManager == nil {
cfg.TokenManager = &config.TokenManager{}
}

if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" {
cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey
}
Expand Down
4 changes: 0 additions & 4 deletions services/proxy/pkg/config/parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ func ParseConfig(cfg *config.Config) error {
}

func Validate(cfg *config.Config) error {
if cfg.TokenManager.JWTSecret == "" {
return shared.MissingJWTTokenError(cfg.Service.Name)
}

if cfg.MachineAuthAPIKey == "" {
return shared.MissingMachineAuthApiKeyError(cfg.Service.Name)
}
Expand Down
2 changes: 0 additions & 2 deletions services/proxy/pkg/middleware/account_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/cs3org/reva/v2/pkg/token/manager/jwt"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend"
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend/mocks"
userRoleMocks "github.com/owncloud/ocis/v2/services/proxy/pkg/userroles/mocks"
Expand Down Expand Up @@ -194,7 +193,6 @@ func newMockAccountResolver(userBackendResult *userv1beta1.User, userBackendErr
Logger(log.NewLogger()),
UserProvider(&ub),
UserRoleAssigner(&ra),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
SkipUserInfo(false),
UserOIDCClaim(oidcclaim),
UserCS3Claim(cs3claim),
Expand Down
9 changes: 0 additions & 9 deletions services/proxy/pkg/middleware/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ type Option func(o *Options)
type Options struct {
// Logger to use for logging, must be set
Logger log.Logger
// TokenManagerConfig for communicating with the reva token manager
TokenManagerConfig config.TokenManager
// PolicySelectorConfig for using the policy selector
PolicySelector config.PolicySelector
// HTTPClient to use for communication with the oidcAuth provider
Expand Down Expand Up @@ -97,13 +95,6 @@ func Logger(l log.Logger) Option {
}
}

// TokenManagerConfig provides a function to set the token manger config option.
func TokenManagerConfig(cfg config.TokenManager) Option {
return func(o *Options) {
o.TokenManagerConfig = cfg
}
}

// PolicySelectorConfig provides a function to set the policy selector config option.
func PolicySelectorConfig(cfg config.PolicySelector) Option {
return func(o *Options) {
Expand Down
Loading