# Azure Resources
## Requirements
The following resources are required for a production environment.
| Type | Description |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| App Service |
A virtual Azure environment to run the Unified Contacts application backend, providing a UI to configure different
application specific settings like CNAME, SSL certificate and App Settings.
|
| App Service Plan | A virtual set of compute resources and configurations for the "App Service".
Here you can configure the pricing tier and resource scaling.
|
| Key Vault | Resource to securely store secrets and certificates. Unified Contacts leverages Key Vault to store API client secrets. |
| Storage account | Storage platform that stores the binaries of the Unified Contacts backend application. |
| SQL database | Relational database used by Unified Contacts to store persistent information such as custom settings and pinned favorites. |
| SQL server | A virtual set of compute resources and configurations for the "SQL database". |
## Run the deployment template
Log in with an Entra administrator account and click the following deployment link:
* [Production channel](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Funifiedcontacts.blob.core.windows.net%2Farm-templates%2FarmDeployment.json)
This will invoke the ARM-deployment-template that is pre-populated with default values. In the default configuration, partly-random resource names will be generated based on the **Resource group** ID.
> [!NOTE]
> In case you have resource naming conventions, you may override the default resource names to match your requirements.
* **Subscription:** Select your subscription, where you have permissions to create app services, app service plans, key vaults, storage accounts, SQL databases and SQL servers
* **Resource group:** Select an existing resource group or create a new one. The Unified Contacts resources will be deployed to this resource group
* **Region:** Select the region according to your location preferences
* **Key Vault Name**: Keep the default value or define a custom but globally unique value
> [!NOTE]
> In case you have previously deployed Unified Contacts with the same **Key Vault Name**, and deleted all resources of the previous deployment, make sure to [purge](https://docs.microsoft.com/en-us/azure/key-vault/general/key-vault-recovery?tabs=azure-cli#key-vault-cli) the previously deleted Key Vault. By default, upon deletion, the Key Vault will remain in [soft-delete](https://docs.microsoft.com/en-us/azure/key-vault/general/soft-delete-overview) state for 90 days, essentially blocking the creation of a new Key Vault with the same name.
* **Storage Account Name**: Keep the default value or define a custom but globally unique value.
> [!WARNING]
> The **Storage Account Name** value must only contain numbers and/or lowercase letters.
* **Server Name**: Keep the default value or define a custom but globally unique value for the SQL server.
> [!WARNING]
> The **Server Name** value must only contain numbers and/or lowercase letters and/or hyphens (not leading or trailing).
* **Sql DB Name**: Keep the default value or define a custom value
* **Administrator Login**: Define a username as part of an administrative access account for the SQL database
* **Administrator Login Password**: Define a password for the administrative access account for the SQL database. Store this password in your password vault.
* **Sharepoint Url**: Domain of your organizations root Sharepoint Online site **without** 'https://'. Typically: `.sharepoint.com`
* **App Service Plan Name**: Keep the default value or define a custom but globally unique value
* **App Service Name**: Keep the default value or define a custom but globally unique value
* **App Registration Name Admin Page**: Keep the default value or define a custom value
* **App Registration Name Teams App**: Keep the default value or define a custom value
# Configuration Steps
## Step 1: Deploy Unified Contacts Base Services
> [!WARNING]
> This is a **mandatory** step.
To start with the deployment, follow our setup instructions:
[Deployment Guide](#deployment-of-azure-resources)
## Step 2: Custom Domain
> [!NOTE]
> This is an **optional** step.
To configure a custom domain for the Unified Contacts backend, follow this guide:
[Custom Domain](ADVANCED-CONFIGURATION.md#custom-domain)
## Step 3: Perform Post-Deployment Steps (Permission Assignments)
> [!WARNING]
> This is a **mandatory** step.
To properly link all components of Unified Contacts, several permissions need to be assigned. Please follow these steps to establish the relevant connections:
1. Navigate to the Unified Contacts backend website. For that, navigate to the Unified Contacts **App Service**, select **Overview** and click **Browse**.
2. Copy the content of the black box to your clipboard and paste it into a text editor.
3. Now you need to replace the `AppServiceAzureUrl` with the correct URL from your Unified Contacts **App Service**. Therefore
a. Navigate to the Unified Contacts **App Service Overview** blade.
b. Copy the URL from your browser and replace the `AppServiceAzureUrl` argument value in the text editor with this URL.
4. Copy all commands from the text editor, open the **Azure Cloud Shell** (Power Shell) on **Azure Portal** and paste the commands.
5. During the script execution, you will be prompted for the SQL server administration account. Please provide the credentials you specified during the deployment in the ARM template.
6. If you have previously configured a **Custom domain** on the Unified Contacts **App Service**, the script will prompt you for the correct **App Service URL**. Please select the custom domain.
7. Towards the end of the script, you will be asked to grant the permissions (**read-only**) required for the Unified Contacts front- and backend to function properly. Please consent to those permissions by
a. Either copying **both** links to your browser and acknowledging the grants manually with a suitable admin account,
b. **Or** by selecting to the **Automatic Permission Grant**. In this case, please complete the **Device Login** by opening the website [https://microsoft.com/devicelogin](https://microsoft.com/devicelogin), pasting the one-time code displayed in the Azure Cloud Shell, and following all steps.
8. Once the script has completed successfully, **restart** the Unified Contacts **App Service**.
9. To verify the successful deployment, navigate to the Unified Contacts **App Service**, select **Overview** and click **Browse**. The health indicators on the left side should all indicate **Healthy**.
> [!NOTE]
> It may initially take up to 10 **minutes** until the Unified Contacts backend portal is loaded.
## Step 4: Configure Access to the Unified Contacts Backend
> [!NOTE]
> This is an **optional** step.
By default, any account from the tenant can access the Unified Contacts Backend. To configure access for certain accounts only, please refer to below article.
[Backend Permissions Guide](ADVANCED-CONFIGURATION.md#backend-permissions)
## Step 5: Add Unified Contacts to your Organization's App Store
> [!WARNING]
> This is a **mandatory** step.
1. Open the Unified Contacts backend website. Therefore, navigate to the Unified Contacts **App Service**, select **Overview** and click **Browse**.
2. In case you have never deployed Unified Contacts before, the website will inform you that you first need to upload the Unified Contacts Manifest. This will make the Unified Contacts Teams App available in your organization's AppStore.
3. Acknowledge the dialogue, navigate to the **Teams Manifest** tab, adapt the manifest to your preferences, click **Save** and then **Upload**. If you have configured a **custom domain**, remeber to **override** the **Api Domain** in the manifest. **Uploading the manifest** **might take a few moments**.
Please note: You can even change the display name of the app that will appear under the icon in the end-users' Teams client.
4. The Unified Contacts Teams app is now available in [**Teams Admin Center**](https://admin.teams.microsoft.com/) and you may distribute it as per your requirements.
## Step 6: Import Contacts from 3rd Party Sources and CRM Systems
> [!NOTE]
> This is an **optional** step.
You may import contacts from 3rd party contact sources or CRM systems by leveraging the UC Database
[UC Database](ADVANCED-CONFIGURATION.md#uc-database)
or SharePoint Online Lists:
[SharePoint Online Lists](ADVANCED-CONFIGURATION.md#sharepoint-online-lists)
# Install Unified Contacts
This document shows how to make the UnifiedContactsPS PowerShell module available in the Azure Portal PowerShell terminal (Cloud Shell) so you can start Cloud Shell in the portal and use the module.
## Prerequisites
- A packaged module folder named `UnifiedContactsPS` containing the module files (.psd1, .psm1, etc.).
- Azure subscription and access to the Azure Portal.
## Prepare the module locally
Compress the module folder into a zip file for upload:
```
Compress-Archive -Path .\UnifiedContactsPS -DestinationPath UnifiedContactsPS.zip -Force
```
## Method A - Upload directly from the portal (recommended)
1. Open the Azure Portal and launch Cloud Shell → choose PowerShell.
2. Click the Upload/Download (↑↓) icon in the Cloud Shell toolbar and upload `UnifiedContactsPS.zip`.
3. In Cloud Shell run:
### Create persistent module path
```
New-Item -ItemType Directory -Force -Path $HOME/Documents/PowerShell/Modules
```
### Unzip into the persistent modules folder
```
Expand-Archive -Path "$HOME/UnifiedContactsPS.zip" -DestinationPath "$HOME/Documents/PowerShell/Modules"
```
### Import and verify
```
Import-Module UnifiedContactsPS
Get-Module -ListAvailable | Where-Object { $_.Name -eq 'UnifiedContactsPS' }
```
> [!NOTE]
> - Files under $HOME persist across Cloud Shell sessions because $HOME is mounted on an Azure Files share.
> - If your zip contains versioned subfolders (e.g. UnifiedContactsPS/1.0.0/), PowerShell will find the module automatically.
## Method B - Upload to storage and download in Cloud Shell
1. Upload `UnifiedContactsPS.zip` to an Azure storage container (Portal or az CLI).
2. Get a blob URL or SAS URL.
3. In Cloud Shell run:
```
Invoke-WebRequest -Uri "" -OutFile "$HOME/UnifiedContactsPS.zip"
```
```
New-Item -ItemType Directory -Force -Path $HOME/Documents/PowerShell/Modules
Expand-Archive -Path "$HOME/UnifiedContactsPS.zip" -DestinationPath "$HOME/Documents/PowerShell/Modules"
```
```
Import-Module UnifiedContactsPS
Get-Module -ListAvailable | Where-Object { $_.Name -eq 'UnifiedContactsPS' }
```
## Verify and use
- List commands exported by the module:
```
Get-Command -Module UnifiedContactsPS
```
- During development, remove and re-import:
```
Remove-Module UnifiedContactsPS -ErrorAction SilentlyContinue
Import-Module "$HOME/Documents/PowerShell/Modules/UnifiedContactsPS"
```
## Troubleshooting
- Ensure the folder name matches the module manifest's ModuleToProcess/RootModule entry.
- Confirm the .psd1 has valid ModuleVersion and PowerShellVersion requirements.
- If Import-Module fails, check that files are readable under $HOME in Cloud Shell.
Place this file in your wiki or documentation folder; once the zip is uploaded to Cloud Shell's $HOME/Documents/PowerShell/Modules path the module is ready to import whenever you open the Azure Portal PowerShell
## Use the module for installation
### Parameters
#### 1. `AppServiceAzureUrl` (Mandatory)
- **Description**: The URL of the Azure App Service.
- **Format**: `https://portal.azure.com/#/resource/subscriptions//resourceGroups//providers/Microsoft.Web/sites//appServices`
- **Example**: `https://portal.azure.com/#Microsoft_Azure_Resource/subscriptions/12345/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/MyAppService/appServices`
#### 2. `SqlCredential` (Mandatory)
- **Description**: The SQL user credentials (username and password).
- **Type**: `PSCredential`
- **Example**:
```powershell
$sqlCredential = Get-Credential
```
### Notes
- Ensure you have the necessary permissions to access the Azure resources and SQL Server.
- The `SqlCredential` parameter must be a valid `PSCredential` object.
- The `AppServiceAzureUrl` must point to the correct Azure App Service resource.
### Example Usage
```powershell
Install-UnifiedContacts -AppServiceAzureUrl "https://portal.azure.com/#Microsoft_Azure_Resource/subscriptions/12345/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/MyAppService/appServices" -SqlCredential (Get-Credential)
```
# Unified Contacts Uninstall
To uninstall Unified Contacts from your tenant, please go through the following steps:
## Step 1: Uninstall Teams App (Front-end)
To remove the Unified Contacts Teams App (front end)
* Open the [**Teams Admin Center**](https://admin.teams.microsoft.com/) and navigate to "Teams apps" --> "Manage apps" and locate the Unified Contacts app.
* Open the app, click on the three dots subsequently to "Actions" --> "Delete"
## Step 2: Uninstall the Unified Contacts Backend
To remove the Unified Contacts backend including all **App registrations**
* Invoke the **Azure Cloud Shell** and paste the following command (powershell):
```
Install-Module UnifiedContactsPS
Uninstall-UnifiedContacts
```
* You will be prompted for the "AppServiceAzureUrl". Get this URL by navigating to the Unified Contacts **App Service** "Overview" blade. Then, copy the URL from your browser and paste it into the **Azure Cloud Shell** and press **Enter**.
* Confirm that you would like to delete the Unified Contacts **Resource group**.
* Once the script has completed (**this might take up to 5 minutes**), all Unified Contacts resources are removed from your Azure tenant.