From 523bf9ddaa591e55e3d643e21231d9f517ea0935 Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Wed, 24 Jul 2024 17:50:50 -0400 Subject: [PATCH 01/10] Add Standard Hub Network deployment --- deploy/standard-hub/.gitignore | 1 + deploy/standard-hub/README.md | 5 + .../standard-hub/azd-hooks/postprovision.ps1 | 82 +++++++++++ deploy/standard-hub/azure.yaml | 10 ++ deploy/standard-hub/infra/abbreviations.json | 137 ++++++++++++++++++ .../infra/core/networking/dns.bicep | 30 ++++ .../infra/core/networking/dnsResolver.bicep | 43 ++++++ .../infra/core/networking/vnet.bicep | 66 +++++++++ .../infra/core/networking/vpnGateway.bicep | 93 ++++++++++++ deploy/standard-hub/infra/main.bicep | 111 ++++++++++++++ .../standard-hub/infra/main.parameters.json | 12 ++ 11 files changed, 590 insertions(+) create mode 100644 deploy/standard-hub/.gitignore create mode 100644 deploy/standard-hub/README.md create mode 100644 deploy/standard-hub/azd-hooks/postprovision.ps1 create mode 100644 deploy/standard-hub/azure.yaml create mode 100644 deploy/standard-hub/infra/abbreviations.json create mode 100644 deploy/standard-hub/infra/core/networking/dns.bicep create mode 100644 deploy/standard-hub/infra/core/networking/dnsResolver.bicep create mode 100644 deploy/standard-hub/infra/core/networking/vnet.bicep create mode 100644 deploy/standard-hub/infra/core/networking/vpnGateway.bicep create mode 100644 deploy/standard-hub/infra/main.bicep create mode 100644 deploy/standard-hub/infra/main.parameters.json diff --git a/deploy/standard-hub/.gitignore b/deploy/standard-hub/.gitignore new file mode 100644 index 0000000000..347ea51b72 --- /dev/null +++ b/deploy/standard-hub/.gitignore @@ -0,0 +1 @@ +.azure \ No newline at end of file diff --git a/deploy/standard-hub/README.md b/deploy/standard-hub/README.md new file mode 100644 index 0000000000..071f79d700 --- /dev/null +++ b/deploy/standard-hub/README.md @@ -0,0 +1,5 @@ +## Deployment Configurations and Scripts + +The deployment configurations and scripts are located in this `deploy` directory. +If you are looking for the deployment instructions, please refer to the [documentation](https://docs.foundationallm.ai) and it is also available in this repository in the `docs` directory as markdown files. +[Setup Guides in Markdown format](https://github.com/solliancenet/foundationallm/blob/main/docs/setup-guides/index.md) \ No newline at end of file diff --git a/deploy/standard-hub/azd-hooks/postprovision.ps1 b/deploy/standard-hub/azd-hooks/postprovision.ps1 new file mode 100644 index 0000000000..273dcb995d --- /dev/null +++ b/deploy/standard-hub/azd-hooks/postprovision.ps1 @@ -0,0 +1,82 @@ +#!/usr/bin/env pwsh + +Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable) +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + +# Variables - Replace these with your actual values + +$dnsServerIp = "${env:DNS_RESOLVER_ENDPOINT_IP}" +$outputFolderPath = "../standard-hub/config/vpn" +$outputFilePath = "$outputFolderPath/VpnClientConfiguration.zip" +$resourceGroupName = "rg-${env:AZURE_ENV_NAME}-${env:AZURE_LOCATION}-net-${env:FLLM_PROJECT}" +$vpnGatewayName = "vpng-${env:AZURE_ENV_NAME}-${env:AZURE_LOCATION}-net-${env:FLLM_PROJECT}" +$xmlFilePath = "$outputFolderPath/AzureVPN/azurevpnconfig.xml" # Assuming the XML file is inside the extracted folder + +# Add the dns-resolver extension to the cli +az extension add --name dns-resolver --allow-preview true --yes --only-show-errors + +# Get the VPN client configuration package URL +$vpnClientPackageUrl = az network vnet-gateway vpn-client generate ` + --resource-group $resourceGroupName ` + --name $vpnGatewayName + +# Remove quotes from the URL +$vpnClientPackageUrl = $vpnClientPackageUrl -replace '"', '' + +# Download the package +Invoke-WebRequest -Uri $vpnClientPackageUrl -OutFile $outputFilePath + +# Expand the ZIP file +Expand-Archive -Path $outputFilePath -DestinationPath $outputFolderPath -Force + +# Assuming the XML file is directly inside the expanded folder +$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName +$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml" + +# Assuming the XML file is directly inside the expanded folder +$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName +$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml" + +# Read the XML file +$xmlContent = Get-Content -Path $xmlFilePath +$azureVpnClientConfig = [xml]$xmlContent + +# Create a namespace manager +$namespaceManager = New-Object System.Xml.XmlNamespaceManager($azureVpnClientConfig.NameTable) +$namespaceManager.AddNamespace("ns", "http://schemas.datacontract.org/2004/07/") +$namespaceManager.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance") + +# Remove node if it exists +$nilClientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig[@i:nil='true']", $namespaceManager) +if ($nilClientConfigNode -ne $null) { + $nilClientConfigNode.ParentNode.RemoveChild($nilClientConfigNode) | Out-Null +} + +# Create DNS servers XML nodes +$dnsServersNode = $azureVpnClientConfig.CreateElement("dnsservers", "http://schemas.datacontract.org/2004/07/") +$dnsServer1 = $azureVpnClientConfig.CreateElement("dnsserver", "http://schemas.datacontract.org/2004/07/") +$dnsServer1.InnerText = $dnsServerIp +$dnsServersNode.AppendChild($dnsServer1) | Out-Null + +# Locate the clientconfig node or create it if it doesn't exist +$clientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig", $namespaceManager) +if ($clientConfigNode -eq $null) { + $clientConfigNode = $azureVpnClientConfig.CreateElement("clientconfig", "http://schemas.datacontract.org/2004/07/") + $azureVpnClientConfig.DocumentElement.AppendChild($clientConfigNode) | Out-Null +} + +# Append DNS servers to clientconfig +$clientConfigNode.AppendChild($dnsServersNode) | Out-Null + +# Save the updated XML file +$azureVpnClientConfig.Save($xmlFilePath) + +Write-Host -ForegroundColor Yellow ` +"Please Install the Azure VPN client via https://aka.ms/azvpnclientdownload, +then import the VPN client configuration package downloaded to +foundationallm/deploy/standard-hub/config/vpn/AzureVPN/azurevpnconfig.xml +Make sure to connect to the VPN prior to running the next step of the +FLLM Install for Standard." + + diff --git a/deploy/standard-hub/azure.yaml b/deploy/standard-hub/azure.yaml new file mode 100644 index 0000000000..597e9fc9ce --- /dev/null +++ b/deploy/standard-hub/azure.yaml @@ -0,0 +1,10 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json + +# Name of the application. +name: foundationallm-standard-hub +hooks: + postprovision: + shell: pwsh + continueOnError: false + interactive: true + run: azd-hooks/postprovision.ps1 diff --git a/deploy/standard-hub/infra/abbreviations.json b/deploy/standard-hub/infra/abbreviations.json new file mode 100644 index 0000000000..5cd5378257 --- /dev/null +++ b/deploy/standard-hub/infra/abbreviations.json @@ -0,0 +1,137 @@ +{ + "analysisServicesServers": "as", + "apiManagementService": "apim-", + "appConfigurationConfigurationStores": "appcs-", + "appManagedEnvironments": "cae-", + "appContainerApps": "ca-", + "authorizationPolicyDefinitions": "policy-", + "automationAutomationAccounts": "aa-", + "blueprintBlueprints": "bp-", + "blueprintBlueprintsArtifacts": "bpa-", + "cacheRedis": "redis-", + "cdnProfiles": "cdnp-", + "cdnProfilesEndpoints": "cdne-", + "cognitiveServicesAccounts": "cog-", + "cognitiveServicesFormRecognizer": "cog-fr-", + "cognitiveServicesTextAnalytics": "cog-ta-", + "computeAvailabilitySets": "avail-", + "computeCloudServices": "cld-", + "computeDiskEncryptionSets": "des", + "computeDisks": "disk", + "computeDisksOs": "osdisk", + "computeGalleries": "gal", + "computeSnapshots": "snap-", + "computeVirtualMachines": "vm", + "computeVirtualMachineScaleSets": "vmss-", + "containerInstanceContainerGroups": "ci", + "containerRegistryRegistries": "cr", + "containerServiceManagedClusters": "aks-", + "databricksWorkspaces": "dbw-", + "dataFactoryFactories": "adf-", + "dataLakeAnalyticsAccounts": "dla", + "dataLakeStoreAccounts": "dls", + "dataMigrationServices": "dms-", + "dBforMySQLServers": "mysql-", + "dBforPostgreSQLServers": "psql-", + "devicesIotHubs": "iot-", + "devicesProvisioningServices": "provs-", + "devicesProvisioningServicesCertificates": "pcert-", + "documentDBDatabaseAccounts": "cosmos-", + "eventGridDomains": "evgd-", + "eventGridDomainsTopics": "evgt-", + "eventGridEventSubscriptions": "evgs-", + "eventHubNamespaces": "evhns-", + "eventHubNamespacesEventHubs": "evh-", + "hdInsightClustersHadoop": "hadoop-", + "hdInsightClustersHbase": "hbase-", + "hdInsightClustersKafka": "kafka-", + "hdInsightClustersMl": "mls-", + "hdInsightClustersSpark": "spark-", + "hdInsightClustersStorm": "storm-", + "hybridComputeMachines": "arcs-", + "insightsActionGroups": "ag-", + "insightsComponents": "appi-", + "keyVaultVaults": "kv-", + "kubernetesConnectedClusters": "arck", + "kustoClusters": "dec", + "kustoClustersDatabases": "dedb", + "logicIntegrationAccounts": "ia-", + "logicWorkflows": "logic-", + "machineLearningServicesWorkspaces": "mlw-", + "managedIdentityUserAssignedIdentities": "id-", + "managementManagementGroups": "mg-", + "migrateAssessmentProjects": "migr-", + "networkApplicationGateways": "agw-", + "networkApplicationSecurityGroups": "asg-", + "networkAzureFirewalls": "afw-", + "networkBastionHosts": "bas-", + "networkConnections": "con-", + "networkDnsResolvers": "dnsr-", + "networkDnsZones": "dnsz-", + "networkExpressRouteCircuits": "erc-", + "networkFirewallPolicies": "afwp-", + "networkFirewallPoliciesWebApplication": "waf", + "networkFirewallPoliciesRuleGroups": "wafrg", + "networkFrontDoors": "fd-", + "networkFrontdoorWebApplicationFirewallPolicies": "fdfp-", + "networkLoadBalancersExternal": "lbe-", + "networkLoadBalancersInternal": "lbi-", + "networkLoadBalancersInboundNatRules": "rule-", + "networkLocalNetworkGateways": "lgw-", + "networkNatGateways": "ng-", + "networkNetworkInterfaces": "nic-", + "networkNetworkSecurityGroups": "nsg-", + "networkNetworkSecurityGroupsSecurityRules": "nsgsr-", + "networkNetworkWatchers": "nw-", + "networkPrivateDnsZones": "pdnsz-", + "networkPrivateLinkServices": "pl-", + "networkPublicIPAddresses": "pip-", + "networkPublicIPPrefixes": "ippre-", + "networkRouteFilters": "rf-", + "networkRouteTables": "rt-", + "networkRouteTablesRoutes": "udr-", + "networkTrafficManagerProfiles": "traf-", + "networkVirtualNetworkGateways": "vgw-", + "networkVirtualNetworks": "vnet-", + "networkVirtualNetworksSubnets": "snet-", + "networkVirtualNetworksVirtualNetworkPeerings": "peer-", + "networkVirtualWans": "vwan-", + "networkVpnGateways": "vpng-", + "networkVpnGatewaysVpnConnections": "vcn-", + "networkVpnGatewaysVpnSites": "vst-", + "notificationHubsNamespaces": "ntfns-", + "notificationHubsNamespacesNotificationHubs": "ntf-", + "openAiAccounts": "openai-", + "operationalInsightsWorkspaces": "log-", + "portalDashboards": "dash-", + "powerBIDedicatedCapacities": "pbi-", + "purviewAccounts": "pview-", + "recoveryServicesVaults": "rsv-", + "resourcesResourceGroups": "rg-", + "searchSearchServices": "srch-", + "serviceBusNamespaces": "sb-", + "serviceBusNamespacesQueues": "sbq-", + "serviceBusNamespacesTopics": "sbt-", + "serviceEndPointPolicies": "se-", + "serviceFabricClusters": "sf-", + "signalRServiceSignalR": "sigr", + "sqlManagedInstances": "sqlmi-", + "sqlServers": "sql-", + "sqlServersDataWarehouse": "sqldw-", + "sqlServersDatabases": "sqldb-", + "sqlServersDatabasesStretch": "sqlstrdb-", + "storageStorageAccounts": "st", + "storageStorageAccountsVm": "stvm", + "storSimpleManagers": "ssimp", + "streamAnalyticsCluster": "asa-", + "synapseWorkspaces": "syn", + "synapseWorkspacesAnalyticsWorkspaces": "synw", + "synapseWorkspacesSqlPoolsDedicated": "syndp", + "synapseWorkspacesSqlPoolsSpark": "synsp", + "timeSeriesInsightsEnvironments": "tsi-", + "webServerFarms": "plan-", + "webSitesAppService": "app-", + "webSitesAppServiceEnvironment": "ase-", + "webSitesFunctions": "func-", + "webStaticSites": "stapp-" +} \ No newline at end of file diff --git a/deploy/standard-hub/infra/core/networking/dns.bicep b/deploy/standard-hub/infra/core/networking/dns.bicep new file mode 100644 index 0000000000..07e174ea95 --- /dev/null +++ b/deploy/standard-hub/infra/core/networking/dns.bicep @@ -0,0 +1,30 @@ +param key string +param tags object +param vnetId string +param zone string + +// Resources +resource main 'Microsoft.Network/privateDnsZones@2018-09-01' = { + location: 'global' + name: zone + tags: tags +} + +resource link 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { + parent: main + name: zone + location: 'global' + tags: tags + + properties: { + registrationEnabled: false + virtualNetwork: { + id: vnetId + } + } +} + +// Outputs +output id string = main.id +output key string = key +output name string = main.name diff --git a/deploy/standard-hub/infra/core/networking/dnsResolver.bicep b/deploy/standard-hub/infra/core/networking/dnsResolver.bicep new file mode 100644 index 0000000000..0b31496a43 --- /dev/null +++ b/deploy/standard-hub/infra/core/networking/dnsResolver.bicep @@ -0,0 +1,43 @@ + +param abbrs object +param environmentName string +param location string +param project string +param vnetName string + +// Locals +var resolverName = namer(abbrs.networkDnsResolvers, environmentName, location, 'net', project) + +// Functions +func namer(resourceAbbr string, env string, region string, workloadName string, projectId string) string => + '${resourceAbbr}${env}-${region}-${workloadName}-${projectId}' + +// Resources +resource resolver 'Microsoft.Network/dnsResolvers@2022-07-01' = { + name: resolverName + location: location + properties: { + virtualNetwork: { + id: resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks', vnetName) + } + } +} + +resource inboundEndpoint 'Microsoft.Network/dnsResolvers/inboundEndpoints@2022-07-01' = { + parent: resolver + name: resolverName + location: location + properties: { + ipConfigurations: [ + { + privateIpAllocationMethod: 'Dynamic' + subnet: { + id: resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', vnetName, 'DNS') + } + } + ] + } +} + +// Outputs +output dnsResolverEndpointIp string = inboundEndpoint.properties.ipConfigurations[0].privateIpAddress diff --git a/deploy/standard-hub/infra/core/networking/vnet.bicep b/deploy/standard-hub/infra/core/networking/vnet.bicep new file mode 100644 index 0000000000..91bf698168 --- /dev/null +++ b/deploy/standard-hub/infra/core/networking/vnet.bicep @@ -0,0 +1,66 @@ +param abbrs object +param cidrVnet string +param environmentName string +param location string +param project string +param tags object + +// Locals +var cidrDns = cidrSubnet(cidrVnet, 27, 1) // 192.168.100.32/27 +var cidrVpnGateway = cidrSubnet(cidrVnet, 27, 0) // 192.168.100.0/27 +var vnetName = namer(abbrs.networkVirtualNetworks, environmentName, location, 'net', project) + +var subnets = [ + { + name: 'GatewaySubnet' + addressPrefix: cidrVpnGateway + } + { + name: 'DNS' + addressPrefix: cidrDns + delegations: [ + { + name: 'Microsoft.Network/dnsResolvers' + properties: { + serviceName: 'Microsoft.Network/dnsResolvers' + } + } + ] + } +] + +// Functions +func namer(resourceAbbr string, env string, region string, workloadName string, projectId string) string => + '${resourceAbbr}${env}-${region}-${workloadName}-${projectId}' + + +// Resources +resource main 'Microsoft.Network/virtualNetworks@2023-05-01' = { + name: vnetName + location: location + + tags: tags + + properties: { + enableDdosProtection: false + addressSpace: { + addressPrefixes: [cidrVnet] + } + subnets: [ + for (subnet, i) in subnets: { + name: subnet.name + properties: { + addressPrefix: subnet.addressPrefix + delegations: subnet.?delegations + privateEndpointNetworkPolicies: 'Enabled' + privateLinkServiceNetworkPolicies: 'Enabled' + serviceEndpoints: subnet.?serviceEndpoints + } + } + ] + } +} + +// Outputs +output vnetId string = main.id +output vnetName string = main.name diff --git a/deploy/standard-hub/infra/core/networking/vpnGateway.bicep b/deploy/standard-hub/infra/core/networking/vpnGateway.bicep new file mode 100644 index 0000000000..758469ad2a --- /dev/null +++ b/deploy/standard-hub/infra/core/networking/vpnGateway.bicep @@ -0,0 +1,93 @@ +/** Inputs **/ +param abbrs object +param environmentName string +param location string +param project string +param subnetId string +param tags object +param vpnClientAddressPool string = '192.168.101.0/28' + +@allowed([ + 'VpnGw1' + 'VpnGw2AZ' +]) +param sku string = 'VpnGw1' + +@allowed([ + 'RouteBased' + 'PolicyBased' +]) +param vpnType string = 'RouteBased' + + +// Locals +var audience = audienceMap[cloud] +var cloud = environment().name +var issuer = 'https://sts.windows.net/${tenantId}/' +var name = namer(abbrs.networkVpnGateways, environmentName, location, 'net', project) +var pipName = namer(abbrs.networkPublicIPAddresses, environmentName, location, 'net', project) +var tenant = uri(environment().authentication.loginEndpoint, tenantId) +var tenantId = subscription().tenantId + +var audienceMap = { AzureCloud: '41b23e61-6c1e-4545-b367-cd054e0ed4b4' } + +// Function +func namer(resourceAbbr string, env string, region string, workloadName string, projectId string) string => + '${resourceAbbr}${env}-${region}-${workloadName}-${projectId}' + +// Resources +resource vpnGateway 'Microsoft.Network/virtualNetworkGateways@2021-02-01' = { + name: name + location: location + tags : tags + properties: { + ipConfigurations: [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: subnetId + } + publicIPAddress: { + id: publicIp.id + } + } + name: 'vnetGatewayConfig' + } + ] + sku: { + name: sku + tier: sku + } + gatewayType: 'Vpn' + vpnType: vpnType + vpnClientConfiguration: { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPool + ] + } + vpnClientProtocols: [ + 'OpenVPN' + ] + vpnAuthenticationTypes: [ + 'AAD' + ] + aadTenant: tenant + aadAudience: audience + aadIssuer: issuer + } + } +} + +resource publicIp 'Microsoft.Network/publicIPAddresses@2021-02-01' = { + name: pipName + location: location + sku: { + name: 'Standard' + } + tags: tags + properties: { + publicIPAllocationMethod: 'Static' + } +} diff --git a/deploy/standard-hub/infra/main.bicep b/deploy/standard-hub/infra/main.bicep new file mode 100644 index 0000000000..c211d44b9f --- /dev/null +++ b/deploy/standard-hub/infra/main.bicep @@ -0,0 +1,111 @@ +targetScope = 'subscription' + +param cidrVnet string = '192.168.100.0/24' +param createDate string = utcNow('u') +param createVpnGateway bool = true +param environmentName string +param location string +param project string +param timestamp string = utcNow() + +// Locals +var abbrs = loadJsonContent('./abbreviations.json') +var resourceGroup = namer(abbrs.resourcesResourceGroups, environmentName, location, 'net', project) + +var privateDnsZones = { + agentsvc: 'privatelink.agentsvc.azure-automation.net' + aks: 'privatelink.${location}.azmk8s.io' + blob: 'privatelink.blob.${environment().suffixes.storage}' + cognitiveservices: 'privatelink.cognitiveservices.azure.com' + configuration_stores: 'privatelink.azconfig.io' + cosmosdb: 'privatelink.documents.azure.com' + cr_region: '${location}.privatelink.azurecr.io' + cr: 'privatelink.azurecr.io' + dfs: 'privatelink.dfs.${environment().suffixes.storage}' + eventgrid: 'privatelink.eventgrid.azure.net' + file: 'privatelink.file.${environment().suffixes.storage}' + monitor: 'privatelink.monitor.azure.com' + ods: 'privatelink.ods.opinsights.azure.com' + oms: 'privatelink.oms.opinsights.azure.com' + openai: 'privatelink.openai.azure.com' + queue: 'privatelink.queue.${environment().suffixes.storage}' + search: 'privatelink.search.windows.net' + sites: 'privatelink.azurewebsites.net' + sql_server: 'privatelink${environment().suffixes.sqlServerHostname}' + table: 'privatelink.table.${environment().suffixes.storage}' + vault: 'privatelink.vaultcore.azure.net' +} + +var tags = { + 'azd-env-name': environmentName + 'create-date': createDate + 'iac-type': 'bicep' + 'project-name': project +} + +// Functions +func namer(resourceAbbr string, env string, region string, workloadName string, projectId string) string => + '${resourceAbbr}${env}-${region}-${workloadName}-${projectId}' + +// Resources +resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroup + location: location + tags: tags +} + +/** Nested Modules **/ +module vnet './core/networking/vnet.bicep' = { + name: 'vnet-${timestamp}' + params: { + abbrs: abbrs + cidrVnet: cidrVnet + environmentName:environmentName + location: location + project: project + tags: tags + } + scope: rg +} + +module dns './core/networking/dns.bicep' = [for zone in items(privateDnsZones): { + dependsOn: [vnet] + name: '${zone.value}-${timestamp}' + params: { + key: zone.key + vnetId: vnet.outputs.vnetId + zone: zone.value + tags: tags + } + scope: rg +}] + +module dnsResolver './core/networking/dnsResolver.bicep' = { + dependsOn: [vnet] + name: 'dnsResolver-${timestamp}' + params: { + abbrs: abbrs + environmentName: environmentName + location: location + project: project + vnetName: vnet.outputs.vnetName + } + scope: rg +} + +module vpn './core/networking/vpnGateway.bicep' = if (createVpnGateway) { + dependsOn: [vnet] + name: 'vpnGw-${timestamp}' + params: { + abbrs: abbrs + environmentName: environmentName + location: location + project: project + subnetId: '${vnet.outputs.vnetId}/subnets/GatewaySubnet' + tags: tags + } + scope: rg +} + +output DNS_RESOLVER_ENDPOINT_IP string = dnsResolver.outputs.dnsResolverEndpointIp +output FLLM_PROJECT string = project diff --git a/deploy/standard-hub/infra/main.parameters.json b/deploy/standard-hub/infra/main.parameters.json new file mode 100644 index 0000000000..f1600cfbcf --- /dev/null +++ b/deploy/standard-hub/infra/main.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "environmentName": { + "value": "${AZURE_ENV_NAME}" + }, + "location": { + "value": "${AZURE_LOCATION}" + } + } +} From 0a758b60beef61e703b853b883c3a65d4e7a9824 Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Thu, 25 Jul 2024 17:09:11 -0400 Subject: [PATCH 02/10] fixed based on feedback to PR --- .../standard-hub/azd-hooks/postprovision.ps1 | 157 +++++++++--------- .../azd-hooks/utility/Get-AbsolutePath.ps1 | 18 ++ .../utility/Load-Utility-Functions.ps1 | 9 + .../infra/core/networking/vpnGateway.bicep | 2 + deploy/standard-hub/infra/main.bicep | 6 +- 5 files changed, 108 insertions(+), 84 deletions(-) create mode 100644 deploy/standard-hub/azd-hooks/utility/Get-AbsolutePath.ps1 create mode 100644 deploy/standard-hub/azd-hooks/utility/Load-Utility-Functions.ps1 diff --git a/deploy/standard-hub/azd-hooks/postprovision.ps1 b/deploy/standard-hub/azd-hooks/postprovision.ps1 index 273dcb995d..49b755bffd 100644 --- a/deploy/standard-hub/azd-hooks/postprovision.ps1 +++ b/deploy/standard-hub/azd-hooks/postprovision.ps1 @@ -1,82 +1,75 @@ -#!/usr/bin/env pwsh - -Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable) -Set-StrictMode -Version 3.0 -$ErrorActionPreference = "Stop" - -# Variables - Replace these with your actual values - -$dnsServerIp = "${env:DNS_RESOLVER_ENDPOINT_IP}" -$outputFolderPath = "../standard-hub/config/vpn" -$outputFilePath = "$outputFolderPath/VpnClientConfiguration.zip" -$resourceGroupName = "rg-${env:AZURE_ENV_NAME}-${env:AZURE_LOCATION}-net-${env:FLLM_PROJECT}" -$vpnGatewayName = "vpng-${env:AZURE_ENV_NAME}-${env:AZURE_LOCATION}-net-${env:FLLM_PROJECT}" -$xmlFilePath = "$outputFolderPath/AzureVPN/azurevpnconfig.xml" # Assuming the XML file is inside the extracted folder - -# Add the dns-resolver extension to the cli -az extension add --name dns-resolver --allow-preview true --yes --only-show-errors - -# Get the VPN client configuration package URL -$vpnClientPackageUrl = az network vnet-gateway vpn-client generate ` - --resource-group $resourceGroupName ` - --name $vpnGatewayName - -# Remove quotes from the URL -$vpnClientPackageUrl = $vpnClientPackageUrl -replace '"', '' - -# Download the package -Invoke-WebRequest -Uri $vpnClientPackageUrl -OutFile $outputFilePath - -# Expand the ZIP file -Expand-Archive -Path $outputFilePath -DestinationPath $outputFolderPath -Force - -# Assuming the XML file is directly inside the expanded folder -$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName -$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml" - -# Assuming the XML file is directly inside the expanded folder -$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName -$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml" - -# Read the XML file -$xmlContent = Get-Content -Path $xmlFilePath -$azureVpnClientConfig = [xml]$xmlContent - -# Create a namespace manager -$namespaceManager = New-Object System.Xml.XmlNamespaceManager($azureVpnClientConfig.NameTable) -$namespaceManager.AddNamespace("ns", "http://schemas.datacontract.org/2004/07/") -$namespaceManager.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance") - -# Remove node if it exists -$nilClientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig[@i:nil='true']", $namespaceManager) -if ($nilClientConfigNode -ne $null) { - $nilClientConfigNode.ParentNode.RemoveChild($nilClientConfigNode) | Out-Null -} - -# Create DNS servers XML nodes -$dnsServersNode = $azureVpnClientConfig.CreateElement("dnsservers", "http://schemas.datacontract.org/2004/07/") -$dnsServer1 = $azureVpnClientConfig.CreateElement("dnsserver", "http://schemas.datacontract.org/2004/07/") -$dnsServer1.InnerText = $dnsServerIp -$dnsServersNode.AppendChild($dnsServer1) | Out-Null - -# Locate the clientconfig node or create it if it doesn't exist -$clientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig", $namespaceManager) -if ($clientConfigNode -eq $null) { - $clientConfigNode = $azureVpnClientConfig.CreateElement("clientconfig", "http://schemas.datacontract.org/2004/07/") - $azureVpnClientConfig.DocumentElement.AppendChild($clientConfigNode) | Out-Null -} - -# Append DNS servers to clientconfig -$clientConfigNode.AppendChild($dnsServersNode) | Out-Null - -# Save the updated XML file -$azureVpnClientConfig.Save($xmlFilePath) - -Write-Host -ForegroundColor Yellow ` -"Please Install the Azure VPN client via https://aka.ms/azvpnclientdownload, -then import the VPN client configuration package downloaded to -foundationallm/deploy/standard-hub/config/vpn/AzureVPN/azurevpnconfig.xml -Make sure to connect to the VPN prior to running the next step of the -FLLM Install for Standard." - - +#!/usr/bin/env pwsh + +Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable) +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + +# Load utility functions +Push-Location $($MyInvocation.InvocationName | Split-Path) +try { + . ./utility/Load-Utility-Functions.ps1 +} +finally { + Pop-Location +} + +$dnsServerIp = "${env:DNS_RESOLVER_ENDPOINT_IP}" +$outputFolderPath = "../standard-hub/config/vpn" | Get-AbsolutePath +$outputFilePath = Join-Path $outputFolderPath "VpnClientConfiguration.zip" +$resourceGroupName = "${env:RESOURCE_GROUP_NAME}" +$vpnGatewayName = "${env:VPN_GATEWAY_NAME}" +$xmlFilePath = Join-Path $outputFolderPath "AzureVPN" "azurevpnconfig.xml" # Assuming the XML file is inside the extracted folder + +# Add the dns-resolver extension to the cli +az extension add --name dns-resolver --allow-preview true --yes --only-show-errors + +# Get the VPN client configuration package URL +$vpnClientPackageUrl = az network vnet-gateway vpn-client generate ` + --name $vpnGatewayName ` + --resource-group $resourceGroupName ` + --output tsv + +# Download the package and extract +Invoke-WebRequest -Uri $vpnClientPackageUrl -OutFile $outputFilePath +Expand-Archive -Path $outputFilePath -DestinationPath $outputFolderPath -Force + +# Assuming the XML file is directly inside the expanded folder & Read the XML file +$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName +$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml" +$xmlContent = Get-Content -Path $xmlFilePath +$azureVpnClientConfig = [xml]$xmlContent + +# Create a namespace manager +$namespaceManager = New-Object System.Xml.XmlNamespaceManager($azureVpnClientConfig.NameTable) +$namespaceManager.AddNamespace("ns", "http://schemas.datacontract.org/2004/07/") +$namespaceManager.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance") + +# Remove node if it exists +$nilClientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig[@i:nil='true']", $namespaceManager) +if ($nilClientConfigNode -ne $null) { + $nilClientConfigNode.ParentNode.RemoveChild($nilClientConfigNode) | Out-Null +} + +# Create DNS servers XML nodes +$dnsServersNode = $azureVpnClientConfig.CreateElement("dnsservers", "http://schemas.datacontract.org/2004/07/") +$dnsServer1 = $azureVpnClientConfig.CreateElement("dnsserver", "http://schemas.datacontract.org/2004/07/") +$dnsServer1.InnerText = $dnsServerIp +$dnsServersNode.AppendChild($dnsServer1) | Out-Null + +# Locate the clientconfig node or create it if it doesn't exist +$clientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig", $namespaceManager) +if ($clientConfigNode -eq $null) { + $clientConfigNode = $azureVpnClientConfig.CreateElement("clientconfig", "http://schemas.datacontract.org/2004/07/") + $azureVpnClientConfig.DocumentElement.AppendChild($clientConfigNode) | Out-Null +} + +# Append DNS servers to clientconfig +$clientConfigNode.AppendChild($dnsServersNode) | Out-Null + +# Save the updated XML file +$azureVpnClientConfig.Save($xmlFilePath) + +Write-Host -ForegroundColor Yellow ` +"Please Install the Azure VPN client via https://aka.ms/azvpnclientdownload, and +then import the VPN client configuration package downloaded to $xmlFilePath. Make sure to connect +to the VPN prior to running the next step of the FLLM Install for Standard." diff --git a/deploy/standard-hub/azd-hooks/utility/Get-AbsolutePath.ps1 b/deploy/standard-hub/azd-hooks/utility/Get-AbsolutePath.ps1 new file mode 100644 index 0000000000..e61235395a --- /dev/null +++ b/deploy/standard-hub/azd-hooks/utility/Get-AbsolutePath.ps1 @@ -0,0 +1,18 @@ +#! /usr/bin/pwsh + +Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable) +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + +function Get-AbsolutePath { + <# + .SYNOPSIS + Get the absolute path of a file or directory. Relative path does not need to exist. + #> + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] + [string]$RelatviePath + ) + + return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelatviePath) +} diff --git a/deploy/standard-hub/azd-hooks/utility/Load-Utility-Functions.ps1 b/deploy/standard-hub/azd-hooks/utility/Load-Utility-Functions.ps1 new file mode 100644 index 0000000000..3055491025 --- /dev/null +++ b/deploy/standard-hub/azd-hooks/utility/Load-Utility-Functions.ps1 @@ -0,0 +1,9 @@ +#!/usr/bin/env pwsh + +Push-Location $($MyInvocation.InvocationName | Split-Path) +try { + . ./utility/Get-AbsolutePath.ps1 +} +finally { + Pop-Location +} diff --git a/deploy/standard-hub/infra/core/networking/vpnGateway.bicep b/deploy/standard-hub/infra/core/networking/vpnGateway.bicep index 758469ad2a..c0c1a53365 100644 --- a/deploy/standard-hub/infra/core/networking/vpnGateway.bicep +++ b/deploy/standard-hub/infra/core/networking/vpnGateway.bicep @@ -91,3 +91,5 @@ resource publicIp 'Microsoft.Network/publicIPAddresses@2021-02-01' = { publicIPAllocationMethod: 'Static' } } + +output vpnGatewayName string = vpnGateway.name diff --git a/deploy/standard-hub/infra/main.bicep b/deploy/standard-hub/infra/main.bicep index c211d44b9f..767bc9185c 100644 --- a/deploy/standard-hub/infra/main.bicep +++ b/deploy/standard-hub/infra/main.bicep @@ -2,7 +2,6 @@ targetScope = 'subscription' param cidrVnet string = '192.168.100.0/24' param createDate string = utcNow('u') -param createVpnGateway bool = true param environmentName string param location string param project string @@ -93,7 +92,7 @@ module dnsResolver './core/networking/dnsResolver.bicep' = { scope: rg } -module vpn './core/networking/vpnGateway.bicep' = if (createVpnGateway) { +module vpn './core/networking/vpnGateway.bicep' = { dependsOn: [vnet] name: 'vpnGw-${timestamp}' params: { @@ -109,3 +108,6 @@ module vpn './core/networking/vpnGateway.bicep' = if (createVpnGateway) { output DNS_RESOLVER_ENDPOINT_IP string = dnsResolver.outputs.dnsResolverEndpointIp output FLLM_PROJECT string = project +output RESOURCE_GROUP_NAME string = rg.name +output VPN_GATEWAY_NAME string = vpn.outputs.vpnGatewayName + From 0fb17cb7fdf041141bc4b650b31ee10c127a5cfb Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Thu, 25 Jul 2024 18:12:24 -0400 Subject: [PATCH 03/10] Update FLLM App Reg script; add admin group script with add current user --- .../common/scripts/Create-FllmAdminGroup.ps1 | 55 +++++++++++ .../common/scripts/Create-FllmEntraIdApps.ps1 | 95 ++++++++++--------- .../scripts/foundationalllm-client.json | 40 -------- .../scripts/foundationalllm-management.json | 56 ----------- .../foundationalllm-managementclient.json | 33 ------- .../foundationalllm-vectorization.json | 56 ----------- deploy/common/scripts/foundationalllm.json | 56 ----------- ... => foundationallm-authorization-api.json} | 0 .../scripts/foundationallm-core-api.json | 71 ++++++++++++++ .../scripts/foundationallm-core-portal.json | 51 ++++++++++ .../foundationallm-management-api.json | 71 ++++++++++++++ .../foundationallm-management-portal.json | 54 +++++++++++ 12 files changed, 354 insertions(+), 284 deletions(-) create mode 100644 deploy/common/scripts/Create-FllmAdminGroup.ps1 delete mode 100644 deploy/common/scripts/foundationalllm-client.json delete mode 100644 deploy/common/scripts/foundationalllm-management.json delete mode 100644 deploy/common/scripts/foundationalllm-managementclient.json delete mode 100644 deploy/common/scripts/foundationalllm-vectorization.json delete mode 100644 deploy/common/scripts/foundationalllm.json rename deploy/common/scripts/{foundationalllm-authorization.json => foundationallm-authorization-api.json} (100%) create mode 100644 deploy/common/scripts/foundationallm-core-api.json create mode 100644 deploy/common/scripts/foundationallm-core-portal.json create mode 100644 deploy/common/scripts/foundationallm-management-api.json create mode 100644 deploy/common/scripts/foundationallm-management-portal.json diff --git a/deploy/common/scripts/Create-FllmAdminGroup.ps1 b/deploy/common/scripts/Create-FllmAdminGroup.ps1 new file mode 100644 index 0000000000..9798835d21 --- /dev/null +++ b/deploy/common/scripts/Create-FllmAdminGroup.ps1 @@ -0,0 +1,55 @@ +<# +.SYNOPSIS + Creates an Entra ID group using the Azure CLI and adds the current user to the group. + +.DESCRIPTION + This script creates a new Entra ID group named 'FLLM-Admins' using the Azure CLI command. + The user running the script is added to the group after its creation. + It checks for errors during execution and outputs the status of group creation. + +.PARAMETER groupName + Specifies the name of the Entra ID group to be created. + +.EXAMPLE + ./Create-FllmAdminGroup.ps1 -groupName "FLLM-Admins" + This example runs the script to create an Entra ID group named 'FLLM-Admins'. +#> + +Param( + [parameter(Mandatory = $false)][string]$groupName = "FLLM-Admins" +) + +# Try block to handle potential errors during the execution +try { + # Check if the group already exists + Write-Host -ForegroundColor Yellow "Checking if the Entra ID group '$groupName' already exists..." + az ad group show --group $groupName + + if ($LASTEXITCODE -eq 0) { + Write-Host -ForegroundColor Red "The Entra ID group '$groupName' already exists. Script execution stopped." + exit + } + + # Command to create the Entra ID group using Azure CLI + Write-Host -ForegroundColor Yellow "Creating Entra ID group '$groupName'..." + az ad group create --display-name $groupName --mail-nickname $groupName + + if ($LASTEXITCODE -ne 0) { + throw "Failed to create group ${message} (code: ${LASTEXITCODE})" + } + + Write-Host -ForegroundColor Yellow "Waiting for group creation to complete..." + Start-Sleep 10 + + # Get the ID of the of the user running the script & add the user to the group + $currentUserId = (az ad signed-in-user show --query id -o tsv).Trim() + Write-Host -ForegroundColor Yellow "Adding current user to the group..." + az ad group member add --group $groupName --member-id $currentUserId + + # If the command executes successfully, output the result + Write-Host -ForegroundColor Yellow "Entra ID group '$groupName' created successfully, and added current user with ID $currentUserId to the group." +} +catch { + # Catch block to handle and report any errors that occur during the execution + Write-Host -ForegroundColor Red "Failed to create Entra ID group. Error: $($_.Exception.Message)" +} diff --git a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 index a3ac731602..70ef9d3f73 100644 --- a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 +++ b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 @@ -1,30 +1,29 @@ #! /usr/bin/pwsh - -Param( - [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", - [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", - [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", - [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", - [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" -) - -Set-StrictMode -Version 3.0 -$ErrorActionPreference = "Stop" - <# .SYNOPSIS - Generates a set of FLLM EntraID API apps and their respective client apps in the Azure AD tenant. - + Generates a set of FLLM EntraID App Registrations and their respective client apps in the Entra ID tenant. + See the following link for more information: https://docs.foundationallm.ai/deployment/authentication-authorization/index.html + **These app names are mandatory, you can't change the names or the scopes.** + .DESCRIPTION The script will create the following apps: - - FoundationaLLM - - FoundationaLLM-Client - - FoundationaLLM-Management - - FoundationaLLM-ManagementClient - - FoundationaLLM-Authorization - - + - FoundationaLLM-Authorization-API + - FoundationaLLM-Core-API + - FoundationaLLM-Core-Portal + - FoundationaLLM-Management-API + - FoundationaLLM-Management-Portal + The script will also assign the required permissions to the client apps and the required API permissions to the API apps. - URLs for the client apps are optional and can be set using the appUrl and appUrlLocal parameters. + +.REQUIREMENTS + - The user must be a Global Administrator in the Entra ID tenant or have RBAC rights to create App Registrations and Service Principals. + - The Azure CLI must be installed and authenticated to the Entra ID tenant. + - Scaffolding JSON files must be present in the same directory as the script. + - foundationallm-core-api.json + - foundationallm-core-portal.json + - foundationallm-management.json + - foundationallm-managementclient.json + - foundationalllm-authorization.json .PARAMETER appPermissionsId The GUID of the permission to assign to the client app. @@ -35,25 +34,35 @@ The URL of the client app. .PARAMETER appUrlLocal The local URL of the client app. -.PARAMETER createClientApp -Whether to create the client app or not. Default is true. False will only create the API app. - .EXAMPLE The following example creates the FoundationaLLM API and client apps. # Create FoundationaLLM Core App Registrations $params = @{ - fllmApi = "FoundationaLLM" - fllmClient = "FoundationaLLM-Client" - fllmApiConfigPath = "foundationalllm.json" - fllmClientConfigPath = "foundationalllm-client.json" + fllmApi = $coreAppName + fllmClient = $coreClientAppName + fllmApiConfigPath = "foundationallm-core-api.json" + fllmApiUri = "api://FoundationaLLM-Core" + fllmClientConfigPath = "foundationallm-core-portal.json" appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" appUrl = "" appUrlLocal = "http://localhost:3000/signin-oidc" } -New-FllmEntraIdApps @params +$($fllmAppRegs).Core = New-FllmEntraIdApps @params #> + +Param( + [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", + [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", + [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", + [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", + [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" +) + +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + function New-FllmEntraIdApps { param ( [Parameter(Mandatory = $true)][string]$appPermissionsId, @@ -69,12 +78,12 @@ function New-FllmEntraIdApps { $fllmAppRegMetaData = @{} try { - # Create the FLLM APIApp Registration + # Create the FLLM API App Registration $($fllmAppRegMetaData).Api = @{ Name = $fllmApi Uri = $fllmApiUri } - Write-Host "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" + Write-Host -For "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" $($fllmAppRegMetaData.Api).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Api.Name) --query appId --output tsv) $($fllmAppRegMetaData.Api).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Api.AppId) --query id --output tsv) az ad sp create --id $($fllmAppRegMetaData.Api.AppId) @@ -88,8 +97,8 @@ function New-FllmEntraIdApps { az ad sp create --id $($fllmAppRegMetaData.Client.AppId) } - # Update the APIApp Registration - Write-Host "Lays down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" + # Update the API App Registration + Write-Host "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$fllmApiConfigPath" Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." Start-Sleep -Seconds 10 @@ -115,21 +124,21 @@ function New-FllmEntraIdApps { Set-Content -Path "$($fllmAppRegMetaData.Api.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Api.Name)`.json" - # Update the ClientApp Registration + # Update the Client App Registration if ($createClientApp) { - Write-Host "Lay down scaffolding for the ClientApp Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$fllmClientConfigPath" Start-Sleep -Seconds 10 Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." - ## Updates the ClientApp Registration - Write-Host "Preparing updates for the API App Registration $($fllmAppRegMetaData.Client.Name)" + ## Updates the Client App Registration + Write-Host "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" $($fllmAppRegMetaData.Client).Uri = @("api://$($fllmAppRegMetaData.Client.Name)") $apiPermissions = @(@{"resourceAppId" = $($fllmAppRegMetaData.Client.AppId); "resourceAccess" = @(@{"id" = "$($appPermissionsId)"; "type" = "Scope" }) }, @{"resourceAppId" = "00000003-0000-0000-c000-000000000000"; "resourceAccess" = @(@{"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; "type" = "Scope" }) }) $appConfig = Get-content $fllmClientConfigPath | ConvertFrom-Json -Depth 20 $appConfig.identifierUris = @($($fllmAppRegMetaData.Client.Uri)) $appConfig.requiredResourceAccess = $apiPermissions $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host "Final Update to ClientApp Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" Set-Content -Path "$($fllmAppRegMetaData.Client.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Client.Name)`.json" } @@ -146,9 +155,9 @@ $fllmAppRegs = @{} $params = @{ fllmApi = $coreAppName fllmClient = $coreClientAppName - fllmApiConfigPath = "foundationalllm.json" + fllmApiConfigPath = "foundationallm-core-api.json" fllmApiUri = "api://FoundationaLLM-Core" - fllmClientConfigPath = "foundationalllm-client.json" + fllmClientConfigPath = "foundationallm-core-portal.json" appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" appUrl = "" appUrlLocal = "http://localhost:3000/signin-oidc" @@ -159,9 +168,9 @@ $($fllmAppRegs).Core = New-FllmEntraIdApps @params $params = @{ fllmApi = $mgmtAppName fllmClient = $mgmtClientAppName - fllmApiConfigPath = "foundationalllm-management.json" + fllmApiConfigPath = "foundationallm-management-api.json" fllmApiUri = "api://FoundationaLLM-Management" - fllmClientConfigPath = "foundationalllm-managementclient.json" + fllmClientConfigPath = "foundationallm-management-portal.json" appPermissionsId = "c57f4633-0e58-455a-8ede-5de815fe6c9c" appUrl = "" appUrlLocal = "http://localhost:3001/signin-oidc" @@ -171,7 +180,7 @@ $($fllmAppRegs).Management = New-FllmEntraIdApps @params # Create FoundationaLLM Authorization App Registration $params = @{ fllmApi = $authAppName - fllmApiConfigPath = "foundationalllm-authorization.json" + fllmApiConfigPath = "foundationalllm-authorization-api.json" fllmApiUri = "api://FoundationaLLM-Authorization" appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" createClientApp = $false diff --git a/deploy/common/scripts/foundationalllm-client.json b/deploy/common/scripts/foundationalllm-client.json deleted file mode 100644 index 2e0cc40c38..0000000000 --- a/deploy/common/scripts/foundationalllm-client.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - } - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-management.json b/deploy/common/scripts/foundationalllm-management.json deleted file mode 100644 index c2ed413f98..0000000000 --- a/deploy/common/scripts/foundationalllm-management.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage data on behalf of users", - "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Data.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-managementclient.json b/deploy/common/scripts/foundationalllm-managementclient.json deleted file mode 100644 index 456d0b7157..0000000000 --- a/deploy/common/scripts/foundationalllm-managementclient.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-vectorization.json b/deploy/common/scripts/foundationalllm-vectorization.json deleted file mode 100644 index 37ee660002..0000000000 --- a/deploy/common/scripts/foundationalllm-vectorization.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage data on behalf of users", - "id": "b2061dc7-ac14-4ce2-9dcc-7f1ac0d8a238", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Data.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm.json b/deploy/common/scripts/foundationalllm.json deleted file mode 100644 index abc8f1bcfa..0000000000 --- a/deploy/common/scripts/foundationalllm.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "adminConsentDisplayName": "Read data on behalf of users", - "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "userConsentDisplayName": "Read data on behalf of users", - "value": "Data.Read" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-authorization.json b/deploy/common/scripts/foundationallm-authorization-api.json similarity index 100% rename from deploy/common/scripts/foundationalllm-authorization.json rename to deploy/common/scripts/foundationallm-authorization-api.json diff --git a/deploy/common/scripts/foundationallm-core-api.json b/deploy/common/scripts/foundationallm-core-api.json new file mode 100644 index 0000000000..94de45cb69 --- /dev/null +++ b/deploy/common/scripts/foundationallm-core-api.json @@ -0,0 +1,71 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "adminConsentDisplayName": "Read data on behalf of users", + "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", + "isEnabled": true, + "type": "User", + "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "userConsentDisplayName": "Read data on behalf of users", + "value": "Data.Read" + } + ], + "preAuthorizedApplications": [ + { + "delegatedPermissionIds": [ + "6da07102-bb6a-421d-a71e-dfdb6031d3d8" + ], + "appId": "1e811dbe-6476-40e1-9aaa-36f159eba424" + }, + { + "delegatedPermissionIds": [ + "6da07102-bb6a-421d-a71e-dfdb6031d3d8" + ], + "appId": "04b07795-8ddb-461a-bbee-02f9e1bf7b46" + } + ], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [ + "api://FoundationaLLM-Core" + ], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} diff --git a/deploy/common/scripts/foundationallm-core-portal.json b/deploy/common/scripts/foundationallm-core-portal.json new file mode 100644 index 0000000000..609b361528 --- /dev/null +++ b/deploy/common/scripts/foundationallm-core-portal.json @@ -0,0 +1,51 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [ + "api://FoundationaLLM-Core-Portal" + ], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "requiredResourceAccess": [ + { + "resourceAppId": "1e811dbe-6476-40e1-9aaa-36f159eba424", + "resourceAccess": [ + { + "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", + "type": "Scope" + } + ] + }, + { + "resourceAppId": "00000003-0000-0000-c000-000000000000", + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ] + } + ], + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + } + } +} diff --git a/deploy/common/scripts/foundationallm-management-api.json b/deploy/common/scripts/foundationallm-management-api.json new file mode 100644 index 0000000000..5eb13e2114 --- /dev/null +++ b/deploy/common/scripts/foundationallm-management-api.json @@ -0,0 +1,71 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage data on behalf of users", + "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Data.Manage" + } + ], + "preAuthorizedApplications": [ + { + "delegatedPermissionIds": [ + "c57f4633-0e58-455a-8ede-5de815fe6c9c" + ], + "appId": "e4c395f1-cc9a-43bc-95e1-fda09bc94476" + }, + { + "delegatedPermissionIds": [ + "c57f4633-0e58-455a-8ede-5de815fe6c9c" + ], + "appId": "04b07795-8ddb-461a-bbee-02f9e1bf7b46" + } + ], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [ + "api://FoundationaLLM-Management" + ], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} diff --git a/deploy/common/scripts/foundationallm-management-portal.json b/deploy/common/scripts/foundationallm-management-portal.json new file mode 100644 index 0000000000..75f1a21d40 --- /dev/null +++ b/deploy/common/scripts/foundationallm-management-portal.json @@ -0,0 +1,54 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [ + "api://FoundationaLLM-Management-Portal" + ], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAppId": "e4c395f1-cc9a-43bc-95e1-fda09bc94476", + "resourceAccess": [ + { + "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", + "type": "Scope" + } + ] + }, + { + "resourceAppId": "00000003-0000-0000-c000-000000000000", + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ] + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} From 3bd78d3f3413cc791306bc4b55c9baf5f6e4fee8 Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:13:56 -0400 Subject: [PATCH 04/10] Update to Entra App Reg scripts to add template files --- deploy/common/scripts/.gitignore | 6 ++ .../common/scripts/Create-FllmEntraIdApps.ps1 | 85 ++++++++++++------- .../foundationallm-authorization-api.json | 56 ------------ ...ationallm-authorization-api.template.json} | 30 ++++--- ... => foundationallm-core-api.template.json} | 19 +---- ... foundationallm-core-portal.template.json} | 17 +--- ...undationallm-management-api.template.json} | 19 +---- ...dationallm-management-portal.template.json | 33 +++++++ 8 files changed, 114 insertions(+), 151 deletions(-) create mode 100644 deploy/common/scripts/.gitignore delete mode 100644 deploy/common/scripts/foundationallm-authorization-api.json rename deploy/common/scripts/{foundationallm-management-portal.json => foundationallm-authorization-api.template.json} (55%) rename deploy/common/scripts/{foundationallm-core-api.json => foundationallm-core-api.template.json} (76%) rename deploy/common/scripts/{foundationallm-core-portal.json => foundationallm-core-portal.template.json} (68%) rename deploy/common/scripts/{foundationallm-management-api.json => foundationallm-management-api.template.json} (76%) create mode 100644 deploy/common/scripts/foundationallm-management-portal.template.json diff --git a/deploy/common/scripts/.gitignore b/deploy/common/scripts/.gitignore new file mode 100644 index 0000000000..82f9485640 --- /dev/null +++ b/deploy/common/scripts/.gitignore @@ -0,0 +1,6 @@ +# Don't commit the generated Entra ID API files +FoundationaLLM-Authorization-API.json +FoundationaLLM-Core-API.json +FoundationaLLM-Core-Portal.json +FoundationaLLM-Management-API.json +FoundationaLLM-Management-Portal.json \ No newline at end of file diff --git a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 index 70ef9d3f73..44c89c0d22 100644 --- a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 +++ b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 @@ -19,11 +19,11 @@ - The user must be a Global Administrator in the Entra ID tenant or have RBAC rights to create App Registrations and Service Principals. - The Azure CLI must be installed and authenticated to the Entra ID tenant. - Scaffolding JSON files must be present in the same directory as the script. - - foundationallm-core-api.json - - foundationallm-core-portal.json - - foundationallm-management.json - - foundationallm-managementclient.json - - foundationalllm-authorization.json + - foundationallm-authorization-api.template.json + - foundationallm-core-api.template.json + - foundationallm-core-portal.template.json + - foundationallm-management-api.template.json + - foundationallm-management-portal.template.json .PARAMETER appPermissionsId The GUID of the permission to assign to the client app. @@ -34,19 +34,38 @@ The URL of the client app. .PARAMETER appUrlLocal The local URL of the client app. +.PARAMETER createClientApp +If set to $true, the script will create a client app. If set to $false, the script will not create a client app. + +.PARAMETER fllmApi +The name of the API app. + +.PARAMETER fllmApiConfigPath +The path to the API app configuration file. + +.PARAMETER fllmApiUri +The URI of the API app. + +.PARAMETER fllmClient +The name of the client app. + +.PARAMETER fllmClientConfigPath +The path to the client app configuration file. + + .EXAMPLE The following example creates the FoundationaLLM API and client apps. # Create FoundationaLLM Core App Registrations $params = @{ + appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" + appUrl = "" + appUrlLocal = "http://localhost:3000/signin-oidc" fllmApi = $coreAppName - fllmClient = $coreClientAppName fllmApiConfigPath = "foundationallm-core-api.json" fllmApiUri = "api://FoundationaLLM-Core" + fllmClient = $coreClientAppName fllmClientConfigPath = "foundationallm-core-portal.json" - appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" - appUrl = "" - appUrlLocal = "http://localhost:3000/signin-oidc" } $($fllmAppRegs).Core = New-FllmEntraIdApps @params @@ -83,7 +102,7 @@ function New-FllmEntraIdApps { Name = $fllmApi Uri = $fllmApiUri } - Write-Host -For "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" + Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" $($fllmAppRegMetaData.Api).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Api.Name) --query appId --output tsv) $($fllmAppRegMetaData.Api).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Api.AppId) --query id --output tsv) az ad sp create --id $($fllmAppRegMetaData.Api.AppId) @@ -91,19 +110,19 @@ function New-FllmEntraIdApps { # Create the FLLM ClientApp Registration if ($createClientApp) { $($fllmAppRegMetaData).Client = @{ Name = $fllmClient } - Write-Host "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" + Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" $($fllmAppRegMetaData.Client).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Client.Name) --query appId --output tsv) $($fllmAppRegMetaData.Client).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Client.AppId) --query id --output tsv) az ad sp create --id $($fllmAppRegMetaData.Client.AppId) } # Update the API App Registration - Write-Host "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" + Write-Host -ForegroundColor Yellow "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$fllmApiConfigPath" - Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." + Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." Start-Sleep -Seconds 10 ## Updates the API App Registration - Write-Host "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" + Write-Host -ForegroundColor Yellow "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" $appConfig = Get-content $fllmApiConfigPath | ConvertFrom-Json -Depth 20 if ($createClientApp) { $preAuthorizedApp = @( @@ -120,25 +139,25 @@ function New-FllmEntraIdApps { } $appConfig.identifierUris = @($($fllmAppRegMetaData.Api.Uri)) $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" + Write-Host -ForegroundColor Yellow "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" Set-Content -Path "$($fllmAppRegMetaData.Api.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Api.Name)`.json" # Update the Client App Registration if ($createClientApp) { - Write-Host "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host -ForegroundColor Yellow "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$fllmClientConfigPath" Start-Sleep -Seconds 10 - Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." + Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." ## Updates the Client App Registration - Write-Host "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host -ForegroundColor Yellow "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" $($fllmAppRegMetaData.Client).Uri = @("api://$($fllmAppRegMetaData.Client.Name)") $apiPermissions = @(@{"resourceAppId" = $($fllmAppRegMetaData.Client.AppId); "resourceAccess" = @(@{"id" = "$($appPermissionsId)"; "type" = "Scope" }) }, @{"resourceAppId" = "00000003-0000-0000-c000-000000000000"; "resourceAccess" = @(@{"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; "type" = "Scope" }) }) $appConfig = Get-content $fllmClientConfigPath | ConvertFrom-Json -Depth 20 $appConfig.identifierUris = @($($fllmAppRegMetaData.Client.Uri)) $appConfig.requiredResourceAccess = $apiPermissions $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host -ForegroundColor Yellow "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" Set-Content -Path "$($fllmAppRegMetaData.Client.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Client.Name)`.json" } @@ -153,38 +172,38 @@ function New-FllmEntraIdApps { $fllmAppRegs = @{} # Create FoundationaLLM Core App Registrations $params = @{ - fllmApi = $coreAppName - fllmClient = $coreClientAppName - fllmApiConfigPath = "foundationallm-core-api.json" - fllmApiUri = "api://FoundationaLLM-Core" - fllmClientConfigPath = "foundationallm-core-portal.json" appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" appUrl = "" appUrlLocal = "http://localhost:3000/signin-oidc" + fllmApi = $coreAppName + fllmApiConfigPath = "foundationallm-core-api.template.json" + fllmApiUri = "api://FoundationaLLM-Core" + fllmClient = $coreClientAppName + fllmClientConfigPath = "foundationallm-core-portal.template.json" } $($fllmAppRegs).Core = New-FllmEntraIdApps @params # Create FoundationaLLM Management App Registrations $params = @{ - fllmApi = $mgmtAppName - fllmClient = $mgmtClientAppName - fllmApiConfigPath = "foundationallm-management-api.json" - fllmApiUri = "api://FoundationaLLM-Management" - fllmClientConfigPath = "foundationallm-management-portal.json" appPermissionsId = "c57f4633-0e58-455a-8ede-5de815fe6c9c" appUrl = "" appUrlLocal = "http://localhost:3001/signin-oidc" + fllmApi = $mgmtAppName + fllmApiConfigPath = "foundationallm-management-api.template.json" + fllmApiUri = "api://FoundationaLLM-Management" + fllmClient = $mgmtClientAppName + fllmClientConfigPath = "foundationallm-management-portal.template.json" } $($fllmAppRegs).Management = New-FllmEntraIdApps @params # Create FoundationaLLM Authorization App Registration $params = @{ - fllmApi = $authAppName - fllmApiConfigPath = "foundationalllm-authorization-api.json" - fllmApiUri = "api://FoundationaLLM-Authorization" appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" createClientApp = $false + fllmApi = $authAppName + fllmApiConfigPath = "foundationallm-authorization-api.template.json" + fllmApiUri = "api://FoundationaLLM-Authorization" } -$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params +$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params Write-Host $($fllmAppRegs | ConvertTo-Json) diff --git a/deploy/common/scripts/foundationallm-authorization-api.json b/deploy/common/scripts/foundationallm-authorization-api.json deleted file mode 100644 index f551573f1b..0000000000 --- a/deploy/common/scripts/foundationallm-authorization-api.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage Authorization", - "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Authorization.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} \ No newline at end of file diff --git a/deploy/common/scripts/foundationallm-management-portal.json b/deploy/common/scripts/foundationallm-authorization-api.template.json similarity index 55% rename from deploy/common/scripts/foundationallm-management-portal.json rename to deploy/common/scripts/foundationallm-authorization-api.template.json index 75f1a21d40..c46f13b937 100644 --- a/deploy/common/scripts/foundationallm-management-portal.json +++ b/deploy/common/scripts/foundationallm-authorization-api.template.json @@ -1,10 +1,21 @@ { "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage Authorization", + "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Authorization.Manage" + } + ], + "preAuthorizedApplications": [], "requestedAccessTokenVersion": 2 }, - "identifierUris": [ - "api://FoundationaLLM-Management-Portal" - ], + "identifierUris": [], "publicClient": { "redirectUris": [ "https://oauth.pstmn.io/v1/callback" @@ -24,22 +35,13 @@ }, "requiredResourceAccess": [ { - "resourceAppId": "e4c395f1-cc9a-43bc-95e1-fda09bc94476", - "resourceAccess": [ - { - "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", - "type": "Scope" - } - ] - }, - { - "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [ { "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", "type": "Scope" } - ] + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" } ], "web": { diff --git a/deploy/common/scripts/foundationallm-core-api.json b/deploy/common/scripts/foundationallm-core-api.template.json similarity index 76% rename from deploy/common/scripts/foundationallm-core-api.json rename to deploy/common/scripts/foundationallm-core-api.template.json index 94de45cb69..f9fffc1949 100644 --- a/deploy/common/scripts/foundationallm-core-api.json +++ b/deploy/common/scripts/foundationallm-core-api.template.json @@ -12,25 +12,10 @@ "value": "Data.Read" } ], - "preAuthorizedApplications": [ - { - "delegatedPermissionIds": [ - "6da07102-bb6a-421d-a71e-dfdb6031d3d8" - ], - "appId": "1e811dbe-6476-40e1-9aaa-36f159eba424" - }, - { - "delegatedPermissionIds": [ - "6da07102-bb6a-421d-a71e-dfdb6031d3d8" - ], - "appId": "04b07795-8ddb-461a-bbee-02f9e1bf7b46" - } - ], + "preAuthorizedApplications": [], "requestedAccessTokenVersion": 2 }, - "identifierUris": [ - "api://FoundationaLLM-Core" - ], + "identifierUris": [], "publicClient": { "redirectUris": [ "https://oauth.pstmn.io/v1/callback" diff --git a/deploy/common/scripts/foundationallm-core-portal.json b/deploy/common/scripts/foundationallm-core-portal.template.json similarity index 68% rename from deploy/common/scripts/foundationallm-core-portal.json rename to deploy/common/scripts/foundationallm-core-portal.template.json index 609b361528..7977749e31 100644 --- a/deploy/common/scripts/foundationallm-core-portal.json +++ b/deploy/common/scripts/foundationallm-core-portal.template.json @@ -2,9 +2,7 @@ "api": { "requestedAccessTokenVersion": 2 }, - "identifierUris": [ - "api://FoundationaLLM-Core-Portal" - ], + "identifierUris": [], "publicClient": { "redirectUris": [ "https://oauth.pstmn.io/v1/callback" @@ -12,22 +10,13 @@ }, "requiredResourceAccess": [ { - "resourceAppId": "1e811dbe-6476-40e1-9aaa-36f159eba424", - "resourceAccess": [ - { - "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", - "type": "Scope" - } - ] - }, - { - "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [ { "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", "type": "Scope" } - ] + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" } ], "servicePrincipalLockConfiguration": { diff --git a/deploy/common/scripts/foundationallm-management-api.json b/deploy/common/scripts/foundationallm-management-api.template.json similarity index 76% rename from deploy/common/scripts/foundationallm-management-api.json rename to deploy/common/scripts/foundationallm-management-api.template.json index 5eb13e2114..6a6bdf7fc8 100644 --- a/deploy/common/scripts/foundationallm-management-api.json +++ b/deploy/common/scripts/foundationallm-management-api.template.json @@ -12,25 +12,10 @@ "value": "Data.Manage" } ], - "preAuthorizedApplications": [ - { - "delegatedPermissionIds": [ - "c57f4633-0e58-455a-8ede-5de815fe6c9c" - ], - "appId": "e4c395f1-cc9a-43bc-95e1-fda09bc94476" - }, - { - "delegatedPermissionIds": [ - "c57f4633-0e58-455a-8ede-5de815fe6c9c" - ], - "appId": "04b07795-8ddb-461a-bbee-02f9e1bf7b46" - } - ], + "preAuthorizedApplications": [], "requestedAccessTokenVersion": 2 }, - "identifierUris": [ - "api://FoundationaLLM-Management" - ], + "identifierUris": [], "publicClient": { "redirectUris": [ "https://oauth.pstmn.io/v1/callback" diff --git a/deploy/common/scripts/foundationallm-management-portal.template.json b/deploy/common/scripts/foundationallm-management-portal.template.json new file mode 100644 index 0000000000..e50a7e0c2b --- /dev/null +++ b/deploy/common/scripts/foundationallm-management-portal.template.json @@ -0,0 +1,33 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} From 28cfaaf0081dc0fdd46e87ddae5d8ff20ff418f0 Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:19:23 -0400 Subject: [PATCH 05/10] Removing from this PR --- .../common/scripts/Create-FllmAdminGroup.ps1 | 55 ----- .../common/scripts/Create-FllmEntraIdApps.ps1 | 209 ------------------ ...dationallm-authorization-api.template.json | 56 ----- .../foundationallm-core-api.template.json | 56 ----- .../foundationallm-core-portal.template.json | 40 ---- ...oundationallm-management-api.template.json | 56 ----- ...dationallm-management-portal.template.json | 33 --- 7 files changed, 505 deletions(-) delete mode 100644 deploy/common/scripts/Create-FllmAdminGroup.ps1 delete mode 100644 deploy/common/scripts/Create-FllmEntraIdApps.ps1 delete mode 100644 deploy/common/scripts/foundationallm-authorization-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-core-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-core-portal.template.json delete mode 100644 deploy/common/scripts/foundationallm-management-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-management-portal.template.json diff --git a/deploy/common/scripts/Create-FllmAdminGroup.ps1 b/deploy/common/scripts/Create-FllmAdminGroup.ps1 deleted file mode 100644 index 9798835d21..0000000000 --- a/deploy/common/scripts/Create-FllmAdminGroup.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -<# -.SYNOPSIS - Creates an Entra ID group using the Azure CLI and adds the current user to the group. - -.DESCRIPTION - This script creates a new Entra ID group named 'FLLM-Admins' using the Azure CLI command. - The user running the script is added to the group after its creation. - It checks for errors during execution and outputs the status of group creation. - -.PARAMETER groupName - Specifies the name of the Entra ID group to be created. - -.EXAMPLE - ./Create-FllmAdminGroup.ps1 -groupName "FLLM-Admins" - This example runs the script to create an Entra ID group named 'FLLM-Admins'. -#> - -Param( - [parameter(Mandatory = $false)][string]$groupName = "FLLM-Admins" -) - -# Try block to handle potential errors during the execution -try { - # Check if the group already exists - Write-Host -ForegroundColor Yellow "Checking if the Entra ID group '$groupName' already exists..." - az ad group show --group $groupName - - if ($LASTEXITCODE -eq 0) { - Write-Host -ForegroundColor Red "The Entra ID group '$groupName' already exists. Script execution stopped." - exit - } - - # Command to create the Entra ID group using Azure CLI - Write-Host -ForegroundColor Yellow "Creating Entra ID group '$groupName'..." - az ad group create --display-name $groupName --mail-nickname $groupName - - if ($LASTEXITCODE -ne 0) { - throw "Failed to create group ${message} (code: ${LASTEXITCODE})" - } - - Write-Host -ForegroundColor Yellow "Waiting for group creation to complete..." - Start-Sleep 10 - - # Get the ID of the of the user running the script & add the user to the group - $currentUserId = (az ad signed-in-user show --query id -o tsv).Trim() - Write-Host -ForegroundColor Yellow "Adding current user to the group..." - az ad group member add --group $groupName --member-id $currentUserId - - # If the command executes successfully, output the result - Write-Host -ForegroundColor Yellow "Entra ID group '$groupName' created successfully, and added current user with ID $currentUserId to the group." -} -catch { - # Catch block to handle and report any errors that occur during the execution - Write-Host -ForegroundColor Red "Failed to create Entra ID group. Error: $($_.Exception.Message)" -} diff --git a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 deleted file mode 100644 index 44c89c0d22..0000000000 --- a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 +++ /dev/null @@ -1,209 +0,0 @@ -#! /usr/bin/pwsh -<# -.SYNOPSIS - Generates a set of FLLM EntraID App Registrations and their respective client apps in the Entra ID tenant. - See the following link for more information: https://docs.foundationallm.ai/deployment/authentication-authorization/index.html - **These app names are mandatory, you can't change the names or the scopes.** - -.DESCRIPTION - The script will create the following apps: - - FoundationaLLM-Authorization-API - - FoundationaLLM-Core-API - - FoundationaLLM-Core-Portal - - FoundationaLLM-Management-API - - FoundationaLLM-Management-Portal - - The script will also assign the required permissions to the client apps and the required API permissions to the API apps. - -.REQUIREMENTS - - The user must be a Global Administrator in the Entra ID tenant or have RBAC rights to create App Registrations and Service Principals. - - The Azure CLI must be installed and authenticated to the Entra ID tenant. - - Scaffolding JSON files must be present in the same directory as the script. - - foundationallm-authorization-api.template.json - - foundationallm-core-api.template.json - - foundationallm-core-portal.template.json - - foundationallm-management-api.template.json - - foundationallm-management-portal.template.json - -.PARAMETER appPermissionsId -The GUID of the permission to assign to the client app. - -.PARAMETER appUrl -The URL of the client app. - -.PARAMETER appUrlLocal -The local URL of the client app. - -.PARAMETER createClientApp -If set to $true, the script will create a client app. If set to $false, the script will not create a client app. - -.PARAMETER fllmApi -The name of the API app. - -.PARAMETER fllmApiConfigPath -The path to the API app configuration file. - -.PARAMETER fllmApiUri -The URI of the API app. - -.PARAMETER fllmClient -The name of the client app. - -.PARAMETER fllmClientConfigPath -The path to the client app configuration file. - - -.EXAMPLE -The following example creates the FoundationaLLM API and client apps. - -# Create FoundationaLLM Core App Registrations -$params = @{ - appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" - appUrl = "" - appUrlLocal = "http://localhost:3000/signin-oidc" - fllmApi = $coreAppName - fllmApiConfigPath = "foundationallm-core-api.json" - fllmApiUri = "api://FoundationaLLM-Core" - fllmClient = $coreClientAppName - fllmClientConfigPath = "foundationallm-core-portal.json" -} -$($fllmAppRegs).Core = New-FllmEntraIdApps @params - -#> - -Param( - [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", - [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", - [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", - [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", - [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" -) - -Set-StrictMode -Version 3.0 -$ErrorActionPreference = "Stop" - -function New-FllmEntraIdApps { - param ( - [Parameter(Mandatory = $true)][string]$appPermissionsId, - [Parameter(Mandatory = $false)][string]$appUrl, - [Parameter(Mandatory = $false)][string]$appUrlLocal, - [Parameter(Mandatory = $false)][bool]$createClientApp = $true, - [Parameter(Mandatory = $true)][string]$fllmApi, - [Parameter(Mandatory = $true)][string]$fllmApiConfigPath, - [Parameter(Mandatory = $true)][string]$fllmApiUri, - [Parameter(Mandatory = $false)][string]$fllmClient, - [Parameter(Mandatory = $false)][string]$fllmClientConfigPath - ) - - $fllmAppRegMetaData = @{} - try { - # Create the FLLM API App Registration - $($fllmAppRegMetaData).Api = @{ - Name = $fllmApi - Uri = $fllmApiUri - } - Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" - $($fllmAppRegMetaData.Api).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Api.Name) --query appId --output tsv) - $($fllmAppRegMetaData.Api).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Api.AppId) --query id --output tsv) - az ad sp create --id $($fllmAppRegMetaData.Api.AppId) - - # Create the FLLM ClientApp Registration - if ($createClientApp) { - $($fllmAppRegMetaData).Client = @{ Name = $fllmClient } - Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" - $($fllmAppRegMetaData.Client).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Client.Name) --query appId --output tsv) - $($fllmAppRegMetaData.Client).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Client.AppId) --query id --output tsv) - az ad sp create --id $($fllmAppRegMetaData.Client.AppId) - } - - # Update the API App Registration - Write-Host -ForegroundColor Yellow "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" - az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$fllmApiConfigPath" - Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." - Start-Sleep -Seconds 10 - ## Updates the API App Registration - Write-Host -ForegroundColor Yellow "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" - $appConfig = Get-content $fllmApiConfigPath | ConvertFrom-Json -Depth 20 - if ($createClientApp) { - $preAuthorizedApp = @( - @{ - "appId" = $($fllmAppRegMetaData.Client.AppId); - "delegatedPermissionIds" = @("$($appPermissionsId)") - }, - @{ - "appId" = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; - "delegatedPermissionIds" = @("$($appPermissionsId)") - } - ) - $appConfig.api.preAuthorizedApplications = $preAuthorizedApp - } - $appConfig.identifierUris = @($($fllmAppRegMetaData.Api.Uri)) - $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host -ForegroundColor Yellow "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" - Set-Content -Path "$($fllmAppRegMetaData.Api.Name)`.json" $appConfigUpdate - az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Api.Name)`.json" - - # Update the Client App Registration - if ($createClientApp) { - Write-Host -ForegroundColor Yellow "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" - az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$fllmClientConfigPath" - Start-Sleep -Seconds 10 - Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." - ## Updates the Client App Registration - Write-Host -ForegroundColor Yellow "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" - $($fllmAppRegMetaData.Client).Uri = @("api://$($fllmAppRegMetaData.Client.Name)") - $apiPermissions = @(@{"resourceAppId" = $($fllmAppRegMetaData.Client.AppId); "resourceAccess" = @(@{"id" = "$($appPermissionsId)"; "type" = "Scope" }) }, @{"resourceAppId" = "00000003-0000-0000-c000-000000000000"; "resourceAccess" = @(@{"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; "type" = "Scope" }) }) - $appConfig = Get-content $fllmClientConfigPath | ConvertFrom-Json -Depth 20 - $appConfig.identifierUris = @($($fllmAppRegMetaData.Client.Uri)) - $appConfig.requiredResourceAccess = $apiPermissions - $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host -ForegroundColor Yellow "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" - Set-Content -Path "$($fllmAppRegMetaData.Client.Name)`.json" $appConfigUpdate - az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Client.Name)`.json" - } - } - catch { - Write-Host "Error occurred: $_" - } - - return $fllmAppRegMetaData -} - -$fllmAppRegs = @{} -# Create FoundationaLLM Core App Registrations -$params = @{ - appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" - appUrl = "" - appUrlLocal = "http://localhost:3000/signin-oidc" - fllmApi = $coreAppName - fllmApiConfigPath = "foundationallm-core-api.template.json" - fllmApiUri = "api://FoundationaLLM-Core" - fllmClient = $coreClientAppName - fllmClientConfigPath = "foundationallm-core-portal.template.json" -} -$($fllmAppRegs).Core = New-FllmEntraIdApps @params - -# Create FoundationaLLM Management App Registrations -$params = @{ - appPermissionsId = "c57f4633-0e58-455a-8ede-5de815fe6c9c" - appUrl = "" - appUrlLocal = "http://localhost:3001/signin-oidc" - fllmApi = $mgmtAppName - fllmApiConfigPath = "foundationallm-management-api.template.json" - fllmApiUri = "api://FoundationaLLM-Management" - fllmClient = $mgmtClientAppName - fllmClientConfigPath = "foundationallm-management-portal.template.json" -} -$($fllmAppRegs).Management = New-FllmEntraIdApps @params - -# Create FoundationaLLM Authorization App Registration -$params = @{ - appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" - createClientApp = $false - fllmApi = $authAppName - fllmApiConfigPath = "foundationallm-authorization-api.template.json" - fllmApiUri = "api://FoundationaLLM-Authorization" -} -$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params - -Write-Host $($fllmAppRegs | ConvertTo-Json) diff --git a/deploy/common/scripts/foundationallm-authorization-api.template.json b/deploy/common/scripts/foundationallm-authorization-api.template.json deleted file mode 100644 index c46f13b937..0000000000 --- a/deploy/common/scripts/foundationallm-authorization-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage Authorization", - "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Authorization.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-core-api.template.json b/deploy/common/scripts/foundationallm-core-api.template.json deleted file mode 100644 index f9fffc1949..0000000000 --- a/deploy/common/scripts/foundationallm-core-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "adminConsentDisplayName": "Read data on behalf of users", - "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "userConsentDisplayName": "Read data on behalf of users", - "value": "Data.Read" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-core-portal.template.json b/deploy/common/scripts/foundationallm-core-portal.template.json deleted file mode 100644 index 7977749e31..0000000000 --- a/deploy/common/scripts/foundationallm-core-portal.template.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - } - } -} diff --git a/deploy/common/scripts/foundationallm-management-api.template.json b/deploy/common/scripts/foundationallm-management-api.template.json deleted file mode 100644 index 6a6bdf7fc8..0000000000 --- a/deploy/common/scripts/foundationallm-management-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage data on behalf of users", - "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Data.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-management-portal.template.json b/deploy/common/scripts/foundationallm-management-portal.template.json deleted file mode 100644 index e50a7e0c2b..0000000000 --- a/deploy/common/scripts/foundationallm-management-portal.template.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} From 0bf21294097d0fc2dd49f8141821cf444cdc752c Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:20:51 -0400 Subject: [PATCH 06/10] Revert "Removing from this PR" This reverts commit 28cfaaf0081dc0fdd46e87ddae5d8ff20ff418f0. --- .../common/scripts/Create-FllmAdminGroup.ps1 | 55 +++++ .../common/scripts/Create-FllmEntraIdApps.ps1 | 209 ++++++++++++++++++ ...dationallm-authorization-api.template.json | 56 +++++ .../foundationallm-core-api.template.json | 56 +++++ .../foundationallm-core-portal.template.json | 40 ++++ ...oundationallm-management-api.template.json | 56 +++++ ...dationallm-management-portal.template.json | 33 +++ 7 files changed, 505 insertions(+) create mode 100644 deploy/common/scripts/Create-FllmAdminGroup.ps1 create mode 100644 deploy/common/scripts/Create-FllmEntraIdApps.ps1 create mode 100644 deploy/common/scripts/foundationallm-authorization-api.template.json create mode 100644 deploy/common/scripts/foundationallm-core-api.template.json create mode 100644 deploy/common/scripts/foundationallm-core-portal.template.json create mode 100644 deploy/common/scripts/foundationallm-management-api.template.json create mode 100644 deploy/common/scripts/foundationallm-management-portal.template.json diff --git a/deploy/common/scripts/Create-FllmAdminGroup.ps1 b/deploy/common/scripts/Create-FllmAdminGroup.ps1 new file mode 100644 index 0000000000..9798835d21 --- /dev/null +++ b/deploy/common/scripts/Create-FllmAdminGroup.ps1 @@ -0,0 +1,55 @@ +<# +.SYNOPSIS + Creates an Entra ID group using the Azure CLI and adds the current user to the group. + +.DESCRIPTION + This script creates a new Entra ID group named 'FLLM-Admins' using the Azure CLI command. + The user running the script is added to the group after its creation. + It checks for errors during execution and outputs the status of group creation. + +.PARAMETER groupName + Specifies the name of the Entra ID group to be created. + +.EXAMPLE + ./Create-FllmAdminGroup.ps1 -groupName "FLLM-Admins" + This example runs the script to create an Entra ID group named 'FLLM-Admins'. +#> + +Param( + [parameter(Mandatory = $false)][string]$groupName = "FLLM-Admins" +) + +# Try block to handle potential errors during the execution +try { + # Check if the group already exists + Write-Host -ForegroundColor Yellow "Checking if the Entra ID group '$groupName' already exists..." + az ad group show --group $groupName + + if ($LASTEXITCODE -eq 0) { + Write-Host -ForegroundColor Red "The Entra ID group '$groupName' already exists. Script execution stopped." + exit + } + + # Command to create the Entra ID group using Azure CLI + Write-Host -ForegroundColor Yellow "Creating Entra ID group '$groupName'..." + az ad group create --display-name $groupName --mail-nickname $groupName + + if ($LASTEXITCODE -ne 0) { + throw "Failed to create group ${message} (code: ${LASTEXITCODE})" + } + + Write-Host -ForegroundColor Yellow "Waiting for group creation to complete..." + Start-Sleep 10 + + # Get the ID of the of the user running the script & add the user to the group + $currentUserId = (az ad signed-in-user show --query id -o tsv).Trim() + Write-Host -ForegroundColor Yellow "Adding current user to the group..." + az ad group member add --group $groupName --member-id $currentUserId + + # If the command executes successfully, output the result + Write-Host -ForegroundColor Yellow "Entra ID group '$groupName' created successfully, and added current user with ID $currentUserId to the group." +} +catch { + # Catch block to handle and report any errors that occur during the execution + Write-Host -ForegroundColor Red "Failed to create Entra ID group. Error: $($_.Exception.Message)" +} diff --git a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 new file mode 100644 index 0000000000..44c89c0d22 --- /dev/null +++ b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 @@ -0,0 +1,209 @@ +#! /usr/bin/pwsh +<# +.SYNOPSIS + Generates a set of FLLM EntraID App Registrations and their respective client apps in the Entra ID tenant. + See the following link for more information: https://docs.foundationallm.ai/deployment/authentication-authorization/index.html + **These app names are mandatory, you can't change the names or the scopes.** + +.DESCRIPTION + The script will create the following apps: + - FoundationaLLM-Authorization-API + - FoundationaLLM-Core-API + - FoundationaLLM-Core-Portal + - FoundationaLLM-Management-API + - FoundationaLLM-Management-Portal + + The script will also assign the required permissions to the client apps and the required API permissions to the API apps. + +.REQUIREMENTS + - The user must be a Global Administrator in the Entra ID tenant or have RBAC rights to create App Registrations and Service Principals. + - The Azure CLI must be installed and authenticated to the Entra ID tenant. + - Scaffolding JSON files must be present in the same directory as the script. + - foundationallm-authorization-api.template.json + - foundationallm-core-api.template.json + - foundationallm-core-portal.template.json + - foundationallm-management-api.template.json + - foundationallm-management-portal.template.json + +.PARAMETER appPermissionsId +The GUID of the permission to assign to the client app. + +.PARAMETER appUrl +The URL of the client app. + +.PARAMETER appUrlLocal +The local URL of the client app. + +.PARAMETER createClientApp +If set to $true, the script will create a client app. If set to $false, the script will not create a client app. + +.PARAMETER fllmApi +The name of the API app. + +.PARAMETER fllmApiConfigPath +The path to the API app configuration file. + +.PARAMETER fllmApiUri +The URI of the API app. + +.PARAMETER fllmClient +The name of the client app. + +.PARAMETER fllmClientConfigPath +The path to the client app configuration file. + + +.EXAMPLE +The following example creates the FoundationaLLM API and client apps. + +# Create FoundationaLLM Core App Registrations +$params = @{ + appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" + appUrl = "" + appUrlLocal = "http://localhost:3000/signin-oidc" + fllmApi = $coreAppName + fllmApiConfigPath = "foundationallm-core-api.json" + fllmApiUri = "api://FoundationaLLM-Core" + fllmClient = $coreClientAppName + fllmClientConfigPath = "foundationallm-core-portal.json" +} +$($fllmAppRegs).Core = New-FllmEntraIdApps @params + +#> + +Param( + [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", + [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", + [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", + [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", + [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" +) + +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + +function New-FllmEntraIdApps { + param ( + [Parameter(Mandatory = $true)][string]$appPermissionsId, + [Parameter(Mandatory = $false)][string]$appUrl, + [Parameter(Mandatory = $false)][string]$appUrlLocal, + [Parameter(Mandatory = $false)][bool]$createClientApp = $true, + [Parameter(Mandatory = $true)][string]$fllmApi, + [Parameter(Mandatory = $true)][string]$fllmApiConfigPath, + [Parameter(Mandatory = $true)][string]$fllmApiUri, + [Parameter(Mandatory = $false)][string]$fllmClient, + [Parameter(Mandatory = $false)][string]$fllmClientConfigPath + ) + + $fllmAppRegMetaData = @{} + try { + # Create the FLLM API App Registration + $($fllmAppRegMetaData).Api = @{ + Name = $fllmApi + Uri = $fllmApiUri + } + Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" + $($fllmAppRegMetaData.Api).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Api.Name) --query appId --output tsv) + $($fllmAppRegMetaData.Api).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Api.AppId) --query id --output tsv) + az ad sp create --id $($fllmAppRegMetaData.Api.AppId) + + # Create the FLLM ClientApp Registration + if ($createClientApp) { + $($fllmAppRegMetaData).Client = @{ Name = $fllmClient } + Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" + $($fllmAppRegMetaData.Client).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Client.Name) --query appId --output tsv) + $($fllmAppRegMetaData.Client).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Client.AppId) --query id --output tsv) + az ad sp create --id $($fllmAppRegMetaData.Client.AppId) + } + + # Update the API App Registration + Write-Host -ForegroundColor Yellow "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" + az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$fllmApiConfigPath" + Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." + Start-Sleep -Seconds 10 + ## Updates the API App Registration + Write-Host -ForegroundColor Yellow "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" + $appConfig = Get-content $fllmApiConfigPath | ConvertFrom-Json -Depth 20 + if ($createClientApp) { + $preAuthorizedApp = @( + @{ + "appId" = $($fllmAppRegMetaData.Client.AppId); + "delegatedPermissionIds" = @("$($appPermissionsId)") + }, + @{ + "appId" = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; + "delegatedPermissionIds" = @("$($appPermissionsId)") + } + ) + $appConfig.api.preAuthorizedApplications = $preAuthorizedApp + } + $appConfig.identifierUris = @($($fllmAppRegMetaData.Api.Uri)) + $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 + Write-Host -ForegroundColor Yellow "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" + Set-Content -Path "$($fllmAppRegMetaData.Api.Name)`.json" $appConfigUpdate + az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Api.Name)`.json" + + # Update the Client App Registration + if ($createClientApp) { + Write-Host -ForegroundColor Yellow "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$fllmClientConfigPath" + Start-Sleep -Seconds 10 + Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." + ## Updates the Client App Registration + Write-Host -ForegroundColor Yellow "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + $($fllmAppRegMetaData.Client).Uri = @("api://$($fllmAppRegMetaData.Client.Name)") + $apiPermissions = @(@{"resourceAppId" = $($fllmAppRegMetaData.Client.AppId); "resourceAccess" = @(@{"id" = "$($appPermissionsId)"; "type" = "Scope" }) }, @{"resourceAppId" = "00000003-0000-0000-c000-000000000000"; "resourceAccess" = @(@{"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; "type" = "Scope" }) }) + $appConfig = Get-content $fllmClientConfigPath | ConvertFrom-Json -Depth 20 + $appConfig.identifierUris = @($($fllmAppRegMetaData.Client.Uri)) + $appConfig.requiredResourceAccess = $apiPermissions + $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 + Write-Host -ForegroundColor Yellow "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" + Set-Content -Path "$($fllmAppRegMetaData.Client.Name)`.json" $appConfigUpdate + az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Client.Name)`.json" + } + } + catch { + Write-Host "Error occurred: $_" + } + + return $fllmAppRegMetaData +} + +$fllmAppRegs = @{} +# Create FoundationaLLM Core App Registrations +$params = @{ + appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" + appUrl = "" + appUrlLocal = "http://localhost:3000/signin-oidc" + fllmApi = $coreAppName + fllmApiConfigPath = "foundationallm-core-api.template.json" + fllmApiUri = "api://FoundationaLLM-Core" + fllmClient = $coreClientAppName + fllmClientConfigPath = "foundationallm-core-portal.template.json" +} +$($fllmAppRegs).Core = New-FllmEntraIdApps @params + +# Create FoundationaLLM Management App Registrations +$params = @{ + appPermissionsId = "c57f4633-0e58-455a-8ede-5de815fe6c9c" + appUrl = "" + appUrlLocal = "http://localhost:3001/signin-oidc" + fllmApi = $mgmtAppName + fllmApiConfigPath = "foundationallm-management-api.template.json" + fllmApiUri = "api://FoundationaLLM-Management" + fllmClient = $mgmtClientAppName + fllmClientConfigPath = "foundationallm-management-portal.template.json" +} +$($fllmAppRegs).Management = New-FllmEntraIdApps @params + +# Create FoundationaLLM Authorization App Registration +$params = @{ + appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" + createClientApp = $false + fllmApi = $authAppName + fllmApiConfigPath = "foundationallm-authorization-api.template.json" + fllmApiUri = "api://FoundationaLLM-Authorization" +} +$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params + +Write-Host $($fllmAppRegs | ConvertTo-Json) diff --git a/deploy/common/scripts/foundationallm-authorization-api.template.json b/deploy/common/scripts/foundationallm-authorization-api.template.json new file mode 100644 index 0000000000..c46f13b937 --- /dev/null +++ b/deploy/common/scripts/foundationallm-authorization-api.template.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage Authorization", + "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Authorization.Manage" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} diff --git a/deploy/common/scripts/foundationallm-core-api.template.json b/deploy/common/scripts/foundationallm-core-api.template.json new file mode 100644 index 0000000000..f9fffc1949 --- /dev/null +++ b/deploy/common/scripts/foundationallm-core-api.template.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "adminConsentDisplayName": "Read data on behalf of users", + "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", + "isEnabled": true, + "type": "User", + "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "userConsentDisplayName": "Read data on behalf of users", + "value": "Data.Read" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} diff --git a/deploy/common/scripts/foundationallm-core-portal.template.json b/deploy/common/scripts/foundationallm-core-portal.template.json new file mode 100644 index 0000000000..7977749e31 --- /dev/null +++ b/deploy/common/scripts/foundationallm-core-portal.template.json @@ -0,0 +1,40 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + } + } +} diff --git a/deploy/common/scripts/foundationallm-management-api.template.json b/deploy/common/scripts/foundationallm-management-api.template.json new file mode 100644 index 0000000000..6a6bdf7fc8 --- /dev/null +++ b/deploy/common/scripts/foundationallm-management-api.template.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage data on behalf of users", + "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Data.Manage" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} diff --git a/deploy/common/scripts/foundationallm-management-portal.template.json b/deploy/common/scripts/foundationallm-management-portal.template.json new file mode 100644 index 0000000000..e50a7e0c2b --- /dev/null +++ b/deploy/common/scripts/foundationallm-management-portal.template.json @@ -0,0 +1,33 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} From 54a3f1a84db963873938624b5d7e1bb6e32068be Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:29:34 -0400 Subject: [PATCH 07/10] Removing from the PR --- .../common/scripts/Create-FllmAdminGroup.ps1 | 55 ------------------ ...dationallm-authorization-api.template.json | 56 ------------------- .../foundationallm-core-api.template.json | 56 ------------------- .../foundationallm-core-portal.template.json | 40 ------------- ...oundationallm-management-api.template.json | 56 ------------------- ...dationallm-management-portal.template.json | 33 ----------- 6 files changed, 296 deletions(-) delete mode 100644 deploy/common/scripts/Create-FllmAdminGroup.ps1 delete mode 100644 deploy/common/scripts/foundationallm-authorization-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-core-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-core-portal.template.json delete mode 100644 deploy/common/scripts/foundationallm-management-api.template.json delete mode 100644 deploy/common/scripts/foundationallm-management-portal.template.json diff --git a/deploy/common/scripts/Create-FllmAdminGroup.ps1 b/deploy/common/scripts/Create-FllmAdminGroup.ps1 deleted file mode 100644 index 9798835d21..0000000000 --- a/deploy/common/scripts/Create-FllmAdminGroup.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -<# -.SYNOPSIS - Creates an Entra ID group using the Azure CLI and adds the current user to the group. - -.DESCRIPTION - This script creates a new Entra ID group named 'FLLM-Admins' using the Azure CLI command. - The user running the script is added to the group after its creation. - It checks for errors during execution and outputs the status of group creation. - -.PARAMETER groupName - Specifies the name of the Entra ID group to be created. - -.EXAMPLE - ./Create-FllmAdminGroup.ps1 -groupName "FLLM-Admins" - This example runs the script to create an Entra ID group named 'FLLM-Admins'. -#> - -Param( - [parameter(Mandatory = $false)][string]$groupName = "FLLM-Admins" -) - -# Try block to handle potential errors during the execution -try { - # Check if the group already exists - Write-Host -ForegroundColor Yellow "Checking if the Entra ID group '$groupName' already exists..." - az ad group show --group $groupName - - if ($LASTEXITCODE -eq 0) { - Write-Host -ForegroundColor Red "The Entra ID group '$groupName' already exists. Script execution stopped." - exit - } - - # Command to create the Entra ID group using Azure CLI - Write-Host -ForegroundColor Yellow "Creating Entra ID group '$groupName'..." - az ad group create --display-name $groupName --mail-nickname $groupName - - if ($LASTEXITCODE -ne 0) { - throw "Failed to create group ${message} (code: ${LASTEXITCODE})" - } - - Write-Host -ForegroundColor Yellow "Waiting for group creation to complete..." - Start-Sleep 10 - - # Get the ID of the of the user running the script & add the user to the group - $currentUserId = (az ad signed-in-user show --query id -o tsv).Trim() - Write-Host -ForegroundColor Yellow "Adding current user to the group..." - az ad group member add --group $groupName --member-id $currentUserId - - # If the command executes successfully, output the result - Write-Host -ForegroundColor Yellow "Entra ID group '$groupName' created successfully, and added current user with ID $currentUserId to the group." -} -catch { - # Catch block to handle and report any errors that occur during the execution - Write-Host -ForegroundColor Red "Failed to create Entra ID group. Error: $($_.Exception.Message)" -} diff --git a/deploy/common/scripts/foundationallm-authorization-api.template.json b/deploy/common/scripts/foundationallm-authorization-api.template.json deleted file mode 100644 index c46f13b937..0000000000 --- a/deploy/common/scripts/foundationallm-authorization-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage Authorization", - "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Authorization.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-core-api.template.json b/deploy/common/scripts/foundationallm-core-api.template.json deleted file mode 100644 index f9fffc1949..0000000000 --- a/deploy/common/scripts/foundationallm-core-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "adminConsentDisplayName": "Read data on behalf of users", - "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", - "userConsentDisplayName": "Read data on behalf of users", - "value": "Data.Read" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-core-portal.template.json b/deploy/common/scripts/foundationallm-core-portal.template.json deleted file mode 100644 index 7977749e31..0000000000 --- a/deploy/common/scripts/foundationallm-core-portal.template.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - } - } -} diff --git a/deploy/common/scripts/foundationallm-management-api.template.json b/deploy/common/scripts/foundationallm-management-api.template.json deleted file mode 100644 index 6a6bdf7fc8..0000000000 --- a/deploy/common/scripts/foundationallm-management-api.template.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "api": { - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", - "adminConsentDisplayName": "Manage data on behalf of users", - "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", - "isEnabled": true, - "type": "User", - "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", - "userConsentDisplayName": "Manage data on behalf of the users", - "value": "Data.Manage" - } - ], - "preAuthorizedApplications": [], - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAccess": [ - { - "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", - "type": "Scope" - } - ], - "resourceAppId": "00000003-0000-0000-c000-000000000000" - } - ], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} diff --git a/deploy/common/scripts/foundationallm-management-portal.template.json b/deploy/common/scripts/foundationallm-management-portal.template.json deleted file mode 100644 index e50a7e0c2b..0000000000 --- a/deploy/common/scripts/foundationallm-management-portal.template.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "api": { - "requestedAccessTokenVersion": 2 - }, - "identifierUris": [], - "publicClient": { - "redirectUris": [ - "https://oauth.pstmn.io/v1/callback" - ] - }, - "servicePrincipalLockConfiguration": { - "allProperties": true, - "credentialsWithUsageSign": true, - "credentialsWithUsageVerify": true, - "identifierUris": false, - "isEnabled": true, - "tokenEncryptionKeyId": true - }, - "signInAudience": "AzureADMyOrg", - "spa": { - "redirectUris": [] - }, - "requiredResourceAccess": [], - "web": { - "implicitGrantSettings": { - "enableAccessTokenIssuance": true, - "enableIdTokenIssuance": true - }, - "redirectUris": [ - "http://localhost" - ] - } -} From f714050a4ff59366f1e8100da2d4fe39ac1775b2 Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:32:59 -0400 Subject: [PATCH 08/10] add ignore --- deploy/common/scripts/.gitignore | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 deploy/common/scripts/.gitignore diff --git a/deploy/common/scripts/.gitignore b/deploy/common/scripts/.gitignore deleted file mode 100644 index 82f9485640..0000000000 --- a/deploy/common/scripts/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Don't commit the generated Entra ID API files -FoundationaLLM-Authorization-API.json -FoundationaLLM-Core-API.json -FoundationaLLM-Core-Portal.json -FoundationaLLM-Management-API.json -FoundationaLLM-Management-Portal.json \ No newline at end of file From a4a8df8cc450283c8e5c0fcfac4e83ba0b75b36e Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:42:27 -0400 Subject: [PATCH 09/10] fixing PR issues --- .../foundationalllm-authorization.json | 56 +++++++++++++++++++ .../scripts/foundationalllm-client.json | 40 +++++++++++++ .../scripts/foundationalllm-management.json | 56 +++++++++++++++++++ .../foundationalllm-managementclient.json | 33 +++++++++++ .../foundationalllm-vectorization.json | 56 +++++++++++++++++++ deploy/common/scripts/foundationalllm.json | 56 +++++++++++++++++++ 6 files changed, 297 insertions(+) create mode 100644 deploy/common/scripts/foundationalllm-authorization.json create mode 100644 deploy/common/scripts/foundationalllm-client.json create mode 100644 deploy/common/scripts/foundationalllm-management.json create mode 100644 deploy/common/scripts/foundationalllm-managementclient.json create mode 100644 deploy/common/scripts/foundationalllm-vectorization.json create mode 100644 deploy/common/scripts/foundationalllm.json diff --git a/deploy/common/scripts/foundationalllm-authorization.json b/deploy/common/scripts/foundationalllm-authorization.json new file mode 100644 index 0000000000..f551573f1b --- /dev/null +++ b/deploy/common/scripts/foundationalllm-authorization.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage Authorization", + "id": "9e313dd4-51e4-4989-84d0-c713e38e467d", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Authorization.Manage" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-client.json b/deploy/common/scripts/foundationalllm-client.json new file mode 100644 index 0000000000..2e0cc40c38 --- /dev/null +++ b/deploy/common/scripts/foundationalllm-client.json @@ -0,0 +1,40 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + } + } +} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-management.json b/deploy/common/scripts/foundationalllm-management.json new file mode 100644 index 0000000000..c2ed413f98 --- /dev/null +++ b/deploy/common/scripts/foundationalllm-management.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage data on behalf of users", + "id": "c57f4633-0e58-455a-8ede-5de815fe6c9c", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Data.Manage" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-managementclient.json b/deploy/common/scripts/foundationalllm-managementclient.json new file mode 100644 index 0000000000..456d0b7157 --- /dev/null +++ b/deploy/common/scripts/foundationalllm-managementclient.json @@ -0,0 +1,33 @@ +{ + "api": { + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm-vectorization.json b/deploy/common/scripts/foundationalllm-vectorization.json new file mode 100644 index 0000000000..37ee660002 --- /dev/null +++ b/deploy/common/scripts/foundationalllm-vectorization.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to manage data on behalf of the signed-in user.", + "adminConsentDisplayName": "Manage data on behalf of users", + "id": "b2061dc7-ac14-4ce2-9dcc-7f1ac0d8a238", + "isEnabled": true, + "type": "User", + "userConsentDescription": " Allows the app to manage data on behalf of the signed-in user.", + "userConsentDisplayName": "Manage data on behalf of the users", + "value": "Data.Manage" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} \ No newline at end of file diff --git a/deploy/common/scripts/foundationalllm.json b/deploy/common/scripts/foundationalllm.json new file mode 100644 index 0000000000..abc8f1bcfa --- /dev/null +++ b/deploy/common/scripts/foundationalllm.json @@ -0,0 +1,56 @@ +{ + "api": { + "oauth2PermissionScopes": [ + { + "adminConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "adminConsentDisplayName": "Read data on behalf of users", + "id": "6da07102-bb6a-421d-a71e-dfdb6031d3d8", + "isEnabled": true, + "type": "User", + "userConsentDescription": "Allows the app to read data on behalf of the signed-in user.", + "userConsentDisplayName": "Read data on behalf of users", + "value": "Data.Read" + } + ], + "preAuthorizedApplications": [], + "requestedAccessTokenVersion": 2 + }, + "identifierUris": [], + "publicClient": { + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback" + ] + }, + "servicePrincipalLockConfiguration": { + "allProperties": true, + "credentialsWithUsageSign": true, + "credentialsWithUsageVerify": true, + "identifierUris": false, + "isEnabled": true, + "tokenEncryptionKeyId": true + }, + "signInAudience": "AzureADMyOrg", + "spa": { + "redirectUris": [] + }, + "requiredResourceAccess": [ + { + "resourceAccess": [ + { + "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", + "type": "Scope" + } + ], + "resourceAppId": "00000003-0000-0000-c000-000000000000" + } + ], + "web": { + "implicitGrantSettings": { + "enableAccessTokenIssuance": true, + "enableIdTokenIssuance": true + }, + "redirectUris": [ + "http://localhost" + ] + } +} \ No newline at end of file From d0d41564ba5c1c4f84b41ca222d715fa0cc2ffbe Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Fri, 26 Jul 2024 17:45:10 -0400 Subject: [PATCH 10/10] fixing PR --- .../common/scripts/Create-FllmEntraIdApps.ps1 | 138 +++++++----------- 1 file changed, 55 insertions(+), 83 deletions(-) diff --git a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 index 44c89c0d22..a3ac731602 100644 --- a/deploy/common/scripts/Create-FllmEntraIdApps.ps1 +++ b/deploy/common/scripts/Create-FllmEntraIdApps.ps1 @@ -1,29 +1,30 @@ #! /usr/bin/pwsh + +Param( + [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", + [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", + [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", + [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", + [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" +) + +Set-StrictMode -Version 3.0 +$ErrorActionPreference = "Stop" + <# .SYNOPSIS - Generates a set of FLLM EntraID App Registrations and their respective client apps in the Entra ID tenant. - See the following link for more information: https://docs.foundationallm.ai/deployment/authentication-authorization/index.html - **These app names are mandatory, you can't change the names or the scopes.** - + Generates a set of FLLM EntraID API apps and their respective client apps in the Azure AD tenant. + .DESCRIPTION The script will create the following apps: - - FoundationaLLM-Authorization-API - - FoundationaLLM-Core-API - - FoundationaLLM-Core-Portal - - FoundationaLLM-Management-API - - FoundationaLLM-Management-Portal - + - FoundationaLLM + - FoundationaLLM-Client + - FoundationaLLM-Management + - FoundationaLLM-ManagementClient + - FoundationaLLM-Authorization + - The script will also assign the required permissions to the client apps and the required API permissions to the API apps. - -.REQUIREMENTS - - The user must be a Global Administrator in the Entra ID tenant or have RBAC rights to create App Registrations and Service Principals. - - The Azure CLI must be installed and authenticated to the Entra ID tenant. - - Scaffolding JSON files must be present in the same directory as the script. - - foundationallm-authorization-api.template.json - - foundationallm-core-api.template.json - - foundationallm-core-portal.template.json - - foundationallm-management-api.template.json - - foundationallm-management-portal.template.json + URLs for the client apps are optional and can be set using the appUrl and appUrlLocal parameters. .PARAMETER appPermissionsId The GUID of the permission to assign to the client app. @@ -35,53 +36,24 @@ The URL of the client app. The local URL of the client app. .PARAMETER createClientApp -If set to $true, the script will create a client app. If set to $false, the script will not create a client app. - -.PARAMETER fllmApi -The name of the API app. - -.PARAMETER fllmApiConfigPath -The path to the API app configuration file. - -.PARAMETER fllmApiUri -The URI of the API app. - -.PARAMETER fllmClient -The name of the client app. - -.PARAMETER fllmClientConfigPath -The path to the client app configuration file. - +Whether to create the client app or not. Default is true. False will only create the API app. .EXAMPLE The following example creates the FoundationaLLM API and client apps. # Create FoundationaLLM Core App Registrations $params = @{ + fllmApi = "FoundationaLLM" + fllmClient = "FoundationaLLM-Client" + fllmApiConfigPath = "foundationalllm.json" + fllmClientConfigPath = "foundationalllm-client.json" appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" appUrl = "" appUrlLocal = "http://localhost:3000/signin-oidc" - fllmApi = $coreAppName - fllmApiConfigPath = "foundationallm-core-api.json" - fllmApiUri = "api://FoundationaLLM-Core" - fllmClient = $coreClientAppName - fllmClientConfigPath = "foundationallm-core-portal.json" } -$($fllmAppRegs).Core = New-FllmEntraIdApps @params +New-FllmEntraIdApps @params #> - -Param( - [parameter(Mandatory = $false)][string]$authAppName="FoundationaLLM-Authorization-API", - [parameter(Mandatory = $false)][string]$coreAppName="FoundationaLLM-Core-API", - [parameter(Mandatory = $false)][string]$coreClientAppName="FoundationaLLM-Core-Portal", - [parameter(Mandatory = $false)][string]$mgmtAppName="FoundationaLLM-Management-API", - [parameter(Mandatory = $false)][string]$mgmtClientAppName="FoundationaLLM-Management-Portal" -) - -Set-StrictMode -Version 3.0 -$ErrorActionPreference = "Stop" - function New-FllmEntraIdApps { param ( [Parameter(Mandatory = $true)][string]$appPermissionsId, @@ -97,12 +69,12 @@ function New-FllmEntraIdApps { $fllmAppRegMetaData = @{} try { - # Create the FLLM API App Registration + # Create the FLLM APIApp Registration $($fllmAppRegMetaData).Api = @{ Name = $fllmApi Uri = $fllmApiUri } - Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" + Write-Host "Creating EntraID Application Registration named $($fllmAppRegMetaData.Api.Name)" $($fllmAppRegMetaData.Api).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Api.Name) --query appId --output tsv) $($fllmAppRegMetaData.Api).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Api.AppId) --query id --output tsv) az ad sp create --id $($fllmAppRegMetaData.Api.AppId) @@ -110,19 +82,19 @@ function New-FllmEntraIdApps { # Create the FLLM ClientApp Registration if ($createClientApp) { $($fllmAppRegMetaData).Client = @{ Name = $fllmClient } - Write-Host -ForegroundColor Yellow "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" + Write-Host "Creating EntraID Application Registration named $($fllmAppRegMetaData.Client.Name)" $($fllmAppRegMetaData.Client).AppId = $(az ad app create --display-name $($fllmAppRegMetaData.Client.Name) --query appId --output tsv) $($fllmAppRegMetaData.Client).ObjectId = $(az ad app show --id $($fllmAppRegMetaData.Client.AppId) --query id --output tsv) az ad sp create --id $($fllmAppRegMetaData.Client.AppId) } - # Update the API App Registration - Write-Host -ForegroundColor Yellow "Laying down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" + # Update the APIApp Registration + Write-Host "Lays down scaffolding for the API App Registration $($fllmAppRegMetaData.Api.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$fllmApiConfigPath" - Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." + Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." Start-Sleep -Seconds 10 ## Updates the API App Registration - Write-Host -ForegroundColor Yellow "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" + Write-Host "Preparing updates for the API App Registration $($fllmAppRegMetaData.Api.Name)" $appConfig = Get-content $fllmApiConfigPath | ConvertFrom-Json -Depth 20 if ($createClientApp) { $preAuthorizedApp = @( @@ -139,25 +111,25 @@ function New-FllmEntraIdApps { } $appConfig.identifierUris = @($($fllmAppRegMetaData.Api.Uri)) $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host -ForegroundColor Yellow "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" + Write-Host "Final Update to API App Registration $($fllmAppRegMetaData.Api.Name)" Set-Content -Path "$($fllmAppRegMetaData.Api.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Api.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Api.Name)`.json" - # Update the Client App Registration + # Update the ClientApp Registration if ($createClientApp) { - Write-Host -ForegroundColor Yellow "Lay down scaffolding for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host "Lay down scaffolding for the ClientApp Registration $($fllmAppRegMetaData.Client.Name)" az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$fllmClientConfigPath" Start-Sleep -Seconds 10 - Write-host -ForegroundColor Yellow "Sleeping for 10 seconds to allow the API App Registration to be created before updating it..." - ## Updates the Client App Registration - Write-Host -ForegroundColor Yellow "Preparing updates for the Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-host "Sleeping for 10 seconds to allow the API App Registration to be created before updating it." + ## Updates the ClientApp Registration + Write-Host "Preparing updates for the API App Registration $($fllmAppRegMetaData.Client.Name)" $($fllmAppRegMetaData.Client).Uri = @("api://$($fllmAppRegMetaData.Client.Name)") $apiPermissions = @(@{"resourceAppId" = $($fllmAppRegMetaData.Client.AppId); "resourceAccess" = @(@{"id" = "$($appPermissionsId)"; "type" = "Scope" }) }, @{"resourceAppId" = "00000003-0000-0000-c000-000000000000"; "resourceAccess" = @(@{"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; "type" = "Scope" }) }) $appConfig = Get-content $fllmClientConfigPath | ConvertFrom-Json -Depth 20 $appConfig.identifierUris = @($($fllmAppRegMetaData.Client.Uri)) $appConfig.requiredResourceAccess = $apiPermissions $appConfigUpdate = $appConfig | ConvertTo-Json -Depth 20 - Write-Host -ForegroundColor Yellow "Final Update to Client App Registration $($fllmAppRegMetaData.Client.Name)" + Write-Host "Final Update to ClientApp Registration $($fllmAppRegMetaData.Client.Name)" Set-Content -Path "$($fllmAppRegMetaData.Client.Name)`.json" $appConfigUpdate az rest --method PATCH --url "https://graph.microsoft.com/v1.0/applications/$($fllmAppRegMetaData.Client.ObjectId)" --header "Content-Type=application/json" --body "@$($fllmAppRegMetaData.Client.Name)`.json" } @@ -172,38 +144,38 @@ function New-FllmEntraIdApps { $fllmAppRegs = @{} # Create FoundationaLLM Core App Registrations $params = @{ + fllmApi = $coreAppName + fllmClient = $coreClientAppName + fllmApiConfigPath = "foundationalllm.json" + fllmApiUri = "api://FoundationaLLM-Core" + fllmClientConfigPath = "foundationalllm-client.json" appPermissionsId = "6da07102-bb6a-421d-a71e-dfdb6031d3d8" appUrl = "" appUrlLocal = "http://localhost:3000/signin-oidc" - fllmApi = $coreAppName - fllmApiConfigPath = "foundationallm-core-api.template.json" - fllmApiUri = "api://FoundationaLLM-Core" - fllmClient = $coreClientAppName - fllmClientConfigPath = "foundationallm-core-portal.template.json" } $($fllmAppRegs).Core = New-FllmEntraIdApps @params # Create FoundationaLLM Management App Registrations $params = @{ + fllmApi = $mgmtAppName + fllmClient = $mgmtClientAppName + fllmApiConfigPath = "foundationalllm-management.json" + fllmApiUri = "api://FoundationaLLM-Management" + fllmClientConfigPath = "foundationalllm-managementclient.json" appPermissionsId = "c57f4633-0e58-455a-8ede-5de815fe6c9c" appUrl = "" appUrlLocal = "http://localhost:3001/signin-oidc" - fllmApi = $mgmtAppName - fllmApiConfigPath = "foundationallm-management-api.template.json" - fllmApiUri = "api://FoundationaLLM-Management" - fllmClient = $mgmtClientAppName - fllmClientConfigPath = "foundationallm-management-portal.template.json" } $($fllmAppRegs).Management = New-FllmEntraIdApps @params # Create FoundationaLLM Authorization App Registration $params = @{ - appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" - createClientApp = $false fllmApi = $authAppName - fllmApiConfigPath = "foundationallm-authorization-api.template.json" + fllmApiConfigPath = "foundationalllm-authorization.json" fllmApiUri = "api://FoundationaLLM-Authorization" + appPermissionsId = "9e313dd4-51e4-4989-84d0-c713e38e467d" + createClientApp = $false } -$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params +$($fllmAppRegs).Authorization = New-FllmEntraIdApps @params Write-Host $($fllmAppRegs | ConvertTo-Json)