Search code examples
azureazure-authenticationazure-sdk

Azure SDK for CPP permission 403


I'm testing dummy Azure application which tries to read information about blob. Public access is denied, I am using two private endpoints, one with DFS type another with BLOB type.

With previous SDK it was working fine With new one NEW SDK I am getting unauthorized access for same getProperties function.

Since storage account is using custom permission roles, how can I check if new SDK has changed endpoints or what is different in new SDK so custom role is no longer sufficient?

OLD

    if(path.size() > 0) {
    cloud_blob_directory dirInfo = storageContainer.get_directory_reference(path);
    blobList = dirInfo.list_blobs(false, blob_listing_details::metadata, 0, requestOptions, operationContext);

    prefix = dirInfo.prefix();
}
else {
    blobList = storageContainer.list_blobs(utility::string_t(), false, blob_listing_details::metadata, 0,
            requestOptions, operationContext);
}

NEW

    if (fileSystem->isHierarchicalNamespaceEnabled()) { 
    auto directoryClient = fileSystem->getDataLakeClient().getDirectoryClient(pathVar);
    dataLakePages = directoryClient.listPaths(false, dataLakeOptions);
    dataLakeIterator = dataLakePages.Paths.begin();
    return; 
}

blobOptions.Prefix = prefixVar;
if (!blobOptions.Prefix.Value().empty() && blobOptions.Prefix.Value().back() != '/') {
    blobOptions.Prefix.Value().append("/");
}

delimiter = "/";
prefixVar = blobOptions.Prefix.Value();
blobPages = fileSystem->getBlobContainer()->listBlobsByHierarchy(delimiter, blobOptions);
blobIterator = blobPages.Blobs.begin();

Solution

  • Azure SDK for CPP permission 403 Since storage account is using custom permission roles, how can I check if new SDK has changed endpoints or what is different in new SDK so custom role is no longer sufficient?

    In the old SDK (azure-storage-cpp) used the azure::storage(Deprecated) namespace and the new SDK (azure-sdk-for-cpp) separates functionality into Azure::Storage::Blobs (for standard blob operations) and Azure::Storage::Files::DataLake (for hierarchical namespace support).

    The new SDK primarily supports Azure::Identity::ClientSecretCredential orDefaultAzureCredential (for RBAC-based authentication [Storage blob data contributor role]) or Shared Access Signatures (SAS) and Account key based credential.

    Code:

    #include <azure/identity/default_azure_credential.hpp>
    #include <azure/storage/blobs.hpp>
    #include <azure/storage/files/datalake.hpp>
    #include <iostream>
    #include <stdexcept>
    
    int main()
    {
        using namespace Azure::Identity;
        using namespace Azure::Storage;
        using namespace Azure::Storage::Blobs;
        using namespace Azure::Storage::Files::DataLake;
    
        const std::string storageAccountName = "youraccount";  
        const std::string fileSystemName = "my-container";
        const std::string directoryPath = "my-directory";
    
        try
        {
            DefaultAzureCredential credential;
            
            std::string blobServiceUrl = "https://" + storageAccountName + ".blob.core.windows.net";
            std::string dataLakeServiceUrl = "https://" + storageAccountName + ".dfs.core.windows.net";
    
            // Create BlobServiceClient to check for Hierarchical Namespace
            auto blobServiceClient = BlobServiceClient(blobServiceUrl, std::make_shared<DefaultAzureCredential>());
            auto accountInfo = blobServiceClient.GetAccountInfo().Value;
            
            bool isHnsEnabled = accountInfo.IsHierarchicalNamespaceEnabled;
            std::cout << "Hierarchical Namespace Enabled: " << (isHnsEnabled ? "Yes" : "No") << std::endl;
    
            auto fileSystemClient = DataLakeFileSystemClient(dataLakeServiceUrl + "/" + fileSystemName, std::make_shared<DefaultAzureCredential>());
    
            if (isHnsEnabled)
            {
                auto directoryClient = fileSystemClient.GetDirectoryClient(directoryPath);
    
                ListPathsOptions dataLakeOptions;
                auto dataLakePages = directoryClient.ListPaths(false, dataLakeOptions);
                for (const auto& path : dataLakePages.Paths)
                {
                    std::cout << "Path: " << path.Name << std::endl;
                }
            }
            else
            {
                auto blobContainerClient = BlobContainerClient(blobServiceUrl + "/" + fileSystemName, std::make_shared<DefaultAzureCredential>());
    
                ListBlobsOptions blobOptions;
                blobOptions.Prefix = directoryPath;
                if (!blobOptions.Prefix.Value().empty() && blobOptions.Prefix.Value().back() != '/')
                {
                    blobOptions.Prefix.Value().append("/");
                }
    
                std::string delimiter = "/";
                auto blobPages = blobContainerClient.ListBlobsByHierarchy(delimiter, blobOptions);
                for (const auto& blob : blobPages.Blobs)
                {
                    std::cout << "Blob: " << blob.Name << std::endl;
                }
            }
        }
        catch (const std::exception& ex)
        {
            std::cerr << "Error: " << ex.what() << std::endl;
        }
    
        return 0;
    }
    

    The above code will check the hierarchical namespace enabled and list the files through the respective endpoint.

    Output:

    Hierarchical Namespace Enabled: Yes
    Path: my-directory/file1.txt
    Path: my-directory/file2.csv
    Path: my-directory/subfolder/
    

    Reference: azure-sdk-for-cpp/sdk/storage/azure-storage-files-datalake at main · Azure/azure-sdk-for-cpp · GitHub