With --auth-proxy set and --auth-key unset, serve s3 registered every client supplied access key ID with an empty secret and verified the SigV4 signature against that, so anyone could sign a request for an arbitrary access key ID with an empty secret and be let in. The proxy program was only ever given the access key ID (as both user and pass) so it had nothing with which to authenticate the client either. An S3 client never sends its secret, only a signature made with it, so the server has to know the secret to check the request. The auth proxy protocol as been changed to handle this. For serve s3 the proxy program is given just the access key ID as the user (no pass or public_key) and must return the matching secret as _secret_access_key in its output. rclone verifies the request's signature against that secret, refusing the request if the proxy rejects the access key ID, doesn't return a secret or returns an empty one, or the signature doesn't match. The secret is only used for this server's own verification and is never registered with gofakes3, so other serve s3 instances in the same process don't honour it. The proxy's answers are cached. If a signature fails against a cached secret the proxy is consulted again so a rotated secret takes effect immediately - but only for a signature mismatch, and at most once every 10 seconds per access key ID and client IP, so a stream of bad signatures can't make the proxy program run for every request. A rotation never shuts down the cached backend under requests still using it. A cached answer is checked with the proxy again once it is 5 minutes old even if in constant use, so revoking an access key ID takes effect within 5 minutes. This means --auth-key is no longer needed with --auth-proxy: it is ignored and a warning is given at startup if both are set. The proxy is the source of truth for both the credentials and the backend they map to. Presigned URLs (credential in the query string) are now recognised by the proxy middleware too. The auth proxy docs are added to serve s3. Note that the serve s3 auth proxy protocol has changed. The proxy program is now given the access key ID as "user" (it was previously given an MD5 hash of it, with the access key ID as "pass") and must return the matching secret as "_secret_access_key". This needs gofakes3 v0.0.9 for signature.V4SignVerifyWithSecret.
61 lines
1.3 KiB
Go
61 lines
1.3 KiB
Go
//go:build ignore
|
|
|
|
// A simple auth proxy for testing purposes
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
// Read the input
|
|
var in map[string]string
|
|
err := json.NewDecoder(os.Stdin).Decode(&in)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Write the output
|
|
var out = map[string]string{}
|
|
for k, v := range in {
|
|
switch k {
|
|
case "user":
|
|
v += "-test"
|
|
case "error":
|
|
log.Fatal(v)
|
|
}
|
|
out[k] = v
|
|
}
|
|
if out["type"] == "" {
|
|
out["type"] = "local"
|
|
}
|
|
if out["_root"] == "" {
|
|
out["_root"] = ""
|
|
}
|
|
// S3 access key auth has neither pass nor public_key and needs
|
|
// the secret returned, unless the user asks for it to be omitted
|
|
// or empty. The secret's suffix can be changed to simulate a
|
|
// rotation and an access key ID can be revoked.
|
|
_, havePass := in["pass"]
|
|
_, havePublicKey := in["public_key"]
|
|
switch {
|
|
case havePass || havePublicKey || in["user"] == "nosecret":
|
|
case in["user"] == os.Getenv("RCLONE_TEST_PROXY_REVOKED"):
|
|
log.Fatalf("access key ID %q revoked", in["user"])
|
|
case in["user"] == "emptysecret":
|
|
out["_secret_access_key"] = ""
|
|
default:
|
|
suffix := os.Getenv("RCLONE_TEST_PROXY_SECRET_SUFFIX")
|
|
if suffix == "" {
|
|
suffix = "-secret"
|
|
}
|
|
out["_secret_access_key"] = in["user"] + suffix
|
|
}
|
|
json.NewEncoder(os.Stdout).Encode(&out)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|