aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2022-01-01 22:34:13 -0800
committerGitHub <noreply@github.com>2022-01-01 22:34:13 -0800
commit9b941773805400c520558d83aed633adc821988c (patch)
tree55cac459c1219bf7b8a50049572260917634ccfc /weed/s3api
parent34742be0295998c2105a5ee50e3e77ef2397c403 (diff)
parent99abddf3769a5e4a25c72e67df9106e41b7aa8f3 (diff)
downloadseaweedfs-9b941773805400c520558d83aed633adc821988c.tar.xz
seaweedfs-9b941773805400c520558d83aed633adc821988c.zip
Merge pull request #2543 from skurfuerst/seaweedfs-158
FEATURE: add JWT to HTTP endpoints of Filer and use them in S3 Client
Diffstat (limited to 'weed/s3api')
-rw-r--r--weed/s3api/s3api_object_copy_handlers.go4
-rw-r--r--weed/s3api/s3api_object_handlers.go36
-rw-r--r--weed/s3api/s3api_server.go21
3 files changed, 50 insertions, 11 deletions
diff --git a/weed/s3api/s3api_object_copy_handlers.go b/weed/s3api/s3api_object_copy_handlers.go
index 7756e1348..8af0cacf1 100644
--- a/weed/s3api/s3api_object_copy_handlers.go
+++ b/weed/s3api/s3api_object_copy_handlers.go
@@ -74,7 +74,7 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request
srcUrl := fmt.Sprintf("http://%s%s/%s%s",
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, srcBucket, urlPathEscape(srcObject))
- _, _, resp, err := util.DownloadFile(srcUrl, "")
+ _, _, resp, err := util.DownloadFile(srcUrl, s3a.maybeGetFilerJwtAuthorizationToken(false))
if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
return
@@ -157,7 +157,7 @@ func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Req
srcUrl := fmt.Sprintf("http://%s%s/%s%s",
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, srcBucket, urlPathEscape(srcObject))
- dataReader, err := util.ReadUrlAsReaderCloser(srcUrl, rangeHeader)
+ dataReader, err := util.ReadUrlAsReaderCloser(srcUrl, s3a.maybeGetFilerJwtAuthorizationToken(false), rangeHeader)
if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
return
diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go
index b06f540fb..fd2a0e6bd 100644
--- a/weed/s3api/s3api_object_handlers.go
+++ b/weed/s3api/s3api_object_handlers.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"encoding/xml"
"fmt"
+ "github.com/chrislusf/seaweedfs/weed/security"
"io"
"net/http"
"net/url"
@@ -143,7 +144,7 @@ func (s3a *S3ApiServer) GetObjectHandler(w http.ResponseWriter, r *http.Request)
destUrl := fmt.Sprintf("http://%s%s/%s%s",
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, bucket, urlPathEscape(object))
- s3a.proxyToFiler(w, r, destUrl, passThroughResponse)
+ s3a.proxyToFiler(w, r, destUrl, false, passThroughResponse)
}
func (s3a *S3ApiServer) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
@@ -154,7 +155,7 @@ func (s3a *S3ApiServer) HeadObjectHandler(w http.ResponseWriter, r *http.Request
destUrl := fmt.Sprintf("http://%s%s/%s%s",
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, bucket, urlPathEscape(object))
- s3a.proxyToFiler(w, r, destUrl, passThroughResponse)
+ s3a.proxyToFiler(w, r, destUrl, false, passThroughResponse)
}
func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) {
@@ -165,7 +166,7 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque
destUrl := fmt.Sprintf("http://%s%s/%s%s?recursive=true",
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, bucket, urlPathEscape(object))
- s3a.proxyToFiler(w, r, destUrl, func(proxyResponse *http.Response, w http.ResponseWriter) (statusCode int) {
+ s3a.proxyToFiler(w, r, destUrl, true, func(proxyResponse *http.Response, w http.ResponseWriter) (statusCode int) {
statusCode = http.StatusNoContent
for k, v := range proxyResponse.Header {
w.Header()[k] = v
@@ -306,7 +307,7 @@ func (s3a *S3ApiServer) doDeleteEmptyDirectories(client filer_pb.SeaweedFilerCli
return
}
-func (s3a *S3ApiServer) proxyToFiler(w http.ResponseWriter, r *http.Request, destUrl string, responseFn func(proxyResponse *http.Response, w http.ResponseWriter) (statusCode int)) {
+func (s3a *S3ApiServer) proxyToFiler(w http.ResponseWriter, r *http.Request, destUrl string, isWrite bool, responseFn func(proxyResponse *http.Response, w http.ResponseWriter) (statusCode int)) {
glog.V(3).Infof("s3 proxying %s to %s", r.Method, destUrl)
@@ -328,6 +329,9 @@ func (s3a *S3ApiServer) proxyToFiler(w http.ResponseWriter, r *http.Request, des
proxyReq.Header[header] = values
}
+ // ensure that the Authorization header is overriding any previous
+ // Authorization header which might be already present in proxyReq
+ s3a.maybeAddFilerJwtAuthorization(proxyReq, isWrite)
resp, postErr := client.Do(proxyReq)
if postErr != nil {
@@ -389,7 +393,9 @@ func (s3a *S3ApiServer) putToFiler(r *http.Request, uploadUrl string, dataReader
proxyReq.Header.Add(header, value)
}
}
-
+ // ensure that the Authorization header is overriding any previous
+ // Authorization header which might be already present in proxyReq
+ s3a.maybeAddFilerJwtAuthorization(proxyReq, true)
resp, postErr := client.Do(proxyReq)
if postErr != nil {
@@ -435,3 +441,23 @@ func filerErrorToS3Error(errString string) s3err.ErrorCode {
}
return s3err.ErrInternalError
}
+
+func (s3a *S3ApiServer) maybeAddFilerJwtAuthorization(r *http.Request, isWrite bool) {
+ encodedJwt := s3a.maybeGetFilerJwtAuthorizationToken(isWrite)
+
+ if encodedJwt == "" {
+ return
+ }
+
+ r.Header.Set("Authorization", "BEARER "+string(encodedJwt))
+}
+
+func (s3a *S3ApiServer) maybeGetFilerJwtAuthorizationToken(isWrite bool) string {
+ var encodedJwt security.EncodedJwt
+ if isWrite {
+ encodedJwt = security.GenJwtForFilerServer(s3a.filerGuard.SigningKey, s3a.filerGuard.ExpiresAfterSec)
+ } else {
+ encodedJwt = security.GenJwtForFilerServer(s3a.filerGuard.ReadSigningKey, s3a.filerGuard.ReadExpiresAfterSec)
+ }
+ return string(encodedJwt)
+}
diff --git a/weed/s3api/s3api_server.go b/weed/s3api/s3api_server.go
index 1abf9259d..b992fdf88 100644
--- a/weed/s3api/s3api_server.go
+++ b/weed/s3api/s3api_server.go
@@ -3,6 +3,8 @@ package s3api
import (
"fmt"
"github.com/chrislusf/seaweedfs/weed/pb"
+ "github.com/chrislusf/seaweedfs/weed/security"
+ "github.com/chrislusf/seaweedfs/weed/util"
"net/http"
"strings"
"time"
@@ -25,14 +27,25 @@ type S3ApiServerOption struct {
}
type S3ApiServer struct {
- option *S3ApiServerOption
- iam *IdentityAccessManagement
+ option *S3ApiServerOption
+ iam *IdentityAccessManagement
+ filerGuard *security.Guard
}
func NewS3ApiServer(router *mux.Router, option *S3ApiServerOption) (s3ApiServer *S3ApiServer, err error) {
+ v := util.GetViper()
+ signingKey := v.GetString("jwt.filer_signing.key")
+ v.SetDefault("jwt.filer_signing.expires_after_seconds", 10)
+ expiresAfterSec := v.GetInt("jwt.filer_signing.expires_after_seconds")
+
+ readSigningKey := v.GetString("jwt.filer_signing.read.key")
+ v.SetDefault("jwt.filer_signing.read.expires_after_seconds", 60)
+ readExpiresAfterSec := v.GetInt("jwt.filer_signing.read.expires_after_seconds")
+
s3ApiServer = &S3ApiServer{
- option: option,
- iam: NewIdentityAccessManagement(option),
+ option: option,
+ iam: NewIdentityAccessManagement(option),
+ filerGuard: security.NewGuard([]string{}, signingKey, expiresAfterSec, readSigningKey, readExpiresAfterSec),
}
s3ApiServer.registerRouter(router)