Something's gone wrong!An error ocurred performing that action. Please try refreshing the page.

Hybrid Cloud Print

By Katy Nicholson, posted on 8 January, 2021

Hybrid Cloud Print is a solution to allow users to print to on-premise printers from their devices without needing to be on site or even have VPN connectivity - they just need Internet access. It is however fairly complicated to set up and requires multiple app registrations in Azure, and an Application Proxy server setting up. In this post I go through the steps on how to set it up and print from an Intune managed device.

Hybrid Cloud Print is being replaced with Universal Print, which is a lot easier to set up and manage - no messing with SQLite and it has a portal in Azure, however it has licensing implications and additional cost. I've also gone through setting up Universal Print.

Before we get started with Hybrid Cloud Print let's have a look at the pre-requisites.

  • Azure AD Premium (P1 or P2),
  • Intune
  • Windows Server 2016 or later Active Directory infrastructure
  • Windows Server 2016 or later Print Server
  • Windows Server 2016 or later Application Proxy server
  • Windows 10 PC for testing
  • Public domain name

I'd expect most networks to already have the majority of this, but an Application Proxy Server is a new thing to me so let's look at how we set that up.

Set up the Application Proxy server

Log on to your selected server for the Application Proxy role with administrative credentials. In my case I've created a new Azure VM to host this role. Open regedit.exe and set the following registry settings, then restart the server:

Copy
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2] [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SchUseStrongCrypto"=dword:00000001

on 2019 only: [HKEYLOCALMACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp] "EnableDefaultHttp2"=dword:00000000

Now go to Azure AD > Application Proxy and click on Download connector service.

Back on your server, make sure IE Enhanced Security Configuration is turned off in Server Manager (this step is required for the log in pop up to work). Now run through the installer on your VM, logging in with an account which has application administrator privileges. If you're the only person doing this it's likely to just be your global admin account.

Now refresh the Application Proxy page in Azure and you should see your connector has appeared.

Set up the Application Registration configuration in Azure

Go to Azure AD > App Registrations and click on New Registration. We're going to create three app registrations here so run through this screen three times:

  • MopriaDiscoveryService
  • EnterpriseCloudPrint
  • NativeAppForHCP

Now in the App Registrations section you should see the three apps - click on MopriaDiscoveryService, Expose an API then Set at the top next to Application ID URI. Leave this at the default and click Save.

Next click on Expose an API and Add a scope. fill out the details, then click **Add Scope

** Now go through the same steps for the EnterpriseCloudPrint registration - setting the App ID URL and adding an API scope, using the scope name (and admin consent name) "Print" and the description "Allow users to print to HCP".

Now go to the NativeAppForHCP and click on API permissions. Click on Add a permission, then APIs my organization uses and type in Mopria, then click on MopriaDiscoveryService that appears. Select Delegated Permissions and tick PrinterDiscovery, then click Add Permissions.

Repeat this step for the EnterpriseCloudPrint API and tick the Print permission.

Wait about 10 seconds then refresh the API permissions screen, you should now see a button called Grant admin consent - click on it:

The Status column should now show a green tick for each item.

Now go to Enterprise Applications > All Applications and find the MopriaDiscoveryService and click on it. Now click on Application proxy and enter the internal URL to your print server, e.g. https://print.katystech.blog/mcs/, make sure Pre Authentication is set to Passthrough then click finish.

If you selected your own domain rather than themsappproxy.net address you'll need to add a CNAME record and provide an SSL certificate - details of this are at the bottom of the Application Proxy screen.

Repeat these steps for the EnterpriseCloudPrint service, the internal URL for this is in the form of https://print.katystech.blog/ecp/

Now if you go back to App Registrations, click on the MopriaDiscoveryService and then look at Overview you should notice the Application ID URI has changed to the path you just configured in the previous steps.

Now we need to assign users to these applications we have created. Go to Azure AD > Enterprise Applications and click on the MopriaDiscoveryService. There are two options here - if we want to assign the application you can go through Users and Groups, otherwise click on Properties and change User assignment required to No so that all users can use the application. Repeat these steps for the EnterpriseCloudPrint application.

Go to App Registrations and click on the NativeAppForHCP entry. Copy the Application (client) ID from the Overview page. Now go to Authentication and click on Add a platform. Click on Mobile and desktop applications and paste in the following Custom redirect URI:

ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-3784861210-599250757-1266852909-3189164077-45880155-1246692841-283550366

Now click on Add URI and add the following URI:

ms-appx-web://Microsoft.AAD.BrokerPlugin/<ClientID> where ClientID is the Application (Client) ID that you copied earlier.

Configure the Print Server

On your print server make sure you have IIS installed as well as the Print Server role. This is done as usual through Server Manager, Windows Admin Centre or through PowerShell. Once this is done, open an elevated PowerShell window and run Install-Module PublishCloudPrinter. If you get an error "Unable to resolve package source" you may need to force it to use TLS1.2 by running this command first: [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Now change directory to "C:\Program Files\WindowsPowerShell\Modules\PublishCloudPrinter\1.0.0.0" and then run .\CloudPrintDeploy.ps1 -AzureTenant -AzureTenantGuid

You can get the tenant domain name and ID from the Azure AD overview page. It should run through and may ask a couple of questions, and will look something like this when done:

Now have a look in regedit and go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\CloudPrint and make the following changes:

EnterpriseCloudPrintService\AzureAudience = the Application ID URI of the EnterpriseCloudPrint app MopriaDiscoveryService\AzureAudience = the Application ID URI of the MopriaDiscoveryService app MopriaDiscoveryService\URL = the Application ID URI of the MopriaDiscoveryService app

Next, still in the elevated PowerShell window, run iisreset.

Now open IIS Manager and configure the Default Web Site for SSL. You'll need either a self signed certificate or one from your CA if you have one.

Back in your elevated PowerShell window run the following command to register the NuGet package source:

Copy
Register-PackageSource -Name nuget.org -ProviderName NuGet -Location https://www.nuget.org/api/v2/ -Trusted -Force

and then install SQLite - I've gone for a fixed version number as trying the latest version at time of writing was a bit of a mess - dependency loop errors etc.

Copy
Install-Package system.data.sqlite -RequiredVersion 1.0.113.0 -ProviderName nuget

Now we need to run the following code to copy the DLLs into the Mopria folder.

Copy
$source = "\Program Files\PackageManagement\NuGet\Packages" $core = "System.Data.SQLite.Core" $linq = "System.Data.SQLite.Linq" $ef6 = "System.Data.SQLite.EF6" $version = "1.0.113.0" $target = "C:\inetpub\wwwroot\MopriaCloudService\bin" xcopy /y $source\$core.$version\lib\net46\System.Data.SQLite.dll $target\ xcopy /y $source\$core.$version\build\net46\x86\SQLite.Interop.dll $target\x86\ xcopy /y $source\$core.$version\build\net46\x64\SQLite.Interop.dll $target\x64\ xcopy /y $source\$linq.$version\lib\net46\System.Data.SQLite.Linq.dll $target\ xcopy /y $source\$ef6.$version\lib\net46\System.Data.SQLite.EF6.dll $target\

Next open C:\inetpub\wwwroot\MopriaCloudService\web.config in a text editor and update the version number to what we have just downloaded in this part of the file:

Copy
<dependentAssembly> <assemblyIdentity name="System.Data.SQLite" culture="neutral" publicKeyToken="db937bc2d44ff139" /> <bindingRedirect oldVersion="0.0.0.0-1.0.113.0" newVersion="1.0.113.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Data.SQLite.Core" culture="neutral" publicKeyToken="db937bc2d44ff139" /> <bindingRedirect oldVersion="0.0.0.0-1.0.113.0" newVersion="1.0.113.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Data.SQLite.EF6" culture="neutral" publicKeyToken="db937bc2d44ff139" /> <bindingRedirect oldVersion="0.0.0.0-1.0.113.0" newVersion="1.0.113.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Data.SQLite.Linq" culture="neutral" publicKeyToken="db937bc2d44ff139" /> <bindingRedirect oldVersion="0.0.0.0-1.0.113.0" newVersion="1.0.113.0" /> </dependentAssembly>

Now you need to download the SQLite tools from the SQLite Download Page - it's the ones called Precompiled Binaries for Windows, and you want the tools zip. Extract these to somewhere, in this case I've gone with c:\sqlite, and run the following:

c:\sqlite\sqlite3.exe "c:\inetpub\wwwroot\MopriaCloudService\Database\MopriaDeviceDb.db"

This will then open a SQLite shell where you need to enter:

Copy
.read "c:/inetpub/wwwroot/MopriaCloudService/Database/MopriaSQLiteDb.sql" .exit

Note the forward slashes in the command as it doesn't like backslashes. This should give you a file called c:\inetpub\wwwroot\MopriaCloudService\Database\MopriaDeviceDb.db - find this in File Explorer, go to its Properties and then Permissions. You will need to grant the user you want to be able to publish printers Full Control to this file.

Configure the Intune policies

Go to Intune > Devices > Configuration profiles and create a new profile. This is going to be targeting Windows 10 and later, and it will be a Device Restrictions profile. Run through the wizard setting the following under Cloud Printer:

Printer discovery URL - the MopriaDiscoveryService app's External URL off the Application Proxy page, but without the trailing /. (under Enterprise Apps) Printer access authority URL - https://login.microsoftonline.com/ Azure Native client app GUID - Application (client) ID for the NativeAppForHCP app (under App Registrations) Print service resource URI - Application ID URI of the EnterpriseCloudPrint app (under App Registrations) with the trailing /. Maximum printers to query - a number, I've gone with 5. Printer discovery service resource URI - Application ID URI of the MopriaDiscoveryService app (under App Registrations) with the trailing /.

Finally go through the standard Assignment screen and complete the wizard.

Publish a printer

Add a printer to your print server, and share it and assign users the relevant permissions. You'll now need to prepare a few things for use in a PowerShell script so pop these into a text editor. Yes they are all required fields unfortunately.

  • Printer: the name of the printer share, exactly the same as shown in the Sharing tab
  • Manufacturer: The manufacturer name
  • Model: Model of the printer
  • OrgLocation: a JSON string with the printer location, e.g. {"attrs": [{"category":"country", "vs":"UK", "depth":0}, {"category":"organization", "vs":"KatysTechBlog", "depth":1}, {"category":"site", "vs":"Manchester", "depth":2}]}
  • Sddl: The permissions for the printer in SDDL format. Run the following PowerShell command against the printer you want to publish: (Get-Printer -Full).PermissionSDDL and prefix this with O:BA to get something which will look a bit like the following (obviously much longer if you have more complex permissions defined): O:BAG:DUD:(A;OICI;FA;;;WD)
  • DiscoveryEndpoint: the MopriaDiscoveryService app External URL without the trailing /.
  • PrintServerEndpoint: the EnterpriseCloudPrint app External URL without the trailing /.
  • AzureClientId: the Application (client) ID of the NativeAppForHCP app.
  • AzureTenantGuid: The ID of your Azure tenancy
  • DiscoveryResourceId: The Application ID URI of the MopriaDiscoveryService application (with the trailing /).

Now log on to an Azure AD joined Windows 10 machine as a user which is synced from AD to Azure AD and has admin rights, and permission to manage printers. Open an elevated PowerShell window and run:

Install-Module PublishCloudPrinter

You will now need to put your command together from the values you have gathered in your text editor. The command you need to run is Publish-CloudPrinter and it should look a little like:

Copy
Publish-CloudPrinter -Printer "TestPrinter" -Manufacturer "Mfr" -Model "Model" -OrgLocation '{"attrs": [{"category":"country", "vs":"UK", "depth":0}, {"category":"organization", "vs":"KatysTechBlog", "depth":1}, {"category":"site", "vs":"Manchester", "depth":2}]}' -Sddl "O:BAG:DUD:(A;OICI;FA;;;WD)" -AzureTenantGuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -AzureClientId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -DiscoveryEndpoint https://mopriadiscoveryservice-katystechblog.msappproxy.net/mcs -PrintServerEndpoint https://enterprisecloudprint-katystechblog.msappproxy.net/ecp -DiscoveryResourceId https://mopriadiscoveryservice-katystechblog.msappproxy.net/mcs/

With any luck you'll get a message saying it has been published and it will spit out the URL and UUID. If you get an error message relating to "unexpected character encountered while parsing value" double check you've got the OrgLocation correct (including the quotes).

Testing

Log on to a device which you targeted with the Intune profiles (you might need to go to Intune > Devices > Windows devices and click on the device, then click Sync if you're impatient)

Open the Settings app, and go to Devices > Printers and Scanners. Click on Add Printer and it should eventually show your cloud printers. On my setup it popped up and made me log in, which wasn't ideal but probably to do with ADFS being involved in my setup.

Unfortunately this doesn't support the more advanced features of PaperCut which require the print client - which obviously won't work with Cloud Print.

Further Reading

In this post

Support My Work

I hope you find my content useful. Please consider tipping to support the running costs of hosting, licensing etc on my Ko-fi page.

Support me on Ko-fi

Search