Skip to content

Commit

Permalink
Merge pull request #1962 from owncloud/ocis-1798
Browse files Browse the repository at this point in the history
  • Loading branch information
refs authored Apr 28, 2021
2 parents 215b015 + 1257bc3 commit 8ec196d
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 18 deletions.
2 changes: 0 additions & 2 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,6 @@ def localApiTests(ctx, storage = 'owncloud', suite = 'apiBugDemonstration', acco
'environment' : {
'TEST_SERVER_URL': 'https://ocis-server:9200',
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/data/' if storage == 'owncloud' else ''),
'DELETE_USER_DATA_CMD': '%s' % ('' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/* /srv/app/tmp/ocis/storage/users/nodes/*-*-*-*'),
'SKELETON_DIR': '/srv/app/tmp/testing/data/apiSkeleton',
'OCIS_SKELETON_STRATEGY': '%s' % ('copy' if storage == 'owncloud' else 'upload'),
'TEST_OCIS':'true',
Expand Down Expand Up @@ -501,7 +500,6 @@ def coreApiTests(ctx, part_number = 1, number_of_parts = 1, storage = 'owncloud'
'environment' : {
'TEST_SERVER_URL': 'https://ocis-server:9200',
'OCIS_REVA_DATA_ROOT': '%s' % ('/srv/app/tmp/ocis/owncloud/data/' if storage == 'owncloud' else ''),
'DELETE_USER_DATA_CMD': '%s' % ('' if storage == 'owncloud' else 'rm -rf /srv/app/tmp/ocis/storage/users/nodes/root/* /srv/app/tmp/ocis/storage/users/nodes/*-*-*-*'),
'SKELETON_DIR': '/srv/app/tmp/testing/data/apiSkeleton',
'OCIS_SKELETON_STRATEGY': '%s' % ('copy' if storage == 'owncloud' else 'upload'),
'TEST_OCIS':'true',
Expand Down
15 changes: 15 additions & 0 deletions changelog/unreleased/ocs-user-deprovisioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Enhancement: User Deprovisioning for the OCS API

Use the CS3 API and Reva to deprovision users completely.

Two new environment variables introduced:
```
OCS_IDM_ADDRESS
OCS_STORAGE_USERS_DRIVER
```

`OCS_IDM_ADDRESS` is also an alias for `OCIS_URL`; allows the OCS service to mint jwt tokens for the authenticated user that will be read by the reva authentication middleware.

`OCS_STORAGE_USERS_DRIVER` determines how a user is deprovisioned. This kind of behavior is needed since every storage driver deals with deleting differently.

https://github.com/owncloud/ocis/pull/1962
2 changes: 2 additions & 0 deletions ocs/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ require (
github.com/owncloud/ocis/proxy v0.0.0-20210412105747-9b95e9b1191b
github.com/owncloud/ocis/settings v0.0.0-20210413063522-955bd60edf33
github.com/owncloud/ocis/store v0.0.0-20210413063522-955bd60edf33
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.10.0
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
github.com/thejerf/suture/v4 v4.0.0
go.opencensus.io v0.23.0
google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea
google.golang.org/grpc v1.37.0 // indirect
google.golang.org/protobuf v1.26.0
)

Expand Down
27 changes: 18 additions & 9 deletions ocs/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,26 @@ type TokenManager struct {
JWTSecret string
}

// IdentityManagement keeps track of the OIDC address. This is because Reva requisite of uniqueness for users
// is based in the combination of IDP hostname + UserID. For more information see:
// https://github.com/cs3org/reva/blob/4fd0229f13fae5bc9684556a82dbbd0eced65ef9/pkg/storage/utils/decomposedfs/node/node.go#L856-L865
type IdentityManagement struct {
Address string
}

// Config combines all available configuration parts.
type Config struct {
File string
Log Log
Debug Debug
HTTP HTTP
Tracing Tracing
TokenManager TokenManager
Service Service
AccountBackend string
RevaAddress string
File string
Log Log
Debug Debug
HTTP HTTP
Tracing Tracing
TokenManager TokenManager
Service Service
AccountBackend string
RevaAddress string
StorageUsersDriver string
IdentityManagement IdentityManagement

Context context.Context
Supervised bool
Expand Down
14 changes: 14 additions & 0 deletions ocs/pkg/flagset/flagset.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"OCS_REVA_GATEWAY_ADDR"},
Destination: &cfg.RevaAddress,
},
&cli.StringFlag{
Name: "idm-address",
Value: flags.OverrideDefaultString(cfg.IdentityManagement.Address, "https://localhost:9200"),
EnvVars: []string{"OCS_IDM_ADDRESS", "OCIS_URL"},
Usage: "keeps track of the IDM Address. Needed because of Reva requisite of uniqueness for users",
Destination: &cfg.IdentityManagement.Address,
},
&cli.StringFlag{
Name: "users-driver",
Value: flags.OverrideDefaultString(cfg.StorageUsersDriver, "ocis"),
Usage: "storage driver for users mount: eg. local, eos, owncloud, ocis or s3",
EnvVars: []string{"OCS_STORAGE_USERS_DRIVER", "STORAGE_USERS_DRIVER"},
Destination: &cfg.StorageUsersDriver,
},
}
}

Expand Down
142 changes: 137 additions & 5 deletions ocs/pkg/service/v0/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,27 @@ import (
"strings"

"github.com/asim/go-micro/plugins/client/grpc/v3"
merrors "github.com/asim/go-micro/v3/errors"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
revauser "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/token"
"github.com/cs3org/reva/pkg/token/manager/jwt"
"github.com/cs3org/reva/pkg/user"
"github.com/go-chi/chi"
"github.com/go-chi/render"
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/protobuf/types/known/fieldmaskpb"

merrors "github.com/asim/go-micro/v3/errors"
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
accounts "github.com/owncloud/ocis/accounts/pkg/proto/v0"
"github.com/owncloud/ocis/ocs/pkg/service/v0/data"
"github.com/owncloud/ocis/ocs/pkg/service/v0/response"
storepb "github.com/owncloud/ocis/store/pkg/proto/v0"
"github.com/pkg/errors"
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/types/known/fieldmaskpb"
)

// GetSelf returns the currently logged in user
Expand Down Expand Up @@ -358,6 +367,100 @@ func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) {
return
}

if o.config.RevaAddress != "" && o.config.StorageUsersDriver != "owncloud" {
t, err := o.mintTokenForUser(r.Context(), account)
if err != nil {
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "error minting token").Error())))
return
}

ctx := metadata.AppendToOutgoingContext(r.Context(), token.TokenHeader, t)

gwc, err := pool.GetGatewayServiceClient(o.config.RevaAddress)
if err != nil {
o.logger.Error().Err(err).Msg("error securing a connection to Reva gateway")
}

homeResp, err := gwc.GetHome(ctx, &provider.GetHomeRequest{})
if err != nil {
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not get home").Error())))
return
}

if homeResp.Status.Code != rpcv1beta1.Code_CODE_OK {
o.logger.Error().
Str("stat_status_code", homeResp.Status.Code.String()).
Str("stat_message", homeResp.Status.Message).
Msg("DeleteUser: could not get user home: get failed")
return
}

statResp, err := gwc.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Path{
Path: homeResp.Path,
},
},
})

if err != nil {
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not stat home").Error())))
return
}

if statResp.Status.Code != rpcv1beta1.Code_CODE_OK {
o.logger.Error().
Str("stat_status_code", statResp.Status.Code.String()).
Str("stat_message", statResp.Status.Message).
Msg("DeleteUser: could not delete user home: stat failed")
return
}

delReq := &provider.DeleteRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Id{
Id: statResp.Info.Id,
},
},
}

delResp, err := gwc.Delete(ctx, delReq)
if err != nil {
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not delete home").Error())))
return
}

if delResp.Status.Code != rpcv1beta1.Code_CODE_OK {
o.logger.Error().
Str("stat_status_code", statResp.Status.Code.String()).
Str("stat_message", statResp.Status.Message).
Msg("DeleteUser: could not delete user home: delete failed")
return
}

req := &gateway.PurgeRecycleRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Path{
Path: homeResp.Path,
},
},
}

purgeRecycleResponse, err := gwc.PurgeRecycle(ctx, req)
if err != nil {
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not delete trash").Error())))
return
}

if purgeRecycleResponse.Status.Code != rpcv1beta1.Code_CODE_OK {
o.logger.Error().
Str("stat_status_code", statResp.Status.Code.String()).
Str("stat_message", statResp.Status.Message).
Msg("DeleteUser: could not delete user trash: delete failed")
return
}
}

req := accounts.DeleteAccountRequest{
Id: account.Id,
}
Expand All @@ -378,6 +481,35 @@ func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) {
mustNotFail(render.Render(w, r, response.DataRender(struct{}{})))
}

// TODO(refs) this to ocis-pkg ... we are minting tokens all over the place ... or use a service? ... like reva?
func (o Ocs) mintTokenForUser(ctx context.Context, account *accounts.Account) (string, error) {
tm, _ := jwt.New(map[string]interface{}{
"secret": o.config.TokenManager.JWTSecret,
"expires": int64(60),
})

u := &revauser.User{
Id: &revauser.UserId{
OpaqueId: account.Id,
Idp: o.config.IdentityManagement.Address,
},
Groups: []string{},
Opaque: &types.Opaque{
Map: map[string]*types.OpaqueEntry{
"uid": {
Decoder: "plain",
Value: []byte(strconv.FormatInt(account.UidNumber, 10)),
},
"gid": {
Decoder: "plain",
Value: []byte(strconv.FormatInt(account.GidNumber, 10)),
},
},
},
}
return tm.MintToken(ctx, u)
}

// EnableUser enables a user
func (o Ocs) EnableUser(w http.ResponseWriter, r *http.Request) {
userid := chi.URLParam(r, "userid")
Expand Down
2 changes: 0 additions & 2 deletions tests/acceptance/expected-failures-API-on-OCIS-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -1539,8 +1539,6 @@ special character username not valid
- [apiProvisioning-v2/enableUser.feature:20](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiProvisioning-v2/enableUser.feature#L20)
- [apiProvisioning-v2/getUser.feature:34](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiProvisioning-v2/getUser.feature#L34)
- [apiProvisioning-v2/getUser.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiProvisioning-v2/getUser.feature#L35)
- [apiTrashbin/trashbinFilesFolders.feature:201](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L201)
- [apiTrashbin/trashbinFilesFolders.feature:202](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L202)
- [apiTrashbin/trashbinFilesFolders.feature:246](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L246)
- [apiTrashbin/trashbinFilesFolders.feature:247](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L247)
- [apiTrashbin/trashbinFilesFolders.feature:248](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L248)
Expand Down

0 comments on commit 8ec196d

Please sign in to comment.