-
Notifications
You must be signed in to change notification settings - Fork 47
Add ChromeOS device identity certificates tutorial #545
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
llewis1234
wants to merge
16
commits into
smallstep:main
Choose a base branch
from
llewis1234:docs/chromeos-device-identity-certificates
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
09b6e94
Add Google Workspace WIF integration docs
hslatman 28081f9
Use `sts.googleapis.com` as audience in Google Workspace WIF
hslatman 0fbecca
Ignore `https://container.googleapis.com` in link checker
hslatman 4586a4a
Add Verified Access API to prerequisites
hslatman a61822d
Fix JSON markup
hslatman 3fbdd05
Ignore `../verifiedaccess.googleapis.com` in URL checker
hslatman 68fa44a
Update `k8s_sa` attribute
hslatman 28296ea
Add ChromeOS device identity certificates tutorial
llewis1234 2e60373
Cross-link ChromeOS troubleshooting to setup and cert-identity docs
llewis1234 32c1996
Link to the device identity certificates tutorial from Confirmation
llewis1234 8d96c02
Address review feedback on device identity certificate behavior
llewis1234 e5fbfda
Stop naming the attestation certificate as a user-facing concept
llewis1234 ef3a33a
Reframe Step 1 as confirming, not self-service choosing
llewis1234 31618a7
Clarify when forcing a fresh enrollment is actually needed
llewis1234 bcad58b
Fix unescaped <team-slug> placeholder breaking MDX compilation
llewis1234 e9f5348
Finish the incomplete Installation URL sentence
llewis1234 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| --- | ||
| updated_at: July 31, 2026 | ||
| title: Configure ChromeOS Device Identity Certificates | ||
| html_title: Configure ChromeOS Device Identity Certificates for mTLS | Smallstep | ||
| description: Issue mTLS-capable device identity certificates to ChromeOS devices enrolled in Google Workspace, for use in Wi-Fi, VPN, or internal application authentication. | ||
| --- | ||
|
|
||
| Smallstep issues a **device identity certificate** to ChromeOS devices enrolled through [Google Workspace](./connect-google-workspace-to-smallstep.mdx) — the certificate you'll use for mTLS: Wi-Fi (802.1X), VPN, or authenticating to internal applications. | ||
|
|
||
| This guide covers issuing that device identity certificate. It's a prerequisite for [ChromeOS Wi-Fi Enrollment](./protect-wireless-networks.mdx#chromeos-with-google-workspace-acme-device-attestation) and for any other mTLS use case involving ChromeOS devices. | ||
|
|
||
| # Prerequisites | ||
|
|
||
| - A completed [Connect Google Workspace to Smallstep](./connect-google-workspace-to-smallstep.mdx) integration, with devices syncing into Smallstep | ||
| - The Smallstep ChromeOS extension deployed to your target Organizational Unit (covered in that same guide) | ||
|
|
||
| A freshly enrolled device isn't ready for mTLS until you complete the steps below, even though it may already appear fully enrolled and "high assurance" in both the Smallstep dashboard and the Admin Console. | ||
|
|
||
| # Step-by-step instructions | ||
|
|
||
| ### 1. Confirm your issuing authority | ||
|
|
||
| The device identity certificate is issued from an authority in Certificate Manager, typically set up together with your Smallstep contact during onboarding rather than chosen independently. There are two conceptual patterns: | ||
|
|
||
| - **Device-bound** (e.g. a "Devices" authority) — binds the certificate to the device itself (subject is the hardware serial number). Use this for device-level authentication such as Wi-Fi. | ||
| - **User-bound** (e.g. an "Accounts" authority) — binds the certificate to the Google Workspace user currently signed in to the device (subject is the user's email). Use this if you need to authenticate the user rather than the device. | ||
|
|
||
| Confirm with your Smallstep contact which authority applies to your setup before continuing — the rest of this guide refers to it as "the authority you chose." | ||
|
|
||
| Both patterns support ACME Device Attestation, so the enrollment mechanics in the steps below are identical either way — only the resulting certificate's identity differs. | ||
|
|
||
| ### 2. Distribute the authority's trust root to Google Admin | ||
|
|
||
| This step must happen **before** step 3, not after. Each authority's ACME directory is served over TLS using a certificate signed by that authority's own private root. If the Chromebook doesn't already trust that root, it cannot reach the directory — the extension retries in the background, but nothing about this is visible: no error appears in the extension, in `chrome://policy`, or in the Smallstep dashboard, and the device keeps presenting its existing certificate until the root is in place. | ||
|
|
||
| 1. In Certificate Manager, go to **Authorities**, select the authority you chose in Step 1, and download its **Root Certificate** and **Intermediate Certificate**. | ||
| 2. In Google Admin, go to **Devices → Networks → Certificates**, select your target Organizational Unit, and add both certificates. Check ✅ **Enabled for Chromebook** for each. | ||
|
|
||
| <Alert severity="info"> | ||
| <div> | ||
| You can confirm whether trust distribution succeeded from your own computer, without touching a Chromebook at all: `curl -sS https://<authority>.<team-slug>.ca.smallstep.com/acme/acme-da/directory`. A TLS error like `unable to get local issuer certificate` means the root hasn't propagated yet or wasn't uploaded. A JSON response means you're clear to continue. | ||
| </div> | ||
| </Alert> | ||
|
|
||
| ### 3. Set the extension policy | ||
|
|
||
| The **Devices** authority is already the default: if that's what you chose in Step 1, the extension issues a device identity certificate from it automatically with just the `team` field, and you can skip to Step 5. | ||
|
|
||
| `devices_ca_directory_url` is only needed if you chose the **Accounts** authority instead, or need to point at a non-default Devices authority. In Google Admin, go to **Devices → Chrome → Apps & Extensions → Users & browsers**, select your Organizational Unit, and open the Smallstep extension's **Policy for extensions**. Add `devices_ca_directory_url`, pointing at the ACME Device Attestation directory of the authority you chose: | ||
|
|
||
| ```json | ||
| { | ||
| "team": { "Value": "<team-slug>" }, | ||
| "devices_ca_directory_url": { | ||
| "Value": "https://devices.<team-slug>.ca.smallstep.com/acme/acme-da/directory" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Use `devices.<team-slug>...` for the Devices authority, or `accounts.<team-slug>...` for the Accounts authority. | ||
|
|
||
| ### 4. Force a fresh enrollment | ||
|
|
||
| This step only applies if you completed the policy change in Step 3 — for example switching to the Accounts authority, or changing `devices_ca_directory_url` on a device that already has a valid certificate. The extension won't pick up a policy change on its own while it already holds a valid certificate, so a policy save alone has no effect. On the Chromebook: | ||
|
|
||
|
Comment on lines
+62
to
+65
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you have a specific use case for wanting to trigger this manually? |
||
| 1. In Google Admin, set the extension's **Installation policy** to **Block**, and save. | ||
| 2. On the device, open `chrome://policy` and click **Reload policies**. | ||
| 3. In Google Admin, set the **Installation policy** back to **Force install + pin**, and save. | ||
| 4. Reload policies again, then **reboot the Chromebook**. | ||
|
|
||
| The reboot matters — a device can otherwise continue presenting its old certificate to an mTLS endpoint even after the new one has been issued. | ||
|
|
||
| ### 5. Verify certificate issuance | ||
|
|
||
| On the Chromebook, go to `chrome://certificate-manager/clientcerts/platformclientcerts`. You should see a new certificate issued by your chosen authority's Intermediate CA (there may be other certificates listed too). Open its **Details** and confirm the **Issuer** matches the authority you configured in Step 1. | ||
|
|
||
| <Alert severity="info"> | ||
| <div> | ||
| The Smallstep dashboard's device detail page may continue to show "This device does not have any identity certificates" even after a certificate has been issued and is actively in use. This is a known gap in the ChromeOS extension today, not a sign anything went wrong — device identity certificates issued to ChromeOS devices don't yet surface on this panel. Confirm issuance on the device itself, or under **Certificate Manager → Certificates → x509** in the Smallstep dashboard, where issued certificates are listed normally. | ||
| </div> | ||
| </Alert> | ||
|
|
||
| # Troubleshooting | ||
|
|
||
| **Setting `devices_ca_directory_url` had no visible effect.** Confirm the authority's root and intermediate were uploaded to Google Admin (Step 2) before the policy was set. If they were added afterward, repeat Step 4 to force re-enrollment. | ||
|
|
||
| **Only one certificate appears after re-enrollment.** Confirm the Organizational Unit in Google Admin actually matches the device — and, separately, the signed-in user's OU, since extension policy is scoped to the user's OU rather than the device's. | ||
|
|
||
| **The certificate's issuer doesn't match what a downstream service expects (e.g. a RADIUS server's configured issuer pattern).** Read the issuer directly off the certificate at `chrome://certificate-manager/clientcerts/platformclientcerts` rather than assuming a value — it's the only way to be certain which authority actually signed it. | ||
|
|
||
| # Next steps | ||
|
|
||
| With a device identity certificate issued, continue to [ChromeOS Wi-Fi Enrollment](./protect-wireless-networks.mdx#chromeos-with-google-workspace-acme-device-attestation) to use it for passwordless 802.1X Wi-Fi authentication. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds more like an
info.The audience for these docs are IT admins responsible for managing a fleet of ChromeOS machines. They don't have direct access to the machines, unless they access the machine using remote desktop? I also think
curlrequires the terminal to be available, which I think is only the case when the Linux development environment is available, which may not always be the case by default.