25 Commits
Author SHA1 Message Date
Henrique Dias a037fe877c docs: update license file
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
2019-05-12 13:48:03 +01:00
Henrique Dias 81f873d2de feat: docker images
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
2019-05-12 13:46:39 +01:00
Henrique DiasandGitHub 505a10a63d chore: circle CI (#14)
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
2019-05-12 12:59:33 +01:00
Henrique DiasandGitHub 61462c1da7 Merge pull request #13 from hacdias/fix/set-depth-header
fix: set depth header
2019-05-12 12:52:56 +01:00
Henrique Dias 21ec95a8db fix: set depth header
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
2019-05-12 12:49:55 +01:00
Henrique Dias 8bf2c4eea3 feat: update modules
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
2019-05-12 12:39:57 +01:00
Henrique DiasandGitHub 4199ffc190 Merge pull request #11 from acez/userdata-from-environment
Add support for loading username and password from environment
2019-05-12 12:34:14 +01:00
Henrique DiasandGitHub 7a67f76947 Merge pull request #12 from meeee/go-module
Make webdav a Go module
2019-03-31 12:14:08 +01:00
Michael Frister 088958913c Travis: Use Go 1.12 for Go module support
gometalinter breaks with Go modules, so disable them.
2019-03-31 12:55:24 +02:00
Michael Frister 3e7b39679b Add Go module files 2019-03-31 12:42:49 +02:00
Christian Wilhelm d95c1ec13b Add support for loading username and password from environment 2018-12-30 13:26:12 +01:00
Henrique Dias 3d06904d1f style: replace Tls by TLS 2018-04-21 08:42:23 +01:00
Henrique DiasandGitHub 4dc7bae6ea Update .travis.yml 2018-04-21 08:39:55 +01:00
Henrique DiasandGitHub 6b139d375c feat: TLS support 2018-04-21 08:39:32 +01:00
Florian Walther 80e3ffd57b added tls options to readme example config 2018-04-20 17:07:52 +02:00
Florian Walther 893d3b429a added TLS support 2018-04-20 17:05:21 +02:00
Henrique DiasandGitHub cdaf929a4b Update readme.md 2018-04-08 19:04:07 +01:00
Henrique DiasandGitHub d216a2edef Merge pull request #4 from alex3305/master
Adds a Systemd service unit
2018-04-08 19:03:19 +01:00
Alex van den Hoogen eeae21cd29 Adds a Systemd service unit
I wanted to run this application as a service on my Debian based machine,
which uses systemd as a service manager. Since there was no default or
example service available in this repository, I've added a very simple
service unit.
2018-04-08 12:48:53 +02:00
Henrique DiasandGitHub b645ac51eb Merge pull request #3 from fzoske/master
Add Support For BCrypt Storage of Passwords
2018-03-31 15:32:19 +01:00
Fabian Zoske 62aea27486 Add Support For BCrypt Storage of Passwords 2018-03-31 12:01:00 +02:00
Henrique DiasandGitHub 541defc796 Update .travis.yml 2017-12-21 17:07:12 +00:00
Henrique DiasandGitHub d2f2b1ccde Update Travis 2017-12-21 17:02:37 +00:00
Henrique DiasandGitHub 6c10c35efe Merge pull request #2 from c35sys/master
Add *address* config option
2017-12-21 17:01:18 +00:00
Christophe Le Guern 8271975046 Add *address* config option 2017-12-21 17:50:03 +01:00
12 changed files with 209 additions and 50 deletions
+45
View File
@@ -0,0 +1,45 @@
version: 2
jobs:
lint:
docker:
- image: golangci/golangci-lint:v1.16
steps:
- checkout
- run: golangci-lint run -v
build:
docker:
- image: circleci/golang:1.12
steps:
- checkout
- run: cd cmd/webdav && go build main.go
release:
docker:
- image: circleci/golang:1.12
steps:
- checkout
- setup_remote_docker
- run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
- run: curl -sL https://git.io/goreleaser | bash
- run: docker logout
workflows:
version: 2
build-workflow:
jobs:
- lint:
filters:
tags:
only: /.*/
- build:
filters:
tags:
only: /.*/
- release:
context: deploy
requires:
- build
- lint
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
-3
View File
@@ -1,3 +0,0 @@
config.yaml
config.yml
config.json
+18 -6
View File
@@ -21,9 +21,21 @@ build:
goarch: arm
goarm: 6
archive:
name_template: "{{.Os}}-{{.Arch}}-{{ .ProjectName }}"
format: tar.gz
format_overrides:
- goos: windows
format: zip
archives:
-
name_template: "{{.Os}}-{{.Arch}}-{{ .ProjectName }}"
format: tar.gz
format_overrides:
- goos: windows
format: zip
dockers:
-
goos: linux
goarch: amd64
goarm: ''
image_templates:
- "hacdias/webdav:latest"
- "hacdias/webdav:{{ .Tag }}"
- "hacdias/webdav:v{{ .Major }}.{{ .Minor }}"
- "hacdias/webdav:v{{ .Major }}"
-22
View File
@@ -1,22 +0,0 @@
language: go
go: 1.8.3
env:
- "PATH=/home/travis/gopath/bin:$PATH"
install:
- go get ./...
# Install gometalinter and certain linters
- go get github.com/alecthomas/gometalinter
- go get github.com/client9/misspell/cmd/misspell
- go get github.com/gordonklaus/ineffassign
- go get golang.org/x/tools/cmd/goimports
- go get github.com/tsenart/deadcode
script:
- gometalinter --disable-all -E vet -E gofmt -E misspell -E ineffassign -E goimports -E deadcode --tests ./...
- go test ./... -timeout 30s
after_success:
- test -n "$TRAVIS_TAG" && curl -sL https://git.io/goreleaser | bash
+11
View File
@@ -0,0 +1,11 @@
FROM alpine:latest as certs
RUN apk --update add ca-certificates
FROM scratch
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
EXPOSE 80
COPY webdav /webdav
ENTRYPOINT [ "/webdav" ]
View File
+77 -18
View File
@@ -11,8 +11,10 @@ import (
"os"
"path/filepath"
"regexp"
"strings"
"github.com/hacdias/webdav"
"golang.org/x/crypto/bcrypt"
wd "golang.org/x/net/webdav"
yaml "gopkg.in/yaml.v2"
)
@@ -75,11 +77,35 @@ func parseUsers(raw []map[string]interface{}, c *cfg) {
log.Fatal("user needs an username")
}
// load username from environment when prefix {env} is added
if strings.HasPrefix(username, "{env}") {
var envUsername = strings.TrimPrefix(username, "{env}")
if envUsername == "" {
log.Fatal("no environment variable specified for username")
}
username = os.Getenv(envUsername)
if username == "" {
log.Fatal("username must be set in environment")
}
}
password, ok := r["password"].(string)
if !ok {
log.Fatal("user needs a password")
}
// load password from environment when prefix {env} is added
if strings.HasPrefix(password, "{env}") {
var envPassword = strings.TrimPrefix(password, "{env}")
if envPassword == "" {
log.Fatal("no environment variable specified for password")
}
password = os.Getenv(envPassword)
if password == "" {
log.Fatal("password must be set in environment")
}
}
c.auth[username] = password
user := &webdav.User{
@@ -133,24 +159,36 @@ func getConfig() []byte {
}
type cfg struct {
webdav *webdav.Config
port string
auth map[string]string
webdav *webdav.Config
address string
port string
tls bool
cert string
key string
auth map[string]string
}
func parseConfig() *cfg {
file := getConfig()
data := struct {
Port string `json:"port" yaml:"port"`
Scope string `json:"scope" yaml:"scope"`
Modify bool `json:"modify" yaml:"modify"`
Rules []map[string]interface{} `json:"rules" yaml:"rules"`
Users []map[string]interface{} `json:"users" yaml:"users"`
Address string `json:"address" yaml:"address"`
Port string `json:"port" yaml:"port"`
TLS bool `json:"tls" yaml:"tls"`
Cert string `json:"cert" yaml:"cert"`
Key string `json:"key" yaml:"key"`
Scope string `json:"scope" yaml:"scope"`
Modify bool `json:"modify" yaml:"modify"`
Rules []map[string]interface{} `json:"rules" yaml:"rules"`
Users []map[string]interface{} `json:"users" yaml:"users"`
}{
Port: "0",
Scope: "./",
Modify: true,
Address: "0.0.0.0",
Port: "0",
TLS: false,
Cert: "cert.pem",
Key: "key.pem",
Scope: "./",
Modify: true,
}
var err error
@@ -165,8 +203,12 @@ func parseConfig() *cfg {
}
config := &cfg{
port: data.Port,
auth: map[string]string{},
address: data.Address,
port: data.Port,
tls: data.TLS,
cert: data.Cert,
key: data.Key,
auth: map[string]string{},
webdav: &webdav.Config{
User: &webdav.User{
Scope: data.Scope,
@@ -198,7 +240,7 @@ func basicAuth(c *cfg) http.Handler {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
username, password, authOK := r.BasicAuth()
if authOK == false {
if !authOK {
http.Error(w, "Not authorized", 401)
return
}
@@ -209,7 +251,8 @@ func basicAuth(c *cfg) http.Handler {
return
}
if password != p {
if !checkPassword(p, password) {
log.Println("Wrong Password for user", username)
http.Error(w, "Not authorized", 401)
return
}
@@ -218,13 +261,22 @@ func basicAuth(c *cfg) http.Handler {
})
}
func checkPassword(saved, input string) bool {
if strings.HasPrefix(saved, "{bcrypt}") {
savedPassword := strings.TrimPrefix(saved, "{bcrypt}")
return bcrypt.CompareHashAndPassword([]byte(savedPassword), []byte(input)) == nil
}
return saved == input
}
func main() {
flag.Parse()
cfg := parseConfig()
handler := basicAuth(cfg)
// Builds the address and a listener.
laddr := ":" + cfg.port
laddr := cfg.address + ":" + cfg.port
listener, err := net.Listen("tcp", laddr)
if err != nil {
log.Fatal(err)
@@ -234,7 +286,14 @@ func main() {
fmt.Println("Listening on", listener.Addr().String())
// Starts the server.
if err := http.Serve(listener, handler); err != nil {
log.Fatal(err)
if cfg.tls {
if err := http.ServeTLS(listener, handler, cfg.cert, cfg.key); err != nil {
log.Fatal(err)
}
} else {
if err := http.Serve(listener, handler); err != nil {
log.Fatal(err)
}
}
}
+11
View File
@@ -0,0 +1,11 @@
module github.com/hacdias/webdav
go 1.12
require (
github.com/kr/pretty v0.1.0 // indirect
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.2
)
+20
View File
@@ -0,0 +1,20 @@
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+11 -1
View File
@@ -7,10 +7,18 @@
```yaml
scope: /path/to/files
address: 0.0.0.0
port: 8080
tls: false
cert: cert.pem
key: key.pem
users:
- username: admin
password: admin
- username: encrypted
password: "{bcrypt}$2y$10$zEP6oofmXFeHaeMfBNLnP.DO8m.H.Mwhd24/TOX2MWLxAExXi4qgi"
- username: "{env}ENV_USERNAME"
password: "{env}ENV_PASSWORD"
- username: basic
password: basic
modify: false
@@ -22,4 +30,6 @@ users:
You can specify the path to the configuration file using the `--config` flag. By default, it will search for a `config.{yaml,json}` file on your current working directory.
Download it [here](https://github.com/hacdias/webdav/releases).
An example of how to use this with `systemd` is on [webdav.service.example](/webdav.service.example).
Download it [here](https://github.com/hacdias/webdav/releases).
+4
View File
@@ -57,6 +57,10 @@ func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
info, err := u.Handler.FileSystem.Stat(context.TODO(), r.URL.Path)
if err == nil && info.IsDir() {
r.Method = "PROPFIND"
if r.Header.Get("Depth") == "" {
r.Header.Add("Depth", "1")
}
}
}
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=WebDAV server
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/webdav --config /opt/webdav.config
Restart=on-failure
[Install]
WantedBy=multi-user.target