diff --git a/.env.sample b/.env.sample index 29e7f0868..42874a224 100644 --- a/.env.sample +++ b/.env.sample @@ -63,6 +63,8 @@ AZURE_SPEECH_SERVICE_REGION= AZURE_AUTH_TYPE=keys USE_KEY_VAULT=true AZURE_KEY_VAULT_ENDPOINT= +# Application environment (e.g., dev, prod) +APP_ENV="dev" # Chat conversation type to decide between custom or byod (bring your own data) conversation type CONVERSATION_FLOW= # Chat History CosmosDB Integration Settings diff --git a/code/backend/batch/utilities/chat_history/database_factory.py b/code/backend/batch/utilities/chat_history/database_factory.py index 980c2cf82..5482581c6 100644 --- a/code/backend/batch/utilities/chat_history/database_factory.py +++ b/code/backend/batch/utilities/chat_history/database_factory.py @@ -2,7 +2,7 @@ from ..helpers.env_helper import EnvHelper from .cosmosdb import CosmosConversationClient from .postgresdbservice import PostgresConversationClient -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from ..helpers.config.database_type import DatabaseType @@ -25,7 +25,7 @@ def get_conversation_client(): f"https://{env_helper.AZURE_COSMOSDB_ACCOUNT}.documents.azure.com:443/" ) credential = ( - DefaultAzureCredential() + get_azure_credential() if not env_helper.AZURE_COSMOSDB_ACCOUNT_KEY else env_helper.AZURE_COSMOSDB_ACCOUNT_KEY ) diff --git a/code/backend/batch/utilities/chat_history/postgresdbservice.py b/code/backend/batch/utilities/chat_history/postgresdbservice.py index a758bb20c..bb53fb190 100644 --- a/code/backend/batch/utilities/chat_history/postgresdbservice.py +++ b/code/backend/batch/utilities/chat_history/postgresdbservice.py @@ -1,7 +1,7 @@ import logging import asyncpg from datetime import datetime, timezone -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from .database_client_base import DatabaseClientBase @@ -21,7 +21,7 @@ def __init__( async def connect(self): try: - credential = DefaultAzureCredential() + credential = get_azure_credential() token = credential.get_token( "https://ossrdbms-aad.database.windows.net/.default" ).token diff --git a/code/backend/batch/utilities/helpers/azure_blob_storage_client.py b/code/backend/batch/utilities/helpers/azure_blob_storage_client.py index fe53dfd23..39b41a9de 100644 --- a/code/backend/batch/utilities/helpers/azure_blob_storage_client.py +++ b/code/backend/batch/utilities/helpers/azure_blob_storage_client.py @@ -12,7 +12,7 @@ from azure.storage.queue import QueueClient, BinaryBase64EncodePolicy import chardet from .env_helper import EnvHelper -from azure.identity import DefaultAzureCredential +from .azure_credential_utils import get_azure_credential def connection_string(account_name: str, account_key: str): @@ -25,7 +25,7 @@ def create_queue_client(): return QueueClient( account_url=f"https://{env_helper.AZURE_BLOB_ACCOUNT_NAME}.queue.core.windows.net/", queue_name=env_helper.DOCUMENT_PROCESSING_QUEUE_NAME, - credential=DefaultAzureCredential(), + credential=get_azure_credential(), message_encode_policy=BinaryBase64EncodePolicy(), ) @@ -56,7 +56,7 @@ def __init__( if self.auth_type == "rbac": self.account_key = None self.blob_service_client = BlobServiceClient( - account_url=self.endpoint, credential=DefaultAzureCredential() + account_url=self.endpoint, credential=get_azure_credential() ) self.user_delegation_key = self.request_user_delegation_key( blob_service_client=self.blob_service_client diff --git a/code/backend/batch/utilities/helpers/azure_computer_vision_client.py b/code/backend/batch/utilities/helpers/azure_computer_vision_client.py index 6ab0733f3..d838f9d9e 100644 --- a/code/backend/batch/utilities/helpers/azure_computer_vision_client.py +++ b/code/backend/batch/utilities/helpers/azure_computer_vision_client.py @@ -1,6 +1,7 @@ import logging from urllib.parse import urljoin -from azure.identity import DefaultAzureCredential, get_bearer_token_provider +from azure.identity import get_bearer_token_provider +from .azure_credential_utils import get_azure_credential import requests from requests import Response @@ -56,7 +57,7 @@ def __make_request(self, path: str, body) -> Response: headers["Ocp-Apim-Subscription-Key"] = self.key else: token_provider = get_bearer_token_provider( - DefaultAzureCredential(), self.__TOKEN_SCOPE + get_azure_credential(), self.__TOKEN_SCOPE ) headers["Authorization"] = "Bearer " + token_provider() diff --git a/code/backend/batch/utilities/helpers/azure_credential_utils.py b/code/backend/batch/utilities/helpers/azure_credential_utils.py new file mode 100644 index 000000000..e8d9d7051 --- /dev/null +++ b/code/backend/batch/utilities/helpers/azure_credential_utils.py @@ -0,0 +1,48 @@ +import os +from azure.identity import ManagedIdentityCredential, DefaultAzureCredential +from azure.identity.aio import ( + ManagedIdentityCredential as AioManagedIdentityCredential, + DefaultAzureCredential as AioDefaultAzureCredential, +) + + +async def get_azure_credential_async(client_id=None): + """ + Returns an Azure credential asynchronously based on the application environment. + + If the environment is 'dev', it uses AioDefaultAzureCredential. + Otherwise, it uses AioManagedIdentityCredential. + + Args: + client_id (str, optional): The client ID for the Managed Identity Credential. + + Returns: + Credential object: Either AioDefaultAzureCredential or AioManagedIdentityCredential. + """ + if os.getenv("APP_ENV", "prod").lower() == "dev": + return ( + AioDefaultAzureCredential() + ) # CodeQL [SM05139] Okay use of DefaultAzureCredential as it is only used in development + else: + return AioManagedIdentityCredential(client_id=client_id) + + +def get_azure_credential(client_id=None): + """ + Returns an Azure credential based on the application environment. + + If the environment is 'dev', it uses DefaultAzureCredential. + Otherwise, it uses ManagedIdentityCredential. + + Args: + client_id (str, optional): The client ID for the Managed Identity Credential. + + Returns: + Credential object: Either DefaultAzureCredential or ManagedIdentityCredential. + """ + if os.getenv("APP_ENV", "prod").lower() == "dev": + return ( + DefaultAzureCredential() + ) # CodeQL [SM05139] Okay use of DefaultAzureCredential as it is only used in development + else: + return ManagedIdentityCredential(client_id=client_id) diff --git a/code/backend/batch/utilities/helpers/azure_form_recognizer_helper.py b/code/backend/batch/utilities/helpers/azure_form_recognizer_helper.py index 5abb54d15..a00f07340 100644 --- a/code/backend/batch/utilities/helpers/azure_form_recognizer_helper.py +++ b/code/backend/batch/utilities/helpers/azure_form_recognizer_helper.py @@ -1,7 +1,7 @@ import logging from azure.core.credentials import AzureKeyCredential from azure.ai.formrecognizer import DocumentAnalysisClient -from azure.identity import DefaultAzureCredential +from .azure_credential_utils import get_azure_credential import html import traceback from .env_helper import EnvHelper @@ -19,7 +19,7 @@ def __init__(self) -> None: if env_helper.AZURE_AUTH_TYPE == "rbac": self.document_analysis_client = DocumentAnalysisClient( endpoint=self.AZURE_FORM_RECOGNIZER_ENDPOINT, - credential=DefaultAzureCredential(), + credential=get_azure_credential(), headers={ "x-ms-useragent": "chat-with-your-data-solution-accelerator/1.0.0" }, diff --git a/code/backend/batch/utilities/helpers/azure_postgres_helper.py b/code/backend/batch/utilities/helpers/azure_postgres_helper.py index 674ba166a..d5ca7263f 100644 --- a/code/backend/batch/utilities/helpers/azure_postgres_helper.py +++ b/code/backend/batch/utilities/helpers/azure_postgres_helper.py @@ -1,7 +1,7 @@ import logging import psycopg2 from psycopg2.extras import execute_values, RealDictCursor -from azure.identity import DefaultAzureCredential +from .azure_credential_utils import get_azure_credential from .llm_helper import LLMHelper from .env_helper import EnvHelper @@ -24,7 +24,7 @@ def _create_search_client(self): dbname = self.env_helper.POSTGRESQL_DATABASE # Acquire the access token - credential = DefaultAzureCredential() + credential = get_azure_credential() access_token = credential.get_token( "https://ossrdbms-aad.database.windows.net/.default" ) diff --git a/code/backend/batch/utilities/helpers/azure_search_helper.py b/code/backend/batch/utilities/helpers/azure_search_helper.py index 85ca2f397..090494e50 100644 --- a/code/backend/batch/utilities/helpers/azure_search_helper.py +++ b/code/backend/batch/utilities/helpers/azure_search_helper.py @@ -2,7 +2,7 @@ from typing import Union from langchain_community.vectorstores import AzureSearch from azure.core.credentials import AzureKeyCredential -from azure.identity import DefaultAzureCredential +from .azure_credential_utils import get_azure_credential from azure.search.documents import SearchClient from azure.search.documents.indexes import SearchIndexClient from azure.search.documents.indexes.models import ( @@ -49,10 +49,10 @@ def _search_credential(self): if self.env_helper.is_auth_type_keys(): return AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) else: - return DefaultAzureCredential() + return get_azure_credential() def _create_search_client( - self, search_credential: Union[AzureKeyCredential, DefaultAzureCredential] + self, search_credential: Union[AzureKeyCredential, get_azure_credential] ) -> SearchClient: return SearchClient( endpoint=self.env_helper.AZURE_SEARCH_SERVICE, @@ -61,7 +61,7 @@ def _create_search_client( ) def _create_search_index_client( - self, search_credential: Union[AzureKeyCredential, DefaultAzureCredential] + self, search_credential: Union[AzureKeyCredential, get_azure_credential] ): return SearchIndexClient( endpoint=self.env_helper.AZURE_SEARCH_SERVICE, credential=search_credential @@ -285,7 +285,7 @@ def get_conversation_logger(self): ] if self.env_helper.AZURE_AUTH_TYPE == "rbac": - credential = DefaultAzureCredential() + credential = get_azure_credential() return AzureSearch( azure_search_endpoint=self.env_helper.AZURE_SEARCH_SERVICE, azure_search_key=None, # Remove API key diff --git a/code/backend/batch/utilities/helpers/env_helper.py b/code/backend/batch/utilities/helpers/env_helper.py index 9e1a843e5..390f7b48c 100644 --- a/code/backend/batch/utilities/helpers/env_helper.py +++ b/code/backend/batch/utilities/helpers/env_helper.py @@ -3,7 +3,8 @@ import logging import threading from dotenv import load_dotenv -from azure.identity import DefaultAzureCredential, get_bearer_token_provider +from azure.identity import get_bearer_token_provider +from .azure_credential_utils import get_azure_credential from azure.keyvault.secrets import SecretClient from ..orchestrator.orchestration_strategy import OrchestrationStrategy @@ -216,7 +217,7 @@ def __load_config(self, **kwargs) -> None: ) self.AZURE_TOKEN_PROVIDER = get_bearer_token_provider( - DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" + get_azure_credential(), "https://cognitiveservices.azure.com/.default" ) self.ADVANCED_IMAGE_PROCESSING_MAX_IMAGES = self.get_env_var_int( "ADVANCED_IMAGE_PROCESSING_MAX_IMAGES", 1 @@ -361,8 +362,8 @@ def __load_config(self, **kwargs) -> None: self.OPEN_AI_FUNCTIONS_SYSTEM_PROMPT = os.getenv( "OPEN_AI_FUNCTIONS_SYSTEM_PROMPT", "" ) - self.SEMENTIC_KERNEL_SYSTEM_PROMPT = os.getenv( - "SEMENTIC_KERNEL_SYSTEM_PROMPT", "" + self.SEMANTIC_KERNEL_SYSTEM_PROMPT = os.getenv( + "SEMANTIC_KERNEL_SYSTEM_PROMPT", "" ) self.ENFORCE_AUTH = self.get_env_var_bool("ENFORCE_AUTH", "True") @@ -416,7 +417,7 @@ def __init__(self) -> None: The constructor sets the USE_KEY_VAULT attribute based on the value of the USE_KEY_VAULT environment variable. If USE_KEY_VAULT is set to "true" (case-insensitive), it initializes a SecretClient object using the - AZURE_KEY_VAULT_ENDPOINT environment variable and the DefaultAzureCredential. + AZURE_KEY_VAULT_ENDPOINT environment variable and the get_azure_credential. Args: None @@ -428,7 +429,7 @@ def __init__(self) -> None: self.secret_client = None if self.USE_KEY_VAULT: self.secret_client = SecretClient( - os.environ.get("AZURE_KEY_VAULT_ENDPOINT"), DefaultAzureCredential() + os.environ.get("AZURE_KEY_VAULT_ENDPOINT"), get_azure_credential() ) def get_secret(self, secret_name: str) -> str: diff --git a/code/backend/batch/utilities/helpers/llm_helper.py b/code/backend/batch/utilities/helpers/llm_helper.py index 7517fb575..3edd0913c 100644 --- a/code/backend/batch/utilities/helpers/llm_helper.py +++ b/code/backend/batch/utilities/helpers/llm_helper.py @@ -8,7 +8,7 @@ AzureChatPromptExecutionSettings, ) from azure.ai.ml import MLClient -from azure.identity import DefaultAzureCredential +from .azure_credential_utils import get_azure_credential from .env_helper import EnvHelper logger = logging.getLogger(__name__) @@ -166,7 +166,7 @@ def get_sk_service_settings(self, service: AzureChatCompletion): def get_ml_client(self): if not hasattr(self, "_ml_client"): self._ml_client = MLClient( - DefaultAzureCredential(), + get_azure_credential(), self.env_helper.AZURE_SUBSCRIPTION_ID, self.env_helper.AZURE_RESOURCE_GROUP, self.env_helper.AZURE_ML_WORKSPACE_NAME, diff --git a/code/backend/batch/utilities/integrated_vectorization/azure_search_datasource.py b/code/backend/batch/utilities/integrated_vectorization/azure_search_datasource.py index 60ab35729..af4931998 100644 --- a/code/backend/batch/utilities/integrated_vectorization/azure_search_datasource.py +++ b/code/backend/batch/utilities/integrated_vectorization/azure_search_datasource.py @@ -7,7 +7,7 @@ ) from azure.search.documents.indexes import SearchIndexerClient from ..helpers.env_helper import EnvHelper -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from azure.core.credentials import AzureKeyCredential @@ -19,7 +19,7 @@ def __init__(self, env_helper: EnvHelper): ( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) diff --git a/code/backend/batch/utilities/integrated_vectorization/azure_search_index.py b/code/backend/batch/utilities/integrated_vectorization/azure_search_index.py index 7ae382ed6..8c95b927e 100644 --- a/code/backend/batch/utilities/integrated_vectorization/azure_search_index.py +++ b/code/backend/batch/utilities/integrated_vectorization/azure_search_index.py @@ -21,7 +21,7 @@ SearchIndex, ) from ..helpers.env_helper import EnvHelper -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from azure.core.credentials import AzureKeyCredential from ..helpers.llm_helper import LLMHelper @@ -39,7 +39,7 @@ def __init__(self, env_helper: EnvHelper, llm_helper: LLMHelper): ( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) diff --git a/code/backend/batch/utilities/integrated_vectorization/azure_search_indexer.py b/code/backend/batch/utilities/integrated_vectorization/azure_search_indexer.py index 9be9fb858..20e1fe8a2 100644 --- a/code/backend/batch/utilities/integrated_vectorization/azure_search_indexer.py +++ b/code/backend/batch/utilities/integrated_vectorization/azure_search_indexer.py @@ -2,7 +2,7 @@ from azure.search.documents.indexes.models import SearchIndexer, FieldMapping from azure.search.documents.indexes import SearchIndexerClient from ..helpers.env_helper import EnvHelper -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from azure.core.credentials import AzureKeyCredential logger = logging.getLogger(__name__) @@ -16,7 +16,7 @@ def __init__(self, env_helper: EnvHelper): ( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) diff --git a/code/backend/batch/utilities/integrated_vectorization/azure_search_skillset.py b/code/backend/batch/utilities/integrated_vectorization/azure_search_skillset.py index 622fa3152..ec1fdac40 100644 --- a/code/backend/batch/utilities/integrated_vectorization/azure_search_skillset.py +++ b/code/backend/batch/utilities/integrated_vectorization/azure_search_skillset.py @@ -15,7 +15,7 @@ from azure.search.documents.indexes import SearchIndexerClient from ..helpers.config.config_helper import IntegratedVectorizationConfig from ..helpers.env_helper import EnvHelper -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from azure.core.credentials import AzureKeyCredential logger = logging.getLogger(__name__) @@ -33,7 +33,7 @@ def __init__( ( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) self.integrated_vectorization_config = integrated_vectorization_config diff --git a/code/backend/batch/utilities/orchestrator/semantic_kernel.py b/code/backend/batch/utilities/orchestrator/semantic_kernel.py index 8cc743c0d..44bc57057 100644 --- a/code/backend/batch/utilities/orchestrator/semantic_kernel.py +++ b/code/backend/batch/utilities/orchestrator/semantic_kernel.py @@ -41,7 +41,7 @@ async def orchestrate( if response := self.call_content_safety_input(user_message): return response - system_message = self.env_helper.SEMENTIC_KERNEL_SYSTEM_PROMPT + system_message = self.env_helper.SEMANTIC_KERNEL_SYSTEM_PROMPT if not system_message: system_message = """You help employees to navigate only private information sources. You must prioritize the function call over your general knowledge for any question by calling the search_documents function. diff --git a/code/backend/batch/utilities/search/integrated_vectorization_search_handler.py b/code/backend/batch/utilities/search/integrated_vectorization_search_handler.py index d9470a6a0..5179e4c6c 100644 --- a/code/backend/batch/utilities/search/integrated_vectorization_search_handler.py +++ b/code/backend/batch/utilities/search/integrated_vectorization_search_handler.py @@ -5,7 +5,7 @@ from azure.search.documents.indexes import SearchIndexClient from azure.search.documents.models import VectorizableTextQuery from azure.core.credentials import AzureKeyCredential -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from ..common.source_document import SourceDocument import re @@ -21,7 +21,7 @@ def create_search_client(self): credential=( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) @@ -170,7 +170,7 @@ def _check_index_exists(self) -> bool: credential=( AzureKeyCredential(self.env_helper.AZURE_SEARCH_KEY) if self.env_helper.is_auth_type_keys() - else DefaultAzureCredential() + else get_azure_credential() ), ) diff --git a/code/backend/batch/utilities/tools/content_safety_checker.py b/code/backend/batch/utilities/tools/content_safety_checker.py index efba3a4c4..89ab1c30a 100644 --- a/code/backend/batch/utilities/tools/content_safety_checker.py +++ b/code/backend/batch/utilities/tools/content_safety_checker.py @@ -1,7 +1,7 @@ import logging from azure.ai.contentsafety import ContentSafetyClient from azure.core.credentials import AzureKeyCredential -from azure.identity import DefaultAzureCredential +from ..helpers.azure_credential_utils import get_azure_credential from azure.core.exceptions import HttpResponseError from azure.ai.contentsafety.models import AnalyzeTextOptions from ..helpers.env_helper import EnvHelper @@ -19,7 +19,7 @@ def __init__(self): logger.info("Initializing ContentSafetyClient with RBAC authentication.") self.content_safety_client = ContentSafetyClient( env_helper.AZURE_CONTENT_SAFETY_ENDPOINT, - DefaultAzureCredential(), + get_azure_credential(), ) else: logger.info( diff --git a/code/create_app.py b/code/create_app.py index c32da6cec..e1cade2ab 100644 --- a/code/create_app.py +++ b/code/create_app.py @@ -22,7 +22,7 @@ from backend.batch.utilities.helpers.config.conversation_flow import ConversationFlow from backend.api.chat_history import bp_chat_history_response from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient -from azure.identity import DefaultAzureCredential +from backend.batch.utilities.helpers.azure_credential_utils import get_azure_credential from backend.batch.utilities.helpers.azure_blob_storage_client import ( AzureBlobStorageClient, ) @@ -376,7 +376,7 @@ def get_speech_key(env_helper: EnvHelper): This is required to generate short-lived tokens when using RBAC. """ client = CognitiveServicesManagementClient( - credential=DefaultAzureCredential(), + credential=get_azure_credential(), subscription_id=env_helper.AZURE_SUBSCRIPTION_ID, ) keys = client.accounts.list_keys( diff --git a/code/tests/chat_history/test_database_factory.py b/code/tests/chat_history/test_database_factory.py index 0a1734171..a487fb8a5 100644 --- a/code/tests/chat_history/test_database_factory.py +++ b/code/tests/chat_history/test_database_factory.py @@ -8,7 +8,7 @@ ) -@patch("backend.batch.utilities.chat_history.database_factory.DefaultAzureCredential") +@patch("backend.batch.utilities.chat_history.database_factory.get_azure_credential") @patch("backend.batch.utilities.chat_history.database_factory.EnvHelper") @patch( "backend.batch.utilities.chat_history.database_factory.CosmosConversationClient", @@ -50,7 +50,7 @@ def test_get_conversation_client_cosmos( assert client == mock_cosmos_instance -@patch("backend.batch.utilities.chat_history.database_factory.DefaultAzureCredential") +@patch("backend.batch.utilities.chat_history.database_factory.get_azure_credential") @patch("backend.batch.utilities.chat_history.database_factory.EnvHelper") @patch( "backend.batch.utilities.chat_history.database_factory.PostgresConversationClient", diff --git a/code/tests/chat_history/test_postgresdbservice.py b/code/tests/chat_history/test_postgresdbservice.py index e160e4a7b..7710f423e 100644 --- a/code/tests/chat_history/test_postgresdbservice.py +++ b/code/tests/chat_history/test_postgresdbservice.py @@ -21,10 +21,10 @@ def mock_connection(): @patch("backend.batch.utilities.chat_history.postgresdbservice.asyncpg.connect") -@patch("backend.batch.utilities.chat_history.postgresdbservice.DefaultAzureCredential") +@patch("backend.batch.utilities.chat_history.postgresdbservice.get_azure_credential") @pytest.mark.asyncio async def test_connect(mock_credential, mock_connect, postgres_client, mock_connection): - # Mock DefaultAzureCredential + # Mock get_azure_credential mock_credential.return_value.get_token.return_value.token = "mock_token" # Mock asyncpg connection diff --git a/code/tests/utilities/helpers/test_azure_computer_vision_client.py b/code/tests/utilities/helpers/test_azure_computer_vision_client.py index ff8c70b9e..506542028 100644 --- a/code/tests/utilities/helpers/test_azure_computer_vision_client.py +++ b/code/tests/utilities/helpers/test_azure_computer_vision_client.py @@ -94,7 +94,7 @@ def test_vectorize_image_calls_computer_vision_with_key_based_authentication( @mock.patch( - "backend.batch.utilities.helpers.azure_computer_vision_client.DefaultAzureCredential" + "backend.batch.utilities.helpers.azure_computer_vision_client.get_azure_credential" ) @mock.patch( "backend.batch.utilities.helpers.azure_computer_vision_client.get_bearer_token_provider" diff --git a/code/tests/utilities/helpers/test_azure_credential_utils.py b/code/tests/utilities/helpers/test_azure_credential_utils.py new file mode 100644 index 000000000..879fc7146 --- /dev/null +++ b/code/tests/utilities/helpers/test_azure_credential_utils.py @@ -0,0 +1,105 @@ +import sys +import os +from unittest.mock import patch, MagicMock +import pytest +import backend.batch.utilities.helpers.azure_credential_utils as azure_credential_utils + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) + +# Synchronous tests + + +@patch("backend.batch.utilities.helpers.azure_credential_utils.os.getenv") +@patch("backend.batch.utilities.helpers.azure_credential_utils.DefaultAzureCredential") +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.ManagedIdentityCredential" +) +def test_get_azure_credential_dev_env( + mock_managed_identity_credential, mock_default_azure_credential, mock_getenv +): + """Test get_azure_credential in dev environment.""" + mock_getenv.return_value = "dev" + mock_default_credential = MagicMock() + mock_default_azure_credential.return_value = mock_default_credential + + credential = azure_credential_utils.get_azure_credential() + + mock_getenv.assert_called_once_with("APP_ENV", "prod") + mock_default_azure_credential.assert_called_once() + mock_managed_identity_credential.assert_not_called() + assert credential == mock_default_credential + + +@patch("backend.batch.utilities.helpers.azure_credential_utils.os.getenv") +@patch("backend.batch.utilities.helpers.azure_credential_utils.DefaultAzureCredential") +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.ManagedIdentityCredential" +) +def test_get_azure_credential_non_dev_env( + mock_managed_identity_credential, mock_default_azure_credential, mock_getenv +): + """Test get_azure_credential in non-dev environment.""" + mock_getenv.return_value = "prod" + mock_managed_credential = MagicMock() + mock_managed_identity_credential.return_value = mock_managed_credential + credential = azure_credential_utils.get_azure_credential(client_id="test-client-id") + + mock_getenv.assert_called_once_with("APP_ENV", "prod") + mock_managed_identity_credential.assert_called_once_with(client_id="test-client-id") + mock_default_azure_credential.assert_not_called() + assert credential == mock_managed_credential + + +# Asynchronous tests + + +@pytest.mark.asyncio +@patch("backend.batch.utilities.helpers.azure_credential_utils.os.getenv") +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.AioDefaultAzureCredential" +) +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.AioManagedIdentityCredential" +) +async def test_get_azure_credential_async_dev_env( + mock_aio_managed_identity_credential, mock_aio_default_azure_credential, mock_getenv +): + """Test get_azure_credential_async in dev environment.""" + mock_getenv.return_value = "dev" + mock_aio_default_credential = MagicMock() + mock_aio_default_azure_credential.return_value = mock_aio_default_credential + + credential = await azure_credential_utils.get_azure_credential_async() + + mock_getenv.assert_called_once_with("APP_ENV", "prod") + mock_aio_default_azure_credential.assert_called_once() + mock_aio_managed_identity_credential.assert_not_called() + assert credential == mock_aio_default_credential + + +@pytest.mark.asyncio +@patch("backend.batch.utilities.helpers.azure_credential_utils.os.getenv") +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.AioDefaultAzureCredential" +) +@patch( + "backend.batch.utilities.helpers.azure_credential_utils.AioManagedIdentityCredential" +) +async def test_get_azure_credential_async_non_dev_env( + mock_aio_managed_identity_credential, mock_aio_default_azure_credential, mock_getenv +): + """Test get_azure_credential_async in non-dev environment.""" + mock_getenv.return_value = "prod" + mock_aio_managed_credential = MagicMock() + mock_aio_managed_identity_credential.return_value = mock_aio_managed_credential + + credential = await azure_credential_utils.get_azure_credential_async( + client_id="test-client-id" + ) + + mock_getenv.assert_called_once_with("APP_ENV", "prod") + mock_aio_managed_identity_credential.assert_called_once_with( + client_id="test-client-id" + ) + mock_aio_default_azure_credential.assert_not_called() + assert credential == mock_aio_managed_credential diff --git a/code/tests/utilities/helpers/test_azure_postgres_helper.py b/code/tests/utilities/helpers/test_azure_postgres_helper.py index 7fc10fcec..fb908acab 100644 --- a/code/tests/utilities/helpers/test_azure_postgres_helper.py +++ b/code/tests/utilities/helpers/test_azure_postgres_helper.py @@ -5,9 +5,7 @@ class TestAzurePostgresHelper(unittest.TestCase): - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") def test_create_search_client_success(self, mock_connect, mock_credential): # Arrange @@ -52,14 +50,10 @@ def test_get_search_client_reuses_connection(self, mock_connect): self.assertEqual(connection, mock_connection) mock_connect.assert_not_called() # Ensure no new connection is created - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.RealDictCursor") - def test_get_vector_store_success( - self, mock_cursor, mock_connect, mock_credential - ): + def test_get_vector_store_success(self, mock_cursor, mock_connect, mock_credential): # Arrange # Mock the EnvHelper and set required attributes mock_env_helper = MagicMock() @@ -101,9 +95,7 @@ def test_get_vector_store_success( "host=mock_host user=mock_user dbname=mock_database password=mock-access-token" ) - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") def test_get_vector_store_query_error(self, mock_connect, mock_credential): # Arrange @@ -142,9 +134,7 @@ def raise_exception(*args, **kwargs): self.assertEqual(str(context.exception), "Query execution error") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") def test_create_search_client_connection_error(self, mock_connect, mock_credential): # Arrange @@ -174,9 +164,7 @@ def raise_exception(*args, **kwargs): self.assertEqual(str(context.exception), "Connection error") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") def test_get_files_success(self, mock_env_helper, mock_connect, mock_credential): @@ -215,9 +203,7 @@ def test_get_files_success(self, mock_env_helper, mock_connect, mock_credential) ) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") def test_get_files_no_results(self, mock_env_helper, mock_connect, mock_credential): @@ -251,9 +237,7 @@ def test_get_files_no_results(self, mock_env_helper, mock_connect, mock_credenti self.assertIsNone(result) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @@ -292,9 +276,7 @@ def test_get_files_db_error( ) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @@ -333,9 +315,7 @@ def test_get_files_unexpected_error( ) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -377,9 +357,7 @@ def test_delete_documents_success( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Deleted 3 documents.") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -417,9 +395,7 @@ def test_delete_documents_no_ids( mock_logger.warning.assert_called_with("No IDs provided for deletion.") mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -461,9 +437,7 @@ def test_delete_documents_db_error( mock_connection.rollback.assert_called_once() mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -505,9 +479,7 @@ def test_delete_documents_unexpected_error( mock_connection.rollback.assert_called_once() mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -558,9 +530,7 @@ def test_perform_search_success( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 1 search result(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -602,9 +572,7 @@ def test_perform_search_no_results( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 0 search result(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -645,9 +613,7 @@ def test_perform_search_error( ) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -692,9 +658,7 @@ def test_get_unique_files_success( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 2 unique title(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -734,9 +698,7 @@ def test_get_unique_files_no_results( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 0 unique title(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -775,9 +737,7 @@ def test_get_unique_files_error( ) mock_connection.close.assert_called_once() - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -823,9 +783,7 @@ def test_search_by_blob_url_success( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 2 unique title(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") @@ -866,9 +824,7 @@ def test_search_by_blob_url_no_results( mock_connection.close.assert_called_once() mock_logger.info.assert_called_with("Retrieved 0 unique title(s).") - @patch( - "backend.batch.utilities.helpers.azure_postgres_helper.DefaultAzureCredential" - ) + @patch("backend.batch.utilities.helpers.azure_postgres_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.azure_postgres_helper.psycopg2.connect") @patch("backend.batch.utilities.helpers.azure_postgres_helper.logger") @patch("backend.batch.utilities.helpers.azure_postgres_helper.EnvHelper") diff --git a/code/tests/utilities/helpers/test_azure_search_helper.py b/code/tests/utilities/helpers/test_azure_search_helper.py index e5745d1fe..53e71db78 100644 --- a/code/tests/utilities/helpers/test_azure_search_helper.py +++ b/code/tests/utilities/helpers/test_azure_search_helper.py @@ -142,7 +142,7 @@ def test_creates_search_clients_with_keys( @patch("backend.batch.utilities.helpers.azure_search_helper.SearchClient") @patch("backend.batch.utilities.helpers.azure_search_helper.SearchIndexClient") -@patch("backend.batch.utilities.helpers.azure_search_helper.DefaultAzureCredential") +@patch("backend.batch.utilities.helpers.azure_search_helper.get_azure_credential") def test_creates_search_clients_with_rabc( default_azure_credential_mock: MagicMock, search_index_client_mock: MagicMock, diff --git a/code/tests/utilities/helpers/test_llm_helper.py b/code/tests/utilities/helpers/test_llm_helper.py index 6608ccc83..57a783a18 100644 --- a/code/tests/utilities/helpers/test_llm_helper.py +++ b/code/tests/utilities/helpers/test_llm_helper.py @@ -139,7 +139,7 @@ def test_generate_embeddings_returns_embeddings(azure_openai_mock): assert actual_embeddings == expected_embeddings -@patch("backend.batch.utilities.helpers.llm_helper.DefaultAzureCredential") +@patch("backend.batch.utilities.helpers.llm_helper.get_azure_credential") @patch("backend.batch.utilities.helpers.llm_helper.MLClient") def test_get_ml_client_initializes_with_expected_parameters( mock_ml_client, mock_default_credential, env_helper_mock diff --git a/infra/main.bicep b/infra/main.bicep index 4c087307a..21734bd54 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -310,6 +310,9 @@ param useKeyVault bool = authType == 'rbac' ? false : true @description('Id of the user or app to assign application roles') param principalId string = '' +@description('Application Environment') +param appEnvironment string = 'Prod' + @description('Hosting model for the web apps. This value is fixed as "container", which uses prebuilt containers for faster deployment.') param hostingModel string = 'container' @@ -678,7 +681,8 @@ module web './app/web.bicep' = if (hostingModel == 'code') { LOGLEVEL: logLevel DATABASE_TYPE: databaseType OPEN_AI_FUNCTIONS_SYSTEM_PROMPT: openAIFunctionsSystemPrompt - SEMENTIC_KERNEL_SYSTEM_PROMPT: semanticKernelSystemPrompt + SEMANTIC_KERNEL_SYSTEM_PROMPT: semanticKernelSystemPrompt + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -792,7 +796,8 @@ module web_docker './app/web.bicep' = if (hostingModel == 'container') { LOGLEVEL: logLevel DATABASE_TYPE: databaseType OPEN_AI_FUNCTIONS_SYSTEM_PROMPT: openAIFunctionsSystemPrompt - SEMENTIC_KERNEL_SYSTEM_PROMPT: semanticKernelSystemPrompt + SEMANTIC_KERNEL_SYSTEM_PROMPT: semanticKernelSystemPrompt + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -896,6 +901,7 @@ module adminweb './app/adminweb.bicep' = if (hostingModel == 'code') { CONVERSATION_FLOW: conversationFlow LOGLEVEL: logLevel DATABASE_TYPE: databaseType + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -995,6 +1001,7 @@ module adminweb_docker './app/adminweb.bicep' = if (hostingModel == 'container') CONVERSATION_FLOW: conversationFlow LOGLEVEL: logLevel DATABASE_TYPE: databaseType + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -1123,6 +1130,7 @@ module function './app/function.bicep' = if (hostingModel == 'code') { LOGLEVEL: logLevel AZURE_OPENAI_SYSTEM_MESSAGE: azureOpenAISystemMessage DATABASE_TYPE: databaseType + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -1208,6 +1216,7 @@ module function_docker './app/function.bicep' = if (hostingModel == 'container') LOGLEVEL: logLevel AZURE_OPENAI_SYSTEM_MESSAGE: azureOpenAISystemMessage DATABASE_TYPE: databaseType + APP_ENV: appEnvironment }, // Conditionally add database-specific settings databaseType == 'CosmosDB' @@ -1470,7 +1479,7 @@ var azureSearchServiceInfo = databaseType == 'CosmosDB' : '' var azureComputerVisionInfo = string({ - service_name: speechServiceName + service_name: computerVisionName endpoint: useAdvancedImageProcessing ? computerVision.outputs.endpoint : '' location: useAdvancedImageProcessing ? computerVision.outputs.location : '' key: useKeyVault ? storekeys.outputs.COMPUTER_VISION_KEY_NAME : '' @@ -1505,6 +1514,7 @@ var backendUrl = 'https://${functionName}.azurewebsites.net' output APPLICATIONINSIGHTS_CONNECTION_STRING string = monitoring.outputs.applicationInsightsConnectionString output AZURE_APP_SERVICE_HOSTING_MODEL string = hostingModel +output APP_ENV string = appEnvironment output AZURE_BLOB_STORAGE_INFO string = azureBlobStorageInfo output AZURE_COMPUTER_VISION_INFO string = azureComputerVisionInfo output AZURE_CONTENT_SAFETY_INFO string = azureContentSafetyInfo @@ -1546,4 +1556,4 @@ output AZURE_COSMOSDB_INFO string = azureCosmosDBInfo output AZURE_POSTGRESQL_INFO string = azurePostgresDBInfo output DATABASE_TYPE string = databaseType output OPEN_AI_FUNCTIONS_SYSTEM_PROMPT string = openAIFunctionsSystemPrompt -output SEMENTIC_KERNEL_SYSTEM_PROMPT string = semanticKernelSystemPrompt +output SEMANTIC_KERNEL_SYSTEM_PROMPT string = semanticKernelSystemPrompt diff --git a/infra/main.bicepparam b/infra/main.bicepparam index 50add98f3..0d683f40c 100644 --- a/infra/main.bicepparam +++ b/infra/main.bicepparam @@ -3,6 +3,7 @@ using './main.bicep' param environmentName = readEnvironmentVariable('AZURE_ENV_NAME', 'env_name') param location = readEnvironmentVariable('AZURE_LOCATION', 'location') param principalId = readEnvironmentVariable('AZURE_PRINCIPAL_ID', 'principal_id') +param appEnvironment = readEnvironmentVariable('APP_ENV', 'Prod') // Please make sure to set this value to false when using rbac with AZURE_AUTH_TYPE diff --git a/infra/main.json b/infra/main.json index 6ead6bec5..e6e9060a5 100644 --- a/infra/main.json +++ b/infra/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.36.177.2456", - "templateHash": "5740998106011376838" + "templateHash": "16352542150707902119" } }, "parameters": { @@ -632,6 +632,13 @@ "description": "Id of the user or app to assign application roles" } }, + "appEnvironment": { + "type": "string", + "defaultValue": "Prod", + "metadata": { + "description": "Application Environment" + } + }, "hostingModel": { "type": "string", "defaultValue": "container", @@ -2908,7 +2915,7 @@ "value": "[parameters('authType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_SPEECH_SERVICE_NAME', parameters('speechServiceName'), 'AZURE_SPEECH_SERVICE_REGION', parameters('location'), 'AZURE_SPEECH_RECOGNIZER_LANGUAGES', parameters('recognizedLanguages'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'ADVANCED_IMAGE_PROCESSING_MAX_IMAGES', parameters('advancedImageProcessingMaxImages'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'OPEN_AI_FUNCTIONS_SYSTEM_PROMPT', variables('openAIFunctionsSystemPrompt'), 'SEMENTIC_KERNEL_SYSTEM_PROMPT', variables('semanticKernelSystemPrompt')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_COSMOSDB_ACCOUNT_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosAccountName, 'AZURE_COSMOSDB_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosDatabaseName, 'AZURE_COSMOSDB_CONVERSATIONS_CONTAINER_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosContainerName, 'AZURE_COSMOSDB_ENABLE_FEEDBACK', true(), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_CONVERSATIONS_LOG_INDEX', parameters('azureSearchConversationLogIndex'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('websiteName')), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_SPEECH_SERVICE_NAME', parameters('speechServiceName'), 'AZURE_SPEECH_SERVICE_REGION', parameters('location'), 'AZURE_SPEECH_RECOGNIZER_LANGUAGES', parameters('recognizedLanguages'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'ADVANCED_IMAGE_PROCESSING_MAX_IMAGES', parameters('advancedImageProcessingMaxImages'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'OPEN_AI_FUNCTIONS_SYSTEM_PROMPT', variables('openAIFunctionsSystemPrompt'), 'SEMANTIC_KERNEL_SYSTEM_PROMPT', variables('semanticKernelSystemPrompt'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_COSMOSDB_ACCOUNT_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosAccountName, 'AZURE_COSMOSDB_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosDatabaseName, 'AZURE_COSMOSDB_CONVERSATIONS_CONTAINER_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosContainerName, 'AZURE_COSMOSDB_ENABLE_FEEDBACK', true(), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_CONVERSATIONS_LOG_INDEX', parameters('azureSearchConversationLogIndex'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('websiteName')), createObject())))]" } }, "template": { @@ -3897,7 +3904,7 @@ "value": "[parameters('authType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_SPEECH_SERVICE_NAME', parameters('speechServiceName'), 'AZURE_SPEECH_SERVICE_REGION', parameters('location'), 'AZURE_SPEECH_RECOGNIZER_LANGUAGES', parameters('recognizedLanguages'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'ADVANCED_IMAGE_PROCESSING_MAX_IMAGES', parameters('advancedImageProcessingMaxImages'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'OPEN_AI_FUNCTIONS_SYSTEM_PROMPT', variables('openAIFunctionsSystemPrompt'), 'SEMENTIC_KERNEL_SYSTEM_PROMPT', variables('semanticKernelSystemPrompt')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_COSMOSDB_ACCOUNT_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosAccountName, 'AZURE_COSMOSDB_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosDatabaseName, 'AZURE_COSMOSDB_CONVERSATIONS_CONTAINER_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosContainerName, 'AZURE_COSMOSDB_ENABLE_FEEDBACK', true(), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_CONVERSATIONS_LOG_INDEX', parameters('azureSearchConversationLogIndex'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('websiteName'))), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_SPEECH_SERVICE_NAME', parameters('speechServiceName'), 'AZURE_SPEECH_SERVICE_REGION', parameters('location'), 'AZURE_SPEECH_RECOGNIZER_LANGUAGES', parameters('recognizedLanguages'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'ADVANCED_IMAGE_PROCESSING_MAX_IMAGES', parameters('advancedImageProcessingMaxImages'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'OPEN_AI_FUNCTIONS_SYSTEM_PROMPT', variables('openAIFunctionsSystemPrompt'), 'SEMANTIC_KERNEL_SYSTEM_PROMPT', variables('semanticKernelSystemPrompt'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_COSMOSDB_ACCOUNT_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosAccountName, 'AZURE_COSMOSDB_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosDatabaseName, 'AZURE_COSMOSDB_CONVERSATIONS_CONTAINER_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosOutput.value.cosmosContainerName, 'AZURE_COSMOSDB_ENABLE_FEEDBACK', true(), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_CONVERSATIONS_LOG_INDEX', parameters('azureSearchConversationLogIndex'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('websiteName'))), createObject())))]" } }, "template": { @@ -4885,7 +4892,7 @@ "value": "[parameters('databaseType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'BACKEND_URL', format('https://{0}.azurewebsites.net', parameters('functionName')), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'FUNCTION_KEY', variables('clientKey'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('adminWebsiteName')), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'BACKEND_URL', format('https://{0}.azurewebsites.net', parameters('functionName')), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'FUNCTION_KEY', variables('clientKey'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('adminWebsiteName')), createObject())))]" } }, "template": { @@ -5796,7 +5803,7 @@ "value": "[parameters('databaseType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'BACKEND_URL', format('https://{0}-docker.azurewebsites.net', parameters('functionName')), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'FUNCTION_KEY', variables('clientKey'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('adminWebsiteName'))), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_TEMPERATURE', parameters('azureOpenAITemperature'), 'AZURE_OPENAI_TOP_P', parameters('azureOpenAITopP'), 'AZURE_OPENAI_MAX_TOKENS', parameters('azureOpenAIMaxTokens'), 'AZURE_OPENAI_STOP_SEQUENCE', parameters('azureOpenAIStopSequence'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'AZURE_OPENAI_STREAM', parameters('azureOpenAIStream'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'BACKEND_URL', format('https://{0}-docker.azurewebsites.net', parameters('functionName')), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'FUNCTION_KEY', variables('clientKey'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'CONVERSATION_FLOW', parameters('conversationFlow'), 'LOGLEVEL', parameters('logLevel'), 'DATABASE_TYPE', parameters('databaseType'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_USE_SEMANTIC_SEARCH', parameters('azureSearchUseSemanticSearch'), 'AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG', parameters('azureSearchSemanticSearchConfig'), 'AZURE_SEARCH_INDEX_IS_PRECHUNKED', parameters('azureSearchIndexIsPrechunked'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK'), 'AZURE_SEARCH_ENABLE_IN_DOMAIN', parameters('azureSearchEnableInDomain'), 'AZURE_SEARCH_FILENAME_COLUMN', parameters('azureSearchFilenameColumn'), 'AZURE_SEARCH_FILTER', parameters('azureSearchFilter'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_URL_COLUMN', parameters('azureSearchUrlColumn'), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('adminWebsiteName'))), createObject())))]" } }, "template": { @@ -8473,7 +8480,7 @@ "value": "[parameters('databaseType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'LOGLEVEL', parameters('logLevel'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'DATABASE_TYPE', parameters('databaseType')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('functionName')), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'LOGLEVEL', parameters('logLevel'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'DATABASE_TYPE', parameters('databaseType'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', parameters('functionName')), createObject())))]" } }, "template": { @@ -9777,7 +9784,7 @@ "value": "[parameters('databaseType')]" }, "appSettings": { - "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'LOGLEVEL', parameters('logLevel'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'DATABASE_TYPE', parameters('databaseType')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('functionName'))), createObject())))]" + "value": "[union(createObject('AZURE_BLOB_ACCOUNT_NAME', parameters('storageAccountName'), 'AZURE_BLOB_CONTAINER_NAME', variables('blobContainerName'), 'AZURE_FORM_RECOGNIZER_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('formRecognizerName')), '2022-09-01').outputs.endpoint.value, 'AZURE_COMPUTER_VISION_ENDPOINT', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_API_VERSION', parameters('computerVisionVectorizeImageApiVersion'), 'AZURE_COMPUTER_VISION_VECTORIZE_IMAGE_MODEL_VERSION', parameters('computerVisionVectorizeImageModelVersion'), 'AZURE_CONTENT_SAFETY_ENDPOINT', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', parameters('contentSafetyName')), '2022-09-01').outputs.endpoint.value, 'AZURE_OPENAI_MODEL', parameters('azureOpenAIModel'), 'AZURE_OPENAI_MODEL_NAME', parameters('azureOpenAIModelName'), 'AZURE_OPENAI_MODEL_VERSION', parameters('azureOpenAIModelVersion'), 'AZURE_OPENAI_EMBEDDING_MODEL', parameters('azureOpenAIEmbeddingModel'), 'AZURE_OPENAI_EMBEDDING_MODEL_NAME', parameters('azureOpenAIEmbeddingModelName'), 'AZURE_OPENAI_EMBEDDING_MODEL_VERSION', parameters('azureOpenAIEmbeddingModelVersion'), 'AZURE_OPENAI_RESOURCE', parameters('azureOpenAIResourceName'), 'AZURE_OPENAI_API_VERSION', parameters('azureOpenAIApiVersion'), 'USE_ADVANCED_IMAGE_PROCESSING', parameters('useAdvancedImageProcessing'), 'DOCUMENT_PROCESSING_QUEUE_NAME', variables('queueName'), 'ORCHESTRATION_STRATEGY', parameters('orchestrationStrategy'), 'LOGLEVEL', parameters('logLevel'), 'AZURE_OPENAI_SYSTEM_MESSAGE', parameters('azureOpenAISystemMessage'), 'DATABASE_TYPE', parameters('databaseType'), 'APP_ENV', parameters('appEnvironment')), if(equals(parameters('databaseType'), 'CosmosDB'), createObject('AZURE_SEARCH_INDEX', parameters('azureSearchIndex'), 'AZURE_SEARCH_SERVICE', format('https://{0}.search.windows.net', parameters('azureAISearchName')), 'AZURE_SEARCH_DATASOURCE_NAME', parameters('azureSearchDatasource'), 'AZURE_SEARCH_INDEXER_NAME', parameters('azureSearchIndexer'), 'AZURE_SEARCH_USE_INTEGRATED_VECTORIZATION', parameters('azureSearchUseIntegratedVectorization'), 'AZURE_SEARCH_FIELDS_ID', parameters('azureSearchFieldId'), 'AZURE_SEARCH_CONTENT_COLUMN', parameters('azureSearchContentColumn'), 'AZURE_SEARCH_CONTENT_VECTOR_COLUMN', parameters('azureSearchVectorColumn'), 'AZURE_SEARCH_TITLE_COLUMN', parameters('azureSearchTitleColumn'), 'AZURE_SEARCH_FIELDS_METADATA', parameters('azureSearchFieldsMetadata'), 'AZURE_SEARCH_SOURCE_COLUMN', parameters('azureSearchSourceColumn'), 'AZURE_SEARCH_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchTextColumn'), ''), 'AZURE_SEARCH_LAYOUT_TEXT_COLUMN', if(parameters('azureSearchUseIntegratedVectorization'), parameters('azureSearchLayoutTextColumn'), ''), 'AZURE_SEARCH_CHUNK_COLUMN', parameters('azureSearchChunkColumn'), 'AZURE_SEARCH_OFFSET_COLUMN', parameters('azureSearchOffsetColumn'), 'AZURE_SEARCH_TOP_K', parameters('azureSearchTopK')), if(equals(parameters('databaseType'), 'PostgreSQL'), createObject('AZURE_POSTGRESQL_HOST_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLServerName, 'AZURE_POSTGRESQL_DATABASE_NAME', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'deploy_postgres_sql'), '2022-09-01').outputs.postgresDbOutput.value.postgreSQLDatabaseName, 'AZURE_POSTGRESQL_USER', format('{0}-docker', parameters('functionName'))), createObject())))]" } }, "template": { @@ -12240,13 +12247,17 @@ "type": "string", "value": "[parameters('hostingModel')]" }, + "APP_ENV": { + "type": "string", + "value": "[parameters('appEnvironment')]" + }, "AZURE_BLOB_STORAGE_INFO": { "type": "string", "value": "[string(createObject('container_name', variables('blobContainerName'), 'account_name', parameters('storageAccountName'), 'account_key', if(parameters('useKeyVault'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'storekeys'), '2022-09-01').outputs.STORAGE_ACCOUNT_KEY_NAME.value, '')))]" }, "AZURE_COMPUTER_VISION_INFO": { "type": "string", - "value": "[string(createObject('service_name', parameters('speechServiceName'), 'endpoint', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'location', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.location.value, ''), 'key', if(parameters('useKeyVault'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'storekeys'), '2022-09-01').outputs.COMPUTER_VISION_KEY_NAME.value, ''), 'vectorize_image_api_version', parameters('computerVisionVectorizeImageApiVersion'), 'vectorize_image_model_version', parameters('computerVisionVectorizeImageModelVersion')))]" + "value": "[string(createObject('service_name', parameters('computerVisionName'), 'endpoint', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.endpoint.value, ''), 'location', if(parameters('useAdvancedImageProcessing'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'computerVision'), '2022-09-01').outputs.location.value, ''), 'key', if(parameters('useKeyVault'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('rgName')), 'Microsoft.Resources/deployments', 'storekeys'), '2022-09-01').outputs.COMPUTER_VISION_KEY_NAME.value, ''), 'vectorize_image_api_version', parameters('computerVisionVectorizeImageApiVersion'), 'vectorize_image_model_version', parameters('computerVisionVectorizeImageModelVersion')))]" }, "AZURE_CONTENT_SAFETY_INFO": { "type": "string", @@ -12372,7 +12383,7 @@ "type": "string", "value": "[variables('openAIFunctionsSystemPrompt')]" }, - "SEMENTIC_KERNEL_SYSTEM_PROMPT": { + "SEMANTIC_KERNEL_SYSTEM_PROMPT": { "type": "string", "value": "[variables('semanticKernelSystemPrompt')]" } diff --git a/scripts/data_scripts/azure_credential_utils.py b/scripts/data_scripts/azure_credential_utils.py new file mode 100644 index 000000000..e8d9d7051 --- /dev/null +++ b/scripts/data_scripts/azure_credential_utils.py @@ -0,0 +1,48 @@ +import os +from azure.identity import ManagedIdentityCredential, DefaultAzureCredential +from azure.identity.aio import ( + ManagedIdentityCredential as AioManagedIdentityCredential, + DefaultAzureCredential as AioDefaultAzureCredential, +) + + +async def get_azure_credential_async(client_id=None): + """ + Returns an Azure credential asynchronously based on the application environment. + + If the environment is 'dev', it uses AioDefaultAzureCredential. + Otherwise, it uses AioManagedIdentityCredential. + + Args: + client_id (str, optional): The client ID for the Managed Identity Credential. + + Returns: + Credential object: Either AioDefaultAzureCredential or AioManagedIdentityCredential. + """ + if os.getenv("APP_ENV", "prod").lower() == "dev": + return ( + AioDefaultAzureCredential() + ) # CodeQL [SM05139] Okay use of DefaultAzureCredential as it is only used in development + else: + return AioManagedIdentityCredential(client_id=client_id) + + +def get_azure_credential(client_id=None): + """ + Returns an Azure credential based on the application environment. + + If the environment is 'dev', it uses DefaultAzureCredential. + Otherwise, it uses ManagedIdentityCredential. + + Args: + client_id (str, optional): The client ID for the Managed Identity Credential. + + Returns: + Credential object: Either DefaultAzureCredential or ManagedIdentityCredential. + """ + if os.getenv("APP_ENV", "prod").lower() == "dev": + return ( + DefaultAzureCredential() + ) # CodeQL [SM05139] Okay use of DefaultAzureCredential as it is only used in development + else: + return ManagedIdentityCredential(client_id=client_id) diff --git a/scripts/data_scripts/create_postgres_tables.py b/scripts/data_scripts/create_postgres_tables.py index 805fd7621..14e395d4f 100644 --- a/scripts/data_scripts/create_postgres_tables.py +++ b/scripts/data_scripts/create_postgres_tables.py @@ -1,4 +1,4 @@ -from azure.identity import DefaultAzureCredential +from azure_credential_utils import get_azure_credential import psycopg2 from psycopg2 import sql @@ -61,7 +61,7 @@ def grant_permissions(cursor, dbname, schema_name, principal_name): # Acquire the access token -cred = DefaultAzureCredential() +cred = get_azure_credential() access_token = cred.get_token("https://ossrdbms-aad.database.windows.net/.default") # Combine the token with the connection string to establish the connection. diff --git a/scripts/data_scripts/requirements.txt b/scripts/data_scripts/requirements.txt index 3cb4d1b3e..614c2c4bd 100644 --- a/scripts/data_scripts/requirements.txt +++ b/scripts/data_scripts/requirements.txt @@ -1,3 +1,3 @@ psycopg2-binary==2.9.10 -azure-identity==1.19.0 -azure-keyvault-secrets==4.9.0 +azure-identity==1.23.1 +azure-keyvault-secrets==4.7.0 diff --git a/scripts/run_create_table_script.sh b/scripts/run_create_table_script.sh index 8777ecbc5..90a20c50e 100644 --- a/scripts/run_create_table_script.sh +++ b/scripts/run_create_table_script.sh @@ -23,6 +23,7 @@ az postgres flexible-server firewall-rule create --resource-group $resourceGroup # Download the create table python file curl --output "create_postgres_tables.py" ${baseUrl}"scripts/data_scripts/create_postgres_tables.py" +curl --output "azure_credential_utils.py" ${baseUrl}"scripts/data_scripts/azure_credential_utils.py" # Download the requirement file curl --output "$requirementFile" "$requirementFileUrl"