Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

support for authentication using sp from auth file #2231

Merged
merged 5 commits into from
Aug 25, 2017

Conversation

amarzavery
Copy link
Contributor

@amarzavery amarzavery commented Jul 22, 2017

@amarzavery
Copy link
Contributor Author

#2225

@amarzavery amarzavery force-pushed the jsoncreds branch 3 times, most recently from dfa4c13 to 6bbc5da Compare July 24, 2017 03:43
@@ -22,11 +34,12 @@
"@types/node": "^7.0.10"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

min dependency for ms-rest should go to ^2.2.2 as the _withAuthFile() function in login.js depends on a function homeDir() added in msRest in this PR. After the CI for first commit is green will update this dep in second commit. until the ms-rest version is not published this PR will fail in the second commit due to this reason.

rpName.should.equal('Microsoft.Devices');
done();
});
it('should correctly parse the error message from service for an existing subscription where the RP was manually unregistered', (done) => {
let msg = "{\"error\":{\"code\":\"MissingSubscriptionRegistration\",\"message\":\"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.Devices'. See https://aka.ms/rps-not-found for how to register subscriptions.\"}}";
var msg = "{\"error\":{\"code\":\"MissingSubscriptionRegistration\",\"message\":\"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.Devices'. See https://aka.ms/rps-not-found for how to register subscriptions.\"}}";
Copy link
Member

Choose a reason for hiding this comment

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

is there a reason to go from let to var ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

jshint was complaining. So changed it.

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

var assert = require('assert');
Copy link
Member

Choose a reason for hiding this comment

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

const ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

should be ok for now

var dummyCreds = {
tokenAudience: undefined,
environment: {},
authorizattionScheme: 'Bearer',
Copy link
Member

Choose a reason for hiding this comment

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

typo. authorizationScheme

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for pointing

});
});

it('should add custom env to AzureEnvironment and authenticate against it', (done) => {
Copy link
Member

Choose a reason for hiding this comment

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

2 more scenarios come to mind -

  1. authfile with insufficient data (if az-cli encounters a bug while generating auth file)
  2. foreign cloud environments? not sure if this is testable with stubs, so i'll leave it to you to decide.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for 2. what i intend to test here is that: if someone wants to test against dogfood or other env that is not predefined then our code can correctly add that environment and try to authenticate using the sp info

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for 1. I have the _validateAuthFileContent that throws an error if something is incorrect.

I can add a test for that scenario.

content = fs.readFileSync(filePath, {encoding: 'utf8'});
credsObj = JSON.parse(content);
_validateAuthFileContent(credsObj, filePath);
if (!process.env[subscriptionEnvVariableName]) {
Copy link
Member

Choose a reason for hiding this comment

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

move this to outside of the try-catch. The code in its current shape reads like - read and parse a json.. if an environment variable isn't set, then set it and the flow breaks there. which makes me wonder, why read and parse at all if the env var is already set. The answer is few lines below here, where we continue to use credsObj. So, move the setting of subscription to outside the try-catch and it doesn't need a try-catch anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The environment variable that we are setting over here is the env. variable for subscriptionId. It is not the env. var for auth location. Node sdk has a recommended set of environment variables for things like subscriptionId, clientId, username, password, domain, etc.
So in this case, if the user provides his custom environment variable name that is being used in his app then we use that env. variable to set the value of subscriptionId. IF not then we set the subscriptionId to AZURE_SUBSCRIPTION_ID env. variable.
This subscription Id will be the only subscriptionId that the customer can use while instantiating the client since the SP is linked to that subscription. Using any other subscriptionId will be setting him up for failure.

I know this is a bit confusing. But whatever I said above, does that make sense or clear the initial question that you asked?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the check is incorrect. It should actually be like this:

//just set the environment variable to correct subscriptionId from the auth file if it is not present.
if (process.env[subscriptionEnvVariableName] && process.env[subscriptionEnvVariableName] !== credsObj.subscriptionId) {
  process.env[subscriptionEnvVariableName] = credsObj.subscriptionId;
}

Copy link
Contributor

@yugangw-msft yugangw-msft Jul 28, 2017

Choose a reason for hiding this comment

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

Hope I understand the context correctly, the subscription from the auth file should be precedent the environment variable. You can overwrite the environment variable here, but that should be just an implementation detail being transparent to users. Same with other fields.
If I got it right, then we don't need an if condition, just overwrite it, optionally emit out a warning if you still like users to know.

break;
}
}
if (envFound.state) {
Copy link
Member

Choose a reason for hiding this comment

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

dont think you need state field. can simply check if name is not null or empty?

let msg = `Either provide an absolute file path to the auth file or set/export the environment variable - ${azureConstants.AZURE_AUTH_LOCATION}.`;
return callback(new Error(msg));
}
filePath = authLocation;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

if the filePath is not provided then we look for the authLocation (env. var). If that is not provided as well then we throw. If it is provided then we set the value of authlocation env. var to the filePath parameter.

Copy link
Contributor

@yugangw-msft yugangw-msft left a comment

Choose a reason for hiding this comment

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

LGTM overall

if (!credsObj.sqlManagementEndpointUrl) {
throw new Error(`"sqlManagementEndpointUrl" is missing from the auth file: ${filePath}.`);
}
if (!credsObj.galleryEndpointUrl) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest we don't throw on this as this gallery endpoint is not being used by any clients, which we can consider to pulling it out in future

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

if (!credsObj.galleryEndpointUrl) {
throw new Error(`"galleryEndpointUrl" is missing from the auth file: ${filePath}.`);
}
if (!credsObj.managementEndpointUrl) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest we don't error on this as well, rather SDK should default to resourceManagerEndpointUrl for management client

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

throw new Error('callback cannot be null or undefined.');
}

let filePath = options.filePath;
Copy link
Contributor

Choose a reason for hiding this comment

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

in case it helps, will the following code simplify it?

    let filePath = options.filePath || process.env[azureConstants.AZURE_AUTH_LOCATION]` 
    if !filepath:
        return callback(new Error(...))

content = fs.readFileSync(filePath, {encoding: 'utf8'});
credsObj = JSON.parse(content);
_validateAuthFileContent(credsObj, filePath);
if (!process.env[subscriptionEnvVariableName]) {
Copy link
Contributor

@yugangw-msft yugangw-msft Jul 28, 2017

Choose a reason for hiding this comment

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

Hope I understand the context correctly, the subscription from the auth file should be precedent the environment variable. You can overwrite the environment variable here, but that should be just an implementation detail being transparent to users. Same with other fields.
If I got it right, then we don't need an if condition, just overwrite it, optionally emit out a warning if you still like users to know.

envParams.activeDirectoryResourceId = credsObj.managementEndpointUrl;
}
if (!envParams.portalUrl) {
envParams.portalUrl = 'https://portal.azure.com';
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not an environment aware url. If SDK never uses it, which I believe is the case, then maybe we just remove it from the environment

@@ -0,0 +1,12 @@
{
"clientId": "0b868e09-1547-4721-9a57-705a15328409",
"clientSecret": "005937fd-3a0f-4cf2-84da-da7388241b9f",
Copy link
Contributor

Choose a reason for hiding this comment

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

Assume this is a faked secret?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

@amarzavery
Copy link
Contributor Author

#2245 and #2247

@amarzavery amarzavery merged commit 3081f68 into Azure:master Aug 25, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants