mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-26 06:50:36 -05:00
Merge pull request #95 from owncloud/roles-middleware
Add assigned roles to access token
This commit is contained in:
5
changelog/unreleased/mint-roles.md
Normal file
5
changelog/unreleased/mint-roles.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Enhancement: Add roleIDs to the access token
|
||||
|
||||
We are using the roleIDs of the authenticated user for permission checks against ocis-settings. We added the roleIDs to the access token to have them available quickly.
|
||||
|
||||
https://github.com/owncloud/ocis-proxy/pull/95
|
||||
18
go.mod
18
go.mod
@@ -3,29 +3,29 @@ module github.com/owncloud/ocis-proxy
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.2.0
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.2.1
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.7.0
|
||||
contrib.go.opencensus.io/exporter/zipkin v0.1.1
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200611124600-7a1be2026543
|
||||
github.com/cs3org/reva v0.1.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20200730121022-c4f3d4f7ddfd
|
||||
github.com/cs3org/reva v1.1.0
|
||||
github.com/justinas/alice v1.2.0
|
||||
github.com/micro/cli/v2 v2.1.2
|
||||
github.com/micro/go-micro/v2 v2.6.0
|
||||
github.com/micro/go-micro/v2 v2.9.1
|
||||
github.com/oklog/run v1.1.0
|
||||
github.com/openzipkin/zipkin-go v0.2.2
|
||||
github.com/owncloud/flaex v0.2.0
|
||||
github.com/owncloud/ocis-accounts v0.1.2-0.20200618163128-aa8ae58dd95e
|
||||
github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200811112628-2151a60cc204
|
||||
github.com/owncloud/ocis-pkg/v2 v2.4.0
|
||||
github.com/owncloud/ocis-settings v0.3.2-0.20200828130413-0cc0f5bf26fe
|
||||
github.com/owncloud/ocis-store v0.0.0-20200716140351-f9670592fb7b
|
||||
github.com/prometheus/client_golang v1.7.0
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/restic/calens v0.2.0
|
||||
github.com/spf13/viper v1.7.0
|
||||
go.opencensus.io v0.22.4
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
google.golang.org/grpc v1.29.1
|
||||
gopkg.in/square/go-jose.v2 v2.4.0 // indirect
|
||||
google.golang.org/grpc v1.31.0
|
||||
)
|
||||
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
|
||||
|
||||
@@ -10,16 +10,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/justinas/alice"
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-proxy/pkg/cs3"
|
||||
"github.com/owncloud/ocis-proxy/pkg/middleware"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/jaeger"
|
||||
"contrib.go.opencensus.io/exporter/ocagent"
|
||||
"contrib.go.opencensus.io/exporter/zipkin"
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/justinas/alice"
|
||||
"github.com/micro/cli/v2"
|
||||
mclient "github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/grpc"
|
||||
@@ -27,15 +22,20 @@ import (
|
||||
openzipkin "github.com/openzipkin/zipkin-go"
|
||||
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
|
||||
acc "github.com/owncloud/ocis-accounts/pkg/proto/v0"
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-proxy/pkg/config"
|
||||
"github.com/owncloud/ocis-proxy/pkg/cs3"
|
||||
"github.com/owncloud/ocis-proxy/pkg/flagset"
|
||||
"github.com/owncloud/ocis-proxy/pkg/metrics"
|
||||
"github.com/owncloud/ocis-proxy/pkg/middleware"
|
||||
"github.com/owncloud/ocis-proxy/pkg/proxy"
|
||||
"github.com/owncloud/ocis-proxy/pkg/server/debug"
|
||||
proxyHTTP "github.com/owncloud/ocis-proxy/pkg/server/http"
|
||||
settings "github.com/owncloud/ocis-settings/pkg/proto/v0"
|
||||
storepb "github.com/owncloud/ocis-store/pkg/proto/v0"
|
||||
"go.opencensus.io/stats/view"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
@@ -258,11 +258,13 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
// TODO this won't work with a registry other than mdns. Look into Micro's client initialization.
|
||||
// https://github.com/owncloud/ocis-proxy/issues/38
|
||||
accounts := acc.NewAccountsService("com.owncloud.api.accounts", mclient.DefaultClient)
|
||||
roles := settings.NewRoleService("com.owncloud.api.settings", mclient.DefaultClient)
|
||||
|
||||
uuidMW := middleware.AccountUUID(
|
||||
middleware.Logger(l),
|
||||
middleware.TokenManagerConfig(cfg.TokenManager),
|
||||
middleware.AccountsClient(accounts),
|
||||
middleware.SettingsRoleService(roles),
|
||||
)
|
||||
|
||||
// the connection will be established in a non blocking fashion
|
||||
|
||||
@@ -2,7 +2,9 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
settings "github.com/owncloud/ocis-settings/pkg/proto/v0"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -146,6 +148,17 @@ func AccountUUID(opts ...Option) func(next http.Handler) http.Handler {
|
||||
groups[i] = account.MemberOf[i].OnPremisesSamAccountName
|
||||
}
|
||||
|
||||
// fetch active roles from ocis-settings
|
||||
assignmentResponse, err := opt.SettingsRoleService.ListRoleAssignments(r.Context(), &settings.ListRoleAssignmentsRequest{AccountUuid: account.Id})
|
||||
roleIDs := make([]string, 0)
|
||||
if err != nil {
|
||||
l.Err(err).Str("accountID", account.Id).Msg("failed to fetch role assignments")
|
||||
} else {
|
||||
for _, assignment := range assignmentResponse.Assignments {
|
||||
roleIDs = append(roleIDs, assignment.RoleId)
|
||||
}
|
||||
}
|
||||
|
||||
l.Debug().Interface("claims", claims).Interface("account", account).Msgf("Associated claims with uuid")
|
||||
user := &revauser.User{
|
||||
Id: &revauser.UserId{
|
||||
@@ -171,6 +184,17 @@ func AccountUUID(opts ...Option) func(next http.Handler) http.Handler {
|
||||
Value: []byte(strconv.FormatInt(account.GidNumber, 10)),
|
||||
}
|
||||
|
||||
// encode roleIDs as json string
|
||||
roleIDsJSON, jsonErr := json.Marshal(roleIDs)
|
||||
if jsonErr != nil {
|
||||
l.Err(jsonErr).Str("accountID", account.Id).Msg("failed to marshal roleIDs into json")
|
||||
} else {
|
||||
user.Opaque.Map["roles"] = &types.OpaqueEntry{
|
||||
Decoder: "json",
|
||||
Value: roleIDsJSON,
|
||||
}
|
||||
}
|
||||
|
||||
token, err := tokenManager.MintToken(r.Context(), user)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-pkg/v2/oidc"
|
||||
"github.com/owncloud/ocis-proxy/pkg/config"
|
||||
settings "github.com/owncloud/ocis-settings/pkg/proto/v0"
|
||||
)
|
||||
|
||||
// TODO testing the getAccount method should inject a cache
|
||||
@@ -35,6 +36,7 @@ func TestAccountUUIDMiddleware(t *testing.T) {
|
||||
Logger(log.NewLogger()),
|
||||
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
|
||||
AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, true)),
|
||||
SettingsRoleService(mockAccountUUIDMiddlewareRolesSvc(false)),
|
||||
)(next)
|
||||
|
||||
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
|
||||
@@ -55,6 +57,7 @@ func TestAccountUUIDMiddlewareWithDisabledAccount(t *testing.T) {
|
||||
Logger(log.NewLogger()),
|
||||
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
|
||||
AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, false)),
|
||||
SettingsRoleService(mockAccountUUIDMiddlewareRolesSvc(false)),
|
||||
)(next)
|
||||
|
||||
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
|
||||
@@ -72,16 +75,11 @@ func TestAccountUUIDMiddlewareWithDisabledAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
func mockAccountUUIDMiddlewareAccSvc(retErr, accEnabled bool) proto.AccountsService {
|
||||
if retErr {
|
||||
return &proto.MockAccountsService{
|
||||
ListFunc: func(ctx context.Context, in *proto.ListAccountsRequest, opts ...client.CallOption) (out *proto.ListAccountsResponse, err error) {
|
||||
return nil, fmt.Errorf("error returned by mockAccountsService LIST")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return &proto.MockAccountsService{
|
||||
ListFunc: func(ctx context.Context, in *proto.ListAccountsRequest, opts ...client.CallOption) (out *proto.ListAccountsResponse, err error) {
|
||||
if retErr {
|
||||
return nil, fmt.Errorf("error returned by mockAccountsService LIST")
|
||||
}
|
||||
return &proto.ListAccountsResponse{
|
||||
Accounts: []*proto.Account{
|
||||
{
|
||||
@@ -92,5 +90,17 @@ func mockAccountUUIDMiddlewareAccSvc(retErr, accEnabled bool) proto.AccountsServ
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func mockAccountUUIDMiddlewareRolesSvc(returnError bool) settings.RoleService {
|
||||
return &settings.MockRoleService{
|
||||
ListRoleAssignmentsFunc: func(ctx context.Context, req *settings.ListRoleAssignmentsRequest, opts ...client.CallOption) (res *settings.ListRoleAssignmentsResponse, err error) {
|
||||
if returnError {
|
||||
return nil, fmt.Errorf("error returned by mockRoleService.ListRoleAssignments")
|
||||
}
|
||||
return &settings.ListRoleAssignmentsResponse{
|
||||
Assignments: []*settings.UserRoleAssignment{},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
settings "github.com/owncloud/ocis-settings/pkg/proto/v0"
|
||||
"net/http"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
@@ -23,6 +24,8 @@ type Options struct {
|
||||
HTTPClient *http.Client
|
||||
// AccountsClient for resolving accounts
|
||||
AccountsClient acc.AccountsService
|
||||
// SettingsRoleService for the roles API in settings
|
||||
SettingsRoleService settings.RoleService
|
||||
// OIDCProviderFunc to lazily initialize a provider, must be set for the oidcProvider middleware
|
||||
OIDCProviderFunc func() (OIDCProvider, error)
|
||||
// OIDCIss is the oidc-issuer
|
||||
@@ -74,6 +77,13 @@ func AccountsClient(ac acc.AccountsService) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// SettingsRoleService provides a function to set the role service option.
|
||||
func SettingsRoleService(rc settings.RoleService) Option {
|
||||
return func(o *Options) {
|
||||
o.SettingsRoleService = rc
|
||||
}
|
||||
}
|
||||
|
||||
// OIDCProviderFunc provides a function to set the the oidc provider function option.
|
||||
func OIDCProviderFunc(f func() (OIDCProvider, error)) Option {
|
||||
return func(o *Options) {
|
||||
|
||||
Reference in New Issue
Block a user