def create_update_roledefinition(self): ''' Creates or updates role definition. :return: deserialized role definition ''' self.log("Creating / Updating role definition {0}".format(self.name)) try: permissions = None if self.permissions: permissions = [AuthorizationManagementClient.models("2018-01-01-preview").Permission( actions=p.get('actions', None), not_actions=p.get('not_actions', None), data_actions=p.get('data_actions', None), not_data_actions=p.get('not_data_actions', None) ) for p in self.permissions] role_definition = AuthorizationManagementClient.models("2018-01-01-preview").RoleDefinition( role_name=self.name, description=self.description, permissions=permissions, assignable_scopes=self.assignable_scopes, role_type='CustomRole') if self.role: role_definition.name = self.role['name'] response = self._client.role_definitions.create_or_update(role_definition_id=self.role['name'] if self.role else str(uuid.uuid4()), scope=self.scope, role_definition=role_definition) if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): response = self.get_poller_result(response) except CloudError as exc: self.log('Error attempting to create role definition.') self.fail("Error creating role definition: {0}".format(str(exc))) return roledefinition_to_dict(response)
def __init__(self, graphrbac_credentials, credentials, tenant_id, subscription_id): self._subscription_id = subscription_id self._client = GraphRbacManagementClient(graphrbac_credentials, tenant_id=tenant_id) self._authorization_client = AuthorizationManagementClient( credentials, subscription_id=subscription_id)
def _query_rbac(ctx: Context, sub: Subscription): logger.info( f"Enumerating rbac permissions for subscription: {sub.subscription_id}" ) auth_client = AuthorizationManagementClient(ctx.cred_msrest, sub.subscription_id, base_url=ctx.cloud["ARM"]) roles = [] for role in auth_client.role_assignments.list(): try: role_dict = role.as_dict() definition = auth_client.role_definitions.get_by_id( role.role_definition_id) role_dict["permissions"] = [ p.as_dict() for p in definition.permissions ] role_dict["roleName"] = definition.role_name role_dict["roleType"] = definition.role_type role_dict["roleDescription"] = definition.description roles.append(role_dict) except Exception as ex: logger.error(ex) logger.info( f"Finishing rbac permissions for subscription: {sub.subscription_id}") return roles
def create_role_assignment(credentials, subscription_id, scope, principal_id): """ Gives service principal contributor role authorization on scope :param credentials: msrestazure.azure_active_directory.AdalAuthentication :param subscription_id: str :param scope: str :param principal_id: str """ authorization_client = AuthorizationManagementClient( credentials, subscription_id) role_name = 'Contributor' roles = list( authorization_client.role_definitions.list( scope, filter="roleName eq '{}'".format(role_name))) contributor_role = roles[0] for i in range(10): try: authorization_client.role_assignments.create( scope, uuid.uuid4(), { 'role_definition_id': contributor_role.id, 'principal_id': principal_id }) break except CloudError as e: # ignore error if service principal has not yet been created time.sleep(1) if i == 10: raise e
def __assignReaderRoleToSubscription(self, subscriptionId): authorizationClient = AuthorizationManagementClient( self.__credentialsProvider.getManagementCredentials(), subscriptionId) servicePrincipalId = self.getServicePrincipalId() if servicePrincipalId == None: raise Exception("Could not find servicePrincipal") roleDefinitionId = self.__getRoleDefinitionId(subscriptionId, authorizationClient) roleAssignment = self.__getRoleAssignments(subscriptionId, servicePrincipalId, roleDefinitionId, authorizationClient) if roleAssignment != None: log.info("Role Assignment already Present for Subscription Id: " + subscriptionId) return roleAssignment roleAssignmentProperties = RoleAssignmentCreateParameters( role_definition_id=roleDefinitionId, principal_id=self.getServicePrincipalId()) return self.__createRoleAssignmentWithRetry(subscriptionId, roleAssignmentProperties, authorizationClient)
def run(self, args): """Run the remediation job. :param args: List of arguments provided to the job. :type args: list. :returns: int """ params = self.parse(args[1]) client_id = os.environ.get("AZURE_CLIENT_ID") client_secret = os.environ.get("AZURE_CLIENT_SECRET") tenant_id = os.environ.get("AZURE_TENANT_ID") key_vault_name = params["key_vault_name"] # credential for Key Vault management client credential = ClientSecretCredential( client_id=client_id, client_secret=client_secret, tenant_id=tenant_id, ) # credential for AzureGraphRbacManagementClient credentials = ServicePrincipalCredentials( client_id=client_id, secret=client_secret, tenant=tenant_id, resource="https://graph.windows.net", ) keyvault_client = KeyVaultManagementClient(credential, params["subscription_id"]) graph_client = GraphRbacManagementClient(credentials, tenant_id, base_url=None) secret_client = SecretClient( vault_url=f"https://{key_vault_name}.vault.azure.net/", credential=credential, ) client_authorization = AuthorizationManagementClient( credential, params["subscription_id"], api_version="2018-01-01-preview") return self.remediate( tenant_id, client_id, secret_client, keyvault_client, graph_client, client_authorization, params["resource_group_name"], params["key_vault_name"], params["secret_name"], params["subscription_id"], )
def connect(): """Set up Azure Login Credentials from Environmental Variables.""" credentials = ServicePrincipalCredentials( client_id=os.environ.get('ARM_CLIENT_ID'), secret=os.environ.get('ARM_CLIENT_SECRET'), tenant=os.environ.get('ARM_TENANT_ID') ) # network_client = NetworkManagementClient(credentials, os.environ.get('ARM_SUBSCRIPTION_ID')) auth_management_client = AuthorizationManagementClient(credentials, os.environ.get('ARM_SUBSCRIPTION_ID'), api_version=None, base_url=None) return auth_management_client
def delete_keylistrole_appservice(self, resource_group_name, storage_name, role_assignment_name): resource_provider = "Microsoft.Storage" resource_type = "storageAccounts" scope = '/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s' % ( self.subscription_id, resource_group_name, resource_provider, resource_type, storage_name) auth_cli = AuthorizationManagementClient(self.credentials, self.subscription_id, api_version="2015-07-01") resp = auth_cli.role_assignments.delete(scope, role_assignment_name) print("%s App Service access revoked %s Storage account" % (role_assignment_name, storage_name))
def get_role_id_by_name(name, scope=""): config = authorization.get_client_config() client_token = authorization.get_client_token() client = AuthorizationManagementClient(TokenCred(client_token.token), config.subscription_id) def_pages = client.role_definitions.list(scope, filter=f'roleName eq {name}') role = None for x in def_pages: role = x.id break if role is None: raise Exception(f'role \'{name}\' not found at scope \'{scope}\'') return role
def __init__(self): if os.environ.get('AZURE_SUBSCRIPTION_ID') is not None: self.subscription_id = os.environ.get( 'AZURE_SUBSCRIPTION_ID') # your Azure Subscription Id else: raise ValueError( 'AZURE_SUBSCRIPTION_ID environment variable missing') # Sanity check if os.environ.get('AZURE_CLIENT_ID') is None: raise ValueError('AZURE_CLIENT_ID environment variable missing') if os.environ.get('AZURE_CLIENT_SECRET') is None: raise ValueError( 'AZURE_CLIENT_SECRET environment variable missing') if os.environ.get('AZURE_TENANT_ID') is None: raise ValueError('AZURE_TENANT_ID environment variable missing') if os.environ.get('STORAGE_ACCOUNT_NAME') is None: raise ValueError( 'STORAGE_ACCOUNT_NAME environment variable missing') self.storage_account_name = os.environ['STORAGE_ACCOUNT_NAME'] self.credentials = ServicePrincipalCredentials( client_id=os.environ['AZURE_CLIENT_ID'], secret=os.environ['AZURE_CLIENT_SECRET'], tenant=os.environ['AZURE_TENANT_ID']) #FIXME do we need two credentials? self.client_secret_credential = ClientSecretCredential( os.environ['AZURE_TENANT_ID'], os.environ['AZURE_CLIENT_ID'], os.environ['AZURE_CLIENT_SECRET']) self.resource_client = ResourceManagementClient( self.credentials, self.subscription_id) self.msi_client = ManagedServiceIdentityClient(self.credentials, self.subscription_id) self.policy_client = PolicyClient(self.credentials, self.subscription_id) self.authorization_client = AuthorizationManagementClient( self.credentials, self.subscription_id) self.storage_client = StorageManagementClient(self.credentials, self.subscription_id) # adls2 storage client self.adls2_client = DataLakeServiceClient( account_url="{}://{}.dfs.core.windows.net".format( "https", self.storage_account_name), credential=self.client_secret_credential)
def main(): SUBSCRIPTION_ID = os.environ.get("SUBSCRIPTION_ID", None) CLIENT_OID = os.environ.get("CLIENT_OID", None) GROUP_NAME = "testgroupx" ROLE_ASSIGNMENT = "88888888-7000-0000-0000-000000000003" ROLE_DEFINITION = "e078ab98-ef3a-4c9a-aba7-12f5172b45d0" SCOPE = "subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}".format( subscriptionId=SUBSCRIPTION_ID, resourceGroupName=GROUP_NAME) # Create client # # For other authentication approaches, please see: https://pypi.org/project/azure-identity/ resource_client = ResourceManagementClient( credential=DefaultAzureCredential(), subscription_id=SUBSCRIPTION_ID) authorization_client = AuthorizationManagementClient( credential=DefaultAzureCredential(), subscription_id=SUBSCRIPTION_ID, api_version="2018-01-01-preview") # Create resource group resource_client.resource_groups.create_or_update(GROUP_NAME, {"location": "eastus"}) # Create role assignment role_assignment = authorization_client.role_assignments.create( SCOPE, ROLE_ASSIGNMENT, { "role_definition_id": "/subscriptions/" + SUBSCRIPTION_ID + "/providers/Microsoft.Authorization/roleDefinitions/" + ROLE_DEFINITION, "principal_id": CLIENT_OID, }) print("Create role assignment:\n{}".format(role_assignment)) # Get role assignment role_assignment = authorization_client.role_assignments.get( SCOPE, ROLE_ASSIGNMENT) print("Get role assignment:\n{}".format(role_assignment)) # Delete role assignment role_assignment = authorization_client.role_assignments.delete( SCOPE, ROLE_ASSIGNMENT) print("Delete role assignment.\n") # Delete Group resource_client.resource_groups.begin_delete(GROUP_NAME).result()
def add_service_principal_to_role(credentials, subscription_id, spoid): auth_client = AuthorizationManagementClient(credentials, subscription_id) scope = '/subscriptions/' + subscription_id # ARM Reader role is hardcoded here role_definition_id = '/subscriptions/' + subscription_id + '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' principal_id = spoid # Try to assign the Service Principal to the Role... but a lot could go wrong. try: result = auth_client.role_assignments.create( scope, uuid.uuid4(), RoleAssignmentProperties(role_definition_id, principal_id)) success = True # Tell the user what went wrong. except Exception as e: result = e success = False return result, success
def get_rbac_permissions(context, sub_id): print(f"Getting rbac permissions for subscription: {sub_id}") auth_client = AuthorizationManagementClient(context.auth.resource_cred, sub_id) rbacs = ["rbac"] for role in auth_client.role_assignments.list(): scope = role.scope principal = role.principal_id assignment_id = role.id role_id = role.role_definition_id #role_id = f'/subscriptions/{sub_id}/providers/Microsoft.Authorization/roleAssignments/{role.name}' role_type, permissions = _get_permissions(context.auth.resource_cred, role_id) # querying for assignment id will give type of AADobject rbacs += (_map_admin_type(sub_id, assignment_id, principal, scope, role_id, role_type, permissions)) print(f"Finished management certs for subscription: {sub_id}") return rbacs
def setup_client(self, context): #user_id = context['environment']['openstack.params']['auth']['credentials']['ADMIN_USER_ID'] #user_pw= context['environment']['openstack.params']['auth']['credentials']['ADMIN_USER_PW'] #azure_tenant_id= str(context['environment']['openstack.params']['auth']['AZURE_TENANT_ID']) subscription_id = str(context['environment']['openstack.params'] ['auth']['SUBSCRIPTION_ID']) credentials = UserPassCredentials( "*****@*****.**", # Your new user "XXXX", # Your password #user_id, #user_pw, resource="https://graph.windows.net") azure_tenant_id = "cc27778d-9be" self.graphrbac_client = GraphRbacManagementClient( GraphRbacManagementClientConfiguration(credentials, azure_tenant_id)) #subscription_id = '1beafe45-ce54' self.authorization_client = AuthorizationManagementClient( AuthorizationManagementClientConfiguration(credentials, subscription_id))
def assign_keylistrole_appservice(self, resource_group_name, storage_name, app_service_name): resource_provider = "Microsoft.Storage" resource_type = "storageAccounts" scope = '/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s' % ( self.subscription_id, resource_group_name, resource_provider, resource_type, storage_name) role_assignment_name = str(uuid.uuid4()) # id for "Storage Account Key Operator Service Role" https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#storage-account-key-operator-service-role role_id = "/subscriptions/%s/providers/Microsoft.Authorization/roleDefinitions/%s" % ( self.subscription_id, "81a9662b-bebf-436f-a333-f67b29880f12") principal_id = self.get_object_id(app_service_name) props = RoleAssignmentProperties(role_definition_id=role_id, principal_id=principal_id) auth_cli = AuthorizationManagementClient(self.credentials, self.subscription_id, api_version="2015-07-01") resp = auth_cli.role_assignments.create(scope, role_assignment_name, properties=props) print("%s App Service authorized to access %s Storage account" % (app_service_name, storage_name)) return role_assignment_name
def run_example(): """Resource Group management example.""" # # Create the Resource Manager Client with an Application (service principal) token provider # subscription_id = os.environ.get( 'AZURE_SUBSCRIPTION_ID', '11111111-1111-1111-1111-111111111111') # your Azure Subscription Id credentials = ServicePrincipalCredentials( client_id=os.environ['AZURE_CLIENT_ID'], secret=os.environ['AZURE_CLIENT_SECRET'], tenant=os.environ['AZURE_TENANT_ID']) resource_client = ResourceManagementClient(credentials, subscription_id) compute_client = ComputeManagementClient(credentials, subscription_id) network_client = NetworkManagementClient(credentials, subscription_id) authorization_client = AuthorizationManagementClient( credentials, subscription_id) # Create Resource group print('\nCreate Resource Group') resource_group = resource_client.resource_groups.create_or_update( GROUP_NAME, {'location': LOCATION}) print_item(resource_group) if USER_ASSIGNED_IDENTITY: # Create a User Assigned Identity if needed print("\nCreate User Assigned Identity") msi_client = ManagedServiceIdentityClient(credentials, subscription_id) user_assigned_identity = msi_client.user_assigned_identities.create_or_update( GROUP_NAME, "myMsiIdentity", # Any name, just a human readable ID LOCATION) print_item(user_assigned_identity) print("\nCreate Network") # Create Network components of the VM # This is not MSI related and is just required to create the VM subnet = create_virtual_network(network_client) public_ip = create_public_ip(network_client) nic = create_network_interface(network_client, subnet, public_ip) print_item(nic) params_identity = {} if USER_ASSIGNED_IDENTITY and SYSTEM_ASSIGNED_IDENTITY: params_identity[ 'type'] = ResourceIdentityType.system_assigned_user_assigned params_identity['user_assigned_identities'] = { user_assigned_identity.id: {} } elif USER_ASSIGNED_IDENTITY: # User Assigned only params_identity['type'] = ResourceIdentityType.user_assigned params_identity['user_assigned_identities'] = { user_assigned_identity.id: {} } elif SYSTEM_ASSIGNED_IDENTITY: # System assigned only params_identity['type'] = ResourceIdentityType.system_assigned # Create a VM MSI enabled params_create = { 'location': LOCATION, 'os_profile': get_os_profile(), 'hardware_profile': get_hardware_profile(), 'network_profile': get_network_profile(nic.id), 'storage_profile': get_storage_profile(), # Activate MSI on that VM 'identity': params_identity } print("\nCreate VM") vm_poller = compute_client.virtual_machines.create_or_update( GROUP_NAME, VM_NAME, params_create, ) vm_result = vm_poller.result() print_item(vm_result) # Get the PublicIP after VM creation, since assignment is dynamic public_ip = network_client.public_ip_addresses.get(GROUP_NAME, PUBLIC_IP_NAME) # By default, the MSI accounts have no permissions # Next part is assignment of permissions to the account # Example is Resource Group access as Contributor, but # you can any permissions you need. msi_accounts_to_assign = [] if SYSTEM_ASSIGNED_IDENTITY: msi_accounts_to_assign.append(vm_result.identity.principal_id) if USER_ASSIGNED_IDENTITY: msi_accounts_to_assign.append(user_assigned_identity.principal_id) print("\nAssign permissions to MSI identities") # Get "Contributor" built-in role as a RoleDefinition object role_name = 'Contributor' roles = list( authorization_client.role_definitions.list( resource_group.id, filter="roleName eq '{}'".format(role_name))) assert len(roles) == 1 contributor_role = roles[0] # Add RG scope to the MSI identities: for msi_identity in msi_accounts_to_assign: role_assignment = authorization_client.role_assignments.create( resource_group.id, uuid.uuid4(), # Role assignment random name { 'role_definition_id': contributor_role.id, 'principal_id': msi_identity }) print_item(role_assignment) print("You can connect to the VM using:") print("ssh {}@{}".format( ADMIN_LOGIN, public_ip.ip_address, )) print("And password: {}\n".format(ADMIN_PASSWORD)) input("Press enter to delete this Resource Group.") # Delete Resource group and everything in it print('Delete Resource Group') delete_async_operation = resource_client.resource_groups.delete(GROUP_NAME) delete_async_operation.wait() print("\nDeleted: {}".format(GROUP_NAME))
def get_client(self, subscription_id: str): client = AuthorizationManagementClient( self.credentials.get_credentials('arm'), subscription_id=subscription_id) client._client.config.add_user_agent(get_user_agent()) return client
import os from azure.identity import ClientSecretCredential from azure.mgmt.authorization import AuthorizationManagementClient subscription_id = '96f7a6ad-39d4-42e5-b676-a510a9e6fd22' tenant_id = '72f988bf-86f1-41af-91ab-2d7cd011db47' client_id = 'fd2bfb66-5b4c-492e-8f39-44699600bca8' client_secret = 'nBQ0.q_i76XQn_318O-sk19.la_UswC-9c' credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret) authorizationClient = AuthorizationManagementClient(credential, subscription_id) roles = authorizationClient.role_assignments.list() for role in roles: print(role)
def AuthorizationManagementClient(self): from azure.mgmt.authorization import AuthorizationManagementClient return AuthorizationManagementClient(self.ManagementCredentials, self.subscription_id)
def get_client_Auth(): return AuthorizationManagementClient(get_credentials(), setting.SUBSCRIPTION_ID)
def _create_azure_state_storage(cls, providers: dict) -> None: resource_group_name = providers["terraform"]["backend"]["azurerm"][ "resource_group_name"] region = providers["provider"]["azurerm"]["location"] subscription_id = providers["provider"]["azurerm"]["subscription_id"] storage_account_name = providers["terraform"]["backend"]["azurerm"][ "storage_account_name"] container_name = providers["terraform"]["backend"]["azurerm"][ "container_name"] # Create RG credential = Azure.get_credentials() resource_client = ResourceManagementClient(credential, subscription_id) try: rg_result = resource_client.resource_groups.create_or_update( resource_group_name, {"location": region}) except ResourceNotFoundError as e: if "SubscriptionNotFound" in e.message: raise UserErrors( f"SubscriptionId {subscription_id} does not exists. Please check and use the correct Subscription Id. " "This is used for accessing the resources in the Resource Group." ) except HttpResponseError as e: if "InvalidSubscriptionId" in e.message: raise UserErrors( f"Malformed or Invalid SubscriptionId {subscription_id} used. Please check and use the correct Subscription Id. " "This is used for accessing the resources in the Resource Group." ) logger.debug( f"Provisioned resource group {rg_result.name} in the {rg_result.location} region" ) authorization_client = AuthorizationManagementClient( credential, subscription_id, api_version="2018-01-01-preview") owner_role_name = "Owner" owner_role = list( authorization_client.role_definitions.list( rg_result.id, filter="roleName eq '{}'".format(owner_role_name)))[0] storage_role_name = "Storage Blob Data Owner" storage_role = list( authorization_client.role_definitions.list( rg_result.id, filter="roleName eq '{}'".format(storage_role_name)))[0] key_vault_role_name = "Key Vault Administrator" key_vault_role = list( authorization_client.role_definitions.list( rg_result.id, filter="roleName eq '{}'".format(key_vault_role_name)))[0] role_assignments = authorization_client.role_assignments.list_for_resource_group( rg_result.name) for role_assignment in role_assignments: if role_assignment.role_definition_id == owner_role.id: try: authorization_client.role_assignments.create( scope= f"/subscriptions/{subscription_id}/resourceGroups/{rg_result.name}", role_assignment_name=uuid4(), parameters={ "role_definition_id": storage_role.id, "principal_id": role_assignment.principal_id, }, ) except ResourceExistsError: pass try: authorization_client.role_assignments.create( scope= f"/subscriptions/{subscription_id}/resourceGroups/{rg_result.name}", role_assignment_name=uuid4(), parameters={ "role_definition_id": key_vault_role.id, "principal_id": role_assignment.principal_id, }, ) except ResourceExistsError: pass # Create SA storage_client = StorageManagementClient(credential, subscription_id) try: storage_client.storage_accounts.get_properties( resource_group_name, storage_account_name) logger.debug( f"Storage account {storage_account_name} already exists!") except ResourceNotFoundError: logger.debug("Need to create storage account") # create sa try: poller = storage_client.storage_accounts.begin_create( resource_group_name, storage_account_name, { "location": region, "kind": "StorageV2", "sku": { "name": "Standard_LRS" }, }, ) except ResourceExistsError: raise UserErrors( "The Storage Account name already exists in Another Subscription. " "Please change the Name or Org Name in Config.") account_result = poller.result() logger.debug(f"Provisioned storage account {account_result.name}") # TODO(ankur): assign Storage Blob Data Contributor to this SA, # otherwise it doesn't work # create container try: container = storage_client.blob_containers.get( resource_group_name, storage_account_name, container_name) logger.debug(f"container {container.name} exists") except ResourceNotFoundError: logger.debug("Need to create container") container = storage_client.blob_containers.create( resource_group_name, storage_account_name, container_name, {}) logger.debug(f"Provisioned container {container.name}")
def stop(self, data): credentials, _, _ = self._get_credentials() # Do NOT use the conf but the actual values from the cluster here cluster_resource_id = data["cluster"]["id"] _, _, subscription_id, _, resource_group, _, _, _, cluster_name = cluster_resource_id.split( "/") clusters_client = ContainerServiceClient(credentials, subscription_id) # Try to detach from ACR if required. It is not mandatory but if not done, it would pollute # the ACR with multiple invalid role attachments and consume attachment quotas node_resource_group = data["cluster"]["node_resource_group"] acr_attachment = data.get("acr_attachment", None) if not _is_none_or_blank(acr_attachment): logging.info( "Cluster has an ACR attachment, check managed identity") cluster_identity_profile = data["cluster"]["identity_profile"] kubelet_mi_resource_id = cluster_identity_profile[ "kubeletidentity"].get("resource_id", None) if kubelet_mi_resource_id is not None: _, _, mi_subscription_id, _, mi_resource_group, _, _, _, mi_name = kubelet_mi_resource_id.split( "/") if mi_resource_group == node_resource_group: logging.info( "Cluster has an AKS managed kubelet identity, try to detach" ) authorization_client = AuthorizationManagementClient( credentials, acr_attachment["subscription_id"]) try: authorization_client.role_assignments.delete_by_id( acr_attachment["role_assignment"]["id"]) except ResourceNotFoundError as e: logging.warn( "It looks that the ACR role assignment doesnt exist. Ignore this step" ) # Detach Vnet like ACR vnet_attachment = data.get("vnet_attachment", None) if not _is_none_or_blank(vnet_attachment): logging.info( "Cluster has an Vnet attachment, check managed identity") if "role_assignment" in vnet_attachment: logging.info( "Cluster has an AKS managed kubelet identity, try to detach" ) authorization_client = AuthorizationManagementClient( credentials, vnet_attachment["subscription_id"]) try: authorization_client.role_assignments.delete_by_id( vnet_attachment["role_assignment"]["id"]) except ResourceNotFoundError as e: logging.warn( "It looks that the Vnet role assignment doesnt exist. Ignore this step" ) def do_delete(): future = clusters_client.managed_clusters.begin_delete( resource_group, cluster_name) return future.result() delete_result = run_and_process_cloud_error(do_delete) # delete returns void, so we poll until the cluster is really gone gone = False while not gone: time.sleep(5) try: cluster = clusters_client.managed_clusters.get( resource_group, cluster_name) if cluster.provisioning_state.lower() != 'deleting': logging.info( "Cluster is not deleting anymore, must be deleted now (state = %s)" % cluster.provisioning_state) # other exceptions should not be ignored except ResourceNotFoundError as e: logging.info( "Cluster doesn't seem to exist anymore, considering it deleted" ) gone = True
def start(self): """ Build the create cluster request. """ credentials, subscription_id, managed_identity_id = self._get_credentials( ) # Fetch metadata about the instance metadata = get_instance_metadata() # Resource group resource_group = self.config.get('resourceGroup', None) dss_host_resource_group = metadata["compute"]["resourceGroupName"] if _is_none_or_blank(resource_group): resource_group = dss_host_resource_group logging.info( "Using same resource group as DSS: {}".format(resource_group)) # Location location = self.config.get('location', None) if _is_none_or_blank(location): location = metadata["compute"]["location"] logging.info("Using same location as DSS: {}".format(location)) # Consistency checks if _is_none_or_blank(resource_group): raise Exception( "A resource group to put the cluster in is required") if _is_none_or_blank(location): raise Exception("A location to put the cluster in is required") # AKS Client clusters_client = None # Credit the cluster to DATAIKU if os.environ.get("DISABLE_AZURE_USAGE_ATTRIBUTION", "0") == "1": logging.info("Azure usage attribution is disabled") clusters_client = ContainerServiceClient(credentials, subscription_id) else: policy = UserAgentPolicy() policy.add_user_agent('pid-fd3813c7-273c-5eec-9221-77323f62a148') clusters_client = ContainerServiceClient(credentials, subscription_id, user_agent_policy=policy) # check that the cluster doesn't exist yet, otherwise azure will try to update it # and will almost always fail try: existing = clusters_client.managed_clusters.get( resource_group, self.cluster_name) if existing is not None: raise Exception( "A cluster with name %s in resource group %s already exists" % (self.cluster_name, resource_group)) except CloudError as e: logging.info("Cluster doesn't seem to exist yet") except ResourceNotFoundError as e: logging.info("Cluster doesn't seem to exist yet") cluster_builder = ClusterBuilder(clusters_client) cluster_builder.with_name(self.cluster_name) cluster_builder.with_dns_prefix("{}-dns".format(self.cluster_name)) cluster_builder.with_resource_group(resource_group) cluster_builder.with_location(location) cluster_builder.add_tags(self.config.get("tags", None)) cluster_builder.with_linux_profile() # default is None cluster_builder.with_network_profile( service_cidr=self.config.get("serviceCIDR", None), dns_service_ip=self.config.get("dnsServiceIP", None), load_balancer_sku=self.config.get("loadBalancerSku", None), outbound_type=self.config.get("outboundType", None), network_plugin=self.config.get("networkPlugin"), docker_bridge_cidr=self.config.get("dockerBridgeCidr")) if self.config.get("useCustomNodeResourceGroup", False): cluster_builder.with_node_resource_group( self.config.get("nodeResourceGroup")) # Cluster identity connection_info = self.config.get("connectionInfo", None) cluster_idendity_legacy_use_distinct_sp = self.config.get( "useDistinctSPForCluster", False) cluster_idendity_legacy_sp = self.config.get("clusterServicePrincipal", None) cluster_identity_type = None cluster_identity = None if not _is_none_or_blank( connection_info) or cluster_idendity_legacy_use_distinct_sp: logging.warn( "Using legacy options to configure cluster identity. Clear them to use the new ones." ) if not cluster_idendity_legacy_use_distinct_sp and not _is_none_or_blank( connection_info): cluster_sp = connection_info elif cluster_idendity_legacy_use_distinct_sp and not _is_none_or_blank( cluster_idendity_legacy_sp): cluster_sp = self.config.get("clusterServicePrincipal") else: raise Exception( "Legacy options are not complete enough to determine cluster identity settings" ) cluster_builder.with_cluster_sp_legacy( cluster_service_principal_connection_info=cluster_sp) else: cluster_identity = self.config.get( "clusterIdentity", {"identityType": "managed-identity"}) cluster_identity_type = cluster_identity.get( "identityType", "managed-identity") if cluster_identity_type == "managed-identity": if cluster_identity.get("inheritDSSIdentity", True): logging.info( "Need to inspect Managed Identity infos from Azure") if metadata is None: metadata = get_instance_metadata() vm_resource_group = metadata["compute"][ "resourceGroupName"] vm_name = metadata["compute"]["name"] compute_client = ComputeManagementClient( credentials, subscription_id) vm = compute_client.virtual_machines.get( vm_resource_group, vm_name) # No choice here but to use the first one if managed_identity_id is None: managed_identity_id = next( iter(vm.identity.user_assigned_identities.keys())) for managed_identity_resource_id, managed_identity_properties in vm.identity.user_assigned_identities.items( ): if managed_identity_id == managed_identity_resource_id or managed_identity_id == managed_identity_properties.client_id: break logging.info("Found managed identity id {}".format( managed_identity_resource_id)) cluster_builder.with_managed_identity( managed_identity_resource_id) cluster_builder.with_kubelet_identity( managed_identity_resource_id, managed_identity_properties.client_id, managed_identity_properties.principal_id) else: control_plane_mi = None if cluster_identity.get( "useAKSManagedIdentity", True ) else cluster_identity["controlPlaneUserAssignedIdentity"] cluster_builder.with_managed_identity(control_plane_mi) if control_plane_mi is None: logging.info( "Configure cluster with system managed identity.") else: logging.info( "Configure cluster with user assigned identity: {}" .format(control_plane_mi)) if not cluster_identity.get("useAKSManagedKubeletIdentity", True): kubelet_mi = cluster_identity[ "kubeletUserAssignedIdentity"] _, _, mi_subscription_id, _, mi_resource_group, _, _, _, mi_name = kubelet_mi.split( "/") msiclient = ManagedServiceIdentityClient( AzureIdentityCredentialAdapter(credentials), mi_subscription_id) mi = msiclient.user_assigned_identities.get( mi_resource_group, mi_name) cluster_builder.with_kubelet_identity( kubelet_mi, mi.client_id, mi.principal_id) logging.info( "Configure kubelet identity with user assigned identity resourceId=\"{}\", clientId=\"{}\", objectId=\"{}\"" .format(kubelet_mi, mi.client_id, mi.principal_id)) elif cluster_identity_type == "service-principal": cluster_builder.with_cluster_sp(cluster_identity["clientId"], cluster_identity["password"]) logging.info("Configure cluster with service principal") else: raise Exception( "Cluster identity type \"{}\" is unknown".format( cluster_identity_type)) # Fail fast for non existing ACRs to avoid drama in case of failure AFTER cluster is created acr_role_id = None authorization_client = None if cluster_identity_type is not None and cluster_identity is not None: if cluster_identity_type == "managed-identity" and cluster_identity.get( "useAKSManagedKubeletIdentity", True) and not cluster_identity.get("inheritDSSIdentity", True): acr_name = cluster_identity.get("attachToACRName", None) if not _is_none_or_blank(acr_name): # build acr scope acr_identifier_splitted = acr_name.split('/') acr_subscription_id = subscription_id acr_resource_group = resource_group if 9 == len(acr_identifier_splitted): _, _, acr_subscription_id, _, acr_resource_group, _, _, _, acr_name = acr_identifier_splitted elif 2 == len(acr_identifier_splitted): acr_resource_group, acr_name = acr_identifier_splitted authorization_client = AuthorizationManagementClient( credentials, acr_subscription_id) acr_scope = "/subscriptions/{acr_subscription_id}/resourceGroups/{acr_resource_group}/providers/Microsoft.ContainerRegistry/registries/{acr_name}".format( **locals()) try: acr_roles = list( authorization_client.role_definitions.list( acr_scope, "roleName eq 'AcrPull'")) except ResourceNotFoundError as e: raise Exception( "ACR {} not found. Check it exists and you are Owner of it." .format(acr_scope)) if 0 == len(acr_roles): raise Exception( "Could not find the AcrPull role on the ACR {}. Check you are Owner of it." .format(acr_scope)) else: acr_role_id = acr_roles[0].id logging.info("ACR pull role id: %s", acr_role_id) # Try to run a fake role assignment. Depending on the failure type we know if we are Owner or not try: fake_role_assignment = authorization_client.role_assignments.create( scope=acr_scope, role_assignment_name=str(uuid.uuid4()), parameters={ "properties": { "role_definition_id": acr_role_id, "principal_id": "00000000-0000-0000-0000-000000000000", }, }, ) except HttpResponseError as e: if e.reason == "Forbidden" and "AuthorizationFailed" in str( e.error): raise Exception( "Cannot create role assignments on ACR {}. Check that your are Owner of it or provide an existing Kubelet identity." .format(acr_scope)) elif e.reason == "Bad Request" and "PrincipalNotFound" in str( e.error): logging.info( "Fake role assignment on ACR looks ok. Identity should be allowed to assign roles in further steps." ) else: raise (e) except Exception as e: raise (e) # Sanity check for node pools node_pool_vnets = set() for idx, node_pool_conf in enumerate(self.config.get("nodePools", [])): node_pool_builder = cluster_builder.get_node_pool_builder() nodepool_vnet = node_pool_conf.get("vnet", None) nodepool_subnet = node_pool_conf.get("subnet", None) vnet, _ = node_pool_builder.resolve_network( inherit_from_host=node_pool_conf.get( "useSameNetworkAsDSSHost"), cluster_vnet=nodepool_vnet, cluster_subnet=nodepool_subnet, connection_info=connection_info, credentials=credentials, resource_group=resource_group, dss_host_resource_group=dss_host_resource_group) node_pool_vnets.add(vnet) if 1 < len(node_pool_vnets): raise Exception( "Node pools must all share the same vnet. Current node pools configuration yields vnets {}." .format(",".join(node_pool_vnets))) elif 0 == len(node_pool_vnets): raise Exception( "You cannot deploy a cluster without any node pool.") # Check role assignments for vnet like on ACR for fail fast if not doable vnet_id = node_pool_vnets.pop() if not vnet_id.startswith("/"): vnet_name = vnet_id vnet_id = "/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Network/virtualNetworks/{vnet_name}".format( **locals()) vnet_role_id = None if cluster_identity_type is not None and cluster_identity is not None: if cluster_identity_type == "managed-identity" and cluster_identity.get( "useAKSManagedIdentity", True) and not cluster_identity.get("inheritDSSIdentity", True): authorization_client = AuthorizationManagementClient( credentials, subscription_id) try: vnet_roles = list( authorization_client.role_definitions.list( vnet_id, "roleName eq 'Contributor'")) except ResourceNotFoundError as e: raise Exception( "Vnet {} not found. Check it exists and you are Owner of it." .format(vnet_id)) if 0 == len(acr_roles): raise Exception( "Could not find the Contributor role on the vnet {}. Check you are Owner of it." .format(vnet_id)) else: vnet_role_id = vnet_roles[0].id logging.info("Vnet contributor role id: %s", acr_role_id) # Try to run a fake role assignment. Depending on the failure type we know if we are Owner or not try: fake_role_assignment = authorization_client.role_assignments.create( scope=vnet_id, role_assignment_name=str(uuid.uuid4()), parameters={ "properties": { "role_definition_id": vnet_role_id, "principal_id": "00000000-0000-0000-0000-000000000000", }, }, ) except HttpResponseError as e: if e.reason == "Forbidden" and "AuthorizationFailed" in str( e.error): raise Exception( "Cannot create role assignments on Vnet {}. Check that your are Owner of it or provide an existing Controle Plane identity." .format(vnet_id)) elif e.reason == "Bad Request" and "PrincipalNotFound" in str( e.error): logging.info( "Fake role assignment on Vnet looks ok. Identity should be allowed to assign roles in further steps." ) else: raise (e) except Exception as e: raise (e) # Access level if self.config.get("privateAccess"): cluster_builder.with_private_access( self.config.get("privateAccess")) cluster_builder.with_cluster_version( self.config.get("clusterVersion", None)) # Node pools for idx, node_pool_conf in enumerate(self.config.get("nodePools", [])): node_pool_builder = cluster_builder.get_node_pool_builder() node_pool_builder.with_idx(idx) node_pool_builder.with_vm_size(node_pool_conf.get("vmSize", None)) vnet = node_pool_conf.get("vnet", None) subnet = node_pool_conf.get("subnet", None) node_pool_builder.with_network( inherit_from_host=node_pool_conf.get( "useSameNetworkAsDSSHost"), cluster_vnet=vnet, cluster_subnet=subnet, connection_info=connection_info, credentials=credentials, resource_group=resource_group, dss_host_resource_group=dss_host_resource_group) node_pool_builder.with_availability_zones( use_availability_zones=node_pool_conf.get( "useAvailabilityZones", True)) node_pool_builder.with_node_count( enable_autoscaling=node_pool_conf.get("autoScaling", False), num_nodes=node_pool_conf.get("numNodes", None), min_num_nodes=node_pool_conf.get("minNumNodes", None), max_num_nodes=node_pool_conf.get("maxNumNodes", None)) node_pool_builder.with_mode( mode=node_pool_conf.get("mode", "Automatic"), system_pods_only=node_pool_conf.get("systemPodsOnly", True)) node_pool_builder.with_disk_size_gb( disk_size_gb=node_pool_conf.get("osDiskSizeGb", 0)) node_pool_builder.with_node_labels( node_pool_conf.get("labels", None)) node_pool_builder.with_node_taints( node_pool_conf.get("taints", None)) node_pool_builder.add_tags(self.config.get("tags", None)) node_pool_builder.add_tags(node_pool_conf.get("tags", None)) node_pool_builder.build() cluster_builder.with_node_pool( node_pool=node_pool_builder.agent_pool_profile) # Run creation logging.info("Start creation of cluster") def do_creation(): cluster_create_op = cluster_builder.build() return cluster_create_op.result() create_result = run_and_process_cloud_error(do_creation) logging.info("Cluster creation finished") # Attach to ACR acr_attachment = {} if cluster_identity_type is not None and cluster_identity is not None: if cluster_identity_type == "managed-identity" and cluster_identity.get( "useAKSManagedKubeletIdentity", True) and not cluster_identity.get("inheritDSSIdentity", True): kubelet_mi_object_id = create_result.identity_profile.get( "kubeletidentity").object_id logging.info("Kubelet Managed Identity object id: %s", kubelet_mi_object_id) if not _is_none_or_blank(acr_role_id): logging.info("Assign ACR pull role id %s to %s", acr_role_id, kubelet_mi_object_id) role_assignment = authorization_client.role_assignments.create( scope=acr_scope, role_assignment_name=str(uuid.uuid4()), parameters={ "properties": { "role_definition_id": acr_role_id, "principal_id": kubelet_mi_object_id, }, }, ) acr_attachment.update({ "name": acr_name, "resource_group": acr_resource_group, "subscription_id": acr_subscription_id, "resource_id": acr_scope, "role_assignment": role_assignment.as_dict(), }) # Attach to VNET to allow LoadBalancers creation vnet_attachment = {} if cluster_identity_type is not None and cluster_identity is not None: if cluster_identity_type == "managed-identity" and cluster_identity.get( "useAKSManagedIdentity", True) and not cluster_identity.get("inheritDSSIdentity", True): # And here we are blocked because we cant get the principal id of a System Assigned Managed Id easily control_plane_object_id = create_result.identity.principal_id logging.info("Controle Plane Managed Identity object id: %s", control_plane_object_id) if not _is_none_or_blank(vnet_role_id): logging.info("Assign Vnet contributolr role id %s to %s", vnet_role_id, control_plane_object_id) vnet_role_assignment = authorization_client.role_assignments.create( scope=vnet_id, role_assignment_name=str(uuid.uuid4()), parameters={ "properties": { "role_definition_id": vnet_role_id, "principal_id": control_plane_object_id, }, }, ) vnet_attachment.update({ "subscription_id": subscription_id, "resource_id": vnet_id, "role_assignment": vnet_role_assignment.as_dict(), }) logging.info("Fetching kubeconfig for cluster {} in {}...".format( self.cluster_name, resource_group)) def do_fetch(): return clusters_client.managed_clusters.list_cluster_admin_credentials( resource_group, self.cluster_name) get_credentials_result = run_and_process_cloud_error(do_fetch) kube_config_content = get_credentials_result.kubeconfigs[ 0].value.decode("utf8") logging.info("Writing kubeconfig file...") kube_config_path = os.path.join(os.getcwd(), "kube_config") with open(kube_config_path, 'w') as f: f.write(kube_config_content) overrides = make_overrides( self.config, yaml.safe_load(kube_config_content), kube_config_path, acr_name=None if _is_none_or_blank(acr_attachment) else acr_attachment["name"], ) return [ overrides, { "kube_config_path": kube_config_path, "cluster": create_result.as_dict(), "acr_attachment": acr_attachment, "vnet_attachment": vnet_attachment } ]
def get_client(self, subscription_id: str): return AuthorizationManagementClient( self.credentials.get_credentials('arm'), subscription_id=subscription_id)
from azure.mgmt.resource import ResourceManagementClient from azure.mgmt.authorization import AuthorizationManagementClient subscription_id = '' scope = '' role_assignment_name = '199d4427-8709-4d93-a15b-61d377708ae6' role_assignment_id = '' + '199d4427-8709-4d93-a15b-61d377708ae6' role_definition_id = '' principal_id = '' if __name__ == "__main__": authorization_client = get_client_from_cli_profile( AuthorizationManagementClient) # , subscription_id=subscription_id ) authorization_models = AuthorizationManagementClient.models( '2018-09-01-preview') parameters = authorization_models.RoleAssignmentCreateParameters( role_definition_id=role_definition_id, principal_id=principal_id, principal_type='User', can_delegate=None) # role_list = authorization_client.role_assignments.list(filter=None, custom_headers=None, raw=False) print('########################################################') # for role_assignment in role_list: # print('id: {}'.format(role_assignment.id)) # print('name: {}'.format(role_assignment.name)) # print('principal_id: {}'.format(role_assignment.principal_id))
def create_instance(self, metadata, verbose=False): from azure.common.credentials import ServicePrincipalCredentials from azure.mgmt.resource import ResourceManagementClient from azure.mgmt.compute import ComputeManagementClient from azure.mgmt.network import NetworkManagementClient from azure.mgmt.compute.models import DiskCreateOption from azure.mgmt.authorization import AuthorizationManagementClient # TODO: Remove this guard after Azure fixes the issue if self.preemptible: print( "Spot instances are not functional on our subscription just yet. Azure is currently investigating this issue." ) print("This guard will be removed as soon as the issue is fixed.") exit(1) azure_resource_group = self.azure_resource_group_base + uuid.uuid4( ).hex[:6] region = metadata['region'] instance_type_str = 'a spot instance' if self.preemptible else 'an instance' print('Creating {} of type {} in {}'.format(instance_type_str, self.instance_type, region)) credentials = ServicePrincipalCredentials( client_id=self.azure_client_id, secret=self.azure_authentication_key, tenant=self.azure_tenant_id, ) resource_group_client = ResourceManagementClient( credentials, self.subscription_id) network_client = NetworkManagementClient(credentials, self.subscription_id) compute_client = ComputeManagementClient(credentials, self.subscription_id) authorization_client = AuthorizationManagementClient( credentials, self.subscription_id, ) resource_group_params = { 'location': region, 'tags': self.tags, } resource_group = resource_group_client.resource_groups.create_or_update( azure_resource_group, resource_group_params) vm_name = 'doodad-vm' print('VM name:', vm_name) print('resource group id:', resource_group.id) public_ip_addess_params = { 'location': region, 'public_ip_allocation_method': 'Dynamic' } try: poller = network_client.public_ip_addresses.create_or_update( azure_resource_group, 'myIPAddress', public_ip_addess_params) publicIPAddress = poller.result() vnet_params = { 'location': region, 'address_space': { 'address_prefixes': ['10.0.0.0/16'] } } network_client.virtual_networks.create_or_update( azure_resource_group, 'myVNet', vnet_params) subnet_params = {'address_prefix': '10.0.0.0/24'} poller = network_client.subnets.create_or_update( azure_resource_group, 'myVNet', 'mySubnet', subnet_params) subnet_info = poller.result() nic_params = { 'location': region, 'ip_configurations': [{ 'name': 'myIPConfig', 'public_ip_address': publicIPAddress, 'subnet': { 'id': subnet_info.id } }] } poller = network_client.network_interfaces.create_or_update( azure_resource_group, 'myNic', nic_params) nic = poller.result() startup_script_str = metadata['startup_script'] # TODO: how do we use this shutdown script? shutdown_script_str = metadata['shutdown_script'] for old, new in [ ('DOODAD_LOG_PATH', self.log_path), ('DOODAD_STORAGE_ACCOUNT_NAME', self.connection_info['AccountName']), ('DOODAD_STORAGE_ACCOUNT_KEY', self.connection_info['AccountKey']), ('DOODAD_CONTAINER_NAME', self.azure_container), ('DOODAD_REMOTE_SCRIPT_PATH', metadata['remote_script_path']), ('DOODAD_REMOTE_SCRIPT_ARGS', metadata['remote_script_args']), ('DOODAD_SHELL_INTERPRETER', metadata['shell_interpreter']), ('DOODAD_TERMINATE_ON_END', metadata['terminate']), ('DOODAD_OVERWRITE_LOGS', metadata['overwrite_logs']), ('DOODAD_INSTALL_NVIDIA_EXTENSION', metadata['install_nvidia_extension']) ]: startup_script_str = startup_script_str.replace(old, new) custom_data = b64e(startup_script_str) # vm_name = ('doodad'+str(uuid.uuid4()).replace('-', ''))[:15] # this authenthication code is based on # https://docs.microsoft.com/en-us/samples/azure-samples/compute-python-msi-vm/compute-python-msi-vm/ from azure.mgmt.compute import models params_identity = { 'type': models.ResourceIdentityType.system_assigned, } vm_parameters = { 'location': region, 'os_profile': { 'computer_name': vm_name, 'admin_username': '******', 'admin_password': '******', 'custom_data': custom_data, }, 'hardware_profile': { 'vm_size': self.instance_type }, 'storage_profile': { 'image_reference': { "offer": "UbuntuServer", "publisher": "Canonical", "sku": "18.04-LTS", "urn": "Canonical:UbuntuServer:18.04-LTS:latest", "urnAlias": "UbuntuLTS", "version": "latest" } }, 'network_profile': { 'network_interfaces': [{ 'id': nic.id }] }, 'tags': self.tags, 'identity': params_identity, } if metadata['use_data_science_image']: vm_parameters['storage_profile']['image_reference'] = { "offer": "ubuntu-1804", "publisher": "microsoft-dsvm", "sku": "1804", "urn": "microsoft-dsvm:ubuntu-1804:1804:latest", "version": "latest" } if self.preemptible: spot_args = { "priority": "Spot", "evictionPolicy": "Deallocate", "billingProfile": { "maxPrice": self.spot_max_price } } vm_parameters.update(spot_args) vm_poller = compute_client.virtual_machines.create_or_update( resource_group_name=azure_resource_group, vm_name=vm_name, parameters=vm_parameters, ) vm_result = vm_poller.result() # We need to ensure that the VM has permissions to delete its own # resource group. We'll assign the built-in "Contributor" role and limit # its scope to this resource group. role_name = 'Contributor' roles = list( authorization_client.role_definitions.list( resource_group.id, filter="roleName eq '{}'".format(role_name))) assert len(roles) == 1 contributor_role = roles[0] # Add RG scope to the MSI tokenddd for msi_identity in [vm_result.identity.principal_id]: authorization_client.role_assignments.create( resource_group.id, uuid.uuid4(), # Role assignment random name { 'role_definition_id': contributor_role.id, 'principal_id': msi_identity }) except (Exception, KeyboardInterrupt) as e: if 'resource_group' in locals(): if verbose: print("Deleting created resource group id: {}.".format( resource_group.id)) resource_group_client.resource_groups.delete( azure_resource_group) from msrestazure.azure_exceptions import CloudError as AzureCloudError if isinstance(e, AzureCloudError): print("Error when creating VM. Error message:") print(e.message + '\n') return False, e raise e success = True return success, resource_group.id
secret = os.getenv('AZURE_CLIENT_SECRET'), tenant = os.getenv('AZURE_TENANT_ID')) return credentials except TypeError: print('\nERROR: Kindly Export the below Environmental vairables to continue ..') print('\nAZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID & AZURE_SUBSCRIPTION_ID') sys.exit(1) credentials = get_credential() compute_client = ComputeManagementClient(credentials,subscriptionId) network_client = NetworkManagementClient(credentials,subscriptionId) storage_client = StorageManagementClient(credentials,subscriptionId) resource_client = ResourceManagementClient(credentials, subscriptionId) auth_client = AuthorizationManagementClient(credentials, subscriptionId) kv_client = KeyVaultManagementClient(credentials,subscriptionId) funcapp_client = WebSiteManagementClient(credentials,subscriptionId) def banner(): size = int(os.popen('tput cols').read().strip()) print('\n') print('#' * size) #print(comment.center(size)) #print('#' * size,'\n') def run_script(script_location): #args = shlex.split(command) output = subprocess.call([script_location]) return output
def getAuthorizationManagementClient(self, subscriptionId): return AuthorizationManagementClient(self.__credentialsProvider.getManagementCredentials(), subscriptionId)
def add_storage_account(self): """ Creates a storage account then adds the storage account to the vault to manage its keys. """ from azure.mgmt.storage import StorageManagementClient from azure.mgmt.storage.models import StorageAccountCreateParameters, Sku, SkuName, Kind from msrestazure.azure_active_directory import AADTokenCredentials from azure.mgmt.authorization.models import RoleAssignmentCreateParameters from azure.keyvault.models import StorageAccountAttributes from azure.mgmt.authorization import AuthorizationManagementClient self.config.storage_account_name = get_name('sa', '') # only user accounts with access to the storage account keys can add a storage account to # a vault. For this reason this sample creates the storage account with a user account # authenticated through device login rather than the service principal credentials used # in other samples. # create the StorageManagementClient with user token credentials user_token_creds = AADTokenCredentials( self.get_user_token('https://management.core.windows.net/')) print('creating storage account %s' % self.config.storage_account_name) storage_mgmt_client = StorageManagementClient( user_token_creds, self.config.subscription_id) # create the storage account sa_params = StorageAccountCreateParameters( sku=Sku(SkuName.standard_ragrs), kind=Kind.storage, location=self.config.location) sa = storage_mgmt_client.storage_accounts.create( resource_group_name=self.config.group_name, account_name=self.config.storage_account_name, parameters=sa_params).result() # the KeyVault service must be given the "Storage Account Key Operator Service Role" on the # storage account before the storage account can be added to the vault print( 'granting Azure Key Vault the "Storage Account Key Operator Service Role" on the storage account' ) # find the role definition for "Storage Account Key Operator Service Role" filter_str = 'roleName eq \'Storage Account Key Operator Service Role\'' authorization_mgmt_client = AuthorizationManagementClient( user_token_creds, self.config.subscription_id) role_id = list( authorization_mgmt_client.role_definitions.list( scope='/', filter=filter_str))[0].id # create a role assignment granting the key vault service principal this role role_params = RoleAssignmentCreateParameters( role_definition_id=role_id, # the Azure Key Vault service id principal_id='93c27d83-f79b-4cb2-8dd4-4aa716542e74') authorization_mgmt_client.role_assignments.create( scope=sa.id, role_assignment_name=str(uuid.uuid4()), parameters=role_params) # since the set_storage_account can only be called by a user account with access to the keys of # the storage account, we grant the user that created the storage account access to the vault # and add the storage account to the vault vault = self.get_sample_vault() # grant the user access the vault self.grant_access_to_sample_vault(vault, self._user_oid) # add the storage account to the vault using the users KeyVaultClient print('adding storage acount %s to vault %s' % (self.config.storage_account_name, vault.name)) attributes = StorageAccountAttributes(enabled=True) self.keyvault_user_client.set_storage_account( vault_base_url=self.sample_vault_url, storage_account_name=sa.name, resource_id=sa.id, active_key_name='key1', auto_regenerate_key=True, regeneration_period='P30D', storage_account_attributes=attributes)
def run(self, args): """Run the remediation job. :param args: List of arguments provided to the job. :type args: list. :returns: int """ params = self.parse(args[1]) client_id = os.environ.get("AZURE_CLIENT_ID") client_secret = os.environ.get("AZURE_CLIENT_SECRET") tenant_id = os.environ.get("AZURE_TENANT_ID") # credential for Storage Account and Key Vault management client credential = ClientSecretCredential( client_id=client_id, client_secret=client_secret, tenant_id=tenant_id, ) # credential for AzureGraphRbacManagementClient credentials_graph = ServicePrincipalCredentials( client_id=client_id, secret=client_secret, tenant=tenant_id, resource="https://graph.windows.net", ) # credential for SqlManagementClient and credentials = ServicePrincipalCredentials( client_id=client_id, secret=client_secret, tenant=tenant_id, ) client_storage = StorageManagementClient(credential, params["subscription_id"]) keyvault_client = KeyVaultManagementClient( credential, params["subscription_id"] ) graph_client = GraphRbacManagementClient( credentials_graph, tenant_id, base_url=None ) monitor_client = MonitorClient(credential, params["subscription_id"]) client = SqlManagementClient( credentials, params["subscription_id"], base_url=None ) client_authorization = AuthorizationManagementClient( credential, params["subscription_id"], api_version="2018-01-01-preview" ) return self.remediate( client_id, tenant_id, credential, client, client_storage, keyvault_client, graph_client, monitor_client, client_authorization, params["resource_group_name"], params["sql_server_name"], params["region"], params["subscription_id"], )