Skip to content
This repository has been archived by the owner on Jan 27, 2021. It is now read-only.

Add assigned roles to access token #95

Merged
merged 7 commits into from
Aug 28, 2020
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
5 changes: 5 additions & 0 deletions changelog/unreleased/mint-roles.md
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
492 changes: 482 additions & 10 deletions go.sum

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@ 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"
"github.com/oklog/run"
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.
Expand Down Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions pkg/middleware/account_uuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package middleware

import (
"context"
"encoding/json"
"fmt"
settings "github.com/owncloud/ocis-settings/pkg/proto/v0"
"net/http"
"strconv"
"strings"
Expand Down Expand Up @@ -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{
Expand All @@ -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 {
Expand Down
26 changes: 18 additions & 8 deletions pkg/middleware/account_uuid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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{
{
Expand All @@ -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
},
}
}
10 changes: 10 additions & 0 deletions pkg/middleware/options.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down