mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-08 15:41:15 +02:00
security: add BearerPrefix constant for Authorization headers (#10101)
Introduce security.BearerPrefix ("Bearer ", RFC 6750) and use it
everywhere an "Authorization: Bearer <token>" header is constructed,
replacing the scattered "BEARER "/"Bearer " string literals. SeaweedFS
matches the scheme case-insensitively when parsing (security.GetJwt), so
behavior is unchanged; this removes the magic string and settles the
casing on the standard form. The parser's upper-case comparison stays as
is on purpose.
This commit is contained in:
@@ -94,7 +94,7 @@ func (store *IamGrpcStore) withIamClient(ctx context.Context, fn func(ctx contex
|
||||
if len(signingKey) > 0 {
|
||||
token := security.GenJwtForFilerAdmin(signingKey, expiresAfterSec)
|
||||
if token != "" {
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+string(token))
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, "authorization", security.BearerPrefix+string(token))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/iam/providers"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
)
|
||||
|
||||
// OIDCProvider implements OpenID Connect authentication
|
||||
@@ -595,7 +596,7 @@ func (p *OIDCProvider) getUserInfoWithToken(ctx context.Context, userID, accessT
|
||||
|
||||
// Set authorization header if access token is provided
|
||||
if accessToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+accessToken)
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
|
||||
@@ -427,7 +427,7 @@ func (wfs *WFS) copyEntryViaFiler(cancel <-chan struct{}, copyRequest wholeFileS
|
||||
return nil, serverSideWholeFileCopyNotCommitted, fmt.Errorf("create filer copy request: %w", err)
|
||||
}
|
||||
if jwt := wfs.filerCopyJWT(); jwt != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+string(jwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(jwt))
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
@@ -504,4 +504,3 @@ func (wfs *WFS) filerCopyJWT() security.EncodedJwt {
|
||||
}
|
||||
return security.GenJwtForFilerServer(wfs.option.FilerSigningKey, wfs.option.FilerSigningExpiresAfterSec)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
util_http "github.com/seaweedfs/seaweedfs/weed/util/http"
|
||||
)
|
||||
|
||||
@@ -84,7 +85,7 @@ func (h *httpClient) sendMessageWithRetry(message *webhookMessage, depth int) er
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if h.token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+h.token)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+h.token)
|
||||
}
|
||||
|
||||
// Apply timeout via context (not on client) to avoid redundancy
|
||||
|
||||
@@ -458,7 +458,7 @@ func (uploader *Uploader) upload_content(ctx context.Context, fillBufferFunction
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
if option.Jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+string(option.Jwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(option.Jwt))
|
||||
}
|
||||
|
||||
request_id.InjectToRequest(ctx, req)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/seaweedfs/seaweedfs/weed/iam/providers"
|
||||
"github.com/seaweedfs/seaweedfs/weed/iam/sts"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
)
|
||||
|
||||
// privateNetworks contains pre-parsed private IP ranges for efficient lookups
|
||||
@@ -87,11 +88,11 @@ func (s3iam *S3IAMIntegration) AuthenticateJWT(ctx context.Context, r *http.Requ
|
||||
|
||||
// Extract bearer token from Authorization header
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
||||
if !strings.HasPrefix(authHeader, security.BearerPrefix) {
|
||||
return nil, s3err.ErrAccessDenied
|
||||
}
|
||||
|
||||
sessionToken := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
sessionToken := strings.TrimPrefix(authHeader, security.BearerPrefix)
|
||||
if sessionToken == "" {
|
||||
return nil, s3err.ErrAccessDenied
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/filer"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
||||
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
||||
@@ -1830,7 +1831,7 @@ func (s3a *S3ApiServer) fetchFullChunk(ctx context.Context, fileId string) (io.R
|
||||
|
||||
// Set JWT for authentication
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+jwt)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+jwt)
|
||||
}
|
||||
|
||||
// Use shared HTTP client
|
||||
@@ -1877,7 +1878,7 @@ func (s3a *S3ApiServer) fetchChunkViewData(ctx context.Context, chunkView *filer
|
||||
|
||||
// Set JWT for authentication
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+jwt)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+jwt)
|
||||
}
|
||||
|
||||
// Use shared HTTP client with connection pooling
|
||||
@@ -2940,7 +2941,7 @@ func (s3a *S3ApiServer) createEncryptedChunkReader(ctx context.Context, chunk *f
|
||||
// Attach volume server JWT for authentication (uses config loaded once at startup)
|
||||
jwt := filer.JwtForVolumeServer(chunk.GetFileIdString())
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+jwt)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+jwt)
|
||||
}
|
||||
|
||||
// Use shared HTTP client with connection pooling
|
||||
|
||||
@@ -1635,7 +1635,7 @@ func (s3a *S3ApiServer) downloadChunkData(srcUrl, fileId string, offset, size in
|
||||
req, err := http.NewRequest(http.MethodHead, srcUrl, nil)
|
||||
if err == nil {
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+string(jwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(jwt))
|
||||
}
|
||||
resp, err := util_http.GetGlobalHttpClient().Do(req)
|
||||
if err == nil {
|
||||
|
||||
@@ -106,7 +106,7 @@ func (s3a *S3ApiServer) streamCopyChunkRange(
|
||||
return fmt.Errorf("create source GET: %w", err)
|
||||
}
|
||||
if srcJwt != "" {
|
||||
srcReq.Header.Set("Authorization", "BEARER "+srcJwt)
|
||||
srcReq.Header.Set("Authorization", security.BearerPrefix+srcJwt)
|
||||
}
|
||||
if isFullChunk {
|
||||
// Manually setting Accept-Encoding tells Go's http.Transport that
|
||||
@@ -188,7 +188,7 @@ func (s3a *S3ApiServer) streamCopyChunkRange(
|
||||
}
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
if dstJwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+string(dstJwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(dstJwt))
|
||||
}
|
||||
|
||||
resp, err := util_http.GetGlobalHttpClient().Do(req)
|
||||
|
||||
@@ -13,6 +13,11 @@ import (
|
||||
type EncodedJwt string
|
||||
type SigningKey []byte
|
||||
|
||||
// BearerPrefix is the RFC 6750 Authorization header scheme prefix for bearer
|
||||
// tokens. Used when constructing "Authorization: Bearer <token>" headers; the
|
||||
// scheme name itself is matched case-insensitively when parsing (see GetJwt).
|
||||
const BearerPrefix = "Bearer "
|
||||
|
||||
// SeaweedFileIdClaims is created by Master server(s) and consumed by Volume server(s),
|
||||
// restricting the access this JWT allows to only a single file.
|
||||
type SeaweedFileIdClaims struct {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/operation"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util"
|
||||
)
|
||||
|
||||
@@ -669,7 +670,7 @@ func (fs *FilerServer) uploadData(ctx context.Context, reader io.Reader, urlLoca
|
||||
}
|
||||
|
||||
if auth != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+auth)
|
||||
req.Header.Set("Authorization", security.BearerPrefix+auth)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
@@ -795,7 +796,7 @@ func (fs *FilerServer) performStreamCopy(ctx context.Context, srcUrl, dstUrl, au
|
||||
|
||||
// Set authorization header if provided
|
||||
if auth != "" {
|
||||
dstReq.Header.Set("Authorization", "Bearer "+auth)
|
||||
dstReq.Header.Set("Authorization", security.BearerPrefix+auth)
|
||||
}
|
||||
dstReq.Header.Set("Content-Type", "application/octet-stream")
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
util_http "github.com/seaweedfs/seaweedfs/weed/util/http"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util/mem"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util/request_id"
|
||||
@@ -99,7 +100,7 @@ func (fs *FilerServer) proxyToVolumeServer(w http.ResponseWriter, r *http.Reques
|
||||
|
||||
// volume server may require a read JWT even though the proxy endpoint doesn't
|
||||
if jwt := fs.maybeGetVolumeReadJwtAuthorizationToken(fileId); jwt != "" {
|
||||
proxyReq.Header.Set("Authorization", "BEARER "+jwt)
|
||||
proxyReq.Header.Set("Authorization", security.BearerPrefix+jwt)
|
||||
}
|
||||
|
||||
proxyResponse, postErr := util_http.GetGlobalHttpClient().Do(proxyReq)
|
||||
|
||||
@@ -221,5 +221,5 @@ func (ms *MasterServer) maybeAddJwtAuthorization(w http.ResponseWriter, fileId s
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Authorization", "BEARER "+string(encodedJwt))
|
||||
w.Header().Set("Authorization", security.BearerPrefix+string(encodedJwt))
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ func (fs *SftpServer) putFile(filepath string, reader io.Reader, user *user.User
|
||||
if len(fs.filerSigningKey) > 0 {
|
||||
jwt := security.GenJwtForFilerServer(security.SigningKey(fs.filerSigningKey), fs.filerSigningExpiresAfter)
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+string(jwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,5 +41,5 @@ func iamAdminAuthContext(ctx context.Context) context.Context {
|
||||
if token == "" {
|
||||
return ctx
|
||||
}
|
||||
return metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+string(token))
|
||||
return metadata.AppendToOutgoingContext(ctx, "authorization", security.BearerPrefix+string(token))
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ func (c *commandVolumeFsck) httpDelete(path util.FullPath) {
|
||||
|
||||
if c.filerSigningKey != "" {
|
||||
encodedJwt := security.GenJwtForFilerServer(security.SigningKey(c.filerSigningKey), jwtFilerTokenExpirationSeconds)
|
||||
req.Header.Set("Authorization", "BEARER "+string(encodedJwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(encodedJwt))
|
||||
}
|
||||
|
||||
if *c.verbose {
|
||||
|
||||
@@ -152,7 +152,7 @@ func Head(url string) (http.Header, error) {
|
||||
|
||||
func maybeAddAuth(req *http.Request, jwt string) {
|
||||
if jwt != "" {
|
||||
req.Header.Set("Authorization", "BEARER "+string(jwt))
|
||||
req.Header.Set("Authorization", security.BearerPrefix+string(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user