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

Credentials fix #1090

Merged
merged 9 commits into from
Oct 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 76 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ Additional info on Azure deployment models [https://azure.microsoft.com/en-us/do
Note: x64 Ruby for Windows is known to have some compatibility issues.

# Getting Started with Azure Resource Manager Usage (Preview)

## Install the rubygem packages

You can install the azure rubygem packages directly.
Expand Down Expand Up @@ -97,6 +96,72 @@ see [Developer’s guide to auth with Azure Resource Manager API](http://aka.ms/
After creating the service principal, you should have three pieces of information, a client id (GUID), client secret
(string) and tenant id (GUID) or domain name (string).

## Prerequisite

In order to use the Azure SDK, you must supply the following values to the Azure SDK:

* Tenant Id
* Client Id
* Subscription Id
* Client Secret

You could pass the above values in the following ways:

### Option 1 - Environment Variables
You can set the (above) values using the following environment variables:

* AZURE_TENANT_ID
* AZURE_CLIENT_ID
* AZURE_SUBSCRIPTION_ID
* AZURE_CLIENT_SECRET
Copy link
Contributor

Choose a reason for hiding this comment

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

can we put simple instructions on how to set them in mac and windows? (I think we had this before)

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


To set the environment variables, in Windows, you could use the command such as:

```
set AZURE_TENANT_ID=<YOUR_TENANT_ID>
```

In Unix based systems, you could use the command such as:

```
export AZURE_TENANT_ID=<YOUR_TENANT_ID>
```

### Option 2 - Options Hash
The initialization of profile clients take an options hash as a parameter. This options hash consists of tenant_id, client_id, client_secret, subscription_id, active_directory_settings and credentials. Among these, the active_directory_settings and credentials are optional.

You can set the (above) values using the options hash:

```ruby
options = {
tenant_id: 'YOUR TENANT ID',
client_id: 'YOUR CLIENT ID',
client_secret: 'YOUR CLIENT SECRET',
subscription_id: 'YOUR SUBSCRIPTION ID'
}
```

If you would like to pass in the credentials object, you could use the the following code:

```ruby
provider = MsRestAzure::ApplicationTokenProvider.new(
'YOUR TENANT ID',
'YOUR CLIENT ID',
'YOUR CLIENT SECRET')
credentials = MsRest::TokenCredentials.new(provider)

options = {
tenant_id: 'YOUR TENANT ID',
client_id: 'YOUR CLIENT ID',
client_secret: 'YOUR CLIENT SECRET',
subscription_id: 'YOUR SUBSCRIPTION ID',
credentials: credentials
}
```

### Option 3 - Combination of Environment Variables & Options Hash
You can set the (above) values using a combination of environment variables and options hash. The values mentioned in the options hash will take precedence over the environment variables.

# Azure Multiple API versions & Profiles

With 0.15.0 of Azure SDK, multiple API versions and profiles are introduced. With these changes, each individual gem
Expand Down Expand Up @@ -150,14 +215,10 @@ The following lines should be used to instantiate a profile client:

```ruby
# Provide credentials
provider = MsRestAzure::ApplicationTokenProvider.new(
ENV['AZURE_TENANT_ID'],
ENV['AZURE_CLIENT_ID'],
ENV['AZURE_CLIENT_SECRET'])
credentials = MsRest::TokenCredentials.new(provider)

options = {
credentials: credentials,
tenant_id: ENV['AZURE_TENANT_ID'],
client_id: ENV['AZURE_CLIENT_ID'],
client_secret: ENV['AZURE_CLIENT_SECRET'],
subscription_id: ENV['AZURE_SUBSCRIPTION_ID']
}

Expand Down Expand Up @@ -195,14 +256,10 @@ The following lines should be used to instantiate a profile client:

```ruby
# Provide credentials
provider = MsRestAzure::ApplicationTokenProvider.new(
ENV['AZURE_TENANT_ID'],
ENV['AZURE_CLIENT_ID'],
ENV['AZURE_CLIENT_SECRET'])
credentials = MsRest::TokenCredentials.new(provider)

options = {
credentials: credentials,
tenant_id: ENV['AZURE_TENANT_ID'],
client_id: ENV['AZURE_CLIENT_ID'],
client_secret: ENV['AZURE_CLIENT_SECRET'],
subscription_id: ENV['AZURE_SUBSCRIPTION_ID']
}

Copy link
Contributor

Choose a reason for hiding this comment

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

would our guidelines from before profile changes not work for initializing credentials, I believe we were doing:

 provider = MsRestAzure::ApplicationTokenProvider.new(
        ENV['AZURE_TENANT_ID'],
        ENV['AZURE_CLIENT_ID'],
        ENV['AZURE_CLIENT_SECRET'])
    credentials = MsRest::TokenCredentials.new(provider)
    @client = Azure::ARM::Resources::ResourceManagementClient.new(credentials)
    @client.subscription_id = @subscription_id

If so, should we leave them as they were, just updating the namespace for ResourceManagementClient? so we demonstrate the minimum change?

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW, after this PR is done, we'd need to re-update the samples that were updated with the last release too.

Copy link
Member Author

Choose a reason for hiding this comment

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

The detailed explanation would be that we always want the user (of the SDK) to provide us with the tenant_id, client_id, client_secret and subscription_id. There is no escaping that. The credentials is just a derived value from these. The user may or may not provide it.

But, when you think about it, why would a user want to provide a derived value when he/she is supplying the original values anyway? That is the reason, I am updating the examples in readme and removed the credentials. But, if a user wants to provide it, then he is free to do that.

Copy link
Member

Choose a reason for hiding this comment

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

So... Credentials are not a bad thing to provide. This abstraction allows any token provider to be used.

Expand All @@ -226,8 +283,7 @@ purchase_plan_obj = Azure::Compute::Profiles::Latest::Mgmt::Models::PurchasePlan

## Usage of Individual gem using using specific api-version

In the previous section, we used the profile associated with individual gem. In the current section, we could use the
version directly.
In the previous section, we used the profile associated with individual gem. In the current section, we could use the version directly.

### Install

Expand All @@ -241,21 +297,18 @@ gem install 'azure_mgmt_compute'
The following lines should be used to instantiate a profile client:

```ruby
# To use this scenario, you must specify the tenant id, client id, subscription id
# and client secret using the environment variables.
# Provide credentials
provider = MsRestAzure::ApplicationTokenProvider.new(
ENV['AZURE_TENANT_ID'],
ENV['AZURE_CLIENT_ID'],
ENV['AZURE_CLIENT_SECRET'])
credentials = MsRest::TokenCredentials.new(provider)

options = {
credentials: credentials,
subscription_id: ENV['AZURE_SUBSCRIPTION_ID']
}

# Target client for 2016_03_30 version of Compute
compute_client = Azure::Compute::Mgmt::V2016_03_30::ComputeManagementClient.new(credentials)
compute_client.subscription_id = subscription_id
compute_client.subscription_id = ENV['AZURE_SUBSCRIPTION_ID']
```

The compute client could be used to access operations and models:
Expand Down
6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ namespace :arm do
# bundle exec ruby profile_generator_client.rb --dir_metadata=dir_metadata.json --profile=profiles.json
command = "#{get_base_profile_generation_cmd}#{get_profile_spec_files_folder}/#{PROFILE_METADATA[:azure_sdk]}"
execute_and_stream(command)

FileUtils.cp("#{__dir__}/generators/profilegen/src/resources/common/configurable.rb", "#{__dir__}/azure_sdk/lib/common/configurable.rb")
FileUtils.cp("#{__dir__}/generators/profilegen/src/resources/common/default.rb", "#{__dir__}/azure_sdk/lib/common/default.rb")
end

desc 'Regen individual profiles'
Expand All @@ -183,6 +186,9 @@ namespace :arm do
# bundle exec ruby profile_generator_client.rb --dir_metadata=dir_metadata.json --profile=authorization_profiles.json
command = "#{get_base_profile_generation_cmd}#{get_profile_spec_files_folder}/#{profile_spec_file}"
execute_and_stream(command)

FileUtils.cp("#{__dir__}/generators/profilegen/src/resources/common/configurable.rb", "#{__dir__}/management/#{sdk}/lib/profiles/common/configurable.rb")
FileUtils.cp("#{__dir__}/generators/profilegen/src/resources/common/default.rb", "#{__dir__}/management/#{sdk}/lib/profiles/common/default.rb")
end
end
end
Expand Down
31 changes: 22 additions & 9 deletions azure_sdk/lib/common/configurable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.

module Azure::ARM
# The Azure::ARM::Configurable module provides basic configuration for Azure ARM activities.
module Azure::Common
# The Azure::Common::Configurable module provides basic configuration for Azure activities.
module Configurable
# @return [String] Azure tenant id (also known as domain).
attr_accessor :tenant_id
Expand All @@ -25,11 +25,11 @@ module Configurable

class << self
#
# List of configurable keys for {Azure::ARM::Client}.
# List of configurable keys for {Azure::Common::Client}.
# @return [Array] of option keys.
#
def keys
@keys ||= [:tenant_id, :client_id, :client_secret, :subscription_id, :active_directory_settings, :credentials]
@keys ||= [:tenant_id, :client_id, :client_secret, :subscription_id, :active_directory_settings]
end
end

Expand All @@ -45,11 +45,23 @@ def configure
# This will also creates MsRest::TokenCredentials to be used for subsequent Azure Resource Manager clients.
#
def reset!(options = {})
Azure::ARM::Configurable.keys.each do |key|
default_value = Azure::ARM::Default.options[key]
Azure::Common::Configurable.keys.each do |key|
default_value = Azure::Common::Default.options[key]
instance_variable_set(:"@#{key}", options.fetch(key, default_value))
end

fail ArgumentError, 'tenant_id is nil' if self.tenant_id.nil?
fail ArgumentError, 'client_id is nil' if self.client_id.nil?
fail ArgumentError, 'client_secret is nil' if self.client_secret.nil?
fail ArgumentError, 'subscription_id is nil' if self.subscription_id.nil?
fail ArgumentError, 'active_directory_settings is nil' if self.active_directory_settings.nil?

default_value = MsRest::TokenCredentials.new(
MsRestAzure::ApplicationTokenProvider.new(
self.tenant_id, self.client_id, self.client_secret, self.active_directory_settings))

instance_variable_set(:"@credentials", options.fetch(:credentials, default_value))

self
end

Expand All @@ -62,11 +74,12 @@ def config
#
# configures configurable options to default values
#
def setup_options
def setup_default_options
opts = {}
Azure::ARM::Configurable.keys.map do |key|
opts[key] = Azure::ARM::Default.options[key]
Azure::Common::Configurable.keys.map do |key|
opts[key] = Azure::Common::Default.options[key]
end

opts
end
end
Expand Down
15 changes: 2 additions & 13 deletions azure_sdk/lib/common/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.

module Azure::ARM
# Default configuration options for {Azure::ARM.Client}
module Azure::Common
module Default
class << self
#
Expand Down Expand Up @@ -38,16 +37,6 @@ def subscription_id
ENV['AZURE_SUBSCRIPTION_ID']
end

#
# Default Azure credentials to authorize HTTP requests made by the service client.
# @return [MsRest::ServiceClientCredentials] Azure credentials to authorize HTTP requests made by the service client.
#
def credentials
MsRest::TokenCredentials.new(
MsRestAzure::ApplicationTokenProvider.new(
self.tenant_id, self.client_id, self.client_secret, self.active_directory_settings))
end

#
# Default Azure Active Directory Service Settings.
# @return [MsRestAzure::ActiveDirectoryServiceSettings] Azure Active Directory Service Settings.
Expand All @@ -61,7 +50,7 @@ def active_directory_settings
# @return [Hash] Configuration options.
#
def options
Hash[Azure::ARM::Configurable.keys.map{|key| [key, send(key)]}]
Hash[Azure::Common::Configurable.keys.map { |key| [key, send(key)]}]
end
end
end
Expand Down
14 changes: 2 additions & 12 deletions azure_sdk/lib/latest/latest_profile_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ module Azure::Profiles::Latest::Mgmt
# Client class for the Latest profile SDK.
#
class Client
include Azure::ARM::Configurable
include Azure::Common::Configurable

attr_reader :analysis_services, :authorization, :automation, :batch, :billing, :cdn, :cognitive_services, :commerce, :compute, :consumption, :container_instance, :container_registry, :container_service, :customer_insights, :data_lake_analytics, :data_lake_store, :dev_test_labs, :dns, :event_grid, :event_hub, :features, :graph, :iot_hub, :key_vault, :links, :locks, :logic, :machine_learning, :managed_applications, :marketplace_ordering, :media_services, :mobile_engagement, :monitor, :network, :notification_hubs, :operational_insights, :policy, :power_bi_embedded, :recovery_services, :recovery_services_backup, :recovery_services_site_recovery, :redis, :relay, :resources, :resources_management, :scheduler, :search, :server_management, :service_bus, :service_fabric, :sql, :stor_simple8000_series, :storage, :stream_analytics, :subscriptions, :traffic_manager, :web

def initialize(options = {})
if options.is_a?(Hash) && options.length == 0
@options = setup_options
@options = setup_default_options
else
@options = options
end
Expand Down Expand Up @@ -140,15 +140,5 @@ def initialize(options = {})
@web = Azure::Profiles::Latest::Web::Mgmt::WebClass.new(self)
end

def credentials
if @credentials.nil?
self.active_directory_settings ||= Azure::ARM::Default.active_directory_settings

@credentials = MsRest::TokenCredentials.new(
MsRestAzure::ApplicationTokenProvider.new(
self.tenant_id, self.client_id, self.client_secret, self.active_directory_settings))
end
@credentials
end
end
end
14 changes: 2 additions & 12 deletions azure_sdk/lib/v2017_03_09/v2017_03_09_profile_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ module Azure::Profiles::V2017_03_09::Mgmt
# Client class for the V2017_03_09 profile SDK.
#
class Client
include Azure::ARM::Configurable
include Azure::Common::Configurable

attr_reader :storage, :network, :compute, :features, :links, :locks, :policy, :resources, :subscriptions

def initialize(options = {})
if options.is_a?(Hash) && options.length == 0
@options = setup_options
@options = setup_default_options
else
@options = options
end
Expand All @@ -44,15 +44,5 @@ def initialize(options = {})
@subscriptions = Azure::Profiles::V2017_03_09::Subscriptions::Mgmt::SubscriptionsClass.new(self)
end

def credentials
if @credentials.nil?
self.active_directory_settings ||= Azure::ARM::Default.active_directory_settings

@credentials = MsRest::TokenCredentials.new(
MsRestAzure::ApplicationTokenProvider.new(
self.tenant_id, self.client_id, self.client_secret, self.active_directory_settings))
end
@credentials
end
end
end
Loading