Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Infrastructure as Code #2

Merged
merged 24 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/_terraformEnvironmentTemplate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ jobs:
runs-on: [self-hosted]
continue-on-error: false
environment: ${{ inputs.environment }}
if: github.event_name == 'push' || github.event_name == 'release'
# if: github.event_name == 'push' || github.event_name == 'release'
needs: [plan]

env:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
with:
environment: "dev"
config: "PerfectThymeTech"
terraform_version: "1.9.4"
terraform_version: "1.9.5"
node_version: 20
working_directory: "./code/infra"
tenant_id: "3556be79-2979-4b19-a1af-4dd4e6d9ed7e"
Expand All @@ -39,7 +39,7 @@ jobs:
with:
environment: "dev"
config: "PerfectThymeTech"
terraform_version: "1.9.4"
terraform_version: "1.9.5"
node_version: 20
working_directory: "./code/infra"
tenant_id: "3556be79-2979-4b19-a1af-4dd4e6d9ed7e"
Expand Down
7 changes: 4 additions & 3 deletions code/backend/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ class Settings(BaseSettings):
APP_ID: str = Field(default="", alias="MICROSOFT_APP_ID")
APP_PASSWORD: str = Field(default="", alias="MICROSOFT_APP_PASSWORD")
APP_TENANTID: str = Field(default="", alias="MICROSOFT_APP_TENANTID")
APP_TYPE: str = Field(default="MultiTenant", alias="MICROSOFT_APP_TYPE")
APP_TYPE: str = Field(default="UserAssignedMSI", alias="MICROSOFT_APP_TYPE")

# Azure Open AI settings
AZURE_OPEN_AI_ENDPOINT: str
AZURE_OPEN_AI_API_VERSION: str
AZURE_OPENAI_API_KEY: str
AZURE_OPEN_AI_API_VERSION: str = "2024-05-01-preview"
AZURE_OPENAI_SYSTEM_PROMPT: str
AZURE_OPENAI_MODEL_NAME: str
AZURE_OPENAI_ASSISTANT_ID: str


Expand Down
24 changes: 22 additions & 2 deletions code/backend/llm/assisstant.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import time

from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from core.config import settings
from openai import AzureOpenAI
from openai.types.beta.threads import Run
Expand All @@ -12,12 +13,31 @@ def __init__(
self,
*args,
) -> None:
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
)
self.client = AzureOpenAI(
api_key=settings.AZURE_OPENAI_API_KEY,
api_version=settings.AZURE_OPEN_AI_API_VERSION,
azure_endpoint=settings.AZURE_OPEN_AI_ENDPOINT,
azure_ad_token_provider=token_provider,
)
if settings.AZURE_OPENAI_ASSISTANT_ID:
self.assistant_id = settings.AZURE_OPENAI_ASSISTANT_ID
else:
self.assistant_id = self.__init_assistant()

def __init_assistant(self) -> str:
"""Creates an assistant if no assistant id was provided.

RETURNS (str): Assistant id of the newly created assistant.
"""
assistant = self.client.beta.assistants.create(
name=settings.PROJECT_NAME,
instructions=settings.AZURE_OPENAI_SYSTEM_PROMPT,
tools=[],
model=settings.AZURE_OPENAI_MODEL_NAME,
)
self.assistant_id = settings.AZURE_OPENAI_ASSISTANT_ID
return assistant.id

def create_thread(self) -> str:
"""Create a thread in the assistant.
Expand Down
1 change: 1 addition & 0 deletions code/backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
azure-identity~=1.17.1
botbuilder-core~=4.16.1
botbuilder-integration-aiohttp~=4.16.1
pydantic-settings~=2.2.1
Expand Down
Empty file removed code/infra/.gitkeep
Empty file.
39 changes: 39 additions & 0 deletions code/infra/aoai.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module "azure_open_ai" {
source = "github.com/PerfectThymeTech/terraform-azurerm-modules//modules/aiservice?ref=main"
providers = {
azurerm = azurerm
time = time
}

location = var.location_openai
location_private_endpoint = var.location
resource_group_name = azurerm_resource_group.resource_group.name
tags = var.tags
cognitive_account_name = "${local.prefix}-aoai001"
cognitive_account_kind = "OpenAI"
cognitive_account_sku = "S0"
cognitive_account_firewall_bypass_azure_services = false
cognitive_account_outbound_network_access_restricted = true
cognitive_account_outbound_network_access_allowed_fqdns = []
cognitive_account_deployments = {}
diagnostics_configurations = []
subnet_id = "/subscriptions/8f171ff9-2b5b-4f0f-aed5-7fa360a1d094/resourceGroups/tfmdltst-dev-rg/providers/Microsoft.Network/virtualNetworks/tfmdltst-dev-vnet/subnets/PrivateEndpoints"
connectivity_delay_in_seconds = 0
private_dns_zone_id_cognitive_account = "/subscriptions/8f171ff9-2b5b-4f0f-aed5-7fa360a1d094/resourceGroups/mycrp-prd-global-dns/providers/Microsoft.Network/privateDnsZones/privatelink.cognitiveservices.azure.com"
customer_managed_key = null
}

resource "azurerm_cognitive_deployment" "cognitive_deployment_gpt_4o" {
name = "gpt-4o"
cognitive_account_id = module.azure_open_ai.cognitive_account_id

model {
format = "OpenAI"
name = "gpt-4o"
version = "2024-05-13"
}
scale {
capacity = 100
type = "Standard"
}
}
14 changes: 14 additions & 0 deletions code/infra/applicationinsights.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module "application_insights" {
source = "github.com/PerfectThymeTech/terraform-azurerm-modules//modules/applicationinsights?ref=main"
providers = {
azurerm = azurerm
}

location = var.location
resource_group_name = azurerm_resource_group.resource_group.name
tags = var.tags
application_insights_name = "${local.prefix}-ai001"
application_insights_application_type = "web"
application_insights_log_analytics_workspace_id = var.log_analytics_workspace_id
diagnostics_configurations = local.diagnostics_configurations
}
18 changes: 18 additions & 0 deletions code/infra/appserviceplan.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module "app_service_plan" {
source = "github.com/PerfectThymeTech/terraform-azurerm-modules//modules/appserviceplan?ref=main"
providers = {
azurerm = azurerm
}

location = var.location
resource_group_name = azurerm_resource_group.resource_group.name
tags = var.tags
service_plan_name = "${local.prefix}-asp001"
service_plan_maximum_elastic_worker_count = null
service_plan_os_type = "Linux"
service_plan_per_site_scaling_enabled = false
service_plan_sku_name = "P0v3"
service_plan_worker_count = 1
service_plan_zone_balancing_enabled = false
diagnostics_configurations = local.diagnostics_configurations
}
34 changes: 34 additions & 0 deletions code/infra/botservice.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module "bot_service" {
source = "github.com/PerfectThymeTech/terraform-azurerm-modules//modules/botservice?ref=main"
providers = {
azurerm = azurerm
time = time
}

location = var.location
resource_group_name = azurerm_resource_group.resource_group.name
tags = var.tags
bot_service_name = "${local.prefix}-bot001"
bot_service_location = "global"
bot_service_endpoint = "https://${azurerm_linux_web_app.linux_web_app.default_hostname}"
bot_service_luis = {
app_ids = []
key = null
}
bot_service_microsoft_app = {
app_id = module.user_assigned_identity.user_assigned_identity_client_id
app_msi_id = module.user_assigned_identity.user_assigned_identity_id
app_tenant_id = module.user_assigned_identity.user_assigned_identity_tenant_id
app_type = "UserAssignedMSI"
}
bot_service_sku = "S1"
bot_service_streaming_endpoint_enabled = false
bot_service_public_network_access_enabled = true
bot_service_application_insights_id = module.application_insights.application_insights_id
diagnostics_configurations = local.diagnostics_configurations
subnet_id = azapi_resource.subnet_private_endpoints.id
connectivity_delay_in_seconds = var.connectivity_delay_in_seconds
private_dns_zone_id_bot_framework_directline = var.private_dns_zone_id_bot_framework_directline
private_dns_zone_id_bot_framework_token = var.private_dns_zone_id_bot_framework_token
customer_managed_key = local.customer_managed_key
}
23 changes: 23 additions & 0 deletions code/infra/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
data "azurerm_virtual_network" "virtual_network" {
name = local.virtual_network.name
resource_group_name = local.virtual_network.resource_group_name
}

data "azurerm_network_security_group" "network_security_group" {
name = local.network_security_group.name
resource_group_name = local.network_security_group.resource_group_name
}

data "azurerm_route_table" "route_table" {
name = local.route_table.name
resource_group_name = local.route_table.resource_group_name
}

data "azurerm_log_analytics_workspace" "log_analytics_workspace" {
name = local.log_analytics_workspace.name
resource_group_name = local.log_analytics_workspace.resource_group_name
}

data "local_file" "file_system_prompt" {
filename = local.system_prompt_code_path
}
18 changes: 18 additions & 0 deletions code/infra/keyvault.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module "key_vault" {
source = "github.com/PerfectThymeTech/terraform-azurerm-modules//modules/keyvault?ref=main"
providers = {
azurerm = azurerm
time = time
}

location = var.location
resource_group_name = azurerm_resource_group.resource_group.name
tags = var.tags
key_vault_name = "${local.prefix}-kv001"
key_vault_sku_name = "standard"
key_vault_soft_delete_retention_days = 7
diagnostics_configurations = local.diagnostics_configurations
subnet_id = azapi_resource.subnet_private_endpoints.id
connectivity_delay_in_seconds = var.connectivity_delay_in_seconds
private_dns_zone_id_vault = var.private_dns_zone_id_vault
}
57 changes: 57 additions & 0 deletions code/infra/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
locals {
# Naming locals
prefix = "${lower(var.prefix)}-${var.environment}"

# Web app locals
app_settings_default = {
# Configuration app settings
SCM_DO_BUILD_DURING_DEPLOYMENT = "true"
WEBSITE_CONTENTOVERVNET = "1"

# Auth app settings
MICROSOFT_APP_ID = module.user_assigned_identity.user_assigned_identity_client_id
MICROSOFT_APP_PASSWORD = ""
MICROSOFT_APP_TENANTID = module.user_assigned_identity.user_assigned_identity_tenant_id
MICROSOFT_APP_TYPE = "UserAssignedMSI"

# Azure open ai app settings
AZURE_OPEN_AI_ENDPOINT = module.azure_open_ai.cognitive_account_endpoint
AZURE_OPEN_AI_API_VERSION = "2024-05-01-preview"
AZURE_OPENAI_MODEL_NAME = azurerm_cognitive_deployment.cognitive_deployment_gpt_4o.name
AZURE_OPENAI_SYSTEM_PROMPT = data.local_file.file_system_prompt.content
AZURE_OPENAI_ASSISTANT_ID = ""
}
web_app_app_settings = merge(local.app_settings_default, var.web_app_app_settings)

# Resource locals
virtual_network = {
resource_group_name = split("/", var.vnet_id)[4]
name = split("/", var.vnet_id)[8]
}
network_security_group = {
resource_group_name = split("/", var.nsg_id)[4]
name = split("/", var.nsg_id)[8]
}
route_table = {
resource_group_name = split("/", var.route_table_id)[4]
name = split("/", var.route_table_id)[8]
}
log_analytics_workspace = {
resource_group_name = split("/", var.log_analytics_workspace_id)[4]
name = split("/", var.log_analytics_workspace_id)[8]
}

# Logging locals
diagnostics_configurations = [
{
log_analytics_workspace_id = var.log_analytics_workspace_id
storage_account_id = ""
}
]

# CMK locals
customer_managed_key = null

# Other locals
system_prompt_code_path = "${path.module}/../../docs/SystemPrompt.txt"
}
5 changes: 5 additions & 0 deletions code/infra/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "azurerm_resource_group" "resource_group" {
name = "${local.prefix}-bot-rg"
location = var.location
tags = var.tags
}
58 changes: 58 additions & 0 deletions code/infra/network.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
resource "azapi_resource" "subnet_web_app" {
type = "Microsoft.Network/virtualNetworks/subnets@2022-07-01"
name = "WebAppSubnet"
parent_id = data.azurerm_virtual_network.virtual_network.id

body = jsonencode({
properties = {
addressPrefix = var.subnet_cidr_web_app
delegations = [
{
name = "WebAppDelegation"
properties = {
serviceName = "Microsoft.Web/serverfarms"
}
}
]
ipAllocations = []
networkSecurityGroup = {
id = data.azurerm_network_security_group.network_security_group.id
}
privateEndpointNetworkPolicies = "Enabled"
privateLinkServiceNetworkPolicies = "Enabled"
routeTable = {
id = data.azurerm_route_table.route_table.id
}
serviceEndpointPolicies = []
serviceEndpoints = []
}
})
}

resource "azapi_resource" "subnet_private_endpoints" {
type = "Microsoft.Network/virtualNetworks/subnets@2022-07-01"
name = "PrivateEndpointSubnet"
parent_id = data.azurerm_virtual_network.virtual_network.id

body = jsonencode({
properties = {
addressPrefix = var.subnet_cidr_private_endpoints
delegations = []
ipAllocations = []
networkSecurityGroup = {
id = data.azurerm_network_security_group.network_security_group.id
}
privateEndpointNetworkPolicies = "Enabled"
privateLinkServiceNetworkPolicies = "Enabled"
routeTable = {
id = data.azurerm_route_table.route_table.id
}
serviceEndpointPolicies = []
serviceEndpoints = []
}
})

depends_on = [
azapi_resource.subnet_web_app
]
}
28 changes: 28 additions & 0 deletions code/infra/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
provider "azurerm" {
disable_correlation_request_id = false
environment = "public"
skip_provider_registration = false
storage_use_azuread = true
# use_oidc = true

features {
key_vault {
recover_soft_deleted_key_vaults = true
recover_soft_deleted_certificates = true
recover_soft_deleted_keys = true
recover_soft_deleted_secrets = true
}
resource_group {
prevent_deletion_if_contains_resources = true
}
}
}

provider "azapi" {
default_location = var.location
default_tags = var.tags
disable_correlation_request_id = false
environment = "public"
skip_provider_registration = false
# use_oidc = true
}
Loading
Loading