def update_account(self): self.log('Update storage account {0}'.format(self.name)) if self.account_type: if self.account_type != self.account_dict['sku_name']: # change the account type if self.account_dict['sku_name'] in [SkuName.premium_lrs, SkuName.standard_zrs]: self.fail("Storage accounts of type {0} and {1} cannot be changed.".format( SkuName.premium_lrs, SkuName.standard_zrs)) if self.account_type in [SkuName.premium_lrs, SkuName.standard_zrs]: self.fail("Storage account of type {0} cannot be changed to a type of {1} or {2}.".format( self.account_dict['sku_name'], SkuName.premium_lrs, SkuName.standard_zrs)) self.results['changed'] = True self.account_dict['sku_name'] = self.account_type if self.results['changed'] and not self.check_mode: # Perform the update. The API only allows changing one attribute per call. try: self.log("sku_name: %s" % self.account_dict['sku_name']) self.log("sku_tier: %s" % self.account_dict['sku_tier']) sku = Sku(SkuName(self.account_dict['sku_name'])) sku.tier = SkuTier(self.account_dict['sku_tier']) parameters = StorageAccountUpdateParameters(sku=sku) self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters) except Exception as exc: self.fail("Failed to update account type: {0}".format(str(exc))) if self.custom_domain: if not self.account_dict['custom_domain'] or \ self.account_dict['custom_domain'] != self.account_dict['custom_domain']: self.results['changed'] = True self.account_dict['custom_domain'] = self.custom_domain if self.results['changed'] and not self.check_mode: new_domain = CustomDomain(name=self.custom_domain['name'], use_sub_domain=self.custom_domain['use_sub_domain']) parameters = StorageAccountUpdateParameters(custom_domain=new_domain) try: self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters) except Exception as exc: self.fail("Failed to update custom domain: {0}".format(str(exc))) update_tags, self.account_dict['tags'] = self.update_tags(self.account_dict['tags']) if update_tags: self.results['changed'] = True if not self.check_mode: parameters = StorageAccountUpdateParameters(tags=self.account_dict['tags']) try: self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters) except Exception as exc: self.fail("Failed to update tags: {0}".format(str(exc)))
def run_action(credentials, rule, entity, params): logging.info(f'{__file__} - ${run_action.__name__} started') subscription_id = entity['accountNumber'] group_name = entity['resourceGroup']['name'] storage_account_name = entity['name'] logging.info( f'{__file__} - subscription_id : {subscription_id} - group_name : {group_name} - storage_account : {storage_account_name}' ) if not subscription_id or not credentials: return raise_credentials_error() try: storage_client = StorageManagementClient(credentials, subscription_id) storage_client.storage_accounts.update( group_name, storage_account_name, StorageAccountUpdateParameters(enable_https_traffic_only=True)) id = entity['id'] msg = f'Secure transfer was enabled successfully in storage account. id: {id}' logging.info(f'{__file__} - {msg}') return f'{msg}' except CloudError as e: msg = f'Unexpected error : {e.message}' logging.info(f'{__file__} - {msg}') return msg
def run_action(credentials, rule, entity, params): logging.info(f'Parameters are: {params}') logging.info(f'{__file__} - ${run_action.__name__} started') subscription_id = entity['accountNumber'] group_name = entity['resourceGroup']['name'] storage_account_name = entity['name'] logging.info( f'{__file__} - subscription_id : {subscription_id} - group_name : {group_name} - storage_account : {storage_account_name}' ) if not subscription_id or not credentials: return raise_credentials_error() try: storage_client = StorageManagementClient(credentials, subscription_id) p1 = StorageAccountUpdateParameters( allow_blob_public_access=False ) #set the allow_blob_public_access settings here storage_client.storage_accounts.update( group_name, storage_account_name, p1) #then use update method to update this feature msg = f'Allow blob public access was successfully configured to disable for storage account: {storage_account_name}' logging.info(f'{__file__} - {msg}') return f'{msg}' except CloudError as e: msg = f'Unexpected error : {e.message}' logging.info( f'Unable to set Allow blob public access property to false') logging.info(f'{__file__} - {msg}') return msg
def _process_resource(self, resource): rule_set = NetworkRuleSet(default_action=self.data['default-action']) if 'ip-rules' in self.data: rule_set.ip_rules = [ IPRule( ip_address_or_range=r['ip-address-or-range'], action='Allow') # 'Allow' is the only allowed action for r in self.data['ip-rules']] if 'virtual-network-rules' in self.data: rule_set.virtual_network_rules = [ VirtualNetworkRule( virtual_network_resource_id=r['virtual-network-resource-id'], action='Allow') # 'Allow' is the only allowed action for r in self.data['virtual-network-rules']] if len(self.data.get('bypass', [])) > 0: rule_set.bypass = '******'.join(self.data['bypass']) else: rule_set.bypass = '******' self.client.storage_accounts.update( resource['resourceGroup'], resource['name'], StorageAccountUpdateParameters(network_rule_set=rule_set))
def ensure_identity_assigned(self, resource_group_name, account_name, region, storage_client): """Checks if the Identity is assigned to the Storage. If not then it assigns the identity :param storage_client: Instance of the Azure StorageManagementClient. :param resource_group_name: Resource group name :param account_name: Storage Account name :param region: location in which the Storage Account exists :type storage_client: object :type resource_group_name: str :type account_name: str :type region: str :returns: Principal Id of the Storage Account :rtype: str """ stg_acc = storage_client.storage_accounts.get_properties( resource_group_name=resource_group_name, account_name=account_name, ) if stg_acc.identity is None: logging.info( f"Assigning Identity to the Storage Account {account_name}") logging.info("executing storage_client.storage_accounts.update") logging.info(f" resource_group_name={resource_group_name}") logging.info(f" account_name={account_name}") updated_stg_acc = storage_client.storage_accounts.update( resource_group_name=resource_group_name, account_name=account_name, parameters=StorageAccountUpdateParameters(identity=Identity( type="SystemAssigned")), ) return updated_stg_acc.identity.principal_id else: return stg_acc.identity.principal_id
def test_storage_settings_require_secure_transfer(self): with patch('azure.mgmt.storage.v%s.operations.' '_storage_accounts_operations.StorageAccountsOperations.update' % self._get_storage_management_client_api_string()) as update_storage_mock: p = self.load_policy({ 'name': 'my-first-policy', 'resource': 'azure.storage', 'filters': [ {'type': 'value', 'key': 'name', 'op': 'glob', 'value_type': 'normalize', 'value': 'cctstorage*'} ], 'actions': [ {'type': 'require-secure-transfer', 'value': True} ] }) p.run() args = update_storage_mock.call_args_list[0][0] self.assertEqual(args[0], 'test_storage') self.assertTrue(args[1].startswith('cctstorage')) self.assertEqual(args[2], StorageAccountUpdateParameters(enable_https_traffic_only=True))
def remediate(self, client, resource_group_name, account_name): """Block public access to blob container :param client: Instance of the Azure NetworkManagementClient. :param resource_group_name: The name of the resource group to which the storage account belongs :param account_name: The name of the storage account. You must specify the account name in the request. :type resource_group_name: str. :type account_name: str. :returns: Integer signaling success or failure :rtype: int :raises: msrestazure.azure_exceptions.CloudError """ update_params = StorageAccountUpdateParameters( enable_https_traffic_only=True) # Allow only https traffic for the storage account logging.info("Enabling HTTPS only traffic for storage account") try: logging.info(" executing client.storage_accounts.update") logging.info(f" resource_group_name={resource_group_name}") logging.info(f" account_name={account_name}") client.storage_accounts.update( resource_group_name=resource_group_name, account_name=account_name, parameters=update_params, ) except Exception as e: logging.error(f"{str(e)}") raise return 0
def remediate(self, client, resource_group_name, account_name): """Set Default Action for network access rule for a Storage Account as Deny :param client: Instance of the Azure StorageManagementClient. :param resource_group_name: The name of the resource group to which the storage account belongs :param account_name: The name of the storage account. :type resource_group_name: str. :type account_name: str. :returns: Integer signaling success or failure :rtype: int :raises: msrestazure.azure_exceptions.CloudError """ # Setting Default Action for network as Deny updated_network_rule_set = NetworkRuleSet(default_action="Deny") logging.info("Setting default action in network rule set to Deny") try: logging.info(" executing client.storage_accounts.update") logging.info(f" resource_group_name={resource_group_name}") logging.info(f" account_name={account_name}") client.storage_accounts.update( resource_group_name=resource_group_name, account_name=account_name, parameters=StorageAccountUpdateParameters( network_rule_set=updated_network_rule_set), ) except Exception as e: logging.error(f"{str(e)}") raise return 0
def update_storage_account_encryption(self, storage_client, resource_group_name, stg_name, key_name, vault_uri): """Updates Storage Account Encryption for a Storage Account. :param storage_client: Instance of the Azure StorageManagementClient. :param resource_group_name: The name of the resource group. :param stg_name: The Storage Account name. :param key_name: Name of the Key to encrypt the Storage Account with. :param vault_uri: Key Vault uri in which the Key exists. :type storage_client: object :type resource_group_name: str :type stg_name: str :type key_name: str :type vault_uri: str :returns: None :rtype: None """ logging.info( " Encrypting Storage Account with Customer Managed Key") logging.info(" executing storage_client.storage_accounts.update") logging.info(f" resource_group_name={resource_group_name}") logging.info(f" account_name={stg_name}") logging.info(f" key_vault_uri={vault_uri}") logging.info(f" key_name={key_name}") storage_client.storage_accounts.update( resource_group_name=resource_group_name, account_name=stg_name, parameters=StorageAccountUpdateParameters(encryption=Encryption( key_source=KeySource.MICROSOFT_KEYVAULT, key_vault_properties=KeyVaultProperties( key_name=key_name, key_vault_uri=vault_uri, ), ), ), )
def _process_resource(self, resource): rules = self._build_ip_rules(resource, self.data.get('ip-rules', [])) # Build out the ruleset model to update the resource rule_set = NetworkRuleSet(default_action=self.data.get('default-action', 'Deny')) # If the user has too many rules log and skip if len(rules) > self.rule_limit: self._log.error("Skipped updating firewall for %s. " "%s exceeds maximum rule count of %s." % (resource['name'], len(rules), self.rule_limit)) return # Add IP rules rule_set.ip_rules = [IPRule(ip_address_or_range=r) for r in rules] # Add VNET rules vnet_rules = self._build_vnet_rules(resource, self.data.get('virtual-network-rules', [])) rule_set.virtual_network_rules = [ VirtualNetworkRule(virtual_network_resource_id=r) for r in vnet_rules] # Configure BYPASS rule_set.bypass = self._build_bypass_rules(resource, self.data.get('bypass', [])) # Update resource self.client.storage_accounts.update( resource['resourceGroup'], resource['name'], StorageAccountUpdateParameters(network_rule_set=rule_set))
def tearDown(self): for restore in self.restore: resource = next(r for r in self.backup_resources if r.name.startswith(restore)) self.client.storage_accounts.update( rg_name, resource.name, StorageAccountUpdateParameters( network_rule_set=resource.network_rule_set))
def tearDown(self): resources = self._get_resources() self.assertEqual(len(resources), 1) resource = resources[0] resource.network_rule_set.ip_rules = [] resource.network_rule_set.virtual_network_rules = [] resource.network_rule_set.bypass = '******' resource.network_rule_set.default_action = DefaultAction.allow self.client.storage_accounts.update( rg_name, resource.name, StorageAccountUpdateParameters( network_rule_set=resource.network_rule_set))
def add_tag_storage_account(storage_account_name, registry_name): '''Add a new tag (key, value) to the storage account. :param str storage_account_name: The name of storage account :param str registry_name: The name of container registry ''' from azure.mgmt.storage.models import StorageAccountUpdateParameters storage_account_resource_group, tags = _parse_storage_account( storage_account_name) tags[registry_name.lower()] = 'acr' client = get_storage_service_client().storage_accounts return client.update(storage_account_resource_group, storage_account_name, StorageAccountUpdateParameters(tags=tags))
def set_storage_account_properties( resource_group_name, account_name, sku=None, tags=None, custom_domain=None, encryption=None, access_tier=None): ''' Update storage account property (only one at a time).''' from azure.mgmt.storage.models import \ (StorageAccountUpdateParameters, Sku, CustomDomain, Encryption, AccessTier) scf = storage_client_factory() params = StorageAccountUpdateParameters( sku=Sku(sku) if sku else None, tags=tags, custom_domain=CustomDomain(custom_domain) if custom_domain else None, encryption=encryption, access_tier=AccessTier(access_tier) if access_tier else None) return scf.storage_accounts.update(resource_group_name, account_name, params)
def _process_resource(self, resource): # Build out the ruleset model to update the resource rule_set = NetworkRuleSet( default_action=self.data.get('default-action', 'Deny')) # Add IP rules if self.data.get('ip-rules') is not None: existing_ip = [ r['value'] for r in resource['properties']['networkAcls'].get( 'ipRules', []) ] ip_rules = self._build_ip_rules(existing_ip, self.data.get('ip-rules', [])) # If the user has too many rules raise exception if len(ip_rules) > self.rule_limit: raise ValueError( "Skipped updating firewall for %s. " "%s exceeds maximum rule count of %s." % (resource['name'], len(ip_rules), self.rule_limit)) rule_set.ip_rules = [ IPRule(ip_address_or_range=r) for r in ip_rules ] # Add VNET rules if self.data.get('virtual-network-rules') is not None: existing_vnet = \ [r['id'] for r in resource['properties']['networkAcls'].get('virtualNetworkRules', [])] vnet_rules = \ self._build_vnet_rules(existing_vnet, self.data.get('virtual-network-rules', [])) rule_set.virtual_network_rules = \ [VirtualNetworkRule(virtual_network_resource_id=r) for r in vnet_rules] # Configure BYPASS if self.data.get('bypass-rules') is not None: existing_bypass = resource['properties']['networkAcls'].get( 'bypass', '').split(',') rule_set.bypass = self._build_bypass_rules( existing_bypass, self.data.get('bypass-rules', [])) # Update resource self.client.storage_accounts.update( resource['resourceGroup'], resource['name'], StorageAccountUpdateParameters(network_rule_set=rule_set))
def set_storage_account_properties(resource_group_name, account_name, account_type=None, tags='', custom_domain=None): ''' Update storage account property (only one at a time). :param str custom_domain:the custom domain name ''' from azure.mgmt.storage.models import StorageAccountUpdateParameters, CustomDomain, Sku scf = storage_client_factory() # TODO Add the new params encryption and access_tier after rc5 update sku = Sku(account_type) if account_type else None params = StorageAccountUpdateParameters(sku=sku, tags=tags, custom_domain=custom_domain) return scf.storage_accounts.update(resource_group_name, account_name, params)
def delete_tag_storage_account(storage_account_name, registry_name): '''Delete a tag (key, value) from the storage account, if value matches registry_name. :param str storage_account_name: The name of storage account :param str registry_name: The name of container registry ''' from azure.mgmt.storage.models import StorageAccountUpdateParameters storage_account_resource_group, tags = _parse_storage_account( storage_account_name) registry_name = registry_name.lower() if registry_name in tags and tags[registry_name] == 'acr': del tags[registry_name] client = get_storage_service_client().storage_accounts return client.update(storage_account_resource_group, storage_account_name, StorageAccountUpdateParameters(tags=tags))
def run_action(credentials, rule, entity, params): logging.info(f'Parameters are: {params}') vnet_group_name, vnet_name, subnet_name = params logging.info(f'{__file__} - ${run_action.__name__} started') subscription_id = entity['accountNumber'] group_name = entity['resourceGroup']['name'] storage_account_name = entity['name'] logging.info( f'{__file__} - subscription_id : {subscription_id} - group_name : {group_name} - storage_account : {storage_account_name}' ) subnet_path = '/subscriptions/' + subscription_id + '/resourceGroups/' + vnet_group_name + \ '/providers/Microsoft.Network/virtualNetworks/' + \ vnet_name + '/subnets/' + subnet_name if not subscription_id or not credentials: return raise_credentials_error() try: storage_client = StorageManagementClient(credentials, subscription_id) storage_client.storage_accounts.update( group_name, storage_account_name, StorageAccountUpdateParameters(network_rule_set=NetworkRuleSet( default_action='Deny', virtual_network_rules=[ VirtualNetworkRule(virtual_network_resource_id=subnet_path) ]))) msg = f'Private network access was successfully configured for storage account: {storage_account_name}' logging.info(f'{__file__} - {msg}') return f'{msg}' except CloudError as e: msg = f'Unexpected error : {e.message}' if 'SubnetsHaveNoServiceEndpointsConfigured' in msg: logging.info( f'Unable to set private access as the VNet does not have Service Endpoints configured' ) logging.info(f'{__file__} - {msg}') return msg
def remediate(self, client, resource_group_name, account_name): """Enable Trusted Microsoft Services for Storage Account access :param client: Instance of the Azure StorageManagementClient. :param resource_group_name: The name of the resource group to which the storage account belongs. :param account_name: The name of the storage account. :param client: str. :type resource_group_name: str. :type account_name: str. :returns: Integer signaling success or failure. :rtype: int :raises: msrestazure.azure_exceptions.CloudError """ try: storage_account = client.storage_accounts.get_properties( resource_group_name=resource_group_name, account_name=account_name, ) if storage_account.network_rule_set.bypass is None: bypass = "******" else: bypass = storage_account.network_rule_set.bypass + ", AzureServices" logging.info(" executing client.blob_containers.update") logging.info(f" resource_group_name={resource_group_name}") logging.info(f" account_name={account_name}") # Enabling Trusted Microsoft Services for Storage Account access client.storage_accounts.update( resource_group_name=resource_group_name, account_name=account_name, parameters=StorageAccountUpdateParameters( network_rule_set=NetworkRuleSet( bypass=bypass, default_action="Deny" ) ), ) except Exception as e: logging.error(f"{str(e)}") raise return 0
def update_storage_account(instance, sku=None, tags=None, custom_domain=None, use_subdomain=None, encryption=None, access_tier=None): from azure.mgmt.storage.models import \ (StorageAccountUpdateParameters, Sku, CustomDomain, AccessTier) domain = instance.custom_domain if custom_domain is not None: domain = CustomDomain(custom_domain) if use_subdomain is not None: domain.name = use_subdomain == 'true' params = StorageAccountUpdateParameters( sku=Sku(sku) if sku is not None else instance.sku, tags=tags if tags is not None else instance.tags, custom_domain=domain, encryption=encryption if encryption is not None else instance.encryption, access_tier=AccessTier(access_tier) if access_tier is not None else instance.access_tier) return params
def run_example(): """Storage management example.""" # # Create the Resource Manager Client with an Application (service principal) token provider # credentials, subscription_id = get_credentials() resource_client = ResourceManagementClient(credentials, subscription_id) storage_client = StorageManagementClient(credentials, subscription_id) # You MIGHT need to add Storage as a valid provider for these credentials # If so, this operation has to be done only once for each credentials resource_client.providers.register('Microsoft.Storage') # Create Resource group print('Create Resource Group') resource_group_params = {'location':'westus'} print_item(resource_client.resource_groups.create_or_update(GROUP_NAME, resource_group_params)) # Check availability print('Check name availability') bad_account_name = 'invalid-or-used-name' availability = storage_client.storage_accounts.check_name_availability(bad_account_name) print('The account {} is available: {}'.format(bad_account_name, availability.name_available)) print('Reason: {}'.format(availability.reason)) print('Detailed message: {}'.format(availability.message)) print('\n\n') # Create a storage account print('Create a storage account') storage_async_operation = storage_client.storage_accounts.create( GROUP_NAME, STORAGE_ACCOUNT_NAME, StorageAccountCreateParameters( sku=Sku(SkuName.standard_ragrs), kind=Kind.storage, location='westus' ) ) storage_account = storage_async_operation.result() print_item(storage_account) print('\n\n') # Get storage account properties print('Get storage account properties') storage_account = storage_client.storage_accounts.get_properties( GROUP_NAME, STORAGE_ACCOUNT_NAME) print_item(storage_account) print("\n\n") # List Storage accounts print('List storage accounts') for item in storage_client.storage_accounts.list(): print_item(item) print("\n\n") # List Storage accounts by resource group print('List storage accounts by resource group') for item in storage_client.storage_accounts.list_by_resource_group(GROUP_NAME): print_item(item) print("\n\n") # Get the account keys print('Get the account keys') storage_keys = storage_client.storage_accounts.list_keys(GROUP_NAME, STORAGE_ACCOUNT_NAME) storage_keys = {v.key_name: v.value for v in storage_keys.keys} print('\tKey 1: {}'.format(storage_keys['key1'])) print('\tKey 2: {}'.format(storage_keys['key2'])) print("\n\n") # Regenerate the account key 1 print('Regenerate the account key 1') storage_keys = storage_client.storage_accounts.regenerate_key( GROUP_NAME, STORAGE_ACCOUNT_NAME, 'key1') storage_keys = {v.key_name: v.value for v in storage_keys.keys} print('\tNew key 1: {}'.format(storage_keys['key1'])) print("\n\n") # Update storage account print('Update storage account') storage_account = storage_client.storage_accounts.update( GROUP_NAME, STORAGE_ACCOUNT_NAME, StorageAccountUpdateParameters( sku=Sku(SkuName.standard_grs) ) ) print_item(storage_account) print("\n\n") # Delete the storage account print('Delete the storage account') storage_client.storage_accounts.delete(GROUP_NAME, STORAGE_ACCOUNT_NAME) print("\n\n") # 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("Deleted: {}".format(GROUP_NAME)) print("\n\n") # List usage print('List usage') for usage in storage_client.usage.list(): print('\t{}'.format(usage.name.value))
def _process_resource(self, resource): self.client.storage_accounts.update( resource['resourceGroup'], resource['name'], StorageAccountUpdateParameters( enable_https_traffic_only=self.data.get('value')))
#PRINTING PROPERTIES OF STORAGE ACCOUNT print("Properties of Storage Account are as follow :") for item in storage_client.storage_accounts.list(): print(item) #PRINTING SPECIFIC PROPERTIES VALUES print("Current Value for Allow Blob Public Access Property : " + str(storage_account.allow_blob_public_access)) print("Current Value for Allow Minimum TLS Version : " + storage_account.minimum_tls_version) #UPDATING THE PROPERTY VALUE storage_client.storage_accounts.update( AZURE_STORAGE_RG_NAME, AZURE_STORAGE_ACCOUNT_NAME, StorageAccountUpdateParameters(allow_blob_public_access=False)) storage_client.storage_accounts.update( AZURE_STORAGE_RG_NAME, AZURE_STORAGE_ACCOUNT_NAME, StorageAccountUpdateParameters(minimum_tls_version='TLS1_1')) #GETTING UPDATED PROPERTIES OF STORAGE ACCOUNT storage_account = storage_client.storage_accounts.get_properties( resource_group_name=AZURE_STORAGE_RESOURCE_NAME, account_name=AZURE_STORAGE_ACCOUNT_NAME) #PRINTING NEW PROPERTIES VALUES print("New Value for Allow Blob Public Access Property : " + str(storage_account.allow_blob_public_access)) print("New Value for Allow Minimum TLS Version : " + storage_account.minimum_tls_version)