Class: Kitchen::Driver::AzureCredentials

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/kitchen/driver/azure_credentials.rb

Overview

Resolves Azure Resource Manager credentials for a single subscription.

Credentials are sourced, in order of precedence, from environment variables (+AZURE_TENANT_ID+, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET) and then from the Azure CLI credentials INI file (by default ~/.azure/credentials, overridable with AZURE_CONFIG_FILE).

The combination of values that resolve determines which token provider is used - see #token_provider.

Examples:

Service principal supplied by environment

ENV["AZURE_TENANT_ID"]     = "..."
ENV["AZURE_CLIENT_ID"]     = "..."
ENV["AZURE_CLIENT_SECRET"] = "..."
client = Kitchen::Driver::AzureCredentials.new(subscription_id: "...").arm_client

Constant Summary collapse

CONFIG_FILE =

Path fragment, relative to the user's home directory, of the Azure CLI credentials file.

Returns:

  • (String)
File.join(".azure", "credentials").freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subscription_id:, environment: "Azure") ⇒ AzureCredentials

Returns a new instance of AzureCredentials.

Parameters:

  • subscription_id (String)

    the Azure subscription to authenticate against.

  • environment (String) (defaults to: "Azure")

    the Azure cloud name. Case-insensitive.

Raises:

  • (Kitchen::UserError)

    if environment is not a known Azure cloud.



60
61
62
63
64
65
66
# File 'lib/kitchen/driver/azure_credentials.rb', line 60

def initialize(subscription_id:, environment: "Azure")
  @subscription_id = subscription_id
  @environment = environment || "Azure"

  # Validate eagerly so a typo surfaces before any Azure call is made.
  azure_environment
end

Instance Attribute Details

#environmentString (readonly)

The Azure cloud name, e.g. "Azure" or "AzureUSGovernment".

Returns:

  • (String)


44
45
46
# File 'lib/kitchen/driver/azure_credentials.rb', line 44

def environment
  @environment
end

#subscription_idString (readonly)

The Azure subscription these credentials authenticate against.

Returns:

  • (String)


39
40
41
# File 'lib/kitchen/driver/azure_credentials.rb', line 39

def subscription_id
  @subscription_id
end

Class Method Details

.default_config_pathString

Default path of the Azure CLI credentials file.

Resolved lazily (rather than at load time) so that a test - or a caller that manipulates HOME - sees the current home directory rather than whichever one happened to be set when this file was first required.

Returns:

  • (String)

    absolute path to ~/.azure/credentials



53
54
55
# File 'lib/kitchen/driver/azure_credentials.rb', line 53

def self.default_config_path
  File.join(Dir.home, CONFIG_FILE)
end

Instance Method Details

#arm_clientAzure::ArmClient

An ARM client authenticated with these credentials.

Returns:



71
72
73
# File 'lib/kitchen/driver/azure_credentials.rb', line 71

def arm_client
  Azure::ArmClient.new(subscription_id:, environment: azure_environment, token_provider:)
end

#azure_environmentAzure::Environments::Environment

Endpoints for the configured cloud.

AZURE_AUTHORITY_HOST overrides the Entra ID endpoint, which is how platforms that issue federated tokens point at their own authority.

Returns:

Raises:

  • (Kitchen::UserError)

    if the cloud name is not recognised.



82
83
84
# File 'lib/kitchen/driver/azure_credentials.rb', line 82

def azure_environment
  @azure_environment ||= Azure::Environments.fetch(environment).with_authority(ENV["AZURE_AUTHORITY_HOST"])
end

#config_pathString

Path of the credentials file actually in use.

Returns:



107
108
109
# File 'lib/kitchen/driver/azure_credentials.rb', line 107

def config_path
  @config_path ||= File.expand_path(ENV["AZURE_CONFIG_FILE"] || self.class.default_config_path)
end

#token_providerAzure::TokenProvider

Selects a token provider based on which credentials resolved.

In precedence order:

  • AZURE_FEDERATED_TOKEN_FILE + client_id + tenant_id - workload identity federation, the secretless option for CI.
  • client_id + client_secret + tenant_id - service principal.
  • AZURE_USE_MSI - managed identity, explicitly.
  • client_id without a secret - user-assigned managed identity.
  • tenant_id only - system-assigned managed identity.
  • none of the above - falls back to the az login token cache.


99
100
101
# File 'lib/kitchen/driver/azure_credentials.rb', line 99

def token_provider
  @token_provider ||= build_token_provider
end