ms-rest-azure-0.12.0/0000755000175000017500000000000013733205770013717 5ustar avronravronrms-rest-azure-0.12.0/LICENSE.txt0000644000175000017500000000210013733205770015533 0ustar avronravronrThe MIT License (MIT) Copyright (c) 2015 Microsoft Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ms-rest-azure-0.12.0/lib/0000755000175000017500000000000013733205770014465 5ustar avronravronrms-rest-azure-0.12.0/lib/ms_rest_azure/0000755000175000017500000000000013733205770017347 5ustar avronravronrms-rest-azure-0.12.0/lib/ms_rest_azure/azure_environment.rb0000644000175000017500000002703613733205770023456 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure module AzureEnvironments # # An instance of this class describes an environment in Azure # class AzureEnvironment # @return [String] the Environment name attr_reader :name # @return [String] the management portal URL attr_reader :portal_url # @return [String] the publish settings file URL attr_reader :publishing_profile_url # @return [String] the management service endpoint attr_reader :management_endpoint_url # @return [String] the resource management endpoint attr_reader :resource_manager_endpoint_url # @return [String] the sql server management endpoint for mobile commands attr_reader :sql_management_endpoint_url # @return [String] the dns suffix for sql servers attr_reader :sql_server_hostname_suffix # @return [String] the template gallery endpoint attr_reader :gallery_endpoint_url # @return [String] the Active Directory login endpoint attr_reader :active_directory_endpoint_url # @return [String] the resource ID to obtain AD tokens for attr_reader :active_directory_resource_id # @return [String] the Active Directory resource ID attr_reader :active_directory_graph_resource_id # @return [String] the Active Directory resource ID attr_reader :active_directory_graph_api_version # @return [String] the endpoint suffix for storage accounts attr_reader :storage_endpoint_suffix # @return [String] the KeyVault service dns suffix attr_reader :key_vault_dns_suffix # @return [String] the data lake store filesystem service dns suffix attr_reader :datalake_store_filesystem_endpoint_suffix # @return [String] the data lake analytics job and catalog service dns suffix attr_reader :datalake_analytics_catalog_and_job_endpoint_suffix # @return [Boolean] determines whether the authentication endpoint should be validated with Azure AD. Default value is true. attr_reader :validate_authority def initialize(options) required_properties = [:name, :portal_url, :management_endpoint_url, :resource_manager_endpoint_url, :active_directory_endpoint_url, :active_directory_resource_id] required_supplied_properties = required_properties & options.keys if required_supplied_properties.nil? || required_supplied_properties.empty? || (required_supplied_properties & required_properties) != required_properties raise ArgumentError.new("#{required_properties.to_s} are the required properties but provided properties are #{options.to_s}") end required_supplied_properties.each do |prop| if options[prop].nil? || !options[prop].is_a?(String) || options[prop].empty? raise ArgumentError.new("Value of the '#{prop}' property must be of type String and non empty.") end end # Setting default to true @validate_authority = true options.each do |k, v| instance_variable_set("@#{k}", v) unless v.nil? end end end AzureCloud = AzureEnvironments::AzureEnvironment.new({ :name => 'AzureCloud', :portal_url => 'https://portal.azure.com', :publishing_profile_url => 'http://go.microsoft.com/fwlink/?LinkId=254432', :management_endpoint_url => 'https://management.core.windows.net', :resource_manager_endpoint_url => 'https://management.azure.com/', :sql_management_endpoint_url => 'https://management.core.windows.net:8443/', :sql_server_hostname_suffix => '.database.windows.net', :gallery_endpoint_url => 'https://gallery.azure.com/', :active_directory_endpoint_url => 'https://login.microsoftonline.com/', :active_directory_resource_id => 'https://management.core.windows.net/', :active_directory_graph_resource_id => 'https://graph.windows.net/', :active_directory_graph_api_version => '2013-04-05', :storage_endpoint_suffix => '.core.windows.net', :key_vault_dns_suffix => '.vault.azure.net', :datalake_store_filesystem_endpoint_suffix => 'azuredatalakestore.net', :datalake_analytics_catalog_and_job_endpoint_suffix => 'azuredatalakeanalytics.net' }) AzureChinaCloud = AzureEnvironments::AzureEnvironment.new({ :name => 'AzureChinaCloud', :portal_url => 'https://portal.azure.cn', :publishing_profile_url => 'http://go.microsoft.com/fwlink/?LinkID=301774', :management_endpoint_url => 'https://management.core.chinacloudapi.cn', :resource_manager_endpoint_url => 'https://management.chinacloudapi.cn', :sql_management_endpoint_url => 'https://management.core.chinacloudapi.cn:8443/', :sql_server_hostname_suffix => '.database.chinacloudapi.cn', :gallery_endpoint_url => 'https://gallery.chinacloudapi.cn/', :active_directory_endpoint_url => 'https://login.chinacloudapi.cn/', :active_directory_resource_id => 'https://management.core.chinacloudapi.cn/', :active_directory_graph_resource_id => 'https://graph.chinacloudapi.cn/', :active_directory_graph_api_version => '2013-04-05', :storage_endpoint_suffix => '.core.chinacloudapi.cn', :key_vault_dns_suffix => '.vault.azure.cn', # TODO: add dns suffixes for the china cloud for datalake store and datalake analytics once they are defined. :datalake_store_filesystem_endpoint_suffix => 'N/A', :datalake_analytics_catalog_and_job_endpoint_suffix => 'N/A' }) AzureUSGovernment = AzureEnvironments::AzureEnvironment.new({ :name => 'AzureUSGovernment', :portal_url => 'https://portal.azure.us', :publishing_profile_url => 'https://manage.windowsazure.us/publishsettings/index', :management_endpoint_url => 'https://management.core.usgovcloudapi.net', :resource_manager_endpoint_url => 'https://management.usgovcloudapi.net', :sql_management_endpoint_url => 'https://management.core.usgovcloudapi.net:8443/', :sql_server_hostname_suffix => '.database.usgovcloudapi.net', :gallery_endpoint_url => 'https://gallery.usgovcloudapi.net/', :active_directory_endpoint_url => 'https://login.microsoftonline.us/', :active_directory_resource_id => 'https://management.core.usgovcloudapi.net/', :active_directory_graph_resource_id => 'https://graph.windows.net/', :active_directory_graph_api_version => '2013-04-05', :storage_endpoint_suffix => '.core.usgovcloudapi.net', :key_vault_dns_suffix => '.vault.usgovcloudapi.net', # TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined. :datalake_store_filesystem_endpoint_suffix => 'N/A', :datalake_analytics_catalog_and_job_endpoint_suffix => 'N/A' }) AzureGermanCloud = AzureEnvironments::AzureEnvironment.new({ :name => 'AzureGermanCloud', :portal_url => 'http://portal.microsoftazure.de/', :publishing_profile_url => 'https://manage.microsoftazure.de/publishsettings/index', :management_endpoint_url => 'https://management.core.cloudapi.de', :resource_manager_endpoint_url => 'https://management.microsoftazure.de', :sql_management_endpoint_url => 'https://management.core.cloudapi.de:8443/', :sql_server_hostname_suffix => '.database.cloudapi.de', :gallery_endpoint_url => 'https://gallery.cloudapi.de/', :active_directory_endpoint_url => 'https://login.microsoftonline.de/', :active_directory_resource_id => 'https://management.core.cloudapi.de/', :active_directory_graph_resource_id => 'https://graph.cloudapi.de/', :active_directory_graph_api_version => '2013-04-05', :storage_endpoint_suffix => '.core.cloudapi.de', :key_vault_dns_suffix => '.vault.microsoftazure.de', # TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined. :datalake_store_filesystem_endpoint_suffix => 'N/A', :datalake_analytics_catalog_and_job_endpoint_suffix => 'N/A' }) end end ms-rest-azure-0.12.0/lib/ms_rest_azure/azure_cli_error.rb0000644000175000017500000000046213733205770023064 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents an error with the Azure CLI. # class AzureCliError < StandardError end end ms-rest-azure-0.12.0/lib/ms_rest_azure/common/0000755000175000017500000000000013733205770020637 5ustar avronravronrms-rest-azure-0.12.0/lib/ms_rest_azure/common/default.rb0000644000175000017500000000257413733205770022620 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure::Common module Default class << self # # Default Azure Tenant Id. # @return [String] Azure Tenant Id. # def tenant_id ENV['AZURE_TENANT_ID'] end # # Default Azure Client Id. # @return [String] Azure Client Id. # def client_id ENV['AZURE_CLIENT_ID'] end # # Default Azure Client Secret. # @return [String] Azure Client Secret. # def client_secret ENV['AZURE_CLIENT_SECRET'] end # # Default Azure Subscription Id. # @return [String] Azure Subscription Id. # def subscription_id ENV['AZURE_SUBSCRIPTION_ID'] end # # Default Azure Active Directory Service Settings. # @return [MsRestAzure::ActiveDirectoryServiceSettings] Azure Active Directory Service Settings. # def active_directory_settings MsRestAzure::ActiveDirectoryServiceSettings.get_azure_settings end # # Configuration options. # @return [Hash] Configuration options. # def options Hash[MsRestAzure::Common::Configurable.keys.map { |key| [key, send(key)]}] end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/common/configurable.rb0000644000175000017500000000543513733205770023633 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure::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 # @return [String] Azure client id. attr_accessor :client_id # @return [String] Azure secret key. attr_accessor :client_secret # @return [String] Azure subscription id. attr_accessor :subscription_id # @return [MsRestAzure::ActiveDirectoryServiceSettings] Azure active directory service settings. attr_accessor :active_directory_settings # @return [MsRest::ServiceClientCredentials] credentials to authorize HTTP requests made by the service client. attr_accessor :credentials class << self # # 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] end end # # Set configuration options using a block. # def configure yield self end # # Resets the configurable options to provided options or defaults. # This will also creates MsRest::TokenCredentials to be used for subsequent Azure Resource Manager clients. # def reset!(options = {}) MsRestAzure::Common::Configurable.keys.each do |key| default_value = MsRestAzure::Common::Default.options[key] instance_variable_set(:"@#{key}", options.fetch(key, default_value)) end if(options[:credentials].nil?) # The user has not passed in the credentials. So, the SDK has to # build the credentials itself. 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, 'active_directory_settings is nil' if self.active_directory_settings.nil? self.credentials = MsRest::TokenCredentials.new( MsRestAzure::ApplicationTokenProvider.new( self.tenant_id, self.client_id, self.client_secret, self.active_directory_settings)) else self.credentials = options[:credentials] end self end def config self end private # # configures configurable options to default values # def setup_default_options opts = {} MsRestAzure::Common::Configurable.keys.map do |key| opts[key] = MsRestAzure::Common::Default.options[key] end opts end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/polling_state.rb0000644000175000017500000001137513733205770022547 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents a state of Azure long running operation. # class PollingState # @return [Net::HTTPRequest] the HTTP request. attr_accessor :request # @return the resource attr_accessor :resource # @return [Net::HTTPResponse] the HTTP response. attr_accessor :response # @return [AzureOperationError] the azure error data. attr_accessor :error_data # @return [String] the latest value captured from Azure-AsyncOperation header. attr_accessor :azure_async_operation_header_link # @return [String] the latest value captured from Location header. attr_accessor :location_header_link # @return [String] status of the long running operation. attr_accessor :status def initialize(azure_response, retry_timeout) @retry_timeout = retry_timeout @request = azure_response.request update_response(azure_response.response) @resource = azure_response.body case @response.status when 200 provisioning_state = get_provisioning_state @status = provisioning_state.nil?? (AsyncOperationStatus::SUCCESS_STATUS):provisioning_state when 201 provisioning_state = get_provisioning_state @status = provisioning_state.nil?? (AsyncOperationStatus::IN_PROGRESS_STATUS):provisioning_state when 202 @status = AsyncOperationStatus::IN_PROGRESS_STATUS when 204 @status = AsyncOperationStatus::SUCCESS_STATUS else @status = AsyncOperationStatus::FAILED_STATUS end end # # Returns the provisioning status of the resource # # @return [String] provisioning status of the resource def get_provisioning_state # On non flattened resource, we should find provisioning_state inside 'properties' if (!@resource.nil? && @resource.respond_to?(:properties) && @resource.properties.respond_to?(:provisioning_state) && !@resource.properties.provisioning_state.nil?) @resource.properties.provisioning_state # On flattened resource, we should find provisioning_state at the top level elsif !@resource.nil? && @resource.respond_to?(:provisioning_state) && !@resource.provisioning_state.nil? @resource.provisioning_state else nil end end # # Returns the amount of time in seconds for long running operation polling delay. # # @return [Integer] Amount of time in seconds for long running operation polling delay. def get_delay return @retry_timeout unless @retry_timeout.nil? if !response.nil? && !response.headers['Retry-After'].nil? return response.headers['Retry-After'].to_i end return AsyncOperationStatus::DEFAULT_DELAY end # # Updates the polling state from the fields of given response object. # @param response [Net::HTTPResponse] the HTTP response. def update_response(response) @response = response unless response.nil? @azure_async_operation_header_link = response.headers['Azure-AsyncOperation'] unless response.headers['Azure-AsyncOperation'].nil? @location_header_link = response.headers['Location'] unless response.headers['Location'].nil? end end # # returns the Azure's response. # # @return [MsRestAzure::AzureOperationResponse] Azure's response. def get_operation_response azure_response = AzureOperationResponse.new(@request, @response, @resource) azure_response end # # Composes and returns cloud error. # # @return [AzureOperationError] the cloud error. def get_operation_error AzureOperationError.new @request, @response, @error_data, "Long running operation failed with status #{@status}" end def get_request(options = {}) link = @azure_async_operation_header_link || @location_header_link options[:connection] = create_connection(options[:base_uri]) MsRest::HttpOperationRequest.new(nil, link, :get, options) end private # @return [Integer] retry timeout. attr_accessor :retry_timeout attr_accessor :connection def create_connection(base_url) @connection ||= Faraday.new(:url => base_url, :ssl => MsRest.ssl_options) do |faraday| [[MsRest::RetryPolicyMiddleware, times: 3, retry: 0.02], [:cookie_jar]].each{ |args| faraday.use(*args) } faraday.adapter Faraday.default_adapter faraday.headers = request.headers logging = ENV['AZURE_HTTP_LOGGING'] || request.log if logging faraday.response :logger, nil, { :bodies => logging == 'full' } end end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/cloud_error_data.rb0000644000175000017500000000274513733205770023214 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents keeps aux data about Azure invalid response. # class CloudErrorData # @return [String] the error code parsed from the body of the http error response. attr_accessor :code # @return [String] the error message parsed from the body of the http error response. attr_accessor :message # @return [String] the error target parsed from the body of the http error response. attr_accessor :target # @return [Array] the list of additional error info parsed from the body of the http error response. attr_accessor :additionalInfo # # Deserializes given hash into CloudErrorData object. # @param object [Hash] object to deserialize. # # @return [CloudErrorData] deserialized object. def self.deserialize_object(object) return if object.nil? output_object = CloudErrorData.new output_object.code = object['code'] output_object.message = object['message'] output_object.target = object['target'] unless object['additionalInfo'].nil? output_object.additionalInfo = [] object['additionalInfo'].each do |info| output_object.additionalInfo << MsRestAzure::TypedErrorInfo.deserialize_object(info) end end output_object end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/serialization.rb0000644000175000017500000000223713733205770022555 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # Base module for Azure Ruby serialization and deserialization. # # Provides methods to serialize Ruby object into Ruby Hash and # to deserialize Ruby Hash into Ruby object. module Serialization include MsRest::Serialization private # # Builds serializer # def build_serializer Serialization.new(self) end # # Class to handle serialization & deserialization. # class Serialization < MsRest::Serialization::Serialization # # Retrieves model of the model_name # # @param model_name [String] Name of the model to retrieve. # def get_model(model_name) begin Object.const_get(@context.class.to_s.split('::')[0...-1].join('::') + "::Models::#{model_name}") rescue NameError # Look into MsRestAzure namespace if model name not found in the ARM's models namespace Object.const_get("MsRestAzure::#{model_name}") end end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/azure_service_client.rb0000644000175000017500000003352413733205770024107 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents a point of access to the REST API. # class AzureServiceClient < MsRest::ServiceClient # @return [Integer] execution interval for long running operations. attr_accessor :long_running_operation_retry_timeout # @return [String] api version of the Azure in string format. attr_accessor :api_version def initialize(credentials, options = nil) super(credentials, options) # This is the current default for Azure services, and content-type # and accept supported by Autorest @request_headers = { 'Content-Type' => 'application/json;charset=utf-8', 'Accept' => 'application/json' } add_user_agent_information("ms_rest_azure/#{MsRestAzure::VERSION}") add_user_agent_information("Azure-SDK-For-Ruby") end # # Retrieves the result of 'POST','DELETE','PUT' or 'PATCH' operation. Performs polling of required. # @param azure_response [MsRestAzure::AzureOperationResponse] response from Azure service. # @param custom_deserialization_block [Proc] custom logic for response deserialization. # @param final_state_via [MsRestAzure::FinalStateVia] Final State via value # # @return [MsRest::HttpOperationResponse] the response. # def get_long_running_operation_result(azure_response, custom_deserialization_block, final_state_via = FinalStateVia::DEFAULT) check_for_status_code_failure(azure_response) http_method = azure_response.request.method polling_state = PollingState.new(azure_response, @long_running_operation_retry_timeout) request = azure_response.request if !AsyncOperationStatus.is_terminal_status(polling_state.status) task = Concurrent::TimerTask.new do begin if !polling_state.azure_async_operation_header_link.nil? update_state_from_azure_async_operation_header(polling_state.get_request(headers: request.headers, base_uri: request.base_uri, user_agent_extended: user_agent_extended), polling_state) elsif !polling_state.location_header_link.nil? update_state_from_location_header(polling_state.get_request(headers: request.headers, base_uri: request.base_uri, user_agent_extended: user_agent_extended), polling_state, custom_deserialization_block, final_state_via) elsif http_method === :put get_request = MsRest::HttpOperationRequest.new(request.base_uri, request.build_path.to_s, :get, {query_params: request.query_params, headers: request.headers, user_agent_extended: user_agent_extended}) update_state_from_get_resource_operation(get_request, polling_state, custom_deserialization_block) else task.shutdown if final_state_via == FinalStateVia::LOCATION if !polling_state.response.body.to_s.empty? body = JSON.load(polling_state.response.body) polling_state.resource = custom_deserialization_block.call(body) else fail AzureOperationError, 'Location header is missing from long running operation' end else fail AzureOperationError, 'Location header is missing from long running operation' end end if AsyncOperationStatus.is_terminal_status(polling_state.status) task.shutdown end rescue Exception => e task.shutdown e end end polling_delay = polling_state.get_delay polling_delay = 0.1 if polling_delay.nil? || polling_delay == 0 task.execution_interval = polling_delay task.execute task.wait_for_termination polling_error = task.value fail polling_error if polling_error.is_a?(Exception) end if AsyncOperationStatus.is_successful_status(polling_state.status) # Process long-running PUT/PATCH if (http_method === :put || http_method === :patch) && polling_state.resource.nil? get_request = MsRest::HttpOperationRequest.new(request.base_uri, request.build_path.to_s, :get, {query_params: request.query_params, headers: request.headers}) update_state_from_get_resource_operation(get_request, polling_state, custom_deserialization_block) end if final_state_via == FinalStateVia::LOCATION if((http_method === :post || http_method === :delete) && !polling_state.location_header_link.nil?) update_state_from_location_header(polling_state.get_request(headers: request.headers, base_uri: request.base_uri, user_agent_extended: user_agent_extended), polling_state, custom_deserialization_block, final_state_via) end end # Process long-running POST/DELETE operation with schema defined on success status codes if (http_method === :post || http_method === :delete) && custom_deserialization_block && polling_state.response unless polling_state.response.body.to_s.empty? body = JSON.load(polling_state.response.body) polling_state.resource = custom_deserialization_block.call(body) end end end if AsyncOperationStatus.is_failed_status(polling_state.status) fail polling_state.get_operation_error end polling_state.get_operation_response end # # Verifies for unexpected polling status code # @param azure_response [MsRestAzure::AzureOperationResponse] response from Azure service. # def check_for_status_code_failure(azure_response) fail MsRest::ValidationError, 'Azure response cannot be nil' if azure_response.nil? fail MsRest::ValidationError, 'Azure response cannot have empty response object' if azure_response.response.nil? fail MsRest::ValidationError, 'Azure response cannot have empty request object' if azure_response.request.nil? status_code = azure_response.response.status http_method = azure_response.request.method fail AzureOperationError, "Unexpected polling status code from long running operation #{status_code}" unless status_code === 200 || status_code === 202 || (status_code === 201 && http_method === :put) || (status_code === 204 && (http_method === :delete || http_method === :post)) end # # Updates polling state based on location header for PUT HTTP requests. # @param request [MsRest::HttpOperationRequest] The url retrieve data from. # @param polling_state [MsRestAzure::PollingState] polling state to update. # @param custom_deserialization_block [Proc] custom deserialization method for parsing response. # def update_state_from_get_resource_operation(request, polling_state, custom_deserialization_block) result = get_async_with_custom_deserialization(request, custom_deserialization_block) fail AzureOperationError, 'The response from long running operation does not contain a body' if result.response.body.nil? || result.response.body.empty? # On non flattened resource, we should find provisioning_state inside 'properties' if result.body.respond_to?(:properties) && result.body.properties.respond_to?(:provisioning_state) && !result.body.properties.provisioning_state.nil? polling_state.status = result.body.properties.provisioning_state # On flattened resource, we should find provisioning_state at the top level elsif result.body.respond_to?(:provisioning_state) && !result.body.provisioning_state.nil? polling_state.status = result.body.provisioning_state else polling_state.status = AsyncOperationStatus::SUCCESS_STATUS end error_data = CloudErrorData.new error_data.code = polling_state.status error_data.message = "Long running operation failed with status #{polling_state.status}" polling_state.error_data = error_data polling_state.update_response(result.response) polling_state.request = result.request polling_state.resource = result.body end # # Updates polling state based on location header for HTTP requests. # @param request [MsRest::HttpOperationRequest] The url retrieve data from. # @param polling_state [MsRestAzure::PollingState] polling state to update. # @param custom_deserialization_block [Proc] custom deserialization method for parsing response. # @param final_state_via [MsRestAzure::FinalStateVia] Final State via value # def update_state_from_location_header(request, polling_state, custom_deserialization_block, final_state_via = FinalStateVia::DEFAULT) result = get_async_with_custom_deserialization(request, custom_deserialization_block) polling_state.update_response(result.response) polling_state.request = result.request status_code = result.response.status http_method = request.method if status_code === 202 polling_state.status = AsyncOperationStatus::IN_PROGRESS_STATUS elsif status_code === 200 || (status_code === 201 && http_method === :put) || (status_code === 204 && (http_method === :delete || http_method === :post || http_method === :get)) polling_state.status = AsyncOperationStatus::SUCCESS_STATUS error_data = CloudErrorData.new error_data.code = polling_state.status error_data.message = "Long running operation failed with status #{polling_state.status}" polling_state.error_data = error_data polling_state.resource = result.body elsif final_state_via == FinalStateVia::LOCATION && status_code === 404 && http_method === :delete && !polling_state.azure_async_operation_header_link.nil? && !polling_state.location_header_link.nil? polling_state.status = AsyncOperationStatus::SUCCESS_STATUS else fail AzureOperationError, "The response from long running operation does not have a valid status code. Method: #{http_method}, Status Code: #{status_code}" end end # # Updates polling state from Azure async operation header. # @param polling_state [MsRestAzure::PollingState] polling state. # def update_state_from_azure_async_operation_header(request, polling_state) result = get_async_with_async_operation_deserialization(request) fail AzureOperationError, 'The response from long running operation does not contain a body' if result.body.nil? || result.body.status.nil? polling_state.status = result.body.status polling_state.error_data = result.body.error polling_state.response = result.response polling_state.request = result.request polling_state.resource = nil polling_state end # # Retrieves data by given URL. # @param request [MsRest::HttpOperationRequest] the URL. # @param custom_deserialization_block [Proc] function to perform deserialization of the HTTP response. # # @return [MsRest::HttpOperationResponse] the response. # def get_async_with_custom_deserialization(request, custom_deserialization_block) result = get_async_common(request) if !result.body.nil? && !custom_deserialization_block.nil? begin result.body = custom_deserialization_block.call(result.body) rescue Exception => e fail MsRest::DeserializationError.new("Error occured in deserializing the response", e.message, e.backtrace, http_response.body) end end result end # # Retrieves data by given URL. # @param request [MsRest::HttpOperationRequest] the URL. # # @return [MsRest::HttpOperationResponse] the response. # def get_async_with_async_operation_deserialization(request) result = get_async_common(request) result.body = AsyncOperationStatus.deserialize_object(result.body) result end # # Retrieves data by given URL. # @param request [MsRest::HttpOperationRequest] the URL. # # @return [MsRest::HttpOperationResponse] the response. # def get_async_common(request) fail ValidationError, 'Request cannot be nil' if request.nil? request.middlewares = [[MsRest::RetryPolicyMiddleware, times: 3, retry: 0.02], [:cookie_jar]] request.headers.merge!({'x-ms-client-request-id' => SecureRandom.uuid}) unless request.headers.key?('x-ms-client-request-id') request.headers.merge!({'Content-Type' => 'application/json'}) unless request.headers.key?('Content-Type') # Send Request http_response = request.run_promise do |req| @credentials.sign_request(req) unless @credentials.nil? end.execute.value! status_code = http_response.status if status_code != 200 && status_code != 201 && status_code != 202 && status_code != 204 json_error_data = JSON.load(http_response.body) error_data = CloudErrorData.deserialize_object(json_error_data) fail AzureOperationError.new request, http_response, error_data, "Long running operation failed with status #{status_code}" end result = MsRest::HttpOperationResponse.new(request, http_response, http_response.body) begin result.body = JSON.load(http_response.body) unless http_response.body.to_s.empty? rescue Exception => e fail MsRest::DeserializationError.new("Error occured in deserializing the response", e.message, e.backtrace, result) end result end private # # Retrieves a new instance of the AzureOperationResponse class. # @param [MsRest::HttpOperationRequest] request the HTTP request object. # @param [Faraday::Response] response the HTTP response object. # @param [String] body the HTTP response body. # @return [MsRestAzure::AzureOperationResponse] the operation response. # def create_response(request, http_response, body = nil) AzureOperationResponse.new(request, http_response, body) end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/async_operation_status.rb0000644000175000017500000000465213733205770024503 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Defines values for AsyncOperationStatus enum. # class AsyncOperationStatus ACCEPTED = 'Accepted' IN_PROGRESS_STATUS = 'InProgress' RUNNING = 'Running' SUCCESS_STATUS = 'Succeeded' FAILED_STATUS = 'Failed' CANCELED_STATUS = 'Canceled' ALL_STATUSES = [ACCEPTED, FAILED_STATUS, CANCELED_STATUS, SUCCESS_STATUS, IN_PROGRESS_STATUS, RUNNING] FAILED_STATUSES = [FAILED_STATUS, CANCELED_STATUS] TERMINAL_STATUSES = [FAILED_STATUS, CANCELED_STATUS, SUCCESS_STATUS] DEFAULT_DELAY = 30 # @return [Integer] delay in seconds which should be used for polling for result of async operation. attr_accessor :retry_after # @return [MsRestAzure::CloudErrorData] error information about async operation. attr_accessor :error # @return [Stirng] status of polling. attr_accessor :status # # Checks if given status is terminal one. # @param status [String] status to verify # # @return [Boolean] True if given status is terminal one, false otherwise. def self.is_terminal_status(status) TERMINAL_STATUSES.any? { |st| st.casecmp(status) == 0 } end # # Checks if given status is failed one. # @param status [String] status to verify # # @return [Boolean] True if given status is failed one, false otherwise. def self.is_failed_status(status) FAILED_STATUSES.any? { |st| st.casecmp(status) == 0 } end # # Checks if given status is successful one. # @param status [String] status to verify # # @return [Boolean] True if given status is successful one, false otherwise. def self.is_successful_status(status) return (status.casecmp(SUCCESS_STATUS) == 0) end # # Deserializes given hash into AsyncOperationStatus object. # @param object [Hash] object to deserialize. # # @return [AsyncOperationStatus] deserialized object. def self.deserialize_object(object) return if object.nil? output_object = AsyncOperationStatus.new output_object.status = object['status'] output_object.error = CloudErrorData.deserialize_object(object['error']) output_object.retry_after = Integer(object['retryAfter']) unless object['retryAfter'].nil? output_object end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/azure_operation_response.rb0000644000175000017500000000117013733205770025017 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents the data received and deserialized from Azure service. # class AzureOperationResponse < MsRest::HttpOperationResponse # @return [String] identificator of the request. attr_accessor :request_id # @return [String] Correlation Id of the request. attr_accessor :correlation_request_id # @return [String] Client Request Id of the request. attr_accessor :client_request_id end end ms-rest-azure-0.12.0/lib/ms_rest_azure/typed_error_info.rb0000644000175000017500000000162113733205770023245 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents the error type and information. # class TypedErrorInfo # @return [String] the error type parsed from the body of the http error response. attr_accessor :type # @return [Object] the error info parsed from the body of the http error response. attr_accessor :info # # Deserializes given hash into TypedErrorInfo object. # @param object [Hash] object to deserialize. # # @return [TypedErrorInfo] deserialized object. def self.deserialize_object(object) return if object.nil? output_object = TypedErrorInfo.new output_object.type = object['type'] output_object.info = object['info'] output_object end end endms-rest-azure-0.12.0/lib/ms_rest_azure/version.rb0000644000175000017500000000033213733205770021357 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure VERSION = '0.12.0' end ms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/0000755000175000017500000000000013733205770021644 5ustar avronravronrms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/azure_cli_token_provider.rb0000644000175000017500000000570213733205770027264 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. require 'time' module MsRestAzure # # Class that provides access to access tokens generated by the azure cli. # class AzureCliTokenProvider < MsRest::TokenProvider private # @return [String] the type of token. attr_reader :cli_path # @return [ActiveDirectoryServiceSettings] settings. attr_accessor :settings # @return [String] auth token. attr_accessor :token # @return [Time] the date when the current token expires. attr_accessor :token_expires_on # @return [Integer] the amount of time we refresh token before it expires. attr_reader :expiration_threshold # @return [String] the type of token. attr_reader :token_type public # # Creates and initialize new instance of the AzureCliTokenProvider class. # @param settings [ActiveDirectoryServiceSettings] active directory setting. def initialize(settings = ActiveDirectoryServiceSettings.get_azure_settings) fail ArgumentError, 'Azure AD settings cannot be nil' if settings.nil? raise AzureCliError, 'Azure CLI is not installed' unless locate_azure_cli @settings = settings @expiration_threshold = 5 * 60 end # # Gets an authentication header string using an access token from the Azure cli # @param settings [ActiveDirectoryServiceSettings] active directory settings. # # @return [String] The authenticaiton header string def get_authentication_header acquire_token if token_expired? "#{token_type} #{token}" end private # # Checks whether token is about to expire. # # @return [Bool] True if token is about to expire, false otherwise. def token_expired? @token.nil? || Time.now >= @token_expires_on + expiration_threshold end # # Checks if the Azure CLI is installed # # @return [Boolean] Does the az command exist on the path def locate_azure_cli exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each do |ext| executable = File.join(path, "az#{ext}") return @cli_path = executable if File.executable?(executable) && !File.directory?(executable) end end return nil end # # Acquires a new access token from teh azure CLI # # @return [String] The access token to the desired resource def acquire_token() response_body = JSON.load(`#{cli_path} account get-access-token -o json --resource #{@settings.token_audience}`) @token_expires_on = Time.parse(response_body['expiresOn']) @token_type = response_body['tokenType'] @token = response_body['accessToken'] rescue raise AzureCliError, 'Error acquiring token from the Azure CLI' end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/application_token_provider.rb0000644000175000017500000001014213733205770027604 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class that provides access to authentication token. # class ApplicationTokenProvider < MsRest::TokenProvider private TOKEN_ACQUIRE_URL = '{authentication_endpoint}{tenant_id}/oauth2/token' REQUEST_BODY_PATTERN = 'resource={resource_uri}&client_id={client_id}&client_secret={client_secret}&grant_type=client_credentials' DEFAULT_SCHEME = 'Bearer' # @return [ActiveDirectoryServiceSettings] settings. attr_accessor :settings # @return [String] tenant id (also known as domain). attr_accessor :tenant_id # @return [String] application id. attr_accessor :client_id # @return [String] application secret key. attr_accessor :client_secret # @return [String] auth token. attr_writer :token # @return [Time] the date when the current token expires. attr_writer :token_expires_on # @return [Integer] the amount of time we refresh token before it expires. attr_reader :expiration_threshold public # @return [Time] the date when the current token expires. attr_reader :token_expires_on # @return [String] the type of token. attr_reader :token_type # @return [String] auth token. attr_reader :token # # Creates and initialize new instance of the ApplicationTokenProvider class. # @param tenant_id [String] tenant id (also known as domain). # @param client_id [String] client id. # @param client_secret [String] client secret. # @param settings [ActiveDirectoryServiceSettings] active directory setting. def initialize(tenant_id, client_id, client_secret, settings = ActiveDirectoryServiceSettings.get_azure_settings) fail ArgumentError, 'Tenant id cannot be nil' if tenant_id.nil? fail ArgumentError, 'Client id cannot be nil' if client_id.nil? fail ArgumentError, 'Client secret key cannot be nil' if client_secret.nil? fail ArgumentError, 'Azure AD settings cannot be nil' if settings.nil? @tenant_id = tenant_id @client_id = client_id @client_secret = client_secret @settings = settings @expiration_threshold = 5 * 60 end # # Returns the string value which needs to be attached # to HTTP request header in order to be authorized. # # @return [String] authentication headers. def get_authentication_header acquire_token if token_expired "#{token_type} #{token}" end private # # Checks whether token is about to expire. # # @return [Bool] True if token is about to expire, false otherwise. def token_expired @token.nil? || Time.now >= @token_expires_on + expiration_threshold end # # Retrieves a new authentication token. # # @return [String] new authentication token. def acquire_token token_acquire_url = TOKEN_ACQUIRE_URL.dup token_acquire_url['{authentication_endpoint}'] = @settings.authentication_endpoint token_acquire_url['{tenant_id}'] = @tenant_id url = URI.parse(token_acquire_url) connection = Faraday.new(:url => url, :ssl => MsRest.ssl_options) do |builder| builder.adapter Faraday.default_adapter end request_body = REQUEST_BODY_PATTERN.dup request_body['{resource_uri}'] = ERB::Util.url_encode(@settings.token_audience) request_body['{client_id}'] = ERB::Util.url_encode(@client_id) request_body['{client_secret}'] = ERB::Util.url_encode(@client_secret) response = connection.get do |request| request.headers['content-type'] = 'application/x-www-form-urlencoded' request.body = request_body end fail AzureOperationError, 'Couldn\'t login to Azure, please verify your tenant id, client id and client secret' unless response.status == 200 response_body = JSON.load(response.body) @token = response_body['access_token'] @token_expires_on = Time.at(Integer(response_body['expires_on'])) @token_type = response_body['token_type'] end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/cognitive_services_credentials.rb0000644000175000017500000000257213733205770030446 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class that provides access to authentication token. # class CognitiveServicesCredentials < MsRest::ServiceClientCredentials private # @return [String] the subscription key attr_reader :subscription_key public # # Creates and initialize new instance of the CognitiveServicesCredentials class. # @param subscription_key [String] subscription key def initialize(subscription_key) fail ArgumentError, 'Subscription key cannot be nil' if subscription_key.nil? fail ArgumentError, 'Subscription key must be of type string' if subscription_key.class.to_s != 'String' @subscription_key = subscription_key end def sign_request(request) super(request) if (request.respond_to?(:request_headers)) request.request_headers['Ocp-Apim-Subscription-Key'] = @subscription_key request.request_headers['X-BingApis-SDK-Client'] = 'ruby-SDK' elsif request.respond_to?(:headers) request.headers['Ocp-Apim-Subscription-Key'] = @subscription_key request.headers['X-BingApis-SDK-Client'] = 'ruby-SDK' else fail ArgumentError, 'Incorrect request object was provided' end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/msi_token_provider.rb0000644000175000017500000002051213733205770026073 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class that provides access to authentication token via Managed Service Identity. # class MSITokenProvider < MsRest::TokenProvider private TOKEN_ACQUIRE_URL = 'http://localhost:{port}/oauth2/token' REQUEST_BODY_PATTERN = 'resource={resource_uri}' USER_ASSIGNED_IDENTITY = '{id_type}={user_assigned_identity}' DEFAULT_SCHEME = 'Bearer' IMDS_TOKEN_ACQUIRE_URL = 'http://169.254.169.254/metadata/identity/oauth2/token' # @return [MSIActiveDirectoryServiceSettings] settings. attr_accessor :settings # @return [Integer] port number where MSI service is running. attr_accessor :port # @return [String] client id for user assigned managed identity attr_accessor :client_id # @return [String] object id for user assigned managed identity attr_accessor :object_id # @return [String] ms_res id for user assigned managed identity attr_accessor :msi_res_id # @return [String] auth token. attr_writer :token # @return [Time] the date when the current token expires. attr_writer :token_expires_on # @return [Integer] the amount of time we refresh token before it expires. attr_reader :expiration_threshold public # @return [Time] the date when the current token expires. attr_reader :token_expires_on # @return [String] the type of token. attr_reader :token_type # @return [String] auth token. attr_reader :token # # Creates and initialize new instance of the MSITokenProvider class. # @param port [Integer] port number where MSI service is running. # @param settings [ActiveDirectoryServiceSettings] active directory setting. # @param msi_id [Hash] MSI id for user assigned managed service identity, # msi_id = {'client_id': 'client id of user assigned identity'} # or # msi_id = {'object_id': 'object id of user assigned identity'} # or # msi_id = {'msi_rest_id': 'resource id of user assigned identity'} # The above key,value pairs are mutually exclusive. def initialize(port = 50342, settings = ActiveDirectoryServiceSettings.get_azure_settings, msi_id = nil) fail ArgumentError, 'Azure AD settings cannot be nil' if settings.nil? fail ArgumentError, 'msi_id must include either client_id, object_id or msi_res_id exclusively' if (!msi_id.nil? && msi_id.length > 1) warn "The 'port' argument is no longer used, and will be removed in a future release" if port != 50342 @port = port @settings = settings if !msi_id.nil? @client_id = msi_id[:client_id] unless msi_id[:client_id].nil? @object_id = msi_id[:object_id] unless msi_id[:object_id].nil? @msi_res_id = msi_id[:msi_res_id] unless msi_id[:msi_res_id].nil? end @expiration_threshold = 5 * 60 end # # Returns the string value which needs to be attached # to HTTP request header in order to be authorized. # # @return [String] authentication headers. def get_authentication_header if !ENV['MSI_VM'].nil? && ENV['MSI_VM'].downcase == 'true' acquire_token if token_expired else acquire_token_from_imds_with_retry if token_expired end "#{token_type} #{token}" end private def append_header(name, value) "#{name}=#{value}" end def acquire_token_from_imds_with_retry token_acquire_url = IMDS_TOKEN_ACQUIRE_URL.dup + "?" + append_header('resource', ERB::Util.url_encode(@settings.token_audience)) + '&' + append_header('api-version', '2018-02-01') token_acquire_url = (token_acquire_url + '&' + append_header('client_id', ERB::Util.url_encode(@client_id))) unless @client_id.nil? token_acquire_url = (token_acquire_url + '&' + append_header('object_id', ERB::Util.url_encode(@object_id))) unless @object_id.nil? token_acquire_url = (token_acquire_url + '&' + append_header('msi_res_id', ERB::Util.url_encode(@msi_res_id))) unless @msi_res_id.nil? url = URI.parse(token_acquire_url) connection = Faraday.new(:url => url, :ssl => MsRest.ssl_options) do |builder| builder.adapter Faraday.default_adapter end retry_value = 1 max_retry = 20 response = nil user_defined_time_limit = ENV['USER_DEFINED_IMDS_MAX_RETRY_TIME'].nil? ? 104900:ENV['USER_DEFINED_IMDS_MAX_RETRY_TIME'] total_wait = 0 slots = [] (0..max_retry-1).each do |i| slots << (100 * ((2 << i) - 1) /1000.to_f) end while retry_value <= max_retry && total_wait < user_defined_time_limit response = connection.get do |request| request.headers['Metadata'] = 'true' request.headers['User-Agent'] = "Azure-SDK-For-Ruby/ms_rest_azure/#{MsRestAzure::VERSION}" end if response.status == 410 || response.status == 429 || response.status == 404 || (response.status > 499 && response.status < 600) puts slots.inspect wait = slots[0..retry_value].sample wait = wait < 1 ? 3 : wait wait = (response.status == 410 && wait < 70) ? 70 : wait retry_value += 1 if (retry_value > max_retry) break end wait = wait > user_defined_time_limit ? user_defined_time_limit : wait sleep(wait) total_wait += wait elsif response.status != 200 fail AzureOperationError, "Couldn't acquire access token from Managed Service Identity, please verify your tenant id, port and settings" else break end end if retry_value > max_retry fail AzureOperationError, "MSI: Failed to acquire tokens after #{max_retry} times" end response_body = JSON.load(response.body) @token = response_body['access_token'] @token_expires_on = Time.at(Integer(response_body['expires_on'])) @token_type = response_body['token_type'] end # # Checks whether token is about to expire. # # @return [Bool] True if token is about to expire, false otherwise. def token_expired @token.nil? || Time.now >= @token_expires_on + expiration_threshold end # # Retrieves a new authentication token. # # @return [String] new authentication token. def acquire_token token_acquire_url = TOKEN_ACQUIRE_URL.dup token_acquire_url['{port}'] = @port.to_s url = URI.parse(token_acquire_url) connection = Faraday.new(:url => url, :ssl => MsRest.ssl_options) do |builder| builder.adapter Faraday.default_adapter end request_body = REQUEST_BODY_PATTERN.dup request_body['{resource_uri}'] = ERB::Util.url_encode(@settings.token_audience) request_body = set_msi_id(request_body, 'client_id', @client_id) unless @client_id.nil? request_body = set_msi_id(request_body, 'object_id', @object_id) unless @object_id.nil? request_body = set_msi_id(request_body, 'msi_res_id', @msi_res_id) unless @msi_res_id.nil? response = connection.post do |request| request.headers['content-type'] = 'application/x-www-form-urlencoded' request.headers['Metadata'] = 'true' request.body = request_body end fail AzureOperationError, 'Couldn\'t acquire access token from Managed Service Identity, please verify your tenant id, port and settings' unless response.status == 200 response_body = JSON.load(response.body) @token = response_body['access_token'] @token_expires_on = Time.at(Integer(response_body['expires_on'])) @token_type = response_body['token_type'] end # # Sets user assigned identity value in request body # @param request_body [String] body of the request used to acquire token # @param id_type [String] type of id to send 'client_id', 'object_id' or 'msi_res_id' # @param id_value [String] id of the user assigned identity # # @return [String] new request body with the addition of =. def set_msi_id(request_body, id_type, id_value) user_assigned_identity = USER_ASSIGNED_IDENTITY.dup request_body = [request_body, user_assigned_identity].join(',') request_body['{id_type}'] = id_type request_body['{user_assigned_identity}'] = ERB::Util.url_encode(id_value) return request_body end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/credentials/topic_credentials.rb0000644000175000017500000000214713733205770025670 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class that provides access to authentication token. # class TopicCredentials < MsRest::ServiceClientCredentials private # @return [String] the topic key attr_reader :topic_key public # # Creates and initialize new instance of the TopicCredentials class. # @param topic_key [String] topic key def initialize(topic_key) fail ArgumentError, 'Topic key cannot be nil' if topic_key.nil? fail ArgumentError, 'Topic key must be of type string' if topic_key.class.to_s != 'String' @topic_key = topic_key end def sign_request(request) super(request) if (request.respond_to?(:request_headers)) request.request_headers['aeg-sas-key'] = @topic_key elsif request.respond_to?(:headers) request.headers['aeg-sas-key'] = @topic_key else fail ArgumentError, 'Incorrect request object was provided' end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/azure_operation_error.rb0000644000175000017500000000245113733205770024315 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents an Azure error. # class AzureOperationError < MsRest::HttpOperationError # @return [String] the error message. attr_accessor :error_message # @return [String] the error code. attr_accessor :error_code # # Creates and initialize new instance of the AzureOperationError class. # @param [Hash] the HTTP request data (uri, body, headers). # @param [Faraday::Response] the HTTP response object. # @param [String] body the HTTP response body. # @param [String] error message. # def initialize(*args) super(*args) # Try to parse @body to find useful error message and code # Body should meet the error condition response requirements for Microsoft REST API Guidelines # https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#7102-error-condition-responses begin unless @body.nil? @error_message = @body['error']['message'] @error_code = @body['error']['code'] @msg = "#{@msg}: #{@error_code}: #{@error_message}" end rescue end end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/active_directory_service_settings.rb0000644000175000017500000000425113733205770026675 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents an settings for Azure AD authentication. # class ActiveDirectoryServiceSettings # @return [String] auth token. attr_accessor :authentication_endpoint # @return [String] auth token. attr_accessor :token_audience # # Returns a set of properties required to login into regular Azure cloud. # # @return [ActiveDirectoryServiceSettings] settings required for authentication. def self.get_azure_settings get_settings(MsRestAzure::AzureEnvironments::AzureCloud) end # # Returns a set of properties required to login into Azure China cloud. # # @return [ActiveDirectoryServiceSettings] settings required for authentication. def self.get_azure_china_settings get_settings(MsRestAzure::AzureEnvironments::AzureChinaCloud) end # # Returns a set of properties required to login into Azure German Cloud. # # @return [ActiveDirectoryServiceSettings] settings required for authentication. def self.get_azure_german_settings get_settings(MsRestAzure::AzureEnvironments::AzureGermanCloud) end # # Returns a set of properties required to login into Azure US Government. # # @return [ActiveDirectoryServiceSettings] settings required for authentication. def self.get_azure_us_government_settings get_settings(MsRestAzure::AzureEnvironments::AzureUSGovernment) end private # # Returns a set of properties required to login into Azure Cloud. # # @param azure_environment [AzureEnvironment] An instance of AzureEnvironment. # @return [ActiveDirectoryServiceSettings] settings required for authentication. def self.get_settings(azure_environment = MsRestAzure::AzureEnvironments::Azure) settings = ActiveDirectoryServiceSettings.new settings.authentication_endpoint = azure_environment.active_directory_endpoint_url settings.token_audience = azure_environment.active_directory_resource_id settings end end end ms-rest-azure-0.12.0/lib/ms_rest_azure/final_state_via.rb0000644000175000017500000000063013733205770023023 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. module MsRestAzure # # Class which represents a final state via of Azure long running operation. # class FinalStateVia NONE = -1 DEFAULT = 0 AZURE_ASYNC_OPERATION = 0 LOCATION = 1 ORIGINAL_URI = 2 end endms-rest-azure-0.12.0/lib/ms_rest_azure.rb0000644000175000017500000000257413733205770017704 0ustar avronravronr# encoding: utf-8 # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. require 'ms_rest' require 'ms_rest_azure/active_directory_service_settings.rb' require 'ms_rest_azure/async_operation_status.rb' require 'ms_rest_azure/azure_environment.rb' require 'ms_rest_azure/azure_operation_error.rb' require 'ms_rest_azure/azure_operation_response.rb' require 'ms_rest_azure/azure_service_client.rb' require 'ms_rest_azure/cloud_error_data.rb' require 'ms_rest_azure/final_state_via.rb' require 'ms_rest_azure/credentials/application_token_provider.rb' require 'ms_rest_azure/credentials/cognitive_services_credentials.rb' require 'ms_rest_azure/credentials/topic_credentials.rb' require 'ms_rest_azure/credentials/msi_token_provider.rb' require 'ms_rest_azure/credentials/azure_cli_token_provider.rb' require 'ms_rest_azure/azure_cli_error.rb' require 'ms_rest_azure/polling_state.rb' require 'ms_rest_azure/serialization.rb' require 'ms_rest_azure/typed_error_info.rb' require 'ms_rest_azure/version' require 'ms_rest_azure/common/configurable' require 'ms_rest_azure/common/default' module MsRestAzure end module MsRestAzure::Serialization end module MsRestAzure::AzureEnvironments end module MsRestAzure::Common end module MsRestAzure::Common::Configurable end module MsRestAzure::Common::Default end ms-rest-azure-0.12.0/README.md0000644000175000017500000000532213733205770015200 0ustar avronravronr# Intro MsRestAzure is a library which supports the Azure clients (SDKs) generated with Autorest tool. It contains core logic and helper classes for error handling and authentication. Also it includes azure specific logic like long polling functionality and Azure application authentication. Usually it is not supposed to be used as a standalone gem but only as a dependency for generated client gems. # Supported Ruby Versions * Ruby 2.0 * Ruby 2.1 * Ruby 2.2 Note: x64 Ruby for Windows is known to have some compatibility issues. # Installation install the appropriate gem: ``` gem install ms_rest_azure ``` and reference it in your code: ```Ruby require 'ms_rest_azure' ``` # Running tests MsRestAzure has only unit tests which doesn't require any preparation, just run 'rspec' command from the gem directory. # Contribution To start working on the gem the only additional dev dependecy is required - rspec. After you've added a new feature and all specs pass - you're good to go with PR. But before starting any bug/feature - please make sure you've thoroughly discussed it with repository maintainers. This gem already powers a few SDKs and backward compatibility should taken in account. # Adding gem to you generated SDK Reference it in the gemfile and also add this line to your client's gemspec file: ```ruby spec.add_runtime_dependency 'ms_rest_azure', '~> 0.11.1' ``` Don't forget to correct the version. # Utilizing MSI(Managed Service Identity) Token Provider MSI support has been enabled in `ms_rest_azure` version `0.9.0`. Below code snippet demonstrates how to use MSITokenProvider with default port `50342`: ```ruby provider = MsRestAzure::MSITokenProvider.new() credentials = MsRest::TokenCredentials.new(provider) ``` **Note**: As of 04/04/2018, there are 2 supported ways to get MSI Token. 1. Using the extension installed locally and accessing http://localhost:50342/oauth2/token to get the MSI Token 2. Accessing the http://169.254.169.254/metadata/identity/oauth2/token to get the MSI Token (default) Usually, you do not have to worry about the way you get the MSI token. If you would like to access the token specifically using the first approach, then set the environment variable 'MSI_VM' to true. # Utilizing Telemetry Extension in your SDK We encourage the customer of ms_rest_azure library to provide information about their product sent via telemetry extension point as below: ```ruby additional_user_agent_information = 'fog-azure-rm/0.2.0' # Refer https://github.com/Azure/azure-sdk-for-ruby/issues/517 for more info. azure_service_client.add_user_agent_information(additional_user_agent_information) ``` # Provide feedback Send email to the azsdkteam@microsoft.com or file new issue in this repository. ms-rest-azure-0.12.0/ms_rest_azure.gemspec0000644000175000017500000000674513733205770020162 0ustar avronravronr######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: ms_rest_azure 0.12.0 ruby lib Gem::Specification.new do |s| s.name = "ms_rest_azure".freeze s.version = "0.12.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://github.com/Azure/azure-sdk-for-ruby/issues", "changelog_uri" => "https://github.com/Azure/azure-sdk-for-ruby/blob/master/runtime/ms_rest_azure/CHANGELOG.md", "documentation_uri" => "https://azure.microsoft.com/en-us/develop/ruby/", "homepage_uri" => "https://aka.ms/azure-sdk-for-ruby", "source_code_uri" => "https://github.com/Azure/azure-sdk-for-ruby/tree/ms_rest_azure-v0.12.0" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Microsoft Corporation".freeze] s.date = "2020-05-21" s.description = "Azure Client Library for Ruby.".freeze s.email = "azsdkteam@microsoft.com".freeze s.files = ["CHANGELOG.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "lib/ms_rest_azure.rb".freeze, "lib/ms_rest_azure/active_directory_service_settings.rb".freeze, "lib/ms_rest_azure/async_operation_status.rb".freeze, "lib/ms_rest_azure/azure_cli_error.rb".freeze, "lib/ms_rest_azure/azure_environment.rb".freeze, "lib/ms_rest_azure/azure_operation_error.rb".freeze, "lib/ms_rest_azure/azure_operation_response.rb".freeze, "lib/ms_rest_azure/azure_service_client.rb".freeze, "lib/ms_rest_azure/cloud_error_data.rb".freeze, "lib/ms_rest_azure/common/configurable.rb".freeze, "lib/ms_rest_azure/common/default.rb".freeze, "lib/ms_rest_azure/credentials/application_token_provider.rb".freeze, "lib/ms_rest_azure/credentials/azure_cli_token_provider.rb".freeze, "lib/ms_rest_azure/credentials/cognitive_services_credentials.rb".freeze, "lib/ms_rest_azure/credentials/msi_token_provider.rb".freeze, "lib/ms_rest_azure/credentials/topic_credentials.rb".freeze, "lib/ms_rest_azure/final_state_via.rb".freeze, "lib/ms_rest_azure/polling_state.rb".freeze, "lib/ms_rest_azure/serialization.rb".freeze, "lib/ms_rest_azure/typed_error_info.rb".freeze, "lib/ms_rest_azure/version.rb".freeze] s.homepage = "https://aka.ms/ms_rest_azure".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.0.0".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "Azure Client Library for Ruby.".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_runtime_dependency(%q.freeze, ["~> 1.0"]) s.add_runtime_dependency(%q.freeze, [">= 0.9", "< 2.0.0"]) s.add_runtime_dependency(%q.freeze, ["~> 0.0.6"]) s.add_runtime_dependency(%q.freeze, ["~> 0.7.6"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, ["~> 3.3"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 1.0"]) s.add_dependency(%q.freeze, [">= 0.9", "< 2.0.0"]) s.add_dependency(%q.freeze, ["~> 0.0.6"]) s.add_dependency(%q.freeze, ["~> 0.7.6"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, ["~> 3.3"]) end end ms-rest-azure-0.12.0/CHANGELOG.md0000644000175000017500000001623313733205770015535 0ustar avronravronr##2020.05.21 ms_rest_azure version 0.12.0 * Unpin unf_ext dependency version. * Update active_directory_endpoint_url in US Cloud. ##2020.03.05 ms_rest_azure version 0.11.2 * Added Azure CLI Token provider. * Update faraday version to allow 1.0.0. * Expose token expires properties to users. ##2019.05.14 ms_rest_azure version 0.11.1 * Set unf_ext dependency version to 0.0.7.2. This change has been done to accommodate the changes made to unf_ext. Refer [Issue #604](https://github.com/meew0/discordrb/issues/604) for further details. * Added correlation_request_id & client_request_id to AzureOperationResponse. ##2018.07.31 ms_rest_azure version 0.11.0 * Added USER_DEFINED_IMDS_MAX_RETRY_TIME to msi_token_provider. Refer [PR #1539](https://github.com/Azure/azure-sdk-for-ruby/pull/1539) and [Issue #1344](https://github.com/Azure/azure-sdk-for-ruby/issues/1344) for further details. * Modified Long Running Operation Logic to make final calls based on Final State Via value. Refer [PR #1537](https://github.com/Azure/azure-sdk-for-ruby/pull/1537) for further details. ##2018.06.08 ms_rest_azure version 0.10.8 * Added case insensitive comparison to Operation status. ##2018.05.16 ms_rest_azure version 0.10.7 * Added new error code 410 for IMDS Support for MSI Token Provider class. ##2018.04.16 ms_rest_azure version 0.10.6 * Added encoding of client id, object id and msi_id in the MSI Token provider class. Refer[PR #1288](https://github.com/Azure/azure-sdk-for-ruby/pull/1288) for further details. ##2018.04.16 ms_rest_azure version 0.10.5 * Added new error codes for IMDS Support for MSI Token Provider class. Refer [PR #1286](https://github.com/Azure/azure-sdk-for-ruby/pull/1286) and [Issue #1285](https://github.com/Azure/azure-sdk-for-ruby/issues/1285) for further details. ##2018.04.04 ms_rest_azure version 0.10.4 * Added IMDS Support for MSI Token Provider class. Refer [PR #1282](https://github.com/Azure/azure-sdk-for-ruby/pull/1282) for further details. ##2018.02.06 ms_rest_azure version 0.10.3 * Removed subscription_id check from configurable. Refer [PR# 1261](https://github.com/Azure/azure-sdk-for-ruby/pull/1261) for further details. ##2018.01.30 ms_rest_azure version 0.10.2 * Added CognitiveServicesCredentials class for the cognitive services data plane SDK. Refer [PR #1257](https://github.com/Azure/azure-sdk-for-ruby/pull/1257) for further details. * Added TopicCredentials class for the event grid data plane SDK. Refer [PR #1257](https://github.com/Azure/azure-sdk-for-ruby/pull/1257) for further details. ##2017.12.19 ms_rest_azure version 0.10.1 * Added support for user assigned identity to MSITokenProvider Modified portal URLs for Azure cloud environments. Refer [Issue #1175](https://github.com/Azure/azure-sdk-for-ruby/issues/1175) for further details. ##2017.11.10 ms_rest_azure version 0.10.0 * Modified portal URLs for Azure cloud environments. Refer [PR #1106](https://github.com/Azure/azure-sdk-for-ruby/pull/1106) for further details. * [Breaking Change] Removed Resource and SubResource classes. Refer [PR #1106](https://github.com/Azure/azure-sdk-for-ruby/pull/1106) for further details. * Added Configurable and Default classes to be used by the profile gems. Refer [PR #1111](https://github.com/Azure/azure-sdk-for-ruby/pull/1111) for further details. ##2017.09.11 ms_rest_azure version 0.9.0 * [Breaking Change] Managed Service Identity authentication to acquire token does not require `tenant_id`.[Issue #930](https://github.com/Azure/azure-sdk-for-ruby/issues/930) [PR #931](https://github.com/Azure/azure-sdk-for-ruby/pull/931) ##2017.08.28 ms_rest_azure version 0.8.2 * Enable Managed Service Identity authentication features into ms_rest_azure runtime for azure_mgmt_* sdks.[Issue #884](https://github.com/Azure/azure-sdk-for-ruby/issues/884) [PR #889](https://github.com/Azure/azure-sdk-for-ruby/pull/889) ##2017.07.10 ms_rest_azure version 0.8.1 * [Bug Fix] Fixed the issue with the polling status object to handle the response code and provisioning status correctly.[Issue #817](https://github.com/Azure/azure-sdk-for-ruby/issues/817) [PR #828](https://github.com/Azure/azure-sdk-for-ruby/pull/828) ##2017.06.30 ms_rest_azure version 0.8.0 * [Breaking Change] Changed the name of the azure environments from 'Azure' to 'AzureCloud' and 'AzureChina' to 'AzureChinaCloud'.[Issue #600](https://github.com/Azure/azure-sdk-for-ruby/issues/600) [PR #711](https://github.com/Azure/azure-sdk-for-ruby/pull/711) * Added 'Accept' header with the value 'application/json'.[Issue #701](https://github.com/Azure/azure-sdk-for-ruby/issues/701) [PR #710](https://github.com/Azure/azure-sdk-for-ruby/pull/710) ##2017.02.06 ms_rest_azure version 0.7.0 * [Breaking Change] Correcting typo in `storage_endpoint_suffix` key for azure environments [Issue #603](https://github.com/Azure/azure-sdk-for-ruby/issues/603) [PR #604](https://github.com/Azure/azure-sdk-for-ruby/pull/604) * [Breaking Change] Handling custom deserialization block in `MsRestAzure::AzureServiceClient.update_state_from_azure_async_operation_header` [PR #656](https://github.com/Azure/azure-sdk-for-ruby/pull/656) * Adding `resource_group` property on MsRestAzure::Resource to be populated with Azure resource group name when available from `id` [Issue 340](https://github.com/Azure/azure-sdk-for-ruby/issues/340) [PR #620](https://github.com/Azure/azure-sdk-for-ruby/pull/620) * Deriving `MsREstAzure::Resource` from `MsRestAzure::SubResource` to share `id` property [PR #663](https://github.com/Azure/azure-sdk-for-ruby/pull/663) ##2016.11.14 ms_rest_azure version 0.6.2 * Update to ms_rest v0.6.2 due to fix for missing default ca-cert for providing ssl options [#580](https://github.com/Azure/azure-sdk-for-ruby/issues/580) ##2016.11.11 ms_rest_azure version 0.6.1 * Adding telemetry extension point into AzureServiceClient [#543](https://github.com/Azure/azure-sdk-for-ruby/pull/543) * Removing explicit json dependency [#523](https://github.com/Azure/azure-sdk-for-ruby/pull/523) ##2016.10.05 ms_rest_azure version 0.6.0 * Minimum supported Ruby version is 2.0.0 [#1463](https://github.com/Azure/autorest/pull/1463) * Implemented generic request method for AzureServiceClient [#1447](https://github.com/Azure/autorest/pull/1447) * Improved AzureOperationError class to expose error_message and error_code properties [#1450](https://github.com/Azure/autorest/pull/1450) ##2016.09.15 ms_rest_azure version 0.5.0 * Updating ms_rest dependency to version 0.5.0 * Adding known Azure Environments in ruby runtime for easy discovery * Default Azure active directory url is updated from `https://login.windows.net/` to `https://login.microsoftonline.com/` (Breaking Change) * Using bundled default ca-cert from ms_rest ##2016.08.10 ms_rest_azure version 0.4.0 * Adding & inheriting serialization class from ms_rest generic serializer ##2016.07.21 ms_rest_azure version 0.3.1 * [Bug fixes](https://github.com/Azure/autorest/commit/ede944a1fa30a7453aa30e6fa79154dc43393cdf) ##2016.07.14 ms_rest_azure version 0.3.0 * Embracing latest ms_rest version [0.3.0](https://rubygems.org/gems/ms_rest) ##2016.05.19 ms_rest_azure version 0.2.3 * Support patch for long running operations. See [#1011](https://github.com/Azure/autorest/pull/1011), [#1056](https://github.com/Azure/autorest/pull/1056)