diff --git a/.env.example b/.env.example index 77d257e..47504bc 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ -CLIENT_ID= -CLIENT_SECRET= +ENGINE_APP_ID= +ENGINE_APP_SECRET= +UI_APP_ID= TENANT_ID= COSMOS_URL=https://.documents.azure.com COSMOS_KEY= diff --git a/.vscode/settings.json b/.vscode/settings.json index ff30c44..5592767 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "editor.tabSize": 2 + "editor.tabSize": 2, + "editor.detectIndentation": false } \ No newline at end of file diff --git a/deploy/appService.bicep b/deploy/appService.bicep index 1e72aae..93880b4 100644 --- a/deploy/appService.bicep +++ b/deploy/appService.bicep @@ -56,6 +56,7 @@ resource appService 'Microsoft.Web/sites@2021-02-01' = { serverFarmId: appServicePlan.id keyVaultReferenceIdentity: managedIdentityId siteConfig: { + alwaysOn: true linuxFxVersion: 'COMPOSE|${dockerCompose}' acrUseManagedIdentityCreds: true acrUserManagedIdentityID: managedIdentityClientId @@ -77,7 +78,7 @@ resource appService 'Microsoft.Web/sites@2021-02-01' = { value: '@Microsoft.KeyVault(SecretUri=${keyVaultUri}secrets/ENGINE-ID/)' } { - name: 'ENGINE_SECRET' + name: 'ENGINE_APP_SECRET' value: '@Microsoft.KeyVault(SecretUri=${keyVaultUri}secrets/ENGINE-SECRET/)' } { diff --git a/deploy/deploy.ps1 b/deploy/deploy.ps1 index 3554312..98e0f26 100644 --- a/deploy/deploy.ps1 +++ b/deploy/deploy.ps1 @@ -10,331 +10,535 @@ #Requires -Modules @{ ModuleName="Microsoft.Graph"; ModuleVersion="1.9.6"} # Intake and set global parameters -Param( - [Parameter(Mandatory=$true)] - [string]$location="westus3", - [Parameter(Mandatory=$true)] - [string]$namePrefix="ipam", - [Parameter(Mandatory=$false)] - [string]$tags +[CmdletBinding(DefaultParameterSetName = 'Full')] +param( + [Parameter(Mandatory = $true, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $true, + ParameterSetName = 'TemplateOnly')] + [string] + $Location, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'AppsOnly')] + [string] + $UIAppName = 'ipam-ui-app', + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'AppsOnly')] + [string] + $EngineAppName = 'ipam-engine-app', + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'TemplateOnly')] + [string] + $NamePRefix, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'TemplateOnly')] + [hashtable] + $Tags, + + [Parameter(Mandatory = $false, + ParameterSetName = 'TemplateOnly')] + [switch] + $TemplateOnly, + + [Parameter(Mandatory = $false, + ParameterSetName = 'AppsOnly')] + [switch] + $AppsOnly, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'AppsOnly')] + [switch] + $NoConsent, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Full')] + [Parameter(Mandatory = $false, + ParameterSetName = 'AppsOnly')] + [switch] + $SubscriptionScope, + + [Parameter(Mandatory = $true, + ParameterSetName = 'TemplateOnly')] + [ValidateScript({ + if(-Not ($_ | Test-Path) ){ + throw "File or does not exist." + } + if(-Not ($_ | Test-Path -PathType Leaf) ){ + throw "The ParameterFile argument must be a file, folder paths are not allowed." + } + if($_ -notmatch "(\.json)"){ + throw "The file specified in the ParameterFile argument must be of type json." + } + return $true + })] + [System.IO.FileInfo]$ParameterFile ) -$engineApiGuid = New-Guid -$logFile = "./deploy_$(get-date -format `"yyyyMMddhhmmsstt`").log" -$tenantId = (Get-AzContext).Tenant.Id # Set preference variables $ErrorActionPreference = "Stop" -Function validateLocation { - # Validate Azure Region - Write-Host "INFO: Validating Azure Region selected for deployment" -ForegroundColor green - Write-Verbose -Message "Validating Azure Region selected for deployment" - - $validLocations = Get-AzLocation - if ($location -in ($validLocations | Select-Object -ExpandProperty Location)) { - foreach ($l in $validLocations) { - if ($location -eq $l.Location) { - $script:locationName = $l.DisplayName +# Hide Azure PowerShell SDK Warnings +$Env:SuppressAzurePowerShellBreakingChangeWarnings = $true - Write-Host "INFO: Azure Region validated successfully" -ForegroundColor green - Write-Verbose -Message "Azure Region validated successfully" - } - } - } - else { - Write-Host "ERROR: Location provided is not a valid Azure Region!" -ForegroundColor red - exit - - } +# Set Log File Location +$logFile = "./deploy_$(get-date -format `"yyyyMMddhhmmsstt`").log" + +Function Test-Location { + Param( + [Parameter(Mandatory=$true)] + [string]$Location + ) + + $validLocations = Get-AzLocation | Select-Object -ExpandProperty Location + + return $validLocations.Contains($Location) } -Function deployEngineApplication { - $azureSvcMgmtApiPermissionsScope = "user_impersonation" - $azureSvcMgmtAppId ="797f4846-ba00-4fd7-ba43-dac1f8f63013" - $msGraphApiPermissionsScope = "offline_access openid profile User.Read" - $msGraphAppId = "00000003-0000-0000-c000-000000000000" - $engineResourceAccess = [System.Collections.ArrayList]@( +Function Deploy-IPAMApplications { + Param( + [Parameter(Mandatory=$true)] + [string]$EngineAppName, + [Parameter(Mandatory=$true)] + [string]$UIAppName, + [Parameter(Mandatory=$true)] + [string]$TenantId, + [Parameter(Mandatory=$false)] + [bool]$SubscriptionScope + ) + + $uiResourceAccess = [System.Collections.ArrayList]@( + @{ + ResourceAppId = "00000003-0000-0000-c000-000000000000"; # Microsoft Graph + ResourceAccess = @( @{ - ResourceAppId = "00000003-0000-0000-c000-000000000000"; - ResourceAccess = @( - @{ - Id = "7427e0e9-2fba-42fe-b0c0-848c9e6a8182"; - Type = "Scope" - }, - @{ - Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; - Type = "Scope" - }, - @{ - Id = "37f7f235-527c-4136-accd-4a02d197296e"; - Type = "Scope" - }, - @{ - Id = "14dad69e-099b-42c9-810b-d002981feec1"; - Type = "Scope" - } - ) + Id = "37f7f235-527c-4136-accd-4a02d197296e"; # openid + Type = "Scope" }, @{ - ResourceAppId = "797f4846-ba00-4fd7-ba43-dac1f8f63013"; - ResourceAccess = @( - @{ - Id = "41094075-9dad-400e-a0bd-54e686782033"; - Type = "Scope" - } - ) + Id = "14dad69e-099b-42c9-810b-d002981feec1"; # profile + Type = "Scope" + }, + @{ + Id = "7427e0e9-2fba-42fe-b0c0-848c9e6a8182"; # offline_access + Type = "Scope" + }, + @{ + Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; # User.Read + Type = "Scope" + }, + @{ + Id = "06da0dbc-49e2-44d2-8312-53f166ab848a"; # Directory.Read.All + Type = "Scope" } - ) + ) + } + ) - # Create IPAM engine application - Write-Host "INFO: Creating Azure IPAM Engine Service Principal" -ForegroundColor green - Write-Verbose -Message "Creating Azure IPAM Engine Service Principal" - $global:engineApp = New-AzADApplication ` - -DisplayName "ipam-engine-app" ` + $uiWebSettings = @{ + ImplicitGrantSetting = @{ + EnableAccessTokenIssuance = $true + EnableIdTokenIssuance = $true + } + } + + # Create IPAM UI Application + Write-Host "INFO: Creating Azure IPAM UI Application" -ForegroundColor green + Write-Verbose -Message "Creating Azure IPAM UI Application" + $uiApp = New-AzADApplication ` + -DisplayName $UiAppName ` + -SPARedirectUri "https://replace-this-value.azurewebsites.net" ` + -Web $uiWebSettings + + $engineResourceAccess = [System.Collections.ArrayList]@( + @{ + ResourceAppId = "797f4846-ba00-4fd7-ba43-dac1f8f63013"; # Azure Service Management + ResourceAccess = @( + @{ + Id = "41094075-9dad-400e-a0bd-54e686782033"; # user_impersonation + Type = "Scope" + } + ) + } + ) + + $engineApiGuid = New-Guid + + $engineApiSettings = @{ + KnownClientApplication = @( + $uiApp.AppId + ) + Oauth2PermissionScope = @( + @{ + AdminConsentDescription = "Allows the IPAM UI to access IPAM Engine API as the signed-in user." + AdminConsentDisplayName = "Access IPAM Engine API" + Id = $engineApiGuid + IsEnabled = $true + Type = "User" + UserConsentDescription = "Allow the IPAM UI to access IPAM Engine API on your behalf." + UserConsentDisplayName = "Access IPAM Engine API" + Value = "access_as_user" + } + ) + RequestedAccessTokenVersion = 2 + } + + # Create IPAM Engine Application + Write-Host "INFO: Creating Azure IPAM Engine Application" -ForegroundColor green + Write-Verbose -Message "Creating Azure IPAM Engine Application" + $engineApp = New-AzADApplication ` + -DisplayName $EngineAppName ` + -Api $engineApiSettings ` -RequiredResourceAccess $engineResourceAccess - # Update IPAM engine application with API endpoint - Update-AzADApplication -ApplicationId $global:engineApp.AppId -IdentifierUri "api://$($global:engineApp.AppId)" - - # Create IPAM engine service principal - $engineSpn = New-AzADServicePrincipal ` - -ApplicationObject $global:engineApp ` - -Role "Reader" ` - -Scope "/providers/Microsoft.Management/managementGroups/$($tenantId)" + # Update IPAM Engine API endpoint + Write-Host "INFO: Updating Azure IPAM Engine API Endpoint" -ForegroundColor green + Write-Verbose -Message "Updating Azure IPAM UI Engine API Endpoint" + Update-AzADApplication -ApplicationId $engineApp.AppId -IdentifierUri "api://$($engineApp.AppId)" - # Create IPAM engine service principal credential - $global:engineSecret = New-AzADAppCredential -ApplicationObject $global:engineApp -StartDate (Get-Date) -EndDate (Get-Date).AddYears(2) - - Write-Host "INFO: Azure IPAM Engine Application & Service Principal created successfully" -ForegroundColor green - Write-Verbose -Message "Azure IPAM Engine Application & Service Principal created successfully" - - # Instantiate Microsoft Graph service principal object - $msGraphSpn = Get-AzADServicePrincipal ` - -ApplicationId $msGraphAppId - - # Instantiate Azure Service Management service principal object - $azureSvcMgmtSpn = Get-AzADServicePrincipal ` - -ApplicationId $azureSvcMgmtAppId - - # Grant admin consent for Microsoft Graph API permissions assigned to IPAM engine application - Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" - New-MgOauth2PermissionGrant ` - -ResourceId $msGraphSpn.Id ` - -Scope $msGraphApiPermissionsScope ` - -ClientId $engineSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" - - # Grant admin consent for Azure Service Management API permissions assigned to IPAM application - Write-Host "INFO: Granting admin consent for Azure Service Management API permissions assigned to IPAM ENgine Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Azure Service Management API permissions assigned to IPAM Engine Application" - New-MgOauth2PermissionGrant ` - -ResourceId $azureSvcMgmtSpn.Id ` - -Scope $azureSvcMgmtApiPermissionsScope ` - -ClientId $engineSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Azure Service Management API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Azure Service Management API API permissions granted successfully" - -} - -Function deployUiApplication { - $engineApiPermissionsScope = "access_as_user" - $msGraphAppId = "00000003-0000-0000-c000-000000000000" - $msGraphApiPermissionsScope = "Directory.Read.All openid User.Read" - $uiResourceAccess = [System.Collections.ArrayList]@( - @{ - ResourceAppId = "00000003-0000-0000-c000-000000000000"; - ResourceAccess = @( - @{ - Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; - Type = "Scope" - }, - @{ - Id = "37f7f235-527c-4136-accd-4a02d197296e"; - Type = "Scope" - }, - @{ - Id = "06da0dbc-49e2-44d2-8312-53f166ab848a"; - Type = "Scope" - } - ) - }, - @{ - ResourceAppId = $global:engineApp.AppId; - ResourceAccess = @( - @{ - Id = $engineApiGuid; - Type = "Scope" - } - ) - } + $uiEngineApiAccess =@{ + ResourceAppId = $engineApp.AppId + ResourceAccess = @( + @{ + Id = $engineApiGuid + Type = "Scope" + } ) - $uiWebSettings = @{ - ImplicitGrantSetting = @{ - EnableAccessTokenIssuance = $true - EnableIdTokenIssuance = $true - } + } + + $uiResourceAccess.Add($uiEngineApiAccess) | Out-Null + + # Update IPAM UI Application Resource Access + Write-Host "INFO: Updating Azure IPAM UI Application Resource Access" -ForegroundColor green + Write-Verbose -Message "Updating Azure IPAM UI Application Resource Access" + Update-AzADApplication -ApplicationId $uiApp.AppId -RequiredResourceAccess $uiResourceAccess + + $uiObject = Get-AzADApplication -ApplicationId $uiApp.AppId + $engineObject = Get-AzADApplication -ApplicationId $engineApp.AppId + + # Create IPAM UI Service Principal + Write-Host "INFO: Creating Azure IPAM UI Service Principal" -ForegroundColor green + Write-Verbose -Message "Creating Azure IPAM UI Service Principal" + New-AzADServicePrincipal -ApplicationObject $uiObject | Out-Null + + if ($SubscriptionScope) { + $subscriptionId = $(Get-AzContext).Subscription.Id + $scope = "/subscriptions/$subscriptionId" + } else { + $scope = "/providers/Microsoft.Management/managementGroups/$TenantId" + } + + # Create IPAM Engine Service Principal + Write-Host "INFO: Creating Azure IPAM Engine Service Principal" -ForegroundColor green + Write-Verbose -Message "Creating Azure IPAM Engine Service Principal" + New-AzADServicePrincipal -ApplicationObject $engineObject ` + -Role "Reader" ` + -Scope $scope ` + | Out-Null + + # Create IPAM Engine Secret + Write-Host "INFO: Creating Azure IPAM Engine Secret" -ForegroundColor green + Write-Verbose -Message "Creating Azure IPAM Engine Secret" + $engineSecret = New-AzADAppCredential -ApplicationObject $engineObject -StartDate (Get-Date) -EndDate (Get-Date).AddYears(2) + + Write-Host "INFO: Azure IPAM Engine & UI Applications/Service Principals created successfully" -ForegroundColor green + Write-Verbose -Message "Azure IPAM Engine & UI Applications/Service Principals created successfully" + + $appDetails = @{ + UIAppId = $uiApp.AppId + EngineAppId = $engineApp.AppId + EngineSecret = $engineSecret.SecretText + } + + return $appDetails +} + +Function Grant-AdminConsent { + Param( + [Parameter(Mandatory=$true)] + [string]$UIAppId, + [Parameter(Mandatory=$true)] + [string]$EngineAppId + ) + + $uiGraphScopes = [System.Collections.ArrayList]@( + @{ + scopeId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph + scopes = " openid profile offline_access User.Read Directory.Read.All" } + ) - # Create IPAM UI Application - Write-Host "INFO: Creating Azure IPAM UI Application" -ForegroundColor green - Write-Verbose -Message "Creating Azure IPAM UI Application" - $global:uiApp = New-AzADApplication ` - -DisplayName "ipam-ui-app" ` - -Web $uiWebSettings ` - -RequiredResourceAccess $uiResourceAccess + $engineGraphScopes = [System.Collections.ArrayList]@( + @{ + scopeId = "797f4846-ba00-4fd7-ba43-dac1f8f63013" # Azure Service Management + scopes = "user_impersonation" + } + ) - # Create IPAM UI service principal - $uiSpn = New-AzADServicePrincipal -ApplicationObject $global:uiApp + # Get Microsoft Graph Access Token + $accesstoken = (Get-AzAccessToken -Resource "https://graph.microsoft.com/").Token - Write-Host "INFO: Azure IPAM UI Application & Service Principal created successfully" -ForegroundColor green - Write-Verbose -Message "Azure IPAM UI Application & Service Principal created successfully" - - # Instantiate Microsoft Graph service principal object - $msGraphSpn = Get-AzADServicePrincipal ` - -ApplicationId $msGraphAppId + # Connect to Microsoft Graph + Write-Host "INFO: Logging in to Microsoft Graph" -ForegroundColor green + Write-Verbose -Message "Logging in to Microsoft Graph" + Connect-MgGraph -AccessToken $accesstoken | Out-Null - # Instantiate Azure IPAM engine service principal object - $engineSpn = Get-AzADServicePrincipal ` - -ApplicationId $global:engineApp.AppId + # Fetch Azure IPAM UI Service Principal + $uiSpn = Get-AzADServicePrincipal ` + -ApplicationId $UIAppId - # Grant admin consent for Microsoft Graph API permissions assigned to IPAM UI application - Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" + # Fetch Azure IPAM Engine Service Principal + $engineSpn = Get-AzADServicePrincipal ` + -ApplicationId $EngineAppId + + # Grant admin consent for Microsoft Graph API permissions assigned to IPAM UI application + Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" -ForegroundColor Green + Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" + foreach($scope in $uiGraphScopes) { + $msGraphId = Get-AzADServicePrincipal ` + -ApplicationId $scope.scopeId + New-MgOauth2PermissionGrant ` - -ResourceId $msGraphSpn.Id ` - -Scope $msGraphApiPermissionsScope ` - -ClientId $uiSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null + -ResourceId $msGraphId.Id ` + -Scope $scope.scopes ` + -ClientId $uiSpn.Id ` + -ConsentType AllPrincipals ` + | Out-Null + } - Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" + Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green + Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" - # Grant admin consent for Azure Service Management API permissions assigned to IPAM application - Write-Host "INFO: Granting admin consent for Azure IPAM Engine API permissions assigned to IPAM UI Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Azure IPAM Engine API permissions assigned to IPAM UI Application" - New-MgOauth2PermissionGrant ` + # Grant admin consent for Azure Service Management API permissions assigned to IPAM application + Write-Host "INFO: Granting admin consent for Azure Service Management API permissions assigned to IPAM Engine Application" -ForegroundColor Green + Write-Verbose -Message "Granting admin consent for Azure Service Management API permissions assigned to IPAM Engine Application" + New-MgOauth2PermissionGrant ` -ResourceId $engineSpn.Id ` - -Scope $engineApiPermissionsScope ` + -Scope "access_as_user" ` -ClientId $uiSpn.Id ` -ConsentType AllPrincipals ` | Out-Null - Write-Host "INFO: Admin consent for Azure IPAM Engine API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Azure IPAM Engine API API permissions granted successfully" + Write-Host "INFO: Admin consent for Azure Service Management API permissions granted successfully" -ForegroundColor green + Write-Verbose -Message "Admin consent for Azure Service Management API API permissions granted successfully" + # Grant admin consent for Microsoft Graph API permissions assigned to IPAM engine application + Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" -ForegroundColor Green + Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" + foreach($scope in $engineGraphScopes) { + $msGraphId = Get-AzADServicePrincipal ` + -ApplicationId $scope.scopeId + + New-MgOauth2PermissionGrant ` + -ResourceId $msGraphId.Id ` + -Scope $scope.scopes ` + -ClientId $engineSpn.Id ` + -ConsentType AllPrincipals ` + | Out-Null + } + + Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green + Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" } -Function updateEngineApplication { - $engineApiSettings = @{ - KnownClientApplication = @( - $global:uiApp.AppId - ) - Oauth2PermissionScope = @( - @{ - AdminConsentDescription = "Allows the IPAM UI to access IPAM Engine API as the signed-in user." - AdminConsentDisplayName = "Access IPAM Engine API" - Id = $engineApiGuid - IsEnabled = $true - Type = "User" - UserConsentDescription = "Allow the IPAM UI to access IPAM Engine API on your behalf." - UserConsentDisplayName = "Access IPAM Engine API" - Value = "access_as_user" - } - ) - RequestedAccessTokenVersion = 2 - } +Function Save-Parameters { + Param( + [Parameter(Mandatory=$true)] + [string]$UIAppId, + [Parameter(Mandatory=$true)] + [string]$EngineAppId, + [Parameter(Mandatory=$true)] + [string]$EngineSecret + ) - # Update IPAM engine application API settings - Write-Host "INFO: Updating Azure IPAM Engine Application" -ForegroundColor green - Write-Verbose -Message "Updating Azure IPAM Engine Application" - Update-AzADApplication -ApplicationId $global:engineApp.AppId -Api $engineApiSettings + Write-Host "INFO: Populating Bicep parameter file for infrastructure deployment" -ForegroundColor Green + Write-Verbose -Message "Populating Bicep parameter file for infrastructure deployment" - - Write-Host "INFO: Updated Azure IPAM Engine Application successfully" -ForegroundColor green - Write-Verbose -Message "Updated Azure IPAM Engine Application successfully" + # Retrieve JSON object from sample parameter file + $parametersObject = Get-Content main.parameters.example.json | ConvertFrom-Json + # Update Parameter Values + $parametersObject.parameters.uiAppId.value = $UIAppId + $parametersObject.parameters.engineAppId.value = $EngineAppId + $parametersObject.parameters.engineAppSecret.value = $EngineSecret + $parametersObject.parameters = $parametersObject.parameters | Select-Object * -ExcludeProperty namePrefix, tags + + # Output updated parameter file for Bicep deployment + $parametersObject | ConvertTo-Json -Depth 4 | Out-File -FilePath main.parameters.json + + Write-Host "INFO: Bicep parameter file populated successfully" -ForegroundColor green + Write-Verbose -Message "Bicep parameter file populated successfully" } -Function deployBicep { - Write-Host "INFO: Deploying IPAM bicep templates" -ForegroundColor green - Write-Verbose -Message "Deploying bicep templates" +Function Import-Parameters { + Param( + [Parameter(Mandatory=$true)] + [System.IO.FileInfo]$ParameterFile + ) - # Instantiate deployment parameter object - $deploymentParameters = @{ - 'engineAppId' = $global:engineApp.AppId - 'engineAppSecret' = $global:engineSecret.SecretText - 'namePrefix' = $namePrefix - 'uiAppId' = $global:uiApp.AppId - } + Write-Host "INFO: Importing values from Bicep parameters file" -ForegroundColor Green + Write-Verbose -Message "Importing values from Bicep parameters file" - # If tags are defined, add them to deployment parameters object - if ($tags) { - $tagsParameter = $tags | ConvertFrom-Json -AsHashtable - - $deploymentParameters.Add('tags',$tagsParameter) - } + # Retrieve JSON object from sample parameter file + $parametersObject = Get-Content $ParameterFile | ConvertFrom-Json - # Deploy IPAM bicep template - $global:deployment = New-AzSubscriptionDeployment ` + # Read Values from Parameters + $UIAppId = $parametersObject.parameters.uiAppId.value + $EngineAppId = $parametersObject.parameters.engineAppId.value + $EngineSecret = $parametersObject.parameters.engineAppSecret.value + + Write-Host "INFO: Successfully import Bicep parameter values" -ForegroundColor green + Write-Verbose -Message "Successfully import Bicep parameter values" + + $appDetails = @{ + UIAppId = $UIAppId + EngineAppId = $EngineAppId + EngineSecret = $EngineSecret + } + + return $appDetails +} + +Function Deploy-Bicep { + Param( + [Parameter(Mandatory=$true)] + [string]$UIAppId, + [Parameter(Mandatory=$true)] + [string]$EngineAppId, + [Parameter(Mandatory=$true)] + [string]$EngineSecret, + [Parameter(Mandatory=$false)] + [string]$NamePrefix, + [Parameter(Mandatory=$false)] + [hashtable]$Tags + ) + + Write-Host "INFO: Deploying IPAM bicep templates" -ForegroundColor green + Write-Verbose -Message "Deploying bicep templates" + + # Instantiate deployment parameter object + $deploymentParameters = @{ + engineAppId = $EngineAppId + engineAppSecret = $EngineSecret + uiAppId = $UiAppId + } + + if($NamePrefix) { + $deploymentParameters.Add('namePrefix', $NamePrefix) + } + + if($Tags) { + $deploymentParameters.Add('tags', $Tags) + } + + # Deploy IPAM bicep template + $deployment = New-AzSubscriptionDeployment ` -Name "ipamInfraDeploy-$(Get-Date -Format `"yyyyMMddhhmmsstt`")" ` -Location $location ` -TemplateFile main.bicep ` -TemplateParameterObject $deploymentParameters - Write-Host "INFO: IPAM bicep templates deployed successfully" -ForegroundColor green - Write-Verbose -Message "IPAM bicep template deployed successfully" - + Write-Host "INFO: IPAM bicep templates deployed successfully" -ForegroundColor green + Write-Verbose -Message "IPAM bicep template deployed successfully" + + return $deployment } -Function updateUiApplication { - Write-Host "INFO: Updating UI Application with SPA configuration" -ForegroundColor green - Write-Verbose -Message "Updating UI Application with SPA configuration" - - $uiAppId = $global:deployment.Parameters["uiAppId"].Value - $appServiceEndpoint = "https://$($global:deployment.Outputs["appServiceHostName"].Value)" - - # Update UI Application with single-page application configuration - Update-AzADApplication -ApplicationId $uiAppId -SPARedirectUri $appServiceEndpoint - - Write-Host "INFO: UI Application SPA configuration update complete" -ForegroundColor green - Write-Verbose -Message "UI Application SPA configuration update complete" - +Function Update-UIApplication { + Param( + [Parameter(Mandatory=$true)] + [string]$UIAppId, + [Parameter(Mandatory=$true)] + [string]$Endpoint + ) + + Write-Host "INFO: Updating UI Application with SPA configuration" -ForegroundColor green + Write-Verbose -Message "Updating UI Application with SPA configuration" + + $appServiceEndpoint = "https://$Endpoint" + + # Update UI Application with single-page application configuration + Update-AzADApplication -ApplicationId $UIAppId -SPARedirectUri $appServiceEndpoint + + Write-Host "INFO: UI Application SPA configuration update complete" -ForegroundColor green + Write-Verbose -Message "UI Application SPA configuration update complete" } try { - # Connect to Microsoft Graph - $accesstoken = (Get-AzAccessToken -Resource "https://graph.microsoft.com/").Token + if ($PSCmdlet.ParameterSetName -in ('Full', 'AppsOnly')) { + # Fetch Tenant ID + Write-Host "INFO: Fetching Tenant ID from Azure PowerShell SDK" -ForegroundColor green + Write-Verbose -Message "Fetching Tenant ID from Azure PowerShell SDK" + $tenantId = (Get-AzContext).Tenant.Id + } - Connect-MgGraph -AccessToken $accesstoken + if ($PSCmdlet.ParameterSetName -in ('Full', 'TemplateOnly')) { + # Validate Azure Region + Write-Host "INFO: Validating Azure Region selected for deployment" -ForegroundColor green + Write-Verbose -Message "Validating Azure Region selected for deployment" - validateLocation $location + if (Test-Location -Location $Location) { + Write-Host "INFO: Azure Region validated successfully" -ForegroundColor green + Write-Verbose -Message "Azure Region validated successfully" + } else { + Write-Host "ERROR: Location provided is not a valid Azure Region!" -ForegroundColor red + exit + } + } - deployEngineApplication + if ($PSCmdlet.ParameterSetName -in ('Full', 'AppsOnly')) { + $appDetails = Deploy-IPAMApplications ` + -UIAppName $UIAppName ` + -EngineAppName $EngineAppName ` + -TenantId $tenantId ` + -SubscriptionScope $SubscriptionScope - deployUiApplication + if (-not $NoConsent) { + Grant-AdminConsent ` + -UIAppId $appDetails.UIAppId ` + -EngineAppId $appDetails.EngineAppId + } + } - updateEngineApplication + if ($PSCmdlet.ParameterSetName -eq 'AppsOnly') { + Save-Parameters @appDetails + } - deployBicep + if ($PSCmdlet.ParameterSetName -eq 'TemplateOnly') { + $appDetails = Import-Parameters ` + -ParameterFile $ParameterFile + } - updateUiApplication + if ($PSCmdlet.ParameterSetName -in ('Full', 'TemplateOnly')) { + $deployment = Deploy-Bicep @appDetails ` + -NamePrefix $NamePrefix ` + -Tags $Tags + } - Write-Host "INFO: Azure IPAM Solution deployed successfully" -ForegroundColor green - Write-Verbose -Message "Azure IPAM Solution deployed successfully" + if ($PSCmdlet.ParameterSetName -eq 'Full') { + Update-UIApplication ` + -UIAppId $appDetails.UIAppId ` + -Endpoint $deployment.Outputs["appServiceHostName"].Value + } + Write-Host "INFO: Azure IPAM Solution deployed successfully" -ForegroundColor green + Write-Verbose -Message "Azure IPAM Solution deployed successfully" } catch { - $_ | Out-File -FilePath $logFile -Append - Write-Host "ERROR: Unable to deploy Azure IPAM solution due to an exception, see $logFile for detailed information!" -ForegroundColor red - exit - + $_ | Out-File -FilePath $logFile -Append + Write-Host "ERROR: Unable to deploy Azure IPAM solution due to an exception, see $logFile for detailed information!" -ForegroundColor red + exit } diff --git a/deploy/deploy_apps.ps1 b/deploy/deploy_apps.ps1 deleted file mode 100644 index c205f9b..0000000 --- a/deploy/deploy_apps.ps1 +++ /dev/null @@ -1,292 +0,0 @@ -############################################################################################################### -## -## Azure IPAM Application & Service Principal Deployment Script -## -############################################################################################################### - -# Set minimum version requirements -#Requires -Version 7.2 -#Requires -Modules @{ ModuleName="Az"; ModuleVersion="7.5.0"} -#Requires -Modules @{ ModuleName="Microsoft.Graph"; ModuleVersion="1.9.6"} - -# Set global parameters -$engineApiGuid = New-Guid -$logFile = "./deploy_$(get-date -format `"yyyyMMddhhmmsstt`").log" -$tenantId = (Get-AzContext).Tenant.Id - -# Set preference variables -$ErrorActionPreference = "Stop" - -Function deployEngineApplication { - $azureSvcMgmtApiPermissionsScope = "user_impersonation" - $azureSvcMgmtAppId ="797f4846-ba00-4fd7-ba43-dac1f8f63013" - $msGraphApiPermissionsScope = "offline_access openid profile User.Read" - $msGraphAppId = "00000003-0000-0000-c000-000000000000" - $engineResourceAccess = [System.Collections.ArrayList]@( - @{ - ResourceAppId = "00000003-0000-0000-c000-000000000000"; - ResourceAccess = @( - @{ - Id = "7427e0e9-2fba-42fe-b0c0-848c9e6a8182"; - Type = "Scope" - }, - @{ - Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; - Type = "Scope" - }, - @{ - Id = "37f7f235-527c-4136-accd-4a02d197296e"; - Type = "Scope" - }, - @{ - Id = "14dad69e-099b-42c9-810b-d002981feec1"; - Type = "Scope" - } - ) - }, - @{ - ResourceAppId = "797f4846-ba00-4fd7-ba43-dac1f8f63013"; - ResourceAccess = @( - @{ - Id = "41094075-9dad-400e-a0bd-54e686782033"; - Type = "Scope" - } - ) - } - ) - - # Create IPAM engine application - Write-Host "INFO: Creating Azure IPAM Engine Service Principal" -ForegroundColor green - Write-Verbose -Message "Creating Azure IPAM Engine Service Principal" - - $global:engineApp = New-AzADApplication ` - -DisplayName "ipam-engine-app" ` - -RequiredResourceAccess $engineResourceAccess - - # Update IPAM engine application with API endpoint - Update-AzADApplication -ApplicationId $global:engineApp.AppId -IdentifierUri "api://$($global:engineApp.AppId)" - - # Create IPAM engine service principal - $engineSpn = New-AzADServicePrincipal ` - -ApplicationObject $global:engineApp ` - -Role "Reader" ` - -Scope "/providers/Microsoft.Management/managementGroups/$($tenantId)" - - # Create IPAM engine service principal credential - $global:engineSecret = New-AzADAppCredential -ApplicationObject $global:engineApp -StartDate (Get-Date) -EndDate (Get-Date).AddYears(2) - - Write-Host "INFO: Azure IPAM Engine Application & Service Principal created successfully" -ForegroundColor green - Write-Verbose -Message "Azure IPAM Engine Application & Service Principal created successfully" - - # Instantiate Microsoft Graph service principal object - $msGraphSpn = Get-AzADServicePrincipal ` - -ApplicationId $msGraphAppId - - # Instantiate Azure Service Management service principal object - $azureSvcMgmtSpn = Get-AzADServicePrincipal ` - -ApplicationId $azureSvcMgmtAppId - - # Grant admin consent for Microsoft Graph API permissions assigned to IPAM engine application - Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM Engine Application" - - New-MgOauth2PermissionGrant ` - -ResourceId $msGraphSpn.Id ` - -Scope $msGraphApiPermissionsScope ` - -ClientId $engineSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" - - # Grant admin consent for Azure Service Management API permissions assigned to IPAM application - Write-Host "INFO: Granting admin consent for Azure Service Management API permissions assigned to IPAM ENgine Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Azure Service Management API permissions assigned to IPAM Engine Application" - - New-MgOauth2PermissionGrant ` - -ResourceId $azureSvcMgmtSpn.Id ` - -Scope $azureSvcMgmtApiPermissionsScope ` - -ClientId $engineSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Azure Service Management API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Azure Service Management API API permissions granted successfully" - -} - -Function deployUiApplication { - $engineApiPermissionsScope = "access_as_user" - $msGraphAppId = "00000003-0000-0000-c000-000000000000" - $msGraphApiPermissionsScope = "Directory.Read.All openid User.Read" - $uiResourceAccess = [System.Collections.ArrayList]@( - @{ - ResourceAppId = "00000003-0000-0000-c000-000000000000"; - ResourceAccess = @( - @{ - Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; - Type = "Scope" - }, - @{ - Id = "37f7f235-527c-4136-accd-4a02d197296e"; - Type = "Scope" - }, - @{ - Id = "06da0dbc-49e2-44d2-8312-53f166ab848a"; - Type = "Scope" - } - ) - }, - @{ - ResourceAppId = $global:engineApp.AppId; - ResourceAccess = @( - @{ - Id = $engineApiGuid; - Type = "Scope" - } - ) - } - ) - $uiWebSettings = @{ - ImplicitGrantSetting = @{ - EnableAccessTokenIssuance = $true - EnableIdTokenIssuance = $true - } - } - - # Create IPAM UI Application - Write-Host "INFO: Creating Azure IPAM UI Application" -ForegroundColor green - Write-Verbose -Message "Creating Azure IPAM UI Application" - - $global:uiApp = New-AzADApplication ` - -DisplayName "ipam-ui-app" ` - -Web $uiWebSettings ` - -RequiredResourceAccess $uiResourceAccess ` - -SPARedirectUri "https://ipam-placeholder-replace-me.azurewebsites.net" - - # Create IPAM UI service principal - $uiSpn = New-AzADServicePrincipal -ApplicationObject $global:uiApp - - Write-Host "INFO: Azure IPAM UI Application & Service Principal created successfully" -ForegroundColor green - Write-Verbose -Message "Azure IPAM UI Application & Service Principal created successfully" - - # Instantiate Microsoft Graph service principal object - $msGraphSpn = Get-AzADServicePrincipal ` - -ApplicationId $msGraphAppId - - # Instantiate Azure IPAM engine service principal object - $engineSpn = Get-AzADServicePrincipal ` - -ApplicationId $global:engineApp.AppId - - # Grant admin consent for Microsoft Graph API permissions assigned to IPAM UI application - Write-Host "INFO: Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Microsoft Graph API permissions assigned to IPAM UI Application" - - New-MgOauth2PermissionGrant ` - -ResourceId $msGraphSpn.Id ` - -Scope $msGraphApiPermissionsScope ` - -ClientId $uiSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Microsoft Graph API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Microsoft Graph API permissions granted successfully" - - # Grant admin consent for Azure Service Management API permissions assigned to IPAM application - Write-Host "INFO: Granting admin consent for Azure IPAM Engine API permissions assigned to IPAM UI Application" -ForegroundColor Green - Write-Verbose -Message "Granting admin consent for Azure IPAM Engine API permissions assigned to IPAM UI Application" - - New-MgOauth2PermissionGrant ` - -ResourceId $engineSpn.Id ` - -Scope $engineApiPermissionsScope ` - -ClientId $uiSpn.Id ` - -ConsentType AllPrincipals ` - | Out-Null - - Write-Host "INFO: Admin consent for Azure IPAM Engine API permissions granted successfully" -ForegroundColor green - Write-Verbose -Message "Admin consent for Azure IPAM Engine API API permissions granted successfully" - -} - -Function updateEngineApplication { - $engineApiSettings = @{ - KnownClientApplication = @( - $global:uiApp.AppId - ) - Oauth2PermissionScope = @( - @{ - AdminConsentDescription = "Allows the IPAM UI to access IPAM Engine API as the signed-in user." - AdminConsentDisplayName = "Access IPAM Engine API" - Id = $engineApiGuid - IsEnabled = $true - Type = "User" - UserConsentDescription = "Allow the IPAM UI to access IPAM Engine API on your behalf." - UserConsentDisplayName = "Access IPAM Engine API" - Value = "access_as_user" - } - ) - RequestedAccessTokenVersion = 2 - } - - # Update IPAM engine application API settings - Write-Host "INFO: Updating Azure IPAM Engine Application" -ForegroundColor green - Write-Verbose -Message "Updating Azure IPAM Engine Application" - - Update-AzADApplication -ApplicationId $global:engineApp.AppId -Api $engineApiSettings - - Write-Host "INFO: Updated Azure IPAM Engine Application successfully" -ForegroundColor green - Write-Verbose -Message "Updated Azure IPAM Engine Application successfully" - -} - -Function populateBicepParameters { - Write-Host "INFO: Populating Bicep parameter file for infrastructure deployment" -ForegroundColor Green - Write-Verbose -Message "Populating Bicep parameter file for infrastructure deployment" - - # Retrieve JSON object from sample parameter file - $parametersObject = Get-Content main.parameters.example.json | ConvertFrom-Json - - # update parameter values - $parametersObject.parameters.engineAppId.value = $global:engineApp.AppId - - $parametersObject.parameters.engineAppSecret.value = $global:engineSecret.SecretText - - $parametersObject.parameters.uiAppId.value = $global:uiApp.AppId - - # Output updated parameter file for Bicep deployment - $parametersObject | ConvertTo-Json -Depth 3 | Out-File -FilePath main.parameters.json - - Write-Host "INFO: Bicep parameter file populated successfully" -ForegroundColor green - Write-Verbose -Message "Bicep parameter file populated successfully" -} - -try { - # Connect to Microsoft Graph - $accesstoken = (Get-AzAccessToken -Resource "https://graph.microsoft.com/").Token - - Connect-MgGraph -AccessToken $accesstoken - - deployEngineApplication - - deployUiApplication - - updateEngineApplication - - populateBicepParameters - - Write-Host "INFO: IPAM Engine Application Deployment Complete" -ForegroundColor Green - Write-Host "INFO: IPAM Engine Application Display Name: $($global:engineApp.DisplayName)" -ForegroundColor Green - Write-Host "INFO: IPAM Engine Application ID: $($global:engineApp.AppId)" -ForegroundColor Green - Write-Host "INFO: IPAM Engine Application Secret: $($global:engineSecret.SecretText)" -ForegroundColor Green - Write-Host "INFO: IPAM UI Application Deployment Complete" -ForegroundColor Green - Write-Host "INFO: IPAM UI Application Display Name: $($global:uiApp.DisplayName)" -ForegroundColor Green - Write-Host "INFO: IPAM UI Application ID: $($global:uiApp.AppId)" -ForegroundColor Green - -} -catch { - $_ | Out-File -FilePath $logFile -Append - Write-Host "ERROR: Unable to create Azure IPAM Applications due to an exception, see $logFile for detailed information!" -ForegroundColor red - exit - -} diff --git a/deploy/deploy_bicep.ps1 b/deploy/deploy_bicep.ps1 deleted file mode 100644 index 0b244a5..0000000 --- a/deploy/deploy_bicep.ps1 +++ /dev/null @@ -1,74 +0,0 @@ -############################################################################################################### -## -## Azure IPAM Infrastructure Deployment Script -## -############################################################################################################### - -# Set minimum version requirements -#Requires -Version 7.2 -#Requires -Modules @{ ModuleName="Az"; ModuleVersion="7.5.0"} - -# Intake and set global parameters -Param( - [Parameter(Mandatory=$true)] - [string] - $location="westus3" -) -$logFile = "./deploy_$(Get-Date -Format `"yyyyMMddhhmmsstt`").log" - -# Set preference variables -$ErrorActionPreference = "Stop" - -Function validateLocation { - $validLocations = Get-AzLocation - - Write-Host "INFO: Validating Azure Region selected for deployment" -ForegroundColor green - Write-Verbose -Message "Validating Azure Region selected for deployment" - - # Validate Azure Region - if ($location -in ($validLocations | Select-Object -ExpandProperty Location)) { - foreach ($l in $validLocations) { - if ($location -eq $l.Location) { - $script:locationName = $l.DisplayName - - Write-Host "INFO: Azure Region validated successfully" -ForegroundColor green - Write-Verbose -Message "Azure Region validated successfully" - } - } - } - else { - Write-Host "ERROR: Location provided is not a valid Azure Region!" -ForegroundColor red - exit - - } -} - -Function deployBicep { - Write-Host "INFO: Deploying IPAM bicep templates" -ForegroundColor green - Write-Verbose -Message "Deploying bicep templates" - - # Deploy Bicep templates - $global:deployment = New-AzSubscriptionDeployment ` - -Name "ipamInfraDeploy-$(Get-Date -Format `"yyyyMMddhhmmsstt`")" ` - -Location $location ` - -TemplateFile main.bicep ` - -TemplateParameterFile main.parameters.json - - Write-Host "INFO: IPAM bicep templates deployed successfully" -ForegroundColor green - Write-Verbose -Message "IPAM bicep templates deployed successfully" -} - -try { - validateLocation $location - - deployBicep - - Write-Host "WARNING: Remember to update Single-Page Application Redirect URI for UI Application with value: https://$($global:deployment.Outputs["appServiceHostName"].Value)" -ForegroundColor yellow - Write-Verbose -Message "Remember to update Single-Page Application Redirect URI for UI Application with value: https://$($global:deployment.Outputs["appServiceHostName"].Value)" -} -catch { - $_ | Out-File -FilePath $logFile -Append - Write-Host "ERROR: Unable to deploy IPAM Infrastructure due to an exception, see $logFile for detailed information!" -ForegroundColor red - exit - -} diff --git a/deploy/main.bicep b/deploy/main.bicep index b8a23f8..4fddefb 100644 --- a/deploy/main.bicep +++ b/deploy/main.bicep @@ -8,7 +8,7 @@ param guid string = newGuid() param location string = deployment().location @description('Prefix for Resource Naming') -param namePrefix string +param namePrefix string = 'ipam' @description('IPAM-UI App Registration Client/App ID') param uiAppId string @@ -21,7 +21,7 @@ param engineAppId string param engineAppSecret string @description('Tags') -param tags object +param tags object = {} // Resource naming variables var appServiceName = '${namePrefix}-${uniqueString(guid)}' diff --git a/deploy/main.parameters.example.json b/deploy/main.parameters.example.json index 7d0b882..75ba28a 100644 --- a/deploy/main.parameters.example.json +++ b/deploy/main.parameters.example.json @@ -3,7 +3,7 @@ "contentVersion": "1.0.0.0", "parameters": { "namePrefix": { - "value": "ipam" + "value": "" }, "tags": { "value": { diff --git a/deploy/storageAccount.bicep b/deploy/storageAccount.bicep index 2900736..ff263a2 100644 --- a/deploy/storageAccount.bicep +++ b/deploy/storageAccount.bicep @@ -47,7 +47,7 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-prev } resource copyNginxConfig 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: 'exampleScript' + name: 'copyNginxConfig' location: location kind: 'AzurePowerShell' identity: { diff --git a/engine/app/routers/user.py b/engine/app/routers/user.py index 90675f8..fd7af05 100644 --- a/engine/app/routers/user.py +++ b/engine/app/routers/user.py @@ -140,7 +140,10 @@ async def get_user( admins = await cosmos_query("admins") - is_admin = next((x for x in admins['admins'] if x['id'] == target_user['id']), None) + if admins['admins']: + is_admin = next((x for x in admins['admins'] if x['id'] == target_user['id']), None) + else: + is_admin = True target_user['isAdmin'] = True if is_admin else False diff --git a/ui/src/features/drawer/drawer.js b/ui/src/features/drawer/drawer.js index ca70fe3..e07f396 100644 --- a/ui/src/features/drawer/drawer.js +++ b/ui/src/features/drawer/drawer.js @@ -130,6 +130,7 @@ export default function NavDrawer() { const [menuAnchorEl, setMenuAnchorEl] = React.useState(null); const [mobileMenuAnchorEl, setMobileMenuAnchorEl] = React.useState(null); const [graphData, setGraphData] = React.useState(null); + const [graphError, setGraphError] = React.useState(false); const [navChildOpen, setNavChildOpen] = React.useState({}); const [drawerState, setDrawerState] = React.useState(false); const [settingsOpen, setSettingsOpen] = React.useState(false); @@ -221,19 +222,29 @@ export default function NavDrawer() { ]; React.useEffect(() => { - const request = { - // ...loginRequest, - scopes: ["User.Read"], - account: accounts[0], - forceRefresh: true, - }; + let graphTimer = setTimeout(() => { + const request = { + // ...loginRequest, + scopes: ["User.Read"], + account: accounts[0], + forceRefresh: true, + }; + + (async() => { + try { + const response = await instance.acquireTokenSilent(request); + const graphResponse = await callMsGraph(response.accessToken); + await setGraphData(graphResponse); + } catch { + setGraphError(x => !x); + } + })(); + }, 5000); - (async() => { - const response = await instance.acquireTokenSilent(request); - const graphResponse = await callMsGraph(response.accessToken); - await setGraphData(graphResponse); - })(); - }, []); + return () => { + clearTimeout(graphTimer); + }; + }, [graphError]); // React.useEffect(() => { // const request = { diff --git a/ui/src/features/login/Login.js b/ui/src/features/login/Login.js index 8daa859..7aae7c5 100644 --- a/ui/src/features/login/Login.js +++ b/ui/src/features/login/Login.js @@ -23,6 +23,15 @@ const Login = () => { } }, [isAuthenticated, inProgress, instance]); + // React.useEffect(() => { + // instance.loginRedirect(loginRequest).catch((e) => { + // console.log("LOGIN ERROR:"); + // console.log("--------------"); + // console.error(e); + // console.log("--------------"); + // }); + // }, []); + return(null) };