Description
Describe the bug
Setup:
Storage account, type Datalake with hierarchical namespace ON
Two private endpoints, one with sub resource type BLOB, other DFS
Using client secret authentication
Storage Blob Data Contributor role added in IAM
Test:
Try to get properties of blob using DataLakeFileSystemClient
Result:
Works fine
Setup:
Storage account, type Datalake with hierarchical namespace ON
One private endpoints, BLOB or DFS
Using client secret authentication
Storage Blob Data Contributor role added in IAM
Test:
Try to get properties of blob using DataLakeFileSystemClient
Result:
403
Exception or Stack Trace
Add the exception log and stack trace if available
To Reproduce
Steps to reproduce the behavior:
Create storage account Data Lake Storage with hierarchical namespace Enabled
Disable public access
Add two private endpoints
Try getting properties using DataLakeFileSystemClient
Remove either endpoint
Code Snippet
`// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include <azure/identity/client_secret_credential.hpp>
#include <azure/storage/files/datalake.hpp>
#include
#include
#include
#include <unordered_map>
// Function to load configuration from a file
std::unordered_map<std::string, std::string> LoadConfig(const std::string& filename)
{
std::unordered_map<std::string, std::string> config;
std::ifstream file(filename);
if (!file)
{
throw std::runtime_error("Failed to open config file: " + filename);
}
std::string line;
while (std::getline(file, line))
{
auto pos = line.find('=');
if (pos != std::string::npos)
{
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
config[key] = value;
}
}
return config;
}
// Function to read directory contents from Azure Data Lake Storage
void ReadDataLakeDirectory(
const Azure::Storage::Files::DataLake::DataLakeFileSystemClient& dataLakeClient,
const std::string& directoryName)
{
try
{
auto directoryClient = dataLakeClient.GetDirectoryClient(directoryName);
auto listDFSOptions = Azure::Storage::Files::DataLake::ListPathsOptions();
auto paths = directoryClient.ListPaths(true, listDFSOptions);
std::cout << "DFS Reading" << std::endl;
for (const auto& path : paths.Paths)
{
std::cout << "******************" << std::endl;
std::cout << path.Name << std::endl;
}
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error reading Data Lake directory: " << e.what() << std::endl;
}
}
// Function to fetch file properties from Azure Data Lake Storage
void ReadDataLakeProperties(
const Azure::Storage::Files::DataLake::DataLakeFileSystemClient& dataLakeClient,
const std::string& directoryName)
{
try
{
std::cout << "Fetching DFS Properties..." << std::endl;
auto fileClient = dataLakeClient.GetFileClient(directoryName);
auto props = fileClient.GetProperties();
std::cout << "Type: " << (props.Value.IsDirectory ? "Directory" : "File") << std::endl;
std::cout << "DFS Properties Retrieved" << std::endl;
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error fetching Data Lake properties: " << e.what() << std::endl;
}
}
// Function to read directory contents from Azure Blob Storage
void ReadBlobDirectory(
const Azure::Storage::Blobs::BlobContainerClient& containerClient)
{
try
{
auto listBlobOptions = Azure::Storage::Blobs::ListBlobsOptions();
auto blobPages = containerClient.ListBlobsByHierarchy("", listBlobOptions);
std::cout << "Blob Reading" << std::endl;
for (const auto& blobItem : blobPages.Blobs)
{
std::cout << "******************" << std::endl;
std::cout << blobItem.Name << std::endl;
}
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error reading Blob directory: " << e.what() << std::endl;
}
}
// Function to fetch file properties from Azure Blob Storage
void ReadBlobProperties(
const Azure::Storage::Blobs::BlobContainerClient& containerClient,
const std::string& directoryName)
{
try
{
std::cout << "Fetching Blob Properties..." << std::endl;
auto blobClient = containerClient.GetBlobClient(directoryName);
auto props = blobClient.GetProperties();
std::cout << "Blob size"+ props.Value.BlobSize << std::endl;
std::cout << "Blob Properties Retrieved" << std::endl;
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error fetching Blob properties: " << e.what() << std::endl;
}
}
int main()
{
using namespace Azure::Storage::Files::DataLake;
using namespace Azure::Storage::Blobs;
// Load configuration
auto config = LoadConfig("../config");
const std::string containerName = config["containerName"];
const std::string directoryName = config["directoryName"];
const std::string tenantId = config["tenantId"];
const std::string clientId = config["clientId"];
const std::string clientSecret = config["clientSecret"];
const std::string storageAccountUrlDFS = config["storageAccountUrlDFS"];
const std::string storageAccountUrlBlob = config["storageAccountUrlBlob"];
auto clientSecretCredential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
try
{
auto datalakeOptions = DataLakeClientOptions();
auto dataLakeClient = DataLakeFileSystemClient(storageAccountUrlDFS + containerName, clientSecretCredential, datalakeOptions);
ReadDataLakeDirectory(dataLakeClient, directoryName);
ReadDataLakeProperties(dataLakeClient, directoryName);
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error with Data Lake operations: " << e.what() << std::endl;
}
try
{
auto blobClientOptions = BlobClientOptions();
auto blobServiceClient = BlobServiceClient(storageAccountUrlBlob, clientSecretCredential, blobClientOptions);
auto containerClient = blobServiceClient.GetBlobContainerClient(containerName);
ReadBlobProperties(containerClient, directoryName);
ReadBlobDirectory(containerClient);
}
catch (const Azure::Storage::StorageException& e)
{
std::cerr << "Error with Blob operations: " << e.what() << std::endl;
}
return 0;
}
`
Expected behavior
Get properties works when user uses DataLakeFileSystemClient and have DFS endpoint
Screenshots
If applicable, add screenshots to help explain your problem.
Setup (please complete the following information):
- OS: Linux
- IDE : VS Code
- Version of the Library used
Additional context
Add any other context about the problem here.
Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report
- Bug Description Added
- Repro Steps Added
- Setup information Added