class MU::Cloud::Azure::User
A user as configured in {MU::Config::BasketofKittens::users}
Public Class Methods
Stub method. Azure
resources are cleaned up by removing the parent resource group. @return [void]
# File modules/mu/providers/azure/user.rb, line 143 def self.cleanup(**args) end
Locate and return cloud provider descriptors of this resource type which match the provided parameters, or all visible resources if no filters are specified. At minimum, implementations of find
must honor credentials
and cloud_id
arguments. We may optionally support other search methods, such as tag_key
and tag_value
, or cloud-specific arguments like project
. See also {MU::MommaCat.findStray}. @param args [Hash]: Hash
of named arguments passed via Ruby's double-splat @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching resources
# File modules/mu/providers/azure/user.rb, line 154 def self.find(**args) found = {} # XXX Had to register Microsoft.ApiManagement at https://portal.azure.com/#@eglobaltechlabs.onmicrosoft.com/resource/subscriptions/3d20ddd8-4652-4074-adda-0d127ef1f0e0/resourceproviders # ffs automate this process, it's just like API enabling in GCP # Azure resources are namedspaced by resource group. If we weren't # told one, we may have to search all the ones we can see. resource_groups = if args[:resource_group] [args[:resource_group]] elsif args[:cloud_id] and args[:cloud_id].is_a?(MU::Cloud::Azure::Id) [args[:cloud_id].resource_group] else MU::Cloud::Azure.resources(credentials: args[:credentials]).resource_groups.list.map { |rg| rg.name } end if args[:cloud_id] id_str = args[:cloud_id].is_a?(MU::Cloud::Azure::Id) ? args[:cloud_id].name : args[:cloud_id] resource_groups.each { |rg| resp = MU::Cloud::Azure.serviceaccts(credentials: args[:credentials]).user_assigned_identities.get(rg, id_str) found[Id.new(resp.id)] = resp if resp } else if args[:resource_group] MU::Cloud::Azure.serviceaccts(credentials: args[:credentials]).user_assigned_identities.list_by_resource_group.each { |ident| found[Id.new(ident.id)] = ident } else MU::Cloud::Azure.serviceaccts(credentials: args[:credentials]).user_assigned_identities.list_by_subscription.each { |ident| found[Id.new(ident.id)] = ident } end end found end
Does this resource type exist as a global (cloud-wide) artifact, or is it localized to a region/zone? @return [Boolean]
# File modules/mu/providers/azure/user.rb, line 130 def self.isGlobal? false end
Initialize this cloud resource object. Calling super
will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like @vpc
, for us. @param args [Hash]: Hash
of named arguments passed via Ruby's double-splat
# File modules/mu/providers/azure/user.rb, line 23 def initialize(**args) super if !mu_name.nil? @mu_name = mu_name @cloud_id = Id.new(cloud_desc.id) if @cloud_id and cloud_desc else @mu_name ||= @deploy.getResourceName(@config["name"], max_length: 31) end end
Denote whether this resource implementation is experiment, ready for testing, or ready for production use.
# File modules/mu/providers/azure/user.rb, line 136 def self.quality MU::Cloud::ALPHA end
Cloud-specific configuration properties. @param _config [MU::Config]: The calling MU::Config
object @return [Array<Array,Hash>]: List of required fields, and json-schema Hash
of cloud-specific configuration parameters for this resource
# File modules/mu/providers/azure/user.rb, line 194 def self.schema(_config) toplevel_required = [] schema = { "region" => MU::Config.region_primitive, "name" => { "type" => "string", "description" => "The name of a account to create. Currently, +service+ is the only account type we support in Azure." }, "type" => { "type" => "string", "description" => "'service' will create a service account (machine credentials) and generate API keys", "enum" => ["service"] }, "roles" => { "type" => "array", "description" => "One or more Azure Authorization roles to associate with this resource.", "default" => ["Reader"], "items" => { "type" => "string", "description" => "One or more Azure Authorization roles to associate with this resource. If no roles are specified, we default to +Reader+, which permits read-only access subscription-wide." } } } [toplevel_required, schema] end
Cloud-specific pre-processing of {MU::Config::BasketofKittens::users}, bare and unvalidated. @param user [Hash]: The resource to process and validate @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member @return [Boolean]: True if validation succeeded, False otherwise
# File modules/mu/providers/azure/user.rb, line 224 def self.validateConfig(user, _configurator) ok = true user['region'] ||= MU::Cloud::Azure.myRegion(user['credentials']) # if user['groups'] and user['groups'].size > 0 and # !MU::Cloud::Azure.credConfig(user['credentials'])['masquerade_as'] # MU.log "Cannot change Azure group memberships in non-GSuite environments.\nVisit https://groups.google.com to manage groups.", MU::ERR # ok = false # end if user['type'] != "service" and user["create_api_key"] MU.log "Only service accounts can have API keys in Azure", MU::ERR ok = false end if user['type'] != "service" MU.log "Human accounts not yet supported in Azure::User", MU::ERR ok = false end ok end
Public Instance Methods
Called automatically by {MU::Deploy#createResources}
# File modules/mu/providers/azure/user.rb, line 36 def create @config['region'] ||= MU::Cloud::Azure.myRegion(@config['credentials']) rgroup_name = @deploy.deploy_id+"-"+@config['region'].upcase tags = {} if !@config['scrub_mu_isms'] tags = MU::MommaCat.listStandardTags end if @config['tags'] @config['tags'].each { |tag| tags[tag['key']] = tag['value'] } end if @config['type'] == "interactive" raise Mu::MuError, "I don't know how to make interactive users in Azure yet" else ident_obj = MU::Cloud::Azure.serviceaccts(:Identity).new # ident_obj.name = @mu_name ident_obj.location = @config['region'] ident_obj.tags = tags begin MU.log "Creating service account #{@mu_name}" resp = MU::Cloud::Azure.serviceaccts(credentials: @config['credentials']).user_assigned_identities.create_or_update(rgroup_name, @mu_name, ident_obj) @cloud_id = Id.new(resp.id) rescue ::MsRestAzure::AzureOperationError => e MU::Cloud::Azure.handleError(e) end begin sleep 1 end while cloud_desc(use_cache: false).nil? or cloud_desc.client_id.nil? end end
If we're a managed service identity or otherwise have a URL for fetching our client secret, fetch it and return it. XXX this doesn't work, and may not be intended to @return [String]
# File modules/mu/providers/azure/user.rb, line 76 def getSecret if cloud_desc and cloud_desc.client_secret_url cred_hash = MU::Cloud::Azure.getSDKOptions(@credentials) token_provider = MsRestAzure::ApplicationTokenProvider.new( cred_hash[:tenant_id], cred_hash[:client_id], cred_hash[:client_secret] ) cred_obj = MsRest::TokenCredentials.new(token_provider) client = ::MsRest::ServiceClient.new(cred_obj) cloud_desc.client_secret_url.match(/^(http.*?\.azure\.net)(\/.*)/) path = Regexp.last_match[2] #MU.log "Calling into #{base} #{path}" promise = client.make_request_async( cloud_desc.client_secret_url, :get, path ) # XXX this is async, need to stop and wait somehow promise.then do | result| result.response # MU.log "RESPONSE", MU::WARN, details: resp end end nil end
Called automatically by {MU::Deploy#createResources}
# File modules/mu/providers/azure/user.rb, line 107 def groom if @config['roles'] @config['roles'].each { |role| MU::Cloud.resourceClass("Azure", "Role").assignTo(cloud_desc.principal_id, role_name: role, credentials: @config['credentials']) } end end
Return the metadata for this user configuration @return [Hash]
# File modules/mu/providers/azure/user.rb, line 117 def notify description = MU.structToHash(cloud_desc) if description description.delete(:etag) return description end { } end
Private Instance Methods
# File modules/mu/providers/azure/user.rb, line 249 def bind_human_user end