We often discuss what are the most blockers moving to Modern Management from Traditional Management? e.g. Deploy Win32 applications.
What about printers? Let’s say if customers only use web applications, they need to print out some paper work continually, they already have many on-premises network printers all over the building, and they want move their devices to Modern Management. So what solutions do we have?

Few days ago I did some search, found this Ignite 2017 video “Solving your printing problems with Windows Server and Microsoft Azure“, this is exactly what I was looking for.

(In this point I really wish that I had attend Ignite  🙂  Maybe someday…)

So what is Microsoft Hybrid Cloud Print?

I would say this in a simple way:
By using Hybrid Cloud Print, user can add and print to on-premises printers over internet or corporate network on a Azure AD joined Windows 10 device.

Quote from Microsoft:

Hybrid Cloud Print provides secure user access to on-premises printers by using Azure’s multi-factor authentication to validate user access. Single sign-on (SSO) functionality simplifies the user experience. Hybrid Cloud Print is built on Windows Print Server role, giving IT Pros an experience that is similar to managing printers and user access security.

Hybrid Cloud Print allows people in your organization to print from the devices they use to complete their work – even when they are away from their desk or workplace.

Hybrid Cloud Print is supported in Windows 10 Creators Update and Windows 10 S.

 

Does it work?

Oh yes! I tested that for the past three days! I couldn’t write about this if it didn’t work. 🙂

Requirements:

  • Azure AD premium subscription
  • MDM service, such as Intune or EMS
  • Windows Server running as Active Directory
  • Domain joined Windows Server 2016 running as Print Server
  • Azure AD Connect
  • Azure Application Proxy Connector
  • Public facing domain name
  • Windows 10 Creators Update or Windows 10 S
  • Printer

My setups:

  • Domain controller: DC02.ZIT.local
  • Azure AD Connector: ADConnector01.ZIT.local
  • Print Server: PrintServer01.ZIT.local
  • Azure Application Proxy Connector: PrintServer01.ZIT.local (You should install that to a separated server, but I am running out of memories in my Hyper-V host, so I installed Azure Application Proxy Connector to same box as print server)
  • Azure AD joined Windows 10 1709 Enterprise: Client01-AAD
  • Network printer: Samsung ML-3310ND
  • Public domain name: smsboot.com
  • Internal domain name: ZIT.local
  • Azure Active Directory name: smsboot.onmicrosoft.com
  • A service account that has Print Server management rights and also synced to Azure AD:  Svc-CloudPrint-Admin@smsboot.com, I gave the service account administrator rights.

Steps by steps:

Step 1 – Install Azure AD Connector

I don’t go through all the small details here, you will find lots of information all over internet, I use “Sync Password” and “Single Sign-on” settings.

Step 2 – Install Print Server Role (PrintServer01.ZIT.local)

  1. Install Print Server Role

  2. Install the Hybrid Cloud Print PowerShell modules
    Run the following commands from an elevated PowerShell command prompt:

    Find-Module -Name "PublishCloudPrinter"
      
    Install-Module -Name "PublishCloudPrinter"
    
    Import-Module PublishCloudPrinter

     

  3. Install the Hybrid Cloud Print solution
    Run the following commands from an elevated PowerShell command prompt:

    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>
    
    

    In my case:

    .\CloudPrintDeploy.ps1 -AzureTenant "smsboot.onmicrosoft.com" -AzureTenantGuid "7d869a9a-681c-4ba0-9c08-xxxxxxxxxxx"

     

Step 3 – Create certificates (PrintServer01.ZIT.local)

The SSL certificate can be a self-signed cert or one issued from some trusted Certificate Authority (CA).
Here I use self-signed certs as example, because not everyone want to buy SSL certs for test lab.
You will need two certificates, one for internal print server, another for application proxy public domain.
Run the following commands from an elevated PowerShell command prompt:

  1. Certificate for printserver01.ZIT.local IIS.
    Note: The SSL certificate can be a self-signed (as the PowerShell commend does) or issue from trusted certificate authority
    If using a self-signed cert, you have to deploy the cert to your clients.

    $cert = New-SelfSignedCertificate -DnsName "PrintServer01.ZIT.local" -CertStoreLocation "cert:\LocalMachine\My"
    
    $password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
    
    if (!(Test-Path "C:\Temp\Cert")) {
     New-Item -Path "C:\Temp\Cert" -ItemType Directory -Verbose
    }
    
    Export-PfxCertificate -Cert $cert -FilePath "C:\Temp\Cert\PrintServer01.pfx" -Password $password
    
    Export-Certificate -Type CERT -Cert $cert -FilePath "C:\Temp\Cert\PrintServer01.cer"
    
    Import-PfxCertificate -FilePath "C:\Temp\Cert\PrintServer01.pfx" -CertStoreLocation "Cert:\LocalMachine\Root" -Password $password
  2. Add the certificate to IIS Binding:
  3. Create certificate for Application Proxy public domain (for later use), save it as smsboot.com.pfx
    Note: The SSL certificate can be a self-signed (as the PowerShell commend does) or issue from trusted certificate authority
    If using a self-signed cert, you have to deploy the cert to your clients.

    $cert = New-SelfSignedCertificate -DnsName "*.smsboot.com" -CertStoreLocation "cert:\LocalMachine\My"
    $password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
    
    if (!(Test-Path "C:\Temp\Cert")) {
     New-Item -Path "C:\Temp\Cert" -ItemType Directory -Verbose
    }
    
    Export-PfxCertificate -Cert $cert -FilePath "C:\Temp\Cert\smsboot.com.pfx" -Password $password
    
    Export-Certificate -Type CERT -Cert $cert -FilePath "C:\Temp\Cert\smsboot.com.cer"

Step 4 – Install and configure SQLite (PrintServer01.ZIT.local)

  1. Install SQLite package
    Run the following commands from an elevated PowerShell command prompt:

    Register-PackageSource -Name nuget.org -ProviderName NuGet -Location https://www.nuget.org/api/v2/ -Trusted -Force
    Install-Package system.data.sqlite -providername NuGet

     

  2. Copy the SQLite dlls to the MopriaCloudService Webapp folder
    NOTE: Change SQLiteVersion as the SQLite version what you installed.

    $SourcePath = "C:\Program Files\PackageManagement\NuGet\Packages"
    
    $SQLiteVersion = "1.0.106.0" #The SQLLite version that you installed
    
    $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.$SQLiteVersion\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.$SQLiteVersion\lib\net46\System.Data.SQLite.EF6.dll" -Destination "$DesPath\bin\System.Data.SQLite.EF6.dll" -Force -Verbose
  3. Update the C:\inetpub\wwwroot\MopriaCloudService\web.config  file, change version number as the one you installed.

  4. Download latest SQLite Tool from https://www.sqlite.org
    In this moment latest SQLiteTools is :  https://www.sqlite.org/2018/sqlite-tools-win32-x86-3230000.zip
    Unzip it to C:\Temp
  5. Run the following commands from an elevated command prompt (not in PowerShell):
    cd "C:\inetpub\wwwroot\MopriaCloudService\Database"
    
    "C:\Temp\sqlite-tools-win32-x86-3230000\sqlite3.exe" MopriaDeviceDb.db ".read MopriaSQLiteDb.sql"

    You should see a new file MopriaDeviceDb.db is created.

  6. Open up the MopriaDeviceDb.db file properties to add Users/Groups which are allowed to publish to Mopria database in the Security tab. Recommend only adding the required Admin user group.

Step 3 – Install Azure Application Proxy Connector

  1. Log on to Azure Portal
  2. Go to Azure Active DirectoryApplication proxy, Click on Enable application proxy
  3. Download the “Application Proxy Connector” to a domain joined Windows Server that will act as the Web Application Proxy (WAP), in my case I installed it to my print server
  4. After application proxy connector is installed, you should see the connector in your portal.

Step 4 – Add Application proxies for Hybrid Cloud print

We will need create two enterprise applications, one for printer discovery, another one for printing.

Create enterprise application for printer discovery
  1. Go to Azure Active DirectoryEnterprise applications, Click on New application

  2. Choose On-premises application

  3. This proxy application is for printer discovery.
    Fill the following information
    Name: DemoMopriaDiscoveryProxy
    Intenal Url: https://your print server/mcs/, in my case: https://PrintServer01.ZIT.local/mcs/
    External Url: I change it to a shorter name example: mcs, and choose your public domain name, in my case smsboot.com

    Update: You don’t have to use your public domain name, you can use the default generated msappproxy.net as well, so that you don’t need deploy the additional certs to your clients.


    Pre Authentication: Passthrough
    Remember: Configure a CNAME entry in your DNS provider.

  4. Click on Users and groups, assign this application DemoMopriaDiscoveryProxy to a user group that allow to use Cloud Print services
    VERY IMPORTANT: Assign this application DemoEnterpriseCloudPrintProxy to Svc-CloudPrint-Admin@smsboot.com, because it need permission to use this enterprise application to publish printers.
  5. Click on Application proxy, Click on Click here to upload a certificate
    Choose the certificate smsboot.com.pfx what we created on above Step 3 – Create certificates
    If you have a public certificate, you can import your public certificate.
  6. Go back to Azure Active DirectoryApp registrations

    You might see app list is empty, don’t panic, change My apps to All apps

  7. Click on DemoMopriaDiscoveryProxy
    Go to SettingsProperties
    Change App ID URI to: http://MopriaDiscoveryService/CloudPrintVERY IMPORTANT: If you change any settings from Enterprise Applications, you must check App registration settings again, and make sure App ID URI is correct.

  8. Click on Required permissions, make sure you have API Windows Azure Active Directory delegated permissions to option Sign in and read user profile
    If you don’t see it there, Add the permission.

  9. After permission is added, client on Grant Permissions, then click Yes

Create enterprise application for printing
  1. Create a new Enterprise application
    Fill the following information
    Name: DemoEnterpriseCloudPrintProxy
    Intenal Url: https://your print server/ecp/, in my case: https://PrintServer01.ZIT.local/ecp/
    External Url: I change it to a shorter name example: ecp, and choose your public domain name, in my case smsboot.com

    Update: You don’t have to use your public domain name, you can use the default generated msappproxy.net as well, so that you don’t need deploy the additional certs to your clients.

    PreAuthentication: Passthrough
    Remember: Configure a CNAME entry in your DNS provider.

  2. Click on Users and groups, assign this application DemoEnterpriseCloudPrintProxy to a user group that allow to use Cloud Print services
  3. Click on Application proxy, Click on Click here to upload a certificate
    Choose the certificate smsboot.com.pfx what we created on above Step 3 – Create certificates
    If you have a public certificate, you can import your public certificate.
  4. Go back to Azure Active DirectoryApp registrations
  5. Click on DemoEnterpriseCloudPrintProxy
    Go to SettingsProperties
    Change App ID URI to: http://MicrosoftEnterpriseCloudPrint/CloudPrint

    VERY IMPORTANT: If you change any settings from Enterprise Applications, you must check App registration settings again, and make sure App ID URI is correct.

  6. Grant permissions. follow the same steps as DemoMopriaDiscoveryProxy (see above 8-9)

VERY IMPORTANT:

If your internal domain name is not same as the public domain name, log on to your print server, in my case: printserver01.zit.local, change this URL registry to your print discovery endpoint external address, because machines are in external network cannot access to the internal printer discovery address, it has to be the external address that match the MDM policy we assign to the machines later steps.

Then run command: iisreset (or restart your IIS services)

 

Step 5 – Create Native client application for cloud print

  1. Go to Azure Active DirectoryApp Registration, click New application registration
  2. Fill the flowing information, to create a native application
    Name: DemoPrintNativeClient
    Application type: Native
    Redirect URI:

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

  3.  After application is created, open this DemoPrintNativeClient again.

    SettingsRedirect URIs, add the following redirect URIs to the list:

    ms-appx-web://Microsoft.AAD.BrokerPlugin/<NativeClientApplicationID>

    In my case: ms-appx-web://Microsoft.AAD.BrokerPlugin/06050d0b-xxxxx-xxxx-xxxx-xxxxx-xxxxx

  4. Add permissions: DemoMopriaDiscoveryProxy, DemoEnterpriseCloudPrintProxy and Windows Azure Active Directory (permission: Sign in and read user profile)
    Then click on Grand Permissions, then click Yes

 

Step 6 – Configure the required MDM policies

  1. Go to IntuneDevice ConfigurationProfiles Create profile
  2. Choose as flowing:
    Platform: Windows 10 and later
    Profile type: Device restrictions – Cloud Printer

  3. Input the follow settings for Hybrid Cloud print:
    Printer discovery URL: External address of CloudPrinterDiscoveryEndPoint, in my case: https://mcs.smsboot.com/mcs/
    Printer access authority URL: https://login.microsoftonline.com/<Your Azure AD Directory ID>
    Azure native client app GUID: NativeClientApplicationID
    Print service resource URL: http://MicrosoftEnterpriseCloudPrint/CloudPrint
    Maximum printers to query(Mobile only): a positive number
    Printer discovery service resource URI:  http://MopriaDiscoveryService/CloudPrint

  4. Create a new profile for deploy trust certificates that we created on above Step 3.
    Both PrintServer01.cer and smsboot.com.cer

  5. Assign the policy to a user group that allow to use Cloud Print services

Step 7 – Deploy Certificate to clients

If you are using self-signed certificates for your print server and Proxy enterprise application, you have to deploy those certificates (PrintServer01.cer and smsboot.com.cer) to clients via GPO or MDM (See from this post “deploy Root CA to clients”).
If you are using msappproxy.net as your Proxy enterprise application address and using public certificate to your print server, then you don’t need deploy additional certs to clients

Step 8 – Publish Shared Printers

  1. VERY IMPORTANT:
    Log on Azure AD joined Windows 10
    as the user account that has print server print management rights, in my case: svc-CloudPrint-Admin@smsboot.com
  2. The account you use use needs to have administrator rights.
  3. Install the Hybrid Cloud Print PowerShell modules
    Run the following commands from an elevated PowerShell command prompt:

    Find-Module -Name "PublishCloudPrinter"
    
    Install-Module -Name "PublishCloudPrinter"
    
    Import-Module PublishCloudPrinter

     

  4. Run Publish-CloudPrinter command:
    Printer: The shared printer name that was defined
    Manufacturer: Printer manufacturer
    Model: Printer model
    OrgLocation: A JSON string specifying the printer location, e.g.:{“attrs”: [{“category”:”country”, “vs”:”Finland”, “depth”:0},
    {“category”:”organization”, “vs”:”SandyTestLab”, “depth”:1},
    {“category”:”site”, “vs”:”Joensuu,FI”, “depth”:2},
    {“category”:”building”, “vs”:”Home”, “depth”:3}]}}Sddl: SDDL string representing permissions for the printer. This can be obtained by modifying the Printer Properties Security tab appropriately and then running the following command in a command prompt:(Get-Printer “YourSharedPrinterName” -Full).PermissionSDDL

    Result: e.g. “G:DUD:(A;OICI;FA;;;WD)”
    NOTE: You will need to add O:BA as prefix to the result from the command prompt command above before setting the value as the SDDL setting. Example:SDDL = O:BAG:DUD:(A;OICI;FA;;;WD)DiscoveryEndpoint: https://<services-machine-endpoint>/mcs, the external address of DiscoveryEndpointProxy application
    PrintServerEndpoint: https://<services-machine-endpoint>/ecp, the external address of PrintEndpointProxy application
    AzureClientId: Application ID of the registered Native Web Application
    AzureTenantGuid: Your Azure AD tenant Directory IDThis is my example:
    (For testing purpose, you can use the virtual printer name EcpPrintTest)

    publish-cloudprinter -Printer "Samsung ML-3310ND" -Manufacturer "Samsung" -Model "ML-3310ND" -OrgLocation '{"attrs": [{"category":"country", "vs":"Finland", "depth":0}, {"category":"organization", "vs":"SandyTestLab", "depth":1}, {"category":"site", "vs":"Joensuu,FI", "depth":2}, {"category":"building", "vs":"Home", "depth":3}]}’ -Sddl "O:BAG:SYD:(A;;LCSWSDRCWDWO;;;S-1-5-21-501278528-1731656756-2472999879-1114)(A;OIIO;RPWPSDRCWDWO;;;S-1-5-21-501278528-1731656756-2472999879-1114)(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)" -DiscoveryEndpoint "https://mcs.smsboot.com/mcs/" -PrintServerEndpoint "https://ecp.smsboot.com/ecp/" -AzureClientId "06050d0b-08c2-xxxx-xxxx-xxxx-xxx" -AzureTenantGuid "8cfbf3fe-xxxxxxx-xxxxxx-xxxxx-xxxx"

    NOTE: The printer share name need to be same as the printer name.

Step 8 – Test the results

  1. Log on to a Azure AD joined Windows 10, sync user policies.
  2. Check if Hybrid Cloud print MDM policies are applied, you should see these registries.

  3. Open Printers & scanners, you should able to see a new setting show up Search for cloud printers
    In my experiences, after EnterpriseCloudPrint polices are applied, this setting page might crash, restart computer will fix that.
  4. You can click on search location or just use Search

  5. Install a printer

  6. If you use EcpPrintTest (it is a virtual test printer) to print out something from your windows 10 machine, you will find a file EcpTestprint.xps created to C:\EcpTestOutput folder in your print server.

    Print Server IIS log:

PowerShell command

Query cloud printer:

Publish-CloudPrinter -Query -DiscoveryEndpoint "External address of DiscoveryEndpoint" -AzureClientId "Natvie Client ID" -AzureTenantGuid "Azure AD ID"

Delete published cloud printer:

Publish-CloudPrinter -Unpublish -Printer "printer name" -DiscoveryEndpoint "external address of discovery endpoint" -PrintServerEndpoint "external address of printer serer endpoint" -AzureClientId "native client ID" -AzureTenantGuid "Azure AD ID"

 

I know this a bit messy, so I draw this map, hopefully help a bit about those internal address, external address, App ID URI.
This show what URI need to be matched, if change URI, then need to change another one to match it.

For more details, follow this:
https://docs.microsoft.com/en-us/windows-server/administration/hybrid-cloud-print/hybrid-cloud-print-deploy-passthrough

 

(2290)

Sandy has been working in the IT industry since 2009. Primarily dealing with SCCM, MDT, Group Policy, software packaging, workstation problem solving. Sandy currently works for a large Finnish company with several thousand endpoints. In 2016, Sandy founded the http://thesccm.com blog and is now a guest blogger on SCConfigMgr.

comments
  • Surjeet
    Posted at 23:20 January 22, 2018
    Surjeet
    Reply
    Author

    Superb blog although I haven’t tested this scenario but quite often you get question from customer around printing on premises on an Azure AD joined W10 machine…

  • Bruce
    Posted at 05:40 February 11, 2018
    Bruce
    Reply
    Author

    I love how you added “Printer” to the requirements! LOL

  • Oscar
    Posted at 10:37 February 28, 2018
    Oscar
    Reply
    Author

    Hi,
    One of your print screens of has “Azure authentication” one has “pass-through”.
    In this article: “https://docs.microsoft.com/en-us/windows-server/administration/hybrid-cloud-print/hybrid-cloud-print-deploy” it stay code as “ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-3784861210-599250757-1266852909-3189164077-45880155-1246692841-283550366” but in yours it is ending with digit 7. Like why all that differences?

    • Zeng Yinghua
      Posted at 10:37 March 1, 2018
      Zeng Yinghua
      Reply
      Author

      Hi, Yes I am using passthrough authentication, end of my post links to Microsoft doc https://docs.microsoft.com/en-us/windows-server/administration/hybrid-cloud-print/hybrid-cloud-print-deploy-passthrough. I don’t know why I had ending digit 7 in my post, my tenant has ending digit 6, must by a typo, thanks for pointing it out. Updated the post.

      • Jeff Lawrence
        Posted at 20:49 March 2, 2018
        Jeff Lawrence
        Reply
        Author

        Any chance you tested in pre-auth mode? The ms docs seem to indicate it works but in past testing it did not (windows enumeration didn’t handle it). Before I try all the steps to make it work wanted to see if you had tried that

        Great blog by the way!

        • Zeng Yinghua
          Posted at 01:53 March 6, 2018
          Zeng Yinghua
          Reply
          Author

          hello Jeff, thanks! I have tried pre-auth mode many times, but I didn’t get it work.

  • Julien Leger
    Posted at 20:18 March 29, 2018
    Julien Leger
    Reply
    Author

    Anyone know why the directory for ECP and MCS never gets created when running CloudPrintDeploy.ps1, I’m unable to proceed with deployment steps. I’ve tried on a fresh install of Server 2016 with same results. Any ideas?

    Could not find a part of the path
    ‘C:\inetpub\wwwroot\EnterpriseCloudPrint’
    ‘C:\inetpub\wwwroot\MopriaCloudService’
    Same with the underlying web.config…

  • Niklas
    Posted at 13:56 April 9, 2018
    Niklas
    Reply
    Author

    Hi,

    Great post, better than MS own docs.

    Have you had any experience in utilizing this to access printers across domains that have a two way trust?

    Regads

    • Zeng Yinghua
      Posted at 22:44 April 11, 2018
      Zeng Yinghua
      Reply
      Author

      Hi, I have not tested that in across domains scenarios. 🙂

  • Oscar
    Posted at 15:20 April 13, 2018
    Oscar
    Reply
    Author

    Finally, worked, used new server actually 🙂 Would be great if Azure Authentication can be checked too. Did try use Microsoft Article, but it fail as they seems has some issue in documentation.

  • Leave a Reply