Skip to content

Commit

Permalink
SPN Auth credential bug fix for ARG and PackerBuild tasks (#11994)
Browse files Browse the repository at this point in the history
* spn auth credential bug fix for ARG task

* SPN Auth Credential Bug fix for PackerBuild task

* Refactoring bug fix to utilize arm-endpoint function

* Refactoring PackerBuildV1 as well

* Updating task version due to Common library change

* Avoiding package-lock.json

* Bug fix

* Review comments

* Bug fix

* Bug fix

* Bug fix

* bug fix

* Merge conflict resolutions

* Bug fix
  • Loading branch information
issacnitinmsft authored and issacnitin committed Jan 5, 2020
1 parent cae4948 commit d06fa21
Show file tree
Hide file tree
Showing 48 changed files with 226 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Tasks/ACRTaskV0/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"version": {
"Major": 0,
"Minor": 162,
"Patch": 1
"Patch": 5
},
"instanceNameFormat": "acrTask",
"showEnvironmentVariables": true,
Expand Down
2 changes: 1 addition & 1 deletion Tasks/ACRTaskV0/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"version": {
"Major": 0,
"Minor": 162,
"Patch": 1
"Patch": 5
},
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
"showEnvironmentVariables": true,
Expand Down
4 changes: 2 additions & 2 deletions Tasks/AzureAppServiceManageV0/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"demands": [],
"version": {
"Major": 0,
"Minor": 2,
"Patch": 65
"Minor": 162,
"Patch": 2
},
"minimumAgentVersion": "1.102.0",
"instanceNameFormat": "$(Action): $(WebAppName)",
Expand Down
4 changes: 2 additions & 2 deletions Tasks/AzureAppServiceManageV0/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"demands": [],
"version": {
"Major": 0,
"Minor": 2,
"Patch": 65
"Minor": 162,
"Patch": 2
},
"minimumAgentVersion": "1.102.0",
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureFileCopyV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"version": {
"Major": 2,
"Minor": 154,
"Patch": 15
"Patch": 18
},
"demands": [
"azureps"
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureFileCopyV2/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"version": {
"Major": 2,
"Minor": 154,
"Patch": 15
"Patch": 18
},
"demands": [
"azureps"
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureFileCopyV3/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"version": {
"Major": 3,
"Minor": 154,
"Patch": 15
"Patch": 18
},
"preview": true,
"demands": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureFileCopyV3/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"version": {
"Major": 3,
"Minor": 154,
"Patch": 15
"Patch": 18
},
"preview": true,
"demands": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureKeyVaultV1/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"version": {
"Major": 1,
"Minor": 155,
"Patch": 8
"Patch": 11
},
"demands": [],
"minimumAgentVersion": "2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureKeyVaultV1/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"version": {
"Major": 1,
"Minor": 155,
"Patch": 8
"Patch": 11
},
"demands": [],
"minimumAgentVersion": "2.0.0",
Expand Down
4 changes: 2 additions & 2 deletions Tasks/AzureMonitorAlertsV0/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
],
"version": {
"Major": 0,
"Minor": 159,
"Patch": 4
"Minor": 163,
"Patch": 2
},
"minimumAgentVersion": "2.111.0",
"instanceNameFormat": "Configure Azure Alerts : $(ResourceName)",
Expand Down
4 changes: 2 additions & 2 deletions Tasks/AzureMonitorAlertsV0/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
],
"version": {
"Major": 0,
"Minor": 159,
"Patch": 4
"Minor": 163,
"Patch": 2
},
"minimumAgentVersion": "2.111.0",
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureMysqlDeploymentV1/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 156,
"Patch": 18
"Patch": 21
},
"demands": [],
"minimumAgentVersion": "1.100.0",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureMysqlDeploymentV1/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 156,
"Patch": 18
"Patch": 21
},
"demands": [],
"minimumAgentVersion": "1.100.0",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzurePowerShellV4/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 4,
"Minor": 159,
"Patch": 7
"Patch": 10
},
"releaseNotes": "Added support for Az Module and cross platform agents.",
"groups": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzurePowerShellV4/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 4,
"Minor": 159,
"Patch": 7
"Patch": 10
},
"releaseNotes": "ms-resource:loc.releaseNotes",
"groups": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzurePowerShellV5/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 5,
"Minor": 162,
"Patch": 1
"Patch": 4
},
"preview": "true",
"releaseNotes": "Added support for Az Module and cross platform agents.",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzurePowerShellV5/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 5,
"Minor": 162,
"Patch": 1
"Patch": 4
},
"preview": "true",
"releaseNotes": "ms-resource:loc.releaseNotes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,9 @@
"loc.messages.LogDeploymentName": "Deployment name is %s",
"loc.messages.ExpiredServicePrincipal": "Could not fetch access token for Azure. Verify if the Service Principal used is valid and not expired.",
"loc.messages.DeploymentGroupConfigurationNotSucceeded": "Deployment group configuration did not succeed on one or more Virtual Machine(s): %s",
"loc.messages.ServicePrincipalRoleAssignmentDetails": "Please make sure the Service Principal with name %s is assigned the right roles for the Resource Group %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal",
"loc.messages.ServicePrincipalFetchFailed": "Error while fetching Service Principal details: %s",
"loc.messages.FindMoreDeploymentDetailsAzurePortal": "Task successfully created an Azure Resource Manager deployment, but the deployment failed. Please see more detailed Azure resource manager deployment logs at: (Please Copy-Paste the link) %s",
"loc.messages.ManagedServiceIdentityDetails": "Please make sure the Managed Service Identity used for deployment is assigned the right roles for the Resource Group %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/howto-assign-access-portal",
"loc.messages.DeploymentGroupConfigurationFailedOnVM": "Failure for Virtual Machine '%s': %s"
}
11 changes: 10 additions & 1 deletion Tasks/AzureResourceGroupDeploymentV2/models/DeployAzureRG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,16 @@ export class AzureRGTaskParameters {
public deploymentName: string;
public deploymentMode: string;
public credentials: msRestAzure.ApplicationTokenCredentials;
public graphCredentials: msRestAzure.ApplicationTokenCredentials;
public deploymentGroupProjectName = "";
public tokenCredentials: TokenCredentials;
public deploymentOutputs: string;
public agentServiceUserCredentials: AgentServiceUserCredentials;
public runAgentServiceAsUser: boolean;
public addSpnToEnvironment: boolean;
public connectedService: string;

public authScheme: string;

private getVSTSPatToken(deploymentGroupEndpointName: string): TokenCredentials {
var endpointAuth = tl.getEndpointAuthorization(deploymentGroupEndpointName, true);
if (endpointAuth.scheme === 'Token') {
Expand Down Expand Up @@ -101,6 +103,11 @@ export class AzureRGTaskParameters {
return azureEndpoint.applicationTokenCredentials;
}

private async getGraphCredentials(connectedService: string): Promise<msRestAzure.ApplicationTokenCredentials> {
var azureEndpoint = await new AzureRMEndpoint(connectedService).getEndpoint(true);
return azureEndpoint.applicationTokenCredentials;
}

public async getAzureRGTaskParameters() : Promise<AzureRGTaskParameters>
{
try {
Expand Down Expand Up @@ -140,6 +147,8 @@ export class AzureRGTaskParameters {
this.deploymentName = tl.getInput("deploymentName");
this.deploymentMode = tl.getInput("deploymentMode");
this.credentials = await this.getARMCredentials(this.connectedService);
this.authScheme = tl.getEndpointAuthorizationScheme(this.connectedService, true);
this.graphCredentials = await this.getGraphCredentials(this.connectedService);
this.deploymentGroupProjectName = tl.getInput("project");
this.deploymentOutputs = tl.getInput("deploymentOutputs");
this.addSpnToEnvironment = tl.getBoolInput("addSpnToEnvironment", false);
Expand Down
48 changes: 48 additions & 0 deletions Tasks/AzureResourceGroupDeploymentV2/operations/ResourceGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import fileEncoding = require('./FileEncoding');
import { ParametersFileObject, TemplateObject, ParameterValue } from "../models/Types";
import httpInterfaces = require("typed-rest-client/Interfaces");
import { sleepFor } from 'azure-arm-rest-v2/webClient';
import azureGraph = require("azure-arm-rest-v2/azure-graph");

var hm = require("typed-rest-client/HttpClient");
var uuid = require("uuid");
Expand Down Expand Up @@ -119,12 +120,14 @@ export class ResourceGroup {
private winRMExtensionHelper: winRM.WinRMExtensionHelper;
private deploymentGroupExtensionHelper: dgExtensionHelper.DeploymentGroupExtensionHelper;
private environmentHelper: env.EnvironmentHelper;
private _spnName: string;

constructor(taskParameters: deployAzureRG.AzureRGTaskParameters) {
this.taskParameters = taskParameters;
this.winRMExtensionHelper = new winRM.WinRMExtensionHelper(this.taskParameters);
this.deploymentGroupExtensionHelper = new dgExtensionHelper.DeploymentGroupExtensionHelper(this.taskParameters);
this.environmentHelper = new env.EnvironmentHelper(this.taskParameters);
this._spnName = null;
}

public async createOrUpdateResourceGroup(): Promise<void> {
Expand Down Expand Up @@ -524,6 +527,10 @@ export class ResourceGroup {
}

private async performAzureDeployment(armClient: armResource.ResourceManagementClient, deployment: Deployment, retryCount = 0): Promise<void> {
if(!this._spnName && this.taskParameters.authScheme == "ServicePrincipal") {
this._spnName = await this.getServicePrincipalName();
}

if (deployment.properties["mode"] === "Validation") {
return this.validateDeployment(armClient, deployment);
} else {
Expand All @@ -537,6 +544,8 @@ export class ResourceGroup {
return this.waitAndPerformAzureDeployment(armClient, deployment, retryCount);
}
this.writeDeploymentErrors(error);
this.checkAndPrintPortalDeploymentURL(result.error);
this.printServicePrincipalRoleAssignmentError(error);
return reject(tl.loc("CreateTemplateDeploymentFailed"));
}
if (result && result["properties"] && result["properties"]["outputs"] && utils.isNonEmpty(this.taskParameters.deploymentOutputs)) {
Expand All @@ -551,6 +560,45 @@ export class ResourceGroup {
}
}

private printServicePrincipalRoleAssignmentError(error: any) {
if(!!error && error.statusCode == 403) {
if(this.taskParameters.authScheme == "ServicePrincipal") {
tl.error(tl.loc("ServicePrincipalRoleAssignmentDetails", this._spnName, this.taskParameters.resourceGroupName));
} else if(this.taskParameters.authScheme == "ManagedServiceIdentity") {
tl.error(tl.loc("ManagedServiceIdentityDetails", this.taskParameters.resourceGroupName));
}
}
}

protected async getServicePrincipalName(): Promise<string> {
try {
var graphClient: azureGraph.GraphManagementClient = new azureGraph.GraphManagementClient(this.taskParameters.graphCredentials);
var servicePrincipalObject = await graphClient.servicePrincipals.GetServicePrincipal(null);
return !!servicePrincipalObject ? servicePrincipalObject.appDisplayName : "";
} catch (error) {
tl.debug(tl.loc("ServicePrincipalFetchFailed", error));
return "";
}
}

protected checkAndPrintPortalDeploymentURL(error: any) {
if(!!error && (error.statusCode < 400 || error.statusCode >= 500)) {
tl.error(tl.loc("FindMoreDeploymentDetailsAzurePortal", this.getAzurePortalDeploymentURL()));
}
}

private getAzurePortalDeploymentURL() {
try {
let portalUrl = this.taskParameters.endpointPortalUrl ? this.taskParameters.endpointPortalUrl : "https://portal.azure.com";
portalUrl += "/#blade/HubsExtension/DeploymentDetailsBlade/overview/id/";
let subscriptionSpecificURL = "/subscriptions/" + this.taskParameters.subscriptionId + "/resourceGroups/" + this.taskParameters.resourceGroupName + "/providers/Microsoft.Resources/deployments/" + this.taskParameters.deploymentName;
return portalUrl + subscriptionSpecificURL.replace(/\//g, '%2F');
} catch (error) {
tl.error(error);
return error;
}
}

private async waitAndPerformAzureDeployment(armClient: armResource.ResourceManagementClient, deployment: Deployment, retryCount): Promise<void> {
await sleepFor(3);
return this.performAzureDeployment(armClient, deployment, retryCount - 1);
Expand Down
8 changes: 6 additions & 2 deletions Tasks/AzureResourceGroupDeploymentV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"author": "Microsoft Corporation",
"version": {
"Major": 2,
"Minor": 162,
"Patch": 2
"Minor": 163,
"Patch": 4
},
"demands": [],
"minimumAgentVersion": "2.119.1",
Expand Down Expand Up @@ -480,6 +480,10 @@
"LogDeploymentName": "Deployment name is %s",
"ExpiredServicePrincipal": "Could not fetch access token for Azure. Verify if the Service Principal used is valid and not expired.",
"DeploymentGroupConfigurationNotSucceeded": "Deployment group configuration did not succeed on one or more Virtual Machine(s): %s",
"ServicePrincipalRoleAssignmentDetails": "Please make sure the Service Principal with name %s is assigned the right roles for the Resource Group %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal",
"ServicePrincipalFetchFailed": "Error while fetching Service Principal details: %s",
"FindMoreDeploymentDetailsAzurePortal": "Task successfully created an Azure Resource Manager deployment, but the deployment failed. Please see more detailed Azure resource manager deployment logs at: (Please Copy-Paste the link) %s",
"ManagedServiceIdentityDetails": "Please make sure the Managed Service Identity used for deployment is assigned the right roles for the Resource Group %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/howto-assign-access-portal",
"DeploymentGroupConfigurationFailedOnVM": "Failure for Virtual Machine '%s': %s"
}
}
8 changes: 6 additions & 2 deletions Tasks/AzureResourceGroupDeploymentV2/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"author": "Microsoft Corporation",
"version": {
"Major": 2,
"Minor": 162,
"Patch": 2
"Minor": 163,
"Patch": 4
},
"demands": [],
"minimumAgentVersion": "2.119.1",
Expand Down Expand Up @@ -480,6 +480,10 @@
"LogDeploymentName": "ms-resource:loc.messages.LogDeploymentName",
"ExpiredServicePrincipal": "ms-resource:loc.messages.ExpiredServicePrincipal",
"DeploymentGroupConfigurationNotSucceeded": "ms-resource:loc.messages.DeploymentGroupConfigurationNotSucceeded",
"ServicePrincipalRoleAssignmentDetails": "ms-resource:loc.messages.ServicePrincipalRoleAssignmentDetails",
"ServicePrincipalFetchFailed": "ms-resource:loc.messages.ServicePrincipalFetchFailed",
"FindMoreDeploymentDetailsAzurePortal": "ms-resource:loc.messages.FindMoreDeploymentDetailsAzurePortal",
"ManagedServiceIdentityDetails": "ms-resource:loc.messages.ManagedServiceIdentityDetails",
"DeploymentGroupConfigurationFailedOnVM": "ms-resource:loc.messages.DeploymentGroupConfigurationFailedOnVM"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,9 @@
"loc.messages.ResourceGroupNameNotProvided": "Resource Group name should be provided",
"loc.messages.LocationNotProvided": "Location is required for deployment",
"loc.messages.ARMServiceConnectionScope": "ARM Service Conection deployment scope - %s",
"loc.messages.ServicePrincipalRoleAssignmentDetails": "Please make sure the Service Principal with name %s is assigned the right roles for the entity %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal",
"loc.messages.ServicePrincipalFetchFailed": "Error while fetching Service Principal details: %s",
"loc.messages.FindMoreDeploymentDetailsAzurePortal": "Task successfully created an Azure Resource Manager deployment, but the deployment failed. Please see more detailed Azure resource manager deployment logs at: (Please Copy-Paste the link) %s",
"loc.messages.ManagedServiceIdentityDetails": "Please make sure the Managed Service Identity used for deployment is assigned the right roles for the Resource Group %s. Follow the link for more details: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/howto-assign-access-portal",
"loc.messages.CompleteDeploymentModeNotSupported": "Deployment mode 'Complete' is not supported for deployment at '%s' scope"
}
Loading

0 comments on commit d06fa21

Please sign in to comment.