All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.identity.AzurePipelinesCredential Maven / Gradle / Ivy

The newest version!
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.identity;

import com.azure.core.annotation.Immutable;
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenCredential;
import com.azure.core.credential.TokenRequestContext;
import com.azure.core.exception.ClientAuthenticationException;
import com.azure.core.http.HttpHeaderName;
import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.identity.implementation.IdentityClient;
import com.azure.identity.implementation.IdentityClientBuilder;
import com.azure.identity.implementation.IdentityClientOptions;
import com.azure.identity.implementation.IdentitySyncClient;
import com.azure.identity.implementation.models.OidcTokenResponse;
import com.azure.identity.implementation.util.IdentityUtil;
import com.azure.identity.implementation.util.LoggingUtil;
import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.net.URL;

/**
 * The {@link AzurePipelinesCredential} acquires a token using the Azure Pipelines service connection.
 *
 * To construct an instance of this credential, use the {@link AzurePipelinesCredentialBuilder}:
 * 
 * 
 * // serviceConnectionId is retrieved from the portal.
 * // systemAccessToken is retrieved from the pipeline environment as shown.
 * // You may choose another name for this variable.
 *
 * String systemAccessToken = System.getenv("SYSTEM_ACCESSTOKEN");
 * AzurePipelinesCredential credential = new AzurePipelinesCredentialBuilder().clientId(clientId)
 *     .tenantId(tenantId)
 *     .serviceConnectionId(serviceConnectionId)
 *     .systemAccessToken(systemAccessToken)
 *     .build();
 * 
* * */ @Immutable public class AzurePipelinesCredential implements TokenCredential { private static final ClientLogger LOGGER = new ClientLogger(AzurePipelinesCredential.class); private final IdentityClient identityClient; private final IdentitySyncClient identitySyncClient; /** * Creates an instance of {@link AzurePipelinesCredential}. * * @param clientId the client id of the service principal * @param tenantId the tenant id of the service principal * @param requestUrl the request url to get the client assertion token * @param systemAccessToken the system access token * @param identityClientOptions the options for configuring the identity client */ AzurePipelinesCredential(String clientId, String tenantId, String requestUrl, String systemAccessToken, IdentityClientOptions identityClientOptions) { IdentityClientBuilder builder = new IdentityClientBuilder().tenantId(tenantId) .clientId(clientId) .identityClientOptions(identityClientOptions) .clientAssertionSupplierWithHttpPipeline((httpPipeline) -> { try { URL url = new URL(requestUrl); HttpRequest request = new HttpRequest(HttpMethod.POST, url); request.setHeader(HttpHeaderName.AUTHORIZATION, "Bearer " + systemAccessToken); request.setHeader(HttpHeaderName.CONTENT_TYPE, "application/json"); // Prevents the service from responding with a redirect HTTP status code (useful for automation). request.setHeader(IdentityUtil.X_TFS_FED_AUTH_REDIRECT, "Suppress"); try (HttpResponse response = httpPipeline.sendSync(request, Context.NONE)) { String responseBody = response.getBodyAsBinaryData().toString(); if (response.getStatusCode() != 200) { String xVssHeader = response.getHeaderValue(IdentityUtil.X_VSS_E2EID); String xMsEdgeRefHeader = response.getHeaderValue(IdentityUtil.X_MSEDGE_REF); String message = "Failed to get the client assertion token " + responseBody + "."; if (xVssHeader != null) { message += " x-vss-e2eid: " + xVssHeader + "."; } if (xMsEdgeRefHeader != null) { message += " x-msedge-ref: " + xMsEdgeRefHeader + "."; } message += "For troubleshooting information see https://aka.ms/azsdk/java/identity/azurepipelinescredential/troubleshoot."; throw LOGGER.logExceptionAsError(new ClientAuthenticationException(message, response)); } try (JsonReader reader = JsonProviders.createReader(responseBody)) { return OidcTokenResponse.fromJson(reader).getOidcToken(); } } } catch (IOException e) { throw LOGGER.logExceptionAsError( new ClientAuthenticationException("Failed to get the client assertion token", null, e)); } }); this.identitySyncClient = builder.buildSyncClient(); this.identityClient = builder.build(); } @Override public Mono getToken(TokenRequestContext request) { return identityClient.authenticateWithConfidentialClientCache(request) .onErrorResume(t -> Mono.empty()) .switchIfEmpty(Mono.defer(() -> identityClient.authenticateWithConfidentialClient(request))) .doOnNext(token -> LoggingUtil.logTokenSuccess(LOGGER, request)) .doOnError( error -> LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, error)); } @Override public AccessToken getTokenSync(TokenRequestContext request) { try { AccessToken token = identitySyncClient.authenticateWithConfidentialClientCache(request); if (token != null) { LoggingUtil.logTokenSuccess(LOGGER, request); return token; } } catch (Exception ignored) { } try { AccessToken token = identitySyncClient.authenticateWithConfidentialClient(request); LoggingUtil.logTokenSuccess(LOGGER, request); return token; } catch (Exception e) { LoggingUtil.logTokenError(LOGGER, identityClient.getIdentityClientOptions(), request, e); // wrap the exception in a RuntimeException to avoid checked exception problems. throw LOGGER.logExceptionAsError(new RuntimeException(e)); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy