diff --git a/.vale/styles/Smallstep/NestedListIndent.yml b/.vale/styles/Smallstep/NestedListIndent.yml new file mode 100644 index 00000000..5fa6eb25 --- /dev/null +++ b/.vale/styles/Smallstep/NestedListIndent.yml @@ -0,0 +1,55 @@ +extends: script +message: "Nested list item is not indented enough. Indent it to the column where the text of the parent item starts, or Markdown will not nest it." +level: error +scope: raw +script: | + text := import("text") + + matches := [] + // stack holds the open list items, outermost first. For each item, indent + // is the column of its marker and content is the column where its text + // starts. A nested item must start at or after content. + stack := [] + in_fence := false + offset := 0 + + for line in text.split(scope, "\n") { + trimmed := text.trim_space(line) + indent := len(line) - len(text.trim_left(line, " ")) + + if text.has_prefix(trimmed, "```") || text.has_prefix(trimmed, "~~~") { + in_fence = !in_fence + } else if in_fence || trimmed == "" { + // Fenced code and blank lines do not change list state. + } else if text.has_prefix(line, "#") { + stack = [] + } else { + m := text.re_find(`^ *([-*+]|[0-9]+[.)])( +)\S`, line) + if m != undefined { + // Close the items at this indentation or deeper. + for len(stack) > 0 && indent <= stack[len(stack)-1].indent { + stack = stack[:len(stack)-1] + } + if len(stack) > 0 && indent < stack[len(stack)-1].content { + matches = append(matches, { + begin: offset + m[0][1].begin, + end: offset + m[0][1].end + }) + } + stack = append(stack, { + indent: indent, + content: indent + len(m[0][1].text) + len(m[0][2].text) + }) + } else if indent == 0 { + // Text at the left margin ends all lists. + stack = [] + } else { + // Indented text ends the items that are not its parents. + for len(stack) > 0 && indent <= stack[len(stack)-1].indent { + stack = stack[:len(stack)-1] + } + } + } + + offset += len(line) + 1 + } diff --git a/.vale/styles/Smallstep/OrderedListNumbering.yml b/.vale/styles/Smallstep/OrderedListNumbering.yml new file mode 100644 index 00000000..22bd8a7c --- /dev/null +++ b/.vale/styles/Smallstep/OrderedListNumbering.yml @@ -0,0 +1,80 @@ +extends: script +message: "Numbered list is out of order. Number the items 1, 2, 3, ... without skipping or repeating a number." +level: error +scope: raw +script: | + text := import("text") + + matches := [] + // expected[indent] is the next number for the list at that indentation. + expected := {} + // broken[indent] is true when other text came after the last item of the + // list at that indentation, so a new list may start there at 1. + broken := {} + in_fence := false + offset := 0 + + // Lists nested deeper than indent belong to the previous item: forget them. + forget_deeper := func(indent) { + for k, _ in expected { + if text.atoi(k) > indent { + delete(expected, k) + delete(broken, k) + } + } + } + + // Text at indent interrupts the lists at that indentation and deeper. + interrupt := func(indent) { + for k, _ in expected { + if text.atoi(k) >= indent { + broken[k] = true + } + } + } + + for line in text.split(scope, "\n") { + trimmed := text.trim_space(line) + indent := len(line) - len(text.trim_left(line, " \t")) + + if text.has_prefix(trimmed, "```") || text.has_prefix(trimmed, "~~~") { + in_fence = !in_fence + interrupt(indent) + } else if in_fence || trimmed == "" { + // Fenced code and blank lines do not change list state. + } else if text.has_prefix(line, "#") { + // A heading starts a new section, so any list after it starts over. + expected = {} + broken = {} + } else { + m := text.re_find(`^[ \t]*([0-9]+)[.)][ \t]`, line) + if m != undefined { + num := text.atoi(m[0][1].text) + forget_deeper(indent) + + key := string(indent) + want := expected[key] + // An item must follow the previous item at the same level. Item 1 + // may start a new list when there is no list at this level or when + // other text separates it from the previous list. + ok := num == want || (num == 1 && (want == undefined || broken[key])) + if !ok { + matches = append(matches, { + begin: offset + m[0][1].begin, + end: offset + m[0][1].end + }) + } + expected[key] = num + 1 + broken[key] = false + } else if text.re_match(`^[-*+][ \t]`, trimmed) { + // A bullet item owns the lists nested under it, and it interrupts a + // numbered list at its own level. + forget_deeper(indent) + interrupt(indent) + } else { + interrupt(indent) + } + } + + offset += len(line) + 1 + } diff --git a/.vale/styles/Smallstep/StepHeadingNumbering.yml b/.vale/styles/Smallstep/StepHeadingNumbering.yml new file mode 100644 index 00000000..2d0784f5 --- /dev/null +++ b/.vale/styles/Smallstep/StepHeadingNumbering.yml @@ -0,0 +1,52 @@ +extends: script +message: "Step heading is out of order. Number the step headings 1, 2, 3, ... (or 0, 1, 2, ...) without skipping or repeating a number." +level: error +scope: raw +script: | + text := import("text") + + matches := [] + // last[level] is the number of the last step heading at that heading level. + last := {} + in_fence := false + offset := 0 + + for line in text.split(scope, "\n") { + trimmed := text.trim_space(line) + + if text.has_prefix(trimmed, "```") || text.has_prefix(trimmed, "~~~") { + in_fence = !in_fence + } else if !in_fence && text.has_prefix(line, "#") { + level := len(line) - len(text.trim_left(line, "#")) + + // A higher-level heading starts a new section, so the step headings + // under it count from the start again. + for k, _ in last { + if text.atoi(k) > level { + delete(last, k) + } + } + + m := text.re_find(`(?i)^#+[ \t]+(?:\*\*)?step[ \t]+([0-9]+)\b`, line) + if m != undefined { + num := text.atoi(m[0][1].text) + key := string(level) + prev := last[key] + ok := false + if prev == undefined { + ok = num == 0 || num == 1 + } else { + ok = num == prev + 1 + } + if !ok { + matches = append(matches, { + begin: offset + m[0][1].begin, + end: offset + m[0][1].end + }) + } + last[key] = num + } + } + + offset += len(line) + 1 + } diff --git a/ssh/azure-ad.mdx b/ssh/azure-ad.mdx index 53e06f63..f35303ff 100644 --- a/ssh/azure-ad.mdx +++ b/ssh/azure-ad.mdx @@ -88,7 +88,7 @@ Your Users and Groups list should now look something like this: 1. Choose **Provisioning** on the left and choose **Get Started**. 2. Set the provisioning mode to **Automatic**. -4. Expand **Admin Credentials:** +3. Expand **Admin Credentials:** * Supply the SCIM **Tenant URL** and **Secret Token** from the Smallstep console. * Choose **Test Connection** and make sure that it works. * Save. diff --git a/step-ca/certificate-authority-server-production.mdx b/step-ca/certificate-authority-server-production.mdx index 155fb456..d17ebba4 100644 --- a/step-ca/certificate-authority-server-production.mdx +++ b/step-ca/certificate-authority-server-production.mdx @@ -280,7 +280,7 @@ the CRL will be hosted at `/1.0/crl`. $(step path)/secrets/intermediate_ca_key ``` -2. Restart `step-ca`. +3. Restart `step-ca`. Clients will be able to renew certificates that were issued by your previous Intermediate CA. #### Enable CRL for leaf certificates @@ -305,7 +305,7 @@ the CRL will be hosted at `/1.0/crl`. Reload the configuration by restarting `step-ca` or sending it a `HUP` signal. -1. Add an X.509 certificate template, and enable `crlDistributionPoints` in the template: +2. Add an X.509 certificate template, and enable `crlDistributionPoints` in the template: ```bash cd $(step path)/templates @@ -815,8 +815,8 @@ If you have PEM bundles containing both your root and intermediate CAs, you will 1. **Create your new intermediate CA** certificate and key, but do not start issuing certificates with it yet. 2. **Append the new intermediate certificate** to the bundles that need it. 3. **Configure `step-ca` to use your new intermediate**. -3. **Wait** for all certificates issued by the old intermediate to expire. -3. It is now safe to **remove the old intermediate from the bundles**. +4. **Wait** for all certificates issued by the old intermediate to expire. +5. It is now safe to **remove the old intermediate from the bundles**. ## Sane cryptographic defaults diff --git a/step-ca/provisioners.mdx b/step-ca/provisioners.mdx index ed6eff6a..6aaf3e72 100644 --- a/step-ca/provisioners.mdx +++ b/step-ca/provisioners.mdx @@ -1108,10 +1108,10 @@ step ca provisioner add acme-da \ To get a client certificate for a hardware-bound private key on your YubiKey: -0. Create a `device-attest-01` provisioner as described above. -1. Install [`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin/) -2. Insert the YubiKey. -3. Generate a private key in one of the YubiKey's slots, if you haven't already. +1. Create a `device-attest-01` provisioner as described above. +2. Install [`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin/) +3. Insert the YubiKey. +4. Generate a private key in one of the YubiKey's slots, if you haven't already. In this example, we'll use slot `9a`. Run: @@ -1119,7 +1119,7 @@ To get a client certificate for a hardware-bound private key on your YubiKey: step kms create 'yubikey:slot-id=9a' \ --kms 'yubikey:?pin-value=123456' ``` -4. Get a certificate for the YubiKey from `step-ca`. +5. Get a certificate for the YubiKey from `step-ca`. Substitute the serial number of your YubiKey here: ```bash diff --git a/tutorials/connect-fleet-dm-to-smallstep.mdx b/tutorials/connect-fleet-dm-to-smallstep.mdx index 89498455..eca054d1 100644 --- a/tutorials/connect-fleet-dm-to-smallstep.mdx +++ b/tutorials/connect-fleet-dm-to-smallstep.mdx @@ -110,12 +110,12 @@ Create a Fleet report to collect the enrollment data. Smallstep reads this repor ``` 5. Click **Save**; a modal should appear 6. In the modal, enter the following details: - - A **Name** for the query, such as "Smallstep Enrollment" - - Optionally, a **Description** - - The **Interval** can be set to **Every hour**. While testing, a shorter interval is helpful - - Optionally, enable the **Observers can run** checkbox - - Enable **macOS** as **Target** - - Select **All hosts** + - A **Name** for the query, such as "Smallstep Enrollment" + - Optionally, a **Description** + - The **Interval** can be set to **Every hour**. While testing, a shorter interval is helpful + - Optionally, enable the **Observers can run** checkbox + - Enable **macOS** as **Target** + - Select **All hosts** 7. Click **Save** 8. Note the numeric ID of the Smallstep enrollment report that was just created @@ -146,7 +146,7 @@ Fleet deploys certificates and configuration to devices using a configuration pr The downloaded profile bundles everything required to enroll a device: your root and intermediate CA certificates, the Smallstep agent settings, and the Login Items entry for the agent. -## Step 6. Upload the configuration profile to Fleet +## Step 5. Upload the configuration profile to Fleet 1. In the Fleet console, go to **Controls → OS settings → Configuration profiles** 2. Click **Add profile** @@ -155,7 +155,7 @@ The downloaded profile bundles everything required to enroll a device: your root The profile will be deployed to devices at their next MDM check-in. -## Step 7. Deploy the Smallstep agent +## Step 6. Deploy the Smallstep agent The macOS Smallstep agent picks up the configuration that Fleet deployed to the device, and uses it to register the device with Smallstep. @@ -167,17 +167,17 @@ Deploy the agent using Fleet's [software deployment](https://fleetdm.com/guides/ Alternatively, you can use a separate software management system such as [Munki](https://github.com/munki/munki) to deploy the agent. See the [Smallstep Agent manual installation guide](../platform/smallstep-agent.mdx#macos-installation) for detailed instructions. -## Step 8. Deploy the osquery extension +## Step 7. Deploy the osquery extension Smallstep provides an osquery extension that registers additional device identity information directly in Fleet. When Smallstep syncs your device inventory from Fleet, it reads this data to enable a seamless enrollment experience on macOS. 1. Download the `step-agent-osquery` package for macOS from [Smallstep's releases](https://releases.smallstep.com). -1. In Fleet, go to **Software** -1. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet -1. Select **Custom package** -1. Click **Choose file**, and select the `step-agent-osquery` package that was downloaded before -1. Enable **Deploy** -1. Click **Add software**. +2. In Fleet, go to **Software** +3. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet +4. Select **Custom package** +5. Click **Choose file**, and select the `step-agent-osquery` package that was downloaded before +6. Enable **Deploy** +7. Click **Add software**. A modal should appear, showing the package upload progress. @@ -187,7 +187,7 @@ See https://fleetdm.com/guides/deploying-custom-osquery-extensions-in-fleet-a-st Alternatively, you can use a separate software management system such as [Munki](https://github.com/munki/munki) to deploy the osquery extension. -## Step 9. Confirmation +## Step 8. Confirmation To confirm certificate deployment: @@ -245,12 +245,12 @@ If your fleet includes multiple Linux distributions or architectures, create sep Smallstep provides an osquery extension that registers additional device identity information, including the TPM Endorsement Key (EK)—directly in Fleet. When Smallstep syncs your device inventory from Fleet, it reads this data to enable a more seamless enrollment experience on Linux. 1. Download the `step-agent-osquery` package for your Linux distribution and target architecture from [Smallstep's releases](https://releases.smallstep.com). -1. In Fleet, go to **Software** -1. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet -1. Select **Custom package** -1. Click **Choose file**, and select the `step-agent-osquery` package that was downloaded before -1. Enable **Deploy** -1. Click **Add software**. +2. In Fleet, go to **Software** +3. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet +4. Select **Custom package** +5. Click **Choose file**, and select the `step-agent-osquery` package that was downloaded before +6. Enable **Deploy** +7. Click **Add software**. A modal should appear, showing the package upload progress. @@ -273,12 +273,12 @@ Once the extension is active on your Linux devices, create a Fleet report to col ``` 5. Click **Save**; a modal should appear 6. In the modal, enter the following details: - - A **Name** for the query, such as "Smallstep Enrollment" - - Optionally, a **Description** - - The **Interval** can be set to **Every hour**. While testing, a shorter interval can be helpful - - Optionally, enable the **Observers can run** checkbox - - Enable **Linux** as **Target** - - Select **All hosts** + - A **Name** for the query, such as "Smallstep Enrollment" + - Optionally, a **Description** + - The **Interval** can be set to **Every hour**. While testing, a shorter interval can be helpful + - Optionally, enable the **Observers can run** checkbox + - Enable **Linux** as **Target** + - Select **All hosts** 7. Click **Save** ## Step 4. Link enrollment report in Smallstep @@ -372,12 +372,12 @@ The osquery extension can be installed by distributing the MSI to your devices, NOTE: the osquery extension MSI distribution is currently work in progress. 1. Download the `step-agent-osquery.ext.exe` MSI for your Windows target architecture(s) from [Smallstep's releases](https://releases.smallstep.com) -1. In Fleet, go to **Software** -1. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet -1. Select **Custom package** -1. Click **Choose file**, and select the `step-agent-osquery` MSI that was downloaded before -1. Enable **Deploy** -1. Click **Add software**. +2. In Fleet, go to **Software** +3. Click **Add software**. Ensure a fleet is selected; software is configured per-fleet +4. Select **Custom package** +5. Click **Choose file**, and select the `step-agent-osquery` MSI that was downloaded before +6. Enable **Deploy** +7. Click **Add software**. A modal should appear, showing the upload progress. @@ -388,8 +388,8 @@ See https://fleetdm.com/guides/deploying-custom-osquery-extensions-in-fleet-a-st ### The Update Framework (TUF) auto-update server 1. Download the `step-agent-osquery.ext.exe` binary for your Windows target architecture(s) from [Smallstep's releases](https://releases.smallstep.com) -1. Upload the binary to your TUF server -1. Configure the `extensions` under `agent_options` in Fleet to include the `step-agent-osquery.ext.exe` binaries for your Windows target architecture(s) +2. Upload the binary to your TUF server +3. Configure the `extensions` under `agent_options` in Fleet to include the `step-agent-osquery.ext.exe` binaries for your Windows target architecture(s) See https://fleetdm.com/docs/configuration/agent-configuration#extensions for more information on how to configure extensions through TUF. @@ -407,12 +407,12 @@ Once the extension is active on your Windows devices, create a Fleet report to c ``` 5. Click **Save**; a modal should appear 6. In the modal, enter the following details: - - A **Name** for the query, such as "Smallstep Enrollment" - - Optionally, a **Description** - - The **Interval** can be set to **Every hour**. While testing, a shorter interval can be helpful - - Optionally, enable the **Observers can run** checkbox - - Enable **Windows** as **Target** - - Select **All hosts** + - A **Name** for the query, such as "Smallstep Enrollment" + - Optionally, a **Description** + - The **Interval** can be set to **Every hour**. While testing, a shorter interval can be helpful + - Optionally, enable the **Observers can run** checkbox + - Enable **Windows** as **Target** + - Select **All hosts** 7. Click **Save** 8. Note the numeric ID of the Smallstep enrollment report that was just created @@ -574,7 +574,7 @@ export SMALLSTEP_CHALLENGE_PASSWORD='your-challenge-password' ## Add configuration profiles -Download the configuration profile for your Fleet connection from the Smallstep dashboard, as described in **Step 5** of the macOS section above, and place the `fleet-.mobileconfig` file in your `lib/` directory. Then reference it from your team YAML file: +Download the configuration profile for your Fleet connection from the Smallstep dashboard, as described in **Step 4** of the macOS section above, and place the `fleet-.mobileconfig` file in your `lib/` directory. Then reference it from your team YAML file: ```yaml controls: diff --git a/tutorials/connect-google-workspace-to-smallstep.mdx b/tutorials/connect-google-workspace-to-smallstep.mdx index d24007f8..e9b74945 100644 --- a/tutorials/connect-google-workspace-to-smallstep.mdx +++ b/tutorials/connect-google-workspace-to-smallstep.mdx @@ -133,9 +133,9 @@ After saving the Google Workspace connection, you will see settings for your int 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 +5. Under Configuration, select **Require verified mode boot for verified access** +6. Set the email address of the GCP service account in the **Services with full access** field +7. Click Save ### 9. ChromeOS Extension Configuration diff --git a/tutorials/sync-entra-id-users-to-smallstep.mdx b/tutorials/sync-entra-id-users-to-smallstep.mdx index e14f0bfc..3517ae9f 100644 --- a/tutorials/sync-entra-id-users-to-smallstep.mdx +++ b/tutorials/sync-entra-id-users-to-smallstep.mdx @@ -75,7 +75,7 @@ The following provisioning features are supported: 2. In Entra ID, return to your Smallstep Enterprise Application. 3. Go to Manage → Provisioning 4. Create a new provisioning configuration. -6. For **Admin Credentials:** +5. For **Admin Credentials:** - Use **Bearer Authentication** - Supply the SCIM **Tenant URL** and **Secret Token** you received from Smallstep. - Choose **Test Connection** and make sure that it works. diff --git a/tutorials/sync-google-workspace-users-to-smallstep.mdx b/tutorials/sync-google-workspace-users-to-smallstep.mdx index 255684b3..a3a462d1 100644 --- a/tutorials/sync-google-workspace-users-to-smallstep.mdx +++ b/tutorials/sync-google-workspace-users-to-smallstep.mdx @@ -44,8 +44,8 @@ The following provisioning features are supported: - **User support email**: choose a Google email address 3. Under Audience: - Choose **Internal** - 5. Update **Contact Information** - 3. Agree to terms + 4. Update **Contact Information** + 5. Agree to terms 6. **Create** 2. Create an OAuth client 1. Visit [Create an OAuth client](https://console.cloud.google.com/auth/clients/create) diff --git a/tutorials/sync-okta-users-to-smallstep.mdx b/tutorials/sync-okta-users-to-smallstep.mdx index 5b3eb09b..66ed8a76 100644 --- a/tutorials/sync-okta-users-to-smallstep.mdx +++ b/tutorials/sync-okta-users-to-smallstep.mdx @@ -75,23 +75,23 @@ In this quickstart, we will: ### Step 3. Add the Smallstep app integration and configure user sync in Okta 1. In the Okta admin console, add the Smallstep application - * Applications → Browse App Catalog - * Search for `Smallstep` - * Select the Smallstep app. + * Applications → Browse App Catalog + * Search for `Smallstep` + * Select the Smallstep app. 2. Click "Add Integration" ![](/graphics/quickstart/okta-app-add.png) 3. Select "Do not display application icon to users" -5. De-select "Automatically log in when user lands on login page" -6. Choose Next +4. De-select "Automatically log in when user lands on login page" +5. Choose Next ![](/graphics/quickstart/okta-app-signon.png) -7. Select "Administrator sets username, user sets password" -8. Application username format: "Okta username prefix" -9. Update application username on "Create and update" -10. Done. We'll assign users for syncing in the next section. +6. Select "Administrator sets username, user sets password" +7. Application username format: "Okta username prefix" +8. Update application username on "Create and update" +9. Done. We'll assign users for syncing in the next section. ### Configure provisioning