Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
09b6e94
Add Google Workspace WIF integration docs
hslatman Jul 6, 2026
28081f9
Use `sts.googleapis.com` as audience in Google Workspace WIF
hslatman Jul 27, 2026
0fbecca
Ignore `https://container.googleapis.com` in link checker
hslatman Jul 27, 2026
4586a4a
Add Verified Access API to prerequisites
hslatman Jul 29, 2026
a61822d
Fix JSON markup
hslatman Jul 29, 2026
3fbdd05
Ignore `../verifiedaccess.googleapis.com` in URL checker
hslatman Jul 30, 2026
68fa44a
Update `k8s_sa` attribute
hslatman Jul 30, 2026
28296ea
Add ChromeOS device identity certificates tutorial
llewis1234 Aug 2, 2026
2e60373
Cross-link ChromeOS troubleshooting to setup and cert-identity docs
llewis1234 Aug 2, 2026
32c1996
Link to the device identity certificates tutorial from Confirmation
llewis1234 Aug 2, 2026
8d96c02
Address review feedback on device identity certificate behavior
llewis1234 Aug 2, 2026
e5fbfda
Stop naming the attestation certificate as a user-facing concept
llewis1234 Aug 2, 2026
ef3a33a
Reframe Step 1 as confirming, not self-service choosing
llewis1234 Aug 2, 2026
31618a7
Clarify when forcing a fresh enrollment is actually needed
llewis1234 Aug 2, 2026
bcad58b
Fix unescaped <team-slug> placeholder breaking MDX compilation
llewis1234 Aug 2, 2026
08d4d34
Add ChromeOS Wi-Fi enrollment via ACME Device Attestation
llewis1234 Aug 2, 2026
1731fac
Use consistent same-directory link style for wireless-networks reference
llewis1234 Aug 2, 2026
3c51717
Address review feedback on ChromeOS Wi-Fi setup
llewis1234 Aug 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/mdl.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
},
{
"pattern": "^https://datatracker.ietf.org"
},
{
"pattern": "^https://container.googleapis.com/*"
},
{
"pattern": "^https://console.cloud.google.com/marketplace/product/google/verifiedaccess.googleapis.com"
}
],
"replacementPatterns": [
Expand Down
4 changes: 4 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
"title": "Configure Browser Certificates",
"path": "/tutorials/browser-certificate-setup-guide.mdx"
},
{
"title": "Configure ChromeOS Device Identity Certificates",
"path": "/tutorials/chromeos-device-identity-certificates.mdx"
},
{
"title": "Configure Enterprise Relay",
"path": "/tutorials/configure-enterprise-relay.mdx"
Expand Down
4 changes: 3 additions & 1 deletion platform/troubleshooting-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ This may indicate the device needs to be registered and approved. See [Registeri
| Check extension version | Click the Smallstep extension icon in Chrome toolbar (version shown at bottom) |
| Verify device enrollment | Device must be enrolled in Google Workspace for enterprise/education |
| Check policies | Navigate to `chrome://policy` and look for `Smallstep Agent for ChromeOS` |
| Verify certificates | Navigate to `chrome://certificate-manager` |
| Verify certificates | Navigate to `chrome://certificate-manager` — see [Configure ChromeOS Device Identity Certificates](../tutorials/chromeos-device-identity-certificates.mdx) if the device only has an attestation certificate rather than a usable device identity certificate |

**ChromeOS Requirements:**
- Device enrolled in a Google Workspace domain
Expand All @@ -628,4 +628,6 @@ This may indicate the device needs to be registered and approved. See [Registeri
- `ExtensionInstallForceList` containing the ChromeOS extension ID
- `AttestationExtensionAllowList` containing the ChromeOS extension ID

For initial setup of these requirements and policies, see [Connect Google Workspace to Smallstep](../tutorials/connect-google-workspace-to-smallstep.mdx).

The extension retries certificate issuance every ~30 seconds. If enrollment continues to fail, contact Smallstep support.
26 changes: 6 additions & 20 deletions tutorials/browser-certificate-setup-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ so there is no per-device configuration step.

### Google Chrome client certificate auto-selection

Prerequisite: complete [Configure ChromeOS Device Identity Certificates](./chromeos-device-identity-certificates.mdx)
first so a client certificate has actually been issued to select.

To automatically select the Smallstep client certificate when a user visits a protected URL,
use the [`AutoSelectCertificateForUrls`](https://chromeenterprise.google/policies/?policy=AutoSelectCertificateForUrls) policy.

Expand Down Expand Up @@ -259,24 +262,7 @@ You should not see any certificate selection dialogs.

### Wi-Fi client certificate auto-selection (802.1X)

For Wi-Fi networks that authenticate with EAP-TLS,
client certificate selection is configured per-network in the Google Workspace Admin Console.

1. In the Google Workspace Admin Console, visit **Devices → Networks → Wi-Fi**.
2. Edit or create the Wi-Fi network used for 802.1X authentication.
3. Set the **EAP type** to **EAP-TLS**.
4. Set the **Issuer pattern** to the full common name of your Smallstep intermediate issuing CA:

```
Smallstep ([Team Slug]) Devices Intermediate CA
```

Replace `[Team Slug]` with your Smallstep team slug.

5. Save the network configuration.

When a Chromebook connects to the network,
it will automatically select the Smallstep client certificate
issued by the matching intermediate CA,
without prompting the user.
Wi-Fi client certificate selection for ChromeOS is now covered in
[ChromeOS with Google Workspace (ACME Device Attestation)](./protect-wireless-networks.mdx#chromeos-with-google-workspace-acme-device-attestation),
alongside the RADIUS and access point setup it depends on.

93 changes: 93 additions & 0 deletions tutorials/chromeos-device-identity-certificates.mdx
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:

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.
106 changes: 94 additions & 12 deletions tutorials/connect-google-workspace-to-smallstep.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ html_title: Integrate Google Workspace with Smallstep Tutorial
description: Integrate Google Workspace with Smallstep for Chromebook device security. Complete guide for enforcing device trust in ChromeOS environments.
---

Smallstep can integrate with Google Workspace to keep your ChromeOS device inventory in sync.
Smallstep can integrate with Google Workspace to keep your ChromeOS device inventory in sync and manage credentials for ChromeOS devices.

# Prerequisites

Expand All @@ -19,11 +19,12 @@ You will need:

In Google Cloud Console, select a project you will use for Smallstep. This can be any project, as long as you can grant domain-wide delegation to the client in a future step.

Your Google Cloud project must have the Admin SDK API enabled. By default, it is disabled.
Your Google Cloud project must have the Admin SDK and Chrome Verified Access APIs enabled. By default, they're disabled.

### 0. Enable admin SDK API
### 0. Enable APIs

1. Go to [Admin SDK API](https://console.cloud.google.com/apis/api/admin.googleapis.com) for your project, and choose **Enable API**
2. Go to [Chrome Verified Access API](https://console.cloud.google.com/marketplace/product/google/verifiedaccess.googleapis.com) for your project, and choose **Enable API**

### 1. Create a service account for Smallstep

Expand All @@ -34,36 +35,77 @@ Your Google Cloud project must have the Admin SDK API enabled. By default, it is
5. Choose **Done**
6. Open the details for the Service Account you just created
7. Copy the **Unique ID** (numeric) and the **Email** shown on the details tab; you’ll need them later
8. Visit the **Keys** tab, and choose **Add key**, then **Create new key**
9. Choose **Create** to create a JSON key

A file containing the service account key will be downloaded. Keep this safe and secure!
### 2. Setup Workload Identity Federation

### 2. Grant device directory API permissions
The Smallstep platform authenticates to your Google Workspace through Workspace Identity Federation for Google Kubernetes Engine.

1. In Google Cloud, visit [IAM & Admin → Workload Identity Federation](https://console.cloud.google.com/iam-admin/workload-identity-pools)
2. Choose **Create pool**
3. Set a name, e.g. "Smallstep Google Workspace Sync Pool"
4. Optionally, provide a **Description** for the pool
5. Click **Continue**
6. Select **OpenID Connect (OIDC)** as the provider
7. Set a name, e.g. "Smallstep Google Workspace Sync"
8. Set the issuer URL to **https://container.googleapis.com/v1/projects/prod-us-central1-e5bd/locations/us-central1/clusters/primary**
9. Set **Allowed audiences** to `sts.googleapis.com`
10. Click **Continue**
11. For the **google.subject** attribute, set **assertion.sub**
12. Click **Add mapping**, and set **attribute.k8s_sa** to **assertion.kubernetes.io.serviceaccount.name**
13. Click **Save**

### 3. Grant Access to the Service Account

1. Click **Grant access**
2. Select **Grant access using service account impersonation**
3. Select the **Service account** you created earlier from the dropdown
4. Select **k8s_sa** as the attribute
5. Set **system:serviceaccount:prod:inventory** as the value for the attribute
6. Click **Save**
7. When the modal appears, you can **Dismiss** it

### 4. Grant device directory API permissions

1. In Google Admin, visit [Security → Access and data control → API controls](https://admin.google.com/ac/owl)
2. Under Domain wide delegation, select **Manage Domain Wide Delegation**
3. In the **API Clients** table, select **Add new**
1. Enter the **Unique ID** of the service account from Step 1
2. For the **OAuth Scopes**, enter the following scope:
2. For the **OAuth Scopes**, enter the following scopes:

```
https://www.googleapis.com/auth/admin.directory.device.chromeos
https://www.googleapis.com/auth/verifiedaccess
```

3. Choose **Authorize**

### 3. Add Google Workspace to Smallstep
### 5. Create and Assign Custom Admin Role to Service Account

1. In Google Admin, visit [Account → Admin roles](https://admin.google.com/ac/list/roles)
2. Click **Create new role**
3. Give it a descriptive name, e.g. **Google Workspace Sync**
4. Enable the **Manage ChromeOS Devices** privilege (incl. all subitems)
5. Click **Continue**
6. Click **Create role**
7. Click the newly created role
8. Click **Admins assigned**
9. Click **Assign service accounts**
10. Enter the principal of the service account created earlier
11. Click **Assign role**

### 6. Add Google Workspace to Smallstep

In Smallstep, visit [Settings → Device Management](https://smallstep.com/app/?next=/settings/devices).

Configure a new Google Workspace Integration with the following values:

- The **Customer ID** of your Google Workspace tenant. The Customer ID is a short alphanumeric string. It can be obtained from the Google Workspace Admin [Account Settings](https://admin.google.com/ac/accountsettings/profile) page
- The **Service Account JSON key** you downloaded earlier
- An email address of a user in your Google Workspace directory with admin permissions
- The numeric **Project ID** of the GCP project your service account was created in
- The **workload identity pool**
- The **workload identity provider**
- The service account **principal**

### 4. Add Smallstep certificates to Google Workspace
### 7. Add Smallstep certificates to Google Workspace

After saving the Google Workspace connection, you will see settings for your integration.

Expand All @@ -85,8 +127,48 @@ After saving the Google Workspace connection, you will see settings for your int
- Choose **Add**
5. Repeat Step 4 for each of the certificates you downloaded

### 8. Verified Access Mode Configuration

1. In Google Workspace, visit [Devices → Chrome → Settings](https://admin.google.com/ac/chrome/settings/device).
2. Select **Device settings**
3. Click **Verified mode**
4. Ensure the correct **Organizational Unit** is selected for scoping the configuration
4. Under Configuration, select **Require verified mode boot for verified access**
5. Set the email address of the GCP service account in the **Services with full access** field
6. Click Save

### 9. ChromeOS Extension Configuration

1. In Google Workspace, visit [Devices → Chrome → Apps & extension](https://admin.google.com/ac/chrome/apps).
2. Click **Users & browsers**
3. Ensure the proper **Organizational Unit** is selected for scoping the configuration
4. Click the **+** icon on the bottom right
5. Click **Add Chrome app or extension by ID**
6. Set the **Extension ID** to **icjpnolkgdnfgpccpkdlipalcmalkndl**
7. In the dropdown, choose **From a custom URL**, and set it to **https://packages.smallstep.com/chromeos/latest/update.xml**
8. Click **Save**
9. Click the newly created extension to edit it
10. Select **Force install + pin** as the **Installation policy**
11. Under **Certificate management**, enable **allow access to keys** and **Allow enterprise challenge**
12. Under **Policy for extensions**, add the following JSON, replacing `<team-slug>` with your Smallstep team slug:

```
{
"team": {
"Value": "<team-slug>"
}
}
```
13. Click **Save** in the top right corner
14. Scroll down in the side panel details, and ensure the installation URL is set to ...
15. Set the **Update URL** to **Installation URL (see above)**
16. Click **Save**


### Confirmation

Within a few minutes, you should see all of your ChromeOS devices in Smallstep's [Devices](https://smallstep.com/app/?next=/devices/all) tab.
A full sync is performed every 8 hours, and a partial sync every hour.

With the extension deployed, continue to [Configure ChromeOS Device Identity Certificates](./chromeos-device-identity-certificates.mdx) — by default the extension only requests a short-lived attestation certificate, which can't be used for Wi-Fi, VPN, or mTLS.

Loading