Browse Source

fix Filer startup failure due to JWT on / path #8149 (#8167)

* fix Filer startup failure due to JWT on / path #8149

- Comment out JWT keys in security.toml.example
- Revert Dockerfile.local change that enabled security by default
- Exempt GET/HEAD on / from JWT check for health checks

* refactor: simplify JWT bypass condition as per PR feedback
pull/8115/merge
Chris Lu 3 days ago
committed by GitHub
parent
commit
6940b7d06e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      docker/Dockerfile.local
  2. 16
      docker/security.toml.example
  3. 14
      weed/server/filer_jwt_test.go
  4. 4
      weed/server/filer_server_handlers.go

1
docker/Dockerfile.local

@ -4,7 +4,6 @@ COPY ./weed /usr/bin/weed
RUN chmod +x /usr/bin/weed && ls -la /usr/bin/weed RUN chmod +x /usr/bin/weed && ls -la /usr/bin/weed
RUN mkdir -p /etc/seaweedfs RUN mkdir -p /etc/seaweedfs
COPY ./filer.toml /etc/seaweedfs/filer.toml COPY ./filer.toml /etc/seaweedfs/filer.toml
COPY ./security.toml.example /etc/seaweedfs/security.toml
COPY ./entrypoint.sh /entrypoint.sh COPY ./entrypoint.sh /entrypoint.sh
# Install dependencies and create non-root user # Install dependencies and create non-root user

16
docker/security.toml.example

@ -13,22 +13,22 @@ values = "*"
# - the Master server generates the JWT, which can be used to write a certain file on a volume server # - the Master server generates the JWT, which can be used to write a certain file on a volume server
# - the Volume server validates the JWT on writing # - the Volume server validates the JWT on writing
# the jwt defaults to expire after 10 seconds. # the jwt defaults to expire after 10 seconds.
[jwt.signing]
key = "V1JJVEVTRUNSRVRFWEFNUExFMTIzNDU2Nzg5MDEy" # Example: WRITESECRETEXAMPLE123456789012
# [jwt.signing]
# key = "V1JJVEVTRUNSRVRFWEFNUExFMTIzNDU2Nzg5MDEy" # Example: WRITESECRETEXAMPLE123456789012
# this jwt signing key is read by master and volume server, and it is used for read operations: # this jwt signing key is read by master and volume server, and it is used for read operations:
# - the Master server generates the JWT, which can be used to read a certain file on a volume server # - the Master server generates the JWT, which can be used to read a certain file on a volume server
# - the Volume server validates the JWT on reading # - the Volume server validates the JWT on reading
[jwt.signing.read]
key = "UkVBRFNFQ1JFVUVYQU1QTEUxMjM0NTY3ODkwMTI=" # Example: READSECRETEXAMPLE123456789012
# [jwt.signing.read]
# key = "UkVBRFNFQ1JFVUVYQU1QTEUxMjM0NTY3ODkwMTI=" # Example: READSECRETEXAMPLE123456789012
# If this JWT key is configured, Filer only accepts writes over HTTP if they are signed with this JWT: # If this JWT key is configured, Filer only accepts writes over HTTP if they are signed with this JWT:
# - f.e. the S3 API Shim generates the JWT # - f.e. the S3 API Shim generates the JWT
# - the Filer server validates the JWT on writing # - the Filer server validates the JWT on writing
# the jwt defaults to expire after 10 seconds. # the jwt defaults to expire after 10 seconds.
[jwt.filer_signing]
key = "RklMRVJXUklURVNFQ1JFVEVYQU1QTEUxMjM0NTY3OA==" # Example: FILERWRITESECRETEXAMPLE12345678
# [jwt.filer_signing]
# key = "RklMRVJXUklURVNFQ1JFVEVYQU1QTEUxMjM0NTY3OA==" # Example: FILERWRITESECRETEXAMPLE12345678
# If this JWT key is configured, Filer only accepts reads over HTTP if they are signed with this JWT: # If this JWT key is configured, Filer only accepts reads over HTTP if they are signed with this JWT:
# - f.e. the S3 API Shim generates the JWT # - f.e. the S3 API Shim generates the JWT
# - the Filer server validates the JWT on reading # - the Filer server validates the JWT on reading
# the jwt defaults to expire after 10 seconds. # the jwt defaults to expire after 10 seconds.
[jwt.filer_signing.read]
key = "RklMRVJSRUFEU0VDUkVURVhBTVBMRTEyMzQ1Njc4OQ==" # Example: FILERREADSECRETEXAMPLE123456789
# [jwt.filer_signing.read]
# key = "RklMRVJSRUFEU0VDUkVURVhBTVBMRTEyMzQ1Njc4OQ==" # Example: FILERREADSECRETEXAMPLE123456789

14
weed/server/filer_jwt_test.go

@ -119,7 +119,15 @@ func TestFilerServer_maybeCheckJwtAuthorization_Scoped(t *testing.T) {
method: "GET", method: "GET",
path: "/", path: "/",
isWrite: false, isWrite: false,
expectAuthorized: false,
expectAuthorized: true,
},
{
name: "root path without token",
token: "",
method: "GET",
path: "/",
isWrite: false,
expectAuthorized: true,
}, },
{ {
name: "exact prefix match", name: "exact prefix match",
@ -134,7 +142,9 @@ func TestFilerServer_maybeCheckJwtAuthorization_Scoped(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest(tt.method, tt.path, nil) req := httptest.NewRequest(tt.method, tt.path, nil)
req.Header.Set("Authorization", "Bearer "+tt.token)
if tt.token != "" {
req.Header.Set("Authorization", "Bearer "+tt.token)
}
if authorized := fs.maybeCheckJwtAuthorization(req, tt.isWrite); authorized != tt.expectAuthorized { if authorized := fs.maybeCheckJwtAuthorization(req, tt.isWrite); authorized != tt.expectAuthorized {
t.Errorf("expected authorized=%v, got %v", tt.expectAuthorized, authorized) t.Errorf("expected authorized=%v, got %v", tt.expectAuthorized, authorized)
} }

4
weed/server/filer_server_handlers.go

@ -211,6 +211,10 @@ func OptionsHandler(w http.ResponseWriter, r *http.Request, isReadOnly bool) {
// maybeCheckJwtAuthorization returns true if access should be granted, false if it should be denied // maybeCheckJwtAuthorization returns true if access should be granted, false if it should be denied
func (fs *FilerServer) maybeCheckJwtAuthorization(r *http.Request, isWrite bool) bool { func (fs *FilerServer) maybeCheckJwtAuthorization(r *http.Request, isWrite bool) bool {
if !isWrite && r.URL.Path == "/" {
return true
}
var signingKey security.SigningKey var signingKey security.SigningKey
if isWrite { if isWrite {

Loading…
Cancel
Save