diff --git a/autotest/gcore/vsiaz.py b/autotest/gcore/vsiaz.py index 1c99382d8b24..9941531ea36b 100755 --- a/autotest/gcore/vsiaz.py +++ b/autotest/gcore/vsiaz.py @@ -1127,6 +1127,57 @@ def test_vsiaz_fake_test_BlobEndpointInConnectionString(): ) +############################################################################### + + +def test_vsiaz_fake_test_SharedAccessSignatureInConnectionString(): + + if gdaltest.webserver_port == 0: + pytest.skip() + + with gdaltest.config_option( + "AZURE_STORAGE_CONNECTION_STRING", + "BlobEndpoint=http://127.0.0.1:%d/myaccount;SharedAccessSignature=sp=rl&st=2022-12-06T20:41:17Z&se=2022-12-07T04:41:17Z&spr=https&sv=2021-06-08&sr=c&sig=xxxxxxxx" + % gdaltest.webserver_port, + ): + + signed_url = gdal.GetSignedURL("/vsiaz/az_fake_bucket/resource") + assert ( + signed_url + == "http://127.0.0.1:%d/myaccount/az_fake_bucket/resource?sp=rl&st=2022-12-06T20:41:17Z&se=2022-12-07T04:41:17Z&spr=https&sv=2021-06-08&sr=c&sig=xxxxxxxx" + % gdaltest.webserver_port + ) + + def method(request): + + request.protocol_version = "HTTP/1.1" + h = request.headers + if "Authorization" in h: + sys.stderr.write("Bad headers: %s\n" % str(h)) + request.send_response(403) + return + request.send_response(200) + request.send_header("Content-type", "text/plain") + request.send_header("Content-Length", 3) + request.send_header("Connection", "close") + request.end_headers() + request.wfile.write("""foo""".encode("ascii")) + + handler = webserver.SequentialHandler() + handler.add( + "GET", + "/myaccount/az_fake_bucket/resource?sp=rl&st=2022-12-06T20:41:17Z&se=2022-12-07T04:41:17Z&spr=https&sv=2021-06-08&sr=c&sig=xxxxxxxx", + custom_method=method, + ) + with webserver.install_http_handler(handler): + f = open_for_read("/vsiaz_streaming/az_fake_bucket/resource") + assert f is not None + data = gdal.VSIFReadL(1, 4, f).decode("ascii") + gdal.VSIFCloseL(f) + + assert data == "foo" + + ############################################################################### # Test rename diff --git a/port/cpl_azure.cpp b/port/cpl_azure.cpp index d05995a6e264..fab850bb6eac 100644 --- a/port/cpl_azure.cpp +++ b/port/cpl_azure.cpp @@ -346,20 +346,37 @@ static bool ParseStorageConnectionString(const std::string& osStorageConnectionS bool& bUseHTTPS, CPLString& osEndpoint, CPLString& osStorageAccount, - CPLString& osStorageKey) + CPLString& osStorageKey, + CPLString& osSAS) { osStorageAccount = AzureCSGetParameter(osStorageConnectionString, - "AccountName", true); + "AccountName", false); osStorageKey = AzureCSGetParameter(osStorageConnectionString, - "AccountKey", true); - if( osStorageAccount.empty() || osStorageKey.empty() ) - return false; + "AccountKey", false); - CPLString osProtocol(AzureCSGetParameter( + const CPLString osProtocol(AzureCSGetParameter( osStorageConnectionString, "DefaultEndpointsProtocol", false)); bUseHTTPS = (osProtocol != "http"); - CPLString osBlobEndpoint = AzureCSGetParameter( + if( osStorageAccount.empty() || osStorageKey.empty() ) + { + osStorageAccount.clear(); + osStorageKey.clear(); + + const CPLString osBlobEndpoint = AzureCSGetParameter( + osStorageConnectionString, "BlobEndpoint", false); + osSAS = AzureCSGetParameter( + osStorageConnectionString, "SharedAccessSignature", false); + if( !osBlobEndpoint.empty() && !osSAS.empty() ) + { + osEndpoint = osBlobEndpoint; + return true; + } + + return false; + } + + const CPLString osBlobEndpoint = AzureCSGetParameter( osStorageConnectionString, "BlobEndpoint", false); if( !osBlobEndpoint.empty() ) { @@ -367,7 +384,7 @@ static bool ParseStorageConnectionString(const std::string& osStorageConnectionS } else { - CPLString osEndpointSuffix(AzureCSGetParameter( + const CPLString osEndpointSuffix(AzureCSGetParameter( osStorageConnectionString, "EndpointSuffix", false)); if( !osEndpointSuffix.empty() ) osEndpoint = (bUseHTTPS ? "https://" : "http://") + osStorageAccount + "." + osServicePrefix + "." + osEndpointSuffix; @@ -470,7 +487,8 @@ static bool GetConfigurationFromCLIConfigFile(const std::string& osServicePrefix bUseHTTPS, osEndpoint, osStorageAccount, - osStorageKey); + osStorageKey, + osSAS); } if( osStorageAccount.empty() ) @@ -542,7 +560,8 @@ bool VSIAzureBlobHandleHelper::GetConfiguration(const std::string& osPathForOpti bUseHTTPS, osEndpoint, osStorageAccount, - osStorageKey); + osStorageKey, + osSAS); } else {