Expose Scopes on the client options (#6522)

* try

* dsf

* Allow for scope to be passed in

* comment

* clang and others

* Update sdk/tables/azure-data-tables/test/ut/table_client_test.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/tables_audience.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/tables_audience.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* PR comments

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/table_audience.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/table_audience.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* PR

* clang

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>
This commit is contained in:
gearama 2025-04-14 16:30:49 -07:00 committed by GitHub
parent ccfdc87473
commit 1752fec5c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 82 additions and 3 deletions

View File

@ -44,6 +44,7 @@ set(
inc/azure/data/tables/dll_import_export.hpp
inc/azure/data/tables/models.hpp
inc/azure/data/tables/rtti.hpp
inc/azure/data/tables/table_audience.hpp
inc/azure/data/tables.hpp
inc/azure/data/tables/table_client.hpp
inc/azure/data/tables/table_service_client.hpp

View File

@ -11,5 +11,6 @@
#include "azure/data/tables/dll_import_export.hpp"
#include "azure/data/tables/models.hpp"
#include "azure/data/tables/rtti.hpp"
#include "azure/data/tables/table_audience.hpp"
#include "azure/data/tables/table_client.hpp"
#include "azure/data/tables/table_service_client.hpp"

View File

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
#pragma once
#include <string>
#include <utility>
namespace Azure { namespace Data { namespace Tables {
/**
* @brief Audiences available for Azure Table storage service.
*
*/
class TableAudience final {
std::string m_audience;
public:
/**
* @brief Get the audience value.
*/
std::string GetAudience() const { return m_audience; }
/**
* @brief Construct a new TablesAudience object
*
* @param tableAudience The Azure Active Directory audience to use when forming authorization
* scopes. For the Language service, this value corresponds to a URL that identifies the Azure
* cloud where the resource is located. For more information: See
* https://learn.microsoft.com/azure/storage/tables/authorize-access-azure-active-directory
*/
explicit TableAudience(std::string tableAudience) : m_audience{std::move(tableAudience)} {}
/**
* @brief The service endpoint for a given storage account. Use this method to acquire a token
* for authorizing requests to that specific Azure Storage account and service only.
*
* @param tableAccountName The storage account name used to populate the service endpoint.
* @return The service endpoint for a given storage account.
*/
static TableAudience CreateAccountAudience(const std::string& tableAccountName)
{
return TableAudience("https://" + tableAccountName + ".table.core.windows.net/");
}
};
}}} // namespace Azure::Data::Tables

View File

@ -4,6 +4,7 @@
#pragma once
#include "azure/data/tables/models.hpp"
#include "azure/data/tables/table_audience.hpp"
#include <azure/core/credentials/credentials.hpp>
#include <azure/core/http/http.hpp>
@ -50,6 +51,12 @@ namespace Azure { namespace Data { namespace Tables {
* to prompt a challenge in order to discover the correct tenant for the resource.
*/
bool EnableTenantDiscovery = false;
/**
* The Audience to use for authentication with Azure Active Directory (AAD).
* Audience will be assumed based on serviceUrl if it is not set.
*/
Azure::Nullable<TableAudience> Audience;
};
/**

View File

@ -40,4 +40,6 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail {
constexpr static const char* ODataType = "odata.type";
constexpr static const char* ODataMeta = "odata.metadata";
constexpr static const char* ODataError = "odata.error";
constexpr static const char* AudienceSuffix = ".default";
constexpr static const char* AudienceSuffixPath = "/.default";
}}}} // namespace Azure::Data::Tables::_detail

View File

@ -18,6 +18,17 @@ using namespace Azure::Data::Tables::_detail::Policies;
using namespace Azure::Data::Tables::_detail::Xml;
using namespace Azure::Data::Tables::_detail;
namespace Azure { namespace Data { namespace Tables { namespace _detail {
std::string GetDefaultScopeForAudience(const std::string& audience = "")
{
if (!audience.empty() && audience.back() == '/')
{
return audience + _detail::AudienceSuffix;
}
return audience + _detail::AudienceSuffixPath;
}
}}}} // namespace Azure::Data::Tables::_detail
TableServiceClient::TableServiceClient(
const std::string& serviceUrl,
const TableClientOptions& options)
@ -51,7 +62,11 @@ TableServiceClient::TableServiceClient(
perRetryPolicies.emplace_back(std::make_unique<TimeoutPolicy>());
{
Azure::Core::Credentials::TokenRequestContext tokenContext;
tokenContext.Scopes.emplace_back(m_url.GetAbsoluteUrl() + "/.default");
// if Scopes passed in are empty, use the default scope
tokenContext.Scopes.emplace_back(
options.Audience.HasValue()
? _detail::GetDefaultScopeForAudience(options.Audience.Value().GetAudience())
: _detail::GetDefaultScopeForAudience(m_url.GetAbsoluteUrl()));
perRetryPolicies.emplace_back(std::make_unique<TenantBearerTokenAuthenticationPolicy>(
credential, tokenContext, newOptions.EnableTenantDiscovery));
@ -269,7 +284,10 @@ TableClient::TableClient(
perRetryPolicies.emplace_back(std::make_unique<TimeoutPolicy>());
{
Azure::Core::Credentials::TokenRequestContext tokenContext;
tokenContext.Scopes.emplace_back(m_url.GetAbsoluteUrl() + "/.default");
tokenContext.Scopes.emplace_back(
options.Audience.HasValue()
? _detail::GetDefaultScopeForAudience(options.Audience.Value().GetAudience())
: _detail::GetDefaultScopeForAudience(m_url.GetAbsoluteUrl()));
perRetryPolicies.emplace_back(std::make_unique<TenantBearerTokenAuthenticationPolicy>(
credential, tokenContext, newOptions.EnableTenantDiscovery));

View File

@ -3,9 +3,10 @@
// Licensed under the MIT License.
#include "../src/private/serializers.hpp"
#include "azure/data/tables/table_client.hpp"
#include "test/ut/test_base.hpp"
#include <azure/data/tables.hpp>
namespace Azure { namespace Data { namespace Test {
class SerializersTest : public Azure::Storage::Test::StorageTest {

View File

@ -36,6 +36,9 @@ namespace Azure { namespace Data { namespace Test {
if (m_tableServiceClient.get() == nullptr)
{
auto clientOptions = InitStorageClientOptions<Tables::TableClientOptions>();
// set audience for only one of the clients thus both paths.
clientOptions.Audience
= Azure::Data::Tables::TableAudience::CreateAccountAudience(GetAccountName());
auto tableClientOptions = InitStorageClientOptions<Tables::TableClientOptions>();
m_tableName = GetTestNameLowerCase();
@ -84,6 +87,8 @@ namespace Azure { namespace Data { namespace Test {
TEST_P(TablesClientTest, CreateTable)
{
Azure::Data::Tables::TableClientOptions tableClientOptions;
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
EXPECT_EQ(createResponse.Value.TableName, m_tableName);
EXPECT_EQ(createResponse.Value.EditLink, "Tables('" + m_tableName + "')");