Tim D'Annecy

tdannecy@gmail.com Header image

#Azure

After setting up RedCap in Azure in a previous post, I got a request to add an external person to your RedCap installation. I wanted to document what I did to make it easier for others.

To make user management easier, I created an Assigned Security Group in Azure AD titled “RedCap Users”. I then added the Group assignment to the RedCap app in Azure AD at Enterprise applications > RedCap > Users and groups > Add user/group:

Screenshot of Azure AD Enterprise Applications, Users and groups blade

After I assigned the Group to the app, I invited my external Gmail account to the Azure AD tenant at Users > New user > Invite external user:

Screenshot of Azure AD, new user create button

I added my user information, then added the account to the RedCap users group: Screenshot of Azure AD New User invite, Groups pane

After I added the account, I needed to change the setting in Azure AD to allow external Microsoft accounts to access Redcap. To do this, I needed to change the App Registration Manifest, found in Azure AD > App registrations > RedCap > Manifest.

I changed 2 values from the default:

  • "accessTokenAcceptedVersion": Null,"accessTokenAcceptedVersion": 2,
  • "signInAudience": "AzureADMyOrg","signInAudience": "AzureADandPersonalMicrosoftAccount",

Screenshot of Azure AD App, Manifest file Screenshot of Azure AD App, Manifest file

After making these changes, I checked my email and completed the invitation to the Azure AD tenant:

Screenshot of an email from Azure AD inviting a user to a tenant

After going through the signup process, I see the App listed in the My Apps page for my Guest account: Screenshot of Microsoft My Apps page

After clicking through, I was able to setup my RedCap account and was authorized to login:

Screenshot of RedCap Basic User Information Form Screenshot of RedCap Account created notification

My RedCap user account shows up as my email at tdannecy_gmail.com#ext#@DOMAIN.onmicrosoft.com, indicating that I am a Guest/External account in the tenant:

Screenshot of RedCap login information

When I login as a RedCap administrator, I can see my Guest account has been added to the Browse Users list:

Screenshot of RedCap Browse Users page

I hope this was helpful to others. It took me a bit to find the attribute I needed to change in the Manifest to get it working.

Discuss...

#Windows #Intune

A company I'm working with requested an Application Deployment of Word LTSC using a Multiple Activation Key (MAK) purchased through Volume Licensing in their Intune/Endpoint environment.

To deploy Office LTSC, I needed to have the MAK key in hand before starting this process, as you'll need it when zipping up the .intunewin package.

To keep things clean, I'm building my package at C:\temp\package

Create an XML configuration for installation using the Office Customization Tool

Open the Office Customization Tool page and begin defining your settings for deployment:

Screenshot of the Office Customization Tool

  • Products and releases
    • Architecture: 64-bit
    • Products: Select the products that you want to deploy.
    • Office Suites: I selected Office LTSC Standard 2021 - Volume License
    • Update Channel:
    • Select the update channel: Office LTSC 2021 Perpetual Enterprise
  • Language
  • Installation
    • Installation options
    • Where do you want to deploy Office from? Office Content Delivery Network (CDN)
    • Show installation to user: Off
    • Shut down running applications: Off
  • Update and upgrade
    • Update and upgrade options
    • Where do you want to deploy updates from? Office Content Delivery Network (CDN)
    • Automatically check for updates On
    • Upgrade options
    • Uninstall any MSI versions of Office, including Visio and Project Off
    • For uninstalled MSI versions of Office, install the same languages Off
    • Automatically upgrade to the selected architecture On
  • Licensing and activation
    • Automatically accept the EULA On
    • Product Key
    • Office LTSC Standard 2021 – Volume License MAK and paste in your 25-character key value here.
    • Product activation
    • User based
  • General
    • Customize as needed.
  • Application preferences
    • Customize as needed.

Save this XML file at C:\temp\package\install.xml

Here is the contents of my file to just install Word and allow regular updating:

<Configuration ID="f42ea3d0-d7a4-46bf-8a49-594df9549b6f">
  <Add OfficeClientEdition="64" Channel="PerpetualVL2021" MigrateArch="TRUE">
    <Product ID="Standard2021Volume" PIDKEY="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX">
      <Language ID="en-us" />
      <ExcludeApp ID="Excel" />
      <ExcludeApp ID="OneDrive" />
      <ExcludeApp ID="OneNote" />
      <ExcludeApp ID="Outlook" />
      <ExcludeApp ID="PowerPoint" />
      <ExcludeApp ID="Publisher" />
      <ExcludeApp ID="Teams" />
    </Product>
  </Add>
  <Property Name="SharedComputerLicensing" Value="0" />
  <Property Name="FORCEAPPSHUTDOWN" Value="FALSE" />
  <Property Name="DeviceBasedLicensing" Value="0" />
  <Property Name="SCLCacheOverride" Value="0" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Updates Enabled="TRUE" />
  <Display Level="None" AcceptEULA="TRUE" />
</Configuration>

Create an XML configuration for uninstallation

Open Notepad or another text editor like VS Code and create an XML file at the location C:\temp\package\uninstall.xml

Add the following information:

<Configuration>
    <Display Level="None" AcceptEULA="True"/>
    <Property Name=""FORCEAPPSHUTDOWN" Value="True"/>
    <Remove>
        <Product ID="Standard2021Volume"> </Product>
    </Remove>
</Configuration>

Be sure to change your Product ID to match what you have in your install.xml file that was generated by the Office Customization Tool:

Screenshot of VS Code

Create an .intunewin package

To perform the next steps, you will need to download two apps, the Office Deployment Tool (ODT) and the Microsoft Win32 Content Prep Tool.

Install the Office Deployment Tool (ODT)

  1. Download the ODT from Microsoft's website and run the application: https://www.microsoft.com/en-us/download/details.aspx?id=49117
  2. You will need to select a destination to extract the files. I'm using C:\temp\
  3. When the extraction is complete, you should have 5 files in the folder: Windows File Explorer, Office Deployment Tool files
  4. Move the setup.exe file to C:\temp\package\setup.exe

Use the Win32 Content Prep Tool

  1. Navigate to the Microsoft Win32 Content Prep Tool from Microsoft's Github site: https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool
  2. Click on the Code icon and select “Download Zip”: Github page for Microsoft Win32 Content Prep Tool
  3. Unzip the file in a location like C:\temp
  4. Open Powershell or the Windows Terminal and navigate to the location by typing: cd C:\temp\Microsoft-Win32-Content-Prep-Tool-master
  5. Run the app “IntuneWinAppUtil.exe”
  6. Make sure you have the 3 files in your C:\temp\package directory before proceeding: Screenshot of Windows File Explorer with 3 files
    • setup.exe
    • install.xml
    • uninstall.xml
  7. Fill in the prompts with the following information:
    • Please specify the source folder: C:\temp\package
    • Please specify the setup file: C:\temp\package\setup.exe
    • Please specify the output folder: C:\temp\package
    • Do you want to specify catalog folder (Y/N)? N
  8. The package will begin to build and you'll see a file created at C:\temp\package\setup.intunewin : Windows Terminal running Win32 Content Prep Tool

When the process is complete, you are ready to upload the package to Intune and configure your Application Deployment.

Create an Application Deployment in Intune

  1. Navigate to the Intune/Endpoint dashboard: https://endpoint.microsoft.com/

  2. Navigate to Apps > Windows and click the “Add” button. Select “Windows app (Win 32)” from the dropdown list and click the “Select” button: Screenshot of Intune dashboard, Windows App Deployment creation

  3. On the App Information tab, click “Select app package file” and upload your setup.intunewin file from C:\temp\package. Click the OK button:Screenshot of Intune dashboard, Windows App Deployment creation, App package file tab

  4. Back on the App Information tab, begin by filling in some basic information about the package and click the “Next” button when finished: Screenshot of Intune dashboard, Windows App Deployment creation, App information tab

  5. On the “Program” tab, configure the Install Command and Uninstall Command fields and leave the rest default. Click “Next” to continue: Screenshot of Intune dashboard, Windows App Deployment creation, Program tab

    • Install command: setup.exe /configure install.xml
    • Uninstall command: setup.exe /configure uninstall.xml
    • Install behavior: System
    • Device restart behavior: App install may force a device restart
  6. On the “Requirements” tab, set the following options and click Next to continue: Screenshot of Intune dashboard, Windows App Deployment creation, Requirements tab

    • Operating system architecture: Set this value based on your Office Customization Tool setting.
    • Minimum operating system: Windows 10 1607
  7. On the “Detection rules” tab, set the following options and click Next to continue: Screenshot of Intune dashboard, Windows App Deployment creation, Detection rules tab

    • Rules format: Manually configure detection rules
    • Rule type: Registry
    • Key path: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Office\
    • Value name: 16.0
    • Detection method: Key exists
    • Assocated with a 32-bit app on 64-bit clients No
  8. Leave the “Dependencies” and “Supersedence” tabs unconfigured.

  9. On the “Assignments” tab, select the group you want to target for deployment or uninstallation.

  10. Double check the options on the “Review + create” tab and then click “Create” to begin uploading your package.

After the application is uploaded, your deployment will begin: Screenshot of Intune Application Deployment

The setup.exe package will always pull the latest version of Office from Microsoft, but your install.xml file determines whether the applications will be automatically updated. If you need to push a new version or a different version (e.g. Standard or ProPlus), you may need to repackage and deploy again.

I hope this is helpful to someone and I wanted to write my steps down in case I have to go back and fix something later.

Discuss...

#Azure

I recently got a trial of Lucidscale, a tool that can ingest your Azure environment and automatically create a resource visualization diagram.

I am pretty happy with the product and will recommend that my company purchase it for client work.

I wanted to detail the setup process in Azure so it's easy to use.

To get Lucidscale to interact with your Azure subscription, you will need to be a Global Administrator. To try Lucidscale, you will need a trial. Once you get that setup, you can continue to configure it.

First, navigate to the main Lucid website and click New > Lucidscale > Azure Model:

Screenshot of Lucid New menu

We will need to configure the subscription information to connect into Azure. Click “Open Data hub to Import Subscriptions”:

Screenshot of Lucidscale Azure subscription setup screen

Click “New Subscription”:

Screenshot of Lucidscale Subscriptions tab

You can automate using an Azure CLI script, but for now let's set it up manually. Click “Azure AD Application”:

Screenshot of LucidScale - New Azure Subscription page

Now, we are ready to configure your Azure environment to allow access to the tool. Open a new tab and navigate to Azure Active Directory. Click “App registrations” and then click “New registration”

Screenshot of Azure Active Directory, App Registration blade

Inside the wizard, type the name you want to use and then click “Register”. Leave the other options on the default setting:

Screenshot of Azure Active Directory, App Registration wizard

After registering the app, open the configuration settings inside Azure AD. Navigate to the “Overview” blade and copy and paste the Application (client) ID and Directory (tenant) ID over into the Lucidscale setup page:

Screenshot of Lucidscale Azure subscription setup and Azure AD App Registration Overview tab

After pasting in that info, navigate to the “Certificates & secrets” blade in Azure AD and click the “Client secrets” tab. Click “New client secret”. Fill in a name and click “Add”:

Once you've created the secret, copy and paste the “Value” of the client secret from the Azure AD page into the “Client Secret” box in Lucid:

After pasting in the three required values, enter an Application name in Lucid. I named mine after the client company.

Now, we will need to give permissions to the App Registration so that it can read the Azure environment. Navigate to the Subscription blade in Azure and click on the one you want to use. Click on the “Access control (IAM)” blade, then click “Add > Add custom role”:

Screenshot of Azure Subscription blade, Access Control IAM tab

On the “Basics” tab, type a Custom role name. I used “Lucidscale import”. Under “Baseline permissions”, select “Start from JSON” and upload the following file:

{
    "properties": {
        "roleName": "Lucidscale import",
        "description": "Role that gives Lucidscale read access to import resources",
        "assignableScopes": [],
        "permissions": [
            {
                "actions": [
                    "Microsoft.Authorization/roleAssignments/read",
                    "Microsoft.ApiManagement/service/read",
                    "Microsoft.Compute/disks/read",
                    "Microsoft.Compute/virtualMachines/read",
                    "Microsoft.Compute/virtualMachineScaleSets/read",
                    "Microsoft.Databricks/workspaces/read",
                    "Microsoft.DBforMySQL/servers/databases/read",
                    "Microsoft.DBforMySQL/servers/read",
                    "Microsoft.DBforPostgreSQL/servers/databases/read",
                    "Microsoft.DBforPostgreSQL/servers/read",
                    "Microsoft.DocumentDB/databaseAccounts/read",
                    "Microsoft.KeyVault/vaults/read",
                    "Microsoft.Network/applicationGateways/read",
                    "Microsoft.Network/azurefirewalls/read",
                    "Microsoft.Network/connections/read",
                    "Microsoft.Network/dnszones/read",
                    "Microsoft.Network/dnszones/recordsets/read",
                    "Microsoft.Network/frontDoors/read",
                    "Microsoft.Network/loadBalancers/read",
                    "Microsoft.Network/localnetworkgateways/read",
                    "Microsoft.Network/networkInterfaces/read",
                    "Microsoft.Network/networkSecurityGroups/read",
                    "Microsoft.Network/privateDnsZones/read",
                    "Microsoft.Network/privateDnsZones/ALL/read",
                    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/read",
                    "Microsoft.Network/privateEndpoints/read",
                    "Microsoft.Network/publicIPAddresses/read",
                    "Microsoft.Network/routeTables/read",
                    "Microsoft.Network/trafficManagerProfiles/read",
                    "Microsoft.Network/virtualNetworkGateways/read",
                    "Microsoft.Network/virtualNetworks/read",
                    "Microsoft.Network/virtualNetworks/subnets/read",
                    "Microsoft.Resources/subscriptions/read",
                    "Microsoft.Resources/subscriptions/resourceGroups/read",
                    "Microsoft.ServiceBus/namespaces/read",
                    "Microsoft.ServiceBus/namespaces/queues/read",
                    "Microsoft.Sql/servers/databases/read",
                    "Microsoft.Sql/servers/read",
                    "Microsoft.Storage/storageAccounts/read",
                    "Microsoft.Web/serverfarms/Read",
                    "microsoft.web/sites/functions/read",
                    "Microsoft.Web/sites/Read"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            }
        ]
    }
}

Screenshot of Azure custom role wizard, Basics tab

Navigate to the Permissions tab. The JSON is not complete and you will need to add an additional role to this list. Click the “Add permissions” button, then search for “managed”. Check the box for Microsoft.ManagedIdentity/userAssignedIdentities > Read : Get User Assigned Identity. Click the “Add” button when you're finished.

Screenshot of Azure custom role wizard, Permissions tab

Navigate to the “Assignable scopes” tab and click the “Add assignable scopes” button. Change the Type field to “Subscription”, then click on your subscription in the right column. Click “Select” when you're finished:

Screenshot of Azure custom role wizard, scopes tab

Leave the JSON tab as default and complete the wizard to Create the role.

Once you've created the role, return to Azure Active Directory and open Subscriptions. Select the subscription you want to use.

Navigate to the “Access control (IAM)” blade and navigate to the “Roles” tab. Search for “Lucid” and locate your newly created role. Click the “View” link:

Screenshot of Azure Subscriptions, Access Control (IAM) blade, Roles tab

In the new popup, click on the Assignments tab, then click “Add assignment”:

Screenshot of Azure Subscriptions, Access Control (IAM) blade, Assignments tab

Navigate to the “Members” tab. Check the radio button for “Assign access to” as “User, group, or service principal” and click the “Select members” button. Search for “Lucid” in the popup window and click on your app. Click the “Select” button when you're finished:

Screenshot of Azure Subscriptions, Access Control (IAM) blade, Assignments, Members tab

After you've completed this part, complete the wizard to add the role assignment in Azure AD.

Now that we've configured the environment, return to Lucidscale to complete the configuration. Move to the “Select Subscriptions” page and check the box next to the correct subscription:

Screenshot of Lucidscale New Azure Subscription, Select Subscriptions tab

On the “Subscription configuration” tab, leave all options as default and click the “Import Azure subscriptions” button:

Screenshot of Lucidscale New Azure Subscription, Select

After completing the wizard, data import will begin. This process could take a while, depending on the size of your environment.

Lucidscale Azure Data Hub page, Subscriptions tab, Importing data

When it's complete, select your subscription and click the “Create new Model” button:

Lucidscale Azure Data Hub page, Subscroptions tab, Create new Model

Check the box next to the subscription you want to diagram, then click the “Choose subscriptions” button at the bottom right.

Lucidscale Azure, Create new Model wizard

Review your selection and then click “Create Azure Model”.

Now, Lucidscale will build your model in the background. It could take a while, depending on the size of your environment:

Lucidscale Azure, Creating Lucidscale Model

After it's complete, your diagram will be generated:

Lucidscale Azure diagram complete

Footer image

Discuss...

#Azure #PowerShell #Windows

If you’ve added a new session host to an existing Azure Virtual Desktop host pool, you might get a Windows Activation error watermark notifying you that the Windows license wasn’t found:

Screenshot of a Windows 10 desktop, showing a Windows activation error

Activate Windows. Go to Settings to activate Windows.

When I got the ticket from users complaining about the watermark, I started brainstorming. I thought I might be able to fix this issue several ways:

  1. License users with Microsoft 365 E5.

  2. Manually add an existing Windows license (only possible if you’re running a stock image of Windows, not the Azure-specific Windows Enterprise Multi-Session).

Since I don’t have those E5 licenses already and I’m running the multi-session OS, it would add cost to purchase and I would need to get approval.

Instead, I found that you can check the VM license by running this command in PowerShell (change the XXX values to match your Resource Group and VM name):

Import-Module AzCLI 
Connect-AzAccount
Get-AzVM -ResourceGroupName XXXresourcegroupXXX -Name XXXvirtualmachineXXX

After running that command, the string that you want to focus on is LicenseType. If it says Windows_Client, you are good to go and Azure will apply the license on the OS-level.

If it is null or displays as {}, that could be a cause for the Activation error. You can run this PowerShell command in the AzCLI (edit the XXX values to match your environment):

$rg = XXXresourcegroupXXX
$vm = XXXvirtualmachineXXX
$vm.LicenseType = ‘Windows_Client’

Get-AzVM -ResourceGroupName $rg -Name $vm | Update-AzVM 

I wish Azure had a built in Troubleshooting function or feature to “quick fix” this issue, but I couldn’t find one.

Putting this here for my notes when I have to fix this issue again.

Discuss...

#Intune #Windows

A company I'm working with requested an Intune deployment of Adobe Acrobat Pro DC to users on machines running Windows 10 or 11.

I wasn't able to find great documentation about how to deploy this using Intune, so I wanted to write all of this down. There are some guides going around about MSP transforms, but that's not necessary for a simple deployment.

  1. First, download the Adobe Acrobat Pro single app package and select the 64 bit Windows installer:

Screenshot of Adobe Acrobat Pro installer download page

  1. Then, download the Microsoft Win32 Content Prep Tool.

  2. Unzip all of the files to that they're in a format as follows:

    • C:\temp\Microsoft-Win32-Content-Prep-Tool-Master
    • C:\temp\Adobe Acrobat
  3. Now that you have the prereqs, we need to build the .intunewin package for Intune. Open Command Prompt and cd into the C:\temp\Microsoft-Win32-Content-Prep-Tool-Master folder and run .\IntuneWinAppUtil.exe

  4. Step through the prompts to build the package:

    • Please specify the source folder: C:\temp\Adobe Acrobat
    • Please specify the setup file: C:\temp\Adobe Acrobat\setup.exe
    • Please specify the output folder: C:\temp\Adobe Acrobat
    • Do you want to specify catalog folder (Y/N)? n

Screenshot of Windows Terminal running the Microsoft Win32 Content Prep tool for Adobe Acrobat Pro

Now that the intunewin package is built, it's time to upload it on the Microsoft Endpoint and create an app package. You can close the Win32 Content Prep tool.

  1. Log into the Intune/Endpoint dashboard and navigate to Apps > Windows > Add. Set the “App type” to Windows app (Win32):

Screenshot of Intune dashboard, Windows app creation wizard

  1. On the “App information” tab, upload the file you created at C:\temp\Adobe Acrobat\setup.intunewin and fill out the required fields to continue:

Screenshot of Intune dashboard, Windows app creation wizard, App information tab

  1. On the “Program” tab, enter the following values:
    • Install command: setup.exe /sAll
    • Uninstall command: msiexec /x "{AC76BA86-1033-FFFF-7760-BC15014EA700}" /q
    • Install behavior: System
    • Device restart behavior: App install may force a device restart
    • Specify return codes to indicate post-installation behavior: Leave as default.

Screenshot of the Intune dashboard, Add App wizard, Program tab

  1. On the “Requirements” tab, enter the following values:
    • Operating system architecture: 64-bit
    • Minimum operating system: Windows 10 1607

Screenshot of the Intune dashboard, Add App wizard, Requirements tab

  1. On the “Detection rules” tab, set “Rules format” to Manually configure detection rules, then click the “+ Add” button. Change the “Rule type” to MSI and set the “MSI product code” field to {AC76BA86-1033-FFFF-7760-BC15014EA700}. Set the “MSI product version check” to No:

Screenshot of the Intune dashboard, Add App wizard, Detection rules tab

  1. On the “Dependencies” and “Supersedence” tabs, just leave the defaults.

  2. On the “Assignments” tab, target your deployment group or users for installation. You may want to hide the “End user notifications” so that it's completely silent, but this is optional:

Screenshot of the Intune dashboard, Add App wizard, Assignments tab

After uploading the file, your application deployment will be complete:

Screenshot of the Intune dashboard, Add App wizard, file upload

Machines will begin to check in and pick up the app assignment. I find that installation can take up to 30 minutes, so be patient!

Screenshot of a Windows 11 desktop notification for Intune/Endpoint application deployment

Screenshot of a Windows 10 desktop notification for Intune/Endpoint application deployment

Discuss...

#Sharepoint #Windows

One of the companies that I'm working with wants to migrate all of their files on a local file share and move them into a Sharepoint site.

To do this, I ran the official Microsoft Sharepoint Migration Tool from the file server. I set my source as the shared folder containing 1.8 TB of files and the target destination as the Documents library in a newly created Sharepoint site.

After letting the tool run for a few hours, the migration tool completed and reported that it had successfully moved 209,726 files, but 500 were not moved because the scanner has issues with special characters:

Screenshot of the Microsoft Sharepoint Migration Tool, migration report page.

They're an international organization and has French, Spanish, and Portuguese workers that connect into the shared drive. They're also using a mix of MacOS and Windows PCs, so the folders can get pretty cluttered with UTF and non-Windows character sets.

From the logs, the Sharepoint Migration Tool seems to only allow ANSI characters, probably for URLs and other internal compatibility. I needed to rename all of the non-migrated files from the accented characters into the ANSI equivalents and then run an incremental sync.

To fix the accent characters, I could go in manually an rename all of the files, but I needed an easier way to automate this.

Instead of figuring out the right regex command and running a rename command in Powershell, I decided to keep it simple and use the Bulk Rename Utility app that I've used for other projects, including the project I wrote about to redact Microsoft Word files quickly.

After downloading and installing the app on the file server, open it and target the share location on the local drive.

Inside the app, click on the option at Special > Character Translations.

I copied and pasted all of the accented characters and their ANSI equivalents into Excel and formatted it for Bulk Rename Utility to be able to use the list. Copy and paste this list into this Character Translation popup window:

Á=A
á=a
À=A
à=a
Â=A
â=a
Ã=A
ã=a
Ä=A
ä=a
Å=A
å=a
ç=c
Ç=C
É=E
é=e
È=E
è=e
Ê=E
ê=e
Ë=E
ë=e
Í=I
í=i
Ì=I
ì=i
Î=I
î=i
Ï=I
ï=i
Ó=O
ó=o
Ò=O
ò=o
Ô=O
ô=o
Ö=O
ö=o
Õ=O
õ=o
Ú=U
ú=u
Ù=U
ù=u
Û=U
û=u
Ü=U
ü=u

After pasting in the info, press OK and return to the main window:

Screenshot of Bulk Rename Utility, character translation popup with characters

Make sure that you have the following options checked:

✓ Files > Files

✓ Files > Folders

✓ Files > Subfolders

✓ Special > Character Translations

Screenshot of Bulk Rename Utility, subfolders and character translations selected.

After checking those boxes, click into the file list at the top right of the window and press the Ctrl + A keys on the keyboard to select all items. This could take a few seconds, depending on the number of files that you have.

To verify, click the “Preview” button, then press “Rename” if the renaming task looks correct:

Screenshot of Bulk Rename Utility, file rename preview popup window

After renaming these files, I returned to the Sharepoint Migration Tool and started the Incremental sync. The sync completed successfully without any file scan issues or unrecognized characters.

Footer

Discuss...

#Exchange #Powershell #Windows

I recently had a request to spin up an on-prem Exchange 2016 server and connect it with a new Azure AD tenant and Exchange Online. I created a new Azure VM with Server 2016 and ran the latest patches and Windows updates before installing anything.

After going through the regular Exchange server setup process and installing Azure AD connect on the Domain Controller, I needed to install and run the Exchange Hybrid Configuration Wizard on the Exchange server.

After running the install, I ran into an error that would not let me continue:

Failed Setup terminiated with an Exit Code 1603

To work through this, I found a post [A] that details some changes that need to be made in the registry relating to the TLS

I wrote up this quick script so that it can be run quickly without mucking through regedit:

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -PropertyType dword -Value 1
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Name 'DisabledByDefault' -PropertyType dword -value 0
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Name 'DisabledByDefault' -PropertyType dword -value 0
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Name 'Enabled' -PropertyType dword -value 1
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Name 'Enabled' -PropertyType dword -value 1

Discuss...

#Powershell #Windows

Recently, I was trying to run a Powershell command to retrieve the list of Local Admin accounts on a domain-joined machine.

I ran this command in Powershell 5.1 and 7.2.5:

Get-LocalGroupMember -Group Administrators

I received an error that something was wrong with the command.

Get-LocalGroupMember : Failed to compare two elements in the array. At line:1 char:1

A SuperUser post [A] suggested that the error is caused by invalid admin accounts that are not cleaned up during domain join or AAD join. The post suggests running the following Powershell command to remove the invalid admin accounts:

# Clean-AdministratorGroup.ps1
# https://gist.github.com/tdannecy/daf057ab9b9280290efb34677d9c0ea8
# https://superuser.com/a/1481036

function Clean-AdministratorGroup {
    $administrators = @(
        ([ADSI]"WinNT://./Administrators").psbase.Invoke('Members') |
        ForEach-Object { 
            $_.GetType().InvokeMember('AdsPath', 'GetProperty', $null, $($_), $null) 
        }
    ) -match '^WinNT';
        
    $administrators = $administrators -replace 'WinNT://', ''
        
    $administrators | ForEach-Object {   
        if ($_ -like "$env:COMPUTERNAME/*" -or $_ -like "AzureAd/*") {
            continue;
        }
        Remove-LocalGroupMember -group 'Administrators' -member $_
    }
}
Clean-AdministratorGroup

Footer image

Discuss...

#Azure #Exchange

A company I work with requested a deployment of RedCap, a web application for building and managing online surveys and databases, into their Azure environment.

Currently, the official RedCap documentation is incomplete and has inaccurate instructions on some of the Azure steps.

While I got this rolled out for the company, I decided to take detailed notes to help others in deploying this in Azure. This process is detailing my environment, running REDCap 12.5.4, PHP 7.4.28 (Windows OS), MySQL 5.7.32

Deployment

To start, you'll need the following credentials:

  • Global Administrator access to your Azure tenant or the ability to create AppService Plans and roll out Templates
  • Exchange Administrator
  • Admin access to your public DNS provider
  • RedCap Community site access

Begin by opening your browser and navigating to the official RedCap GitHub fork for the Azure Template: https://github.com/vanderbilt-redcap/redcap-azure

Click on the link in the README page with the text “Deploy with your SMTP Relay” to open the Azure Template page and begin deployment:

Screenshot of RedCap Azure Template on Github

  • Subscription: Choose your organization's subscription
  • Resource group: Create new to keep things organized
  • Region: Choose the region closest to the usage location
  • Site Name: Something with “Redcap” to keep it organized
  • Administrator Login: Keep the default of redcap_app
  • Administrator Login Password: Set to a strong password
  • Redcap Community Username and Password: Copy and paste this from your welcome email from RedCap after purchasing a license. If this information is not correct, the Template deployment will fail because it won't be able to download the RedCap installation.
  • Redcap App Zip Version: latest
  • From Email Address: Create an Shared Mailbox in Exchange and put it here like redcap@domain.com. Login to the Microsoft Admin center and reset the password for that RedCap Shared Mailbox as a User object.
  • Smtp FQDN: smtp.office365.com
  • Smtp User and password: redcap@domain.com
  • Smtp Port: 587
  • Sku Name: S1
  • Sku Capacity: 1
  • Database Sku Size MB: 5120
  • Database For My Sql Tier: General Purpose
  • Database For My Sql Family: Gen5
  • Database For My Sql Cores: 2
  • Mysql Version: 5.7
  • Storage Type: Standard_LRS
  • Storage Container Name: redcap
  • Repo URL: https://github.com/vanderbilt-redcap/redcap-azure.git
  • Branch: master

Screenshot of Azure Template deployment for RedCap

You can adjust the size of your AppService after deployment, so leave the Sku options default.

After inputting your data, deploy it and wait about 30 minutes for everything to provision and install.

I had some issues with the deployment, specifically the clean up tasks at the end. These can be ignored. You should have a working install if the following items were created successfully:

  • AppService Plan
  • AppService
  • Azure Database for MySQL single server
  • Storage Account

Screenshot of Azure Portal showing the RedCap Resource Group after template deployment

After deploying, there are quite a few things you'll need to fix before rollout.

You should be able to open the newly deployed RedCap app in the Azure Portal by navigating to your Resource Group and clicking on the RedCap AppService. On the Overview blade, click on the “Browse” button:

Screenshot of Azure App Service, Overview blade

You should be able to open the app with no authentication.

Click on the Control Center button at the top of the page and click on Configuration Check on the left pane to begin working through the many issues displayed on this page.

Fixing cron process

For some reason, the scheduled tasks performed by the cron process are not running as expected after deployment. This impacts regular server tasks like database cleanup and sending emails.

To work around this issue, you'll need to create a manual job in the App Service that forces the process to start. This manual job has two files: a PowerShell script that calls PHP and cron, and a cron file that sets a schedule for auto-running the app every minute. Since RedCap was created using an Azure Template, we won't be able to use the built in portal GUI since Azure wants to keep the git repository in sync that we used in the Template. We will need to create this process manually, but the task is configurable inside the Azure Portal after creation.

To start, open the Azure App Service page for your newly deployed app and navigate to the “Advanced Tools” blade. This opens a tool called Kudu.

From the Kudu dashboard, navigate to Debug console > PowerShell.

Screenshot of Kudu in Azure, Debug console, PowerShell

In this browser, navigate to /site/wwwroot and click on the Plus icon and select “New folder”.

Create all folders until you have the following structure: C:\home\site\wwwroot\App_Data\jobs\triggered\Start-CronService

Screenshot of Kudu in Azure, Debug console, new folder option

Create a file in that location and name it Start-CronService.ps1. Click on the pencil/edit icon and paste in the following PowerShell command:

# Start-CronService.ps1
# Tim D'Annecy - 2022-08-04
# Starts the cron PHP service
# Should be deployed to C:\home\site\wwwroot\App_Data\jobs\triggered\Start-CronService\Start-CronService.ps1
# Had to hard code URIs for some reason... Working with RedCap 12.5.1

function Start-CronService {
    $cronFile = 'C:\home\site\wwwroot\cron.php'
    $phpExe = 'C:\Program Files (x86)\PHP\v7.4\php.exe'

    Start-Process -NoNewWindow -FilePath $phpExe -ArgumentList $cronFile
}
Start-CronService

In that same folder, create a file titled settings.job and paste in the following code:

{
  "schedule": "0 */1 * * * *",
}

After creating these files, you should have the following items in your folder at C:\home\site\wwwroot\App_Data\jobs\triggered\Start-CronService:

Screenshot of Kudu in Azure, Debug console, PowerShell, File view

After saving, restart your AppService from the “Overview” blade. You will see this task appear from the AppService page under the WebJobs blade:

Screenshot of Azure portal, AppService page, WebJobs blade

You can check the status by viewing logs logs and stop/start the process, as needed.

Subdomain and HTTPS connection

At this point, your app is reachable over HTTP with the long name of blah.azurewebsites.com. It's better to use a subdomain like redcap.domain.com and to force users to access the site over HTTPS.

To accomplish both of these, you'll need to make a few changes in your DNS hosting provider, in the Azure environment, and inside the RedCap AppService.

To begin, navigate to the Azure Portal and open up your AppService for RedCap. Click on the “Custom domains” blade and change HTTPS Only to On. After this is enabled, you can add your custom subdomain.

Click the “Add custom domain” button and fill in the subdomain that you want to use. For this example, I'm using redcap.domain.com

After opening the “Add custom domain” configuration pane, open a tab for your DNS provider. The company I'm working with uses Oracle DynDNS.

From the custom domain configuration pane in Azure, you'll copy and paste the following values into your DNS provider:

  1. From “Custom Domain Verification ID” in Azure into a TXT record in DNS for asuid.redcap.domain.com.
  2. From CNAME in Azure into a CNAME record in DNS for redcap.domain.com

Screenshot of Azure AppService DNS settings and Oracle DynDNS

Once these are in place, you'll create a certificate in Azure to secure the web connection for HTTPS traffic.

Open the “Certificates (preview)” blade. Click “Add certificate”. Set the Source to “Create App Service Managed Certificate” and type in your subdomain from earlier (redcap.domain.com). The “Certificate friendly name” can be set to something more readable, if you like. Change the SSL binding to a “SNI SSL” and deploy it:

Screenshot of Azure AppService Certificates

Once this certificate is deployed, switch back to the “Custom Domains” blade. You should see your subdomain populated as “Secure”. You should be able to load your site over an HTTPS connection and your certificate will be valid. You may need to wait a little bit for DNS and the certificate to propogate.

After making this change in Azure, navigate back to your RedCap instance and open Control Center > General Configuration and change the “REDCap base URL” to your subdomain (e.g. https://redcap.domain.com).

Screenshot of RedCap General Configuration page

Azure AD single-sign on

This piece is very finicky. If you make an error in setting the SSO settings inside Redcap, you can get locked out of your instance. If this happens, you can use a SQL query on your to get back in:

UPDATE `redcap_config` SET `value`='none' WHERE `field_name`='auth_meth_global' LIMIT 1

Navigate back to your AppService for RedCap and click on the “Authentication” blade. Click “Add an identity provider”.

In the wizard, on the Basics tab, change the Identity Provider to Microsoft and change the “App registration type” to Create new app registration. Give it a name like “RedCap”. Change the “Supported account types” to Any Azure AD directory - Multi-tenant. Leave the other fields as default.

Azure AppService Authentication Add an identity provider, Basics tab

On the Permissions tab, keep the default value for User.Read:

Azure AppService Authentication Add an identity provider, Permissions tab

After adding the identity provider, return to the Authentication page. Click on the Pencil icon next to your new Authentication provider.

On the “Edit identity provider” page, copy the Application (client) ID.

Open your RedCap instance and navigate to Control Center > Security & Authentication and change the “Authentication Method” to Azure AD OAuth2. Scroll down the page and paste this Application ID into the “Azure AD API Client ID” field:

Screenshot of RedCap Azure AD OAuth2 and Azure AppService identity provider configuration

Click on Client secret value. It will redirect you to the AppService Configuration blade. Copy the value of the MICROSOFT_PROVIDER_AUTHENTICATION_SECRET into the RedCap field for Azure AD API Client Secret:

Screenshot of RedCap Azure AD OAuth2 and Azure AppService identity provider configuration

Set your RedCap@domain.com account or yourself as a Primary and/or Secondary Admin and click “Save”.

You might need to save this value twice, RedCap may reload the page without saving the values. After saving, you will need to set some values in Azure AD to handle post-login behavior.

Navigate to the Azure AD portal

Navigate to the “App registrations” blade and click on the RedCap application you named earlier. Open the “Authentication” blade.

Under the “Web” section, you'll need to add the following two URLs to your instance for the URL callback: * https://redcap.domain.com/.auth/login/aad/callback * https://redcapFULLNAME.azurewebsites.net/.auth/login/aad/callback

Under “Select the tokens you would like...” to be set to ID tokens (used for implicit and hybrid flows)

Screenshot of Azure AD App Registration for Redcap, Authentication blade

After that, navigate to the “API permissions” blade and click “Add a permission”. Select Microsoft Graph > Delegated permissions. Add the following items and save :

  • OpenID permissions
    • email – View users' email address
    • openid – Sign users in
    • profile – View users' basic profile
    • User.Read – Sign in and read user profile

Screenshot of Azure Registered Apps, API permissions page

After making these changes, try accessing your domain at https://redcap.domain.com.

If you can successfully login, you'll get this error on the page Control Center > Configuration Check:

Screenshot of RedCap, site_admin error

“siteadmin” user should not be an Administrator! It appears that the user “siteadmin” is an Administrator. However, this user account should ONLY ever be an Administrator when the system-level authentication method is set to None (Public), otherwise this user should NOT be an Administrator. You should go to the “Administrators & Acct Managers' page and remove them as an Administrator immediately, otherwise users accessing public REDCap projects may gain access to things that only REDCap Administrators should be accessing.

The instructions in this error are not accurate to the current version of RedCap. To make this error disappear, navigate to the Control Center > Administrator Privileges and uncheck all of the permissions for the user:

Screenshot of RedCap, user permissions

After that's cleaned up, you can suspend the account on the Control Center > Browse Users > View list by criteria page. Click the “Display user list” button and select the site_admin account. Check the box next to the account and suspend it using the button on the bottom:

Screenshot of Redcap, Browse Users

Do not delete this user. On a reboot of the AppService, RedCap will check to make sure this user is still present and show a database error if it's missing.

Cleaning up

After you've made these changes, you can delete some items out of the Configuration page in the AppService blade, as recommended by RedCap documentation, but there's no real reason to do so.

MySQL database changes

RedCap will give you a warning about the default MySQL database configuration:

RedCap MySQL warning message

Your database configuration settings do not appear to be optimal. For better database performance and stability, consider making the changes below to your database configuration settings in your my.cnf (Linux/Unix) or my.ini (Windows) configuration file. TIP: Remember to restart the MySQL service after making any edits to the configuration, otherwise they won't take effect.

Navigate to the Azure Portal and open up the SQL object that was created with the Template deployment. Navigate to the Query Performance Insight blade. From here, click on the top banner:

Screenshot of Azure MySQL Query Performance Insite message

Change the following options and save: * query_store_capture_mode = ALL * query_store_capture_utility_queries = YES

Screenshot of Azure MySQL server parameters

Over time, Azure should make recommendations to adjust your SQL configuration to be more efficient.

User-uploaded document store

After first install and logging in with an admin account, RedCap will give an error about the user-uploaded documents:

RedCap user-uploaded documents error message

Directory that stores user-uploaded documents is exposed to the web: It is HIGHLY recommended that you change your location where user-uploaded files are stored. Currently, they are being stored in REDCap's “edocs” directory, which is the default location and is completely accessible to the web. Although it is extremely unlikely that anyone could successfully retrieve a file from that location on the server via the web, it is still a potential security risk, especially if the documents contain sensitive information. It is recommend that you go to the File Upload Settings page in the Control Center and set a new path for your user-uploaded documents (i.e. “Enable alternate internal storage of uploaded files rather than default 'edocs' folder”), and set it to a path on your web server that is NOT accessible from the web. Once you have changed that value, go to the 'edocs' directory and copy all existing files in that folder to the new location you just set.

You can fix this by navigating to the Control Center and opening the “File Upload Settings” page. From here, change the dropdown to Microsoft Azure Blob Storage and scroll down to the section with the same title.

Open another browser tab and navigate back to your Resource Group that you setup in Azure. Open the Storage account for the app and copy and paste the Storage account name and the blob container name:

Screenshot of Azure Storage account and RedCap File Upload Settings pages

In the Azure tab, open the Access keys blade and copy and paste the Key from Key1 in the RedCap configuration page:

Screenshot of Azure Storage account and RedCap File Upload Settings pages

Save the changes at the bottom of the page, then confirm this worked by opening the Control Center and clicking on Configuration Check.

SMTP settings

The company I'm working with is using Exchange Online for its email service. To make things easy with Redcap, I created a Shared Mailbox of “RedCap@domain.com” and set a password on the Microsoft 365 Admin dashboard.

After a fresh install of RedCap 12.5.4, the SMTP settings I set in the Template did not work:

RedCap SMTP email error message

REDCap is not able to send emails – CRITICAL: It appears that your SMTP configuration (email-sending functionality) is either not set up or not configured correctly on the web server. It is HIGHLY recommended that you configure your email/SMTP server correctly in your web server's PHP.INI configuration file or else emails will not be able to be sent out from REDCap. REDCap requires email-sending capabilities for many vital application functions. For more details on configuring email-sending capabilities on your web server, visit PHP's mail configuration page.

To fix this, you'll need to open Control Center > General Settings. Scroll down to the “Configuration for Outgoing Emails” section and set the Universal FROM Email address as your redcap@domain.com email. Also set this same email under Other system settings under Email Address of REDCap Administrator.

After you update the config, you'll also need to update the version of SendMail. The one bundled with RedCap 12.5.4 does not work with TLS 1.2 and needs to be updated. To do this, we'll push the files to the AppService using FTPS.

Start by opening the GitHub page for Sendmail with TLS 1.2: https://github.com/sendmail-tls1-2/main . Download the Sendmail_v33_TLS1_2.zip file and unzip the files on your computer.

Edit the file settings.ini and put in the SMTP settings you set earlier during the deployment step, be sure to change these values to your environment:

  • smtp_server=smtp.office365.com
  • smtp_port=587
  • smtp_ssl=auto
  • auth_username=redcap@domain.com
  • auth_password=XXX
  • force_sender=redcap@domain.com
  • hostname=domain.dom

After making the changes to the file, save and close it. Now, you'll upload the patched Sendmail with the changed .ini file into your AppService using FTPS.

Navigate to the Azure Portal and open your RedCap AppService. Click on the “Deployment center” blade. Click on the “FTPS credentials” tab.

Download FileZilla or another application that can connect to an SFTP endpoint. For this example, I'll be using FileZilla.

Open the app and add a new site. Copy the connection information from the AppService FTPS credentials page into FileZilla:

Screenshot of Filzilla and Azure AppService, setting up a New Site wizard

Once you've connected to the FTPS endpoint, use the left pane to find the new Sendmail folder that you unzipped on your local computer. Navigate on the right pane to the location C:\home\site\repository\Files\sendmail. Select and right click on all of the files in the Sendmail folder in the local view and click “Upload”, overwriting all files.

Screenshot of Filzilla connected to Azure FTPS endpoint in AppService

After this is complete, restart your AppService for the patched changes to take effect.

If your organization is using Azure AD's Security Defaults, you will need to allow the redcap@domain.com account to use basic authentication to login.

To do this, open Azure AD Conditional Access policies and allow basic authentication for your redcap@domain.com account, or add an exception:

Screenshot of Azure AD Conditional Access policies, adding an exception

You will also need to create a Rule inside Exchange Online to allow emails to go through without being tagged as Spam. To do this, open the Exchange Admin center and navigate to Mail flow > Rules. Create a new rule with the following properties:

  • Name: Allow RedCap emails
  • If the message... Includes these words in the sender's address: 'redcap'
  • Do the following... Set the spam confidence level (SCL) to '-1'
  • Rule mode Enforce
  • Additional properties Sender address matches: Header

You can send a test email inside RedCap by navigating to Control Center > Email Users.

You can get logs from email delivery issues by opening the directory C:\home\site\repository\Files\sendmail inside the Kudu, or Advanced Tools, from your AppService page. The debug.log file should have any applicable email failures.

If emails are still not sending, check to make sure that the cron job is running with the WebJobs blade in your AppService.

Conclusion and caveats

After deployment and performing these cleanup tasks, you should have a fully working environment for a Microsoft shop: hosted in Azure, uses AzureAD for authentication, and Exchange Online for SMTP.

Since the official RedCap Azure template does not currently have support for automatic updating, you'll need to redeploy it each time. I haven't tried redeploying yet, but I'll make a new post when a major new version comes up.

Overall, this process has been difficult because the RedCap documentation is currently not updated and is often incomplete. Hopefully this guide can help someone else get the system online with modern hosting and authentication without headaches.

Footer image

Discuss...

#Windows #Powershell #Networking

A company I'm working with is looking to move from an OpenVPN connection to a Meraki VPN on newly installed MX hardware.

To accomplish this, I wrote a short script that can be deployed in GPO that adds the new VPN connection and uninstalls the existing OpenVPN application.

Here's the script:

# Migrate-VPN.ps1
# Adds a new Meraki VPN config and removes the existing OpenVPN GUI application.
# Tim D'Annecy 2022-08-04

Start-Transcript -Path 'C:\temp\Migrate-VPN.log'
function Add-VPN {
  $ConnectionName = 'New VPN'
  $ServerAddress = 'XXXyourhostnameXXX'
  $PresharedKey = 'XXXyourpskXXX'

  $check = Get-VpnConnection -Name $ConnectionName -AllUserConnection -ErrorAction SilentlyContinue

  if ($check) {
    Write-Host 'VPN connection named' $ConnectionName 'already exists. Exiting.'
  }
  else {
    Write-Host 'Adding VPN connection' $ConnectionName
    Add-VpnConnection `
      -Name $ConnectionName `
      -ServerAddress $ServerAddress `
      -TunnelType L2tp `
      -EncryptionLevel Optional `
      -L2tpPsk $PresharedKey `
      -AuthenticationMethod Pap `
      -RememberCredential $true `
      -AllUserConnection  $true `
      -Force `
      -WarningAction SilentlyContinue
  }
}
Add-VPN

function Remove-OpenVPN {
  if (Test-Path -Path 'C:\Program Files\OpenVPN') {
    Write-Host 'OpenVPN installed. Removing...'
    (Get-WmiObject -Class Win32_Product -filter "Name LIKE 'OpenVPN%'").Uninstall() | Out-Null
  }
  else {
    Write-Host 'OpenVPN not installed. Exiting.'
  }
}
Remove-OpenVPN

Stop-Transcript

Copy and paste this script into your \\domain.com\SYSVOL\scripts folder and save it as Migrate-VPN.ps1.

Once you've done this, go into Group Policy Management and create a new GPO Object that does 3 things: * Create a folder at C:\temp * Copy the file from \\domain.com\SYSVOL\scripts\Migrate-VPN.ps1 to C:\temp\Migrate-VPN.ps1 * Run a Scheduled Task that calls Powershell to run the script every hour on the hour

With these things in place, you should see the changes trickle out to your environment as the machines check in.

Discuss...

Enter your email to subscribe to updates.