azure-sdk-for-cpp
azure-sdk-for-cpp copied to clipboard
Add Support for Workload Identity Federation for Azure Service Connections
Tracking item to add WorkloadIdentityCredential support for Azure Service Connections (App Config). @KarishmaGhiya is driving the investigation.
Original partner ask: https://github.com/Azure/azure-sdk-for-js/issues/27093
From @KarishmaGhiya:
@joshfree I spoke to @ChristineWanjau Looks like App Configuration is using the preview feature Azure Devops for their authenication for service connection using workload identity. Essentially what happens is when they request an idToken, it gets supplied by Azure Devops (https://devblogs.microsoft.com/devops/public-preview-of-workload-identity-federation-for-azure-pipelines/#custom-azure-tasks-and-extensions). But this idToken is not written to a file, it's speculated to be supplied through the env. So the ask was that do we support the scenario.
It seems like the Azure::Identity::AzureCliCredential is not executing the az commands in the correct context.
When trying to use credentials inside a program executed in the AzureCli@2 task, all I'm getting from the AzureCliCredential is
[2023-09-27T09:19:47.9285620Z] WARN : Identity: AzureCliCredential didn't get the token: "ERROR: Please run 'az login' to setup account.
Whereas, if I take that exact az command that it executes (az account get-access-token ...), and runs that outside my program but still inside the AzureCli@2 task, it works just fine and provides a token I can use to communicate with my blob storage.
To workaround this issue, I've had to implement a custom Azure::Core::Credentials::TokenCredential which uses the manually created token, injected into my program as an environment variable.
This is a temporary workaround as I don't read the expiration of the token, and I assume the token is set up correctly wrt. scopes.
- task: AzureCLI@2
env:
AZURE_LOG_LEVEL: 1
inputs:
azureSubscription: 'My_Federated_Service_Connection'
scriptType: 'ps'
scriptLocation: 'inlineScript'
inlineScript: |
$env:accessToken = (az account get-access-token --output json --scope https://storage.azure.com/.default | ConvertFrom-Json).accessToken
.\_build\blob_storage_fetcher.exe
class AccessTokenCredential : public Azure::Core::Credentials::TokenCredential {
std::optional<Azure::Core::Credentials::AccessToken> _token;
public:
explicit AccessTokenCredential() : Azure::Core::Credentials::TokenCredential("Access Token") {
#pragma warning(push)
#pragma warning(disable: 4996)
auto access_token = std::getenv("accessToken");
#pragma warning(pop)
if(access_token) {
_token = Azure::Core::Credentials::AccessToken();
_token->Token = access_token;
_token->ExpiresOn = std::chrono::system_clock::now() + std::chrono::seconds(static_cast<std::int32_t>(3600));
}
}
Azure::Core::Credentials::AccessToken GetToken(const Azure::Core::Credentials::TokenRequestContext &tokenRequestContext, const Azure::Core::Context &context) const override {
if(_token) {
return *_token;
}
throw Azure::Core::Credentials::AuthenticationException("Token cannot be read from environment variable.");
}
};
And then I use it like
auto cred = std::make_shared<Azure::Identity::ChainedTokenCredential>(Azure::Identity::ChainedTokenCredential::Sources{
std::make_shared<AccessTokenCredential>(),
std::make_shared<Azure::Identity::DefaultAzureCredential>()
});
const auto sc = BlobServiceClient("https://"+storage_account+".blob.core.windows.net", cred);
@willadsen can you please file a separate issue for the AzureCliCredential behavior you are seeing, as that is not related to the topic of this issue, around Workload Identity Federation, and we can investigate further.
@willadsen can you please file a separate issue for the
AzureCliCredentialbehavior you are seeing, as that is not related to the topic of this issue, around Workload Identity Federation, and we can investigate further.
I'm fairly certain it is related, because if I use a good old Service connection using a SP, it works just fine.
If you still think it's a separate issue I'll gladly create a new issue
Hi all, any update on this? We are also facing this issue and are going to have to resort back to using a service principal (secret) for AzureFileCopy tasks in ADO pipelines. Thanks!
@bbrandt and @cyclelabs-ryanberger the AzurePipelinesCredential which be used for authenticating using Azure Service Connections has shipped and is available as of 1.9.0-beta.1.
You can acquire it via vcpkg, or directly from GitHub: https://github.com/Azure/azure-sdk-vcpkg-betas/tree/main https://github.com/Azure/azure-sdk-for-cpp/tree/azure-identity_1.9.0-beta.1/sdk/identity/azure-identity