Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users/ajya/nationalcloudclientsidechanges #3551

Merged
merged 13 commits into from
Feb 16, 2017
1 change: 1 addition & 0 deletions Tasks/AzureAppServiceManage/azureappservicemanage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ async function run() {
endPoint["servicePrincipalKey"] = tl.getEndpointAuthorizationParameter(connectedServiceName, 'serviceprincipalkey', true);
endPoint["tenantID"] = tl.getEndpointAuthorizationParameter(connectedServiceName, 'tenantid', true);
endPoint["subscriptionId"] = tl.getEndpointDataParameter(connectedServiceName, 'subscriptionid', true);
endPoint["envAuthUrl"] = tl.getEndpointDataParameter(connectedServiceName, 'environmentAuthorityUrl', true);
endPoint["url"] = tl.getEndpointUrl(connectedServiceName, true);

if(resourceGroupName === null) {
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureAppServiceManage/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 0,
"Minor": 2,
"Patch": 2
"Patch": 3
},
"minimumAgentVersion": "1.102.0",
"instanceNameFormat": "$(Action): $(WebAppName)",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureAppServiceManage/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 0,
"Minor": 2,
"Patch": 2
"Patch": 3
},
"minimumAgentVersion": "1.102.0",
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
Expand Down
35 changes: 18 additions & 17 deletions Tasks/AzureNLBManagement/nlbazureutility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import * as httpClient from 'vso-node-api/HttpClient';
import * as restClient from 'vso-node-api/RestClient';

var httpObj = new httpClient.HttpCallbackClient(tl.getVariable("AZURE_HTTP_USER_AGENT"));
var authUrl = 'https://login.windows.net/';
var defaultAuthUrl = 'https://login.windows.net/';
var azureApiVersion = '2016-09-01';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this API version work fine in other Cloud environment types. Do you see any issue with Azure deployments causing issues?


function getAccessToken(SPN, endpointUrl: string): Q.Promise<string> {
function getAccessToken(endpoint, endpointUrl: string): Q.Promise<string> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having the second parameter as enpointurl is confusing. There is already endpoint taken as input which has endpoint.url. I presume this is the resource for which you are requesting token. So should we just call it resource?


var deferred = Q.defer<string>();
var authorityUrl = authUrl + SPN.tenantID + "/oauth2/token/";
var envAuthUrl = (endpoint.envAuthUrl) ? endpoint.envAuthUrl : defaultAuthUrl;
var authorityUrl = envAuthUrl + endpoint.tenantID + "/oauth2/token/";

var post_data = querystring.stringify({
resource: endpointUrl,
client_id: SPN.servicePrincipalClientID,
client_id: endpoint.servicePrincipalClientID,
grant_type: "client_credentials",
client_secret: SPN.servicePrincipalKey
client_secret: endpoint.servicePrincipalKey
});

var requestHeader = {
Expand All @@ -40,11 +41,11 @@ function getAccessToken(SPN, endpointUrl: string): Q.Promise<string> {
return deferred.promise;
}

export async function getNetworkInterfacesInRG(SPN, endpointUrl: string, resourceGroupName: string) {
export async function getNetworkInterfacesInRG(endpoint, endpointUrl: string, resourceGroupName: string) {

var deferred = Q.defer<any>();
var restUrl = "https://management.azure.com/subscriptions/" + SPN.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(SPN, endpointUrl);
var restUrl = endpoint.url + "subscriptions/" + endpoint.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(endpoint, endpointUrl);

var requestHeader = {
Authorization: 'Bearer ' + accessToken
Expand All @@ -66,11 +67,11 @@ export async function getNetworkInterfacesInRG(SPN, endpointUrl: string, resourc
return deferred.promise;
}

export async function getLoadBalancer(SPN, endpointUrl: string, name: string, resourceGroupName: string) {
export async function getLoadBalancer(endpoint, endpointUrl: string, name: string, resourceGroupName: string) {

var deferred = Q.defer<any>();
var restUrl = "https://management.azure.com/subscriptions/" + SPN.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/loadBalancers/" + name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(SPN, endpointUrl);
var restUrl = endpoint.url + "subscriptions/" + endpoint.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/loadBalancers/" + name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(endpoint, endpointUrl);

var requestHeader = {
authorization: 'Bearer ' + accessToken
Expand All @@ -92,10 +93,10 @@ export async function getLoadBalancer(SPN, endpointUrl: string, name: string, re
return deferred.promise;
}

export async function getNetworkInterface(SPN, endpointUrl, name: string, resourceGroupName: string) {
export async function getNetworkInterface(endpoint, endpointUrl, name: string, resourceGroupName: string) {
var deferred = Q.defer<any>();
var restUrl = "https://management.azure.com/subscriptions/" + SPN.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/" + name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(SPN, endpointUrl);
var restUrl = endpoint.url + "subscriptions/" + endpoint.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/" + name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(endpoint, endpointUrl);

var requestHeader = {
authorization: 'Bearer ' + accessToken
Expand Down Expand Up @@ -136,11 +137,11 @@ async function checkProvisioningState(url: string, accessToken: string) {
return deferred.promise;
}

export async function setNetworkInterface(SPN, endpointUrl: string, nic, resourceGroupName: string){
export async function setNetworkInterface(endpoint, endpointUrl: string, nic, resourceGroupName: string){

var deferred = Q.defer();
var restUrl = "https://management.azure.com/subscriptions/" + SPN.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/" + nic.name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(SPN, endpointUrl);
var restUrl = endpoint.url + "subscriptions/" + endpoint.subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/" + nic.name + "?api-version=" + azureApiVersion;
var accessToken = await getAccessToken(endpoint, endpointUrl);
var requestHeader = {
"Content-Type": "application/json; charset=utf-8",
"Authorization": 'Bearer ' + accessToken
Expand Down
2 changes: 2 additions & 0 deletions Tasks/AzureNLBManagement/nlbtask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ async function run() {
SPN["servicePrincipalKey"] = endPointAuthCreds.parameters["serviceprincipalkey"];
SPN["tenantID"] = endPointAuthCreds.parameters["tenantid"];
SPN["subscriptionId"] = tl.getEndpointDataParameter(connectedServiceName, 'subscriptionid', true);
SPN["envAuthUrl"] = tl.getEndpointDataParameter(connectedServiceName, 'environmentAuthorityUrl', true);
SPN["url"] = tl.getEndpointUrl(connectedServiceName, true);

var nicVm = await getNetworkInterface(SPN, endpointUrl, resourceGroupName);
tl.debug(`Network Interface - ${nicVm.name}'s configuration details fetched for the virtual machine ${process.env.COMPUTERNAME}`);
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureNLBManagement/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 0,
"Patch": 1
"Patch": 2
},
"minimumAgentVersion": "1.95.0",
"instanceNameFormat": "Azure Network Load Balancer: $(LoadBalancer) - $(Action)",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureNLBManagement/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 0,
"Patch": 1
"Patch": 2
},
"minimumAgentVersion": "1.95.0",
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
"loc.messages.ClientIdCannotBeEmpty": "clientId must be a non empty string.",
"loc.messages.DomainCannotBeEmpty": "domain must be a non empty string.",
"loc.messages.SecretCannotBeEmpty": "secret must be a non empty string.",
"loc.messages.armUrlCannotBeEmpty": "arm Url must be a non empty string.",
"loc.messages.authorityUrlCannotBeEmpty": "authority must be a non empty string.",
"loc.messages.CouldNotFetchAccessTokenforAzureStatusCode": "Could not fetch access token for azure. Status code: %s, status message: %s",
"loc.messages.LoadBalancerNameCannotBeNull": "'loadBalancerName cannot be null or undefined and it must be of type string.'",
"loc.messages.NetworkInterfaceNameCannotBeNull": "networkInterfaceName cannot be null or undefined and it must be of type string.",
Expand Down
2 changes: 2 additions & 0 deletions Tasks/AzureResourceGroupDeployment/Tests/addVSTSExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ process.env["__mg__internal__project__name"] = "AzureProj";
process.env[ "ENDPOINT_AUTH_AzureRM"] = "{\"parameters\":{\"serviceprincipalid\":\"id\",\"serviceprincipalkey\":\"key\",\"tenantid\":\"tenant\"},\"scheme\":\"ServicePrincipal\"}";
process.env["ENDPOINT_DATA_AzureRM_SUBSCRIPTIONID"] = "sId";
process.env["ENDPOINT_DATA_AzureRM_SUBSCRIPTIONNAME"] = "sName";
process.env["ENDPOINT_URL_AzureRM"] = "https://management.azure.com/";
process.env["ENDPOINT_DATA_AzureRM_ENVIRONMENTAUTHORITYURL"] = "https://login.windows.net/";

tr.registerMock('vsts-task-lib/toolrunner', require('vsts-task-lib/mock-toolrunner'));
tr.registerMock('./azure-rest/azure-arm-network', require('./mock_node_modules/azure-arm-network'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ tr.setInput("vstsPATToken", "PAT");
process.env[ "ENDPOINT_AUTH_AzureRM"] = "{\"parameters\":{\"serviceprincipalid\":\"id\",\"serviceprincipalkey\":\"key\",\"tenantid\":\"tenant\"},\"scheme\":\"ServicePrincipal\"}";
process.env["ENDPOINT_DATA_AzureRM_SUBSCRIPTIONID"] = "sId";
process.env["ENDPOINT_DATA_AzureRM_SUBSCRIPTIONNAME"] = "sName";
process.env["ENDPOINT_URL_AzureRM"] = "https://management.azure.com/";
process.env["ENDPOINT_DATA_AzureRM_ENVIRONMENTAUTHORITYURL"] = "https://login.windows.net/";

process.env["__mg__internal__collection__uri"] = "https://testking123.visualstudio.com";
process.env["__mg__internal__project__name"] = "AzureProj";
Expand Down
4 changes: 3 additions & 1 deletion Tasks/AzureResourceGroupDeployment/models/DeployAzureRG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export class AzureRGTaskParameters {
var servicePrincipalId: string = endpointAuth.parameters["serviceprincipalid"];
var servicePrincipalKey: string = endpointAuth.parameters["serviceprincipalkey"];
var tenantId: string = endpointAuth.parameters["tenantid"];
var credentials = new msRestAzure.ApplicationTokenCredentials(servicePrincipalId, tenantId, servicePrincipalKey);
var armUrl: string = tl.getEndpointUrl(connectedService, true);
var envAuthorityUrl: string = tl.getEndpointDataParameter(connectedService, 'environmentAuthorityUrl', true);
var credentials = new msRestAzure.ApplicationTokenCredentials(servicePrincipalId, tenantId, servicePrincipalKey, armUrl, envAuthorityUrl);
return credentials;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class ServiceClient {

this.credentials = credentials;
this.subscriptionId = subscriptionId
this.baseUri = 'https://management.azure.com';
this.baseUri = this.credentials.armUrl;
this.longRunningOperationRetryTimeout = 60; // In minutes
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ var util = require('util');

var httpObj = new httpClient.HttpCallbackClient(tl.getVariable("AZURE_HTTP_USER_AGENT"));

var authUrl = 'https://login.windows.net/';
var armUrl = 'https://management.azure.com/';
var azureApiVersion = 'api-version=2016-08-01';


export class ApplicationTokenCredentials {
private clientId: string;
private domain: string;
private secret: string;
public armUrl: string;
public authorityUrl: string;
private token_deferred: Q.Promise<string>;

constructor(clientId: string, domain: string, secret: string) {
constructor(clientId: string, domain: string, secret: string, armUrl: string, authorityUrl: string) {
if (!Boolean(clientId) || typeof clientId.valueOf() !== 'string') {
throw new Error(tl.loc("ClientIdCannotBeEmpty"));
}
Expand All @@ -30,9 +30,19 @@ export class ApplicationTokenCredentials {
throw new Error(tl.loc("SecretCannotBeEmpty"));
}

if (!Boolean(armUrl) || typeof armUrl.valueOf() !== 'string') {
throw new Error(tl.loc("armUrlCannotBeEmpty"));
}

if (!Boolean(authorityUrl) || typeof authorityUrl.valueOf() !== 'string') {
throw new Error(tl.loc("authorityUrlCannotBeEmpty"));
}

this.clientId = clientId;
this.domain = domain;
this.secret = secret;
this.armUrl = armUrl;
this.authorityUrl = authorityUrl;
}

public getToken(force?: boolean): Q.Promise<string> {
Expand All @@ -45,9 +55,9 @@ export class ApplicationTokenCredentials {

private getAuthorizationToken(): Q.Promise<string> {
var deferred = Q.defer<string>();
var authorityUrl = authUrl + this.domain + "/oauth2/token/";
var oauthTokenRequestUrl = this.authorityUrl + this.domain + "/oauth2/token/";
var requestData = querystring.stringify({
resource: 'https://management.azure.com/',
resource: this.armUrl,
client_id: this.clientId,
grant_type: "client_credentials",
client_secret: this.secret
Expand All @@ -56,8 +66,8 @@ export class ApplicationTokenCredentials {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
};

tl.debug('Requesting for Auth Token: ' + authorityUrl);
httpObj.send('POST', authorityUrl, requestData, requestHeader, (error, response, body) => {
tl.debug('Requesting for Auth Token: ' + oauthTokenRequestUrl);
httpObj.send('POST', oauthTokenRequestUrl, requestData, requestHeader, (error, response, body) => {
if (error) {
deferred.reject(error);
}
Expand Down
2 changes: 2 additions & 0 deletions Tasks/AzureResourceGroupDeployment/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@
"ClientIdCannotBeEmpty": "clientId must be a non empty string.",
"DomainCannotBeEmpty": "domain must be a non empty string.",
"SecretCannotBeEmpty": "secret must be a non empty string.",
"armUrlCannotBeEmpty": "arm Url must be a non empty string.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the plan only to add support in latest task version for ARG? I am fine with that call, but want to confirm with PMs.

"authorityUrlCannotBeEmpty": "authority must be a non empty string.",
"CouldNotFetchAccessTokenforAzureStatusCode": "Could not fetch access token for azure. Status code: %s, status message: %s",
"LoadBalancerNameCannotBeNull": "'loadBalancerName cannot be null or undefined and it must be of type string.'",
"NetworkInterfaceNameCannotBeNull": "networkInterfaceName cannot be null or undefined and it must be of type string.",
Expand Down
2 changes: 2 additions & 0 deletions Tasks/AzureResourceGroupDeployment/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@
"ClientIdCannotBeEmpty": "ms-resource:loc.messages.ClientIdCannotBeEmpty",
"DomainCannotBeEmpty": "ms-resource:loc.messages.DomainCannotBeEmpty",
"SecretCannotBeEmpty": "ms-resource:loc.messages.SecretCannotBeEmpty",
"armUrlCannotBeEmpty": "ms-resource:loc.messages.armUrlCannotBeEmpty",
"authorityUrlCannotBeEmpty": "ms-resource:loc.messages.authorityUrlCannotBeEmpty",
"CouldNotFetchAccessTokenforAzureStatusCode": "ms-resource:loc.messages.CouldNotFetchAccessTokenforAzureStatusCode",
"LoadBalancerNameCannotBeNull": "ms-resource:loc.messages.LoadBalancerNameCannotBeNull",
"NetworkInterfaceNameCannotBeNull": "ms-resource:loc.messages.NetworkInterfaceNameCannotBeNull",
Expand Down
1 change: 1 addition & 0 deletions Tasks/AzureRmWebAppDeployment/azurermwebappdeployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ async function run() {
endPoint["servicePrincipalKey"] = tl.getEndpointAuthorizationParameter(connectedServiceName, 'serviceprincipalkey', true);
endPoint["tenantID"] = tl.getEndpointAuthorizationParameter(connectedServiceName, 'tenantid', true);
endPoint["subscriptionId"] = tl.getEndpointDataParameter(connectedServiceName, 'subscriptionid', true);
endPoint["envAuthUrl"] = tl.getEndpointDataParameter(connectedServiceName, 'environmentAuthorityUrl', true);
endPoint["url"] = tl.getEndpointUrl(connectedServiceName, true);

if(deployToSlotFlag) {
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureRmWebAppDeployment/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"version": {
"Major": 3,
"Minor": 0,
"Patch": 5
"Patch": 6
},
"preview": "true",
"releaseNotes": "What's new in Version 3.0: <br/>&nbsp;&nbsp;Supports File Transformations (XDT) <br/>&nbsp;&nbsp;Supports Variable Substitutions(XML, JSON) <br/>Click [here](https://aka.ms/azurermwebdeployreadme) for more Information.",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/AzureRmWebAppDeployment/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"version": {
"Major": 3,
"Minor": 0,
"Patch": 5
"Patch": 6
},
"preview": "true",
"releaseNotes": "What's new in Version 3.0: <br/>&nbsp;&nbsp;Supports File Transformations (XDT) <br/>&nbsp;&nbsp;Supports Variable Substitutions(XML, JSON) <br/>Click [here](https://aka.ms/azurermwebdeployreadme) for more Information.",
Expand Down
12 changes: 6 additions & 6 deletions Tasks/Common/VstsAzureHelpers_/InitializeFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ function Initialize-AzureSubscription {

#Set UserAgent for Azure Calls
Set-UserAgent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you ensure Azure PowerShell task is covered as part of your testing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I have tested Azure Powershell Task

$environmentName = "AzureCloud"
if( $Endpoint.Data.Environment ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not validate if it contains an empty string with space. Please check if you want to trim it before it gets used

$environmentName = $Endpoint.Data.Environment
}

if ($Endpoint.Auth.Scheme -eq 'Certificate') {
# Certificate is only supported for the Azure module.
Expand All @@ -57,11 +62,6 @@ function Initialize-AzureSubscription {
$additional['CurrentStorageAccountName'] = $StorageAccount
}

$environmentName = "AzureCloud"
if( $Endpoint.Data.Environment ) {
$environmentName = $Endpoint.Data.Environment
}

# Set the subscription.
Write-Host "##[command]Set-AzureSubscription -SubscriptionName $($Endpoint.Data.SubscriptionName) -SubscriptionId $($Endpoint.Data.SubscriptionId) -Certificate ******** -Environment $environmentName $(Format-Splat $additional)"
Set-AzureSubscription -SubscriptionName $Endpoint.Data.SubscriptionName -SubscriptionId $Endpoint.Data.SubscriptionId -Certificate $certificate -Environment $environmentName @additional
Expand Down Expand Up @@ -127,7 +127,7 @@ function Initialize-AzureSubscription {
# Else, this is AzureRM.
try {
Write-Host "##[command]Add-AzureRMAccount -ServicePrincipal -Tenant $($Endpoint.Auth.Parameters.TenantId) -Credential $psCredential"
$null = Add-AzureRMAccount -ServicePrincipal -Tenant $Endpoint.Auth.Parameters.TenantId -Credential $psCredential
$null = Add-AzureRMAccount -ServicePrincipal -Tenant $Endpoint.Auth.Parameters.TenantId -Credential $psCredential -EnvironmentName $environmentName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to log $environmentName if it is within security rules

} catch {
# Provide an additional, custom, credentials-related error message.
Write-VstsTaskError -Message $_.Exception.Message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ foreach ($variableSet in $variableSets) {
Assert-WasCalled Set-CurrentAzureSubscription -- -SubscriptionId $endpoint.Data.SubscriptionId -StorageAccount $variableSet.StorageAccount
} else {
Assert-WasCalled Add-AzureRMAccount -ArgumentsEvaluator {
$args.Length -eq 5 -and
$args.Length -eq 7 -and
$args[0] -eq '-ServicePrincipal' -and
$args[1] -eq '-Tenant' -and
$args[2] -eq 'Some tenant ID' -and
Expand Down
Loading