diff --git a/src/content/changelog/access/2026-04-15-independent-mfa.mdx b/src/content/changelog/access/2026-04-15-independent-mfa.mdx index cff474d1e59b5c5..e080844cf3f4b4d 100644 --- a/src/content/changelog/access/2026-04-15-independent-mfa.mdx +++ b/src/content/changelog/access/2026-04-15-independent-mfa.mdx @@ -17,7 +17,7 @@ Independent MFA supports the following authenticator types: - **Biometrics** — Built-in device authenticators including Apple Touch ID, Apple Face ID, and Windows Hello. :::note -Infrastructure applications do not yet support independent MFA. +Infrastructure applications support MFA with YubiKey PIV keys for SSH connections. For more information, refer to [MFA for SSH with PIV keys](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications). ::: ## Configuration levels diff --git a/src/content/changelog/access/2026-05-15-ssh-mfa-piv-keys.mdx b/src/content/changelog/access/2026-05-15-ssh-mfa-piv-keys.mdx new file mode 100644 index 000000000000000..4e53a0b2d0c2331 --- /dev/null +++ b/src/content/changelog/access/2026-05-15-ssh-mfa-piv-keys.mdx @@ -0,0 +1,19 @@ +--- +title: Independent MFA for infrastructure applications +description: Add hardware-backed multi-factor authentication to SSH connections through Access for Infrastructure. +date: 2026-05-15 +products: + - access +--- + +[Access for Infrastructure](/cloudflare-one/access-controls/applications/non-http/infrastructure-apps/) now supports independent multi-factor authentication (MFA) for SSH connections using YubiKey PIV keys. This adds a hardware-backed second factor to SSH access, ensuring that a compromised device session alone is not sufficient to reach your servers. + +With per-application and per-policy configuration, you can enforce PIV key authentication for sensitive usernames (for example, `root`) while applying different requirements for other usernames. You can also set an MFA session duration to control how often users must re-authenticate. + +## Enrollment + +Users enroll their YubiKey PIV key through the [App Launcher](/cloudflare-one/access-controls/access-settings/app-launcher/). For enrollment instructions and SSH client setup, refer to [Enroll a PIV key for infrastructure apps](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps). + +## Configuration + +For setup instructions, refer to [Enforce MFA for infrastructure applications](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications). diff --git a/src/content/docs/cloudflare-one/access-controls/access-settings/independent-mfa.mdx b/src/content/docs/cloudflare-one/access-controls/access-settings/independent-mfa.mdx index dbe753f016786d6..22f2c3eae90bcc3 100644 --- a/src/content/docs/cloudflare-one/access-controls/access-settings/independent-mfa.mdx +++ b/src/content/docs/cloudflare-one/access-controls/access-settings/independent-mfa.mdx @@ -10,7 +10,7 @@ tags: - Authentication --- -import { Tabs, TabItem, APIRequest, Details } from "~/components"; +import { Tabs, TabItem, APIRequest, Details, Render } from "~/components"; Independent multi-factor authentication (MFA) allows you to enforce MFA requirements directly in Access without relying on your identity provider (IdP). Users authenticate with their IdP as usual, and Access prompts for an additional authentication method before granting access to the application. @@ -18,11 +18,12 @@ Because you can [configure MFA at the application and policy level](/cloudflare- ## Supported MFA methods -| MFA method | Description | -| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Authenticator application | Time-based one-time passwords (TOTP) generated by apps such as Google Authenticator, Microsoft Authenticator, or Authy. Access supports one TOTP authenticator per user at a time. | -| Security key | YubiKeys and hardware security keys that support the [WebAuthn](https://www.w3.org/TR/webauthn-2/) standard. Users can enroll multiple security keys. | -| Biometrics | Built-in device authenticators that use [WebAuthn](https://www.w3.org/TR/webauthn-2/), including Apple Touch ID, Apple Face ID, and Windows Hello. Users can enroll multiple biometrics. | +| MFA method | Description | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Authenticator application | Time-based one-time passwords (TOTP) generated by apps such as Google Authenticator, Microsoft Authenticator, or Authy. Access supports one TOTP authenticator per user at a time. | +| Security key | YubiKeys that support the [WebAuthn](https://www.w3.org/TR/webauthn-2/) standard. Users can enroll multiple security keys. | +| Biometrics | Built-in device authenticators that use [WebAuthn](https://www.w3.org/TR/webauthn-2/), including Apple Touch ID, Apple Face ID, and Windows Hello. Users can enroll multiple biometrics. | +| PIV key (infrastructure apps only) | YubiKey PIV keys used for public key authentication during SSH connections. Requires YubiKey firmware 4.3 or later. This method is only available for [infrastructure applications](/cloudflare-one/access-controls/applications/non-http/infrastructure-apps/). Users can enroll multiple PIV keys. | ## Turn on independent MFA @@ -79,6 +80,29 @@ Before you can [enforce independent MFA on applications and policies](/cloudflar After you turn on independent MFA, users can [enroll authenticators](#enroll-authenticators) through the [App Launcher](/cloudflare-one/access-controls/access-settings/app-launcher/). +### Configure PIV key requirements + +If you plan to use PIV keys for [MFA for infrastructure applications](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications), configure the PIV key requirements in your organization's Access settings. These requirements determine which PIV keys users can enroll. + +1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Access settings**. +2. Under **Allow multi-factor authentication (MFA)**, turn on the PIV key authenticator. +3. Configure the following settings: + + | Setting | Description | Options | + | ---------------- | ----------------------------------------- | --------------------------------------------------------------- | + | **Key type** | The SSH key algorithm | ECDSA, Ed25519, RSA | + | **Key size** | The key length in bits | ECDSA: 256, 384, 521. RSA: 2048, 3072, 4096 | + | **PIN policy** | When the user must enter their PIV PIN | `never`, `once` (once per session), `always` (every use) | + | **Touch policy** | When the user must touch the hardware key | `never`, `always` (every use), `cached` (cached for 15 seconds) | + +4. Select **Save**. + +Enrolled PIV keys that do not meet these requirements are rejected during SSH authentication. + +:::note + +::: + ## Restrict authenticators by AAGUID An [AAGUID](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-registry-v2.0-id-20180227.html#authenticator-attestation-guid) (Authenticator Attestation GUID) is a 128-bit identifier that indicates the make and model of a [WebAuthn](https://www.w3.org/TR/webauthn-2/) authenticator. By restricting enrollment to a specific set of AAGUIDs, you can require that users only enroll approved hardware, such as FIPS-validated security keys or company-issued devices. @@ -196,8 +220,8 @@ If your identity provider already prompts users for MFA, you can configure Acces ### Supported AMR values -| AMR value | Matches Access authenticator type | Description | -| --------- | --------------------------------- | -------------------------------------- | +| AMR value | Matches Access authenticator type | Description | +| --------- | --------------------------------- | ------------------------------------- | | `hwk` | Security key | Proof-of-possession of a hardware key | | `swk` | Security key | Proof-of-possession of a software key | | `otp` | Authenticator application | One-time password | @@ -339,8 +363,13 @@ To enroll an authenticator:
+ + :::note + Access currently supports YubiKeys as the only hardware security key. + ::: + 1. Select **Security key**. - 2. When your browser prompts you, insert your security key and follow the on-screen instructions. + 2. When your browser prompts you, insert your YubiKey and follow the on-screen instructions. 3. After your browser confirms the registration, the security key is enrolled. You can enroll multiple security keys for backup purposes. @@ -354,8 +383,97 @@ To enroll an authenticator:
+
+ PIV key enrollment requires additional client-side setup and is only used for [MFA with infrastructure applications](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications). For full instructions, refer to [Enroll a PIV key for infrastructure apps](#enroll-a-piv-key-for-infrastructure-apps). +
+ You can now use these authenticators to log in to your organization's applications. +### Enroll a PIV key for infrastructure apps + +PIV key enrollment is separate from the general authenticator enrollment above and requires additional client-side setup. + +Before enrolling, you must have a YubiKey with firmware 4.3 or later and a key generated in PIV slot `9a`. If you have not generated a PIV key yet, refer to [Generate a PIV key](#generate-a-piv-key). + +#### Generate attestation certificates + +Attestation certificates prove that the key was generated on genuine hardware. Run the following commands to export them from your YubiKey: + +```bash +ykman piv keys attest 9a leaf.pem +ykman piv certificates export f9 intermediate.pem +``` + +- `leaf.pem` contains the public key and metadata for the key in slot `9a`. +- `intermediate.pem` is the YubiKey attestation CA certificate. + +#### Upload certificates to Cloudflare + +1. Go to your organization's App Launcher at `.cloudflareaccess.com`. +2. Log in with your identity provider or with a one-time PIN (OTP). +3. Go to **Account** > **MFA devices** > **Add an MFA device**. +4. Select **MFA PIV Key**. +5. Paste the contents of `leaf.pem` into the **Leaf certificate** field. +6. Paste the contents of `intermediate.pem` into the **Intermediate certificate** field. +7. Select **Enroll**. + +Access extracts and stores the SSH public key from your certificate for future authentication to infrastructure apps. You can enroll multiple PIV keys for backup purposes. + +#### Configure your SSH client + +After enrollment, configure your SSH client to use the PIV key. The following example uses `yubikey-agent` on macOS. For Linux, refer to the [yubikey-agent documentation](https://github.com/nicholasgasior/yubikey-agent). + +1. Install and start `yubikey-agent`: + + ```bash + brew install yubikey-agent + brew services start yubikey-agent + ``` + +2. Extract the SSH public key from your leaf certificate: + + ```bash + openssl x509 -in leaf.pem -pubkey -noout | ssh-keygen -i -m PKCS8 -f /dev/stdin > ~/.ssh/id_yubikey.pub + ``` + +3. Add the following to your `~/.ssh/config`: + + ```txt + Host * + IdentityAgent /opt/homebrew/var/run/yubikey-agent.sock + IdentitiesOnly yes + AddKeysToAgent yes + IdentityFile ~/.ssh/id_yubikey.pub + ``` + +4. Verify that the key is loaded: + + ```sh + ssh-add -L + ``` + + The output should show an `ecdsa-sha2-nistp256` key. + +#### Generate a PIV key + +If you do not already have a PIV key on your YubiKey, generate one in slot `9a`: + +```bash +ykman piv keys generate \ + --algorithm ECCP256 \ + --pin-policy ONCE \ + --touch-policy ALWAYS \ + 9a pubkey.pem +``` + +Touch your YubiKey when it blinks to confirm key generation. Then create a self-signed certificate to make the key visible to SSH agents: + +```bash +ykman piv certificates generate --subject "CN=SSH-Identity" 9a pubkey.pem +``` + +After generating the key, [generate attestation certificates](#generate-attestation-certificates) and continue with enrollment. + ### Delete an authenticator Users can delete their own authenticators from the App Launcher. If the user has at least one authenticator enrolled, Access requires them to [verify with an existing MFA method](#mfa-verification-for-authenticator-changes) before they can remove a device. diff --git a/src/content/docs/cloudflare-one/access-controls/applications/non-http/infrastructure-apps.mdx b/src/content/docs/cloudflare-one/access-controls/applications/non-http/infrastructure-apps.mdx index 32171ca33941ce3..2815696bbd0a875 100644 --- a/src/content/docs/cloudflare-one/access-controls/applications/non-http/infrastructure-apps.mdx +++ b/src/content/docs/cloudflare-one/access-controls/applications/non-http/infrastructure-apps.mdx @@ -7,8 +7,8 @@ title: Add an infrastructure application sidebar: order: 2 tags: -- SSH -- Authentication + - SSH + - Authentication --- import { Badge, Details, Tabs, TabItem, Render } from "~/components"; @@ -16,8 +16,8 @@ import { Badge, Details, Tabs, TabItem, Render } from "~/components";
| [Client modes](/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | -| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -|
  • Traffic and DNS mode
  • Traffic only mode
| All plans | +| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +|
  • Traffic and DNS mode
  • Traffic only mode
| All plans | | System | Availability | | -------- | ------------ | @@ -33,7 +33,7 @@ import { Badge, Details, Tabs, TabItem, Render } from "~/components"; Access for Infrastructure allows you to have granular control over how users access individual servers, clusters, or databases. By adding an infrastructure application to Cloudflare Access, you can configure how users authenticate to the resource as well as control and authorize the ports, protocols, and usernames that they can connect with. Access and command logs ensure regulatory compliance and allow for auditing of user activity in case of a security breach. :::note -Access for Infrastructure currently only supports [SSH](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/). To connect using other protocols, [add a self-hosted private application](/cloudflare-one/access-controls/applications/non-http/self-hosted-private-app/). For browser-based SSH, RDP, or VNC, refer to [browser-rendered terminal](/cloudflare-one/access-controls/applications/non-http/browser-rendering/). +Access for Infrastructure currently supports [SSH](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/). To connect using other protocols, [add a self-hosted private application](/cloudflare-one/access-controls/applications/non-http/self-hosted-private-app/). For browser-based SSH, RDP, or VNC, refer to [browser-rendered terminal](/cloudflare-one/access-controls/applications/non-http/browser-rendering/). ::: ## Prerequisites @@ -61,13 +61,19 @@ Access for Infrastructure currently only supports [SSH](/cloudflare-one/networks params={{ selector: "Access Infrastructure Target", protocol: "infra" }} /> -## 4. Configure the server +## 4. (Optional) Require independent MFA + +You can require users to authenticate with a [YubiKey PIV key](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps) before connecting with SSH to targets. MFA can be configured at the application level or at the policy level, allowing you to enforce stricter requirements for sensitive usernames. + +For setup instructions, refer to [Enforce MFA for infrastructure applications](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications). + +## 5. Configure the server Certain protocols require configuring the server to trust connections through Access for Infrastructure. For more information, refer to the protocol-specific tutorial: -- [SSH](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/#6-configure-ssh-server) +- [SSH](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/#7-configure-ssh-server) -## 5. Connect as a user +## 6. Connect as a user Users connect to the target's IP address using their preferred client software. The user must be logged into the Cloudflare One Client on their device, but no other system configuration is required. You can optionally configure a [private DNS resolver](/cloudflare-one/traffic-policies/resolver-policies/) to allow connections to the target's private hostname. @@ -84,13 +90,13 @@ If a user is connected to a target in VNET-A and needs to connect to a target in
| System | Availability | Minimum client version | -| -------- | ------------ | -------------------- | -| Windows | ✅ | 2024.9.346.0 | -| macOS | ✅ | 2024.9.346.0 | -| Linux | ✅ | 2024.9.346.0 | -| iOS | ❌ | | -| Android | ❌ | | -| ChromeOS | ❌ | | +| -------- | ------------ | ---------------------- | +| Windows | ✅ | 2024.9.346.0 | +| macOS | ✅ | 2024.9.346.0 | +| Linux | ✅ | 2024.9.346.0 | +| iOS | ❌ | | +| Android | ❌ | | +| ChromeOS | ❌ | |
diff --git a/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx b/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx index 66966ba9371ff0d..954df0b231b479c 100644 --- a/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx +++ b/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx @@ -12,13 +12,15 @@ tags: - Authentication --- -import { GlossaryTooltip } from "~/components"; +import { GlossaryTooltip, Details, Render } from "~/components"; Cloudflare Access supports two methods of enforcing multi-factor authentication (MFA): - **[Identity provider-based MFA](#identity-provider-based-mfa)** — Require specific MFA methods reported by your identity provider (IdP). - **[Independent MFA](#independent-mfa)** — Prompt users for a second factor directly in Access, without relying on a third-party identity provider. +For SSH connections to [infrastructure applications](/cloudflare-one/access-controls/applications/non-http/infrastructure-apps/), Access also supports [independent MFA with PIV keys](#infrastructure-applications). + ## Identity provider-based MFA You can require that users log in with specific MFA methods provided by their identity provider. For example, you can create rules that only allow users to reach a given application if they authenticate with a security key through their IdP. @@ -107,6 +109,8 @@ To configure MFA for an application: - To exempt the application from MFA, select **Disable MFA**. 5. Select **Save**. +To configure MFA for an infrastructure application, refer to [Infrastructure applications](#infrastructure-applications). + ### Configure independent MFA for a policy Each policy has the same three MFA options described in [Configure independent MFA for an application](#configure-independent-mfa-for-an-application). Policy-level settings override application-level settings. @@ -119,6 +123,8 @@ Each policy has the same three MFA options described in [Configure independent M - To exempt users who match this policy from MFA, select **Disable MFA**. 4. Select **Save**. +To configure MFA for an infrastructure application policy, refer to [Infrastructure applications](#infrastructure-applications). + ### MFA session duration The MFA session duration determines how long a successful MFA authentication remains valid. After the MFA session expires, the user must complete MFA again on their next Cloudflare Access login in addition to completing IdP authentication. You can require users to complete MFA on each Access login or set a custom duration. MFA session durations are only checked during the login flow and do not affect a user's existing session. @@ -163,3 +169,144 @@ In this example: - Users who access Application A and match Policy 2 are not prompted for MFA. - Users who access Application A and match neither policy must use an authenticator application or a security key, with a 24-hour session. - Users who access Application B are not prompted for MFA. + +## Infrastructure applications + +Infrastructure applications that use SSH support independent MFA with [YubiKey PIV keys](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps). When MFA is required, users must complete public key authentication with their enrolled PIV key before the connection is established. Users must [enroll their PIV key](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps) through the App Launcher before they can connect. + +You can configure MFA for infrastructure apps at the application level or at the policy level. + +### Configure MFA for an infrastructure application + +Infrastructure applications use a PIV key authenticator (`infrastructure_ssh`) that is specific to SSH connections. This authenticator type is not available for other Access application types. + +:::note + +::: + +
+ +1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Applications**. +2. Find your infrastructure application and select **Configure**. +3. Go to the **Authentication** tab and select **MFA**. +4. Select one of the following options: + - **Respect global enforcement setting** — Uses the [organization-level](/cloudflare-one/access-controls/access-settings/independent-mfa/) MFA configuration. This is the default. + - **Custom MFA settings** — Override the global setting with a custom MFA session duration for this application. + - **Disable MFA** — Users are not prompted for MFA when accessing this application. +5. Select **Save**. + +
+ +
+ +Add the `mfa_settings` object to your infrastructure application: + +```bash +curl --request PUT \ +https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id} \ +--header "Authorization: Bearer " \ +--header "Content-Type: application/json" \ +--data '{ + "mfa_settings": { + "mfa_use_global_settings": false, + "mfa_bypass": false, + "mfa_session_duration": 720, + "mfa_allowed_authenticators": ["infrastructure_ssh"] + } +}' +``` + +| Field | Type | Description | +| ---------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------- | +| `mfa_use_global_settings` | Boolean | If `true`, uses the organization-level MFA settings. Other fields are ignored. | +| `mfa_bypass` | Boolean | If `true`, MFA is not required for this application, even if global settings enforce MFA. | +| `mfa_session_duration` | Integer | Duration in minutes before the user must re-authenticate with MFA. Set to `0` to require MFA on every SSH connection. | +| `mfa_allowed_authenticators` | Array | List of allowed authenticator types. Use `infrastructure_ssh` for PIV keys. | + +
+ +### Configure MFA for an infrastructure policy + +You can set different MFA requirements for different SSH usernames by configuring MFA at the policy level. Policy-level MFA settings override application-level settings. + +
+ +1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Applications**. +2. Find your infrastructure application and select **Configure**. +3. Go to **Policies** and select the policy you want to configure. +4. Under **Multi-factor authentication (MFA)**, select an option: + - **Respect global enforcement setting** — Inherits the application or organization setting. + - **Custom MFA settings** — Set a custom MFA session duration for users who match this policy. + - **Disable MFA** — Users who match this policy are not prompted for MFA. +5. Select **Save**. + +
+ +
+ +Add the `mfa_settings` object to the policy within your infrastructure application. The `mfa_settings` object uses the same fields as the [application-level configuration](#configure-mfa-for-an-infrastructure-application). + +```bash +curl --request PUT \ +https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id} \ +--header "Authorization: Bearer " \ +--header "Content-Type: application/json" \ +--data '{ + "policies": [ + { + "name": "Require MFA for root", + "decision": "allow", + "include": [ + { + "email": { + "email": "jdoe@company.com" + } + } + ], + "mfa_settings": { + "mfa_use_global_settings": false, + "mfa_bypass": false, + "mfa_session_duration": 60, + "mfa_allowed_authenticators": ["infrastructure_ssh"] + }, + "connection_rules": { + "ssh": { + "usernames": ["root"], + "allow_email_alias": false + } + } + } + ] +}' +``` + +
+ +### MFA session duration for SSH + +The MFA session duration determines how long after performing MFA a user can open new SSH connections without being prompted again. After the session expires, the user must re-authenticate with their PIV key on their next SSH connection. Existing SSH sessions are not affected by session expiration. Set the session duration to `0` to require MFA on every SSH connection. + +MFA sessions are bound to the user's device. If a user switches to a different device, they must re-authenticate regardless of the remaining session duration. + +Session duration is evaluated in the following order: + +1. **Policy-level duration** — If set, applies to users who match the policy. +2. **Application-level duration** — If no policy-level duration is set, uses the application setting. +3. **Organization-level duration** — If neither policy nor application defines a duration, uses the global setting. + +When a user matches multiple policies that each define a session duration, Access uses the **shortest** duration across all matching policies. + +### Precedence and conflict resolution + +MFA configuration is evaluated from most specific to least specific: **policy** > **application** > **organization**. + +| Organization MFA | Application MFA | Policy MFA | Result | +| ---------------- | --------------- | ---------- | ------------------------------------------- | +| Required | Required | Required | MFA required | +| Required | Required | Disabled | MFA not required (policy wins) | +| Required | Disabled | (not set) | MFA not required (application wins) | +| Disabled | Required | (not set) | MFA required (application wins) | +| Disabled | Disabled | Required | MFA required (policy wins) | +| Required | (not set) | (not set) | MFA required (organization setting applies) | + +Explicit settings at a lower level always override higher levels. If no explicit setting exists at a level, the next higher level applies. diff --git a/src/content/docs/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access.mdx b/src/content/docs/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access.mdx index 387c74deca4ce2b..1ca6e1dae0ee914 100644 --- a/src/content/docs/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access.mdx +++ b/src/content/docs/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access.mdx @@ -107,7 +107,20 @@ chmod 600 /etc/ssh/ca.pub -## 8. Connect as a user +## 8. (Optional) Require independent MFA for SSH + +You can require users to authenticate with a [YubiKey PIV key](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps) before connecting to your SSH servers. When MFA is required, users must complete public key authentication with their enrolled PIV key before the connection is established. + +To configure independent MFA for SSH, refer to [Enforce MFA for infrastructure applications](/cloudflare-one/access-controls/policies/mfa-requirements/#infrastructure-applications). + +Before users can connect with MFA enabled, they must: + +1. [Enroll a PIV key](/cloudflare-one/access-controls/access-settings/independent-mfa/#enroll-a-piv-key-for-infrastructure-apps) through the App Launcher. +2. [Configure their SSH client](/cloudflare-one/access-controls/access-settings/independent-mfa/#configure-your-ssh-client) to use the enrolled PIV key. + +When the user runs `ssh @`, the SSH proxy checks if MFA is required for the matching policy. If required, the user must touch their YubiKey and enter their PIN (depending on the key's PIN policy). The proxy then completes the connection. + +## 9. Connect as a user Users can use any SSH client to connect to the target, as long as they are logged into the Cloudflare One Client on their device. If the target is located within a particular virtual network, ensure that the Cloudflare One Client is [connected to that virtual network](/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/#connect-to-a-virtual-network) before initiating the connection. Users do not need to modify any SSH configs on their device. For example, to SSH from a terminal: @@ -117,7 +130,7 @@ ssh @ Access for Infrastructure also supports `scp`, `sftp`, and `rsync` commands. Refer to [Known limitations](#known-limitations) for a list of unsupported SSH commands and features. -To learn more about user connections, refer to the [Access for Infrastructure documentation](/cloudflare-one/access-controls/applications/non-http/infrastructure-apps/#4-connect-as-a-user). +To learn more about user connections, refer to the [Access for Infrastructure documentation](/cloudflare-one/access-controls/applications/non-http/infrastructure-apps/#6-connect-as-a-user). ## SSH command logs @@ -484,7 +497,52 @@ These troubleshooting steps could result in you being locked out of your SSH ser By completing all four troubleshooting steps, you should have resolved any connection issues caused by misconfiguration of the SSH server. If issues persist, [recheck `sshd` logs](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/#review-your-sshd-logs). The example [`sshd_config` shared above](/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/ssh/ssh-infrastructure-access/#review-your-sshd_config-file-for-misconfigurations) enables debug logging and may expose more specific issues. -### 5. Get help +### 5. Troubleshoot PIV key authentication + +If MFA is enabled and the user cannot authenticate with their PIV key, check the following: + +#### Hardware key not detected + +Verify that the YubiKey is recognized and the PIV applet is functional: + +```bash +ykman list +ykman piv info +``` + +#### SSH agent does not show the key + +Verify that `yubikey-agent` is running and the key is loaded: + +```bash +brew services list | grep yubikey-agent +ssh-add -L +``` + +If no key is listed, restart `yubikey-agent`: + +```bash +brew services restart yubikey-agent +``` + +#### PIV PIN blocked + +The PIV PIN has a retry counter (default: 3 attempts). If the counter is exhausted, the PIN is blocked. Check the retry counter and unblock with the PUK (PIN Unblocking Key): + +```bash +ykman piv info +ykman piv access unblock-pin +``` + +If the PUK is also blocked, you must reset the PIV applet. This destroys all keys stored on the device: + +```bash +ykman piv reset +``` + +After resetting, [generate a new PIV key](/cloudflare-one/access-controls/access-settings/independent-mfa/#generate-a-piv-key) and re-enroll. + +### 6. Get help