azureblob: fix Entra ID server-side copy source authentication
When using Microsoft Entra ID credentials, Azure Blob server-side copy uses a user delegation SAS URL for the private copy source. The SAS start time was set to the current local time. Azure Storage validates the copy source from the service side, and small clock differences can make that SAS appear not yet valid. The service then returns 403 CannotVerifyCopySource with AuthenticationFailed. Start the copy-source SAS 15 minutes in the past, matching Microsoft SAS guidance for clock skew.
This commit is contained in:
committed by
Nick Craig-Wood
parent
5629f2668c
commit
e4c7aca6bd
@@ -70,6 +70,7 @@ const (
|
||||
defaultChunkSize = 4 * fs.Mebi
|
||||
defaultAccessTier = blob.AccessTier("") // FIXME AccessTierNone
|
||||
sasCopyValidity = time.Hour // how long SAS should last when doing server side copy
|
||||
sasCopyStartSkew = 15 * time.Minute // how far back SAS should start to allow for clock skew
|
||||
)
|
||||
|
||||
// setAcceptEncodingGzip is a per-call policy that sets Accept-Encoding: gzip
|
||||
@@ -1827,7 +1828,7 @@ func (f *Fs) getUserDelegation(ctx context.Context) (*service.UserDelegationCred
|
||||
}
|
||||
|
||||
// Validity window
|
||||
start := time.Now().UTC()
|
||||
start := time.Now().UTC().Add(-sasCopyStartSkew)
|
||||
expiry := start.Add(2 * sasCopyValidity)
|
||||
startStr := start.Format(time.RFC3339)
|
||||
expiryStr := expiry.Format(time.RFC3339)
|
||||
@@ -1876,7 +1877,7 @@ func (o *Object) getAuth(ctx context.Context, noAuth bool) (srcURL string, err e
|
||||
// Build the SAS values
|
||||
perms := sas.BlobPermissions{Read: true}
|
||||
container, containerPath := o.split()
|
||||
start := time.Now().UTC()
|
||||
start := time.Now().UTC().Add(-sasCopyStartSkew)
|
||||
expiry := start.Add(sasCopyValidity)
|
||||
vals := sas.BlobSignatureValues{
|
||||
StartTime: start,
|
||||
|
||||
@@ -54,6 +54,11 @@ func TestBlockIDCreator(t *testing.T) {
|
||||
assert.ErrorContains(t, bic2.checkID(chunkNumber, got), "random bytes")
|
||||
}
|
||||
|
||||
func TestCopySASTimingConstants(t *testing.T) {
|
||||
require.Greater(t, sasCopyStartSkew, time.Duration(0))
|
||||
require.Greater(t, sasCopyValidity, sasCopyStartSkew)
|
||||
}
|
||||
|
||||
func (f *Fs) testFeatures(t *testing.T) {
|
||||
// Check first feature flags are set on this remote
|
||||
enabled := f.Features().SetTier
|
||||
|
||||
Reference in New Issue
Block a user