Browse Source

s3: Fix SSE decryption JWT authentication and streaming errors

Critical fix for SSE (Server-Side Encryption) test failures:

1. **JWT Authentication Bug** (Root Cause):
   - Changed from GenJwtForFilerServer to GenJwtForVolumeServer
   - S3 API now uses correct JWT when directly reading from volume servers
   - Matches filer's authentication pattern for direct volume access
   - Fixes 'unexpected EOF' and 500 errors in SSE tests

2. **Streaming Error Handling**:
   - Added error propagation in getEncryptedStreamFromVolumes goroutine
   - Use CloseWithError() to properly communicate stream failures
   - Added debug logging for streaming errors

3. **Response Header Timing**:
   - Removed premature WriteHeader(http.StatusOK) call
   - Let Go's http package write status automatically on first write
   - Prevents header lock when errors occur during streaming

4. **Enhanced SSE Decryption Debugging**:
   - Added IV/Key validation and logging for SSE-C, SSE-KMS, SSE-S3
   - Better error messages for missing or invalid encryption metadata
   - Added glog.V(2) debugging for decryption setup

This fixes SSE integration test failures where encrypted objects
could not be retrieved due to volume server authentication failures.
The JWT bug was causing volume servers to reject requests, resulting
in truncated/empty streams (EOF) or internal errors.
pull/7481/head
chrislu 3 weeks ago
parent
commit
e8b47c1b3a
  1. 15
      weed/s3api/s3api_object_handlers.go

15
weed/s3api/s3api_object_handlers.go

@ -690,8 +690,8 @@ func (s3a *S3ApiServer) streamFromVolumeServers(w http.ResponseWriter, r *http.R
ctx,
masterClient,
func(fileId string) string {
// Use read signing key for volume server auth
return string(security.GenJwtForFilerServer(s3a.filerGuard.ReadSigningKey, s3a.filerGuard.ReadExpiresAfterSec))
// Use volume server JWT (not filer JWT) for direct volume reads
return string(security.GenJwtForVolumeServer(s3a.filerGuard.ReadSigningKey, s3a.filerGuard.ReadExpiresAfterSec, fileId))
},
resolvedChunks,
offset,
@ -797,9 +797,6 @@ func (s3a *S3ApiServer) streamFromVolumeServersWithSSE(w http.ResponseWriter, r
totalSize := int64(filer.FileSize(entry))
s3a.setResponseHeaders(w, entry, totalSize)
s3a.addSSEResponseHeadersFromEntry(w, r, entry, sseType)
// Write status header before streaming data
w.WriteHeader(http.StatusOK)
headerSetTime = time.Since(tHeaderSet)
// Get encrypted data stream (without headers)
@ -904,7 +901,8 @@ func (s3a *S3ApiServer) getEncryptedStreamFromVolumes(ctx context.Context, entry
ctx,
masterClient,
func(fileId string) string {
return string(security.GenJwtForFilerServer(s3a.filerGuard.ReadSigningKey, s3a.filerGuard.ReadExpiresAfterSec))
// Use volume server JWT (not filer JWT) for direct volume reads
return string(security.GenJwtForVolumeServer(s3a.filerGuard.ReadSigningKey, s3a.filerGuard.ReadExpiresAfterSec, fileId))
},
resolvedChunks,
0,
@ -919,7 +917,10 @@ func (s3a *S3ApiServer) getEncryptedStreamFromVolumes(ctx context.Context, entry
pipeReader, pipeWriter := io.Pipe()
go func() {
defer pipeWriter.Close()
streamFn(pipeWriter)
if err := streamFn(pipeWriter); err != nil {
glog.Errorf("getEncryptedStreamFromVolumes: streaming error: %v", err)
pipeWriter.CloseWithError(err)
}
}()
return pipeReader, nil

Loading…
Cancel
Save