mirror of
https://github.com/project-zot/zot.git
synced 2024-12-30 22:34:13 -05:00
Merge pull request #18 from rchincha/tls
auth: allow for world-readable deployment mode
This commit is contained in:
commit
672c0886aa
9 changed files with 340 additions and 36 deletions
33
WORKSPACE
33
WORKSPACE
|
@ -1,29 +1,39 @@
|
||||||
workspace(name = "com_github_anuvu_zot")
|
workspace(name = "com_github_anuvu_zot")
|
||||||
|
|
||||||
|
go_version = "1.12.9"
|
||||||
|
|
||||||
|
go_os = "linux"
|
||||||
|
|
||||||
|
go_arch = "amd64"
|
||||||
|
|
||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
|
|
||||||
go_rules_version = "0.18.6"
|
go_rules_version = "0.19.3"
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "io_bazel_rules_go",
|
name = "io_bazel_rules_go",
|
||||||
sha256 = "f04d2373bcaf8aa09bccb08a98a57e721306c8f6043a2a0ee610fd6853dcde3d",
|
urls = [
|
||||||
urls = ["https://github.com/bazelbuild/rules_go/releases/download/{}/rules_go-{}.tar.gz".format(go_rules_version, go_rules_version)],
|
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/{}/rules_go-{}.tar.gz".format(go_rules_version, go_rules_version),
|
||||||
|
"https://github.com/bazelbuild/rules_go/releases/download/{}/rules_go-{}.tar.gz".format(go_rules_version, go_rules_version),
|
||||||
|
],
|
||||||
|
sha256 = "313f2c7a23fecc33023563f082f381a32b9b7254f727a7dd2d6380ccc6dfe09b",
|
||||||
)
|
)
|
||||||
|
|
||||||
gazelle_version = "0.17.0"
|
gazelle_version = "0.18.1"
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "bazel_gazelle",
|
name = "bazel_gazelle",
|
||||||
sha256 = "3c681998538231a2d24d0c07ed5a7658cb72bfb5fd4bf9911157c0e9ac6a2687",
|
sha256 = "be9296bfd64882e3c08e3283c58fcb461fa6dd3c171764fcc4cf322f60615a9b",
|
||||||
urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/{}/bazel-gazelle-{}.tar.gz".format(gazelle_version, gazelle_version)],
|
urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/{}/bazel-gazelle-{}.tar.gz".format(gazelle_version, gazelle_version)],
|
||||||
)
|
)
|
||||||
|
|
||||||
buildtools_version = "0.26.0"
|
buildtools_version = "0.25.1"
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_github_bazelbuild_buildtools",
|
name = "com_github_bazelbuild_buildtools",
|
||||||
sha256 = "86592d703ecbe0c5cbb5139333a63268cf58d7efd2c459c8be8e69e77d135e29",
|
sha256 = "0a0920151acf18c51866331944d12db9023707a6861e78225366f5711efc845b",
|
||||||
strip_prefix = "buildtools-{}".format(buildtools_version),
|
strip_prefix = "buildtools-{}".format(buildtools_version),
|
||||||
urls = ["https://github.com/bazelbuild/buildtools/archive/{}.tar.gz".format(buildtools_version)],
|
urls = ["https://github.com/bazelbuild/buildtools/archive/{}.tar.gz".format(buildtools_version)],
|
||||||
)
|
)
|
||||||
|
@ -47,7 +57,14 @@ load("@bazel_skylib//lib:versions.bzl", "versions")
|
||||||
|
|
||||||
versions.check(minimum_bazel_version = "0.26.1")
|
versions.check(minimum_bazel_version = "0.26.1")
|
||||||
|
|
||||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_register_toolchains", "go_rules_dependencies")
|
||||||
|
|
||||||
|
go_download_sdk(
|
||||||
|
name = "go_sdk",
|
||||||
|
goos = go_os,
|
||||||
|
goarch = go_arch,
|
||||||
|
version = go_version,
|
||||||
|
)
|
||||||
|
|
||||||
go_rules_dependencies()
|
go_rules_dependencies()
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
"path": "test/data/htpasswd"
|
"path": "test/data/htpasswd"
|
||||||
},
|
},
|
||||||
"failDelay": 5
|
"failDelay": 5
|
||||||
}
|
},
|
||||||
|
"allowReadAccess": false
|
||||||
},
|
},
|
||||||
"log":{
|
"log":{
|
||||||
"level":"debug",
|
"level":"debug",
|
||||||
|
|
|
@ -14,6 +14,7 @@ http:
|
||||||
htpasswd:
|
htpasswd:
|
||||||
path: test/data/htpasswd
|
path: test/data/htpasswd
|
||||||
failDelay: 5
|
failDelay: 5
|
||||||
|
allowReadAccess: false
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
output: /tmp/zot.log
|
output: /tmp/zot.log
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -20,6 +20,10 @@ require (
|
||||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 // indirect
|
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 // indirect
|
||||||
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e
|
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e
|
||||||
github.com/swaggo/swag v1.6.2
|
github.com/swaggo/swag v1.6.2
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 // indirect
|
||||||
|
golang.org/x/text v0.3.2 // indirect
|
||||||
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a // indirect
|
||||||
gopkg.in/resty.v1 v1.12.0
|
gopkg.in/resty.v1 v1.12.0
|
||||||
)
|
)
|
||||||
|
|
13
go.sum
13
go.sum
|
@ -162,6 +162,8 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -172,6 +174,9 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -185,16 +190,24 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 h1:fTfk6GjmihJbK0mSUFgPPgYpsdmApQ86Mcd4GuKax9U=
|
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 h1:fTfk6GjmihJbK0mSUFgPPgYpsdmApQ86Mcd4GuKax9U=
|
||||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a h1:0JEq5ZQ3TgsRlFmz4BcD+E6U6cOk4pOImCQSyIG59ZM=
|
||||||
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
|
@ -21,22 +21,30 @@ func authFail(w http.ResponseWriter, realm string, delay int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BasicAuthHandler(c *Controller) mux.MiddlewareFunc {
|
func BasicAuthHandler(c *Controller) mux.MiddlewareFunc {
|
||||||
if c.Config.HTTP.Auth.HTPasswd.Path == "" {
|
|
||||||
// no authentication
|
|
||||||
return func(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// Process request
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
realm := c.Config.HTTP.Realm
|
realm := c.Config.HTTP.Realm
|
||||||
if realm == "" {
|
if realm == "" {
|
||||||
realm = "Authorization Required"
|
realm = "Authorization Required"
|
||||||
}
|
}
|
||||||
realm = "Basic realm=" + strconv.Quote(realm)
|
realm = "Basic realm=" + strconv.Quote(realm)
|
||||||
delay := c.Config.HTTP.Auth.FailDelay
|
delay := c.Config.HTTP.Auth.FailDelay
|
||||||
|
|
||||||
|
if c.Config.HTTP.Auth.HTPasswd.Path == "" {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if c.Config.HTTP.AllowReadAccess &&
|
||||||
|
c.Config.HTTP.TLS.CACert != "" &&
|
||||||
|
r.TLS.VerifiedChains == nil &&
|
||||||
|
r.Method != "GET" && r.Method != "HEAD" {
|
||||||
|
authFail(w, realm, delay)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process request
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
credMap := make(map[string]string)
|
credMap := make(map[string]string)
|
||||||
|
|
||||||
f, err := os.Open(c.Config.HTTP.Auth.HTPasswd.Path)
|
f, err := os.Open(c.Config.HTTP.Auth.HTPasswd.Path)
|
||||||
|
@ -56,6 +64,12 @@ func BasicAuthHandler(c *Controller) mux.MiddlewareFunc {
|
||||||
|
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if (r.Method == "GET" || r.Method == "HEAD") && c.Config.HTTP.AllowReadAccess {
|
||||||
|
// Process request
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
basicAuth := r.Header.Get("Authorization")
|
basicAuth := r.Header.Get("Authorization")
|
||||||
if basicAuth == "" {
|
if basicAuth == "" {
|
||||||
authFail(w, realm, delay)
|
authFail(w, realm, delay)
|
||||||
|
|
|
@ -24,11 +24,12 @@ type AuthConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPConfig struct {
|
type HTTPConfig struct {
|
||||||
Address string
|
Address string
|
||||||
Port string
|
Port string
|
||||||
TLS TLSConfig `mapstructure:",omitempty"`
|
TLS TLSConfig `mapstructure:",omitempty"`
|
||||||
Auth AuthConfig `mapstructure:",omitempty"`
|
Auth AuthConfig `mapstructure:",omitempty"`
|
||||||
Realm string
|
Realm string
|
||||||
|
AllowReadAccess bool `mapstructure:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
|
|
|
@ -45,13 +45,13 @@ func (c *Controller) Run() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientAuth := tls.VerifyClientCertIfGiven
|
|
||||||
if c.Config.HTTP.Auth.HTPasswd.Path == "" {
|
|
||||||
clientAuth = tls.RequireAndVerifyClientCert
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Config.HTTP.TLS.Key != "" && c.Config.HTTP.TLS.Cert != "" {
|
if c.Config.HTTP.TLS.Key != "" && c.Config.HTTP.TLS.Cert != "" {
|
||||||
if c.Config.HTTP.TLS.CACert != "" {
|
if c.Config.HTTP.TLS.CACert != "" {
|
||||||
|
clientAuth := tls.VerifyClientCertIfGiven
|
||||||
|
if c.Config.HTTP.Auth.HTPasswd.Path == "" && !c.Config.HTTP.AllowReadAccess {
|
||||||
|
clientAuth = tls.RequireAndVerifyClientCert
|
||||||
|
}
|
||||||
|
|
||||||
caCert, err := ioutil.ReadFile(c.Config.HTTP.TLS.CACert)
|
caCert, err := ioutil.ReadFile(c.Config.HTTP.TLS.CACert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -26,6 +26,7 @@ const (
|
||||||
htpasswdPath = "../../test/data/htpasswd" // nolint (gosec) - this is just test data
|
htpasswdPath = "../../test/data/htpasswd" // nolint (gosec) - this is just test data
|
||||||
ServerCert = "../../test/data/server.cert"
|
ServerCert = "../../test/data/server.cert"
|
||||||
ServerKey = "../../test/data/server.key"
|
ServerKey = "../../test/data/server.key"
|
||||||
|
CACert = "../../test/data/ca.crt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
|
@ -91,7 +92,7 @@ func TestBasicAuth(t *testing.T) {
|
||||||
|
|
||||||
func TestTLSWithBasicAuth(t *testing.T) {
|
func TestTLSWithBasicAuth(t *testing.T) {
|
||||||
Convey("Make a new controller", t, func() {
|
Convey("Make a new controller", t, func() {
|
||||||
caCert, err := ioutil.ReadFile("../../test/data/ca.crt")
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
caCertPool := x509.NewCertPool()
|
caCertPool := x509.NewCertPool()
|
||||||
caCertPool.AppendCertsFromPEM(caCert)
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
@ -158,9 +159,80 @@ func TestTLSWithBasicAuth(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) {
|
||||||
|
Convey("Make a new controller", t, func() {
|
||||||
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
|
||||||
|
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
|
||||||
|
defer func() { resty.SetTLSClientConfig(nil) }()
|
||||||
|
config := api.NewConfig()
|
||||||
|
config.HTTP.Port = SecurePort2
|
||||||
|
config.HTTP.Auth.HTPasswd.Path = htpasswdPath
|
||||||
|
config.HTTP.TLS.Cert = ServerCert
|
||||||
|
config.HTTP.TLS.Key = ServerKey
|
||||||
|
config.HTTP.AllowReadAccess = true
|
||||||
|
|
||||||
|
c := api.NewController(config)
|
||||||
|
dir, err := ioutil.TempDir("", "oci-repo-test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
c.Config.Storage.RootDirectory = dir
|
||||||
|
go func() {
|
||||||
|
// this blocks
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait till ready
|
||||||
|
for {
|
||||||
|
_, err := resty.R().Get(BaseURL2)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
ctx := context.Background()
|
||||||
|
_ = c.Server.Shutdown(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// accessing insecure HTTP site should fail
|
||||||
|
resp, err := resty.R().Get(BaseURL2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 400)
|
||||||
|
|
||||||
|
// without creds, should still be allowed to access
|
||||||
|
resp, err = resty.R().Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// with creds, should get expected status code
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 404)
|
||||||
|
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// without creds, writes should fail
|
||||||
|
resp, err = resty.R().Post(BaseSecureURL2 + "/v2/repo/blobs/uploads/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 401)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestTLSMutualAuth(t *testing.T) {
|
func TestTLSMutualAuth(t *testing.T) {
|
||||||
Convey("Make a new controller", t, func() {
|
Convey("Make a new controller", t, func() {
|
||||||
caCert, err := ioutil.ReadFile("../../test/data/ca.crt")
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
caCertPool := x509.NewCertPool()
|
caCertPool := x509.NewCertPool()
|
||||||
caCertPool.AppendCertsFromPEM(caCert)
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
@ -171,7 +243,7 @@ func TestTLSMutualAuth(t *testing.T) {
|
||||||
config.HTTP.Port = SecurePort2
|
config.HTTP.Port = SecurePort2
|
||||||
config.HTTP.TLS.Cert = ServerCert
|
config.HTTP.TLS.Cert = ServerCert
|
||||||
config.HTTP.TLS.Key = ServerKey
|
config.HTTP.TLS.Key = ServerKey
|
||||||
config.HTTP.TLS.CACert = "../../test/data/ca.crt"
|
config.HTTP.TLS.CACert = CACert
|
||||||
|
|
||||||
c := api.NewController(config)
|
c := api.NewController(config)
|
||||||
dir, err := ioutil.TempDir("", "oci-repo-test")
|
dir, err := ioutil.TempDir("", "oci-repo-test")
|
||||||
|
@ -240,9 +312,9 @@ func TestTLSMutualAuth(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTLSMutualAndBasicAuth(t *testing.T) {
|
func TestTLSMutualAuthAllowReadAccess(t *testing.T) {
|
||||||
Convey("Make a new controller", t, func() {
|
Convey("Make a new controller", t, func() {
|
||||||
caCert, err := ioutil.ReadFile("../../test/data/ca.crt")
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
caCertPool := x509.NewCertPool()
|
caCertPool := x509.NewCertPool()
|
||||||
caCertPool.AppendCertsFromPEM(caCert)
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
@ -253,7 +325,97 @@ func TestTLSMutualAndBasicAuth(t *testing.T) {
|
||||||
config.HTTP.Port = SecurePort2
|
config.HTTP.Port = SecurePort2
|
||||||
config.HTTP.TLS.Cert = ServerCert
|
config.HTTP.TLS.Cert = ServerCert
|
||||||
config.HTTP.TLS.Key = ServerKey
|
config.HTTP.TLS.Key = ServerKey
|
||||||
config.HTTP.TLS.CACert = "../../test/data/ca.crt"
|
config.HTTP.TLS.CACert = CACert
|
||||||
|
config.HTTP.AllowReadAccess = true
|
||||||
|
|
||||||
|
c := api.NewController(config)
|
||||||
|
dir, err := ioutil.TempDir("", "oci-repo-test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
c.Config.Storage.RootDirectory = dir
|
||||||
|
go func() {
|
||||||
|
// this blocks
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait till ready
|
||||||
|
for {
|
||||||
|
_, err := resty.R().Get(BaseURL2)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
ctx := context.Background()
|
||||||
|
_ = c.Server.Shutdown(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// accessing insecure HTTP site should fail
|
||||||
|
resp, err := resty.R().Get(BaseURL2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 400)
|
||||||
|
|
||||||
|
// without client certs and creds, reads are allowed
|
||||||
|
resp, err = resty.R().Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// with creds but without certs, reads are allowed
|
||||||
|
resp, err = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// without creds, writes should fail
|
||||||
|
resp, err = resty.R().Post(BaseSecureURL2 + "/v2/repo/blobs/uploads/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 401)
|
||||||
|
|
||||||
|
// setup TLS mutual auth
|
||||||
|
cert, err := tls.LoadX509KeyPair("../../test/data/client.cert", "../../test/data/client.key")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
resty.SetCertificates(cert)
|
||||||
|
defer func() { resty.SetCertificates(tls.Certificate{}) }()
|
||||||
|
|
||||||
|
// with client certs but without creds, should succeed
|
||||||
|
resp, err = resty.R().Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// with client certs and creds, should get expected status code
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 404)
|
||||||
|
|
||||||
|
// with client certs, creds shouldn't matter
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTLSMutualAndBasicAuth(t *testing.T) {
|
||||||
|
Convey("Make a new controller", t, func() {
|
||||||
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
|
||||||
|
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
|
||||||
|
defer func() { resty.SetTLSClientConfig(nil) }()
|
||||||
|
config := api.NewConfig()
|
||||||
|
config.HTTP.Port = SecurePort2
|
||||||
|
config.HTTP.TLS.Cert = ServerCert
|
||||||
|
config.HTTP.TLS.Key = ServerKey
|
||||||
|
config.HTTP.TLS.CACert = CACert
|
||||||
config.HTTP.Auth.HTPasswd.Path = htpasswdPath
|
config.HTTP.Auth.HTPasswd.Path = htpasswdPath
|
||||||
|
|
||||||
c := api.NewController(config)
|
c := api.NewController(config)
|
||||||
|
@ -325,3 +487,94 @@ func TestTLSMutualAndBasicAuth(t *testing.T) {
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) {
|
||||||
|
Convey("Make a new controller", t, func() {
|
||||||
|
caCert, err := ioutil.ReadFile(CACert)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
|
||||||
|
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
|
||||||
|
defer func() { resty.SetTLSClientConfig(nil) }()
|
||||||
|
config := api.NewConfig()
|
||||||
|
config.HTTP.Port = SecurePort2
|
||||||
|
config.HTTP.TLS.Cert = ServerCert
|
||||||
|
config.HTTP.TLS.Key = ServerKey
|
||||||
|
config.HTTP.TLS.CACert = CACert
|
||||||
|
config.HTTP.Auth.HTPasswd.Path = htpasswdPath
|
||||||
|
config.HTTP.AllowReadAccess = true
|
||||||
|
|
||||||
|
c := api.NewController(config)
|
||||||
|
dir, err := ioutil.TempDir("", "oci-repo-test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
c.Config.Storage.RootDirectory = dir
|
||||||
|
go func() {
|
||||||
|
// this blocks
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait till ready
|
||||||
|
for {
|
||||||
|
_, err := resty.R().Get(BaseURL2)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
ctx := context.Background()
|
||||||
|
_ = c.Server.Shutdown(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// accessing insecure HTTP site should fail
|
||||||
|
resp, err := resty.R().Get(BaseURL2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 400)
|
||||||
|
|
||||||
|
// without client certs and creds, should fail
|
||||||
|
_, err = resty.R().Get(BaseSecureURL2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 400)
|
||||||
|
|
||||||
|
// with creds but without certs, should succeed
|
||||||
|
_, err = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 400)
|
||||||
|
|
||||||
|
// setup TLS mutual auth
|
||||||
|
cert, err := tls.LoadX509KeyPair("../../test/data/client.cert", "../../test/data/client.key")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
resty.SetCertificates(cert)
|
||||||
|
defer func() { resty.SetCertificates(tls.Certificate{}) }()
|
||||||
|
|
||||||
|
// with client certs but without creds, reads should succeed
|
||||||
|
resp, err = resty.R().Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
// with only client certs, writes should fail
|
||||||
|
resp, err = resty.R().Post(BaseSecureURL2 + "/v2/repo/blobs/uploads/")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 401)
|
||||||
|
|
||||||
|
// with client certs and creds, should get expected status code
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 404)
|
||||||
|
|
||||||
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseSecureURL2 + "/v2/")
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue