Configuring Azure Application Proxy for Jamf Pro SCEP Certificates

The Short Version/tldr:

You may have SaaS or remote clients that need access to SCEP cert provisioning but your security team may not allow inbound connections from the DMZ to the internal network where your NDES Server is located. Read this Microsoft document that deals with this issue: Integrate with Azure AD Application Proxy on a Network Device Enrollment Service (NDES) server

The Long Version:

Jamf Pro can deliver certificates to managed devices if you integrate it with a certificate authority. This can get more complicated when hosting Jamf Pro on Jamf Cloud because many will be reluctant to set up an internet-facing CA or SCEP server. Since these servers typically run on internal networks, the network admin would need to create a route where they pass internet traffic through a reverse proxy or load balancer in their DMZ network zone. But connections from the DMZ to internal networks should be avoided where possible, so it would be even better if the network connections were initiated outbound from the internal network. This is a common issue for every app that an organization is moving to the cloud or implementing as SaaS but which requires connection to internal IT resources.

Microsoft Azure AD Application Proxy can be used to solve this problem.

Azure AD App Proxy includes two components, a cloud-based Proxy to which clients will connect instead of your internal resource’s URL, and an “Application Proxy Connector” that you’ll install on an internal Windows server. Clients like Jamf Pro will connect to the cloud URL provided by the Azure Application Proxy Service and the internal Microsoft Application Proxy Connector will reach outbound to the Azure proxy to retrieve HTTP connections. This Microsoft diagram shows the basic traffic flow…

In the case we’re talking about here, Jamf Pro is the client (the little blue person above) and NDES is the “Application”.

If you’re already using Microsoft Intune/Endpoint Manager to deploy AD CS-sourced certs to your Windows clients, this will sound really familiar to you. You probably already did the same basic setup as what we’re about to describe here. You might even be wondering if you couldn’t just use the same Azure app you just set up for Intune. You cannot. One your run Intune’s NDESConnectorSetup.exe on an NDES server, it alters the auth mechanism so that only traffic coming in from Intune will authenticate properly in IIS and any other client requests will get rejected.

So non-Intune applications are going to need a plain-vanilla NDES instance they can talk to.

How – To:

Step 1: Set up your AD Certificate Services and Microsoft NDES

Your organization most likely has a PKI infrastructure and an NDES instance may already be up and running as a part of that. If you don’t yet have NDES setup, you can add the role to a Windows server. Use a web browser to login to your NDES server’s /certsrv/mscep_admin page to make sure you know your NDES URL and the service account you’ll use to login to retrieve dynamic challenge codes. You should see a page like this…

Step 2: Set up Azure AD Application Proxy

Microsoft has step-by-step instructions here. If this is your first Azure App Proxy app, they’ll walk you through the install of the Connector software that needs to run on an internal server. If you already have app proxies for other applications you can reuse your existing on-premise Connector — you only need one. If you’re installing the Connector on Server 2019 or need to configure an outbound proxy (e.g. Bluecoat), read this page on Connector TLS requirements. My setup runs on Server 2016 and no outbound proxy or firewall. I didn’t have to mess with any of that.

Below there’s a screenshot of the Azure portal blade for the Application Proxy. For “Internal URL”, enter the hostname of your NDES Server. The External URL is what you’ll tell Jamf Pro to use when it needs to talk to your NDES Server. To generate the external URL, you enter a name (e.g., “jamfscepserver”, or whatever you want to call it) and select the tenant from the drop-down menu. The external Azure App Proxy and the internal Microsoft App Proxy Connector link the external and internal URLs together. Clients like Jamf Pro don’t even know that there’s a proxy involved.

Step 3: Test!

Once the App proxy is setup, test it by hitting <Microsoft's External Url>/certsrv/mscep_admin in a web browser and logging in with the NDES Service account before you do anything in Jamf Pro. If you see this page, you’re good to go. If you don’t, you probably made a mistake entering the internal url in the App Proxy setup, tried the wrong external URL in your browser, or have the wrong info for the NDES service account. The browser error will probably give you a pretty good idea about what’s wrong. Also, check if you have any conditional access rules on the Azure App that might be blocking you.

Step 4: Try a SCEP Profile in Jamf Pro

If you have an existing/known-good SCEP profile in Jamf Pro that relies on direct connections to the NDES server on your internal network, you could just clone that and change the URLs to the Azure versions, then scope that to a test device. It should work just as the direct/internal one does.

If you need to set up a SCEP profile for the first time, here are some notes about the settings. A screenshot from Jamf Pro appears below as well.

URLThe base URL for the SCEP server
In this example, we’re using the external URL Microsoft gave up when we set up the Azure AD Proxy App, followed by the standard path to NDES’s SCEP service.
NameThe CA-IDENT name of the issuing CA instance.
It’s what you see at the top of the tree when you run certsrv.
Redistribute ProfileRedistribute the profile automatically when its SCEP-issued certificate is the specified number of days from expiring. 15 Days
SubjectX.500 format. At minimum the cn=___ part is needed. Here, we’re going to use the $username that appears in Jamf Pro’s user and location info for the device. $hostname is used to make a cert with the machine name. Jamf Pro automatically tacks on the profile id part so it can track the cert down if it hits it’s auto-renewal date. CN=$,O=$PROFILE_IDENTIFIER
Challenge TypeType of challenge password to useDynamic-Microsoft CA
URL To SCEP Admin URL of the page to use to retrieve the SCEP challenge
Username/PasswordThe same user you’d use to log in to the SCEP Admin page in a web browserndes_service_account
Retries Number of times to retry after PENDING response3ADCS enrolls certs pretty fast, but it can’t hurt to retry a few times if yours sometimes gets busy and cert requests sit in pending status for a while.
Retry DelayNumber of seconds to wait before each retry. Set it higher if your CA gets busy sometimes. 10
Certificate Expiration Notification ThresholdThe number of days before the certificate expires at which to start showing the expiration notification10
Key Size Key size in bits
Use as digital signatureAsk your PKI gal/guy. Depends what the certs going to be used for. No
Use for key enciphermentAsk your PKI gal/guy. Depends what the certs going to be used for.No
Fingerprint Login to https://your.ndes.server/certsrv/mscep_admin — the thumbprint is displayed there. d0ad406e6619c7b7a1a974dc0fdbe8cd
Allow export from keychain 
Allow computer’s administrators to export private key from the keychain. I don’t know anybody who actually allows this. Maybe for troubleshooting? No
Allow all apps accessFor the typical 802.1x/VPN needs of macOS, leave this turned off. If you need some other app to be able to reach it, you can allow it, but that’s uncommon . No
CertificateLeave it blank if you use a trusted/third-party cert on your NDES. Otherwise, upload your SSL cert chain here. Blank. We use Let’s Encrypt certs so we’re pre-trusted.
Jamf Pro Certificate Profile Settings

Here’s a screenshot…

Once you scope that out to a test device and see it get its cert, you can scope it out to any devices that need a cert and set it as an automatic install.

Firewall rules

Your internal Microsoft Connector is only ever going to reach outbound to Microsoft and to their public CA to verify certificate validity so no firewall rules should allow inbound access to the Connector from either the internet or DMZ. Given the sensitivity of the service, your organization may even have a separate network zone for these things or use Windows Firewall to prevent incoming access from even your internal networks. If you are dedicating an NDES host to this service, you can use Windows Firewall on the NDES server to allow inbound 443 only from your internal Azure App Proxy Connector.

Azure App Proxy Conditional Access Rules don’t work with pass-through authentication

Since the Jamf Cloud source IP addresses are known, ideally, we would setup Jamf Pro to act as a SCEP Proxy and set an Azure AD conditional access rule to make sure only Jamf Cloud could connect to the Azure AD App Proxy. This won’t work because the certificate retrieval step of a SCEP flow is secured only by the dynamic challenge and the validity of those can only be verified by NDES… Azure has no knowledge of them. Therefore we have to set the App Proxy’s authentication to “passthrough” and Azure doesn’t apply conditional access rules (not even source IP) to this auth type. Ref:

Azure offers some built-in protections against denial of service that may prevent an attacker from flooding the App Proxy endpoint. Granted, a SCEP server may not be a very interesting target for DDOS, but you might want to use a dedicated NDES server with the App Proxy so only Jamf Pro’s cert requests are effected. The important thing is that the CA itself would not be effected. NDES will only connect to the CA when it receives a valid signing request and dynamic challenge password. Brute force against the service account used to obtain dynamic challenge would not be effective because Windows would disable the account after a number of bad password attempts. The number depends on your policies, but it’s typically set to 10.

You can block invalid traffic before it reaches your NDES server. Azure inserts x-forwarded-for so you have the option of putting a proxy in front that can have rules that check the headers. The “forwarded for” IP address should be one of the members of the limited set of Jamf Cloud’s AWS outbound NAT IP addresses. (See Jamf’s “Permitting inbound/outbound traffic with Jamf Cloud KB article.”

'HTTP_X_MS_PROXY' => 'AzureAD-Application-Proxy'

Normally you would not trust the IP in an X-forwarded for since the client could set that themself but in this case the header will always have been inserted by Azure. See IIS 8.0 Dynamic IP Address Restrictions for information on IP blocking in IIS.

Here are some screenshots that help explain how NDES works in case you’re not already familiar with that side of things…

You can get into certsrv from Server manager
Or you can just run certsrv from the admin command line
This is certsrv. In this example, the CA-Ident is “ca”. That’s what you put into the Name field in a Jamf Pro SCEP Profile
Right-click and select “Manage” on cert templates so we can check some details.
Unless your CA admin has selected something different, NDES uses the IPSEC Offline template.

You can right-click on the IPSEC Offline template and hit properties to see what it does.

These are the default settings but ask your CA admin what they do for validity period so you have some idea when your devices will need to renew their certificates. Make sure your cert profile renewal threshold is less than the template’s renewal period.
Jamf Pro and other SCEP clients specify the subject in the request so type of subject doesn’t matter.
You can see the key usage on the cert.
The NDES Service account you put into Jamf Pro for dynamic challenge retrieval has “Enroll” permissions on this template. The NDES role installer added this permission when you configured NDES.

2 thoughts on “Configuring Azure Application Proxy for Jamf Pro SCEP Certificates

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: