diff --git a/changelog/unreleased/fix-cs3-backend.md b/changelog/unreleased/fix-cs3-backend.md new file mode 100644 index 000000000..ec72befa0 --- /dev/null +++ b/changelog/unreleased/fix-cs3-backend.md @@ -0,0 +1,5 @@ +Bugfix: IDP CS3 backend sessions now survire restart + +We now correctly reinitialize the CS3 backend session after the IDP has been restarted. + +https://github.com/owncloud/ocis/pull/8142 diff --git a/services/idp/pkg/backends/cs3/identifier/cs3.go b/services/idp/pkg/backends/cs3/identifier/cs3.go index 2370a0734..f4a2fa3fd 100644 --- a/services/idp/pkg/backends/cs3/identifier/cs3.go +++ b/services/idp/pkg/backends/cs3/identifier/cs3.go @@ -7,6 +7,7 @@ import ( cs3gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/libregraph/lico" "github.com/libregraph/lico/config" "github.com/libregraph/lico/identifier/backends" @@ -14,9 +15,6 @@ import ( "github.com/libregraph/lico/identity" cmap "github.com/orcaman/concurrent-map" "github.com/sirupsen/logrus" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - ins "google.golang.org/grpc/credentials/insecure" "stash.kopano.io/kgol/oidc-go" ) @@ -35,20 +33,18 @@ type CS3Backend struct { logger logrus.FieldLogger tlsConfig *tls.Config - gatewayURI string + gatewayAddr string machineAuthAPIKey string insecure bool sessions cmap.ConcurrentMap - - gateway cs3gateway.GatewayAPIClient } // NewCS3Backend creates a new CS3 backend identifier backend func NewCS3Backend( c *config.Config, tlsConfig *tls.Config, - gatewayURI string, + gatewayAddr string, machineAuthAPIKey string, insecure bool, ) (*CS3Backend, error) { @@ -62,7 +58,7 @@ func NewCS3Backend( logger: c.Logger, tlsConfig: tlsConfig, - gatewayURI: gatewayURI, + gatewayAddr: gatewayAddr, machineAuthAPIKey: machineAuthAPIKey, insecure: insecure, @@ -83,13 +79,10 @@ func (b *CS3Backend) RunWithContext(ctx context.Context) error { // password as provided. Requests are bound to the provided context. func (b *CS3Backend) Logon(ctx context.Context, audience, username, password string) (bool, *string, *string, backends.UserFromBackend, error) { - l, err := b.connect(ctx) + client, err := pool.GetGatewayServiceClient(b.gatewayAddr) if err != nil { - return false, nil, nil, nil, fmt.Errorf("cs3 backend logon connect error: %v", err) + return false, nil, nil, nil, err } - defer l.Close() - - client := cs3gateway.NewGatewayAPIClient(l) res, err := client.Authenticate(ctx, &cs3gateway.AuthenticateRequest{ Type: "basic", @@ -130,16 +123,46 @@ func (b *CS3Backend) Logon(ctx context.Context, audience, username, password str // context. func (b *CS3Backend) GetUser(ctx context.Context, userEntryID string, sessionRef *string, requestedScopes map[string]bool) (backends.UserFromBackend, error) { - session, err := b.getSessionForUser(ctx, userEntryID, sessionRef, true, true, false) - if err != nil { - return nil, fmt.Errorf("cs3 backend resolve session error: %v", err) + var session *cs3Session + if s, ok := b.sessions.Get(*sessionRef); ok { + // We have a cached session + session = s.(*cs3Session) + if session != nil { + user, err := newCS3User(session.User()) + if err != nil { + return nil, fmt.Errorf("cs3 backend get user failed to process user: %v", err) + } + return user, nil + } } - user, err := newCS3User(session.User()) + // rebuild session + + client, err := pool.GetGatewayServiceClient(b.gatewayAddr) if err != nil { - return nil, fmt.Errorf("cs3 backend get user failed to process user: %v", err) + return nil, err + } + + res, err := client.Authenticate(ctx, &cs3gateway.AuthenticateRequest{ + Type: "machine", + ClientId: "userid:" + userEntryID, + ClientSecret: b.machineAuthAPIKey, + }) + if err != nil { + return nil, fmt.Errorf("cs3 backend get user machine authenticate rpc error: %v", err) + } + if res.Status.Code != cs3rpc.Code_CODE_OK { + return nil, fmt.Errorf("cs3 backend get user machine authenticate failed with code %s: %s", res.Status.Code.String(), res.Status.Message) + } + + // cache session + session = createSession(ctx, res.User) + b.sessions.Set(*sessionRef, session) + + user, err := newCS3User(res.User) + if err != nil { + return nil, fmt.Errorf("cs3 backend get user data error: %v", err) } - // TODO double check userEntryID matches session? return user, nil } @@ -148,13 +171,10 @@ func (b *CS3Backend) GetUser(ctx context.Context, userEntryID string, sessionRef // user by providing the username. Requests are bound to the provided context. func (b *CS3Backend) ResolveUserByUsername(ctx context.Context, username string) (backends.UserFromBackend, error) { - l, err := b.connect(ctx) + client, err := pool.GetGatewayServiceClient(b.gatewayAddr) if err != nil { - return nil, fmt.Errorf("cs3 backend resolve username connect error: %v", err) + return nil, err } - defer l.Close() - - client := cs3gateway.NewGatewayAPIClient(l) res, err := client.Authenticate(ctx, &cs3gateway.AuthenticateRequest{ Type: "machine", @@ -210,29 +230,3 @@ func (b *CS3Backend) ScopesMeta() *scopes.Scopes { func (b *CS3Backend) Name() string { return cs3BackendName } - -func (b *CS3Backend) connect(ctx context.Context) (*grpc.ClientConn, error) { - if b.insecure { - return grpc.Dial(b.gatewayURI, grpc.WithTransportCredentials(ins.NewCredentials())) - } - - creds := credentials.NewTLS(b.tlsConfig) - return grpc.Dial(b.gatewayURI, grpc.WithTransportCredentials(creds)) -} - -func (b *CS3Backend) getSessionForUser(ctx context.Context, userEntryID string, sessionRef *string, register bool, refresh bool, removeIfRegistered bool) (*cs3Session, error) { - if sessionRef == nil { - return nil, nil - } - - var session *cs3Session - if s, ok := b.sessions.Get(*sessionRef); ok { - // Existing session. - session = s.(*cs3Session) - if session != nil { - return session, nil - } - } - - return session, nil -} diff --git a/services/idp/pkg/backends/cs3/identifier/session.go b/services/idp/pkg/backends/cs3/identifier/session.go index 3e2960c17..12ec61812 100644 --- a/services/idp/pkg/backends/cs3/identifier/session.go +++ b/services/idp/pkg/backends/cs3/identifier/session.go @@ -36,8 +36,5 @@ type cs3Session struct { // User returns the cs3 user of the session func (s *cs3Session) User() *cs3user.User { - if s == nil { - return nil - } return s.u }