def create_resource(self, name, **kwargs): if self.is_live: storage_account = kwargs.pop("storage_account") storage_account_key = kwargs.pop("storage_account_key") sas_token = generate_account_sas( account_name=storage_account.name, account_key=storage_account_key, resource_types=ResourceTypes(container=True, object=True), permission=AccountSasPermissions(create=True, list=True, write=True, read=True, add=True, delete=True, delete_previous_version=True), expiry=datetime.utcnow() + timedelta(minutes=5), ) blob_client = BlobServiceClient( storage_account.primary_endpoints.blob, sas_token) container = blob_client.create_container(name) container_uri = storage_account.primary_endpoints.blob + container.container_name self.test_class_instance.scrubber.register_name_pair( sas_token, "redacted") self.test_class_instance.scrubber.register_name_pair( container_uri, "https://storage/container") else: sas_token = "fake-sas" container_uri = "https://storage/container" return {"container_uri": container_uri, "sas_token": sas_token}
def generate_token(): blob_service_client = BlobServiceClient(account_url=config.URL, credential=config.SHARED_KEY) try: for i in blob_service_client.list_containers(): continue except: return 'cannot generate the sas token' container_client = blob_service_client.get_container_client("mycontainer") # container_token = generate_container_sas( # container_client.account_name, # container_client.container_name, # account_key=container_client.credential.account_key, # policy_id='my-access-policy-id' # ) sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True, write=True, add=True, create=True), expiry=datetime.utcnow() + timedelta(hours=1)) return sas_token
def upload_file_on_cloud(file_name): try: tar = tarfile.open(os.path.join(settings.MEDIA_ROOT, file_name), "r:gz") for member in tar.getmembers(): if ".bin" in member.name: tar.extract(member.name, settings.MEDIA_ROOT) blob = BlobClient.from_connection_string( conn_str= "DefaultEndpointsProtocol=https;AccountName=fotastorage1;AccountKey=ZH4xN/rJcvButa2oTELpASSq2Ag2mMDQLzWgqz6+g6nvuyY1Hs1csGUUzzquQaIS8FG7OMLzKU97r7PYAX7s+g==;EndpointSuffix=core.windows.net", container_name="fotacontainer", blob_name=member.name) with open(os.path.join(settings.MEDIA_ROOT, member.name), "rb") as data: blob.upload_blob(data, overwrite=True) if os.path.isfile( os.path.join(settings.MEDIA_ROOT, member.name)): os.remove(os.path.join(settings.MEDIA_ROOT, member.name)) account_name = "fotastorage1" container_name = "fotacontainer" blob_name = member.name account_key = "ZH4xN/rJcvButa2oTELpASSq2Ag2mMDQLzWgqz6+g6nvuyY1Hs1csGUUzzquQaIS8FG7OMLzKU97r7PYAX7s+g==" url = f"https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}" sas_token = generate_blob_sas( account_name=account_name, account_key=account_key, container_name=container_name, blob_name=blob_name, permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=11)) url_with_sas = f"{url}?{sas_token}" return url_with_sas except Exception as e: print(e)
def test_filter_blobs_using_account_sas(self, resource_group, location, storage_account, storage_account_key): token = generate_account_sas( storage_account.name, storage_account_key, ResourceTypes(service=True, container=True, object=True), AccountSasPermissions(write=True, list=True, read=True, delete_previous_version=True, tag=True, filter_by_tags=True), datetime.utcnow() + timedelta(hours=1), ) self._setup(storage_account, token) tags = {"year": '1000', "tag2": "secondtag", "tag3": "thirdtag", "habitat_type": 'Shallow Lowland Billabongs'} blob_client, _ = self._create_block_blob(tags=tags, container_name=self.container_name) blob_client.set_blob_tags(tags=tags) tags_on_blob = blob_client.get_blob_tags() self.assertEqual(len(tags_on_blob), len(tags)) if self.is_live: sleep(10) # To filter in a specific container use: # where = "@container='{}' and tag1='1000' and tag2 = 'secondtag'".format(container_name1) where = "\"year\"='1000' and tag2 = 'secondtag' and tag3='thirdtag'" blob_list = self.bsc.find_blobs_by_tags(filter_expression=where, results_per_page=2).by_page() first_page = next(blob_list) items_on_page1 = list(first_page) self.assertEqual(1, len(items_on_page1))
def generate_sas_token(storage_account, access_key): sas_token = generate_account_sas( storage_account, account_key=access_key, resource_types=ResourceTypes(service=True, container=True, object=True), permission=AccountSasPermissions(read=True, write=True), expiry=datetime.utcnow() + timedelta(hours=5)) return sas_token
def generate_sas_token(self): fake_key = 'a' * 30 + 'b' * 30 return '?' + generate_account_sas( account_name='test', # name of the storage account account_key=fake_key, # key for the storage account resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True, list=True), start=datetime.now() - timedelta(hours=24), expiry=datetime.now() + timedelta(days=8))
def _get_container_sas_token(self): sas_token = generate_account_sas( self.blob_service_client.account_name, account_key=self.blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(write=True, delete=True, read=True), expiry=datetime.utcnow() + timedelta(hours=8) ) return sas_token
def get_sas_token(connection_string): blob_service_client = BlobServiceClient.from_connection_string( connection_string) sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) print(sas_token) return sas_token
def generate_sas_key(connection_string): """Generate SAS key from connection string info.""" account_name, account_key = get_account_info(connection_string) sas_token = generate_account_sas( account_name=account_name, account_key=account_key, resource_types=ResourceTypes(container=True, object=True), permission=AccountSasPermissions(read=True, write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) return sas_token
def getAzureStorageAccessSignature(): blob_service_client = BlobServiceClient.from_connection_string(os.environ['aiengstorageaccntcode_STORAGE']) sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) return sas_token
def generate_url_with_sas(blob_uri): # Generate SAS token to retrieve image content from blob storage blob_service_client = BlobServiceClient.from_connection_string( conn_str=connection_string) sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) image_url = blob_uri + '?' + sas_token return image_url
def GetSASToken(): """Create a shared access token in order to read share access to the images. """ sas_token = generate_account_sas( account_name, account_key=account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) return sas_token
def _create_sas_token(self): """Generate the shared access signature token using the storage account access key""" account_keys = self._getstorageaccountkey() # get one of the account keys account_keys = json.loads(account_keys)[0]['value'] self.credential_token = generate_account_sas( account_name=self.storageaccount, account_key=account_keys, resource_types=ResourceTypes(service=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1))
def auth_shared_access_signature(): from azure.storage.blob import BlobServiceClient # [START create_sas_token] # Create a SAS token to use to authenticate a new client from datetime import datetime, timedelta from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas return generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1))
def azure_url_sas(self): from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas try: sas_token = generate_account_sas(self.blob_service_client.account_name, account_key=self.blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.datetime.utcnow() + datetime.timedelta(minutes=5)) except Exception as ex: tty.error("{}, Could not generate a sas token for Azure blob storage".format(ex)) url_str = self.url.geturl() url_str = url_str.replace('azure', 'https', 1) url_sas_str = url_str + '?' + sas_token return url_sas_str
def create_token_sas(): """ Cette fonction crée un token d'une durée de vie d'une heure elle renvoie et print le token """ sas_token = generate_account_sas( account_name=(f"{config['storage']['account']}"), account_key=(f"{config['storage']['key']}"), resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) print(sas_token) return sas_token
def sas_account_token(): """ This function create a token with account and key the token sas, is a provisory key for share. """ sas_token = generate_account_sas( account_name=(f"{config['storage']['account']}"), account_key=(f"{config['storage']['key']}"), resource_types=ResourceTypes(container=True, object=True), permission=AccountSasPermissions(read=True, list=True), expiry=datetime.utcnow() + timedelta(hours=1)) return sas_token
def create_connection(self, storage_account_name, storage_account_key, container): try: dfs_url = "{}://{}.dfs.core.windows.net".format( "https", storage_account_name) blob_url = "{}://{}.blob.core.windows.net/".format( "https", storage_account_name) # print("ADLS URL:", dfs_url) # print("Blob URL:", blob_url) self.service_client = DataLakeServiceClient( account_url=dfs_url, credential=storage_account_key) # print("Getting file_system_client...") self.file_system_client = self.service_client.get_file_system_client( file_system=self.settings.storage_container) # print("Getting blob_service_client...") connect_string="DefaultEndpointsProtocol=https;AccountName=" + storage_account_name + ";AccountKey="\ + storage_account_key + ";EndpointSuffix=core.windows.net" self.blob_service_client = BlobServiceClient.from_connection_string( conn_str=connect_string) # Create sas token for blob self.sas_token = generate_account_sas( account_name=self.blob_service_client.account_name, account_key=storage_account_key, resource_types=ResourceTypes(service=True, object=True, container=True), permission=AccountSasPermissions(read=True, write=True, delete=True, list=True, add=True, create=True), start=datetime.now() - timedelta(hours=1), expiry=datetime.utcnow() + timedelta(hours=4) # Token valid for 4 hours ) self.container_client = self.blob_service_client.get_container_client( container) # print("returning references.") return self.service_client\ , self.file_system_client\ , self.blob_service_client\ , self.container_client\ , self.sas_token except Exception as e: print(e) return None, None, None, None, None
def setUp(self, *args, **kwargs): hsm_playback_url = "https://managedhsmname.managedhsm.azure.net" container_playback_uri = "https://storagename.blob.core.windows.net/container" playback_sas_token = "fake-sas" if self.is_live: self.managed_hsm_url = os.environ.get("AZURE_MANAGEDHSM_URL") if self.managed_hsm_url: self._scrub_url(real_url=self.managed_hsm_url, playback_url=hsm_playback_url) storage_name = os.environ.get("BLOB_STORAGE_ACCOUNT_NAME") storage_endpoint_suffix = os.environ.get( "KEYVAULT_STORAGE_ENDPOINT_SUFFIX") container_name = os.environ.get("BLOB_CONTAINER_NAME") self.container_uri = "https://{}.blob.{}/{}".format( storage_name, storage_endpoint_suffix, container_name) self._scrub_url(real_url=self.container_uri, playback_url=container_playback_uri) storage_account_key = os.environ.get( "BLOB_PRIMARY_STORAGE_ACCOUNT_KEY") if storage_account_key: self.sas_token = generate_account_sas( account_name=storage_name, account_key=storage_account_key, resource_types=ResourceTypes(container=True, object=True), permission=AccountSasPermissions( create=True, list=True, write=True, read=True, add=True, delete=True, delete_previous_version=True, ), expiry=datetime.utcnow() + timedelta(minutes=30), ) self.scrubber.register_name_pair(self.sas_token, playback_sas_token) else: self.managed_hsm_url = hsm_playback_url self.container_uri = container_playback_uri self.sas_token = playback_sas_token self._set_mgmt_settings_real_values() super(AdministrationTestCase, self).setUp(*args, **kwargs)
def auth_shared_access_signature(self): # Instantiate a BlobServiceClient using a connection string from azure.storage.blob import BlobServiceClient blob_service_client = BlobServiceClient.from_connection_string(self.connection_string) # [START create_sas_token] # Create a SAS token to use to authenticate a new client from datetime import datetime, timedelta from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) )
async def _test_auth_shared_access_signature_async(self): # SAS URL is calculated from storage key, so this test runs live only if TestMode.need_recording_file(self.test_mode): return # Instantiate a BlobServiceClient using a connection string from azure.storage.blob.aio import BlobServiceClient blob_service_client = BlobServiceClient.from_connection_string(self.connection_string) # [START create_sas_token] # Create a SAS token to use to authenticate a new client from datetime import datetime, timedelta from azure.storage.blob import ResourceTypes, AccountSasPermissions sas_token = blob_service_client.generate_shared_access_signature( resource_types=ResourceTypes.OBJECT, permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1) ) # [END create_sas_token] assert sas_token is not None
async def main(path: str) -> str: # Get blob name and container from path container = path.split('/')[0] blob = "/".join(path.split('/')[1:]) blob_service_client = BlobServiceClient.from_connection_string(os.environ["StorageAccount"]) blob_container_client = blob_service_client.get_container_client(container) blob_client = blob_container_client.get_blob_client(blob) # Generate a token valid for 15 minutes sas_token = generate_blob_sas( account_name=blob_container_client.account_name, account_key=blob_container_client.credential.account_key, container_name=blob_container_client.container_name, blob_name=blob, permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(minutes=15), ) sas_url = f"{blob_client.url}?{sas_token}" return sas_url
def generate_sastoken(filename, saslife, connections): container_name = connections.get('container_name') connection_string = connections.get('storageaccount_connection') try: blob_service_client = BlobServiceClient.from_connection_string( connection_string) # generateToken with expiry sas_token = generate_blob_sas( blob_service_client.account_name, container_name=container_name, blob_name=filename, account_key=blob_service_client.credential.account_key, permission=AccountSasPermissions(read=True), expiry=datetime.now() + relativedelta(months=saslife)) print(f'sas token generated: {sas_token}') app.logger.info(f'sas token generated: {sas_token}') return sas_token except Exception as e: print(f'failed to generate token for file {filename} error: {e}') app.logger.info( f'failed to generate token for file {filename} error:{e}') return None
def download_it(): blob_list() # connect_str = os.getenv('AZURE_STORAGE_CONNECTION_STRING') --> Use in production # Temporary connection string format connect_str = storage_conn container_name = 'credentials' account_name = 'decentraliseduploads' blob_service_client = BlobServiceClient.from_connection_string(connect_str) sas_token = generate_account_sas( blob_service_client.account_name, account_key=blob_service_client.credential.account_key, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) file_conn = 'https://' + account_name + '.blob.core.windows.net/' + container_name + '/' + blob_name[0] \ + '?' + sas_token return file_conn
def _get_blob_service_client(self): """Connect to Azure and return the blob service client The following environment variables must be set: * ``AZURE_STORAGE_CONNECTION_STRING`` or * ``AZURE_STORAGE_ACCOUNT_NAME`` * ``AZURE_STORAGE_ACCOUNT_URL`` * ``AZURE_STORAGE_ACCOUNT_KEY`` or if you want to use AAD (pod identity), set it to 1 or 0 * ``AZURE_STORAGE_USE_AAD`` """ connect_str = os.environ.get("AZURE_STORAGE_CONNECTION_STRING") account_name = os.environ.get("AZURE_STORAGE_ACCOUNT_NAME") account_url = os.environ.get("AZURE_STORAGE_ACCOUNT_URL") account_key = os.environ.get("AZURE_STORAGE_ACCOUNT_KEY") account_use_aad = os.environ.get("AZURE_STORAGE_USE_AAD") if not ( connect_str or (account_name and account_url and account_key) or account_use_aad ): msg = _( "If you want to read from the Azure container, you must provide the " "following environment variables:\n" "* AZURE_STORAGE_CONNECTION_STRING\n" "or\n" "* AZURE_STORAGE_ACCOUNT_NAME\n" "* AZURE_STORAGE_ACCOUNT_URL\n" "* AZURE_STORAGE_ACCOUNT_KEY\n" "or\n" "* AZURE_STORAGE_USE_AAD\n" ) raise exceptions.UserError(msg) blob_service_client = None if account_use_aad: token_credential = DefaultAzureCredential() blob_service_client = BlobServiceClient( account_url=account_url, credential=token_credential ) elif connect_str: try: blob_service_client = BlobServiceClient.from_connection_string( connect_str ) except HttpResponseError as error: _logger.exception( "Error during the connection to Azure container using the " "connection string." ) raise exceptions.UserError(str(error)) else: try: sas_token = generate_account_sas( account_name=account_name, account_key=account_key, resource_types=ResourceTypes(container=True, object=True), permission=AccountSasPermissions(read=True, write=True), expiry=datetime.utcnow() + timedelta(hours=1), ) blob_service_client = BlobServiceClient( account_url=account_url, credential=sas_token, ) except HttpResponseError as error: _logger.exception( "Error during the connection to Azure container using the Shared " "Access Signature (SAS)" ) raise exceptions.UserError(str(error)) return blob_service_client
args = parser.parse_args() def convert_file(inputFile): output_path = ".\\output\\" + args.outputFilename stream = ffmpeg.input(args.inputFilename) stream = ffmpeg.output(stream, output_path) ffmpeg.run(stream) return output_path sas_token = generate_account_sas(account_name=azure_acocunt_name, account_key=os.getenv("AZURE_ACCOUNT_KEY"), resource_types=ResourceTypes(service=True, object=True), permission=AccountSasPermissions(read=True, write=True), expiry=datetime.utcnow() + timedelta(hours=1)) service = BlobServiceClient(account_url=account_url, credential=sas_token) blob = service.get_blob_client(container=container_name, blob=args.outputFilename) def upload_blob(blobName): content_settings = ContentSettings(content_type='video/mp4') with open(blobName, "rb") as data: blob.upload_blob(data, content_settings=content_settings) converted_blob = convert_file(args.inputFilename)
def resource_download(self, id, resource_id, filename=None): ''' Provide a download by either redirecting the user to the url stored or downloading the uploaded file from azure. ''' context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'auth_user_obj': c.userobj } try: rsc = get_action('resource_show')(context, {'id': resource_id}) get_action('package_show')(context, {'id': id}) except NotFound: abort(404, _('Resource not found')) except NotAuthorized: abort(401, _('Unauthorized to read resource %s') % id) if rsc.get('url_type') == 'upload': upload = uploader.get_resource_uploader(rsc) container_name = config.get( 'ckanext.azurefilestore.container_name') container_client = upload.get_container_client(container_name) if filename is None: filename = os.path.basename(rsc['url']) key_path = upload.get_path(rsc['id'], filename) key = filename if key is None: log.warn('Key \'{0}\' not found in container \'{1}\''.format( key_path, container_name)) url_with_sas = None try: # Small workaround to manage downloading of large files # We are redirecting to the azure resource's public URL storage_account = config.get( 'ckanext.azurefilestore.storage_account') account_key = config.get('ckanext.azurefilestore.account_key') url = 'https://{storage_account}.blob.core.windows.net/{container_name}/{key_path}'.format( storage_account=storage_account, container_name=container_name, key_path=key_path) # Legacy SDK # service = BaseBlobService(account_name=storage_account, account_key=account_key) # token = service.generate_blob_shared_access_signature( # container_name, blob_name, # permission=BlobPermissions.READ, # expiry=datetime.utcnow() + timedelta(hours=1)) # https://stackoverflow.com/questions/56769671/how-to-download-an-azure-blob-storage-file-via-url-in-python token = generate_blob_sas( account_name=storage_account, account_key=account_key, container_name=container_name, blob_name=key_path, permission=AccountSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) url_with_sas = '{url}?{token}'.format(url=url, token=token) except Exception as ex: log.error(str(ex)) # attempt fallback if config.get( 'ckanext.azurefilestore.filesystem_download_fallback', False): log.info('Attempting filesystem fallback for resource {0}'. format(resource_id)) url = toolkit.url_for( controller= 'ckanext.azurefilestore.controller:AzureController', action='filesystem_resource_download', id=id, resource_id=resource_id, filename=filename) redirect(url) abort(404, _('Resource data not found')) redirect(url_with_sas)
async def present( hub, ctx, name, resource_group, functions_file_path, os_type, runtime_stack, storage_account, storage_rg=None, app_service_plan=None, functions_version=2, enable_app_insights=None, app_insights=None, tags=None, connection_auth=None, **kwargs, ): """ .. versionadded:: 3.0.0 Ensure that a Function App exists. :param name: The name of the Function App. :param resource_group: The name of the resource group of the Function App. :param functions_file_path: The file path of the compressed (zip) file containing any Azure Functions that should be deployed to the Function App. The Azure Functions inside of this zip file should be using the same runtime stack or language that is specified within the runtime_stack parameter. This file will be uploaded every successfully run of this state. If there is a prior version of the zip file it will be overwritten. IMPORTANT: The code for all the functions in a specific function app should be located in a root project folder that contains a host configuration file and one or more subfolders. Each subfolder contains the code for a separate function. The folder structure is shown in the representation below:: | functionapp.zip | - host.json | - MyFirstFunction/ | - function.json | - .. | - MySecondFunction/ | - function.json | - .. | - SharedCode/ | - bin/ :param os_type: The operation system utilized by the Function App. This cannot be changed after the Function App has been created. Possible values are "linux" or "windows". :param runtime_stack: The language stack to be used for functions in this Function App. Possible values are "dotnet", "node", "java", "python", or "powershell". :param storage_account: The name of the storage account that will hold the Azure Functions used by the Function App. This storage account must be of the kind "Storage" or "StorageV2". If not already present, a container named "function-releases" will be created within this storage account to hold the zip file containing any Azure Functions. :param storage_rg: (Optional, used with storage_account) The resource group of the storage account passed. This parameter is only necessary if the storage account has a different resource group than the one specified for the Function App. :param app_service_plan: The name of the App Service (Consumption) Plan used by the Function App. If this parameter is not provided or the provided name is invalid/does not exist, then an App Service (Consumption) Plan will be built for the Function App with the name "plan-{name}". This plan should have the same OS as specified by the os_type parameter. :param functions_version: The version of Azure Functions to use. Additional information about Azure Functions versions can be found here: https://docs.microsoft.com/en-us/azure/azure-functions/functions-versions. Possible values include: 1, 2, and 3. Defaults to 2. :param enable_app_insights: Boolean flag for enabling Application Insights. :param app_insights: (Optional, used with enable_app_insights) The name of the Application Insights Component to use for the Function App. If the specified Application Insights Component does not exist, then it will be created. If this parameter is not specified, then an Application Insights Component named "app-insights-{name}" will be created and used. :param tags: A dictionary of strings representing tag metadata for the Function App. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. Example usage: .. code-block:: yaml Ensure function app exists: azurerm.web.function_app.present: - name: my_app - resource_group: my_group - functions_file_path: "/path/to/functions.zip" - os_type: "linux" - runtime_stack: "python" - storage_account: my_account - app_service_plan: my_plan - enable_app_insights: True - tags: "Owner": "EITR Technologies" """ ret = {"name": name, "result": False, "comment": "", "changes": {}} action = "create" app_settings = [ {"name": "FUNCTIONS_WORKER_RUNTIME", "value": runtime_stack.lower()}, {"name": "FUNCTIONS_EXTENSION_VERSION", "value": f"~{functions_version}",}, {"name": "FUNCTION_APP_EDIT_MODE", "value": "readonly"}, {"name": "SCM_DO_BUILD_DURING_DEPLOYMENT", "value": "false"}, ] if not isinstance(connection_auth, dict): if ctx["acct"]: connection_auth = ctx["acct"] else: ret[ "comment" ] = "Connection information must be specified via acct or connection_auth dictionary!" return ret # Ensures location is specified if "location" not in kwargs: rg_props = await hub.exec.azurerm.resource.group.get( ctx, resource_group, **kwargs ) if "error" in rg_props: log.error("Unable to determine location from resource group specified.") return { "error": "Unable to determine location from resource group specified." } kwargs["location"] = rg_props["location"] # Handle storage account validation if not storage_rg: storage_rg = resource_group storage_acct = await hub.exec.azurerm.storage.account.get_properties( ctx, name=storage_account, resource_group=storage_rg ) if "error" in storage_acct: log.error( f"The storage account {storage_account} does not exist within the given resource group {resource_group}." ) ret[ "comment" ] = f"The storage account {storage_account} does not exist within the given resource group {resource_group}." return ret # Ensure that the file path contains a zip file filename = os.path.basename(functions_file_path) if not filename.lower().endswith(".zip"): log.error( "The specified file in functions_file_path is not a compressed (zip) file." ) ret[ "comment" ] = "The specified file in functions_file_path is not a compressed (zip) file." return ret # Set reserved for the ASP and Function App based upon OS type if os_type.lower() == "windows": reserved = False else: # linux reserved = True # Handle App Service Plan creation if not app_service_plan: app_service_plan = f"plan-{name}" plan = await hub.exec.azurerm.web.app_service_plan.get( ctx, name=app_service_plan, resource_group=resource_group ) if "error" in plan: plan = await hub.exec.azurerm.web.app_service_plan.create_or_update( ctx, name=app_service_plan, resource_group=resource_group, kind="functionapp", reserved=reserved, sku="Y1", **connection_auth, ) if "error" in plan: log.error( f"Unable to create the App Service Plan {app_service_plan} in the resource group {resource_group}." ) ret[ "comment" ] = f"Unable to create the App Service Plan {app_service_plan} in the resource group {resource_group}." return ret elif plan["reserved"] != reserved: log.error( f"The OS of the App Service Plan {app_service_plan} does not match the specified OS type for the Function App and thus cannot be used." ) ret[ "comment" ] = f"The OS of the App Service Plan {app_service_plan} does not match the specified OS type for the Function App and thus cannot be used." return ret # Gets the resource ID of the ASP server_farm_id = plan["id"] # Handle App Insights Validation and Creation if enable_app_insights: if not app_insights: app_insights = f"app-insights-{name}" component = await hub.exec.azurerm.application_insights.component.get( ctx, name=app_insights, resource_group=resource_group ) if "error" in component: component = await hub.exec.azurerm.application_insights.component.create_or_update( ctx, name=app_insights, resource_group=resource_group, kind="web", application_type="web", ) if "error" in component: log.error( f"Unable to create the Application Insights Component {app_insights} within the resource group {resource_group}." ) ret[ "comment" ] = f"Unable to create the Application Insights Component {app_insights} within the resource group {resource_group}." return ret instrumentation_key = component["instrumentation_key"] # Configures the application insights for the app settings app_settings.append( {"name": "APPINSIGHTS_INSTRUMENTATIONKEY", "value": instrumentation_key} ) # Builds a storage container named "function-releases" within the specified storage account if not already present container = await hub.exec.azurerm.storage.container.get( ctx, name="function-releases", account=storage_account, resource_group=storage_rg, ) if "error" in container: container = await hub.exec.azurerm.storage.container.create( ctx, name="function-releases", account=storage_account, resource_group=storage_rg, public_access="None", ) # Upload the zip file containing the Azure Functions upload_zip = await hub.exec.azurerm.storage.container.upload_blob( ctx, name=filename, container="function-releases", account=storage_account, resource_group=storage_rg, file_path=functions_file_path, overwrite=True, ) if "error" in upload_zip: log.error( f"Unable to upload {filename} to the function-releases container within the storage account {storage_account}." ) ret[ "comment" ] = f"Unable to upload {filename} to the function-releases container within the storage account {storage_account}." return ret # Retrieves the access keys for the storage account storage_acct_keys = await hub.exec.azurerm.storage.account.list_keys( ctx, name=storage_account, resource_group=storage_rg ) if "error" not in storage_acct_keys: storage_acct_key = storage_acct_keys["keys"][0]["value"] else: log.error( f"Unable to get the account access key for the specified storage account {storage_account} within the given resource group {storage_rg}." ) ret[ "comment" ] = f"Unable to get the account access key for the specified storage account {storage_account} within the given resource group {storage_rg}." return ret # Generate the sas token used within app settings sas_token = generate_account_sas( account_name=storage_account, account_key=storage_acct_key, resource_types=ResourceTypes(object=True, container=True, service=True), permission=AccountSasPermissions(read=True, write=True, list=True, delete=True), expiry=datetime.utcnow() + timedelta(days=2), ) # Update app settings information from the storage account app_settings.append( { "name": "AzureWebJobsStorage", "value": f"DefaultEndpointsProtocol=https;AccountName={storage_account};AccountKey={storage_acct_key}", } ) app_settings.append( { "name": "WEBSITE_RUN_FROM_PACKAGE", "value": f"https://{storage_account}.blob.core.windows.net/function-releases/{filename}?{sas_token}", } ) # Add any app settings related to a specific OSs if os_type.lower() == "windows": app_settings.append( { "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", "value": f"DefaultEndpointsProtocol=https;AccountName={storage_account};AccountKey={storage_acct_key}", } ) app_settings.append({"name": "WEBSITE_CONTENTSHARE", "value": name.lower()}) # Check for the existence of the Function App function_app = await hub.exec.azurerm.web.app.get( ctx, name, resource_group, azurerm_log_level="info", **connection_auth ) if "error" not in function_app: action = "update" # tag changes tag_changes = differ.deep_diff(function_app.get("tags", {}), tags or {}) if tag_changes: ret["changes"]["tags"] = tag_changes # app service plan changes if function_app.get("server_farm_id") != server_farm_id: ret["changes"]["server_farm_id"] = { "new": server_farm_id, "old": function_app.get("server_farm_id"), } # app setting changes existing_settings = await hub.exec.azurerm.web.app.list_application_settings( ctx, name=name, resource_group=resource_group ) old_settings = existing_settings["properties"] new_settings = {} for setting in app_settings: new_settings.update({setting.get("name"): setting.get("value")}) # Checks specifically for changes within the WEBSITE_RUN_FROM_PACKAGE app setting because the value of that # setting is changed every run. new_run_package_setting = new_settings.pop("WEBSITE_RUN_FROM_PACKAGE", "") old_run_package_setting = old_settings.pop("WEBSITE_RUN_FROM_PACKAGE", "") new_beginning = (new_run_package_setting.split("?"))[0] old_beginning = (old_run_package_setting.split("?"))[0] run_package_changes = False if old_beginning != new_beginning: run_package_changes = True # If there are changes within WEBSITE_RUN_FROM_PACKAGE, then that app setting should be readded to both settings # dictionaries to be recorded as app setting changes changes if run_package_changes: new_settings.update({"WEBSITE_RUN_FROM_PACKAGE": new_run_package_setting}) old_settings.update({"WEBSITE_RUN_FROM_PACKAGE": old_run_package_setting}) app_settings_changes = differ.deep_diff(old_settings, new_settings) if app_settings_changes: ret["changes"]["site_config"] = {"app_settings": app_settings_changes} if not ret["changes"]: ret["result"] = True ret["comment"] = "Function App {0} is already present.".format(name) return ret if ctx["test"]: ret["result"] = None ret["comment"] = "Function App {0} would be updated.".format(name) return ret else: ret["changes"] = { "old": {}, "new": { "name": name, "resource_group": resource_group, "app_service_plan": app_service_plan, "os_type": os_type, "runtime_stack": runtime_stack, "site_config": {"app_settings": app_settings}, "tags": tags, }, } if enable_app_insights: ret["changes"]["new"]["application_insights"] = app_insights if ctx["test"]: ret["comment"] = "Function App {0} would be created.".format(name) ret["result"] = None return ret app_kwargs = kwargs.copy() app_kwargs.update(connection_auth) kind = "functionapp" if os_type.lower() == "linux": kind = kind + ",Linux" function_app = await hub.exec.azurerm.web.app.create_or_update( ctx=ctx, name=name, resource_group=resource_group, tags=tags, server_farm_id=server_farm_id, kind=kind, site_config={"app_settings": app_settings}, **app_kwargs, ) if "error" not in function_app: ret["result"] = True ret["comment"] = f"Function App {name} has been {action}d." return ret ret["comment"] = "Failed to {0} Function App {1}! ({2})".format( action, name, function_app.get("error") ) if not ret["result"]: ret["changes"] = {} return ret
def create_sas_uri(self, group_name, location, storage_account_name): if self.is_live: from azure.mgmt.storage.models import BlobContainer from azure.storage.blob import generate_account_sas, AccountSasPermissions, ContainerClient, ResourceTypes BODY = { "sku": { "name": "Standard_GRS" }, "kind": "StorageV2", # Storage v2 support policy "location": location, "encryption": { "services": { "file": { "key_type": "Account", "enabled": True }, "blob": { "key_type": "Account", "enabled": True } }, "key_source": "Microsoft.Storage" }, "tags": { "key1": "value1", "key2": "value2" } } result = self.storage_client.storage_accounts.begin_create( group_name, storage_account_name, BODY ) storage_account = result.result() # result = self.storage_client.blob_containers.create( # group_name, # storage_account_name, # "foo", # {} # ) # result = result.result() keys = self.storage_client.storage_accounts.list_keys( group_name, storage_account_name ).keys sas_token = generate_account_sas( account_name=storage_account_name, account_key=keys[0].value, resource_types=ResourceTypes(object=True), permission=AccountSasPermissions(read=True, list=True), start=dt.datetime.now() - dt.timedelta(hours=24), expiry=dt.datetime.now() - dt.timedelta(days=8) ) container_client = ContainerClient( storage_account.primary_endpoints.blob.rstrip("/"), credential="?" + sas_token, container_name="foo", blob_name="default" ) return container_client.url # container_client.create_container() # return container_client.url + "?" + sas_token else: return "fakeuri"