Free IT Guide · ChromeOS · Google Cloud · Microsoft NDES
Migrate ChromeOS Secure SCEP to Google’s Certificate Provisioning API
In this walkthrough, we’ll configure the Google Cloud Certificate Connector, the Pub/Sub permissions, a SCEP Certificate Authority connection, and a ChromeOS provisioning profile. I’ll also cover the issues we encountered in a large deployment, including a JSON syntax mistake in the published example and the difference between a certificate being issued and successfully installed on a Chromebook.
The instructions work for both a new deployment and a migration from legacy Secure SCEP. Every migration-only step is clearly labeled so you can skip it during a fresh deployment.
What this configuration does
ChromeOS obtains its certificate through a Google-managed provisioning process. The connector, running on Windows, subscribes to Google Cloud Pub/Sub and communicates with your SCEP endpoint. You do not need to publish the internal NDES endpoint to the public internet, although the connector requires outbound access to Google Cloud and internally to NDES.
Before you begin
- A Google Cloud project with a billing account enabled for Pub/Sub.
- ChromeOS 138 or newer on test devices.
- Google Cloud Certificate Connector 5.21 or newer on Windows.
- A working CA/SCEP service, such as Microsoft NDES; know its HTTPS SCEP URL and whether the deployment uses a static challenge.
- Google Admin rights for network/certificate policies and Google Cloud permissions to manage APIs, Pub/Sub, service accounts, and IAM.
- A small test OU and a Chromebook with temporary network connectivity that does not rely on the certificate being provisioned.
1. Verify the connector and locate any legacy profile
On the Windows connector host, locate connector.exe in the installed Google Cloud Certificate Connector directory. Right-click it, choose Properties → Details, and confirm the Product version is at least 5.21. If the Product version field is empty, Google’s guide says to upgrade.
2. Configure Google Cloud
2.1 Enable the Chrome Management API
- Open the Google Cloud Console and select the intended project. Confirm that billing is connected.
- Go to APIs & Services → Library.
- Search for Chrome Management API, open it, and select Enable.
2.2 Create a Pub/Sub topic and subscription
- In Google Cloud Console, search for Pub/Sub, then choose Topics → Create topic.
- Give the topic a meaningful ID, such as
cert-provisioning-api. - Keep Add a default subscription selected, then choose Create.
- Record the actual subscription name shown under Pub/Sub → Subscriptions. A default subscription commonly uses
projects/PROJECT_ID/subscriptions/TOPIC_ID-sub.
Copy the complete subscription resource name. The configuration generator below will use the same value.
2.3 Give Google’s publishing account the Publisher role
- Navigate to IAM & Admin → IAM → Grant access.
- Enter
cert-provisioning-api-pubsub-publisher@system.gserviceaccount.com. - Assign the role Pub/Sub Publisher and save.
Why two accounts? Google’s system service account publishes requests. Your separate connector service account reads them. Giving the publishing account Subscriber permissions does not fix connector read failures.
2.4 Create the connector’s service account
- Open IAM & Admin → Service accounts → Create service account.
- Choose a descriptive name such as
gccc-pubsub-subscriber; create and continue. - Assign Pub/Sub Subscriber (
roles/pubsub.subscriber) and finish. - Verify the role applies to the project containing the new subscription, or explicitly to that subscription.
- Copy the new service account’s email address. You’ll use it in Google Admin in the next step.
3. Create the Certificate Authority connection in Google Admin
In Google Admin → Devices → Networks, scroll to Certificates → Certificate Authority connections and choose Add connection.
- Select SCEP Certificate Authority connection as the type.
- Enter a descriptive connection name.
- Enter the connector service account email created in step 2.4 (not Google’s system publisher account).
- Enter the Pub/Sub topic resource name for this project.
- Choose a unique CA connection configuration identifier such as
campus-devices-scep. - Click Add and record the identifier exactly. It must match
ca_connection_config_idin the JSON.
Google describes CA connections as domain-wide, not OU-specific. Testing is controlled using the provisioning profile’s OU assignment.
4. Create a ChromeOS certificate provisioning profile
- In Google Admin go to Devices → Networks and select a small test OU.
- Under Certificates → Certificate provisioning profiles, click Add profile.
- Choose the CA connection created in step 3.
- Set a descriptive profile name and select the appropriate device platform.
- Configure renewal, authentication type, key usage, certificate subject, SANs, certificate template, and key type, then click Add.
${DEVICE_ASSET_ID} and ${DEVICE_ANNOTATED_LOCATION} are not supported by the new profile. Keep old and new profiles simultaneously during validation.Renewal: The profile allows 1–90 days before expiration. This is the renewal trigger, not the certificate lifetime; the CA controls validity. Google’s guide suggests 30 days as a common choice for a one-year certificate. Select RSA 2048 or supported ECC 256 as appropriate for your CA and clients.
5. Install and configure the Google Cloud Certificate Connector
5.1 Download the connector and service account key
- From Google Admin → Devices → Networks → Certificates → Certificate Authority connections, choose Download connector if this is a fresh installation.
- Install it on a Windows host with network connectivity to the SCEP URL and outbound HTTPS to Google.
- In Google Cloud Console open IAM & Admin → Service accounts and select the connector subscriber service account.
- Select Keys → Add key → Create new key → JSON → Create. Put the downloaded credential JSON in the connector installation directory as
adapter_key.json(or another name you choose in the generator). - Restrict local access to this private key to the connector service identity and administrators. Never paste the JSON private key into a website form or support chat.
5.2 Configure the optional SCEP challenge
If your SCEP endpoint requires a static challenge, create challenge-file.txt in the connector directory and put the challenge string inside. Google describes recovering the legacy value from the Secure SCEP HTML or the NDES /mscep_admin page; do not post or share it.
5.3 Generate adapter_config.json
This is where I recommend using the interactive builder. Enter your own project/subscription, CA configuration identifier, SCEP URL, and local filenames. Use the legacy section only if migrating so existing devices can continue receiving old-profile certificates.
Build your connector configuration
Complete the required fields to generate your configuration.
{}
Runs entirely in your browser. It does not request or save private key content, challenge secrets, or credentials.
Save adapter_config.json in the connector installation directory. Test the syntax in PowerShell before restarting:
Get-Content . dapter_config.json -Raw | ConvertFrom-Json
legacy_configuration using the existing response_topic and request_subscription values from config.json. The former poll_period setting is deprecated and can be omitted. With adapter_config.json present, the connector ignores the separate config.json, so keep the latter safely for rollback.5.4 Restart the connector and inspect events
Open services.msc and restart the Google Cloud Certificate Connector. Review relevant application events; use PowerShell to filter:
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
StartTime = (Get-Date).AddMinutes(-30)
} | Where-Object {
$_.ProviderName -match 'Google|Certificate Connector'
} | Select-Object TimeCreated, LevelDisplayName, Message | Format-List
Check Google Cloud Pub/Sub subscription permissions, connector events, and NDES IIS logs rather than treating every informational polling entry as a failure.
6. Test the complete enrollment path
- Keep a Chromebook in the test OU online, on ChromeOS 138+, with a network connection that works before the new certificate is installed.
- Use
chrome://policyand choose Reload policies to confirm the new profile is assigned. - Open
chrome://certificate-managerand inspect provisioning status and certificate installation. - Check connector errors, Pub/Sub permissions, and SCEP-related IIS logs.
- On the CA, confirm whether the test device request is issued, rejected, or pending. An issued CA certificate does not prove it reached the Chromebook.
- Only mark the test successful after the Chromebook has the certificate and can authenticate where intended.
7. Switch the Wi-Fi profile (legacy migrations only)
Common problems we encountered
The connector rejects adapter_config.json
Check for invalid JSON, particularly an extra trailing comma. Use ConvertFrom-Json before restarting the service.
Pub/Sub PermissionDenied on StreamingPull
Confirm that the subscriber service account referenced by adapter_key.json has roles/pubsub.subscriber on the project/subscription actually listed in request_subscriptions. The publishing account needs roles/pubsub.publisher. They’re not interchangeable.
(Get-Content . dapter_key.json -Raw | ConvertFrom-Json).client_email
PollOnOperationForSignature: operation is not done yet
This is an in-progress signing-operation poll, not definitive proof of a failure. With many active devices, queueing and retries may complicate diagnosis. Check whether a specific pilot Chromebook eventually progresses rather than increasing concurrency or enabling debug logs across a large fleet immediately.
NDES returns HTTP 200 and the CA issues, but the Chromebook has no certificate
In IIS, successful GetCACert, GetCACaps and PKIOperation calls demonstrate HTTP-level processing, not end-to-end delivery. Verify the certificate on the Chromebook, and correlate connector events with the CA request time. In our rollout, a test device began receiving the certificate after moving to an internal guest network with an ACL allowing TCP 443 toward our certificate host. That was an observed network change, not a documented universal requirement for direct Chromebook-to-NDES connectivity. Use firewall logs or packet captures to establish the actual destination before broadly opening access.
Too many Chromebooks provisioning together
Use a pilot OU, then expand gradually. Watch connector errors, request volume, CA issuance and, most importantly, device certificate installation. The guide recommends phased migration rather than immediate root-OU rollout.
Rollback and cleanup
adapter_config.json, verify the original config.json remains, and restart the connector as Google documents. Do not delete the legacy SCEP profile while devices still depend on it. Once devices have working new certificates and Wi-Fi has been verified, retire the old profile and legacy config according to your change plan.Conclusion
The new API is straightforward once the three moving pieces line up: Google Cloud Pub/Sub identities, the connector-to-CA configuration, and the ChromeOS policy assignment. Test against a small OU, validate certificate installation—not just issuance—and keep legacy enrollment available until you’re confident in the new process.
Reference: Google LLC, Migrating from legacy SCEP to Certificate Provisioning API (2026), 18-page migration guide provided with this article.
Anthony V

Leave a Reply