mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-14 18:40:48 +02:00
* remote_storage/azure: allow a per-request HTTP client Thread an optional *http.Client through NewAzBlobClient and add azure.MakeWithHTTPClient, mirroring the S3 backend. When set, the client overrides the azblob transport so a caller can pin the dial path. The existing makers pass nil, so behavior is unchanged. * volume: extend the remote-endpoint guard to the azure backend The endpoint validation and rebinding-safe dialer in FetchAndWriteNeedle covered the S3-SDK backends. The azure backend also dials a caller-supplied AzureEndpoint, so route both families through a single guardedRemoteClient helper that returns the endpoint each backend dials and a constructor bound to the guarded HTTP client. azure is guarded only when AzureEndpoint is set; an empty endpoint derives the public host from the account. -volume.allowUntrustedRemoteEndpoints still opts out. * rust volume: assert the azure endpoint has no remote-client path The Rust volume server has no azure backend, so make_remote_storage_client rejects the type before any client is built. Add a regression test pinning that invariant.
99 lines
3.1 KiB
Go
99 lines
3.1 KiB
Go
package azure
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewAzBlobClientRequiresAccountName(t *testing.T) {
|
|
if _, err := NewAzBlobClient("", "aW52YWxpZGtleQ==", "", "", nil); err == nil {
|
|
t.Error("expected an error without an account name")
|
|
}
|
|
}
|
|
|
|
func TestNewAzBlobClientRejectsMalformedAccountName(t *testing.T) {
|
|
for _, accountName := range []string{"ab", "TestAccount", "test-account", "evil.com/x", "evil@host.com", "account?x=1"} {
|
|
if _, err := NewAzBlobClient(accountName, "", "", "", nil); err == nil {
|
|
t.Errorf("expected an error for account name %q", accountName)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewAzBlobClientSharedKey(t *testing.T) {
|
|
client, err := NewAzBlobClient("testaccount", "aW52YWxpZGtleQ==", "", "", nil)
|
|
if err != nil {
|
|
t.Fatalf("failed to create a shared key client: %v", err)
|
|
}
|
|
if client == nil {
|
|
t.Error("expected a client")
|
|
}
|
|
}
|
|
|
|
func TestNewAzBlobClientSharedKeyRejectsMalformedKey(t *testing.T) {
|
|
if _, err := NewAzBlobClient("testaccount", "not base64", "", "", nil); err == nil {
|
|
t.Error("expected an error with a malformed account key")
|
|
}
|
|
}
|
|
|
|
func TestAzureServiceURL(t *testing.T) {
|
|
serviceURL, err := azureServiceURL("testaccount", "")
|
|
if err != nil {
|
|
t.Fatalf("failed to derive the public service url: %v", err)
|
|
}
|
|
if serviceURL != "https://testaccount.blob.core.windows.net/" {
|
|
t.Errorf("unexpected public service url %q", serviceURL)
|
|
}
|
|
|
|
government := "https://testaccount.blob.core.usgovcloudapi.net/"
|
|
serviceURL, err = azureServiceURL("testaccount", government)
|
|
if err != nil {
|
|
t.Fatalf("failed to keep the configured service url: %v", err)
|
|
}
|
|
if serviceURL != government {
|
|
t.Errorf("expected %q, got %q", government, serviceURL)
|
|
}
|
|
|
|
for _, endpoint := range []string{"core.usgovcloudapi.net", "http://testaccount.blob.core.windows.net/", "https://", "https://:443/", "://x"} {
|
|
if _, err := azureServiceURL("testaccount", endpoint); err == nil {
|
|
t.Errorf("expected an error for endpoint %q", endpoint)
|
|
}
|
|
}
|
|
}
|
|
|
|
// no account key: authenticate through the Entra ID chain instead
|
|
func TestNewAzBlobClientEntraID(t *testing.T) {
|
|
client, err := NewAzBlobClient("testaccount", "", "", "", nil)
|
|
if err != nil {
|
|
t.Fatalf("failed to create an Entra ID client: %v", err)
|
|
}
|
|
if client == nil {
|
|
t.Error("expected a client")
|
|
}
|
|
}
|
|
|
|
func TestNewAzBlobClientWorkloadIdentity(t *testing.T) {
|
|
t.Setenv("AZURE_FEDERATED_TOKEN_FILE", filepath.Join(t.TempDir(), "token"))
|
|
t.Setenv("AZURE_TENANT_ID", "00000000-0000-0000-0000-000000000000")
|
|
|
|
client, err := NewAzBlobClient("testaccount", "", "11111111-1111-1111-1111-111111111111", "", nil)
|
|
if err != nil {
|
|
t.Fatalf("failed to create a workload identity client: %v", err)
|
|
}
|
|
if client == nil {
|
|
t.Error("expected a client")
|
|
}
|
|
}
|
|
|
|
// a pinned client id without a projected token file is a plain managed identity
|
|
func TestNewAzureTokenCredentialManagedIdentity(t *testing.T) {
|
|
t.Setenv("AZURE_FEDERATED_TOKEN_FILE", "")
|
|
|
|
credential, err := newAzureTokenCredential("11111111-1111-1111-1111-111111111111")
|
|
if err != nil {
|
|
t.Fatalf("failed to create a managed identity credential: %v", err)
|
|
}
|
|
if credential == nil {
|
|
t.Error("expected a credential")
|
|
}
|
|
}
|