mirror of
https://github.com/restic/rest-server.git
synced 2025-10-19 07:33:21 +00:00
Add group-accessible-repos option (#308)
* Add group-accessible-repos option The group-accessible-repos option will let filesystem group id be able to access files and dir within the restic repo Default stick with old behaviour to be owner restricted While here make dirMode and fileMode within Options struct private --------- Co-authored-by: Michael Eischer <michael.eischer@fau.de>
This commit is contained in:
parent
10a06dcbf1
commit
f053e33486
4 changed files with 71 additions and 37 deletions
9
changelog/unreleased/issue-189
Normal file
9
changelog/unreleased/issue-189
Normal file
|
@ -0,0 +1,9 @@
|
|||
Enhancement: Support group accessible repositories
|
||||
|
||||
Rest-server now supports making repositories accessible to the filesystem group
|
||||
by setting the `--group-accessible-repos` option. Note that permissions of
|
||||
existing files are not modified. Use `chmod -R g+rwX /path/to/repo` to make
|
||||
the repository group-accessible.
|
||||
|
||||
https://github.com/restic/rest-server/issues/189
|
||||
https://github.com/restic/rest-server/pull/308
|
|
@ -69,6 +69,7 @@ func newRestServerApp() *restServerApp {
|
|||
flags.BoolVar(&rv.Server.PrivateRepos, "private-repos", rv.Server.PrivateRepos, "users can only access their private repo")
|
||||
flags.BoolVar(&rv.Server.Prometheus, "prometheus", rv.Server.Prometheus, "enable Prometheus metrics")
|
||||
flags.BoolVar(&rv.Server.PrometheusNoAuth, "prometheus-no-auth", rv.Server.PrometheusNoAuth, "disable auth for Prometheus /metrics endpoint")
|
||||
flags.BoolVar(&rv.Server.GroupAccessibleRepos, "group-accessible-repos", rv.Server.GroupAccessibleRepos, "let filesystem group be able to access repo files")
|
||||
|
||||
return rv
|
||||
}
|
||||
|
@ -149,6 +150,12 @@ func (app *restServerApp) runRoot(_ *cobra.Command, _ []string) error {
|
|||
log.Println("Private repositories disabled")
|
||||
}
|
||||
|
||||
if app.Server.GroupAccessibleRepos {
|
||||
log.Println("Group accessible repos enabled")
|
||||
} else {
|
||||
log.Println("Group accessible repos disabled")
|
||||
}
|
||||
|
||||
enabledTLS, privateKey, publicKey, err := app.tlsSettings()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -32,6 +32,7 @@ type Server struct {
|
|||
MaxRepoSize int64
|
||||
PanicOnError bool
|
||||
NoVerifyUpload bool
|
||||
GroupAccessibleRepos bool
|
||||
|
||||
htpasswdFile *HtpasswdFile
|
||||
quotaManager *quota.Manager
|
||||
|
@ -94,6 +95,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
PanicOnError: s.PanicOnError,
|
||||
NoVerifyUpload: s.NoVerifyUpload,
|
||||
FsyncWarning: &s.fsyncWarning,
|
||||
GroupAccessible: s.GroupAccessibleRepos,
|
||||
}
|
||||
if s.Prometheus {
|
||||
opt.BlobMetricFunc = makeBlobMetricFunc(username, folderPath)
|
||||
|
|
44
repo/repo.go
44
repo/repo.go
|
@ -28,8 +28,6 @@ import (
|
|||
type Options struct {
|
||||
AppendOnly bool // if set, delete actions are not allowed
|
||||
Debug bool
|
||||
DirMode os.FileMode
|
||||
FileMode os.FileMode
|
||||
NoVerifyUpload bool
|
||||
|
||||
// If set, we will panic when an internal server error happens. This
|
||||
|
@ -39,6 +37,13 @@ type Options struct {
|
|||
BlobMetricFunc BlobMetricFunc
|
||||
QuotaManager *quota.Manager
|
||||
FsyncWarning *sync.Once
|
||||
|
||||
// If set makes files group accessible
|
||||
GroupAccessible bool
|
||||
|
||||
// Defaults dir and file mode
|
||||
dirMode os.FileMode
|
||||
fileMode os.FileMode
|
||||
}
|
||||
|
||||
// DefaultDirMode is the file mode used for directory creation if not
|
||||
|
@ -49,6 +54,14 @@ const DefaultDirMode os.FileMode = 0700
|
|||
// overridden in the Options
|
||||
const DefaultFileMode os.FileMode = 0600
|
||||
|
||||
// GroupAccessibleDirMode is the file mode used for directory creation when
|
||||
// group access is enabled
|
||||
const GroupAccessibleDirMode os.FileMode = 0770
|
||||
|
||||
// GroupAccessibleFileMode is the file mode used for file creation when
|
||||
// group access is enabled
|
||||
const GroupAccessibleFileMode os.FileMode = 0660
|
||||
|
||||
// New creates a new Handler for a single Restic backup repo.
|
||||
// path is the full filesystem path to this repo directory.
|
||||
// opt is a set of options.
|
||||
|
@ -56,12 +69,15 @@ func New(path string, opt Options) (*Handler, error) {
|
|||
if path == "" {
|
||||
return nil, fmt.Errorf("path is required")
|
||||
}
|
||||
if opt.DirMode == 0 {
|
||||
opt.DirMode = DefaultDirMode
|
||||
}
|
||||
if opt.FileMode == 0 {
|
||||
opt.FileMode = DefaultFileMode
|
||||
|
||||
opt.dirMode = DefaultDirMode
|
||||
opt.fileMode = DefaultFileMode
|
||||
|
||||
if opt.GroupAccessible {
|
||||
opt.dirMode = GroupAccessibleDirMode
|
||||
opt.fileMode = GroupAccessibleFileMode
|
||||
}
|
||||
|
||||
h := Handler{
|
||||
path: path,
|
||||
opt: opt,
|
||||
|
@ -288,7 +304,7 @@ func (h *Handler) saveConfig(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
cfg := h.getSubPath("config")
|
||||
|
||||
f, err := os.OpenFile(cfg, os.O_CREATE|os.O_WRONLY|os.O_EXCL, h.opt.FileMode)
|
||||
f, err := os.OpenFile(cfg, os.O_CREATE|os.O_WRONLY|os.O_EXCL, h.opt.fileMode)
|
||||
if err != nil && os.IsExist(err) {
|
||||
if h.opt.Debug {
|
||||
log.Print(err)
|
||||
|
@ -554,15 +570,15 @@ func (h *Handler) saveBlob(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
tmpFn := filepath.Join(filepath.Dir(path), objectID+".rest-server-temp")
|
||||
tf, err := tempFile(tmpFn, h.opt.FileMode)
|
||||
tf, err := tempFile(tmpFn, h.opt.fileMode)
|
||||
if os.IsNotExist(err) {
|
||||
// the error is caused by a missing directory, create it and retry
|
||||
mkdirErr := os.MkdirAll(filepath.Dir(path), h.opt.DirMode)
|
||||
mkdirErr := os.MkdirAll(filepath.Dir(path), h.opt.dirMode)
|
||||
if mkdirErr != nil {
|
||||
log.Print(mkdirErr)
|
||||
} else {
|
||||
// try again
|
||||
tf, err = tempFile(tmpFn, h.opt.FileMode)
|
||||
tf, err = tempFile(tmpFn, h.opt.fileMode)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -759,13 +775,13 @@ func (h *Handler) createRepo(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
log.Printf("Creating repository directories in %s\n", h.path)
|
||||
|
||||
if err := os.MkdirAll(h.path, h.opt.DirMode); err != nil {
|
||||
if err := os.MkdirAll(h.path, h.opt.dirMode); err != nil {
|
||||
h.internalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, d := range ObjectTypes {
|
||||
if err := os.Mkdir(filepath.Join(h.path, d), h.opt.DirMode); err != nil && !os.IsExist(err) {
|
||||
if err := os.Mkdir(filepath.Join(h.path, d), h.opt.dirMode); err != nil && !os.IsExist(err) {
|
||||
h.internalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
@ -773,7 +789,7 @@ func (h *Handler) createRepo(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
for i := 0; i < 256; i++ {
|
||||
dirPath := filepath.Join(h.path, "data", fmt.Sprintf("%02x", i))
|
||||
if err := os.Mkdir(dirPath, h.opt.DirMode); err != nil && !os.IsExist(err) {
|
||||
if err := os.Mkdir(dirPath, h.opt.dirMode); err != nil && !os.IsExist(err) {
|
||||
h.internalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue