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

Specify a list of allowed folders/files to be archived #2235

Merged
merged 4 commits into from
Nov 9, 2021
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
6 changes: 6 additions & 0 deletions changelog/unreleased/select-folders-to-be-archived.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Specify a list of allowed folders/files to be archived

Adds a configuration to the archiver service in order to specify
a list of folders (as regex) that can be archived.

https://github.com/cs3org/reva/pull/2235
78 changes: 64 additions & 14 deletions internal/http/services/archiver/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"

"regexp"

"github.com/cs3org/reva/internal/http/services/archiver/manager"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
Expand All @@ -52,17 +54,20 @@ type svc struct {
log *zerolog.Logger
walker walker.Walker
downloader downloader.Downloader

allowedFolders []*regexp.Regexp
}

// Config holds the config options that need to be passed down to all ocdav handlers
type Config struct {
Prefix string `mapstructure:"prefix"`
GatewaySvc string `mapstructure:"gatewaysvc"`
Timeout int64 `mapstructure:"timeout"`
Insecure bool `mapstructure:"insecure"`
Name string `mapstructure:"name"`
MaxNumFiles int64 `mapstructure:"max_num_files"`
MaxSize int64 `mapstructure:"max_size"`
Prefix string `mapstructure:"prefix"`
GatewaySvc string `mapstructure:"gatewaysvc"`
Timeout int64 `mapstructure:"timeout"`
Insecure bool `mapstructure:"insecure"`
Name string `mapstructure:"name"`
MaxNumFiles int64 `mapstructure:"max_num_files"`
MaxSize int64 `mapstructure:"max_size"`
AllowedFolders []string `mapstructure:"allowed_folders"`
}

func init() {
Expand All @@ -84,12 +89,23 @@ func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, erro
return nil, err
}

// compile all the regex for filtering folders
allowedFolderRegex := make([]*regexp.Regexp, 0, len(c.AllowedFolders))
for _, s := range c.AllowedFolders {
regex, err := regexp.Compile(s)
if err != nil {
return nil, err
}
allowedFolderRegex = append(allowedFolderRegex, regex)
}

return &svc{
config: c,
gtwClient: gtw,
downloader: downloader.NewDownloader(gtw, rhttp.Insecure(c.Insecure), rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second)))),
walker: walker.NewWalker(gtw),
log: log,
config: c,
gtwClient: gtw,
downloader: downloader.NewDownloader(gtw, rhttp.Insecure(c.Insecure), rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second)))),
walker: walker.NewWalker(gtw),
log: log,
allowedFolders: allowedFolderRegex,
}, nil
}

Expand All @@ -110,7 +126,7 @@ func (s *svc) getFiles(ctx context.Context, files, ids []string) ([]string, erro
return nil, errtypes.BadRequest("file and id lists are both empty")
}

f := []string{}
f := make([]string, 0, len(files)+len(ids))

for _, id := range ids {
// id is base64 encoded and after decoding has the form <storage_id>:<resource_id>
Expand Down Expand Up @@ -142,7 +158,39 @@ func (s *svc) getFiles(ctx context.Context, files, ids []string) ([]string, erro

}

return append(f, files...), nil
total := append(f, files...)

// check if all the folders are allowed to be archived
err := s.allAllowed(total)
if err != nil {
return nil, err
}

return total, nil
}

// return true if path match with at least with one allowed folder regex
func (s *svc) isPathAllowed(path string) bool {
for _, reg := range s.allowedFolders {
if reg.MatchString(path) {
return true
}
}
return false
}

// return nil if all the paths in the slide match with at least one allowed folder regex
func (s *svc) allAllowed(paths []string) error {
if len(s.allowedFolders) == 0 {
return nil
}

for _, f := range paths {
if !s.isPathAllowed(f) {
return errtypes.BadRequest(fmt.Sprintf("resource at %s not allowed to be archived", f))
}
}
return nil
}

func (s *svc) Handler() http.Handler {
Expand All @@ -164,6 +212,7 @@ func (s *svc) Handler() http.Handler {
if err != nil {
s.log.Error().Msg(err.Error())
rw.WriteHeader(http.StatusBadRequest)
_, _ = rw.Write([]byte(err.Error()))
return
}

Expand All @@ -174,6 +223,7 @@ func (s *svc) Handler() http.Handler {
if err != nil {
s.log.Error().Msg(err.Error())
rw.WriteHeader(http.StatusInternalServerError)
_, _ = rw.Write([]byte(err.Error()))
return
}

Expand Down