In a previous post, I gave an overview of the Windows Server Hybrid Cloud Print solution. This is a solution that enables organizations to support print functionality for MDM-managed BYOD and Azure AD joined devices. Organizations will find this solution useful if they plan to:
- Leverage existing global printing investments to support BYOD and non-domain joined devices
- deploy Azure AD joined devices into existing AD and global print environment
- support MDM managed BYOD
- support printing while away from the corpnet
The solution supports single sign-on user authentication and allows your to leverage your existing authorization processes. I briefly covered this in the previous post.
In this article, I will go over the steps for configuring Hybrid Cloud Print using passthrough authentication. I’ll touch on some considerations and point out some issues you might encounter, and provide some tips on how to address them.
Let’s list the requirements:
- Azure AD premium. Cloud-based authorization and identity provider. As a hybrid solution, your hybrid users will need to access both the on-premises and cloud components of the solution.
- Windows Server Active Directory. Authorization and identity on-premises
- MDM Service: Use a MDM provider ervice such as Intune for device provisioning, and applying solution policies to your devices.
- Azure AD Connect to synchronize your user identities between on-premises AD and Azure AD.
- Azure AD Proxy. Reverse proxy for that enables remote access to the on-premises printer infrastructure.
- Windows Server 2016 server with Print server role installed. This server must be on-premises domain joined.
- Web APIs and a client Native app. The discovery and proxy Web APIs provide the web service endpoint for printer discover and print operations for the remote and internet clients respectively. The Native app, as part of the OAuth 2.0 authorization workflow, will call the web APIs on behalf of the requesting user.
Azure creates a domain name for you defined for your Web APIs, and you can use this, or use your own domain name. I will use the default azure-provided domain names for illustration in this article.
Once the solution components are in place, you can test out the solution workflow on a Azure AD-joined Windows 10 device to which you’ve applied the solution MDM policies.
Recommended: Create 2 security groups:
- A group comprised of user accounts for admins with permissions to publish to Mopria database. This will be used later in this article, and will be granted permissions to the MopriaDeviceDb database file. This group will also be granted Print Server management rights. I called mine “CloudPrintAdmins”
- Create another group comprised of user accounts that will be able to discover and utilize print resources on MDM-managed devices. I called mine “MDM User Group”
Deploy solution
- #1 Configure Hybrid Identity. If you haven’t already configured hybrid identity, Install and configure the Azure AD Connect. For lab deployments and purposes of this article, one connector will suffice. However in your production environment, observe any high availability requirements for the solution.
- #2 Install Print Server and Grant Management permissions
If you don’t already have a print server, install the printer server Windows Server role on your Print server, and verify availability of print resources.
Install-WindowsFeature -Name "Print-Server" - IncludeManagementTools -verbose
Grant Print server management rights to the Admin security group created above.
- #3 Install the Hybrid cloud Print package on the Print Server
- Run the following PowerShell commands:
Find-Module -Name "PublishCloudPrinter" Install-Module -Name "PublishCloudPrinter" Import-Module PublishCloudPrinter
- Navigate to the module folder, and Install the Cloud Print package
cd 'C:\Program Files\WindowsPowerShell\Modules\PublishCloudPrinter\1.0.0.0' .\CloudPrintDeploy.ps1 -AzureTenant <Domain name used by Azure AD Connect> -AzureTenantGuid <Azure AD Directory ID>
As seen above, the script enables the IIS web server role on the print server, opens relevant firewall ports, and creates a virtual printer which I will use to test and illustrate the printing workflow later on in this article.
- Run the following PowerShell commands:
- #4 Create certificates
The solution requires you to configure the 2 IIS endpoints for SSL support. You can use certs from a trusted CA or self-signed certs. I will use self-signed certs in this illustration. I also made sure cert is imported into relevant cert store, and will configure IIS binding for SSL. - #5 Install SQLite Package
Run the following commands:Register-PackageSource -Name nuget.org -ProviderName NuGet -Location https://www.nuget.org/api/v2/ -Trusted -Force Install-Package system.data.sqlite -providername NuGet
I have found over several deployments of this solution that SQLite package version numbers aren’t always consistent as seen below. Note the version numbers for the various SQLite packages that you install. This is very important for the next step.
- #6 Copy the SQLite dlls to the MopriaCloudService webapp folder.
Yes, I know what you may be thinking. Why do we need to do this? Surely this can be abstracted away and made unnecessary for solution implementation…We all agree, as does the MSFT product team who are looking to streamline much of this workflow.Use this script below making sure that you have referenced the right SQLite package version numbers. Change the version numbers to reflect the version for your downloaded packages. Having 2 variables would obviously not be necessary if your SQLite package versions matched, as was the case in version 1.0.108.0, etc.
$SourcePath = "C:\Program Files\PackageManagement\NuGet\Packages" $SQLiteVersion = "1.0.109.2" #The SQLLite version that you installed $SQLiteVersion2="1.0.109.0" #The second SQLite version referenced in packages. $DesPath = "C:\inetpub\wwwroot\MopriaCloudService" Copy-Item -Path "$SourcePath\System.Data.SQLite.Core.$SQLiteVersion\lib\net46\System.Data.SQLite.dll" -Destination "$DesPath\bin\System.Data.SQLite.dll" -Force -Verbose if (!(Test-Path "$DesPath\bin\x86")) { New-Item -Path "$DesPath\bin\x86" -ItemType Directory -Verbose } Copy-Item -Path "$SourcePath\System.Data.SQLite.Core.$SQLiteVersion\build\net46\x86\SQLite.Interop.dll" -Destination "$DesPath\bin\x86\SQLite.Interop.dll" -Force -Verbose Copy-Item -Path "$SourcePath\System.Data.SQLite.Core.$SQLiteVersion\build\net46\x64\SQLite.Interop.dll" -Destination "$DesPath\bin\x64\SQLite.Interop.dll" -Force -Verbose Copy-Item -Path "$SourcePath\System.Data.SQLite.Linq.$SQLiteVersion2\lib\net46\System.Data.SQLite.Linq.dll" -Destination "$DesPath\bin\System.Data.SQLite.Linq.dll" -Force -Verbose Copy-Item -Path "$SourcePath\System.Data.SQLite.EF6.$SQLiteVersion2\lib\net46\System.Data.SQLite.EF6.dll" -Destination "$DesPath\bin\System.Data.SQLite.EF6.dll" -Force -Verbose
- #7 Update the C:\intepub\wwwroot\MopriaCloudService\web.config file to include the SQLite version in the relevant runtime/assembly sections. Update SQLite package version numbers accordingly.
- #8 Create the SQLite database
- Download and install the SQLite tools binaries from https://www.sqlite.org/
- Navigate to the “C:\inetpub\wwwroot\MopriaCloudService\Database” directory
- Run the following command to create the database:
sqlite3.exe MopriaDeviceDb.db ".read MopriaSQLiteDb.sql"
Navigate to the MopriaDeviceDb database file from File Explorer, and under properties and the security tab, add the security group or users that will be granted permission to publish printers from MDM managed AAD joined devices. Grant the group full control of the file.
- #9 install Azure Application Proxy
If you don’t already have AAD App Proxy connectors, configure a Web Application Proxy role by downloading the App Proxy Connector from AAD, to a domain-joined Windows server machine and installing the connector. You can install multiple connectors but for this exercise, 1 connector will suffice.In the AAD workspace in the Azure portal, select Application Proxy, and click “Enable application proxy”
- #10 Create Web Apps for Hybrid cloud print in Azure AD
- In the Azure Portal, navigate to Azure Active Directory, and Enterprise applications tab.
- Click New Application and select On-premises application
- Provide required information for the Web API:
- Name: Any name for your web app. I’ve easily named mine, Odikslabprinterdiscovery
- Internal URL: This is the internal URL of the Mopria Discovery cloud service running in IIS. Format is https:// Name of your print server/mcs/
- External URL: Configure as appropriate. AAD will create a “msappproxy.bet/mcs/” URL for you but you can use your public domain name here, in format <https://public domain name/mcs/> if you prefer.
- Preauthentication Method: Click drop down and select passthrough
- Connector Group: Select the connector group for your AAD Application Proxy connector(s) if you have one, if not, use Default
- While still in the Web app, click on Users and groups, and add security groups containing admin users who can publish printers, and users who will discovery and use printer resources.
- Navigate to Azure Active Directory –> App Registrations –> click drop down and select All apps and select the corresponding App registration for your Hybrid cloud print Web API.
- In the App registration blade for the Web API, click Settings, and select Properties. Change the App ID URI to http://MopriaDiscoveryService/CloudPrint
- While still in the App Registration blade for the Web API, click Required permissions, and click on Windows Azure Active Directory. Ensure that it has Sign in and read user profile delegated permissions. and Grant Permissions.
- #11 Repeat steps for number 10 Above for the Enterprise Cloud Print (ECP) service.
- Name: Any name for your web app. I’ve named mine, OdikslabCloudPrintProxy
- Internal URL: This is the internal URL of the Mopria Discovery cloud service running in IIS. Format is https:// Name of your print server/ecp/
- External URL: Configure as appropriate. AAD will create a “msappproxy.bet/ecp/” URL for you but you can use your public domain name here, in format <https://public domain name/ecp/> if you prefer.
- Preauthentication Method: Click drop down and select passthrough
- Connector Group: Select the connector group for your AAD Application Proxy connector(s) if you have one, if not, use Default
Make sure to add security groups to the users and groups tab for the Web app, and under settings –> Properties, change the app ID URI for this second web app to http://MicrosoftEnterpriseCloudPrint/CloudPrint
Navigate to on-premises Print server hosting the Print service resources and review registry settings:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\CloudPrint\MopriaDiscoveryService
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\CloudPrint\EnterpriseCloudPrintService
Ensure that APP ID URI values defined for the Web APIs are reflected in the registry AzureAudience values
- #12 Create Native client application in Azure AD
- Navigate to Azure Active Directory –> App Registration –> New Application Registration.
- Fill in information for:
- Name: Give your native app a name. Mine is OdiksLabPrintNativeClient
- Application type: Native
- Redirect URI: ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-3784861210-599250757-1266852909-3189164077-45880155-1246692841-283550366
- In the Native app, click Settings –> Redirect URIs, and and the following redirect URI to the list:
ms-appx-web://Microsoft.AAD.BrokerPlugin/<NativeClientApplicationID> - Click on Required Permissions, and add permissions to native client for both Hybrid Cloud print web APIs, and verify delegations for Windows Azure Active Directory, as shown above.
- #13 Configure the Required MDM Policies
Perform these tasks with any MDM provider in use within your organization. For illustration, I am using the Intune service.- In the Azure Portal, search for and select the Intune service. Navigate to Device Configuration –> Profiles –> Create Profile.
- Give the profile a Name, under Platform, select Windows 10 and later, and under Profile Type, select Device restrictions –> Cloud Printer
- Input the following settings for the Cloud Printer:
- Printer discovery URL: This is the web printer discovery endpoints. It is the external Url of your printer discovery web API. In my case, https://odikslabprinterdiscovery-odikslab.msappproxy.net/mcs/
- Printer access authority URL: Azure tenant directory ID: https://login.microsoftonline.com/< Enter your AAD Directory ID here>
- Azure native client app GUID: Application ID for your native client created in STEP #12 above. Find this in properties of the app
- Print service resource URI: This is the App ID URI for your enterprise cloud print service web API. http://MicrosoftEnterpriseCloudPrint/CloudPrint
- Maximum printers to query (Mobile only): enter a positive integer value here
- Printer discovery service resource URI: This is the App ID URI for your discovery web API. http://MopriaDiscoveryService/CloudPrint
Note: If your MDM provider doesn’t support the Cloud Print policy Group, you can set the same policies using OMA-URI settings if your provider supports it.
The OMA-URI configs should look like this:
- CloudPrintOAuthAuthority
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/CloudPrintOAuthAuthorityData type: string
Value: https://login.microsoftonline.com/<Azure AD Directory ID> - CloudPrintOAuthClientId
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/CloudPrintOAuthClientIdData type: string
Value: Application ID for your native client created in STEP #12 above - CloudPrinterDiscoveryEndPoint
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/CloudPrinterDiscoveryEndPointData type: string
Value: This is the web printer discovery endpoints. It is the external Url of your printer discovery web API. In my case: https://odikslabprinterdiscovery-odikslab.msappproxy.net/mcs/ - MopriaDiscoveryResourceId
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/MopriaDiscoveryResourceIdData type: String
Value: http://MopriaDiscoveryService/CloudPrint - CloudPrintResourceId
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/CloudPrintResourceIdData type: String
Value: http://MicrosoftEnterpriseCloudPrint/CloudPrint - DiscoveryMaxPrinterLimit
OMA-URI: ./Vendor/MSFT/Policy/Config/EnterpriseCloudPrint/DiscoveryMaxPrinterLimitData type: Integer
Value: a positive integer value to define the maximum number of printers discovered.
Once done with the hybrid cloud print MDM policies, save your settings, and assign the policy to your user group of user accounts allowed to use Cloud Print resources.
- #14 Confirm that MDM policy is successfully applied.
- Logon to a Azure AD joined MDM managed Windows 10 machine with a user account that is assigned MDM policies.
- From the Start Menu, search for and open Printers & Scanners. Verify that you see an option to “Search for cloud printers”
You can further confirm by checking registry settings on the client machine:
HLKM\SOFTWARE\Microsoft\PolicyManager\current\S-1-12-1-.xxxx
- #15 Publish Shared Printers
NOTE: Log on to a Azure AD joined Windows 10 machine with a user account that is a member of your Admin security group with permissions to the Mopria database files and print server management rights as described in steps #2 and #8 respectively.- Run the following commands from an elevated PowerShell command prompt
Find-Module -Name "PublishCloudPrinter" Install-Module -Name "PublishCloudPrinter" Import-Module PublishCloudPrinter
NOTE: You may see a messaging stating that ‘PSGallery’ is an untrusted repository. Enter ‘y’ to continue with the installation.
- Run the Publish-CloudPrinter command using the following parameters:
- Printer: The name of the shared printer installed on the Print Server that you would like to use
- Manufacturer: The printer manufacturer
- Model: The Printer Model
- OrgLocation: A JSON string specifying the printer location. E.g.:
{“attrs”: [{“category”:”country”, “vs”:”USA”, “depth”:0}, {“category”:”organization”, “vs”:”your org Name“, “depth”:1}, {“category”:”site”, “vs”:”your org site“, “depth”:2}, {“category”:”building”, “vs”:”Main Office“, “depth”:3}]} - Sddl: SDDL string representing permissions for the printer. You can use the string below for all printers:
O:BAG:SYD:(A;;LCSWSDRCWDWO;;;S-1-5-21-2239587960-226070004-4116843781-45806)(A;OIIO;RPWPSDRCWDWO;;;S-1-5-21-2239587960-226070004-4116843781-45806)(A;OIIO;GA;;;CO)(A;OIIO;GA;;;AC)(A;;SWRC;;;WD)(A;CIIO;GX;;;WD)(A;;SWRC;;;AC)(A;CIIO;GX;;;AC)(A;;LCSWDTSDRCWDWO;;;BA)(A;OICIIO;GA;;;BA) - Discovery Endpoint: It is the external Url of your printer discovery web API. In my case, https://odikslabprinterdiscovery-odikslab.msappproxy.net/mcs/
- PrintServerEndpoint: The external URL address of the enterprise cloud print service web API. In my case: https://odikslabcloudprintproxy-odikslab.msappproxy.net/ecp/
- AzureClientId: The Application ID of the registered printer native client app
- AzureTenantGuid: Azure AD tenant directory ID
NOTE: You can use the specific Sddl value for a on-premises printer resource when you publish it, or use the Sddl value defined above. I have found it extensive testing that this works for multiple printers, without incident.
To publish the virtual printer installed in my on-premises Print server, I can therefore use the following command:
Publish-CloudPrinter -Printer EcpPrintTest -Manufacturer Microsoft -Model FilePrinterEcp -OrgLocation ‘{“attrs”: [{“category”:”country”, “vs”:”USA”, “depth”:0}, {“category”:”organization”, “vs”:”ODIKSLAB”, “depth”:1}, {“category”:”site”, “vs”:”Chicago, IL”, “depth”:2}, {“category”:”building”, “vs”:”Main Office”, “depth”:3}]}’ -Sddl “O:BAG:SYD:(A;;SWRC;;;WD)(A;;SWRC;;;AC)(A;CIIO;RC;;;AC)(A;OIIO;RPWPSDRCWDWO;;;AC)(A;;LCSWSDRCWDWO;;;S-1-5-21-2084019512-1293031765-2771479870-1136)(A;OIIO;RPWPSDRCWDWO;;;S-1-5-21-2084019512-1293031765-2771479870-1136)(A;CIIO;RC;;;CO)(A;OIIO;RPWPSDRCWDWO;;;CO)(A;OIIO;RPWPSDRCWDWO;;;S-1-5-21-2084019512-1293031765-2771479870-1105)(A;;LCSWSDRCWDWO;;;S-1-5-21-2084019512-1293031765-2771479870-1105)(A;OIIO;RPWPSDRCWDWO;;;BA)(A;;LCSWSDRCWDWO;;;BA)” -DiscoveryEndpoint “https://odikslabprinterdiscovery-odikslab.msappproxy.net/mcs/” -PrintServerEndpoint “https://odikslabcloudprintproxy-odikslab.msappproxy.net/ecp/” -AzureClientId “248f6b83-xxxx-xxxx-xxxx-xxxxxxxxxxx” -AzureTenantGuid “eff949f8-xxxx-xxxx-xxxx-xxxxxxxxxxx” -DiscoveryResourceId “http://MopriaDiscoveryService/CloudPrint
- Confirm that Publish-CloudPrinter command completed successfully
Once published, you can now search for the printer on any Azure AD-joined, and MDM-managed Windows 10 device with a permitted user account, and search for the Cloud Printer.
Once you install the printer, you can Manage the printer, and print to it from said device.
You can review detailed printing activity in the Print server event logs at Applications and Services Logs –> Microsoft –> Windows –> Print Service/Operational
- Run the following commands from an elevated PowerShell command prompt
And that’s it folks! You are now well on your way to leveraging your AD and printing investments for BYOD scenarios, and supporting printing for while away from the Corpnet scenarios. I’ll reiterate that this workflow is rather complex at this time, and the MSFT product team is working to streamline this so that you won’t have to perform such terribly exciting tasks as manually updating dlls, and runtimes, and parsing config files.
Cheers!
Latest posts by Chiyo Odika (see all)
- Replicate Proximity Placement Group workloads in Azure - January 13, 2021
- Azure NetApp Files (ANF) – Deploy with JSON - October 9, 2020
- Addressing Critical ZeroLogon Vulnerability CVE-2020-1472 - September 26, 2020