From b6f439fd7982c1be1378644f43317fbf8f91b3e1 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Mon, 11 Aug 2025 16:20:57 -0400 Subject: [PATCH 01/10] draft: security freshness --- .../enterprise/security/domain-management.md | 188 ++++--- .../security/enforce-sign-in/_index.md | 69 ++- .../security/enforce-sign-in/methods.md | 405 ++++++-------- .../security/hardened-desktop/_index.md | 40 +- .../enhanced-container-isolation/_index.md | 165 +++--- .../features-benefits.md | 268 ++++------ .../how-eci-works.md | 112 ++-- .../settings-management/_index.md | 76 +-- .../compliance-reporting.md | 157 +++--- .../configure-admin-console.md | 64 ++- .../configure-json-file.md | 103 ++-- .../settings-management/settings-reference.md | 494 +++++++++--------- .../security/provisioning/_index.md | 72 ++- .../security/provisioning/group-mapping.md | 158 +++--- .../security/provisioning/just-in-time.md | 24 +- .../enterprise/security/provisioning/scim.md | 120 ++--- .../security/roles-and-permissions.md | 62 +-- .../security/single-sign-on/_index.md | 68 ++- .../security/single-sign-on/configure.md | 73 +-- .../security/single-sign-on/connect.md | 229 ++++---- .../security/single-sign-on/manage.md | 143 +++-- content/manuals/security/_index.md | 25 +- data/summary.yaml | 1 + hugo_stats.json | 7 + layouts/shortcodes/admin-scim-disable.html | 13 - layouts/shortcodes/admin-scim.html | 13 - layouts/shortcodes/admin-sso-management.md | 26 - 27 files changed, 1448 insertions(+), 1727 deletions(-) delete mode 100644 layouts/shortcodes/admin-scim-disable.html delete mode 100644 layouts/shortcodes/admin-scim.html delete mode 100644 layouts/shortcodes/admin-sso-management.md diff --git a/content/manuals/enterprise/security/domain-management.md b/content/manuals/enterprise/security/domain-management.md index 0d3d0ef17c45..6ddfd5297bf4 100644 --- a/content/manuals/enterprise/security/domain-management.md +++ b/content/manuals/enterprise/security/domain-management.md @@ -1,7 +1,7 @@ --- -description: Learn how to manage domains and users in the Admin Console -keywords: domain management, security, identify users, manage users -title: Domain management +title: Manage domains +description: Add, verify, and manage domains to control user access and enable auto-provisioning in Docker organizations +keywords: domain management, domain verification, auto-provisioning, user management, DNS, TXT record, Admin Console weight: 55 aliases: - /security/for-admins/domain-management/ @@ -9,16 +9,15 @@ aliases: {{< summary-bar feature_name="Domain management" >}} -Domain management lets you add and verify domains, and enable -auto-provisioning for users. Auto-provisioning adds users to your -organization when they sign in with an email address that matches a verified -domain. +Domain management lets you add and verify domains for your organization, then enable auto-provisioning to automatically add users when they sign in with email addresses that match your verified domains. -This simplifies user management, ensures consistent security settings, and -reduces the risk of unmanaged users accessing Docker without visibility -or control. +This approach simplifies user management, ensures consistent security settings, and reduces the risk of unmanaged users accessing Docker without visibility or control. -## Add a domain +## Add and verify a domain + +Adding a domain requires verification to confirm ownership. The verification process uses DNS records to prove you control the domain. + +### Add a domain 1. Sign in to [Docker Home](https://app.docker.com) and select your organization. If your organization is part of a company, select the company @@ -28,18 +27,13 @@ and configure the domain for the organization at the company level. 1. Enter your domain and select **Add domain**. 1. In the pop-up modal, copy the **TXT Record Value** to verify your domain. -## Verify a domain +### Verify a domain -Verifying your domain confirms that you own it. To verify, add a TXT record to -your Domain Name System (DNS) host using the value provided by Docker. This -value proves ownership and instructs your DNS to publish the record. +Verification confirms that you own the domain by adding a TXT record to your Domain Name System (DNS) host. It can take up to 72 hours for the DNS change to propagate. Docker automatically checks for the record and confirms ownership once the change is recognized. -Follow your DNS provider’s documentation to add the **TXT Record Value**. If -your provider isn't listed, use the steps for other providers. - > [!TIP] > > The record name field determines where the TXT record is added in your domain @@ -53,81 +47,113 @@ domain name. These values may direct to the wrong place. > > Check your DNS provider's documentation to verify record name requirements. +Follow the steps for your DNS provider to add the **TXT Record Value**. If +your provider isn't listed, use the steps for "Other providers": + {{< tabs >}} {{< tab name="AWS Route 53" >}} -1. To add your TXT record to AWS, see [Creating records by using the Amazon Route 53 console](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html). -1. TXT record verification can take 72 hours. Once you have waited for -TXT record verification, return to the **Domain management** page of the +1. Add your TXT record to AWS by following [Creating records by using the Amazon Route 53 console](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html). +1. Wait up to 72 hours for TXT record verification. +1. Return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. {{< /tab >}} {{< tab name="Google Cloud DNS" >}} -1. To add your TXT record to Google Cloud DNS, see [Verifying your domain with a TXT record](https://cloud.google.com/identity/docs/verify-domain-txt). -1. TXT record verification can take 72 hours. Once you have waited for TXT -record verification, return to the **Domain management** page of the +1. Add your TXT record to Google Cloud DNS by following [Verifying your domain with a TXT record](https://cloud.google.com/identity/docs/verify-domain-txt). +1. Wait up to 72 hours for TXT record verification. +1. Return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. {{< /tab >}} {{< tab name="GoDaddy" >}} -1. To add your TXT record to GoDaddy, see [Add a TXT record](https://www.godaddy.com/help/add-a-txt-record-19232). -1. TXT record verification can take 72 hours. Once you have waited for TXT -record verification, return to the **Domain management** page of the -[Admin Console](https://app.docker.com/admin) and select **Verify** next to your -domain name. +1. Add your TXT record to GoDaddy by following [Add a TXT record](https://www.godaddy.com/help/add-a-txt-record-19232). +1. Wait up to 72 hours for TXT record verification. +1. Return to the **Domain management** page of the +[Admin Console](https://app.docker.com/admin) and select **Verify** next to +your domain name. {{< /tab >}} {{< tab name="Other providers" >}} 1. Sign in to your domain host. -1. Add a TXT record to your DNS settings and save the record. -1. TXT record verification can take 72 hours. Once you have waited for TXT -record verification, return to the **Domain management** page of the +1. Add a TXT record to your DNS settings using the **TXT Record Value** from Docker. +1. Wait up to 72 hours for TXT record verification. +1. Return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. {{< /tab >}} {{< /tabs >}} -## Delete a domain +## Configure auto-provisioning + +Auto-provisioning automatically adds users to your organization when they sign in with email addresses that match your verified domains. You must verify a domain before enabling auto-provisioning. + +> [!IMPORTANT] +> +> For domains that are part of an SSO connection, Just-in-Time (JIT) provisioning takes precedence over auto-provisioning when adding users to an organization. + +### How auto-provisioning works + +When auto-provisioning is enabled for a verified domain: + +- Users who sign in to Docker with matching email addresses are automatically added to your organization. +- Auto-provisioning only adds existing Docker users to your organization, it doesn't create new accounts. +- Users experience no changes to their sign-in process. +- Company and organization owners receive email notifications when new users are added. +- You may need to [manage seats](/manuals/subscription/manage-seats.md) to accomodate new users. + +### Enable auto-provisioning -Deleting a domain removes the assigned TXT record value. To delete a domain: +Auto-provisioning is configured per domain. To enable it: 1. Sign in to [Docker Home](https://app.docker.com) and select your organization. If your organization is part of a company, select the company and configure the domain for the organization at the company level. 1. Select **Admin Console**, then **Domain management**. -1. For the domain you want to delete, section the **Actions** menu, then -**Delete domain**. -1. To confirm, select **Delete domain** in the pop-up modal. +1. Select the **Actions menu** next to the domain you want to enable +auto-provisioning for. +1. Select **Enable auto-provisioning**. +1. Optional. If enabling auto-provisioning at the company level, select an +organization. +1. Select **Enable** to confirm. -## Audit domains +The **Auto-provisioning** column will update to **Enabled** for the domain. + +### Disable auto-provisioning + +To disable auto-provisioning for a user: + +1. Sign in to [Docker Home](https://app.docker.com) and select +your organization. If your organization is part of a company, select the company +and configure the domain for the organization at the company level. +1. Select **Admin Console**, then **Domain management**. +1. Select the **Actions menu** next to your domain. +1. Select **Disable auto-provisioning**. +1. Select **Disable** to confirm. + +## Audit domains for uncaptured users {{< summary-bar feature_name="Domain audit" >}} -The domain audit feature identifies uncapture users in an organization. -Uncaptured users are Docker users who have authenticated to Docker -using an email address associated with one of your verified domains, -but they're not a member of your Docker organization. +Domain audit identifies uncaptured users. Uncaptured users are Docker users who have authenticated using an email address associated with your verified domains but aren't members of your Docker organization. -### Known limitations +### Limitations -Domain audit can't identify the following Docker users: +Domain audit can't identify: - Users who access Docker Desktop without authenticating - Users who authenticate using an account that doesn't have an -email address associated with one of your verified domains. +email address associated with one of your verified domains -Although domain audit can't identify all Docker users, -you can enforce sign-in to prevent unidentifiable users from accessing -Docker Desktop in your environment. For more information, -see [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md). +To prevent unidentifiable users from accessing Docker Desktop, [enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md). -### Audit your domain for uncaptured users +### Run a domain audit 1. Sign in to [Docker Home](https://app.docker.com) and choose your company. @@ -137,68 +163,30 @@ of uncaptured users. The CSV file contains the following columns: - - Name: Name of the Docker user - - Username: Docker ID of the Docker user - - Email: Email address of the Docker user + - Name: Docker user's display name + - Username: Docker ID of the user + - Email: Email address of the user ### Invite uncaptured users -You can invite all uncaptured users to your organization using the exported +You can bulk invite uncaptured users to your organization using the exported CSV file. For more information on bulk inviting users, see [Manage organization members](/manuals/admin/organization/members.md). -## Auto-provisioning +## Delete a domain -You must add and verify a domain before enabling auto-provisioning. This -confirms your organization owns the domain. Once a domain is verified, -Docker can automatically associate matching users with your organization. -Auto-provisioning does not require an SSO connection. +Deleting a domain removes its TXT record value and disables any associated auto-provisioning. -> [!IMPORTANT] +>[!WARNING] > -> For domains that are part of an SSO connection, Just-in-Time (JIT) overrides -auto-provisioning to add users to an organization. - -### How it works - -When auto-provisioning is enabled for a verified domain, the next time a user -signs into Docker with an email address that is associated with your verified -domain, they are automatically added to your organization. Auto-provisioning -does not create accounts for new users, it adds existing unassociated users to -your organization. Users will *not* experience any sign in or user experience -changes. +> Deleting a domain will disable auto-provisioning for that domain and remove verification. This action cannot be undone. -When a new user is auto-provisioned, company and organization owners will -receive an email notifying them that a new user has been added to their -organization. If you need to add more seats to your organization to -to accomodate new users, see [Manage seats](/manuals/subscription/manage-seats.md). - -### Enable auto-provisioning - -Auto-provisioning is enabled per user. To enable -auto-provisioning: +To delete a domain: 1. Sign in to [Docker Home](https://app.docker.com) and select your organization. If your organization is part of a company, select the company and configure the domain for the organization at the company level. 1. Select **Admin Console**, then **Domain management**. -1. Select the **Actions menu** next to the user you want to enable -auto-provisioning for. -1. Select **Enable auto-provisioning**. -1. Optional. If enabling auto-provisioning at the company level, select an -organization for the user. -1. Select **Enable** to confirm. - -The **Auto-provisioning** column will update to **Enabled**. - -### Disable auto-provisioning - -To disable auto-provisioning for a user: - -1. Sign in to [Docker Home](https://app.docker.com) and select -your organization. If your organization is part of a company, select the company -and configure the domain for the organization at the company level. -1. Select **Admin Console**, then **Domain management**. -1. Select the **Actions menu** next to your user. -1. Select **Disable auto-provisioning**. -1. Select **Disable**. +1. For the domain you want to delete, section the **Actions** menu, then +**Delete domain**. +1. To confirm, select **Delete domain** in the pop-up modal. diff --git a/content/manuals/enterprise/security/enforce-sign-in/_index.md b/content/manuals/enterprise/security/enforce-sign-in/_index.md index c0cc6e5088d9..c62acdc0ed3e 100644 --- a/content/manuals/enterprise/security/enforce-sign-in/_index.md +++ b/content/manuals/enterprise/security/enforce-sign-in/_index.md @@ -1,9 +1,9 @@ --- -description: Understand what happens when you force users to sign in to Docker Desktop -toc_max: 2 -keywords: authentication, registry.json, configure, enforce sign-in, docker desktop, security, .plist, registry key, mac, windows title: Enforce sign-in for Docker Desktop linkTitle: Enforce sign-in +description: Require users to sign in to Docker Desktop to access organization benefits and security features +toc_max: 2 +keywords: authentication, registry.json, configure, enforce sign-in, docker desktop, security, .plist, registry key, mac, windows, organization tags: [admin] aliases: - /security/for-admins/configure-sign-in/ @@ -14,56 +14,49 @@ weight: 30 {{< summary-bar feature_name="Enforce sign-in" >}} -By default, members of your organization can use Docker Desktop without signing -in. When users don’t sign in as a member of your organization, they don’t -receive the [benefits of your organization’s -subscription](/manuals/subscription/details.md) and they can circumvent -[Docker’s -security features](/manuals/enterprise/security/hardened-desktop/_index.md) for -your organization. +By default, users can run Docker Desktop without signing in to your organization. +When users don't sign in as organization members, they miss out on [subscription benefits](/manuals/subscription/details.md) and can bypass +[security features](/manuals/enterprise/security/hardened-desktop/_index.md) configured for your organization. + +You can enforce sign-in using several methods, depending on your setup: -There are multiple methods for enforcing sign-in, depending on your companies' -set up and preferences: -- [Registry key method (Windows only)](methods.md#registry-key-method-windows-only){{< badge color=green text="New" >}} -- [Configuration profiles method (Mac only)](methods.md#configuration-profiles-method-mac-only){{< badge color=green text="New" >}} -- [`.plist` method (Mac only)](methods.md#plist-method-mac-only){{< badge color=green text="New" >}} +- [Registry key method (Windows only)](methods.md#registry-key-method-windows-only) +- [Configuration profiles method (Mac only)](methods.md#configuration-profiles-method-mac-only) +- [`.plist` method (Mac only)](methods.md#plist-method-mac-only) - [`registry.json` method (All)](methods.md#registryjson-method-all) -## How is sign-in enforced? +## How sign-in enforcement works -When Docker Desktop starts and it detects a registry key, `.plist` file, or -`registry.json` file, the following occurs: +When Docker Desktop detects a registry key, `.plist` file, or +`registry.json` file: -- A **Sign in required!** prompt appears requiring the user to sign - in as a member of your organization to use Docker Desktop. ![Enforce Sign-in +- A **Sign in required!** prompt appears, requiring users to sign + in as organization members to use Docker Desktop. ![Enforce Sign-in Prompt](../../images/enforce-sign-in.png?w=400) -- When a user signs in to an account that isn’t a member of your organization, - they are automatically signed out and can’t use Docker Desktop. The user - can select **Sign in** and try again. -- When a user signs in to an account that is a member of your organization, they - can use Docker Desktop. -- When a user signs out, the **Sign in required!** prompt appears and they can - no longer use Docker Desktop. +- If users sign in with accounts that aren't organization members, they're + automatically signed out and can't use Docker Desktop. They can select **Sign in** + to try again with a different account. +- When users sign in with organization member accounts, they can use Docker + Desktop normally. +- When users sign out, the **Sign in required!** prompt reappears and they can + no longer use Docker Desktop unless they sign back in. > [!NOTE] > -> Enforcing sign-in for Docker Desktop does not impact accessing the Docker CLI. -CLI access is only impacted for organizations that enforce single sign-on. +> Enforcing sign-in for Docker Desktop doesn't affect Docker CLI access. CLI access is only restricted for organizations that enforce single sign-on (SSO). ## Enforcing sign-in versus enforcing single sign-on (SSO) -[Enforcing SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso) -and enforcing sign-in are different features. The following table provides a -description and benefits when using each feature. +Enforcing Docker Desktop sign-in and [enforcing SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso) are different features that server different purposes: + | Enforcement | Description | Benefits | |:----------------------------------|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Enforce sign-in only | Users must sign in before using Docker Desktop. | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. | | Enforce single sign-on (SSO) only | If users sign in, they must sign in using SSO. | Centralizes authentication and enforces unified policies set by the identity provider. | -| Enforce both | Users must sign in using SSO before using Docker Desktop. | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. Finally, it centralizes authentication and enforces unified policies set by the identity provider. | -| Enforce neither | If users sign in, they can use SSO or their Docker credentials. | Lets users access Docker Desktop without barriers, but at the cost of reduced security and insights. | - -## What's next? +| Enforce both | Users must sign in using SSO before using Docker Desktop. | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. It also centralizes authentication and enforces unified policies set by the identity provider. | +| Enforce neither | If users sign in, they can use SSO or their Docker credentials. | Lets users access Docker Desktop without barriers, at the cost of reduced security and insights. | +## Next steps -- To enforce sign-in, review the [Methods](/manuals/enterprise/security/enforce-sign-in/methods.md) guide. -- To enforce SSO, review the [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md) steps. \ No newline at end of file +- To set up sign-in enforcement, see [Configure sign-in enforcement](/manuals/enterprise/security/enforce-sign-in/methods.md) guide. +- To configure SSO enforcement, see [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md). \ No newline at end of file diff --git a/content/manuals/enterprise/security/enforce-sign-in/methods.md b/content/manuals/enterprise/security/enforce-sign-in/methods.md index 6b4052140000..8c8c6e6f41e0 100644 --- a/content/manuals/enterprise/security/enforce-sign-in/methods.md +++ b/content/manuals/enterprise/security/enforce-sign-in/methods.md @@ -1,71 +1,85 @@ --- -description: Learn about the different ways you can force your developers to sign in to Docker Desktop -keywords: authentication, registry.json, configure, enforce sign-in, docker desktop, security, .plist. registry key, mac, windows -title: Ways to enforce sign-in for Docker Desktop +title: Configure sign-in enforcement +linkTitle: Configure +description: Configure sign-in enforcement for Docker Desktop using registry keys, configuration profiles, plist files, or registry.json files +keywords: authentication, registry.json, configure, enforce sign-in, docker desktop, security, .plist, registry key, mac, windows, linux tags: [admin] -linkTitle: Methods aliases: - /security/for-admins/enforce-sign-in/methods/ --- {{< summary-bar feature_name="Enforce sign-in" >}} -This page outlines the different methods for enforcing sign-in for Docker Desktop. +You can enforce sign-in for Docker Desktop using several methods. Choose the method that best fits your organization's infrastructure and security requirements. -## Registry key method (Windows only) +## Choose your method -> [!NOTE] +| Method | Platform | +|:-------|:---------| +| Registry key | Windows only | +| Configuration profiles | macOS only | +| `plist` file | macOS only | +| `registry.json` | All platforms | + +> [!TIP] > -> The registry key method is available with Docker Desktop version 4.32 and later. +> For macOS, configuration profiles offer the highest security because they're +protected by Apple's System Integrity Protection (SIP). + +## Windows: Registry key method + +{{< tabs >}} +{{< tab name="Manual setup" >}} -To enforce sign-in for Docker Desktop on Windows, you can configure a registry key that specifies your organization's allowed users. The following steps guide you through creating and deploying the registry key to enforce this policy: +To configure the registry key method manually: -1. Create the registry key. Your new key should look like the following: +1. Create the registry key: ```console $ HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Docker\Docker Desktop ``` -2. Create a multi-string value `allowedOrgs`. - > [!IMPORTANT] - > - > As of Docker Desktop version 4.36 and later, you can add more than one organization. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. -3. Use your organization's name, all lowercase as string data. If you're adding more than one organization, make sure they are all on their own line. Don't use any other separators such as spaces or commas. -4. Restart Docker Desktop. -5. When Docker Desktop restarts, verify that the **Sign in required!** prompt appears. - -In some cases, a system reboot may be necessary for enforcement to take effect. +1. Create a multi-string value name `allowedOrgs`. +1. Use your organization names as string data: + - Use lowercase letters only + - Add each organization on a separate line + - Do not use spaces or commas as separators +1. Restart Docker Desktop. +1. Verify the **Sign in required!** prompt appears. -> [!NOTE] +> [!IMPORTANT] > -> If a registry key and a `registry.json` file both exist, the registry key takes precedence. +> You can add multiple organizations with Docker Desktop version 4.36 and later. +With version 4.35 and earlier, adding multiple organizations causes sign-in +enforcement to fail silently. -### Example deployment via Group Policy - -The following example outlines how to deploy a registry key to enforce sign-in on Docker Desktop using Group Policy. There are multiple ways to deploy this configuration depending on your organization's infrastructure, security policies, and management tools. +{{< /tab >}} +{{< tab name="Group Policy deployment" >}} + +Deploy the registry key across your organization using Group Policy: + +1. Create a registry script with the required key structure. +1. In Group Policy Management, create or edit a GPO. +1. Navigate to **Computer Configuration** > **Preferences** > **Windows Settings** > **Registry**. +1. Right-click **Registry** > **New** > **Registry Item**. +1. Configure the registry item: + - Action: **Update** + - Path: `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Docker\Docker Desktop` + - Value name: `allowedOrgs` + - Value data: Your organization names +1. Link the GPO to the target Organizational Unit. +1. Test on a small group using `gpupdate/force`. +1. Deploy organization-wide after verification. -1. Create the registry script. Write a script to create the `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Docker\Docker Desktop` key, add the `allowedOrgs` multi-string, and then set the value to your organization’s name. -2. Within Group Policy, create or edit a Group Policy Objective (GPO) that applies to the machines or users you want to target. -3. Within the GPO, navigate to **Computer Configuration** and select **Preferences**. -4. Select **Windows Settings** then **Registry**. -5. To add the registry item, right-click on the **Registry** node, select **New**, and then **Registry Item**. -6. Configure the new registry item to match the registry script you created, specifying the action as **Update**. Make sure you input the correct path, value name (`allowedOrgs`), and value data (your organization names). -7. Link the GPO to an Organizational Unit (OU) that contains the machines you want to apply this setting to. -8. Test the GPO on a small set of machines first to ensure it behaves as expected. You can use the `gpupdate /force` command on a test machine to manually refresh its group policy settings and check the registry to confirm the changes. -9. Once verified, you can proceed with broader deployment. Monitor the deployment to ensure the settings are applied correctly across the organization's computers. +{{< /tab >}} +{{< /tabs >}} -## Configuration profiles method (Mac only) +## macOS: Configuration profiles method (recommended) {{< summary-bar feature_name="Config profiles" >}} -Configuration profiles are a feature of macOS that let you distribute -configuration information to the Macs you manage. It is the safest method to -enforce sign-in on macOS because the installed configuration profiles are -protected by Apples' System Integrity Protection (SIP) and therefore can't be -tampered with by the users. - -1. Save the following XML file with the extension `.mobileconfig`, for example - `docker.mobileconfig`: +Configuration profiles provide the most secure enforcement method for macOS because they're protected by Apple's System Integrity Protection. +1. Create a file named `docker.mobileconfig` with this content: ```xml @@ -109,33 +123,22 @@ tampered with by the users. ``` +1. Replace placeholders: + - Change `com.yourcompany.docker.config` to your company identifier + - Replace `Your Company Name` with your organization name + - Update the `allowedOrgs` value with your organization names (separated by semicolons) +1. Deploy the profile using your MDM solution. +1. Verify the profile appears in **System Settings** > **General** > **Device Management** under **Device (Managed)** profiles. -2. Change the placeholders `com.yourcompany.docker.config` and `Your Company Name` to the name of your company. +## macOS: plist file method -3. Add your organization name. The names of the allowed organizations are stored in the `allowedOrgs` - property. It can contain either the name of a single organization or a list of organization names, - separated by a semicolon: - - ```xml - allowedOrgs - first_org;second_org - ``` - -4. Use a MDM solution to distribute your modified `.mobileconfig` file to your macOS clients. - -5. Verify that the profile is added to **Device (Managed)** profiles list (**System Settings** > **General** > **Device Management**) on your macOS clients. - -## plist method (Mac only) - -> [!NOTE] -> -> The `plist` method is available with Docker Desktop version 4.32 and later. +Use this alternative method for macOS with Docker Desktop version 4.32 and later. -To enforce sign-in for Docker Desktop on macOS, you can use a `plist` file that defines the required settings. The following steps guide you through the process of creating and deploying the necessary `plist` file to enforce this policy: +{{< tabs >}} +{{< tab name="Manual creation" >}} 1. Create the file `/Library/Application Support/com.docker.docker/desktop.plist`. -2. Open `desktop.plist` in a text editor and add the following content, where `myorg` is replaced with your organization’s name all lowercase: - +1. Add this content, replacing `myorg1` and `myorg2` with your organization names: ```xml @@ -149,250 +152,138 @@ To enforce sign-in for Docker Desktop on macOS, you can use a `plist` file that ``` - > [!IMPORTANT] - > - > As of Docker Desktop version 4.36 and later, you can add more than one organization. With Docker Desktop version 4.35 and earlier, sign-in enforcement silently fails if you add more than one organization. +1. Set file permissions to prevent editing by non-administrator users. +1. Restart Docker Desktop. +1. Verify the **Sign in required!** prompt appears. -3. Modify the file permissions to ensure the file cannot be edited by any non-administrator users. -4. Restart Docker Desktop. -5. When Docker Desktop restarts, verify that the **Sign in required!** prompt appears. +{{< /tab >}} +{{< tab name="Shell script deployment" >}} -> [!NOTE] -> -> If a `plist` and `registry.json` file both exist, the `plist` file takes precedence. +Create and deploy a script for organization-wide distribution: -### Example deployment +```bash +#!/bin/bash -The following example outlines how to create and distribute the `plist` file to enforce sign-in on Docker Desktop. There are multiple ways to deploy this configuration depending on your organization's infrastructure, security policies, and management tools. +# Create directory if it doesn't exist +sudo mkdir -p "/Library/Application Support/com.docker.docker" -{{< tabs >}} -{{< tab name="MDM" >}} +# Write the plist file +sudo defaults write "/Library/Application Support/com.docker.docker/desktop.plist" allowedOrgs -array "myorg1" "myorg2" -1. Follow the steps previously outlined to create the `desktop.plist` file. -2. Use an MDM tool like Jamf or Fleet to distribute the `desktop.plist` file to `/Library/Application Support/com.docker.docker/` on target macOS devices. -3. Through the MDM tool, set the file permissions to permit editing by administrators only. +# Set appropriate permissions +sudo chmod 644 "/Library/Application Support/com.docker.docker/desktop.plist" +sudo chown root:admin "/Library/Application Support/com.docker.docker/desktop.plist" +``` -{{< /tab >}} -{{< tab name="Shell script" >}} - -1. Create a Bash script that can check for the existence of the `.plist` file in the correct directory, create or modify it as needed, and set the appropriate permissions. - Include commands in your script to: - - Navigate to the `/Library/Application Support/com.docker.docker/` directory or create it if it doesn't exist. - - Use the `defaults` command to write the required keys and values to the `desktop.plist` file. For example: - ```console - $ defaults write /Library/Application\ Support/com.docker.docker/desktop.plist allowedOrgs -string "myorg" - ``` - - Change permissions of the `plist` file to restrict editing, using `chmod` and possibly `chown` to set the owner to root or another administrator account, ensuring it can't be easily modified by unauthorized users. -2. Before deploying the script across the organization, test it on a local macOS machine to ensure it behaves as expected. Pay attention to directory paths, permissions, and the successful application of `plist` settings. -3. Ensure that you have the capability to execute scripts remotely on macOS devices. This might involve setting up SSH access or using a remote support tool that supports macOS. -4. Use a method of remote script execution that fits your organization's infrastructure. Options include: - - SSH: If SSH is enabled on the target machines, you can use it to execute the script remotely. This method requires knowledge of the device's IP address and appropriate credentials. - - Remote support tool: For organizations using a remote support tool, you can add the script to a task and execute it across all selected machines. -5. Ensure the script is running as expected on all targeted devices. You may have to check log files or implement logging within the script itself to report its success or failure. +Deploy this script using SSH, remote support tools, or your preferred deployment method. {{< /tab >}} {{< /tabs >}} -## registry.json method (All) - -The following instructions explain how to create and deploy a `registry.json` file to a single device. There are many ways to deploy the `registry.json` file. You can follow the example deployments outlined in the `.plist` file section. The method you choose is dependent on your organization's infrastructure, security policies, and the administrative rights of the end-users. - -### Option 1: Create a registry.json file to enforce sign-in - -1. Ensure the user is a member of your organization in Docker. For more -details, see [Manage members](/admin/organization/members/). -2. Create the `registry.json` file. - - Based on the user's operating system, create a file named `registry.json` at the following location and make sure the file can't be edited by the user. +## All platforms: registry.json method - | Platform | Location | - | --- | --- | - | Windows | `/ProgramData/DockerDesktop/registry.json` | - | Mac | `/Library/Application Support/com.docker.docker/registry.json` | - | Linux | `/usr/share/docker-desktop/registry/registry.json` | +The registry.json method works across all platforms and offers flexible deployment options. -3. Specify your organization in the `registry.json` file. +### File locations - Open the `registry.json` file in a text editor and add the following contents, where `myorg` is replaced with your organization’s name. The file contents are case-sensitive and you must use lowercase letters for your organization's name. +Create the `registry.json` file at the appropriate location: +| Platform | Location | +| --- | --- | +| Windows | `/ProgramData/DockerDesktop/registry.json` | +| Mac | `/Library/Application Support/com.docker.docker/registry.json` | +| Linux | `/usr/share/docker-desktop/registry/registry.json` | - ```json - { - "allowedOrgs": ["myorg1", "myorg2"] - } - ``` - > [!IMPORTANT] - > - > As of Docker Desktop version 4.36 and later, you can add more than one organization. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. - -4. Verify that sign-in is enforced. - - To activate the `registry.json` file, restart Docker Desktop on the user’s machine. When Docker Desktop starts, verify that the **Sign in - required!** prompt appears. - - In some cases, a system reboot may be necessary for the enforcement to take effect. - - > [!TIP] - > - > If your users have issues starting Docker Desktop after you enforce sign-in, they may need to update to the latest version. - -### Option 2: Create a registry.json file when installing Docker Desktop - -To create a `registry.json` file when installing Docker Desktop, use the following instructions based on your user's operating system. +### Basic setup {{< tabs >}} -{{< tab name="Windows" >}} - -To automatically create a `registry.json` file when installing Docker Desktop, -download `Docker Desktop Installer.exe` and run one of the following commands -from the directory containing `Docker Desktop Installer.exe`. Replace `myorg` -with your organization's name. You must use lowercase letters for your -organization's name. - -If you're using PowerShell: - -```powershell -PS> Start-Process '.\Docker Desktop Installer.exe' -Wait 'install --allowed-org=myorg' -``` - -If you're using the Windows Command Prompt: +{{< tab name="Manual creation" >}} + +1. Ensure users are members of your Docker organization. +1. Create the `registry.json` file at the appropriate location for your platform. +1. Add this content, replacing organization names with your own: + ```json + { + "allowedOrgs": ["myorg1", "myorg2"] + } + ``` +1. Set file permissions to prevent user editing. +1. Restart Docker Desktop. +1. Verify the **Sign in required!** prompt appears. -```console -C:\Users\Admin> "Docker Desktop Installer.exe" install --allowed-org=myorg -``` -> [!IMPORTANT] +> [!TIP] > -> As of Docker Desktop version 4.36 and later, you can add more than one organization to a single `registry.json` file. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. +> If users have issues starting Docker Desktop after enforcing sign-in, +they may need to update to the latest version. {{< /tab >}} -{{< tab name="Mac" >}} +{{< tab name="Command line setup" >}} -To automatically create a `registry.json` file when installing Docker Desktop, -download `Docker.dmg` and run the following commands in a terminal from the -directory containing `Docker.dmg`. Replace `myorg` with your organization's name. You must use lowercase letters for your organization's name. +#### Windows (PowerShell as Administrator): -```console -$ sudo hdiutil attach Docker.dmg -$ sudo /Volumes/Docker/Docker.app/Contents/MacOS/install --allowed-org=myorg -$ sudo hdiutil detach /Volumes/Docker +```shell +Set-Content /ProgramData/DockerDesktop/registry.json '{"allowedOrgs":["myorg1","myorg2"]}' ``` -{{< /tab >}} -{{< /tabs >}} - -### Option 3: Create a registry.json file using the command line +#### macOS: -To create a `registry.json` using the command line, use the following instructions based on your user's operating system. - -{{< tabs >}} -{{< tab name="Windows" >}} - -To use the CLI to create a `registry.json` file, run the following PowerShell -command as an administrator and replace `myorg` with your organization's name. The file -contents are case-sensitive and you must use lowercase letters for your -organization's name. - -```powershell -PS> Set-Content /ProgramData/DockerDesktop/registry.json '{"allowedOrgs":["myorg"]}' +```console +sudo mkdir -p "/Library/Application Support/com.docker.docker" +echo '{"allowedOrgs":["myorg1","myorg2"]}' | sudo tee "/Library/Application Support/com.docker.docker/registry.json" ``` -This creates the `registry.json` file at -`C:\ProgramData\DockerDesktop\registry.json` and includes the organization -information the user belongs to. Make sure that the user can't edit this file, but only the administrator can: +#### Linux: ```console -PS C:\ProgramData\DockerDesktop> Get-Acl .\registry.json - - - Directory: C:\ProgramData\DockerDesktop - - -Path Owner Access ----- ----- ------ -registry.json BUILTIN\Administrators NT AUTHORITY\SYSTEM Allow FullControl... +sudo mkdir -p /usr/share/docker-desktop/registry +echo '{"allowedOrgs":["myorg1","myorg2"]}' | sudo tee /usr/share/docker-desktop/registry/registry.json ``` -> [!IMPORTANT] -> -> As of Docker Desktop version 4.36 and later, you can add more than one organization to a single `registry.json` file. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. - {{< /tab >}} -{{< tab name="Mac" >}} +{{< tab name="Installation-time setup" >}} -To use the CLI to create a `registry.json` file, run the following commands in a -terminal and replace `myorg` with your organization's name. The file contents -are case-sensitive and you must use lowercase letters for your organization's -name. +Create the registry.json file during Docker Desktop installation: -```console -$ sudo mkdir -p "/Library/Application Support/com.docker.docker" -$ echo '{"allowedOrgs":["myorg"]}' | sudo tee "/Library/Application Support/com.docker.docker/registry.json" -``` - -This creates (or updates, if the file already exists) the `registry.json` file -at `/Library/Application Support/com.docker.docker/registry.json` and includes -the organization information the user belongs to. Make sure that the file has the -expected content, and that the user can't edit this file, but only the administrator can. +#### Windows: -Verify that the content of the file contains the correct information: +```shell +# PowerShell +Start-Process '.\Docker Desktop Installer.exe' -Wait 'install --allowed-org=myorg' -```console -$ sudo cat "/Library/Application Support/com.docker.docker/registry.json" -{"allowedOrgs":["myorg"]} +# Command Prompt +"Docker Desktop Installer.exe" install --allowed-org=myorg ``` -Verify that the file has the expected permissions (`-rw-r--r--`) and ownership -(`root` and `admin`): +#### macOS: ```console -$ sudo ls -l "/Library/Application Support/com.docker.docker/registry.json" --rw-r--r-- 1 root admin 26 Jul 27 22:01 /Library/Application Support/com.docker.docker/registry.json +sudo hdiutil attach Docker.dmg +sudo /Volumes/Docker/Docker.app/Contents/MacOS/install --allowed-org=myorg +sudo hdiutil detach /Volumes/Docker ``` -> [!IMPORTANT] -> -> As of Docker Desktop version 4.36 and later, you can add more than one organization to a single `registry.json` file. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. - {{< /tab >}} -{{< tab name="Linux" >}} - -To use the CLI to create a `registry.json` file, run the following commands in a -terminal and replace `myorg` with your organization's name. The file contents -are case-sensitive and you must use lowercase letters for your organization's -name. - -```console -$ sudo mkdir -p /usr/share/docker-desktop/registry -$ echo '{"allowedOrgs":["myorg"]}' | sudo tee /usr/share/docker-desktop/registry/registry.json -``` - -This creates (or updates, if the file already exists) the `registry.json` file -at `/usr/share/docker-desktop/registry/registry.json` and includes the -organization information to which the user belongs. Make sure the file has the -expected content and that the user can't edit this file, only the root can. - -Verify that the content of the file contains the correct information: +{{< /tabs >}} -```console -$ sudo cat /usr/share/docker-desktop/registry/registry.json -{"allowedOrgs":["myorg"]} -``` +## Method precedence -Verify that the file has the expected permissions (`-rw-r--r--`) and ownership -(`root`): +When multiple configuration methods exist on the same system, Docker Desktop uses this precedence order: -```console -$ sudo ls -l /usr/share/docker-desktop/registry/registry.json --rw-r--r-- 1 root root 26 Jul 27 22:01 /usr/share/docker-desktop/registry/registry.json -``` +1. Registry key (Windows only) +2. Configuration profiles (macOS only) +3. plist file (macOS only) +4. registry.json file > [!IMPORTANT] > -> As of Docker Desktop version 4.36 and later, you can add more than one organization to a single `registry.json` file. With Docker Desktop version 4.35 and earlier, if you add more than one organization sign-in enforcement silently fails. +> Docker Desktop version 4.36 and later supports multiple organizations in a single configuration. Earlier versions (4.35 and below) fail silently when multiple organizations are specified. -{{< /tab >}} -{{< /tabs >}} +## Troubleshoot sign-in enforcement -## More resources +If sign-in enforcement doesn't work: -- [Video: Enforce sign-in with a registry.json](https://www.youtube.com/watch?v=CIOQ6wDnJnM) +- Verify file locations and permissions +- Check that organization names use lowercase letters +- Restart Docker Desktop or reboot the system +- Confirm users are members of the specified organizations +- Update Docker Desktop to the latest version diff --git a/content/manuals/enterprise/security/hardened-desktop/_index.md b/content/manuals/enterprise/security/hardened-desktop/_index.md index 9da8d7fd5cc0..7275ce56bf58 100644 --- a/content/manuals/enterprise/security/hardened-desktop/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/_index.md @@ -1,10 +1,8 @@ --- -title: Overview of Hardened Docker Desktop +title: Hardened Docker Desktop linkTitle: Hardened Docker Desktop -description: Overview of what Hardened Docker Desktop is and its key features -keywords: security, hardened desktop, enhanced container isolation, registry access - management, settings management root access, admins, docker desktop, image access - management +description: Security features that help organizations secure developer environments without impacting productivity +keywords: security, hardened desktop, enhanced container isolation, registry access management, settings management, admins, docker desktop, image access management, air-gapped containers tags: [admin] aliases: - /desktop/hardened-desktop/ @@ -35,23 +33,31 @@ weight: 60 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Hardened Docker Desktop is a group of security features, designed to improve the security of developer environments with minimal impact on developer experience or productivity. +Hardened Docker Desktop provides a collection of security features designed to strengthen developer environments without compromising productivity or developer experience. -It lets you enforce strict security settings, preventing developers and their containers from bypassing these controls, either intentionally or unintentionally. Additionally, you can enhance container isolation, to mitigate potential security threats such as malicious payloads breaching the Docker Desktop Linux VM and the underlying host. +With Hardened Docker Desktop, you can enforce strict security policies that prevent developers and containers from bypassing organizational controls. You can also enhance container isolation to protect against security threats like malicious payloads that might breach the Docker Desktop Linux VM or underlying host system. -Hardened Docker Desktop moves the ownership boundary for Docker Desktop configuration to the organization, meaning that any security controls you set cannot be altered by the user of Docker Desktop. +## Key benefits -It is for security conscious organizations who: -- Don’t give their users root or administrator access on their machines -- Would like Docker Desktop to be within their organization’s centralized control -- Have certain compliance obligations +Hardened Docker Desktop shifts configuration ownership from individual developers to your organization. This means security controls you establish can't be modified by Docker Desktop users. -### How does it help my organization? +Hardened Docker Desktop is ideal for security-focused organizations that: -Hardened Desktop features work independently but collectively to create a defense-in-depth strategy, safeguarding developer workstations against potential attacks across various functional layers, such as configuring Docker Desktop, pulling container images, and running container images. This multi-layered defense approach ensures comprehensive security. It helps mitigate against threats such as: +- Don't provide root or administrator access to developers' machines +- Want centralized control over Docker Desktop configurations +- Must meet specific compliance requirements - - Malware and supply chain attacks: Registry Access Management and Image Access Management prevent developers from accessing certain container registries and image types, significantly lowering the risk of malicious payloads. Additionally, Enhanced Container Isolation (ECI) restricts the impact of containers with malicious payloads by running them without root privileges inside a Linux user namespace. - - Lateral movement: Air-gapped containers lets you configure network access restrictions for containers, thereby preventing malicious containers from performing lateral movement within the organization's network. - - Insider threats: Settings Management configures and locks various Docker Desktop settings so you can enforce company policies and prevent developers from introducing insecure configurations, intentionally or unintentionally. +### How Hardened Docker Desktop protects your organization + +The Hardened Docker Desktop features work independently and together to create a defense-in-depth security strategy. They protect developer workstations against attacks across multiple layers, including Docker Desktop configuration, container image management, and container runtime security: + +- Registry Access Management and Image Access Management prevent access to unauthorized container registries and image types, reducing exposure to malicious payloads +- Enhanced Container Isolation runs containers without root privileges inside a Linux user namespace, limiting the impact of malicious containers +- Air-gapped containers let you configure network restrictions for containers, preventing malicious containers from accessing your organization's internal network resources +- Settings Management locks down Docker Desktop configurations to enforce company policies and prevent developers from introducing insecure settings, whether intentionally or accidentally + +## Next steps + +Explore Hardened Docker Desktop features to understand how they can strengthen your organization's security posture: {{< grid >}} diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md index 13402bab95d6..aa4557cf8b7a 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md @@ -1,9 +1,8 @@ --- -description: Enhanced Container Isolation - benefits, why use it, how it differs to - Docker rootless, who it is for -keywords: containers, rootless, security, sysbox, runtime -title: What is Enhanced Container Isolation? +title: Enhanced Container Isolation linkTitle: Enhanced Container Isolation +description: Enhanced Container Isolation provides additional security for Docker Desktop by preventing malicious containers from compromising the host +keywords: nhanced container isolation, container security, sysbox runtime, linux user namespaces, hardened desktop aliases: - /desktop/hardened-desktop/enhanced-container-isolation/ - /security/for-admins/hardened-desktop/enhanced-container-isolation/ @@ -12,75 +11,69 @@ weight: 20 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Enhanced Container Isolation (ECI) provides an additional layer of security to prevent malicious workloads running in containers from compromising Docker Desktop or the host. +Enhanced Container Isolation (ECI) adds an extra layer of security to prevent malicious containers from compromising Docker Desktop or the host system. It uses advanced isolation techniques while maintaining full developer productivity. -It uses a variety of advanced techniques to harden container isolation, but without impacting developer productivity. - -Enhanced Container Isolation ensures stronger container isolation and also locks in any security configurations that have been created by administrators, for instance through [Registry Access Management policies](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) or with [Settings Management](../settings-management/_index.md). +ECI strengthens container isolation and locks in security configurations created by administrators, such as [Registry Access Management policies](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) and [Settings Management](../settings-management/_index.md) controls. > [!NOTE] > -> ECI is in addition to other container security techniques used by Docker. For example, reduced Linux Capabilities, seccomp, and AppArmor. - -## Who is it for? +> ECI works alongside other Docker security features like reduced Linux capabilities, seccomp, and AppArmor. -- For organizations and developers that want to prevent container attacks and reduce vulnerabilities in developer environments. -- For organizations that want to ensure stronger container isolation that is easy and intuitive to implement on developers' machines. +## Who should use Enhanced Container Isolation? -## What happens when Enhanced Container Isolation is turned on? +Enhanced Container Isolation is designed for: -When Enhanced Container Isolation is turned on, the following features and security techniques are enabled: +- Organizations that want to prevent container-based attacks and reduce security vulnerabilities in developer environments +- Security teams that need stronger container isolation without impacting developer workflows +- Enterprises that require additional protection when running untrusted or third-party container images -- All user containers are automatically run in Linux user namespaces which ensures stronger isolation. Each container runs in a dedicated Linux user-namespace. -- The root user in the container maps to an unprivileged user inside the Docker Desktop Linux VM. -- Containers become harder to breach. For example, sensitive system calls are vetted and portions of `/proc` and `/sys` are emulated inside the container. -- Users can continue using containers as usual, including bind mounting host directories, volumes, etc. -- No change in the way developers run containers, and no special container images are required. -- Privileged containers (e.g., `--privileged` flag) work, but they are only privileged within the container's Linux user namespace, not in the Docker Desktop VM. Therefore they can't be used to breach the Docker Desktop VM. -- Docker-in-Docker and even Kubernetes-in-Docker works, but run unprivileged inside the Docker Desktop Linux VM. +## How Enhanced Container Isolation works -In addition, the following restrictions are imposed: +For an overview of how ECI works, see [How Enhanced Container Isolation works](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md). -- Containers can no longer share namespaces with the Docker Desktop VM (e.g., `--network=host`, `--pid=host` are disallowed). -- Containers can no longer modify configuration files inside the Docker Desktop VM (e.g., mounting any VM directory into the container is disallowed). -- Containers can no longer access the Docker Engine. For example, mounting the Docker Engine's socket into the container is restricted which prevents malicious containers from gaining control of the Docker Engine. Administrators can relax this for [trusted container images](config.md). -- Console access to the Docker Desktop VM is forbidden for all users. +## Enable Enhanced Container Isolation -These features and restrictions ensure that containers are better secured at runtime, with minimal impact to developer experience and productivity. Developers can continue to use Docker Desktop as usual, but the containers they launch are more strongly isolated. +### For developers -For more information on how Enhanced Container Isolation work, see [How does it work](how-eci-works.md). +To turn on ECI: -> [!IMPORTANT] -> -> ECI protection for Docker builds and [Kubernetes in Docker Desktop](/manuals/desktop/features/kubernetes.md) varies according to the -> Docker Desktop version. Later versions include more protection than earlier versions. Also, ECI does not yet -> protect extension containers. For more information on known limitations and workarounds, see [FAQs](faq.md). +1. Verify your organization has a Docker Business subscription. +1. Sign in to your organization in Docker Desktop to access ECI features. +1. Stop and remove all existing containers: -## How do I enable Enhanced Container Isolation? + ```console + $ docker stop $(docker ps -q) + $ docker rm $(docker ps -aq) + ``` -### As a developer - -To enable Enhanced Container Isolation as a developer: -1. Ensure your organization has a Docker Business subscription. -2. Sign in to your organization in Docker Desktop. This will ensure the ECI feature is available to you in Docker Desktop's Settings menu. -3. Stop and remove all existing containers. -4. Navigate to **Settings** > **General** in Docker Desktop. -5. Next to **Use Enhanced Container Isolation**, select the checkbox. -6. Select **Apply and restart** to save your settings. +1. In Docker Desktop, go to **Settings** > **General**. +1. Select the **Use Enhanced Container Isolation** checkbox. +1. Select **Apply and restart**. > [!IMPORTANT] > -> Enhanced Container Isolation does not protect containers created prior to enabling ECI. For more information on known limitations and workarounds, see [FAQs](faq.md). +> ECI doesn't protect containers created before turning on the feature. Remove existing containers before turning on ECI. + +### For administrators + +Before you begin, [enforce sign-in](/manuals/enterprise/security/enforce-sign-in) so users authenticate with your organization +when signing into Docker Desktop. -### As an administrator +You can configure Enhanced Container Isolation for your organization using +Settings Management. -#### Prerequisite +{{< tabs >}} +{{< tab name="Admin Console" >}} -You first need to [enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure that all Docker Desktop developers authenticate with your organization. Since Settings Management requires a Docker Business subscription, enforced sign-in guarantees that only authenticated users have access and that the feature consistently takes effect across all users, even though it may still work without enforced sign-in. +1. Sign in to [Docker Home](https:app.docker.com) and select your organization. +1. Go to **Admin Console** > **Desktop Settings Management**. +1. [Create or edit a settings policy](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). +1. Set **Enhanced Container Isolation** to **Always enabled**. -#### Setup +{{< /tab >}} +{{< tab name="`admin-settings.json` file" >}} -[Create and configure the `admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) and specify: +Create an [`admin-settings.json`](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) file with: ```json { @@ -92,75 +85,65 @@ You first need to [enforce sign-in](/manuals/enterprise/security/enforce-sign-in } ``` -Setting `"value": true` ensures ECI is enabled by default. By -setting `"locked": true`, ECI can't be disabled by -developers. If you want to give developers the ability to disable the feature, -set `"locked": false`. +Configuration options: +- `"value": true`: Turns on ECI by default +- `"locked": true`: Prevents developers from turning off ECI +- `"locked": false`: Allows developers to control the setting -In addition, you can also [configure Docker -socket mount permissions for containers](config.md). +{{< /tab >}} +{{< /tabs >}} -For this to take effect: +#### Apply the configuration -- On a new install, developers need to launch Docker Desktop and authenticate to their organization. -- On an existing install, developers need to quit Docker Desktop through the Docker menu, and then relaunch Docker Desktop. If they are already signed in, they don’t need to sign in again for the changes to take effect. +To apply the updated Enhanced Container Isolation setting for your organization: + +- New installations: Users launch Docker Desktop and sign in +- Existing installations: Users must fully quit Docker Desktop and relaunch > [!IMPORTANT] > -> Selecting **Restart** from the Docker menu isn't enough as it only restarts some components of Docker Desktop. - -## What do users see when this setting is enforced by an administrator? +> Restarting from the Docker Desktop menu isn't sufficient. Users must completely quit and reopen Docker Desktop. -> [!TIP] -> -> You can now also configure these settings in the [Docker Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). +You can also configure Docker socket mount permissions for trusted images that need Docker API access. -When Enhanced Container Isolation is enabled, users see: -- **Use Enhanced Container Isolation** toggled on in **Settings** > **General**. -- Containers run within a Linux user namespace. +## Verify Enhanced Container Isolation is active -To check, run: +When ECI is turned on, users can verify it's working by checking the user +namespace mapping: ```console $ docker run --rm alpine cat /proc/self/uid_map ``` -The following output displays: +When ECI is turned on: ```text - 0 100000 65536 +0 100000 65536 ``` -This indicates that the container's root user (0) maps to unprivileged user -(100000) in the Docker Desktop VM, and that the mapping extends for a range of -64K user-IDs. If a container process were to escape the container, it would -find itself without privileges at the VM level. The user-ID mapping varies with -each new container, as each container gets an exclusive range of host User-IDs -for isolation. User-ID mapping is automatically managed by Docker Desktop. For -further details, see [How Enhanced Container Isolation works](how-eci-works.md). +This shows the container's root user (0) maps to an unprivileged user (100000) in the Docker Desktop VM, with a range of 64K user IDs. Each container gets an exclusive user ID range for isolation. -In contrast, without ECI the Linux user namespace is not used for containers, the following displays: +When ECI is turned off: ```text - 0 0 4294967295 +0 0 4294967295 ``` -This means that the root user in the container (0) is in fact the root user in the Docker Desktop VM (0) which reduces container isolation. +This shows the container root user (0) maps directly to the VM root user (0), providing less isolation. -Since Enhanced Container Isolation [uses the Sysbox container runtime](how-eci-works.md) embedded in the Docker Desktop Linux VM, another way to determine if a container is running with Enhanced Container Isolation is by using `docker inspect`: +You can also check the container runtime: ```console -$ docker inspect --format='{{.HostConfig.Runtime}}' my_container +$ docker inspect --format='{{.HostConfig.Runtime}}' ``` -It outputs: - -```text -sysbox-runc -``` +With ECI, it returns `sysbox-runc`. Without ECI it returns `runc`. -Without Enhanced Container Isolation, `docker inspect` outputs `runc`, which is the standard OCI runtime. +## What developers see with enforced ECI -## More resources +When administrators enforce Enhanced Container Isolation: -- [Video: Enhanced Container Isolation](https://www.youtube.com/watch?v=oA1WQZWnTAk) +- The Use Enhanced Container Isolation setting appears turned on in Docker Desktop settings +- The setting is locked and can't be changed if `"locked": true` was configured +- All new containers automatically use Linux user namespaces +- Existing development workflows continue to work without modification diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md index c640aa18640b..c2d68f87fd59 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md @@ -1,6 +1,7 @@ --- -description: The benefits of enhanced container isolation -title: Key features and benefits +title: Features and benefits of ECI +linkTitle: Features and benefits +description: Key security features and benefits of Enhanced Container Isolation for Docker Desktop keywords: set up, enhanced container isolation, rootless, security, features, Docker Desktop aliases: - /desktop/hardened-desktop/enhanced-container-isolation/features-benefits/ @@ -10,11 +11,12 @@ weight: 20 {{< summary-bar feature_name="Hardened Docker Desktop" >}} +Enhanced Container Isolation provides multiple layers of security protection that work together to prevent container breaches while maintaining full developer productivity. This page explains the key security features and their benefits. + ## Linux user namespace on all containers -With Enhanced Container Isolation, all user containers leverage the [Linux user namespace](https://man7.org/linux/man-pages/man7/user_namespaces.7.html) -for extra isolation. This means that the root user in the container maps to an unprivileged -user in the Docker Desktop Linux VM. +Enhanced Container Isolation automatically applies [Linux user namespaces](https://man7.org/linux/man-pages/man7/user_namespaces.7.html) +to every container. The root user inside containers maps to unprivileged users in the Docker Desktop Linux VM, preventing privilege escalation attacks. For example: @@ -24,13 +26,13 @@ $ docker run -it --rm --name=first alpine 0 100000 65536 ``` -The output `0 100000 65536` is the signature of the Linux user namespace. It -means that the root user (0) in the container is mapped to unprivileged user -100000 in the Docker Desktop Linux VM, and the mapping extends for a continuous -range of 64K user IDs. The same applies to group IDs. +The output `0 100000 65536` shows that: + +- Container root user (0) maps to unprivileged user 100000 in the VM +- The mapping covers a continuous range of 64K user IDs +- The same principle applies to group IDs -Each container gets an exclusive range of mappings, managed by Sysbox. For -example, if a second container is launched the mapping range is different: +Each container gets an exclusive user ID range managed automatically by Sysbox: ```console $ docker run -it --rm --name=second alpine @@ -47,36 +49,33 @@ $ docker run -it --rm alpine 0 0 4294967295 ``` -By virtue of using the Linux user namespace, Enhanced Container Isolation -ensures the container processes never run as user ID 0 (true root) in the Linux -VM. In fact they never run with any valid user-ID in the Linux VM. Thus, their -Linux capabilities are constrained to resources within the container only, -increasing isolation significantly compared to regular containers, both -container-to-host and cross-container isolation. +This shows the container root user maps directly to VM root user (0), providing much less isolation. + +## Security benefits + +Enhanced Container Isolation provides the following security benefits: + +- Container processes never run with true root privileges in the Linux VM +- Processes don't run with any valid user ID in the Linux VM +- Linux capabilities are constrained to resources within the container only +- Significantly improved container-to-host and cross-container isolation -## Privileged containers are also secured +## Secured privileged containers -Privileged containers `docker run --privileged ...` are insecure because they -give the container full access to the Linux kernel. That is, the container runs -as true root with all capabilities enabled, seccomp and AppArmor restrictions -are disabled, all hardware devices are exposed, for example. +Privileged containers (`docker run --privileged`) normally pose significant security risks because they provide unrestricted access to the Linux kernel. Without Enhanced Container Isolation, privileged containers can: -Organizations aiming to secure Docker Desktop on developers' machines face challenges with privileged containers. These containers, whether running benign or malicious workloads, can gain control of the Linux kernel within the Docker Desktop VM, potentially altering security related settings, for example registry -access management, and network proxies. +- Run as true root with all capabilities +- Bypass seccomp and AppArmor restrictions +- Access all hardware devices +- Modify global kernel settings -With Enhanced Container Isolation, privileged containers can no longer do -this. The combination of the Linux user namespace and other security techniques -used by Sysbox ensures that processes inside a privileged container can only -access resources assigned to the container. +Organizations securing developer environments face challenges with privileged containers because they can gain control of the Docker Desktop VM and alter security settings like registry access management and network proxies. + +Enhanced Container Isolation ensures privileged containers can only access resources within their container boundary. The Linux user namespace and Sysbox security techniques prevent privileged containers from breaching the Docker Desktop VM. > [!NOTE] > -> Enhanced Container Isolation does not prevent users from launching privileged -> containers, but rather runs them securely by ensuring that they can only -> modify resources associated with the container. Privileged workloads that -> modify global kernel settings, for example loading a kernel module or changing Berkeley Packet Filters (BPF) -> settings will not work properly as they will receive "permission -> denied" error when attempting such operations. +> Enhanced Container Isolation doesn't prevent users from running privileged containers, but makes them secure by containing their access to container resources only. Privileged workloads that modify global kernel settings (loading kernel modules, changing Berkeley Packet Filter settings) receive "permission denied" errors. For example, Enhanced Container Isolation ensures privileged containers can't access Docker Desktop network settings in the Linux VM configured via BPF: @@ -86,8 +85,7 @@ $ docker run --privileged djs55/bpftool map show Error: can't get next map: Operation not permitted ``` -In contrast, without Enhanced Container Isolation, privileged containers -can easily do this: +Without Enhanced Container Isolation, privileged containers can access and modify these settings: ```console $ docker run --privileged djs55/bpftool map show @@ -99,16 +97,11 @@ $ docker run --privileged djs55/bpftool map show key 8B value 8B max_entries 1024 memlock 16384B ``` -Note that some advanced container workloads require privileged containers, for -example Docker-in-Docker, Kubernetes-in-Docker, etc. With Enhanced Container -Isolation you can still run such workloads but do so much more securely than -before. +Advanced container workloads like Docker-in-Docker and Kubernetes-in-Docker still work with Enhanced Container Isolation but run much more securely than before. -## Containers can't share namespaces with the Linux VM +## Namespace isolation enforcement -When Enhanced Container Isolation is enabled, containers can't share Linux -namespaces with the host (e.g., PID, network, uts, etc.) as that essentially -breaks isolation. +Enhanced Container Isolation prevents containers from sharing Linux namespaces with the Docker Desktop VM, which would break isolation boundaries. For example, sharing the PID namespace fails: @@ -137,56 +130,45 @@ Finally, Docker build `--network=host` and Docker buildx entitlements (`network.host`, `security.insecure`) are not allowed. Builds that require these won't work properly. -## Bind mount restrictions +## Protected bind mounts -When Enhanced Container Isolation is enabled, Docker Desktop users can continue -to bind mount host directories into containers as configured via **Settings** > -**Resources** > **File sharing**, but they are no longer allowed to bind mount -arbitrary Linux VM directories into containers. +Enhanced Container Isolation maintains support for standard file sharing while preventing access to sensitive VM directories. -This prevents containers from modifying sensitive files inside the Docker -Desktop Linux VM, files that can hold configurations for registry access -management, proxies, Docker Engine configurations, and more. +### Allowed: Host directory bind mounts -For example, the following bind mount of the Docker Engine's configuration file -(`/etc/docker/daemon.json` inside the Linux VM) into a container is restricted -and therefore fails: +Users can continue bind mounting host directories configured in **Settings** > **Resources** > **File sharing**: ```console -$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine -docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown +$ docker run -it --rm -v $HOME:/mnt alpine +/ # ls /mnt +# Lists home directory contents successfully ``` -In contrast, without Enhanced Container Isolation this mount works and gives the -container full read and write access to the Docker Engine's configuration. +### Blocked: VM configuration bind mounts -Of course, bind mounts of host files continue to work as usual. For example, -assuming a user configures Docker Desktop to file share her `$HOME` directory, -she can bind mount it into the container: +Containers can't mount sensitive Docker Desktop VM directories that contain security configurations: -```console -$ docker run -it --rm -v $HOME:/mnt alpine -/ # ``` +$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine +docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown +``` + +This prevents containers from reading or modifying: + +- Docker Engine configurations +- Registry access management settings +- Proxy configurations +- Other security-related VM files > [!NOTE] > -> By default, Enhanced Container Isolation won't allow bind mounting the Docker Engine socket -> (`/var/run/docker.sock`) into a container, as doing so essentially grants the -> container control of Docker Engine, thus breaking container isolation. However, -> as some legitimate use cases require this, it's possible to relax -> this restriction for trusted container images. See [Docker socket mount permissions](config.md#docker-socket-mount-permissions). +> By default, Enhanced Container Isolation blocks bind mounting the Docker Engine socket (`/var/run/docker.sock`) as this would grant containers control over Docker Engine. Administrators can create exceptions for trusted container images. See [Docker socket mount permissions](config.md#docker-socket-mount-permissions). -## Vetting sensitive system calls +## Advanced system call filtering -Another feature of Enhanced Container Isolation is that it intercepts and vets a -few highly sensitive system calls inside containers, such as `mount` and -`umount`. This ensures that processes that have capabilities to execute these -system calls can't use them to breach the container. +Enhanced Container Isolation intercepts and inspects sensitive system calls between containers and the Linux kernel, preventing containers from using legitimate capabilities maliciously. -For example, a container that has `CAP_SYS_ADMIN` (required to execute the -`mount` system call) can't use that capability to change a read-only bind mount -into a read-write mount: +Even containers with CAP_SYS_ADMIN capability can't use mount operations to breach container boundaries: ```console $ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine @@ -194,21 +176,16 @@ $ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine mount: permission denied (are you root?) ``` -Since the `$HOME` directory was mounted into the container's `/mnt` directory as -read-only, it can't be changed from within the container to read-write, even if the container process has the capability to do so. This -ensures container processes can't use `mount`, or `umount`, to breach the container's -root filesystem. +The read-only bind mount can't be changed to read-write from within the container, even with the appropriate capability. + +### Allowed: Internal container mounts -Note however that in the previous example the container can still create mounts -within the container, and mount them read-only or read-write as needed. Those -mounts are allowed since they occur within the container, and therefore don't -breach it's root filesystem: +Containers can still create and modify mounts within their own filesystem: -```text +```console / # mkdir /root/tmpfs / # mount -t tmpfs tmpfs /root/tmpfs / # mount -o remount,ro /root/tmpfs /root/tmpfs - / # findmnt | grep tmpfs ├─/root/tmpfs tmpfs tmpfs ro,relatime,uid=100000,gid=100000 @@ -217,57 +194,42 @@ breach it's root filesystem: ├─/root/tmpfs tmpfs tmpfs rw,relatime,uid=100000,gid=100000 ``` -This feature, together with the user-namespace, ensures that even if a container -process has all Linux capabilities they can't be used to breach the container. - -Finally, Enhanced Container Isolation does system call vetting in such a way -that it does not affect the performance of containers in the great majority of -cases. It intercepts control-path system calls that are rarely used in most -container workloads but data-path system calls are not intercepted. - -## Filesystem user-ID mappings - -As mentioned, ECI enables the Linux -user namespace on all containers. This ensures that the container's user-ID -range (0->64K) maps to an unprivileged range of "real" user-IDs in the Docker -Desktop Linux VM (e.g., 100000->165535). - -Moreover, each container gets an exclusive range of real user-IDs in the Linux -VM (e.g., container 0 could get mapped to 100000->165535, container 2 to -165536->231071, container 3 to 231072->296607, and so on). The same applies to -group-IDs. In addition, if a container is stopped and restarted, there is no -guarantee it will receive the same mapping as before. This is by design and -further improves security. - -However this presents a problem when mounting Docker volumes into -containers. Files written to such volumes have the real -user/group-IDs and therefore won't be accessible across a container's -start/stop/restart, or between containers due to the different real -user-ID/group-ID of each container. - -To solve this problem, Sysbox uses "filesystem user-ID remapping" via the Linux -Kernel's ID-mapped mounts feature (added in 2021) or an alternative `shiftsfs` module. These technologies map filesystem accesses from the container's -real user-ID (e.g., range 100000->165535) to the range (0->65535) inside Docker -Desktop's Linux VM. This way, volumes can now be mounted or shared across -containers, even if each container uses an exclusive range of user-IDs. Users -need not worry about the container's real user-IDs. - -Although filesystem user-ID remapping may cause containers to access -Linux VM files mounted into the container with real user-ID 0, the -[restricted mounts feature](#bind-mount-restrictions) ensures -that sensitive Linux VM files can't be mounted into the container. - -## Procfs & sysfs emulation - -Another feature of Enhanced Container Isolation is that inside each container, -the `/proc` and `/sys` filesystems are partially emulated. This -serves several purposes, such as hiding sensitive host information inside the -container and namespacing host kernel resources that are not yet namespaced by -the Linux kernel itself. - -As a simple example, when Enhanced Container Isolation is enabled the -`/proc/uptime` file shows the uptime of the container itself, not that of the -Docker Desktop Linux VM: +### Performance optimization + +Enhanced Container Isolation performs system call filtering efficiently by: + +- Intercepting only control-path system calls (rarely used in most workloads) +- Avoiding interception of data-path system calls (frequent operations) +- Maintaining container performance in the majority of use cases + +This approach ensures that containers with all Linux capabilities still can't breach container boundaries while maintaining good performance. + +## Automatic filesystem user ID mapping + +Enhanced Container Isolation solves the challenge of sharing files between containers that use different user ID ranges through automatic filesystem mapping. + +The challenge is, each container gets exclusive user ID mappings (container 1: 100000-165535, container 2: 165536-231071). Without mapping, files created by one container would be inaccessible to others due to different user IDs. + +To solve this, Sysbox uses filesystem user ID remapping through: + +- ID-mapped mounts: Linux kernel feature (added in 2021) that maps filesystem accesses +- Alternative shiftsfs: Fallback module for older kernel versions + +### How it works + +Filesystem accesses from containers' real user IDs (e.g., 100000-165535) are mapped to the standard range (0-65535) in the Docker Desktop VM. This allows: + +- Volume sharing across containers with different user ID ranges +- Consistent file ownership regardless of container user ID mappings +- Transparent file access without user intervention + +Even though filesystem mapping allows containers to access VM files with user ID 0, the bind mount restrictions prevent containers from mounting sensitive VM directories. + +## Procfs and sysfs emulation + +Enhanced Container Isolation emulates portions of the `/proc` and `/sys` filesystems within containers to hide sensitive host information and provide per-container views of kernel resources. + +The `/proc/uptime` file shows container uptime instead of VM uptime: ```console $ docker run -it --rm alpine @@ -275,18 +237,16 @@ $ docker run -it --rm alpine 5.86 5.86 ``` -In contrast, without Enhanced Container Isolation you see the uptime of -the Docker Desktop Linux VM. Though this is a trivial example, it shows how -Enhanced Container Isolation aims to prevent the Linux VM's configuration and -information from leaking into the container so as to make it more difficult to -breach the VM. - -In addition several other resources under `/proc/sys` that are not namespaced by -the Linux Kernel are also emulated inside the container. Each container -sees a separate view of each such resource and Sysbox reconciles the values -across the containers when programming the corresponding Linux kernel setting. - -This has the advantage of enabling container workloads that would otherwise -require truly privileged containers to access such non-namespaced kernel -resources to run with Enhanced Container Isolation enabled, thereby improving -security. +Without Enhanced Container Isolation, this would show Docker Desktop VM uptime, potentially +leaking system information. + +Several `/proc/sys resources` that aren't namespaced by the Linux kernel are emulated per-container. Each container sees a separate view of these resources, and Sysbox coordinates values when programming kernel settings. + +## Performance and compatibility + +Enhanced Container Isolation is designed to provide strong security without impacting developer productivity: + +- No performance impact: System call filtering targets only control-path calls, leaving data-path operations unaffected +- Full workflow compatibility: Existing development processes, tools, and container images work unchanged +- Advanced workload support: Docker-in-Docker, Kubernetes-in-Docker, and other complex scenarios work securely +- Automatic management: User ID mappings, filesystem access, and security policies are handled automatically diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md index 8ee8ddb314df..6a3a9e14a52f 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md @@ -1,6 +1,6 @@ --- -description: How Enhanced Container Isolation works -title: How does it work? +title: How ECI works +description: Technical details of how Enhanced Container Isolation provides additional security for Docker Desktop keywords: set up, enhanced container isolation, rootless, security aliases: - /desktop/hardened-desktop/enhanced-container-isolation/how-eci-works/ @@ -10,83 +10,67 @@ weight: 10 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Docker implements Enhanced Container Isolation by using the [Sysbox -container runtime](https://github.com/nestybox/sysbox). Sysbox is a fork of the -standard OCI runc runtime that was modified to enhance standard container isolation and -workloads. For more details see [Under the hood](#under-the-hood). +Enhanced Container Isolation uses the [Sysbox +container runtime](https://github.com/nestybox/sysbox) to provide stronger container security. Sysbox is a specialized fork of the standard OCI runc runtime that enhances container isolation without impacting developer workflows. -When [Enhanced Container Isolation is enabled](index.md#how-do-i-enable-enhanced-container-isolation), containers -created by users through `docker run` or `docker create` are automatically -launched using Sysbox instead of the standard OCI runc runtime. Users need not -do anything else and can continue to use containers as usual. For exceptions, -see [FAQs](faq.md). +When [Enhanced Container Isolation is turned on](index.md#how-do-i-enable-enhanced-container-isolation), containers +created through `docker run` or `docker create` automatically +use Sysbox instead of the standard runc runtime. Users can continue working with containers normally without any changes to their workflows. -Even containers that use the insecure `--privileged` flag can now be run -securely with Enhanced Container Isolation, such that they can no longer be used -to breach the Docker Desktop Virtual Machine (VM) or other containers. +Even containers using the `--privileged` flag run securely with Enhanced Container Isolation, preventing them from breaching the Docker Desktop virtual machine or other containers. > [!NOTE] > -> When Enhanced Container Isolation is enabled in Docker Desktop, the Docker CLI -> `--runtime` flag is ignored. Docker's default runtime continues to be `runc`, -> but all user containers are implicitly launched with Sysbox. +> When Enhanced Container Isolation is turned on, the Docker CLI `--runtime` flag is ignored. Docker's default runtime remains `runc`, but all user containers implicitly launch with Sysbox. -Enhanced Container Isolation is not the same as [Docker Engine's userns-remap mode or Rootless Docker](#enhanced-container-isolation-versus-user-namespace-remapping). +## How Enhanced Container Isolation secures containers -### Under the hood +Enhanced Container Isolation applies multiple security techniques simultaneously: -Sysbox enhances container isolation by using techniques such as: +- Linux user namespaces: Root user in containers maps to unprivileged users in the Docker Desktop VM +- Sensitive directory restrictions: Containers can't mount sensitive VM directories +- System call filtering: Sensitive system calls between containers and the Linux kernel are inspected and restricted +- Filesystem user/group mapping: User and group IDs are safely mapped between container namespaces and the Linux VM +- Filesystem emulation: Portions of `/proc` and `/sys` filesystems are emulated inside containers for security +- Exclusive namespace mappings: Each container gets unique user-namespace mappings automatically +- Namespace isolation enforcement: Containers can't share namespaces with the Docker Desktop VM (`--network=host`, `--pid=host` are blocked) +- Configuration protection: Containers can't modify Docker Desktop VM configuration files +- Docker socket restrictions: Containers can't access the Docker Engine socket by default +- VM console restrictions: Direct console access to the Docker Desktop VM is blocked +- Privileged container containment: `--privileged` containers only have privileges within their own namespace +- Workflow compatibility: No changes required to existing development processes, tools, or container images +- Docker-in-Docker security: DinD and Kubernetes-in-Docker work but run unprivileged within the VM -* Enabling the Linux user-namespace on all containers (root user in the container maps to an unprivileged user in the Linux VM). -* Restricting the container from mounting sensitive VM directories. -* Vetting sensitive system-calls between the container and the Linux kernel. -* Mapping filesystem user/group IDs between the container's user-namespace and the Linux VM. -* Emulating portions of the `/proc` and `/sys` filesystems inside the container. +These techniques use recent Linux kernel advances and complement Docker's existing security mechanisms including Linux namespaces, cgroups, restricted capabilities, seccomp, and AppArmor. Together, they create strong isolation between containers and the Linux kernel inside the Docker Desktop VM. -Some of these are made possible by recent advances in the Linux kernel which -Docker Desktop now incorporates. Sysbox applies these techniques with minimal -functional or performance impact to containers. +> [!IMPORTANT] +> +> ECI protection varies by Docker Desktop version. Later versions include more comprehensive protection. ECI doesn't yet protect extension containers. -These techniques complement Docker's traditional container security mechanisms -such as using other Linux namespaces, cgroups, restricted Linux Capabilities, -Seccomp, and AppArmor. They add a strong layer of isolation between the -container and the Linux kernel inside the Docker Desktop VM. +## Enhanced Container Isolation versus user namespace remapping -For more information, see [Key features and benefits](features-benefits.md). +The Docker Engine includes [userns-remap mode](/engine/security/userns-remap/) +that turns on user namespaces in all containers. However, this feature has several +[limitations](/engine/security/userns-remap/) and isn't supported in Docker Desktop. -### Enhanced Container Isolation versus user namespace remapping +Both userns-remap mode and Enhanced Container Isolation improve container isolation using Linux user namespaces, but Enhanced Container Isolation provides significant advantages: -The Docker Engine includes a feature called [userns-remap mode](/engine/security/userns-remap/) -that enables the user namespace in all containers. However it suffers from a few -[limitations](/engine/security/userns-remap/) and it's -not supported within Docker Desktop. +- Automatic exclusive mappings: Each container gets unique user-namespace mappings without manual configuration +- Advanced isolation features: Includes system call filtering, filesystem emulation, and other security enhancements beyond basic user namespace remapping +- Docker Desktop optimization: Designed specifically for Docker Desktop's virtual machine architecture +- Enterprise security focus: Built for organizations with stringent security requirements -Userns-remap mode is similar to Enhanced Container Isolation in that both improve -container isolation by leveraging the Linux user-namespace. +### Enhanced Container Isolation versus Rootless Docker -However, Enhanced Container Isolation is much more advanced since it assigns -exclusive user-namespace mappings per container automatically and adds several -other [container isolation features](#under-the-hood) meant to secure Docker -Desktop in organizations with stringent security requirements. +[Rootless Docker](/engine/security/rootless/) allows Docker Engine and containers to run without root privileges on Linux hosts. This lets non-root users install and run Docker natively on Linux systems. -### Enhanced Container Isolation versus Rootless Docker +Rootless Docker isn't supported in Docker Desktop because Docker Desktop already provides isolation through virtualization. Docker Desktop runs Docker Engine in a Linux VM, which already allows non-root host users to run Docker safely. + +Key differences between Enhanced Container Isolation and Rootless Docker: + +- Scope: Enhanced Container Isolation secures containers within the VM, while Rootless Docker secures the entire Docker Engine on the host +- Architecture: Enhanced Container Isolation works within Docker Desktop's VM architecture, while Rootless Docker modifies the host installation +- Limitations: Enhanced Container Isolation avoids the known limitations of Rootless Docker +- Security boundary: Enhanced Container Isolation creates stronger isolation between containers and the Docker Engine, while Rootless Docker focuses on isolating the Docker Engine from the host -[Rootless Docker](/engine/security/rootless/) lets Docker Engine, and by -extension the containers, to run without root privileges natively on a Linux host. This -lets non-root users to install and run Docker natively on Linux. - -Rootless Docker is not supported within Docker Desktop. While it's a valuable -feature when running Docker natively on Linux, its value within Docker Desktop -is reduced since Docker Desktop runs the Docker Engine within a Linux VM. That -is, Docker Desktop already lets non-root host users to run Docker and -isolates the Docker Engine from the host using a virtual machine. - -Unlike Rootless Docker, Enhanced Container Isolation does not run Docker Engine -within a Linux user-namespace. Rather it runs the containers generated by that -engine within a user-namespace. This has the advantage of bypassing [the -limitations](/engine/security/rootless/#known-limitations) of Rootless Docker -and creates a stronger boundary between the containers and the Docker Engine. - -Enhanced Container Isolation is meant to ensure containers launched with Docker -Desktop can't easily breach the Docker Desktop Linux VM and therefore modify -security settings within it. +Enhanced Container Isolation ensures that containers can't breach the Docker Desktop Linux VM or modify security settings within it, providing an additional security layer specifically designed for Docker Desktop's architecture. diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md index 1dde5103df72..dfd20819db67 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md @@ -1,9 +1,8 @@ --- -description: Understand how Settings Management works, who it is for, and what the - benefits are -keywords: Settings Management, rootless, docker desktop, hardened desktop +description: Understand how Settings Management works, who it's for, and the benefits it provides +keywords: Settings Management, rootless, docker desktop, hardened desktop, admin control, enterprise tags: [admin] -title: What is Settings Management? +title: Settings Management linkTitle: Settings Management aliases: - /desktop/hardened-desktop/settings-management/ @@ -13,38 +12,51 @@ weight: 10 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Settings Management lets administrators configure and enforce Docker Desktop -settings across end-user machines. It helps maintain consistent configurations -and enhances security within your organization. +Settings Management lets administrators configure and enforce Docker Desktop settings across end-user machines. It helps maintain consistent configurations and enhances security within your organization. -## Who is it for? +## Who is Settings Management for? Settings Management is designed for organizations that: -- Require centralized control over Docker Desktop configurations. -- Aim to standardize Docker Desktop environments across teams. -- Operate in regulated environments and need to enforce compliance. +- Need centralized control over Docker Desktop configurations +- Want to standardize Docker Desktop environments across teams +- Operate in regulated environments and must enforce compliance policies This feature is available with a Docker Business subscription. -## How it works +## How Settings Management works -Administrators can define settings using one of the following methods: +Administrators can define settings using one of these methods: - [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md): Create and assign settings policies through the -Docker Admin Console. +Docker Admin Console. This provides a web-based interface for managing settings +across your organization. - [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md): Place a configuration file on the -user's machine to enforce settings. +user's machine to enforce settings. This method works well for automated +deployments and scripted installations. -Enforced settings override user-defined configurations and can't be modified -by developers. +Enforced settings override user-defined configurations and can't be modified by developers. ## Configurable settings -Settings Management supports a broad range of Docker Desktop features, -including proxies, network configurations, and container isolation. +Settings Management supports a wide range of Docker Desktop features, including: -For a full list of settings you can enforce, see the [Settings reference](/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md). +- Proxy configurations +- Network settings +- Container isolation options +- Registry access controls +- Resource limits +- Security policies + +For a complete list of settings you can enforce, see the [Settings reference](/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md). + +## Policy precedence + +When multiple policies exist, Docker Desktop applies them in this order: + +1. User-specific policies: Highest priority +1. Organization default policy: Applied when no user-specific policy exists +1. Local `admin-settings.json` file: Lowest priority, overriden by Admin Console policies ## Set up Settings Management @@ -55,32 +67,32 @@ ensure all developers authenticate with your organization. - Manually create and configure the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md). - Create a settings policy in the [Docker Admin Console](configure-admin-console.md). -After configuration, developers receive the enforced setting when they: +After configuration, developers receive the enforced settings when they: -- Quit and relaunch Docker Desktop, then sign in. -- Launch and sign in to Docker Desktop for the first time. +- Quit and relaunch Docker Desktop, then sign in +- Launch and sign in to Docker Desktop for the first time > [!NOTE] > -> Docker Desktop does not automatically prompt users to restart or re-authenticate -after a settings change. +> Docker Desktop doesn't automatically prompt users to restart or re-authenticate after a settings change. You may need to communicate these requirements to your developers. ## Developer experience When settings are enforced: -- Options appear grayed out in Docker Desktop and can't be modified via the -Dashboard, CLI, or configuration files. -- If Enhanced Container Isolation is enabled, developers can't use privileged -containers or similar methods to alter enforced settings within the Docker -Desktop Linux VM. +- Settings options appear grayed out in Docker Desktop and can't be modified through the Dashboard, CLI, or configuration files +- If Enhanced Container Isolation is enabled, developers can't use privileged containers or similar methods to alter enforced settings within the Docker Desktop Linux VM + +This ensures consistent environments while maintaining a clear visual indication of which settings are managed by administrators. + +## Next steps -## What's next? +Get started with Settings Management: - [Configure Settings Management with the `admin-settings.json` file](configure-json-file.md) - [Configure Settings Management with the Docker Admin Console](configure-admin-console.md) -## Learn more +## More resources - To see how each Docker Desktop setting maps across the Docker Dashboard, `admin-settings.json` file, and Admin Console, see the [Settings reference](settings-reference.md). - Read the [Settings Management blog post](https://www.docker.com/blog/settings-management-for-docker-desktop-now-generally-available-in-the-admin-console/). diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md index 600cca8e1c7e..976881b741a9 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md @@ -1,94 +1,66 @@ --- -description: Understand how to use the Desktop settings reporting dashboard -keywords: Settings Management, docker desktop, hardened desktop, reporting, compliance title: Desktop settings reporting linkTitle: Desktop settings reporting +description: Track and monitor user compliance with Docker Desktop settings policies using the reporting dashboard +keywords: settings management, compliance reporting, admin console, policy enforcement, docker desktop weight: 30 -params: - sidebar: - badge: - color: violet - text: EA aliases: - /security/for-admins/hardened-desktop/settings-management/compliance-reporting/ --- {{< summary-bar feature_name="Compliance reporting" >}} -Desktop settings reporting is a feature of Desktop Settings Management that -tracks and reports user compliance with the settings policies that are assigned -to them. This lets administrators track the application of settings and -monitor what actions they need to take to make users compliant. +Desktop settings reporting tracks user compliance with Docker Desktop settings policies. Use this feature to monitor policy application across your organization and identify users who need assistance with compliance. -This guide provides steps for accessing Desktop settings reporting, viewing -compliance status, and resolving non-compliant users. +## Prerequisites -## Access Desktop settings reporting +Before you can use Docker Desktop settings reporting, make sure you have: -> [!IMPORTANT] -> -> Desktop settings reporting is in Early Access and is being rolled out -> gradually. You may not see this setting in the Admin Console yet. - -1. Sign in to [Docker Home](https://app.docker.com) and select -your organization. -1. Select **Admin Console**, then **Desktop settings reporting**. - -This opens the Desktop settings reporting page. From here you can: - -- Use the **Search** field to search by username or email address -- Filter by policies -- Hide or un-hide compliant users -- View a user’s compliance status and what policy is assigned to the user -- Download a CSV file of user compliance information - -## View compliance status +- Docker Desktop 4.37.1 or later installed across your organization +- A verified domain +- Enforced sign-in for your organization +- A Docker Business subscription +- At least one settings policy configured > [!WARNING] > -> Users on Docker Desktop versions older than 4.40 may appear non-compliant -> because older versions can't report compliance. To ensure accurate -> compliance status, users must update to Docker Desktop version 4.40 and later. +> Users on Docker Desktop versions older than 4.40 may appear non-compliant because older versions can't report compliance status. For accurate reporting, update users to Docker Desktop version 4.40 or later. + +## Access the reporting dashboard + +To view compliance reporting: 1. Sign in to [Docker Home](https://app.docker.com) and select your organization. 1. Select **Admin Console**, then **Desktop settings reporting**. -1. Optional. Select the **Hide compliant users** checkbox to show both compliant -and non-compliant users. -1. Use the **Search** field to search by username or email address. -1. Hover over a user’s compliance status indicator to quickly view their status. -1. Select a username to view more details about their compliance status, and for -steps to resolve non-compliant users. - -## Understand compliance status -Docker evaluates compliance status based on: +The reporting dashboard provides these tools: -- Compliance status: Whether a user has fetched and applied the latest settings. This is the primary label shown on the reporting page. -- Domain status: Whether the user's email matches a verified domain. -- Settings status: Whether a settings policy is applied to the user. +- A search field to find users by username or email address +- Filter options to show users assigned to specific policies +- Toggles to hide or un-hide compliant users +- Compliance status indicators +- CSV export option to download compliance data -The combination of these statuses determines what actions you need to take. +## Understanding compliance status -### Compliance status reference +Docker Desktop evaluates three types of status to determine overall compliance: -This reference explains how each status is determined in the reporting dashboard -based on user domain and settings data. The Admin Console displays the -highest-priority applicable status according to the following rules. +### Compliance status -**Compliance status** +This is the primary status shown in the dashboard: | Compliance status | What it means | |-------------------|---------------| -| Uncontrolled domain | The user's email domain is not verified. | -| No policy assigned | The user does not have any policy assigned to them. | +| Compliant | The user fetched and applied the latest assigned policy. | | Non-compliant | The user fetched the correct policy, but hasn't applied it. | | Outdated | The user fetched a previous version of the policy. | -| Compliant | The user fetched and applied the latest assigned policy. | +| No policy assigned | The user does not have any policy assigned to them. | +| Uncontrolled domain | The user's email domain is not verified. | -**Domain status** +### Domain status -This reflects how the user’s email domain is evaluated based on the organization’s domain setup. +Shows how the user's email domain relates to your organization: | Domain status | What it means | |---------------|---------------| @@ -96,9 +68,9 @@ This reflects how the user’s email domain is evaluated based on the organizati | Guest user | The user's email domain is not verified. | | Domainless | Your organization has no verified domains, and the user's domain is unknown. | -**Settings status** +### Settings status -This shows whether and how the user is assigned a settings policy. +Indicates the user's policy assignment: | Settings status | What it means | |-----------------|---------------| @@ -106,41 +78,48 @@ This shows whether and how the user is assigned a settings policy. | User policy | The user is assigned a specific custom policy. | | No policy assigned | The user is not assigned to any policy. | -## Resolve compliance status +## Monitor compliance + +From the **Desktop settings reporting** dashboard, you can: + +- Review organization-wide compliance at a glance +- Turn on **Hide compliant users** to focus on issues +- Filter by specific policies to check targeted compliance +- Export compliance data +- Select any user's name for detailed status and resolution steps + +When you select a user's name, you'll see their detailed compliance information including current status, domain verification, assigned policy, last policy fetch time, and Docker Desktop version. + +## Resolve compliance issues + +Follow these steps based on the user's compliance status: + +### Non-compliant or outdated users + +- Ask the user to fully quit and relaunch Docker Desktop +- Verify the user is signed in to Docker Desktop +- Confirm the user has Docker Desktop 4.40 or later -To resolve compliance status, you must view a user's compliance status details -by selecting their username from the Desktop settings reporting page. -These details include the following information: +### Uncontrolled domain users -- **Compliance status**: Indicates whether the user is compliant with the -settings applied to them -- **Domain status**: Indicates whether the user’s email address is associated -with a verified domain -- **Settings status**: Indicates whether the user has settings applied to them -- **Resolution steps**: If a user is non-compliant, this provides information -on how to resolve the user’s compliance status +- Verify the user's email domain in your organization settings +- If the domain should be controlled, add and verify it, then wait for verification +- If the user is a guest and shouldn't be controlled, no action is needed -### Compliant +### No policy assigned users -When a user is compliant, a **Compliant** icon appears next to their name on the -Desktop settings reporting dashboard. Select a compliant user to open their -compliance status details. Compliant users have the following status details: +- Assign the user to an existing policy +- Create a new user-specific policy for them +- Verify they're included in your organization's default policy scope -- **Compliance status**: Compliant -- **Domain status**: Verified -- **Settings status**: Global policy or user policy -- **User is compliant** indicator +After users take corrective action, refresh the reporting dashboard to verify status changes. -No resolution steps are needed for compliant users. +## Policy update timing -### Non-compliant +Docker Desktop checks for policy updates: -When a user is non-compliant, a **Non-compliant** or **Unknown** icon appears -next to their name on the Desktop settings reporting dashboard. Non-compliant -users must have their compliance status resolved: +- At startup +- Every 60 minutes while Docker Desktop is running +- When users restart Docker Desktop -1. Select a username from the Desktop settings reporting dashboard. -1. On the compliance status details page, follow the resolution steps provided -to resolve the compliance status. -1. Refresh the page to ensure the resolution steps resolved the compliance -status. +Changes to policies in the Admin Console are available immediately, but users must restart Docker Desktop to apply them. diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md index 4846e6034b96..1db063a6d907 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md @@ -1,8 +1,8 @@ --- -description: How to configure Settings Management for Docker Desktop using the Docker Admin Console -keywords: admin, controls, rootless, enhanced container isolation title: Configure Settings Management with the Admin Console linkTitle: Use the Admin Console +description: Configure and enforce Docker Desktop settings across your organization using the Docker Admin Console +keywords: admin console, settings management, policy configuration, enterprise controls, docker desktop weight: 20 aliases: - /security/for-admins/hardened-desktop/settings-management/configure-admin-console/ @@ -10,17 +10,16 @@ aliases: {{< summary-bar feature_name="Admin Console" >}} -This page explains how administrators can use the Docker Admin Console to create -and apply settings policies for Docker Desktop. These policies help standardize -and secure Docker Desktop environments across your organization. +Use the Docker Admin Console to create and manage settings policies for Docker Desktop across your organization. Settings policies let you standardize configurations, enforce security requirements, and maintain consistent Docker Desktop environments. ## Prerequisites -- [Install Docker Desktop 4.37.1 or later](/manuals/desktop/release-notes.md). -- [Verify your domain](/manuals/enterprise/security/single-sign-on/configure.md#step-one-add-and-verify-your-domain). -- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to -ensure users authenticate to your organization. -- A Docker Business subscription is required. +Before you begin, make sure you have: + +- [Docker Desktop 4.37.1 or later](/manuals/desktop/release-notes.md) installed +- [A verified domain](/manuals/enterprise/security/single-sign-on/configure.md#step-one-add-and-verify-your-domain) +- [Enforced sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) for your organization +- A Docker Business subscription > [!IMPORTANT] > @@ -28,6 +27,8 @@ ensure users authenticate to your organization. ## Create a settings policy +To create a new settings policy: + 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. 1. Select **Admin Console**, then **Desktop Settings Management**. @@ -45,10 +46,9 @@ your organization. > [!NOTE] > - > User-specific policies override the global default. Test your policy with - a few users before rolling it out globally. + > User-specific policies override global default policies. Test your policy with a small group before applying it organization-wide. -1. Configure the state for each setting: +1. Configure each setting using a state: - **User-defined**: Users can change the setting. - **Always enabled**: Setting is on and locked. - **Enabled**: Setting is on but can be changed. @@ -57,31 +57,43 @@ your organization. > [!TIP] > - > For a complete list of available settings, their supported platforms, and which configuration methods they work with, see the [Settings reference](settings-reference.md). + > For a complete list of configurable settings, supported platforms, and configuration methods, see the [Settings reference](settings-reference.md). + +1. Select **Create** to save your policy. + +## Apply the policy -1. Select **Create**. +Settings policies take effect after Docker Desktop restarts and users sign in. -To apply the policy: +For new installations: -- New installs: Launch Docker Desktop and sign in. -- Existing installs: Fully quit and relaunch Docker Desktop. +1. Launch Docker Desktop. +1. Sign in with your Docker account. + +For existing installations: + +1. Quit Docker Desktop completely. +1. Relaunch Docker Desktop. > [!IMPORTANT] > -> Restarting from the Docker Desktop menu isn't enough. Users must fully quit -and relaunch Docker Desktop. +> Users must fully quit and reopen Docker Desktop. Restarting from the Docker Desktop menu isn't sufficient. -Docker Desktop checks for policy updates at launch and every 60 minutes. To roll -back a policy, either delete it or set individual settings to **User-defined**. +Docker Desktop checks for policy updates when it launches and every 60 minutes while running. -## Manage policies +## Manage existing policies -From the **Actions** menu on the **Settings Management** page, you can: +From the **Desktop Settings Management** page in the Admin Console, use the **Actions** menu to: - Edit or delete an existing settings policy - Export a settings policy as an `admin-settings.json` file - Promote a user-specific policy to be the new global default -## Learn more +## Roll back policies + +To roll back a settings policy: + +- Complete rollback: Delete the entire policy. +- Partial rollback: Set specific settings to **User-defined**. -To see how each Docker Desktop setting maps across the Docker Dashboard, `admin-settings.json` file, and Admin Console, see the [Settings reference](settings-reference.md). \ No newline at end of file +When you roll back settings, users regain control over those settings configurations. diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md index 2bb9ea66fe30..8a7f5cdf6551 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md @@ -1,8 +1,8 @@ --- -description: How to configure Settings Management for Docker Desktop -keywords: admin, controls, rootless, enhanced container isolation title: Configure Settings Management with a JSON file linkTitle: Use a JSON file +description: Configure and enforce Docker Desktop settings using an admin-settings.json file +keywords: admin controls, settings management, configuration, enterprise, docker desktop, json file weight: 10 aliases: - /desktop/hardened-desktop/settings-management/configure/ @@ -12,75 +12,66 @@ aliases: {{< summary-bar feature_name="Hardened Docker Desktop" >}} -This page explains how to use an `admin-settings.json` file to configure and -enforce Docker Desktop settings. Use this method to standardize Docker -Desktop environments in your organization. +Settings Management lets you configure and enforce Docker Desktop settings across your organization using an `admin-settings.json` file. This standardizes Docker Desktop environments and ensures consistent configurations for all users. ## Prerequisites -- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to -ensure all users authenticate with your organization. -- A Docker Business subscription is required. +Before you begin, make sure you have: -Docker Desktop only applies settings from the `admin-settings.json` file if both -authentication and Docker Business license checks succeed. +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) for +your organization +- A Docker Business subscription + +Docker Desktop only applies settings from the `admin-settings.json` file when both authentication and Docker Business license checks succeed. > [!IMPORTANT] > -> If a user isn't signed in or isn't part of a Docker Business organization, -the settings file is ignored. +> Users must be signed in and part of a Docker Business organization. If either condition isn't met, the settings file is ignored. ## Limitation -- The `admin-settings.json` file doesn't work in air-gapped or offline -environments. -- The file is not compatible with environments that restrict authentication -with Docker Hub. +Settings Management has the following limitations: + +- Doesn't work in air-gapped or offline environments +- Not compatible with environments that restrict authentication with Docker Hub ## Step one: Create the settings file -You can: +You can create the `admin-settings.json` file in two ways: -- Use the `--admin-settings` installer flag to auto-generate the file. See: - - [macOS](/manuals/desktop/setup/install/mac-install.md#install-from-the-command-line) install guide - - [Windows](/manuals/desktop/setup/install/windows-install.md#install-from-the-command-line) install guide -- Or create it manually and place it in the following locations: +- Use the `--admin-settings` installer flag to auto-generate the file: + - [macOS](/manuals/desktop/setup/install/mac-install.md#install-from-the-command-line) installation guide + - [Windows](/manuals/desktop/setup/install/windows-install.md#install-from-the-command-line) installation guide +- Create it manually and place it in the following locations: - Mac: `/Library/Application\ Support/com.docker.docker/admin-settings.json` - Windows: `C:\ProgramData\DockerDesktop\admin-settings.json` - Linux: `/usr/share/docker-desktop/admin-settings.json` > [!IMPORTANT] > -> Place the file in a protected directory to prevent modification. Use MDM tools -like [Jamf](https://www.jamf.com/lp/en-gb/apple-mobile-device-management-mdm-jamf-shared/?attr=google_ads-brand-search-shared&gclid=CjwKCAjw1ICZBhAzEiwAFfvFhEXjayUAi8FHHv1JJitFPb47C_q_RCySTmF86twF1qJc_6GST-YDmhoCuJsQAvD_BwE) to distribute it at scale. +> Place the file in a protected directory to prevent unauthorized changes. Use Mobile Device Management (MDM) tools like Jamf to distribute the file at scale across your organization. -## Step two: Define settings +## Step two: Configure settings > [!TIP] > > For a complete list of available settings, their supported platforms, and which configuration methods they work with, see the [Settings reference](settings-reference.md). -The `admin-settings.json` file uses structured keys to define what can -be configured and whether the values are enforced. +The `admin-settings.json` file uses structured keys to define configurable settings and whether values are enforced. -Each setting supports the `locked` field. When `locked` is set to `true`, users -can't change that value in Docker Desktop, the CLI, or config files. When -`locked` is set to `false`, the value acts like a default suggestion and users +Each setting supports a `locked` field that controls user permissions: + +- When `locked` is set to `true`, users can't change that value in Docker Desktop, the CLI, or config files. +- When `locked` is set to `false`, the value acts like a default suggestion and users can still update it. Settings where `locked` is set to `false` are ignored on existing installs if a user has already customized that value in `settings-store.json`, `settings.json`, or `daemon.json`. -> [!NOTE] -> -> Some settings are platform-specific or require a minimum Docker Desktop -version. See the [Settings reference](/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md) for details. - -### Example settings file +### Example configuration -The following file is an example `admin-settings.json` file. For a full list -of configurable settings for the `admin-settings.json` file, see [`admin-settings.json` configurations](#admin-settingsjson-configurations). +The folloiwng sample is an `admin-settings.json` file with common enterprise settings configured: ```json {collapse=true} { @@ -207,21 +198,33 @@ of configurable settings for the `admin-settings.json` file, see [`admin-setting } ``` -## Step three: Restart and apply settings +## Step three: Apply the settings + +Settings take effect after Docker Desktop restarts and the user signs in. -Settings apply after Docker Desktop is restarted and the user is signed in. +For new installations: -- New installs: Launch Docker Desktop and sign in. -- Existing installs: Quit Docker Desktop fully and relaunch it. +1. Launch Docker Desktop. +1. Sign in with your Docker account. + +For existing installations: + +1. Quit Docker Desktop completely. +1. Relaunch Docker Desktop. > [!IMPORTANT] > -> Restarting Docker Desktop from the menu isn't enough. It must be fully -quit and reopened. +> You must fully quit and reopen Docker Desktop. Restarting from the menu isn't sufficient. ## `admin-settings.json` configurations -### General +The following tables describe all available settings in the `admin-settings.json` file. + +> [!NOTE] +> +> Some settings are platform-specific or require minimum Docker Desktop versions. Check the Version column for requirements. + +### General settings |Parameter|OS|Description|Version| |:-------------------------------|---|:-------------------------------|---| @@ -249,7 +252,7 @@ quit and reopened. |:-------------------------------|---|:-------------------------------|---| |`scout`| | Setting `useBackgroundIndexing` to `false` disables automatic indexing of images loaded to the image store. Setting `sbomIndexing` to `false` prevents users from being able to index image by inspecting them in Docker Desktop or using `docker scout` CLI commands. | | -### Proxy +### Proxy settings |Parameter|OS|Description|Version| |:-------------------------------|---|:-------------------------------|---| @@ -263,7 +266,7 @@ quit and reopened. |:-------------------------------|---|:-------------------------------|---| |`containersProxy` | | Creates air-gapped containers. For more information see [Air-Gapped Containers](../air-gapped-containers.md).| Docker Desktop version 4.29 and later. | -### Linux VM +### Linux VM settings |Parameter|OS|Description|Version| |:-------------------------------|---|:-------------------------------|---| @@ -283,7 +286,7 @@ quit and reopened. > > This setting is not available to configure via the Docker Admin Console. -### Kubernetes +### Kubernetes settings |Parameter|OS|Description|Version| |:-------------------------------|---|:-------------------------------|---| @@ -291,14 +294,14 @@ quit and reopened. > [!NOTE] > -> When using the `imagesRepository` setting and Enhanced Container Isolation (ECI), add the following images to the [ECI Docker socket mount image list](#enhanced-container-isolation): +> When using `imagesRepository` with Enhanced Container Isolation (ECI), add these images to the [ECI Docker socket mount image list](#enhanced-container-isolation): > > * [imagesRepository]/desktop-cloud-provider-kind:* > * [imagesRepository]/desktop-containerd-registry-mirror:* > -> These containers mount the Docker socket, so you must add the images to the ECI images list. If not, ECI will block the mount and Kubernetes won't start. +> These containers mount the Docker socket, so you must add them to the ECI images list. Otherwise, ECI blocks the mount and Kubernetes won't start. -### Networking +### Networking settings |Parameter|OS|Description|Version| |:-------------------------------|---|:-------------------------------|---| diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md index ac89fd75a3fe..649005360641 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md @@ -1,26 +1,32 @@ --- -description: Reference for all settings and features that are configured with Settings Management -keywords: admin, controls, settings management, reference title: Settings reference linkTitle: Settings reference -aliases: +description: Complete reference for all Docker Desktop settings and configuration options +keywords: docker desktop settings, configuration reference, admin controls, settings management +aliases: - /security/for-admins/hardened-desktop/settings-management/settings-reference/ --- -This reference lists all Docker Desktop settings, including where they are configured, which operating systems they apply to, and whether they're available in the Docker Desktop GUI, the Docker Admin Console, or the `admin-settings.json` file. Settings are grouped to match the structure of the Docker Desktop interface. +This reference documents all Docker Desktop settings and configuration options. Use this to understand setting behavior across different configuration methods and platforms. Each setting includes: -- The display name used in Docker Desktop -- A table of values, default values, and required format -- A description and use cases -- OS compatibility -- Configuration methods: via [Docker Desktop](/manuals/desktop/settings-and-maintenance/settings.md), the Admin Console, or the `admin-settings.json` file +- Default and accepted values +- Platform compatibility +- Configuration methods (Docker Desktop GUI, Admin Console, admin-settings.json file, or CLI) +- Enterprise security recommendations where applicable -Use this reference to compare how settings behave across different configuration -methods and platforms. +## How to use this reference -## General +Settings are organized to match the Docker Desktop GUI structure. Configuration +methods are indicated with these labels: + +- Desktop GUI: Configurable through Docker Desktop settings interface +- Admin Console: Configurable through the Docker Admin Console using Settings Management +- JSON file: Configurable htrough `admin-settings.json` using Settings Managemet +- CLI: Configurable through command-line tools + +## General settings ### Start Docker Desktop when you sign in to your computer @@ -28,9 +34,9 @@ methods and platforms. |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Start Docker Desktop automatically when booting machine. +- **Description:** Automatic startup of Docker Desktop when the user logs in to their computer. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Ensure Docker Desktop is always running after boot. +- **Use case:** Ensure Docker Desktop is always available after system boot. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -40,9 +46,9 @@ methods and platforms. |---------------|----------------------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Open the Docker Dashboard automatically when Docker Desktop starts. +- **Description:** Whether the Docker Dashboard opens automatically when Docker Desktop launches. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Quickly access containers, images, and volumes in the Docker Dashboard after starting Docker Desktop. +- **Use case:** Provide immediate access to containers, images, and volumes after startup. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -52,9 +58,9 @@ methods and platforms. |---------------|----------------------------|--------| | `system` | `light`, `dark`, `system` | Enum | -- **Description:** Choose the Docker Desktop GUI theme. +- **Description:** Visual appearance of the Docker Desktop interface. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Personalize Docker Desktop appearance. +- **Use case:** Customize interface appearance to match user preferences or system theme. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -64,9 +70,9 @@ methods and platforms. |---------------|-------------------------|--------| | `integrated` | `integrated`, `system` | String | -- **Description:** If installed, automatically edits your shell configuration. +- **Description:** How Docker CLI auto-completion integrates with the user's shell. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Customize developer experience with shell completions. +- **Use case:** Control whether Docker modifies shell configuration files for auto-completion. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -76,10 +82,9 @@ methods and platforms. |---------------|-------------------------|--------| | `integrated` | `integrated`, `system` | String | -- **Description:** Select default terminal for launching Docker CLI from Docker -Desktop. +- **Description:** Default terminal used when launching Docker CLI from Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Customize developer experience with preferred terminal. +- **Use case:** Set preferred terminal application for Docker CLI interactions. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -89,24 +94,28 @@ Desktop. |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable access to the Docker Desktop integrated terminal. If +- **Description:** Access to Docker Desktop's integrated terminal feature. If the value is set to `false`, users can't use the Docker terminal to interact with the host machine and execute commands directly from Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Allow or restrict developer access to the built-in terminal. +- **Use case:** Allow or restrict developer access to the built-in terminal for host system interaction. - **Configure this setting with:** - **General** setting in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `desktopTerminalEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) +> [!NOTE] +> +> In hardened environments, disable and lock this setting to limit host access. + ### Enable Docker Debug by default | Default value | Accepted values | Format | |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable debug logging by default for Docker CLI commands. +- **Description:** Whether debug logging is turned on by default for Docker CLI commands. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Assist with debugging support issues. +- **Use case:** Provide verbose output for troubleshooting and support scenarios. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -116,9 +125,9 @@ with the host machine and execute commands directly from Docker Desktop. |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Back up the Docker Desktop virtual machine. +- **Description:** Whether the Docker Desktop virtual machine is included in macOS Time Machine backups. - **OS:** {{< badge color=blue text="Mac only" >}} -- **Use case:** Manage persistence of application data. +- **Use case:** Balance backup completeness with backup size and performance. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -128,10 +137,9 @@ with the host machine and execute commands directly from Docker Desktop. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Use containerd native snapshotter instead of legacy -snapshotters. +- **Description:** Image storage backend used by Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Improve image handling performance and compatibility. +- **Use case:** Improve image handling performance and enable containerd-native features. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -166,17 +174,16 @@ is set to `true`, Docker Desktop turns on Rosetta to accelerate x86_64/amd64 binary emulation on Apple Silicon. - **OS:** {{< badge color=blue text="Mac only" >}} 13+ - **Use case:** Run Intel-based containers on Apple Silicon hosts. +- **Configure this setting with:** + - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - Settings Management:`useVirtualizationFrameworkRosetta` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Use Rosetta for x86_64/amd64 emulation on Apple Silicon** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > > In hardened environments, disable and lock this setting so only ARM-native images are permitted. -- **Configure this setting with:** - - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - - Settings Management:`useVirtualizationFrameworkRosetta` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Use Rosetta for x86_64/amd64 emulation on Apple Silicon** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - > [!NOTE] > > Rosetta requires enabling Apple Virtualization framework. @@ -200,18 +207,17 @@ containers. If value is set to `true`, VirtioFS is set as the file sharing mechanism. If both VirtioFS and gRPC are set to `true`, VirtioFS takes precedence. - **OS:** {{< badge color=blue text="Mac only" >}} 12.5+ -- **Use case:** Improve volume mount performance and compatibility. +- **Use case:** Achieve better file system performance and compatibility on modern macOS. +- **Configure this setting with:** + - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - Settings Management: `useVirtualizationFrameworkVirtioFS` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Use VirtioFS for file sharing** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > > In hardened environments, enable and lock this setting for macOS 12.5 and later. -- **Configure this setting with:** - - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - - Settings Management: `useVirtualizationFrameworkVirtioFS` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Use VirtioFS for file sharing** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - #### gRPC FUSE | Default value | Accepted values | Format | @@ -221,29 +227,27 @@ later. - **Description:** Enable gRPC FUSE for macOS file sharing. If value is set to `true`, gRPC Fuse is set as the file sharing mechanism. - **OS:** {{< badge color=blue text="Mac only" >}} -- **Use case:** Improve performance and compatibility of file mounts. - -> [!NOTE] -> -> In hardened environments, disable and lock this setting. - +- **Use case:** Alternative file sharing with improved performance over legacy osxfs. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `useGrpcfuse` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **Use gRPC FUSE for file sharing** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) +> [!NOTE] +> +> In hardened environments, disable and lock this setting. + #### osxfs | Default value | Accepted values | Format | | ------------- | --------------- | ------- | | `false` | `true`, `false` | Boolean | -- **Description:** Enable the legacy osxfs file sharing driver for macOS. When +- **Description:** Use the original osxfs file sharing driver for macOS. When set to true, Docker Desktop uses osxfs instead of VirtioFS or gRPC FUSE to mount host directories into containers. - **OS:** {{< badge color=blue text="Mac only" >}} -- **Use case:** Use the original file sharing implementation when compatibility -with older tooling or specific workflows is required. +- **Use case:** Compatibility with legacy tooling that requires the original file sharing implementation. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -259,8 +263,11 @@ gathered from the Docker Desktop application itself. It does not affect server-side telemetry collected via Docker Hub or other backend services, such as login timestamps, pulls, or builds. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable analytics to help Docker improve the product based on -usage data. +- **Use case:** Help Docker improve the product based on usage patterns. +- **Configure this setting with:** + - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - Settings Management: `analyticsEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Send usage statistics** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > @@ -268,11 +275,6 @@ usage data. to control all your data flows and collect support logs via secure channels if needed. -- **Configure this setting with:** - - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - - Settings Management: `analyticsEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Send usage statistics** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - > [!NOTE] > > Organizations using the Insights Dashboard may need this setting enabled to @@ -286,30 +288,29 @@ views. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable Enhanced Container Isolation for secure container -execution. +- **Description:** Advanced container security through Linux user namespaces and additional isolation. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Prevent containers from modifying configuration or sensitive -host areas. - -> [!NOTE] -> -> In hardened environments, disable and lock this setting. - +- **Use case:** Prevent containers from modifying Docker Desktop VM configuration or accessing sensitive host areas. - **Configure this setting with:** - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enhancedContainerIsolation` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **Enable enhanced container isolation** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) +> [!NOTE] +> +> In hardened environments, disable and lock this setting. This allows you +to control all your data flows and collect support logs via secure channels +if needed. + ### Show CLI hints | Default value | Accepted values | Format | |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Display helpful CLI tips in the terminal when using Docker commands. +- **Description:** Display of helpful CLI suggestions in the terminal when using Docker commands. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Help users discover and learn Docker CLI features through inline suggestions. +- **Use case:** Help users discover Docker CLI features through contextual tips. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -319,36 +320,33 @@ host areas. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Enable Docker Scout to generate and display SBOM data for container images. +- **Description:** Docker Scout SBOM generation and vulnerability scanning for container images. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Turn on Docker Scout analysis features to view vulnerabilities, packages, and metadata associated with images. - -> [!NOTE] -> -> In hardened environments, enable and lock this setting to ensure SBOMs are -always built to satisfy compliance scans. - +- **Use case:** Turn on vulnerability scanning and software bill of materials analysis. - **Configure this setting with:** - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `sbomIndexing` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **SBOM indexing** settings in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) +> [!NOTE] +> +> In hardened environments, enable and lock this setting to ensure compliance scanning is always available. + ### Enable background Scout SBOM indexing | Default value | Accepted values | Format | |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Automatically index SBOM data for images in the background without requiring user interaction. +- **Description:** Automatic SBOM indexing for images without requiring user interaction. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Keep image metadata up to date by allowing Docker to perform SBOM indexing during idle time or after image pull operations. +- **Use case:** KKeep image metadata current by indexing during idle time or after image operations. +- **Configure this setting with:** + - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) > [!NOTE] > -> In hardened environments, enable and lock this setting. - -- **Configure this setting with:** - - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) +> In hardened environments, enable and lock this setting for continuous security analysis. ### Automatically check configuration @@ -356,14 +354,14 @@ always built to satisfy compliance scans. |-----------------------|-----------------|---------| | `CurrentSettingsVersions` | Integer | Integer | -- **Description:** Regularly checks your configuration to ensure no unexpected changes have been made by another application +- **Description:** Regular verification that Docker Desktop configuration hasn't been modified by external applications. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Track versions for compatibility +- **Use case:** Track configuration versions for compatibility and change detection. - **Configure this setting with:** - **General** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `configurationFileVersion` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) -## Resources +## Resources settings ### CPU limit @@ -371,9 +369,9 @@ always built to satisfy compliance scans. |-----------------------------------------------|-----------------|---------| | Number of logical CPU cores available on host | Integer | Integer | -- **Description:** Number of CPUs assigned to the Docker Desktop virtual machine. +- **Description:** Number of CPU cores allocated to the Docker Desktop virtual machine. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Resource allocation control. +- **Use case:** Balance Docker performance with host system resource availability. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -383,9 +381,9 @@ always built to satisfy compliance scans. |---------------------------|-----------------|---------| | Based on system resources | Integer | Integer | -- **Description:** Amount of RAM (in MiB) assigned to the Docker virtual machine. +- **Description:** Amount of RAM (in MiB) allocated to the Docker Desktop virtual machine. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Control how much memory Docker can use on the host. +- **Use case:** Control memory allocation to optimize performance for both Docker and host applications. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -395,9 +393,9 @@ always built to satisfy compliance scans. |---------------|-----------------|---------| | `1024` | Integer | Integer | -- **Description:** Amount of swap space (in MiB) assigned to the Docker virtual machine +- **Description:** Amount of swap space (in MiB) available to the Docker virtual machine. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Extend memory availability via swap +- **Use case:** Extend available memory for container workloads when physical RAM is limited. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -407,9 +405,9 @@ always built to satisfy compliance scans. |-------------------------------|-----------------|---------| | Default disk size of machine. | Integer | Integer | -- **Description:** Maximum disk size (in MiB) allocated for Docker Desktop. +- **Description:** Maximum disk space (in MiB) allocated for Docker Desktop data. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Constrain Docker's virtual disk size for storage management. +- **Use case:** Prevent Docker from consuming excessive disk space on the host system. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -419,9 +417,9 @@ always built to satisfy compliance scans. |--------------------------------------------------|-----------------|--------| | macOS: `~/Library/Containers/com.docker.docker/Data/vms/0`
Windows: `%USERPROFILE%\AppData\Local\Docker\wsl\data` | File path | String | -- **Description:** Path where Docker Desktop stores virtual machine data. +- **Description:** File system path where Docker Desktop stores virtual machine data. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Redirect Docker data to a custom location. +- **Use case:** Move Docker data to custom storage locations for performance or space management. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -431,9 +429,9 @@ always built to satisfy compliance scans. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Enable Docker Desktop to pause when idle. +- **Description:** Automatic pausing of Docker Desktop when idle to conserve system resources. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Save system resources during periods of inactivity. +- **Use case:** Reduce CPU and memory usage when Docker Desktop isn't actively being used. - **Configure this setting with:** - **Advanced** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -443,40 +441,36 @@ always built to satisfy compliance scans. |----------------------------------------|---------------------------------|--------------------------| | Varies by OS | List of file paths as strings | Array list of strings | -- **Description:** List of allowed directories shared between the host and -containers. When a path is added, its subdirectories are allowed. +- **Description:** Host directories that can be mounted into containers as volumes. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Restrict or define what file paths are available to containers. - -> [!NOTE] -> -> In hardened environments, lock to an explicit whitelist and disable end-user -edits. - +- **Use case:** Define which host directories containers can access for development workflows. - **Configure this setting with:** - **File sharing** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `filesharingAllowedDirectories` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **Allowed file sharing directories** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) +> [!NOTE] +> +> In hardened environments, lock to an explicit allowlist and disable end-user +edits. + ### Proxy exclude | Default value | Accepted values | Format | |---------------|--------------------|--------| | `""` | List of addresses | String | -- **Description:** Configure addresses that containers should bypass from proxy -settings. +- **Description:** Network addresses that containers should bypass when using proxy settings. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Fine-tune proxy exceptions for container networking. - -> [!NOTE] -> -> In hardened environments, disable and lock this setting. - +- **Use case:** Define proxy exceptions for internal services or specific domains. - **Configure this setting with:** - **Proxies** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `proxy` setting with `manual` and `exclude` modes in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) +> [!NOTE] +> +> In hardened environments, disable and lock this setting to maintain strict proxy control. + ### Docker subnet | Default value | Accepted values | Format | @@ -499,7 +493,7 @@ settings. - **Description:** Use the host’s kernel network stack for UDP traffic instead of Docker’s virtual network driver. This enables faster and more direct UDP communication, but may bypass some container isolation features. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Improve performance or compatibility for workloads that rely heavily on UDP traffic, such as real-time media, DNS, or game servers. +- **Use case:** Improve performance for UDP-intensive applications like real-time media, DNS, or gaming. - **Configure this setting with:** - **Network** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -509,9 +503,9 @@ settings. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable experimental host networking support. +- **Description:** Experimental support for containers to use the host network stack directly. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Allow containers to use the host network stack. +- **Use case:** Allow containers to bypass Docker's network isolation for specific scenarios. - **Configure this setting with:** - **Network** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -521,9 +515,9 @@ settings. |---------------|-----------------|----------| | `dual-stack` | `ipv4only`, `ipv6only` | String | -- **Description:** Set the networking mode. +- **Description:** Default IP protocol used when Docker creates new networks. - **OS:** {{< badge color=blue text="Windows and Mac" >}} -- **Use case:** Choose the default IP protocol used when Docker creates new networks. +- **Use case:** Align with network infrastructure that supports only IPv4 or IPv6. - **Configure this setting with:** - **Network** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `defaultNetworkingMode` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -556,18 +550,17 @@ For more information, see [Networking](/manuals/desktop/features/networking.md#n based engine. This overrides anything that may have been set at installation using the `--backend=` flag. - **OS:** {{< badge color=blue text="Windows only" >}} + WSL -- **Use case:** Enable Linux containers via WSL 2 backend. - -> [!NOTE] -> -> In hardened environments, enable and lock this setting. - +- **Use case:** Run Linux containers on Windows using the WSL 2 backend for better performance. - **Configure this setting with:** - **WSL Integration** Resources settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `wslEngineEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **Windows Subsystem for Linux (WSL) Engine** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) -## Docker Engine +> [!NOTE] +> +> In hardened environments, enable and lock this setting for improved security and performance. + +## Docker Engine settings The Docker Engine settings let you configure low-level daemon settings through a raw JSON object. These settings are passed directly to the dockerd process that powers container management in Docker Desktop. @@ -580,15 +573,20 @@ The Docker Engine settings let you configure low-level daemon settings through a - **Description:** Customize the behavior of the Docker daemon using a structured JSON config passed directly to dockerd. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Fine-tune registry access, enable debug mode, or opt into experimental features. +- **Use case:** Configure registry access, enable debug logging, or turn on experimental features. - **Configure this setting with:** - **Docker Engine** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) > [!NOTE] > +> In hardened environments, provide a vetted configuration and lock it to prevent +unauthorized daemon modifications. + +> [!IMPORTANT] +> > Values for this setting are passed as-is to the Docker daemon. Invalid or unsupported fields may prevent Docker Desktop from starting. -## Builders +## Builders settings Builders settings lets you manage Buildx builder instances for advanced image-building scenarios, including multi-platform builds and custom backends. @@ -598,9 +596,9 @@ Builders settings lets you manage Buildx builder instances for advanced image-bu | `driver` | `"docker-container"` | Backend used by the builder (`docker`, `docker-container`, `remote`, etc.) | String | `docker` | | `platforms` | `["linux/amd64", "linux/arm64"]` | Target platforms supported by the builder | Array of platform strings | Host arch | -- **Description:** Configure custom Buildx builders for Docker Desktop, including driver type and supported platforms. +- **Description:** Buildx builder instances for advanced image building scenarios. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Set up advanced build configurations like cross-platform images or remote builders. +- **Use case:** Set up cross-platform builds, remote builders, or custom build environments. - **Configure this setting with:** - **Builders** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -608,7 +606,7 @@ Builders settings lets you manage Buildx builder instances for advanced image-bu > > Builder definitions are structured as an array of objects, each describing a builder instance. Conflicting or unsupported configurations may cause build errors. -## Kubernetes +## Kubernetes settings ### Enable Kubernetes @@ -616,13 +614,17 @@ Builders settings lets you manage Buildx builder instances for advanced image-bu |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable the integrated Kubernetes cluster in Docker Desktop. +- **Description:** Local Kubernetes cluster integration with Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or disable Kubernetes support for developers. +- **Use case:** Provide local Kubernetes development environment for testing and development. +- **Configure this setting with:** + - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - Settings Management: `kubernetes` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Allow Kubernetes** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > -> In hardened environments, disable and lock this setting. +> In hardened environments, disable and lock this setting unless Kubernetes development is specifically required. > [!IMPORTANT] > @@ -630,20 +632,15 @@ Builders settings lets you manage Buildx builder instances for advanced image-bu `kubeadm` cluster provisioning method is supported. The `kind` provisioning method is not yet supported by Settings Management. -- **Configure this setting with:** - - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - - Settings Management: `kubernetes` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Allow Kubernetes** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - ### Choose cluster provisioning method | Default value | Accepted values | Format | |---------------|-----------------|--------| | `kubeadm` | `kubeadm`, `kind` | String | -- **Description:** Set the Kubernetes node mode (single-node or multi-node). +- **Description:** Kubernetes cluster topology and node configuration. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Control the topology of the integrated Kubernetes cluster. +- **Use case:** Choose between single-node (`kubeadm`) or multi-node (`kind`)` cluster configurations for different development needs. - **Configure this setting with:** - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -653,9 +650,9 @@ method is not yet supported by Settings Management. |---------------|-----------------|---------| | `1` | Integer | Integer | -- **Description:** Number of nodes to create in a multi-node Kubernetes cluster. +- **Description:** Number of nodes in multi-node Kubernetes clusters. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Scale the number of Kubernetes nodes for development or testing. +- **Use case:** Scale cluster size for testing distributed applications or cluster features. - **Configure this setting with:** - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -665,10 +662,9 @@ method is not yet supported by Settings Management. |---------------|-------------------------------|--------| | `1.31.1` | Semantic version (e.g., 1.29.1) | String | -- **Description:** Version of Kubernetes used for cluster node creation. +- **Description:** Kubernetes version used for cluster nodes. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Pin a specific Kubernetes version for consistency or -compatibility. +- **Use case:** Pin specific Kubernetes versions for consistency or compatibility requirements. - **Configure this setting with:** - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -678,16 +674,15 @@ compatibility. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Show Kubernetes system containers in the Docker Dashboard container list +- **Description:** Visibility of Kubernetes system containers in Docker Desktop Dashboard. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Allow developers to view kube-system containers for debugging +- **Use case:** Allow developers to view and debug kube-system containers. +- **Configure this setting with:** + - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) > [!NOTE] > -> In hardened environments, disable and lock this setting. - -- **Configure this setting with:** - - **Kubernetes** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) +> In hardened environments, disable and lock this setting to reduce interface complexity. ### Custom Kubernetes image repository @@ -695,35 +690,27 @@ compatibility. |---------------|-----------------|----------| | `""` | Registry URL | String | -- **Description**: Configure a custom image repository for Kubernetes control -plane images. This allows Docker Desktop to pull Kubernetes system +- **Description**: Registry used for Kubernetes control plane images instead of Docker Hub. This allows Docker Desktop to pull Kubernetes system images from a private registry or mirror instead of Docker Hub. This setting overrides the `[registry[:port]/][namespace]` portion of image names. - **OS**: {{< badge color=blue text="All" >}} -- **Use case**: Use private registries in air-gapped environments or -when Docker Hub access is restricted. - -> [!NOTE] -> -> The images must be cloned/mirrored from Docker Hub with matching tags. The -specific images required depend on the cluster provisioning method (`kubeadm` -or `kind`). See the Kubernetes documentation for the complete list -of required images and detailed setup instructions. - +- **Use case**: Support air-gapped environments or when Docker Hub access is restricted. - **Configure this setting with**: - Settings Management: `KubernetesImagesRepository` settings in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - Settings Management: **Kubernetes Images Repository** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) +> [!NOTE] +> +> Images must be mirrored from Docker Hub with matching tags. Required images depend on the cluster provisioning method. + > [!IMPORTANT] > -> When using `KubernetesImagesRepository` with Enhanced Container Isolation (ECI) -enabled, you must add the following images to the ECI Docker socket mount image -list: `[imagesRepository]/desktop-cloud-provider-kind:*` and +> When using custom image repositories with Enhanced Container Isolation, add these images to the ECI allowlist: `[imagesRepository]/desktop-cloud-provider-kind:*` and `[imagesRepository]/desktop-containerd-registry-mirror:*`. -## Software updates +## Software updates settings ### Automatically check for updates @@ -731,35 +718,34 @@ list: `[imagesRepository]/desktop-cloud-provider-kind:*` and |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Disable automatic update polling for Docker Desktop. If the +- **Description:** Whether Docker Desktop checks for and notifies about available updates. If the value is set to `true`, checking for updates and notifications about Docker Desktop updates are disabled. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Freeze the current version in enterprise environments. +- **Use case:** Control update notifications and automatic version checking. +- **Configure this setting with:** + - Settings Management: `disableUpdate` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Disable update** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > > In hardened environments, enable this setting and lock. This guarantees that only internally vetted versions are installed. -- **Configure this setting with:** - - Settings Management: `disableUpdate` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Disable update** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - ### Always download updates | Default value | Accepted values | Format | |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Automatically download Docker Desktop updates when available. +- **Description:** Automatic downloading of Docker Desktop updates when they become available. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Manage auto update behavior. +- **Use case:** Manage bandwidth usage and control when updates are downloaded. - **Configure this setting with:** - **Software updates** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: **Disable updates** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) -## Extensions +## Extensions settings ### Enable Docker extensions @@ -767,30 +753,28 @@ only internally vetted versions are installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Enable or disable Docker Extensions. +- **Description:** Access to Docker Extensions marketplace and installed extensions. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Control access to the Extensions Marketplace and installed -extensions. +- **Use case:** Control whether users can install and run Docker Extensions. +- **Configure this setting with:** + - **Extensions** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - Settings Management: `extensionsEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **Allow Extensions** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > > In hardened environments, disable and lock this setting. This prevents third-party or unvetted plugins from being installed. -- **Configure this setting with:** - - **Extensions** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - - Settings Management: `extensionsEnabled` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **Allow Extensions** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - ### Allow only extensions distributed through the Docker Marketplace | Default value | Accepted values | Format | |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Restrict Docker Desktop to only run Marketplace extensions. +- **Description:** Restriction of Docker Extensions to only those available through the official marketplace. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Prevent running third-party or local extensions. +- **Use case:** Prevent installation of third-party or locally developed extensions. - **Configure this setting with:** - **Extensions** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -800,17 +784,17 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Show system containers used by Docker Extensions in the container list +- **Description:** Visibility of system containers used by Docker Extensions in the container list. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Help developers troubleshoot or view extension system containers +- **Use case:** Help developers troubleshoot extension issues by viewing underlying containers. - **Configure this setting with:** - **Extensions** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) -## Beta features +## Beta features settings > [!IMPORTANT] > -> For Docker Desktop versions 4.41 and earlier, these settings lived under the **Experimental features** tab on the **Features in development** page. +> For Docker Desktop versions 4.41 and earlier, these settings were under the **Experimental features** tab on the **Features in development** page. ### Enable Docker AI @@ -818,9 +802,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable Docker AI features in the Docker Desktop experience. +- **Description:** Docker AI features including "Ask Gordon" functionality. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or disable AI features like "Ask Gordon". +- **Use case:** Turn on AI-powered assistance and recommendations within Docker Desktop. - **Configure this setting with:** - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableDockerAI` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -831,9 +815,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Enable Docker Model Runner features in Docker Desktop. +- **Description:** Docker Model Runner functionality for running AI models in containers. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or disable Docker Model Runner features. +- **Use case:** Run and manage AI/ML models using Docker infrastructure. - **Configure this setting with:** - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableDockerAI` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -844,13 +828,13 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable Docker Model Runner features in Docker Desktop. +- **Description:** TCP connectivity for Docker Model Runner services. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or disable Docker Model Runner features. +- **Use case:** Allow external applications to connect to Model Runner via TCP. - **Configure this setting with:** - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableDockerAI` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - + > [!NOTE] > > This setting requires Docker Model Runner setting to be enabled first. @@ -861,9 +845,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|---------| | 12434 | Integer | Integer | -- **Description:** Specifies the exposed TCP port. +- **Description:** Specific port used for Model Runner TCP connections. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Connect to the Model Runner via TCP. +- **Use case:** Customize the port for Model Runner TCP connectivity. - **Configure this setting with:** - **Beta features** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableInferenceTCP` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -874,9 +858,9 @@ third-party or unvetted plugins from being installed. |---------------|---------------------------------------------------------------------------------|--------| | Empty string | Empty string to deny all,`*` to accept all, or a list of comma-separated values | String | -- **Description:** Specifies the allowed CORS origins. +- **Description:** Cross-origin resource sharing settings for Model Runner web integration. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Integration with a web app. +- **Use case:** Allow web applications to connect to Model Runner services. - **Configure this setting with:** - **Beta features** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableInferenceCORS` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -889,10 +873,10 @@ third-party or unvetted plugins from being installed. - **Description:** Enable [Docker MCP Toolkit](/manuals/ai/mcp-catalog-and-toolkit/_index.md) in Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} +- **Use case:** Turn on MCP toolkit features for AI model development workflows. - **Configure this setting with:** - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `enableDockerMCPToolkit` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - ### Enable Wasm @@ -902,8 +886,9 @@ third-party or unvetted plugins from being installed. - **Description:** Enable [Wasm](/manuals/desktop/features/wasm.md) to run Wasm workloads. - **OS:** {{< badge color=blue text="All" >}} +- **Use case:** Run WebAssembly applications and modules within Docker containers. - **Configure this setting with:** - - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) + - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) ### Enable Compose Bridge @@ -913,10 +898,11 @@ third-party or unvetted plugins from being installed. - **Description:** Enable [Compose Bridge](/manuals/compose/bridge/_index.md). - **OS:** {{< badge color=blue text="All" >}} +- **Use case:** Turn on enhanced Compose features and integrations. - **Configure this setting with:** - **Beta** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) -## Notifications +## Notifications settings ### Status updates on tasks and processes @@ -924,9 +910,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Display general informational messages inside Docker Desktop +- **Description:** General informational messages displayed within Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Customize in-app communication visibility +- **Use case:** Control visibility of operational status messages and process updates. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -936,9 +922,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Display promotional announcements and banners inside Docker Desktop +- **Description:** Promotional content and feature recommendations displayed in Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Control exposure to Docker news and feature promotion +- **Use case:** Manage exposure to Docker marketing content and feature promotions. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -948,9 +934,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Display general announcements inside Docker Desktop. +- **Description:** General announcements and news displayed within Docker Desktop. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or suppress Docker-wide announcements in the GUI. +- **Use case:** Control visibility of Docker-wide announcements and important updates. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -960,9 +946,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Display notifications inviting users to participate in surveys +- **Description:** Survey invitations and feedback requests displayed to users. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enable or disable in-product survey prompts +- **Use case:** Manage user participation in Docker product feedback and research. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -972,9 +958,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Enable Docker Scout popups inside Docker Desktop. +- **Description:** In-application notifications from Docker Scout vulnerability scanning. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Show or hide vulnerability scan notifications +- **Use case:** Control visibility of vulnerability scan results and security recommendations. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -984,13 +970,13 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable Docker Scout notifications through the operating system. +- **Description:** Operating system-level notifications from Docker Scout. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Push Scout updates via system notification center +- **Use case:** Receive Scout security alerts through the system notification center. - **Configure this setting with:** - **Notifications** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) -## Advanced +## Advanced settings ### Configure installation of Docker CLI @@ -998,9 +984,9 @@ third-party or unvetted plugins from being installed. |---------------|-----------------|----------| | `system` | File path | String | -- **Description:** Install location for Docker CLI binaries. +- **Description:** File system location where Docker CLI binaries are installed. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Customize CLI install location for compliance or tooling. +- **Use case:** Customize CLI installation location for compliance or tooling integration requirements. - **Configure this setting with:** - **Advanced** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) @@ -1015,8 +1001,7 @@ the Docker Engine socket into containers (e.g., `docker run -v /var/run/docker.sock:/var/run/docker.sock ...`). This lets you relax this in a controlled way. See ECI Configuration for more info. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Allow containers to access the Docker socket for scenarios like -Docker-in-Docker or containerized CI agents. +- **Use case:** Support Docker-in-Docker scenarios, CI agents, or tools like Testcontainers while maintaining Enhanced Container Isolation. - **Configure this setting with:** - **Advanced** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) - Settings Management: `dockerSocketMount` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -1027,13 +1012,13 @@ Docker-in-Docker or containerized CI agents. |---------------|-----------------|----------| | `true` | `true`, `false` | Boolean | -- **Description:** Starts the privileged helper process which binds privileged ports that are between 1 and 1024 +- **Description:** Permission to bind container ports to privileged ports (1-1024) on the host. - **OS:** {{< badge color=blue text="Mac only" >}} -- **Use case:** Enforce elevated privileges for networking support +- **Use case:** Allow containers to use standard service ports like HTTP (80) or HTTPS (443). - **Configure this setting with:** - **Advanced** settings in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) -## Settings not available in the Docker Desktop GUI +## Settings not available in Docker Desktop The following settings aren’t shown in the Docker Desktop GUI. You can only configure them using Settings Management with the Admin Console or the `admin-settings.json` file. @@ -1045,16 +1030,15 @@ The following settings aren’t shown in the Docker Desktop GUI. You can only co - **Description:** Prevent users from loading local Docker images using the `docker load` command. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Enforce image provenance by restricting local image imports. +- **Use case:** Enforce image provenance by requiring all images to come from registries. +- **Configure this setting with:** + - Settings Management: `blockDockerLoad` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) > [!NOTE] > > In hardened environments, enable and lock this setting. This forces all images to come from your secure, scanned registry. -- **Configure this setting with:** - - Settings Management: `blockDockerLoad` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - ### Expose Docker API on TCP 2375 | Default value | Accepted values | Format | @@ -1063,25 +1047,24 @@ to come from your secure, scanned registry. - **Description:** Exposes the Docker API over an unauthenticated TCP socket on port 2375. Only recommended for isolated and protected environments. - **OS:** {{< badge color=blue text="Windows only" >}} -- **Use case:** Required for legacy integrations or environments without named pipe support. +- **Use case:** Support legacy integrations that require TCP API access. +- **Configure this setting with:** + - Settings Management: `exposeDockerAPIOnTCP2375` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) > [!NOTE] > > In hardened environments, disable and lock this setting. This ensures the Docker API is only reachable via the secure internal socket. -- **Configure this setting with:** - - Settings Management: `exposeDockerAPIOnTCP2375` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - ### Air-gapped container proxy | Default value | Accepted values | Format | | ------------- | --------------- | ----------- | | See example | Object | JSON object | -- **Description:** Configure a manual HTTP/HTTPS proxy for containers. Useful in air-gapped environments where containers need restricted access. +- **Description:** HTTP/HTTPS proxy configuration for containers in air-gapped environments. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Redirect or block container networking to comply with offline or secured network environments. +- **Use case:** Provide controlled network access for containers in offline or restricted network environments. - **Configure this setting with:** - Settings Management: `containersProxy` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -1099,15 +1082,15 @@ Docker API is only reachable via the secure internal socket. } ``` -Docker socket access control (ECI exceptions) +### Docker socket access control (ECI exceptions) | Default value | Accepted values | Format | | ------------- | --------------- | ----------- | | - | Object | JSON object | -- **Description:** Allow specific images or commands to use the Docker socket when Enhanced Container Isolation is enabled. +- **Description:** Specific images and commands allowed to use the Docker socket when Enhanced Container Isolation is active. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Support tools like Testcontainers or LocalStack that need Docker socket access while maintaining secure defaults. +- **Use case:** Support tools like Testcontainers, LocalStack, or CI systems that need Docker socket access while maintaining security. - Configure this setting with: - Settings Management: `enhancedContainerIsolation` > `dockerSocketMount` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) @@ -1138,17 +1121,16 @@ Docker socket access control (ECI exceptions) |---------------|-----------------|----------| | `false` | `true`, `false` | Boolean | -- **Description:** Enable access to beta features in Docker Desktop. +- **Description:** Access to Docker Desktop features in public beta. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Give developers early access to features that are in public beta. +- **Use case:** Provide early access to features in development for testing and feedback. +- **Configure this setting with:** + - Settings Management: `allowBetaFeatures` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) > [!NOTE] > > In hardened environments, disable and lock this setting. -- **Configure this setting with:** - - Settings Management: `allowBetaFeatures` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - ### Docker daemon options (Linux or Windows) | Default value | Accepted values | Format | @@ -1157,42 +1139,40 @@ Docker socket access control (ECI exceptions) - **Description:** Override the Docker daemon configuration used in Linux or Windows containers. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Configure low-level Docker daemon options (e.g., logging, storage drivers) without editing the local config files. +- **Use case:** Configure advanced daemon options without modifying local configuration files. +- **Configure this setting with:** + - Settings Management: `linuxVM.dockerDaemonOptions` or `windowsContainers.dockerDaemonOptions` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) > [!NOTE] > > In hardened environments, provide a vetted JSON config and lock it so no overrides are possible. -- **Configure this setting with:** - - Settings Management: `linuxVM.dockerDaemonOptions` or `windowsContainers.dockerDaemonOptions` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - ### VPNKit CIDR | Default value | Accepted values | Format | |-------------------|-----------------|--------| | `192.168.65.0/24` | CIDR notation | String | -- **Description:** Set the subnet used for internal VPNKit DHCP/DNS services. +- **Description:** Network subnet used for Docker Desktop's internal VPNKit DHCP/DNS services. - **OS:** {{< badge color=blue text="Mac only" >}} -- **Use case:** Prevent IP conflicts in environments with overlapping subnets. +- **Use case:** Prevent IP address conflicts in environments with overlapping network subnets. +- **Configure this setting with:** + - Settings Management: `vpnkitCIDR` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) + - Settings Management: **VPN Kit CIDR** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) > [!NOTE] > > In hardened environments, lock to an approved, non-conflicting CIDR. -- **Configure this setting with:** - - Settings Management: `vpnkitCIDR` setting in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) - - Settings Management: **VPN Kit CIDR** setting in the [Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) - ### Enable Kerberos and NTLM authentication | Default value | Accepted values | Format | |---------------|-----------------|--------| | `false` | `true`, `false` | Boolean | -- **Description:** Enables Kerberos and NTLM proxy authentication for enterprise environments. +- **Description:** Enterprise proxy authentication support for Kerberos and NTLM protocols. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** Allow users to authenticate with enterprise proxy servers that require Kerberos or NTLM. +- **Use case:** Support enterprise proxy servers that require Kerberos or NTLM authentication. - **Configure this setting with:** - Settings Management: `proxy.enableKerberosNtlm` in the [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) diff --git a/content/manuals/enterprise/security/provisioning/_index.md b/content/manuals/enterprise/security/provisioning/_index.md index 8d4eca3c8e5d..4704e517d76c 100644 --- a/content/manuals/enterprise/security/provisioning/_index.md +++ b/content/manuals/enterprise/security/provisioning/_index.md @@ -1,51 +1,70 @@ --- description: Learn about provisioning users for your SSO configuration. -keywords: provision users, provisioning, JIT, SCIM, group mapping, sso, docker hub, hub, docker admin, admin, security +keywords: provision users, provisioning, JIT, SCIM, group mapping, sso, docker admin, admin, security title: Provision users linkTitle: Provision weight: 20 aliases: - /security/for-admins/provisioning/ +grid: + - title: "Just-in-Time (JIT) provisioning" + description: "Set up automatic user creation on first sign-in. Ideal for smaller teams with minimal setup requirements." + icon: "schedule" + link: "just-in-time/" + - title: "SCIM provisioning" + description: "Enable continuous user data synchronization between your IdP and Docker. Best for larger organizations." + icon: "sync" + link: "scim/" + - title: "Group mapping" + description: "Configure role-based access control using IdP groups. Perfect for strict access control requirements." + icon: "group" + link: "group-mapping/" --- {{< summary-bar feature_name="SSO" >}} -Once you've configured your SSO connection, the next step is to provision users. This process ensures that users can access your organization. -This guide provides an overview of user provisioning and supported provisioning methods. +After configuring your SSO connection, the next step is to provision users. This process ensures that users can access your organization through automated user management. + +This page provides an overview of user provisioning and the supported provisioning methods. ## What is provisioning? -Provisioning helps manage users by automating tasks like creating, updating, and deactivating users based -on data from your identity provider (IdP). There are three methods for user provisioning, with benefits for -different organization needs: +Provisioning helps manage users by automating tasks like account creation, updates, and deactivation based on data from your identity provider (IdP). There are three methods for user provisioning, each offering benefits for different organizational needs: | Provisioning method | Description | Default setting in Docker | Recommended for | | :--- | :--- | :------------- | :--- | -| Just-in-Time (JIT) | Automatically create and provisions user accounts when they first sign in via SSO | Enabled by default | Best for organizations who need minimal setup, who have smaller teams, or low-security environments | -| System for Cross-domain Identity Management (SCIM) | Continuously syncs user data between your IdP and Docker, ensuring user attributes remain updated without requiring manual updates | Disabled by default | Best for larger organizations or environments with frequent changes in user information or roles | -| Group mapping | Maps user groups from your IdP to specific roles and permissions within Docker, enabling fine-tuned access control based on group membership | Disabled by default | Best for organizations that require strict access control and for managing users based on their roles and permissions | +| Just-in-Time (JIT) | Automatically creates and provisions user accounts when they first sign in via SSO | Enabled by default | Organizations needing minimal setup, smaller teams, or low-security environments | +| System for Cross-domain Identity Management (SCIM) | Continuously syncs user data between your IdP and Docker, ensuring user attributes remain updated without manual intervention | Disabled by default | Larger organizations or environments with frequent changes in user information or roles | +| Group mapping | Maps user groups from your IdP to specific roles and permissions within Docker, enabling fine-grained access control based on group membership | Disabled by default | Organizations requiring strict access control and role-based user management | ## Default provisioning setup By default, Docker enables JIT provisioning when you configure an SSO connection. With JIT enabled, user accounts are automatically created the first time a user signs in using your SSO flow. -JIT provisioning may not provide the level of control or security some organizations need. In such cases, SCIM or group mapping can be configured to give administrators more control over user access and attributes. +JIT provisioning may not provide sufficient control or security for some organizations. In such cases, SCIM or group mapping can be configured to give administrators more control over user access and attributes. ## SSO attributes When a user signs in through SSO, Docker obtains several attributes from your IdP to manage the user's identity and permissions. These attributes include: -- **Email address**: The unique identifier for the user -- **Full name**: The user's complete name -- **Groups**: Optional. Used for group-based access control -- **Docker Org**: Optional. Specifies the organization the user belongs to -- **Docker Team**: Optional. Defines the team the user belongs to within the organization -- **Docker Role**: Optional. Determines the user's permission within Docker -- **Docker session minutes**: Optional. Sets the duration of a user’s session before they must re-authenticate with their identity provider (IdP). The value must be a positive integer greater than 0. -If this is attribute is not provided, by default: - - Docker Desktop signs you out after 90 days, or 30 days of inactivity. - - Docker Hub and Docker Home sign you out after 24 hours. - -If your organization uses SAML for SSO, Docker retrieves these attributes from the SAML assertion message. Keep in mind that different IdPs may use different names for these attributes. The following reference table outlines possible SAML attributes used by Docker: + +- Email address: The unique identifier for the user. +- Full name: The user's complete name. +- Groups: Optional. Used for group-based access control. +- Docker Org: Optional. Specifies the organization the user belongs to. +- Docker Team: Optional. Defines the team the user belongs to within the organization. +- Docker Role: Optional. Determines the user's permissions within Docker +- Docker session minutes: Optional. Sets the session duration before users must re-authenticate with their IdP. Must be a positive integer greater than 0. If not provided, default session timeouts apply. + +> [!NOTE] +> +> Default session timeouts when Docker session minutes is not specified are +as follows: +> - Docker Desktop: 90 days, or 30 days of inactivity +> - Docker Hub and Docker Home: 24 hours + +## SAML attribute mapping + +If your organization uses SAML for SSO, Docker retrieves these attributes from the SAML assertion message. Different IdPs may use different names for these attributes. | SSO Attribute | SAML Assertion Message Attributes | | :--- | :--- | @@ -57,9 +76,8 @@ If your organization uses SAML for SSO, Docker retrieves these attributes from t | Docker Role (optional) | `dockerRole` | | Docker session minutes (optional) | `dockerSessionMinutes`, must be a positive integer > 0 | -## What's next? +## Next steps + +Choose the provisioning method that best fits your organization's needs: -Review the provisioning method guides for steps on configuring provisioning methods: -- [JIT](just-in-time.md) -- [SCIM](scim.md) -- [Group mapping](group-mapping.md) \ No newline at end of file +{{< grid >}} \ No newline at end of file diff --git a/content/manuals/enterprise/security/provisioning/group-mapping.md b/content/manuals/enterprise/security/provisioning/group-mapping.md index 78f4f9eb2260..222fa079c173 100644 --- a/content/manuals/enterprise/security/provisioning/group-mapping.md +++ b/content/manuals/enterprise/security/provisioning/group-mapping.md @@ -1,41 +1,63 @@ --- -description: Group mapping for administrators -keywords: Group Mapping, SCIM, Docker Hub, Docker Admin, admin, security title: Group mapping +description: Automate team membership by syncing identity provider groups with Docker teams +keywords: Group Mapping, SCIM, Docker Admin, admin, security, team management, user provisioning, identity provider aliases: - /admin/company/settings/group-mapping/ - /admin/organization/security-settings/group-mapping/ - /docker-hub/group-mapping/ - /security/for-admins/group-mapping/ - /security/for-admins/provisioning/group-mapping/ -weight: 40 +weight: 30 --- {{< summary-bar feature_name="SSO" >}} -Group mapping lets you sync user groups from your identity provider (IdP) with teams in your Docker organization. This automates team membership management, keeping your Docker Teams up to date based on changes in your IdP. You can use group mapping once you have configured [single sign-on (SSO)](../single-sign-on/_index.md). +Group mapping automatically synchronizes user groups from your identity provider (IdP) with teams in your Docker organization. For example, when you add a developer to the "backend-team" group in your IdP, they're automatically added to the corresponding team in Docker > [!TIP] > > Group mapping is ideal for adding users to multiple organizations or multiple teams within one organization. If you don't need to set up multi-organization or multi-team assignment, you can use SCIM [user-level attributes](scim.md#set-up-role-mapping). +## Prerequisites + +- SSO is configured for your organization +- You have administrator access to Docker Home and your identity provider + ## How group mapping works -With group mapping enabled, when a user authenticates through SSO, your IdP shares key attributes with Docker, such as the user's email address, name, and groups. Docker uses these attributes to create or update the user's profile, as well as to manage their team and organization assignments. With group mapping, users’ team memberships in Docker automatically reflect changes made in your IdP groups. +Group mapping keeps your Docker teams synchronized with your IdP groups through these key components: -It's important to note that Docker uses the user's email address as a unique identifier. Each Docker account must always have a unique email address. +- Authentication flow: When users sign in through SSO, your IdP shares user attributes with Docker including email, name, and group memberships. +- Automatic updates: Docker uses these attributes to create or update user profiles and manage team assignments based on IdP group changes. +- Unique identification: Docker uses email addresses as unique identifiers, so each Docker account must have a unique email address. +- Team synchronization: Users' team memberships in Docker automatically reflect changes made in your IdP groups. -## Use group mapping +## Set up group mapping -To assign users to Docker Teams through your IdP, you must create groups in your IdP following the naming pattern: `organization:team`. For example, if your organization is called "moby" and you want to manage the "developers" team, the group name in your IdP should be `moby:developers`. In this example, any user added to this group in your IdP is automatically assigned to the "developers" team in Docker. +Group mapping setup involves configuring your identity provider to share group +information with Docker. This requires: -You can also use this format to assign users to multiple organizations. For example, to add a user to the "backend" team in the "moby" organization and the "desktop" team in the "whale" organization, the group names would be `moby:backend` and `whale:desktop`. +- Creating groups in your IdP using Docker's naming format +- Configuring attributes so your IdP sends group data during authentication +- Adding users to the appropriate groups +- Testing the connection to ensure groups sync properly -> [!TIP] -> -> Match the group names in your IdP with your Docker Teams. When groups are synced, Docker creates a team if it doesn’t already exist. +You can use group mapping with SSO only, or with both SSO and SCIM for enhanced +user lifecycle management. + +### Group naming format + +Create groups in your IdP using the format: `organization:team`. + +Examples: + +- For the "developers" team in the "moby" organization: `mobdy:developers` +- For multi-organization access: `moby:backend` and `whale:desktop` -The following lists the supported group mapping attributes: +Docker creates teams automatically if they don't already exist when groups sync. + +### Supported attributes | Attribute | Description | |:--------- | :---------- | @@ -44,89 +66,80 @@ The following lists the supported group mapping attributes: | members | A list of users that are members of this group. | | members(x).value | Unique ID of the user that is a member of this group. Members are referenced by ID. | -The general steps to use group mapping are: - -1. In your IdP, create groups with the `organization:team` format. -2. Add users to the group. -3. Add the Docker application that you created in your IdP to the group. -4. Add attributes in the IdP. -5. Push groups to Docker. +## Configure group mapping with SSO -The exact configuration may vary depending on your IdP. You can use [group mapping with SSO](#use-group-mapping-with-sso), or with SSO and [SCIM enabled](#use-group-mapping-with-scim). +Use group mapping with SSO connections that use the SAML authentication method. -### Use group mapping with SSO - -The following steps describe how to set up and use group mapping with SSO -connections that use the SAML authentication method. Note that group mapping -with SSO isn't supported with the Azure AD (OIDC) authentication method. -Additionally, SCIM isn't required for these configurations. +> [!NOTE] +> +> Group mapping with SSO isn't supported with the Azure AD (OIDC) authentication method. SCIM isn't required for these configurations. {{< tabs >}} {{< tab name="Okta" >}} -The user interface for your IdP may differ slightly from the following steps. You can refer to the [Okta documentation](https://help.okta.com/oie/en-us/content/topics/apps/define-group-attribute-statements.htm) to verify. +The user interface for your IdP may differ slightly from the following steps. Refer to the [Okta documentation](https://help.okta.com/oie/en-us/content/topics/apps/define-group-attribute-statements.htm) to verify. To set up group mapping: 1. Sign in to Okta and open your application. -2. Navigate to the **SAML Settings** page for your application. -3. In the **Group Attribute Statements (optional)** section, configure like the following: +1. Navigate to the **SAML Settings** page for your application. +1. In the **Group Attribute Statements (optional)** section, configure like the following: - **Name**: `groups` - **Name format**: `Unspecified` - **Filter**: `Starts with` + `organization:` where `organization` is the name of your organization The filter option will filter out the groups that aren't affiliated with your Docker organization. -4. Create your groups by selecting **Directory**, then **Groups**. -5. Add your groups using the format `organization:team` that matches the names of your organization(s) and team(s) in Docker. -6. Assign users to the group(s) that you create. +1. Create your groups by selecting **Directory**, then **Groups**. +1. Add your groups using the format `organization:team` that matches the names of your organization(s) and team(s) in Docker. +1. Assign users to the group(s) that you create. The next time you sync your groups with Docker, your users will map to the Docker groups you defined. {{< /tab >}} {{< tab name="Entra ID" >}} -The user interface for your IdP may differ slightly from the following steps. You can refer to the [Entra ID documentation](https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes) to verify. +The user interface for your IdP may differ slightly from the following steps. Refer to the [Entra ID documentation](https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes) to verify. To set up group mapping: 1. Sign in to Entra ID and open your application. -2. Select **Manage**, then **Single sign-on**. -3. Select **Add a group claim**. -4. In the Group Claims section, select **Groups assigned to the application** with the source attribute **Cloud-only group display names (Preview)**. -5. Select **Advanced options**, then the **Filter groups** option. -6. Configure the attribute like the following: +1. Select **Manage**, then **Single sign-on**. +1. Select **Add a group claim**. +1. In the Group Claims section, select **Groups assigned to the application** with the source attribute **Cloud-only group display names (Preview)**. +1. Select **Advanced options**, then the **Filter groups** option. +1. Configure the attribute like the following: - **Attribute to match**: `Display name` - **Match with**: `Contains` - **String**: `:` -7. Select **Save**. -8. Select **Groups**, **All groups**, then **New group** to create your group(s). -9. Assign users to the group(s) that you create. +1. Select **Save**. +1. Select **Groups**, **All groups**, then **New group** to create your group(s). +1. Assign users to the group(s) that you create. The next time you sync your groups with Docker, your users will map to the Docker groups you defined. {{< /tab >}} {{< /tabs >}} -### Use group mapping with SCIM +## Configure group mapping with SCIM -The following steps describe how to set up and use group mapping with SCIM. Before you begin, make sure you [set up SCIM](./scim.md#enable-scim) first. +Use group mapping with SCIM for more advanced user lifecycle management. Before you begin, make sure you [set up SCIM](./scim.md#enable-scim) first. {{< tabs >}} {{< tab name="Okta" >}} -The user interface for your IdP may differ slightly from the following steps. You can refer to the [Okta documentation](https://help.okta.com/en-us/Content/Topics/users-groups-profiles/usgp-enable-group-push.htm) to verify. +The user interface for your IdP may differ slightly from the following steps. Refer to the [Okta documentation](https://help.okta.com/en-us/Content/Topics/users-groups-profiles/usgp-enable-group-push.htm) to verify. To set up your groups: 1. Sign in to Okta and open your application. -2. Select **Applications**, then **Provisioning**, and **Integration**. -3. Select **Edit** to enable groups on your connection, then select **Push groups**. -4. Select **Save**. Saving this configuration will add the **Push Groups** tab to your application. -5. Create your groups by navigating to **Directory** and selecting **Groups**. -6. Add your groups using the format `organization:team` that matches the names of your organization(s) and team(s) in Docker. -7. Assign users to the group(s) that you create. -8. Return to the **Integration** page, then select the **Push Groups** tab to open the view where you can control and manage how groups are provisioned. -9. Select **Push Groups**, then **Find groups by rule**. -10. Configure the groups by rule like the following: +1. Select **Applications**, then **Provisioning**, and **Integration**. +1. Select **Edit** to enable groups on your connection, then select **Push groups**. +1. Select **Save**. Saving this configuration will add the **Push Groups** tab to your application. +1. Create your groups by navigating to **Directory** and selecting **Groups**. +1. Add your groups using the format `organization:team` that matches the names of your organization(s) and team(s) in Docker. +1. Assign users to the group(s) that you create. +1. Return to the **Integration** page, then select the **Push Groups** tab to open the view where you can control and manage how groups are provisioned. +1. Select **Push Groups**, then **Find groups by rule**. +1. Configure the groups by rule like the following: - Enter a rule name, for example `Sync groups with Docker Hub` - Match group by name, for example starts with `docker:` or contains `:` for multi-organization - If you enable **Immediately push groups by rule**, sync will happen as soon as there's a change to the group or group assignments. Enable this if you don't want to manually push groups. @@ -136,33 +149,33 @@ Find your new rule under **By rule** in the **Pushed Groups** column. The groups To push the groups from this table: 1. Select **Group in Okta**. -2. Select the **Push Status** drop-down. -3. Select **Push Now**. +1. Select the **Push Status** drop-down. +1. Select **Push Now**. {{< /tab >}} {{< tab name="Entra ID" >}} -The user interface for your IdP may differ slightly from the following steps. You can refer to the [Entra ID documentation](https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes) to verify. +The user interface for your IdP may differ slightly from the following steps. Refer to the [Entra ID documentation](https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes) to verify. Complete the following before configuring group mapping: 1. Sign in to Entra ID and go to your application. -2. In your application, select **Provisioning**, then **Mappings**. -3. Select **Provision Microsoft Entra ID Groups**. -4. Select **Show advanced options**, then **Edit attribute list**. -5. Update the `externalId` type to `reference`, then select the **Multi-Value** checkbox and choose the referenced object attribute `urn:ietf:params:scim:schemas:core:2.0:Group`. -6. Select **Save**, then **Yes** to confirm. -7. Go to **Provisioning**. -8. Toggle **Provision Status** to **On**, then select **Save**. +1. In your application, select **Provisioning**, then **Mappings**. +1. Select **Provision Microsoft Entra ID Groups**. +1. Select **Show advanced options**, then **Edit attribute list**. +1. Update the `externalId` type to `reference`, then select the **Multi-Value** checkbox and choose the referenced object attribute `urn:ietf:params:scim:schemas:core:2.0:Group`. +1. Select **Save**, then **Yes** to confirm. +1. Go to **Provisioning**. +1. Toggle **Provision Status** to **On**, then select **Save**. Next, set up group mapping: 1. Go to the application overview page. -2. Under **Provision user accounts**, select **Get started**. -3. Select **Add user/group**. -4. Create your group(s) using the `organization:team` format. -5. Assign the group to the provisioning group. -6. Select **Start provisioning** to start the sync. +1. Under **Provision user accounts**, select **Get started**. +1. Select **Add user/group**. +1. Create your group(s) using the `organization:team` format. +1. Assign the group to the provisioning group. +1. Select **Start provisioning** to start the sync. To verify, select **Monitor**, then **Provisioning logs** to see that your groups were provisioned successfully. In your Docker organization, you can check that the groups were correctly provisioned and the members were added to the appropriate teams. @@ -174,10 +187,3 @@ Once complete, a user who signs in to Docker through SSO is automatically added > [!TIP] > > [Enable SCIM](scim.md) to take advantage of automatic user provisioning and de-provisioning. If you don't enable SCIM users are only automatically provisioned. You have to de-provision them manually. - -## More resources - -The following videos demonstrate how to use group mapping with your IdP with SCIM enabled: - -- [Video: Group mapping with Okta](https://youtu.be/c56YECO4YP4?feature=shared&t=3023) -- [Video: Attribute and group mapping with Entra ID (Azure)](https://youtu.be/bGquA8qR9jU?feature=shared&t=2039) diff --git a/content/manuals/enterprise/security/provisioning/just-in-time.md b/content/manuals/enterprise/security/provisioning/just-in-time.md index 1d1bc6ad65af..00a3bc55e114 100644 --- a/content/manuals/enterprise/security/provisioning/just-in-time.md +++ b/content/manuals/enterprise/security/provisioning/just-in-time.md @@ -1,15 +1,21 @@ --- description: Learn how Just-in-Time provisioning works with your SSO connection. -keywords: user provisioning, just-in-time provisioning, JIT, autoprovision, Docker Hub, Docker Admin, admin, security +keywords: user provisioning, just-in-time provisioning, JIT, autoprovision, Docker Admin, admin, security title: Just-in-Time provisioning linkTitle: Just-in-Time -aliases: +weight: 10 +aliases: - /security/for-admins/provisioning/just-in-time/ --- {{< summary-bar feature_name="SSO" >}} -Just-in-Time (JIT) provisioning automatically creates and updates user accounts after every successful single sign-on (SSO) authentication. JIT verifies that the user signing in belongs to the organization and the teams assigned to them in your identity provider (IdP). When you [create your SSO connection](../single-sign-on/_index.md), JIT provisioning is turned on by default. +Just-in-Time (JIT) provisioning streamlines user onboarding by automatically creating and updating user accounts during SSO authentication. This eliminates manual account creation and ensures users have immediate access to your organization's resources. JIT verifies that users belong to the organization and assigns them to the appropriate teams based on your identity provider (IdP) configuration. When you [create your SSO connection](../single-sign-on/_index.md), JIT provisioning is turned on by default. + +## Prerequisites + +- SSO is configured for your organization +- You have administrator access to Docker Home and your identity provider ## SSO authentication with JIT provisioning enabled @@ -32,7 +38,7 @@ When a user signs in with SSO and your SSO configuration has JIT provisioning en The following graphic provides an overview of SSO authentication with JIT enabled: - ![JIT provisioning enabled](../images/jit-enabled-flow.svg) + ![JIT provisioning enabled workflow](../images/jit-enabled-flow.svg) ## SSO authentication with JIT provisioning disabled @@ -52,7 +58,7 @@ With JIT disabled, group mapping is only available if you have [SCIM enabled](sc The following graphic provides an overview of SSO authentication with JIT disabled: -![JIT provisioning disabled](../images/jit-disabled-flow.svg) +![JIT provisioning disabled workflow](../images/jit-disabled-flow.svg) ## Disable JIT provisioning @@ -69,5 +75,11 @@ Users are provisioned with JIT by default. If you enable SCIM, you can disable J 1. In [Docker Home](https://app.docker.com/), select your organization. 1. Select **Admin Console**, then **SSO and SCIM**. -1. In the SSO connections table, select the **Action** icon and then **Disable JIT provisioning**. +1. In the **SSO connections** table, select the **Action** icon, then select **Disable JIT provisioning**. 1. Select **Disable** to confirm. + +## Next steps + +- Configure [SCIM provisioning](/manuals/enterprise/security/provisioning/scim.md) for advanced user management +- Set up [group mapping](/manuals/enterprise/security/provisioning/group-mapping.md) to automatically assign users to teams +- Review [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md) diff --git a/content/manuals/enterprise/security/provisioning/scim.md b/content/manuals/enterprise/security/provisioning/scim.md index 1b2c36d3355e..1662b310c4f4 100644 --- a/content/manuals/enterprise/security/provisioning/scim.md +++ b/content/manuals/enterprise/security/provisioning/scim.md @@ -1,30 +1,34 @@ --- -keywords: SCIM, SSO, user provisioning, de-provisioning, role mapping, assign users title: SCIM provisioning linkTitle: SCIM description: Learn how System for Cross-domain Identity Management works and how to set it up. +keywords: SCIM, SSO, user provisioning, de-provisioning, role mapping, assign users aliases: - /security/for-admins/scim/ - /docker-hub/scim/ - /security/for-admins/provisioning/scim/ -weight: 30 +weight: 20 --- {{< summary-bar feature_name="SSO" >}} -System for Cross-domain Identity Management (SCIM) is available for Docker -Business customers. This guide provides an overview of SCIM provisioning. +This page shows you how to automate user provisioning and de-provisioning for Docker using System for Cross-domain Identity Management (SCIM). + +## Prerequisites + +- SSO is configured for your organization +- You have administrator access to Docker Home and your identity provider ## How SCIM works SCIM automates user provisioning and de-provisioning for Docker through your -identity provider (IdP). After you enable SCIM, any user assigned to your -Docker application in your IdP is automatically provisioned and added to your +identity provider. After you enable SCIM, any user assigned to your +Docker application in your identity provider is automatically provisioned and added to your Docker organization. When a user is removed from the Docker application in your -IdP, SCIM deactivates and removes them from your Docker organization. +identity provider, SCIM deactivates and removes them from your Docker organization. In addition to provisioning and removal, SCIM also syncs profile updates like -name changes—made in your IdP. You can use SCIM alongside Docker’s default +name changes made in your identity provider. You can use SCIM alongside Docker's default Just-in-Time (JIT) provisioning or on its own with JIT disabled. SCIM automates: @@ -37,19 +41,16 @@ SCIM automates: > [!NOTE] > -> SCIM only manages users provisioned through your IdP after SCIM is enabled. -It cannot remove users who were manually added to your Docker organization -before SCIM was set up. +> SCIM only manages users provisioned through your identity provider after SCIM is enabled. It cannot remove users who were manually added to your Docker organization before SCIM was set up. > > To remove those users, delete them manually from your Docker organization. For more information, see [Manage organization members](/manuals/admin/organization/members.md). ## Supported attributes -SCIM uses attributes (e.g., name, email) to sync user information between your -IdP and Docker. Properly mapping these attributes in your IdP ensures that user -provisioning works smoothly and prevents issues like duplicate user accounts -when using single sign-on (SSO). +SCIM uses attributes (name, email, etc.) to sync user information between your +identity provider and Docker. Properly mapping these attributes in your identity provider ensures that user provisioning works smoothly and prevents issues like duplicate user accounts +when using single sign-on. Docker supports the following SCIM attributes: @@ -72,35 +73,18 @@ SCIM values. > Alternatively, you can disable JIT provisioning to rely solely on SCIM. For details, see [Just-in-Time](just-in-time.md). -## Prerequisites - -- You've [set up SSO](../single-sign-on/_index.md) -with Docker and verified your domain. -- You have access to your identity provider's administrator portal with -permission to create and manage applications. - ## Enable SCIM in Docker -You must [configure SSO](../single-sign-on/configure/_index.md) before you enable SCIM. Enforcing SSO isn't required to use SCIM. +To enable SCIM: -{{< tabs >}} -{{< tab name="Admin Console" >}} - -{{% admin-scim product="admin" %}} - -{{< /tab >}} -{{< tab name="Docker Hub" >}} - -{{% include "hub-org-management.md" %}} - -{{% admin-scim %}} - -{{< /tab >}} -{{< /tabs >}} +1. Sign in to [Docker Home](https://app.docker.com). +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **SSO connections** table, select the **Actions** icon for your conection, then select **Setup SCIM**. +1. Copy the **SCIM Base URL** and **API Token** and paste the values into your IdP. ## Enable SCIM in your IdP -The user interface for your IdP may differ slightly from the following steps. You can refer to the documentation for your IdP to verify. For additional details, see the documentation for your IdP: +The user interface for your identity provider may differ slightly from the following steps. You can refer to the documentation for your identity provider to verify. For additional details, see the documentation for your identity provider: - [Okta](https://help.okta.com/en-us/Content/Topics/Apps/Apps_App_Integration_Wizard_SCIM.htm) - [Entra ID/Azure AD SAML 2.0](https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/user-provisioning) @@ -108,7 +92,7 @@ The user interface for your IdP may differ slightly from the following steps. Yo > [!NOTE] > > Microsoft does not currently support SCIM and OIDC in the same non-gallery -application in Entra ID. This guide provides a verified workaround using a +application in Entra ID. This page provides a verified workaround using a separate non-gallery app for SCIM provisioning. While Microsoft does not officially document this setup, it is widely used and supported in practice. @@ -121,13 +105,13 @@ officially document this setup, it is widely used and supported in practice. 1. Open the application you created when you configured your SSO connection. 1. On the application page, select the **General** tab, then **Edit App Settings**. 1. Enable SCIM provisioning, then select **Save**. -1. Now you can access the **Provisioning** tab in Okta. Navigate to this tab, then select **Edit SCIM Connection**. +1. Navigate to the **Provisioning**, then select **Edit SCIM Connection**. 1. To configure SCIM in Okta, set up your connection using the following values and settings: - - SCIM Base URL: SCIM connector base URL (copied from Docker Hub) + - SCIM Base URL: SCIM connector base URL (copied from Docker Home) - Unique identifier field for users: `email` - Supported provisioning actions: **Push New Users** and **Push Profile Updates** - Authentication Mode: HTTP Header - - SCIM Bearer Token: HTTP Header Authorization Bearer Token (copied from Docker Hub) + - SCIM Bearer Token: HTTP Header Authorization Bearer Token (copied from Docker Home) 1. Select **Test Connector Configuration**. 1. Review the test results and select **Save**. @@ -163,8 +147,8 @@ provisioning. 1. In your new SCIM application, go to **Provisioning** > **Get started**. 1. Set **Provisioning Mode** to **Automatic**. 1. Under **Admin Credentials**: - - **Tenant URL**: Paste the **SCIM Base URL** from Docker. - - **Secret Token**: Paste the **SCIM API token** from Docker. + - **Tenant URL**: Paste the **SCIM Base URL** from Docker Home. + - **Secret Token**: Paste the **SCIM API token** from Docker Home. 1. Select **Test Connection** to verify. 1. Select **Save** to store credentials. @@ -173,15 +157,13 @@ Next, [set up role mapping](#set-up-role-mapping). {{< /tab >}} {{< tab name="Entra ID (SAML 2.0)" >}} -### Configure SCIM provisioning - 1. In the Azure Portal, go to **Microsoft Entra ID** > **Enterprise Applications**, and select your Docker SAML app. 1. Select **Provisioning** > **Get started**. 1. Set **Provisioning Mode** to **Automatic**. 1. Under **Admin Credentials**: - - **Tenant URL**: Paste the **SCIM Base URL** from Docker. - - **Secret Token**: Paste the **SCIM API token** from Docker. + - **Tenant URL**: Paste the **SCIM Base URL** from Docker Home. + - **Secret Token**: Paste the **SCIM API token** from Docker Home. 1. Select **Test Connection** to verify. 1. Select **Save** to store credentials. @@ -211,7 +193,7 @@ The following table lists the supported optional user-level attributes: | `dockerTeam` | Docker `teamName` (e.g., `developers`) | Provisions the user to the specified team in the default or specified organization. If the team doesn't exist, it is automatically created.

You can still use [group mapping](group-mapping.md) to assign users to multiple teams across organizations. | The external namespace used for these attributes is: `urn:ietf:params:scim:schemas:extension:docker:2.0:User`. -This value is required in your IdP when creating custom SCIM attributes for Docker. +This value is required in your identity provider when creating custom SCIM attributes for Docker. {{< tabs >}} {{< tab name="Okta" >}} @@ -222,7 +204,9 @@ This value is required in your IdP when creating custom SCIM attributes for Dock 1. In the Okta admin portal, go to **Directory**, select **Profile Editor**, and then **User (Default)**. 1. Select **Add Attribute** and configure the values for the role, organization, or team you want to add. Exact naming isn't required. 1. Return to the **Profile Editor** and select your application. -1. Select **Add Attribute** and enter the required values. The **External Name** and **External Namespace** must be exact. The external name values for organization/team/role mapping are `dockerOrg`, `dockerTeam`, and `dockerRole` respectively, as listed in the previous table. The external namespace is the same for all of them: `urn:ietf:params:scim:schemas:extension:docker:2.0:User`. +1. Select **Add Attribute** and enter the required values. The **External Name** and **External Namespace** must be exact. + - The external name values for organization/team/role mapping are `dockerOrg`, `dockerTeam`, and `dockerRole` respectively, as listed in the previous table. + - The external namespace is the same for all of them: `urn:ietf:params:scim:schemas:extension:docker:2.0:User`. 1. After creating the attributes, navigate to the top of the page and select **Mappings**, then **Okta User to YOUR APP**. 1. Go to the newly created attributes and map the variable names to the external names, then select **Save Mappings**. If you’re using JIT provisioning, continue to the following steps. 1. Navigate to **Applications** and select **YOUR APP**. @@ -291,14 +275,13 @@ is only compatible with one attribute. #### Direct mapping -Use this method if you need to map multiple attributes (e.g., `dockerRole` + +Use this method if you need to map multiple attributes (`dockerRole` + `dockerTeam`). -1. For each Docker attribute, choose a unique Entra extension attribute (e.g., -`extensionAttribute1`, `extensionAttribute2`, etc.). +1. For each Docker attribute, choose a unique Entra extension attribute (`extensionAttribute1`, `extensionAttribute2`, etc.). 1. In the **Edit Attribute** view: - Set mapping type to **Direct**. - - Set **Source attribute** to your selected extension attribute (e.g., `extensionAttribute1`). + - Set **Source attribute** to your selected extension attribute. - Set **Target attribute** to one of: - `dockerRole: urn:ietf:params:scim:schemas:extension:docker:2.0:User:dockerRole` - `dockerOrg: urn:ietf:params:scim:schemas:extension:docker:2.0:User:dockerOrg` @@ -355,7 +338,6 @@ See the documentation for your IdP for additional details: After completing role mapping, you can test the configuration manually. - {{< tabs >}} {{< tab name="Okta" >}} @@ -385,30 +367,14 @@ and select your SCIM app. If SCIM is disabled, any user provisioned through SCIM will remain in the organization. Future changes for your users will not sync from your IdP. User de-provisioning is only possible when manually removing the user from the organization. -{{< tabs >}} -{{< tab name="Admin Console" >}} - -{{% admin-scim-disable product="admin" %}} - -{{< /tab >}} -{{< tab name="Docker Hub" >}} - -{{% include "hub-org-management.md" %}} - -{{% admin-scim-disable %}} - -{{< /tab >}} -{{< /tabs >}} - -## More resources +To disable SCIM: -The following videos demonstrate how to configure SCIM for your IdP: +1. Sign in to [Docker Home](https://app.docker.com). +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **SSO connections** table, select the **Actions** icon. +1. Select **Disable SCIM**. -- [Video: Configure SCIM with Okta](https://youtu.be/c56YECO4YP4?feature=shared&t=1314) -- [Video: Attribute mapping with Okta](https://youtu.be/c56YECO4YP4?feature=shared&t=1998) -- [Video: Configure SCIM with Entra ID/Azure AD](https://youtu.be/bGquA8qR9jU?feature=shared&t=1668) -- [Video: Attribute and group mapping with Entra ID/Azure AD](https://youtu.be/bGquA8qR9jU?feature=shared&t=2039) -Refer to the following troubleshooting guide if needed: +## Next steps - [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md) diff --git a/content/manuals/enterprise/security/roles-and-permissions.md b/content/manuals/enterprise/security/roles-and-permissions.md index 3c79802a3b4c..d64f61681deb 100644 --- a/content/manuals/enterprise/security/roles-and-permissions.md +++ b/content/manuals/enterprise/security/roles-and-permissions.md @@ -1,7 +1,7 @@ --- -description: Use roles in your organization to control who has access to content, registry, and organization management permissions. -keywords: members, teams, organization, company, roles, access, docker hub, admin console, security title: Roles and permissions +description: Control access to content, registry, and organization management with roles in your organization. +keywords: members, teams, organization, company, roles, access, docker hub, admin console, security, permissions aliases: - /docker-hub/roles-and-permissions/ - /security/for-admins/roles-and-permissions/ @@ -10,44 +10,25 @@ weight: 40 {{< summary-bar feature_name="General admin" >}} -This guide outlines Docker's organization roles and their permission scopes. +Roles control what users can do in your organization. When you invite users, you assign them a role that determines their permissions for repositories, teams, and organization settings. -## Roles +## Organization roles -When you invite users to your organization, you assign them a role. A role is a -collection of permissions. Roles define whether users can create repositories, -pull images, create teams, and configure organization settings. +Docker organizations have three main roles: -The following roles are available to assign: +- Member: Non-administrative role with basic access. Members can view other organization members and pull images from repositories they have access to. +- Editor: Partial administrative access. Editors can create, edit, and delete repositories. They can also manage team permissions for repositories. +- Owner: Full administrative access. Owners can manage all organization settings, including repositories, teams, members, billing, and security features. -- Member: Non-administrative role. Members can view other members that are in -the same organization. -- Editor: Partial administrative access to the organization. Editors can -create, edit, and delete repositories. They can also edit an existing team's -access permissions. -- Owner: Full organization administrative access. Owners can manage organization -repositories, teams, members, settings, and billing. - -Owners can manage roles for members of an organization using Docker Hub or the Admin Console: - -- Update a member role in [Docker Hub](/manuals/admin/organization/members.md#update-a-member-role) -- Update an organization's members or company in the [Admin Console](/manuals/admin/company/users.md#update-a-member-role) -- Learn more about [organizations and companies](/manuals/admin/_index.md) - -## Permissions +## Permissions by role > [!NOTE] > -> Company owners have the same access as owners for all associated organizations. For more information, see [Company overview](/admin/company/). - -The following sections describe the permissions for each role. +> An owner role assigned at the company level has the same access as an owner role assigned at the organization level. For more information, see [Company overview](/admin/company/). ### Content and registry permissions -The following table outlines content and registry permissions for member, -editor, and owner roles. These permissions and roles apply to the entire -organization, including all the repositories in the namespace for the -organization. +These permissions apply organization-wide, including all repositories in your organization's namespace. | Permission | Member | Editor | Owner | | :---------------------------------------------------- | :----- | :----- | :----------------- | @@ -66,22 +47,17 @@ organization. | View teams | ✅ | ✅ | ✅ | | Assign team permissions to repositories | ❌ | ✅ | ✅ | -When you add members to a team, you can manage their repository permissions. -For team repository permissions, see [Create and manage a team permissions reference](/manuals/admin/organization/manage-a-team.md#permissions-reference). +When you add members to teams, you can grant additional repository permissions +beyond their organization role. The following diagram shows how permissions +work: -The following diagram provides an example of how permissions may work for a -user. In this example, the first permission check is for the role: member or -editor. Editors have administrative permissions for repositories across the -namespace of the organization. Members may have administrative permissions for -a repository if they're a member of a team that grants those permissions. +1. Role permissions: Applied organization-wide (member or editor) +2. Team permissions: Additional permissions for specific repositories ![User repository permissions within an organization](../images/roles-and-permissions-member-editor-roles.png) ### Organization management permissions -The following table outlines organization management permissions for member, -editor, owner, and company owner roles. - | Permission | Member | Editor | Owner | | :---------------------------------------------------------------- | :----- | :----- | :----------------- | | Create teams | ❌ | ❌ | ✅ | @@ -108,9 +84,6 @@ _\* If not part of a company_ ### Docker Scout permissions -The following table outlines Docker Scout management permissions for member, -editor, and owner roles. - | Permission | Member | Editor | Owner | | :---------------------------------------------------- | :----- | :----- | :----------------- | | View and compare analysis results | ✅ | ✅ | ✅ | @@ -121,9 +94,6 @@ editor, and owner roles. ### Docker Build Cloud permissions -The following table outlines Docker Build Cloud management permissions for -member, editor, and owner roles. - | Permission | Member | Editor | Owner | | ---------------------------- | :----- | :----- | :----------------- | | Use a cloud builder | ✅ | ✅ | ✅ | diff --git a/content/manuals/enterprise/security/single-sign-on/_index.md b/content/manuals/enterprise/security/single-sign-on/_index.md index ba0cb4a254a9..9e2772969d69 100644 --- a/content/manuals/enterprise/security/single-sign-on/_index.md +++ b/content/manuals/enterprise/security/single-sign-on/_index.md @@ -1,8 +1,8 @@ --- -description: Learn how single sign-on works, how to set it up, and the required SSO attributes. -keywords: Single Sign-On, SSO, sign-on, admin, docker hub, admin console, security title: Single sign-on overview linkTitle: Single sign-on +description: Learn how single sign-on works, how to set it up, and the required SSO attributes. +keywords: Single Sign-On, SSO, sign-in, admin, docker hub, admin console, security, indentity provider, SSO configuration, enterprise login, Docker Business, user authentication aliases: - /single-sign-on/ - /admin/company/settings/sso/ @@ -13,40 +13,60 @@ weight: 10 {{< summary-bar feature_name="SSO" >}} -Single sign-on (SSO) lets users access Docker by authenticating using their identity providers (IdPs). SSO is available for a whole company, and all associated organizations within that company, or an individual organization that has a Docker Business subscription. To upgrade your existing account to a Docker Business subscription, see [Upgrade your subscription](/manuals/subscription/change.md). +Single sign-on (SSO) lets users access Docker by authenticating through their +identity providers (IdPs). SSO can be configured for an entire company, +including all associated organizations, or for a single organization that has a +Docker Business subscription. To upgrade, see +[Upgrade your subscription](/manuals/subscription/change.md). ## How SSO works -When you enable SSO, Docker supports a non-IdP-initiated SSO flow for user login. Instead of users authenticating using their Docker username and password, they are redirected to your identity provider's authentication page to sign in. Users must sign in to Docker Hub or Docker Desktop to initiate the SSO authentication process. +When SSO is enabled, Docker supports a non-IdP-initiated flow for user sign-in. +Instead of signing in with a Docker username and password, users are redirected +to your IdP’s sign-in page. Users must initiate the SSO authentication process +by signing in to Docker Hub or Docker Desktop. -The following diagram shows how SSO operates and is managed in Docker Hub and Docker Desktop. In addition, it provides information on how to authenticate between your IdP. +The following diagram illustrates how SSO operates and is managed between +Docker Hub, Docker Desktop, and your IdP. ![SSO architecture](images/SSO.png) -## How to set it up +## Set up SSO + +To configure SSO in Docker, follow these steps: -SSO is configured using the following steps: -1. [Configure SSO](configure.md) by creating and verifying a domain in Docker. -2. [Create your SSO connection](connect.md) in Docker and your IdP. -3. Cross-connect Docker and your IdP. -4. Test your connection. -5. Provision users. -6. Optional. [Enforce sign-in](../enforce-sign-in/_index.md). -7. [Manage your SSO configuration](manage.md). +1. [Configure your domain](configure.md) by creating and verifying it. +1. [Create your SSO connection](connect.md) in Docker and your IdP. +1. Link Docker to your identity provider. +1. Test your SSO connection. +1. Provision users in Docker. +1. Optional. [Enforce sign-in](../enforce-sign-in/_index.md). +1. [Manage your SSO configuration](manage.md). -Once your SSO configuration is complete, a first-time user can sign in to Docker Hub or Docker Desktop using their company's domain email address. Once they sign in, they are added to your company, assigned to an organization, and if necessary, assigned to a team. +Once configuration is complete, users can sign in to Docker services using +their company email address. After signing in, users are added to your company, +assigned to an organization, and added to a team. ## Prerequisites -Before configuring SSO, ensure you meet the following prerequisites: -* Notify your company about the new SSO sign in procedures. -* Verify that all users have Docker Desktop version 4.4.2 or later installed. -* If your organization is planning to [enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso), members using the Docker CLI are required to [create a Personal Access Token (PAT)](/docker-hub/access-tokens/). The PAT will be used instead of their username and password. Docker plans to deprecate signing in to the CLI with a password in the future, so using a PAT will be required to prevent issues with authentication. For more details see the [security announcement](/manuals/security/security-announcements.md#deprecation-of-password-logins-on-cli-when-sso-enforced). -* Ensure all your Docker users have a valid user on your IdP with the same email address as their Unique Primary Identifier (UPN). -* Confirm that all CI/CD pipelines have replaced their passwords with PATs. -* For your service accounts, add your additional domains or enable it in your IdP. +Before you begin, make sure the following conditions are met: + +- Notify your company about the upcoming SSO sign-in process. +- Ensure all users have Docker Desktop version 4.42 or later installed. +- Confirm that each Docker user has a valid IdP account using the same +email address as their Unique Primary Identifier (UPN). +- If you plan to [enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso), +users accessing Docker through the CLI must [create a personal access token (PAT)](/docker-hub/access-tokens/). The PAT replaces their username and password for authentication. +- Ensure CI/CD pipelines use PATs or OATs instead of passwords. + +> [!IMPORTANT] +> +> Docker plans to deprecate CLI password-based sign-in in future releases. +Using a PAT ensures continued CLI access. For more information, see the +[security announcement](/manuals/security/security-announcements.md#deprecation-of-password-logins-on-cli-when-sso-enforced). ## What's next? -- Start [configuring SSO](configure.md) in Docker -- Explore the [FAQs](/manuals/security/faqs/_index.md) +- Start [configuring SSO](configure.md) +- Read the FAQs [FAQs](/manuals/security/faqs/_index.md) +- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues diff --git a/content/manuals/enterprise/security/single-sign-on/configure.md b/content/manuals/enterprise/security/single-sign-on/configure.md index 7630928572d0..6dfa9cf9f311 100644 --- a/content/manuals/enterprise/security/single-sign-on/configure.md +++ b/content/manuals/enterprise/security/single-sign-on/configure.md @@ -1,8 +1,8 @@ --- -description: Learn how to configure single sign-on for your organization or company. -keywords: configure, sso, docker hub, hub, docker admin, admin, security title: Configure single sign-on linkTitle: Configure +description: Learn how to configure single sign-on for your organization or company. +keywords: configure, sso, docker hub, hub, docker admin, admin, security aliases: - /docker-hub/domains/ - /docker-hub/sso-connection/ @@ -15,92 +15,67 @@ aliases: {{< summary-bar feature_name="SSO" >}} -Get started creating a single sign-on (SSO) connection for your organization or company. This guide walks through the steps to add and verify the domains your members use to sign in to Docker. +Learn how to set up single sign-on (SSO) for your Docker organization by adding +and verifying the domains your members use to sign in. -## Step one: Add your domain +## Step one: Add a domain > [!NOTE] > -> Docker supports multiple identity provider (IdP) configurations. With a multiple IdP configuration, one domain can be associated with more than one SSO identity provider. - -{{< tabs >}} -{{< tab name="Admin Console" >}} +> Docker supports multiple identity provider (IdP) configurations. You can +associate one domain with more than one IdP. 1. Sign in to [Docker Home](https://app.docker.com) and choose your -organization. Note that when an organization is part of a company, you must -select the company and configure the domain for the organization at the company level. +organization. If it's part of a company, select the company first to manage +the domain at that level. 1. Select **Admin Console**, then **Domain management**. 1. Select **Add a domain**. 1. Enter your domain in the text box and select **Add domain**. -1. The pop-up modal will prompt you with steps to verify your domain. Copy the **TXT Record Value**. - -{{< /tab >}} -{{< tab name="Docker Hub" >}} - -{{% include "hub-org-management.md" %}} - -1. Sign in to [Docker Hub](https://hub.docker.com/). -1. Select **My Hub** and then your organization from the list. -1. On your organization page, select **Settings** and then **Security**. -1. Select **Add a domain**. -1. Enter your domain in the text box and select **Add domain**. -1. The pop-up modal will prompt you with steps to verify your domain. Copy the **TXT Record Value**. - -{{< /tab >}} -{{< /tabs >}} +1. In the modal, copy the **TXT Record Value** provided for domain verification. ## Step two: Verify your domain -Verifying your domain ensures Docker knows you own it. To verify, you add a TXT record to your Domain Name System (DNS) host using the value Docker provides. The TXT Record Value proves ownership, which signals the DNS to add this record. It can take up to 72 hours for DNS to recognize the change. When the change is reflected in DNS, Docker automatically checks the record to confirm your ownership. - -Use the **TXT Record Value** provided by Docker and follow the steps based on your DNS host. If your provider isn't listed, use the instructions for other providers. +To confirm domain ownership, add a TXT record to your Domain Name System (DNS) +host using the TXT Record Value from Docker. DNS propagation can take up to +72 hours. Docker automatically checks for the record during this time. > [!TIP] > -> The record name field controls where the TXT record is applied in your domain, for example root or subdomain. In general, refer to the following tips for adding a record name: +> Use these guidelines when adding a record name: > -> - Use `@` or leave the record name empty for root domains like `example.com`, depending on your provider. -> - Don't enter values like `docker`, `docker-verification`, `www`, or your domain name. These values may direct to the wrong place. -> -> Check your DNS provider's documentation to verify record name requirements. +> - Use `@` or leave the record name empty for root domains like `example.com`. +> - Avoid values like `docker`, `docker-verification`, `www`, or your domain name itself. +> - Check your DNS provider's documentation to verify record name requirements. {{< tabs >}} {{< tab name="AWS Route 53" >}} 1. To add your TXT record to AWS, see [Creating records by using the Amazon Route 53 console](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html). -1. TXT record verification can take 72 hours. Once you have waited for TXT record verification, return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. +1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< tab name="Google Cloud DNS" >}} 1. To add your TXT record to Google Cloud DNS, see [Verifying your domain with a TXT record](https://cloud.google.com/identity/docs/verify-domain-txt). -1. TXT record verification can take 72 hours. Once you have waited for TXT record verification, return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. +1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< tab name="GoDaddy" >}} 1. To add your TXT record to GoDaddy, see [Add a TXT record](https://www.godaddy.com/help/add-a-txt-record-19232). -1. TXT record verification can take 72 hours. Once you have waited for TXT record verification, return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. +1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< tab name="Other providers" >}} 1. Sign in to your domain host. 1. Add a TXT record to your DNS settings and save the record. -1. TXT record verification can take 72 hours. Once you have waited for TXT record verification, return to the **Domain management** page of the [Admin Console](https://app.docker.com/admin) and select **Verify** next to your domain name. +1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< /tabs >}} -Once you have added and verified your domain, you are ready to create an SSO connection between Docker and your identity provider (IdP). - -## More resources - -The following videos walk through verifying your domain to create your SSO connection in Docker. - -- [Video: Verify your domain for SSO with Okta](https://youtu.be/c56YECO4YP4?feature=shared&t=529) -- [Video: Verify your domain for SSO with Azure AD (OIDC)](https://youtu.be/bGquA8qR9jU?feature=shared&t=496) - -## What's next? +## Next steps -[Connect Docker and your IdP](connect.md). +- [Connect Docker and your IdP](connect.md) +- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues diff --git a/content/manuals/enterprise/security/single-sign-on/connect.md b/content/manuals/enterprise/security/single-sign-on/connect.md index 85f50dcde1fa..9bb91701ad6a 100644 --- a/content/manuals/enterprise/security/single-sign-on/connect.md +++ b/content/manuals/enterprise/security/single-sign-on/connect.md @@ -1,89 +1,68 @@ --- -description: Learn how to complete your single-sign on connection and next steps for enabling SSO. -keywords: configure, sso, docker hub, hub, docker admin, admin, security -title: Create an SSO connection +title: Connect single sign-on linkTitle: Connect +description: Connect Docker and your identity provider, test the setup, and enable enforcement +keywords: configure sso, set up sso, docker sso setup, docker identity provider, sso enforcement, docker hub, security aliases: - /security/for-admins/single-sign-on/connect/ --- {{< summary-bar feature_name="SSO" >}} -Creating a single sign-on (SSO) connection requires setting up the connection in Docker first, followed by setting up the connection in your identity provider (IdP). This guide provides steps for setting up your SSO connection in Docker and your IdP. +Setting up a single sign-on (SSO) connection involves configuring both Docker +and your identity provider (IdP). This guide walks you through each step: setup +in Docker, setup in your IdP, and final connection. > [!TIP] > -> This guide requires copying and pasting values in both Docker and your IdP. To ensure a seamless connection process, complete all the steps in this guide in one session and keep separate browsers open for both Docker and your IdP. +> You’ll copy and paste values between Docker and your IdP. Complete this guide +in one session with separate browser windows open for Docker and your IdP. ## Prerequisites -Make sure you have completed the following before you begin: +Before you begin: -- Your domain is verified -- You have an account set up with an IdP -- You have completed the steps in the [Configure single sign-on](configure.md) guide +- Verify your domain +- Set up an account with your identity provider (IdP) +- Complete the steps in the [Configure single sign-on](configure.md) guide ## Step one: Create an SSO connection in Docker >[!NOTE] > -> Before creating an SSO connection in Docker, you must verify at least one domain. - -{{< tabs >}} -{{< tab name="Admin Console" >}} +> You must verify at least one domain before creating an SSO connection. 1. Sign in to [Docker Home](https://app.docker.com) and choose your -organization. Note that when an organization is part of a company, you must -select the company and configure the domain for the organization at the company level. +organization. 1. Select **Admin Console**, then **SSO and SCIM**. 1. Select **Create Connection** and provide a name for the connection. -1. Select an authentication method, **SAML** or **Azure AD (OIDC)**. -1. Copy the following fields to add to your IdP: - - Okta SAML: **Entity ID**, **ACS URL** - - Azure OIDC: **Redirect URL** -1. Keep this window open so you can paste the connection information from your IdP here at the end of this guide. - -{{< /tab >}} -{{< tab name="Docker Hub" >}} - -{{% include "hub-org-management.md" %}} - -1. Sign in to Docker Hub. -1. Select **My Hub** and then your organization from the list. -1. On your organization page, select **Settings** and then **Security**. -1. In the SSO connection table, select **Create Connection** and provide a name for the connection. -1. Select an authentication method, **SAML** or **Azure AD (OIDC)**. -1. Copy the following fields to add to your IdP: +1. Select an authentication method: **SAML** or **Azure AD (OIDC)**. +1. Copy the required values for your IdP: - Okta SAML: **Entity ID**, **ACS URL** - Azure OIDC: **Redirect URL** -1. Keep this window open so you can paste the connection information from your IdP here at the end of this guide. -{{< /tab >}} -{{< /tabs >}} +Keep this window open to paste values from your IdP later. ## Step two: Create an SSO connection in your IdP -The user interface for your IdP may differ slightly from the following steps. Refer to the documentation for your IdP to verify. +Use the following tabs based on your IdP provider. {{< tabs >}} {{< tab name="Okta SAML" >}} -1. Sign in to your Okta account. -1. Select **Admin** to open the Okta Admin portal. -1. From the left-hand navigation, select **Administration**. +1. Sign in to your Okta account and open the Admin portal. 1. Select **Administration** and then **Create App Integration**. -1. Select **SAML 2.0** and then **Next**. -1. Enter "Docker Hub" as your **App Name**. +1. Select **SAML 2.0**, then **Next**. +1. Name your app "Docker". 1. Optional. Upload a logo. -1. Select **Next**. -1. Enter the following values from Docker into their corresponding Okta fields: - - Docker ACS URL: **Single Sign On URL** - - Docker Entity ID: **Audience URI (SP Entity ID)** -1. Configure the following settings in Okta: +1. Paste values from Docker: + - Docker ACS URL -> **Single Sign On URL** + - Docker Entity ID -> **Audience URI (SP Entity ID)** +1. Configure the following settings: - Name ID format: `EmailAddress` - Application username: `Email` - Update application on: `Create and update` -1. Optional. Add SAML attributes. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes) for a table of SSO attributes. +1. Optional. Add SAML attributes. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes). 1. Select **Next**. 1. Select the **This is an internal app that we have created** checkbox. 1. Select **Finish**. @@ -91,162 +70,134 @@ The user interface for your IdP may differ slightly from the following steps. Re {{< /tab >}} {{< tab name="Entra ID SAML 2.0" >}} -1. Sign in to your Azure AD admin portal. -1. Select **Default Directory** and then **Add**. -1. Choose **Enterprise Application** and select **Create your own application**. -1. Enter "Docker" for application name and select the **non-gallery** option. -1. After the application is created, go to **Single Sign-On** and select **SAML**. +1. Sign in to Microsoft Entra (formerly Azure AD). +1. Select **Default Directory** > **Add** > **Enterprise Application**. +1. Choose **Create your own application**, name it "Docker", and choose **Non-gallery**. +1. After creating your app, go to **Single Sign-On** and select **SAML**. 1. Select **Edit** on the **Basic SAML configuration** section. -1. Enter the following values from Docker into their corresponding Azure fields: - - Docker Entity ID: **Identifier** - - Docker ACS URL: **Reply URL** -1. Optional. Add SAML attributes. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes) for a table of SSO attributes. -1. Save configuration. +1. Edit **Basic SAML configuration** and paste values from Docker: + - Docker Entity ID -> **Identifier** + - Docker ACS URL -> **Reply URL** +1. Optional. Add SAML attributes. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes). +1. Save the configuration. 1. From the **SAML Signing Certificate** section, download your **Certificate (Base64)**. {{< /tab >}} {{< tab name="Azure Connect (OIDC)" >}} -To create an Azure Connect (OIDC) connection, you must create an app registration, client secrets, and configure API permissions for Docker: - -### Create app registration +### Register the app -1. Sign in to your Azure AD admin portal. -1. Select **App Registration** and then **New Registration**. -1. Enter "Docker Hub SSO" or similar for application name. -1. Under **Supported account types**, specify who can use this application or access the app. -1. In the **Redirect URI** section, select **Web** from the drop-down menu and paste the **Redirect URI** value from the Docker console into this field. -1. Select **Register** to register the app. -1. Copy the **Client ID** from the app's overview page. You need this information to continue configuring SSO in Docker. +1. Sign in to Microsoft Entra (formerly Azure AD). +1. Select **App Registration** > **New Registration**. +1. Name the application "Docker". +1. Set account types and paste the **Redirect URI** from Docker. +1. Select **Register**. +1. Copy the **Client ID**. ### Create client secrets -1. Open your app in Azure AD and select **Certificates & secrets**. -1. Select **+ New client secret**. -1. Specify the description of the secret and set how long keys can be used. -1. Select **Add** to continue. -1. Copy the secret **Value** field. You need this to continue configuring SSO in Docker. +1. In your app, go to **Certificates & secrets**. +1. Select **New client secret**, describe and configure duration, then **Add**. +1. Copy the **value** of the new secret. -### Configure API permissions +### Set API permissions -1. Open your app in Azure AD and navigate to your app settings. -1. Select **API permission** and then **Grant admin consent for [your tenant name]**. -1. Select **Yes** to confirm. -1. After confirming, select **Add a permission** and then **Delegated permissions**. -1. Search for `User.Read` and select this option. -1. Select **Add permissions** to confirm. -1. Verify admin consent was granted for each permission by checking the **Status** column. +1. In your app, go to **API permissions**. +1. Select **Grant admin consent** and confirm. +1. Select **Add a permissions** > **Delegated permissions**. +1. Search and select `User.Read`. +1. Confirm that admin consent is granted. {{< /tab >}} {{< /tabs >}} -## Step three: Connect Docker and your IdP +## Step three: Connect Docker to your IdP -After creating your connection in Docker and your IdP, you can cross-connect them to complete your SSO connection: +Complet the integration by pasting your IdP values into Docker. {{< tabs >}} {{< tab name="Okta SAML" >}} -1. Open your app you created in Okta and select **View SAML setup instructions**. -1. Copy the following values from the Okta SAML setup instruction page: - - **SAML Sign-in URL** - - **x509 Certificate** +1. In Okta, select your app and go to **View SAML setup instructions**. +1. Copy the **SAML Sign-in URL** and **x509 Certificate**. - > [!IMPORTANT] - > - > You must copy the entire contents of your **x509 Certificate**, - including the `----BEGIN CERTIFICATE----` and `----END CERTIFICATE----` lines. - -1. Open Docker Hub or the Admin Console. Your SSO configuration page should still be open from Step one of this guide. -1. Select **Next** to open the **Update single-sign on connection** page. -1. Paste your Okta **SAML Sign-in URL** and **x509 Certificate** values in Docker. -1. Select **Next**. -1. Optional. Select a default team to provision users to and select **Next**. -1. Verify your SSO connection details and select **Create Connection**. + > [!IMPORTANT] + > + > Copy the entire certificate, including `----BEGIN CERTIFICATE----` and `----END CERTIFICATE----` lines. +1. Return to the Docker Admin Console. +1. Paste the **SAML Sign-in URL** and **x509 Certificate** values. +1. Optional. Select a default team. +1. Review and select **Create connection**. {{< /tab >}} {{< tab name="Entra ID SAML 2.0" >}} -1. Open your app in Azure AD. 1. Open your downloaded **Certificate (Base64)** in a text editor. 1. Copy the following values: - From Azure AD: **Login URL** - - Copy the contents of your **Certificate (Base64)** file from your text editor - - > [!IMPORTANT] - > - > You must copy the entire contents of your **Certificate (base64)**, - including the `----BEGIN CERTIFICATE----` and `----END CERTIFICATE----` lines. + - **Certificate (Base64)** contents -1. Open Docker Hub or the Admin Console. Your SSO configuration page should still be open from Step one of this guide. -1. Paste your **Login URL** and **Certificate (Base64)** values in Docker. -1. Select **Next**. -1. Optional. Select a default team to provision users to and select **Next**. -1. Verify your SSO connection details and select **Create Connection**. + > [!IMPORTANT] + > + > Copy the entire certificate, including `----BEGIN CERTIFICATE----` and `----END CERTIFICATE----` lines. +1. Return to the Docker Admin Console. +1. Paste the **Login URL** and **Certificate (Base64)** values. +1. Optional. Select a default team. +1. Review and select **Create connection**. {{< /tab >}} {{< tab name="Azure Connect (OIDC)" >}} -1. Open Docker Hub or the Admin Console. Your SSO configuration page should still be open from Step one of this guide. -1. Paste the following values from Azure AD in to Docker: +1. Return to the Docker Admin Console. +1. Paste the following values: - **Client ID** - **Client Secret** - **Azure AD Domain** -1. Select **Next**. -1. Optional. Select a default team to provision users to and select **Next**. -1. Verify your SSO connection details and select **Create Connection**. +1. Optional. Select a default team. +1. Review and select **Create connection**. {{< /tab >}} {{< /tabs >}} -## Step four: Test your connection - -After you've completed the SSO connection process in Docker, we recommend testing it: +## Step four: Test the connection -1. Open an incognito browser. +1. Open an incognito browser window. 1. Sign in to the Admin Console using your **domain email address**. 1. The browser will redirect to your identity provider's sign in page to authenticate. If you have [multiple IdPs](#optional-configure-multiple-idps), choose the sign sign-in option **Continue with SSO**. 1. Authenticate through your domain email instead of using your Docker ID. -You can also test your SSO connection through the command-line interface (CLI). If you want to test through the CLI, your users must have a personal access token (PAT). +If you're using the CLI, you must authenticate using a personal access token. ## Optional: Configure multiple IdPs -Docker supports multiple IdP configurations. With multiple IdPs configured, one domain can be associated with multiple SSO identity providers. To configure multiple IdPs, repeat steps 1-4 in this guide for each IdP. Ensure each IdP configuration uses the same domain. +Docker supports multiple IdP configurations. To use multiple IdPs with one domain: -When a user signs in to a Docker organization that has multiple IdPs, on the sign-in page, they must choose the option **Continue with SSO**. This prompts them to choose their identity provider and authenticate through their domain email. +- Repeat Steps 1-4 for each IdP. +- Each connection must use the same domain. +- Users will select **Continue with SSO** to choose their IdP at sign in. ## Optional: Enforce SSO > [!IMPORTANT] > -> If SSO isn't enforced, users can choose to sign in with either their Docker username and password or SSO. +> If SSO is not enforced, users can still sign in using Docker usernames and passwords. Enforcing SSO requires users to use SSO when signing into Docker. This centralizes authentication and enforces policies set by the IdP. 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. Note that when an organization is part of a company, you must select the company and configure the domain for the organization at the company level. 1. Select **Admin Console**, then **SSO and SCIM**. -1. In the SSO connections table, select the **Action** icon and then **Enable enforcement**. When SSO is enforced, your users are unable to modify their email address and password, convert a user account to an organization, or set up 2FA through Docker Hub. If you want to use 2FA, you must enable 2FA through your IdP. -1. Continue with the on-screen instructions and verify you've completed all tasks. -1. Select **Turn on enforcement** to complete. - -Your users must now sign in to Docker with SSO. - -> [!NOTE] -> -> When SSO is enforced, [users can't use passwords to access the Docker CLI](/manuals/security/security-announcements.md#deprecation-of-password-logins-on-cli-when-sso-enforced). Users must use a [personal access token](/manuals/enterprise/security/access-tokens.md) (PAT) for authentication to access the Docker CLI. - -## More resources - -The following videos demonstrate how to enforce SSO. - -- [Video: Enforce SSO with Okta SAML](https://youtu.be/c56YECO4YP4?feature=shared&t=1072) -- [Video: Enforce SSO with Azure AD (OIDC)](https://youtu.be/bGquA8qR9jU?feature=shared&t=1087) +1. In the SSO connections table, select the **Action** menu, then **Enable enforcement**. +1. Follow the on-screen instructions. +1. Select **Turn on enforcement**. +When SSO is enforced, your users are unable to modify their email address and +password, convert a user account to an organization, or set up 2FA through +Docker Hub. If you want to use 2FA, you must enable 2FA through your IdP. -## What's next +## Next steps - [Provision users](/manuals/enterprise/security/provisioning/_index.md) - [Enforce sign-in](../enforce-sign-in/_index.md) - [Create access tokens](/manuals/enterprise/security/access-tokens.md) +- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues diff --git a/content/manuals/enterprise/security/single-sign-on/manage.md b/content/manuals/enterprise/security/single-sign-on/manage.md index e3cbbbfaf79b..71433516362a 100644 --- a/content/manuals/enterprise/security/single-sign-on/manage.md +++ b/content/manuals/enterprise/security/single-sign-on/manage.md @@ -1,8 +1,8 @@ --- -description: Learn how to manage Single Sign-On for your organization or company. -keywords: manage, single sign-on, SSO, sign-on, docker hub, admin console, admin, security title: Manage single sign-on linkTitle: Manage +description: Learn how to manage Single Sign-On for your organization or company. +keywords: manage, single sign-on, SSO, sign-on, admin console, admin, security, domains, connections, users, provisioning aliases: - /admin/company/settings/sso-management/ - /single-sign-on/manage/ @@ -11,65 +11,121 @@ aliases: {{< summary-bar feature_name="SSO" >}} +This page covers how to manage single sign-on (SSO) after initial setup, +including managing organizations, domains, connections, users, and provisioning +settings. + ## Manage organizations > [!NOTE] > > You must have a [company](/admin/company/) to manage more than one organization. -{{% admin-sso-management-orgs product="admin" %}} +To manage SSO for organizations in your company: + +1. Sign in to [Docker Home](https://app.docker.com) and select your company. +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **Organizations** section, you can: + + - View all organizations in your company + - Turn SSO on or off for each organization + - Configure organization-specific SSO settings ## Manage domains -{{< tabs >}} -{{< tab name="Admin Console" >}} +### Add a domain -{{% admin-sso-management product="admin" %}} +To add a domain to an existing SSO connection: -{{< /tab >}} -{{< tab name="Docker Hub" >}} +1. Sign in to [Docker Home](https://app.docker.com) and select your company or +organization. +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the SSO connections table, select the **Actions** menu for your +connection, then select **Edit connection**. +1. Select **Next** to navigate to the domains section. +1. In the **Domains** section, select **Add domain**. +1. Enter the domain you want to add to the connection. +1. Select **Next** to confirm or change the connected organizations. +1. Select **Next** to confirm or change the default organization and +team provisioning selections. +1. Review the connection details and select **Update connection**. -{{% include "hub-org-management.md" %}} +### Remove a domain from an SSO connection -{{% admin-sso-management product="hub" %}} +> [!IMPORTANT] +> +> If you use multiple identity providers with the same domain, you must remove the domain from each SSO connection individually. + +1. Sign in to [Docker Home](https://app.docker.com) and select your company or organization. +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **SSO connections** table, select the **Actions** menu for your connection, then +**Edit connection**. +1. Select **Next** to navigate to the domains section. +1. In the **Domain** section, select the **X** icon next to the domain +you want to remove. +1. Select **Next** to confirm or change the connected organizations. +1. Select **Next** to confirm or change the default organization and +team provisioning selections. +1. Review the connection details and select **Update connection**. -{{< /tab >}} -{{< /tabs >}} +> [!NOTE] +> +> When you re-add a domain, Docker assigns a new TXT record value. You must complete domain verification again with the new TXT record. ## Manage SSO connections -{{< tabs >}} -{{< tab name="Admin Console" >}} +### View connections -{{% admin-sso-management-connections product="admin" %}} +To view all configured SSO connections: -{{< /tab >}} -{{< tab name="Docker Hub" >}} +1. Sign in to [Docker Home](https://app.docker.com) and select your company or organization. +1. Select **Admin Console**, then **SSO and SCIM**. +1. View all configured connections in the **SSO connections** table. -{{% include "hub-org-management.md" %}} +### Edit a connection -{{% admin-sso-management-connections product="hub" %}} +To modify an existing SSO connection: -{{< /tab >}} -{{< /tabs >}} +1. Sign in to [Docker Home](https://app.docker.com) and select your company or organization. +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **SSO connections** table, select the **Actions** menu for your connection, then +**Edit connection**. +1. Follow the on-screen instructions to modify your connection settings. -## Manage users +### Delete a connection -> [!IMPORTANT] -> -> SSO has Just-In-Time (JIT) Provisioning enabled by default unless you have [disabled it](../provisioning/just-in-time/#sso-authentication-with-jit-provisioning-disabled). This means your users are auto-provisioned to your organization. -> -> You can change this on a per-app basis. To prevent auto-provisioning users, you can create a security group in your IdP and configure the SSO app to authenticate and authorize only those users that are in the security group. Follow the instructions provided by your IdP: -> -> - [Okta](https://help.okta.com/en-us/Content/Topics/Security/policies/configure-app-signon-policies.htm) -> - [Entra ID (formerly Azure AD)](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-restrict-your-app-to-a-set-of-users) +To remove an SSO connection: + +1. Sign in to [Docker Home](https://app.docker.com) and select your company or organization. +1. Select **Admin Console**, then **SSO and SCIM**. +1. In the **SSO connections** table, select the **Actions** menu for your connection, then +**Delete connection**. +1. Follow the on-screen instructions to confirm the deletion. + +> [!WARNING] > -> Alternatively, see the [Provisioning overview](../provisioning/_index.md) guide. +> Deleting an SSO connection removes access for all users who authenticate through +that connection. + +## Manage users and provisioning + +Docker automatically provisions users through Just-in-Time (JIT) provisioning when they sign in via SSO. You can also manually manage users and configure different provisioning methods. + +### How provisioning works + +Docker supports the following provisioning methods: +- JIT provisioning (default): Users are automatically added to your organization +when they sign in via SSO +- SCIM provisioning: Sync users and groups from your identity provider to Docker +- Group mapping: Sync user groups from your identity provider with teams in your Docker organization +- Manual provisioning: Turn off automatic provisioning and manually invite users -### Add guest users when SSO is enabled +For more information on provisioning methods, see [Provision users](/manuals/enterprise/security/provisioning/_index.md). -To add a guest that isn't verified through your IdP: +### Add guest users + +To invite users who don't authenticate through your identity provider: 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. @@ -77,22 +133,17 @@ your organization. 1. Select **Invite**. 1. Follow the on-screen instructions to invite the user. -### Remove users from the SSO company +The uesr receives an email invitation and can create a Docker account or sign +in with their existing account. + +### Remove users -To remove a user: +To remove a user from your organization: 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. 1. Select **Members**. -1. Select the action icon next to a user’s name, and then select **Remove member**, if you're an organization, or **Remove user**, if you're a company. -1. Follow the on-screen instructions to remove the user. - -## Manage provisioning - -Users are provisioned with Just-in-Time (JIT) provisioning by default. If you enable SCIM, you can disable JIT. For more information, see the [Provisioning overview](../provisioning/_index.md) guide. - -## What's next? - -- [Set up SCIM](../provisioning/scim.md) -- [Enable Group mapping](../provisioning/group-mapping.md) +1. Find the user you want to remove and select the **Actions** menu next to their name. +1. Select **Remove** and confirm the removal. +The user loses access to your organization immediately upon removal. diff --git a/content/manuals/security/_index.md b/content/manuals/security/_index.md index 798d18d796bd..dce68badb60b 100644 --- a/content/manuals/security/_index.md +++ b/content/manuals/security/_index.md @@ -1,8 +1,8 @@ --- title: Security for developers -linkTitle: Security -description: Learn about developer-level security features Docker has to offer and explore best practices -keywords: docker, docker hub, docker desktop, security +linkTitle: Security +description: Learn about developer-level security features like 2FA and access tokens +keywords: docker, docker hub, docker desktop, security, developer security, 2FA, access tokens weight: 40 params: sidebar: @@ -41,21 +41,26 @@ grid_resources: description: Learn how to suppress non-applicable or fixed vulnerabilities found in your images. icon: query_stats link: /scout/guides/vex/ +- title: Docker Hardened Images + description: Learn how to use Docker Hardened Images to enhance your software supply security. + icon: encrypted_add_circle + link: /dhi/ --- -Docker provides security guardrails for both administrators and developers. +Docker helps you protect your local environments, infrastructure, and networks +with its developer-level security features. -If you're an administrator, you can enforce sign-in across Docker products for your developers, and -scale, manage, and secure your instances of Docker Desktop with DevOps security controls like Enhanced Container Isolation and Registry Access Management. +Use tools like two-factor authentication (2FA), personal access tokens, and +Docker Scout to manage access and detect vulnerabilities early in your workflow. +You can also integrate secrets securely into your development stack using Docker Compose, +or enhance your software supply security with Docker Hardened Images. -For both administrators and developers, Docker provides security-specific products such as Docker Scout, for securing your software supply chain with proactive image vulnerability monitoring and remediation strategies. +Explore the following sections to learn more. ## For developers -See how you can protect your local environments, infrastructure, and networks without impeding productivity. - {{< grid items="grid_developers" >}} -## Further resources +## More resources {{< grid items="grid_resources" >}} diff --git a/data/summary.yaml b/data/summary.yaml index df5868a4841a..0b40ff0c8e22 100644 --- a/data/summary.yaml +++ b/data/summary.yaml @@ -236,6 +236,7 @@ SOCKS5 proxy support: SSO: subscription: [Business] for: Administrators + requires: Docker Desktop [4.42](/manuals/desktop/release-notes.md#4420) and later Synchronized file sharing: subscription: [Pro, Team, Business] USB/IP support: diff --git a/hugo_stats.json b/hugo_stats.json index 2c6b88e62daf..c353ff5ebf90 100644 --- a/hugo_stats.json +++ b/hugo_stats.json @@ -29,6 +29,7 @@ "Clone-with-git", "Command-Prompt", "Command-Prompt-CLI", + "Command-line-setup", "Compliant", "Custom-builder", "DNS-resolution", @@ -65,10 +66,12 @@ "Go", "GoDaddy", "Google-Cloud-DNS", + "Group-Policy-deployment", "HTTP", "Heredocs", "Hyper-V-backend-x86_64", "Inline", + "Installation-time-setup", "Instant-verification", "JSON", "Java", @@ -89,6 +92,8 @@ "Mac-with-Apple-silicon", "Mac-with-Intel-chip", "MacOS", + "Manual-creation", + "Manual-setup", "Manual-verification", "Manually-create-assets", "NetworkManager", @@ -120,6 +125,7 @@ "Rust", "Separate-containers", "Shell-script", + "Shell-script-deployment", "Single-container", "Specific-version", "Svelte", @@ -150,6 +156,7 @@ "Without-systemd", "[display:none]", "absolute", + "admin-settings.json-file", "admonition", "admonition-content", "admonition-danger", diff --git a/layouts/shortcodes/admin-scim-disable.html b/layouts/shortcodes/admin-scim-disable.html deleted file mode 100644 index 3b1499fd42db..000000000000 --- a/layouts/shortcodes/admin-scim-disable.html +++ /dev/null @@ -1,13 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. - - Organization: Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com/) and select your organization." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -1. Sign in to {{ $product_link }}. -1. {{ $sso_navigation }} -1. In the SSO connections table, select the **Actions** icon. -1. Select **Disable SCIM**. diff --git a/layouts/shortcodes/admin-scim.html b/layouts/shortcodes/admin-scim.html deleted file mode 100644 index 874ad92b5516..000000000000 --- a/layouts/shortcodes/admin-scim.html +++ /dev/null @@ -1,13 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. - - Organization: Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com/) and select your organization." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -1. Sign in to {{ $product_link }}. -1. {{ $sso_navigation }} -1. In the SSO connections table, select the **Actions** icon and **Setup SCIM**. -1. Copy the **SCIM Base URL** and **API Token** and paste the values into your IdP. diff --git a/layouts/shortcodes/admin-sso-management.md b/layouts/shortcodes/admin-sso-management.md deleted file mode 100644 index 5155191a4102..000000000000 --- a/layouts/shortcodes/admin-sso-management.md +++ /dev/null @@ -1,26 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com) and select your organization. Note that when an organization is part of a company, you must select the company and configure SSO for that organization at the company level. Each organization can have its own SSO configuration and domain, but it must be configured at the company level." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -### Remove a domain from an SSO connection - -> [!IMPORTANT] -> -> Docker supports multiple IdP configurations, where a single domain is used for multiple SSO identity providers. If you want to remove a domain from multiple SSO connections, you must remove it from each connection individually. - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon and then **Edit connection**. -4. Select **Next** to navigate to the section where the connected domains are listed. -5. In the **Domain** drop-down, select the **x** icon next to the domain that you want to remove. -6. Select **Next** to confirm or change the connected organization(s). -7. Select **Next** to confirm or change the default organization and team provisioning selections. -8. Review the **Connection Summary** and select **Update connection**. - -> [!NOTE] -> -> If you want to re-add the domain, a new TXT record value is assigned. You must then complete the verification steps with the new TXT record value. From 4f9ea1fda9837bd2ec0f5252647524c36e7a3bc0 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Tue, 12 Aug 2025 11:28:46 -0400 Subject: [PATCH 02/10] add ECI docs --- .../enhanced-container-isolation/_index.md | 228 ++++++---- .../enhanced-container-isolation/config.md | 424 +++++++----------- .../enable-eci.md | 166 +++++++ .../enhanced-container-isolation/faq.md | 135 ++---- .../features-benefits.md | 252 ----------- .../how-eci-works.md | 76 ---- .../limitations.md | 213 +++++---- 7 files changed, 672 insertions(+), 822 deletions(-) create mode 100644 content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md delete mode 100644 content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md delete mode 100644 content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md index aa4557cf8b7a..3d837ad0d8d1 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md @@ -2,16 +2,18 @@ title: Enhanced Container Isolation linkTitle: Enhanced Container Isolation description: Enhanced Container Isolation provides additional security for Docker Desktop by preventing malicious containers from compromising the host -keywords: nhanced container isolation, container security, sysbox runtime, linux user namespaces, hardened desktop +keywords: enhanced container isolation, container security, sysbox runtime, linux user namespaces, hardened desktop aliases: - /desktop/hardened-desktop/enhanced-container-isolation/ - /security/for-admins/hardened-desktop/enhanced-container-isolation/ -weight: 20 + - /security/hardened-desktop/enhanced-container-isolation/how-eci-works + - /security/hardened-desktop/enhanced-container-isolation/features-benefits +weight: 10 --- {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Enhanced Container Isolation (ECI) adds an extra layer of security to prevent malicious containers from compromising Docker Desktop or the host system. It uses advanced isolation techniques while maintaining full developer productivity. +Enhanced Container Isolation (ECI) prevents malicious containers from compromising Docker Desktop or the host system. It applies advanced security techniques automatically while maintaining full developer productivity and workflow compatibility. ECI strengthens container isolation and locks in security configurations created by administrators, such as [Registry Access Management policies](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) and [Settings Management](../settings-management/_index.md) controls. @@ -29,121 +31,193 @@ Enhanced Container Isolation is designed for: ## How Enhanced Container Isolation works -For an overview of how ECI works, see [How Enhanced Container Isolation works](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md). +Docker implements ECI using the [Sysbox container runtime](https://github.com/nestybox/sysbox), a +security-enhanced fork of the standard OCI runc runtime. When ECI is turned on, containers created through `docker run` or `docker create` automatically use Sysbox instead of runc without requiring any changes to developer workflows. -## Enable Enhanced Container Isolation +> [!NOTE] +> +> When ECI is turned on, the Docker CLI `--runtime` flag is ignored. +Docker's default runtime remains `runc`, but all user containers +implicitly launch with Sysbox. -### For developers +Even containers using the `--privileged` flag run securely with Enhanced Container Isolation, preventing them from breaching the Docker Desktop virtual machine or other containers. -To turn on ECI: +## Key security features -1. Verify your organization has a Docker Business subscription. -1. Sign in to your organization in Docker Desktop to access ECI features. -1. Stop and remove all existing containers: +### Linux user namespace isolation - ```console - $ docker stop $(docker ps -q) - $ docker rm $(docker ps -aq) - ``` +With Enhanced Container Isolation, all containers leverage Linux user namespaces for stronger isolation. Container root users map to unprivileged users in the Docker Desktop VM: -1. In Docker Desktop, go to **Settings** > **General**. -1. Select the **Use Enhanced Container Isolation** checkbox. -1. Select **Apply and restart**. +```console +$ docker run -it --rm --name=first alpine +/ # cat /proc/self/uid_map + 0 100000 65536 +``` -> [!IMPORTANT] -> -> ECI doesn't protect containers created before turning on the feature. Remove existing containers before turning on ECI. +This output shows that container root (0) maps to unprivileged user 100000 in the VM, with a range of 64K user IDs. Each container gets exclusive mappings: -### For administrators +```console +$ docker run -it --rm --name=second alpine +/ # cat /proc/self/uid_map + 0 165536 65536 +``` -Before you begin, [enforce sign-in](/manuals/enterprise/security/enforce-sign-in) so users authenticate with your organization -when signing into Docker Desktop. +Without Enhanced Container Isolation, containers run as true root: -You can configure Enhanced Container Isolation for your organization using -Settings Management. +```console +$ docker run -it --rm alpine +/ # cat /proc/self/uid_map + 0 0 4294967295 +``` -{{< tabs >}} -{{< tab name="Admin Console" >}} +By using Linux user namespaces, ECI ensures container processes never run with valid user IDs in the Linux VM, constraining their capabilities to resources within the container only. -1. Sign in to [Docker Home](https:app.docker.com) and select your organization. -1. Go to **Admin Console** > **Desktop Settings Management**. -1. [Create or edit a settings policy](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). -1. Set **Enhanced Container Isolation** to **Always enabled**. +### Secured privileged containers -{{< /tab >}} -{{< tab name="`admin-settings.json` file" >}} +Privileged containers (`docker run --privileged`) normally pose significant security risks because they provide unrestricted access to the Linux kernel. Without ECI, privileged containers can: -Create an [`admin-settings.json`](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) file with: +- Run as true root with all capabilities +- Bypass seccomp and AppArmor restrictions +- Access all hardware devices +- Modify global kernel settings -```json -{ - "configurationFileVersion": 2, - "enhancedContainerIsolation": { - "value": true, - "locked": true - } -} -``` +Organizations securing developer environments face challenges with privileged containers because they can gain control of the Docker Desktop VM and alter security settings like registry access management and network proxies. -Configuration options: -- `"value": true`: Turns on ECI by default -- `"locked": true`: Prevents developers from turning off ECI -- `"locked": false`: Allows developers to control the setting +Enhanced Container Isolation transforms privileged containers by ensuring they can only access resources within their container boundary. For example, privileged containers can't access Docker Desktop's network configuration: -{{< /tab >}} -{{< /tabs >}} +```console +$ docker run --privileged djs55/bpftool map show +Error: can't get next map: Operation not permitted +``` -#### Apply the configuration +Without ECI, privileged containers can easily access and modify these settings: -To apply the updated Enhanced Container Isolation setting for your organization: +```console +$ docker run --privileged djs55/bpftool map show +17: ringbuf name blocked_packets flags 0x0 + key 0B value 0B max_entries 16777216 memlock 0B +18: hash name allowed_map flags 0x0 + key 4B value 4B max_entries 10000 memlock 81920B +``` -- New installations: Users launch Docker Desktop and sign in -- Existing installations: Users must fully quit Docker Desktop and relaunch +Advanced container workloads like Docker-in-Docker and Kubernetes-in-Docker still work with ECI but run much more securely. -> [!IMPORTANT] +> [!NOTE] > -> Restarting from the Docker Desktop menu isn't sufficient. Users must completely quit and reopen Docker Desktop. +> ECI doesn't prevent users from running privileged containers, but makes them secure by containing their access. Privileged workloads that modify global kernel settings (loading kernel modules, changing Berkeley Packet Filter settings) receive "permission denied" errors. + +### Namespace isolation enforcement + +Enhanced Container Isolation prevents containers from sharing Linux namespaces with the Docker Desktop VM, maintaining isolation boundaries: + +**PID namespace sharing blocked:** + +```console +$ docker run -it --rm --pid=host alpine +docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown. +``` + +**Network namespace sharing blocked:** + +```console +$ docker run -it --rm --network=host alpine +docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown. +``` + +**User namespace override ignored:** -You can also configure Docker socket mount permissions for trusted images that need Docker API access. +```console +$ docker run -it --rm --userns=host alpine +/ # cat /proc/self/uid_map + 0 100000 65536 +``` -## Verify Enhanced Container Isolation is active +Docker build operations using `--network-host` and Docker buildx entitlements (`network.host`, +`security.insecure`) are also blocked. -When ECI is turned on, users can verify it's working by checking the user -namespace mapping: +### Protected bind mounts + +Enhanced Container Isolation maintains support for standard file sharing while preventing access to sensitive VM directories: + +**Host directory mounts continue to work:** ```console -$ docker run --rm alpine cat /proc/self/uid_map +$ docker run -it --rm -v $HOME:/mnt alpine +/ # ls /mnt +# Successfully lists home directory contents ``` -When ECI is turned on: +**VM configuration mounts are blocked:** + +```console +$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine +docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown +``` + +This prevents containers from reading or modifying Docker Engine configurations, registry access management settings, proxy configurations, and other security-related VM files. + +> [!NOTE] +> +> By default, ECI blocks bind mounting the Docker Engine socket (/var/run/docker.sock) as this would grant containers control over Docker Engine. Administrators can create exceptions for trusted container images. + +### Advanced system call protection + +Enhanced Container Isolation intercepts sensitive system calls to prevent containers from using legitimate capabilities maliciously: -```text -0 100000 65536 +```console +$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine +/ # mount -o remount,rw /mnt /mnt +mount: permission denied (are you root?) ``` -This shows the container's root user (0) maps to an unprivileged user (100000) in the Docker Desktop VM, with a range of 64K user IDs. Each container gets an exclusive user ID range for isolation. +Even with `CAP_SYS_ADMIN` capability, containers can't change read-only bind mounts to read-write, ensuring they can't breach container boundaries. -When ECI is turned off: +Containers can still create internal mounts within their filesystem: -```text -0 0 4294967295 +```console +/ # mkdir /root/tmpfs +/ # mount -t tmpfs tmpfs /root/tmpfs +/ # mount -o remount,ro /root/tmpfs /root/tmpfs +/ # findmnt | grep tmpfs +├─/root/tmpfs tmpfs tmpfs ro,relatime,uid=100000,gid=100000 ``` -This shows the container root user (0) maps directly to the VM root user (0), providing less isolation. +ECI performs system call filtering efficiently by intercepting only control-path system calls (rarely used) while leaving data-path system calls unaffected, maintaining container performance. + +### Automatic filesystem user ID mapping + +Enhanced Container Isolation solves file sharing challenges between containers with different user ID ranges through automatic filesystem mapping. + +Each container gets exclusive user ID mappings, but Sysbox uses filesystem user ID remapping via Linux kernel ID-mapped mounts (added in 2021) or alternative shiftsfs module. This maps filesystem accesses from containers' real user IDs to standard ranges, enabling: -You can also check the container runtime: +- Volume sharing across containers with different user ID ranges +- Consistent file ownership regardless of container user ID mappings +- Transparent file access without user intervention + +### Information hiding through filesystem emulation + +ECI emulates portions of `/proc` and `/sys` filesystems within containers to hide sensitive host information and provide per-container views of kernel resources: ```console -$ docker inspect --format='{{.HostConfig.Runtime}}' +$ docker run -it --rm alpine +/ # cat /proc/uptime +5.86 5.86 ``` -With ECI, it returns `sysbox-runc`. Without ECI it returns `runc`. +This shows container uptime instead of Docker Desktop VM uptime, preventing system information from leaking into containers. + +Several `/proc/sys` resources that aren't namespaced by the Linux kernel are emulated per-container, with Sysbox coordinating values when programming kernel settings. This enables container workloads that normally require privileged access to run securely. -## What developers see with enforced ECI +## Performance and compatibility -When administrators enforce Enhanced Container Isolation: +Enhanced Container Isolation maintains excellent performance and full compatibility: -- The Use Enhanced Container Isolation setting appears turned on in Docker Desktop settings -- The setting is locked and can't be changed if `"locked": true` was configured -- All new containers automatically use Linux user namespaces -- Existing development workflows continue to work without modification +- No performance impact: System call filtering targets only control-path calls, leaving data-path operations unaffected +- Full workflow compatibility: Existing development processes, tools, and container images work unchanged +- Advanced workload support: Docker-in-Docker, Kubernetes-in-Docker, and other complex scenarios work securely +- Automatic management: User ID mappings, filesystem access, and security policies are handled automatically +- Standard image support: No special container images or modifications required + +> [!IMPORTANT] +> +> ECI protection varies by Docker Desktop version and doesn't yet protect extension containers. Docker builds and Kubernetes in Docker Desktop have varying protection levels depending on the version. For details, see [Enhanced Container Isolation limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md index a555f45cb3be..15f476b457e3 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md @@ -1,45 +1,51 @@ --- -description: Advanced Configuration for Enhanced Container Isolation -title: Advanced configuration options for ECI -linkTitle: Advanced configuration -keywords: enhanced container isolation, Docker Desktop, Docker socket, bind mount, configuration +title: Configure Docker socket exceptions and advanced settings +linkTitle: Configure Docker socket exceptions +description: Configure Docker socket exceptions and advanced settings for Enhanced Container Isolation +keywords: enhanced container isolation, docker socket, configuration, testcontainers, admin settings aliases: - /desktop/hardened-desktop/enhanced-container-isolation/config/ - /security/for-admins/hardened-desktop/enhanced-container-isolation/config/ -weight: 30 +weight: 20 --- {{< summary-bar feature_name="Hardened Docker Desktop" >}} +This page shows you how to configure Docker socket exceptions and other advanced settings for Enhanced Container Isolation (ECI). These configurations enable trusted tools like Testcontainers to work with ECI while maintaining security. + ## Docker socket mount permissions -By default, when Enhanced Container Isolation (ECI) is enabled, Docker Desktop does not allow bind-mounting the -Docker Engine socket into containers: +By default, Enhanced Container Isolation blocks containers from mounting the Docker socket to prevent malicious access to Docker Engine. However, some legitimate tools require Docker socket access. -```console -$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:cli -docker: Error response from daemon: enhanced container isolation: docker socket mount denied for container with image "docker.io/library/docker"; image is not in the allowed list; if you wish to allow it, configure the docker socket image list in the Docker Desktop settings. -``` -This prevents malicious containers from gaining access to the Docker Engine, as -such access could allow them to perform supply chain attacks. For example, build and -push malicious images into the organization's repositories or similar. +Common scenarios requiring Docker socket access include: -However, some legitimate use cases require containers to have access to the -Docker Engine socket. For example, the popular [Testcontainers](https://testcontainers.com/) -framework sometimes bind-mounts the Docker Engine socket into containers to -manage them or perform post-test cleanup. Similarly, some Buildpack frameworks, -for example [Paketo](https://paketo.io/), require Docker socket bind-mounts into -containers. +- Testing frameworks: Testcontainers, which manages test containers +- Build tools: Paketo buildpacks that create ephemeral build containers +- CI/CD tools: Tools that manage containers as part of deployment pipelines +- Development utilities: Docker CLI containers for container management -Administrators can optionally configure ECI to allow -bind mounting the Docker Engine socket into containers, but in a controlled way. -This can be done via the Docker Socket mount permissions section in the -[`admin-settings.json`](../settings-management/configure-json-file.md) file. For example: +## Configure socket exceptions +Configure Docker socket exceptions using Settings Management: -```json -{ +{{< tabs >}} +{{< tab name="Admin Console" >}} + +1. Sign in to [Docker Home](https://app.docker.com) and select your organization. +1. Go to **Admin Console** > **Desktop Settings Management**. +1. [Create or edit a setting policy](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). +1. Find **Enhanced Container Isolation** settings. +1. Configure **Docker socket access control** with your trusted images and +command restrictions. + +{{< /tab >}} +{{< tab name="JSON file" >}} + +Create an [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) and add: + + ```json + { "configurationFileVersion": 2, "enhancedContainerIsolation": { "locked": true, @@ -55,113 +61,75 @@ This can be done via the Docker Socket mount permissions section in the }, "commandList": { "type": "deny", - "commands": ["push"] + "commands": ["push", "build"] } } } -} -``` + } + ``` -> [!TIP] -> -> You can now also configure these settings in the [Docker Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). +{{< /tab >}} +{{< /tabs >}} -As shown above, there are two configurations for bind-mounting the Docker -socket into containers: the `imageList` and the `commandList`. These are -described below. +## Image allowlist configuration -### Image list +The `imageList` defines which container images can mount the Docker socket. -The `imageList` is a list of container images that are allowed to bind-mount the -Docker socket. By default the list is empty, no containers are allowed to -bind-mount the Docker socket when ECI is enabled. However, an administrator can add -images to the list, using either of these formats: +### Image reference formats -| Image Reference Format | Description | +| Format | Description | | :---------------------- | :---------- | | `[:]` | Name of the image, with optional tag. If the tag is omitted, the `:latest` tag is used. If the tag is the wildcard `*`, then it means "any tag for that image." | | `@` | Name of the image, with a specific repository digest (e.g., as reported by `docker buildx imagetools inspect `). This means only the image that matches that name and digest is allowed. | -The image name follows the standard convention, so it can point to any registry -and repository. +### Example configurations -In the previous example, the image list was configured with three images: +**Basic allowlist for testing tools:** ```json "imageList": { "images": [ - "docker.io/localstack/localstack:*", "docker.io/testcontainers/ryuk:*", - "docker:cli" + "docker:cli", + "alpine:latest" ] } ``` -This means that containers that use either the `docker.io/localstack/localstack` -or the `docker.io/testcontainers/ryuk` image (with any tag), or the `docker:cli` -image, are allowed to bind-mount the Docker socket when ECI is enabled. Thus, -the following works: +**Wildcard allowlist (Docker Desktop 4.36 and later):** -```console -$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker:cli sh -/ # +```json +"imageList": { + "images": ["*"] +} ``` -> [!TIP] +> [!WARNING] > -> Be restrictive with the images you allow, as described in [Recommendations](#recommendations). +> Using `"*"` allows all containers to mount the Docker socket, which reduces security. Only use this when explicitly listing allowed images isn't feasible. + +### Security validation -In general, it's easier to specify the image using the tag wildcard format, for example `:*`, because then `imageList` doesn't need to be updated whenever a new version of the -image is used. Alternatively, you can use an immutable tag, for example `:latest`, -but it does not always work as well as the wildcard because, for example, -Testcontainers uses specific versions of the image, not necessarily the latest -one. +Docker Desktop validates allowed images by: -When ECI is enabled, Docker Desktop periodically downloads the image digests -for the allowed images from the appropriate registry and stores them in -memory. Then, when a container is started with a Docker socket bind-mount, -Docker Desktop checks if the container's image digest matches one of the allowed -digests. If so, the container is allowed to start, otherwise it's blocked. +1. Downloading image digests from registries for allowed images +1. Comparing container image digests against the allowlist when containers start +1. Blocking containers whose digests don't match allowed images -Due to the digest comparison, it's not possible to bypass the Docker socket -mount permissions by re-tagging a disallowed image to the name of an allowed -one. In other words, if a user does: +This prevents bypassing restrictions by retagging unauthorized images: ```console -$ docker image rm -$ docker tag -$ docker run -v /var/run/docker.sock:/var/run/docker.sock +$ docker tag malicious-image docker:cli +$ docker run -v /var/run/docker.sock:/var/run/docker.sock docker:cli +# This fails because the digest doesn't match the real docker:cli image ``` -then the tag operation succeeds, but the `docker run` command fails -because the image digest of the disallowed image won't match that of the allowed -ones in the repository. - -### Docker Socket Mount Permissions for derived images - -{{< summary-bar feature_name="Docker Scout Mount Permissions" >}} - -As described in the prior section, administrators can configure the list of container -images that are allowed to mount the Docker socket via the `imageList`. - -This works for most scenarios, but not always, because it requires knowing upfront -the name of the image(s) on which the Docker socket mounts should be allowed. -Some container tools such as [Paketo](https://paketo.io/) buildpacks, -build ephemeral local images that require Docker socket bind mounts. Since the name of -those ephemeral images is not known upfront, the `imageList` is not sufficient. - -To overcome this, starting with Docker Desktop version 4.34, the Docker Socket -mount permissions not only apply to the images listed in the `imageList`; they -also apply to any local images derived (i.e., built from) an image in the -`imageList`. +## Derived images support -That is, if a local image called "myLocalImage" is built from "myBaseImage" -(i.e., has a Dockerfile with a `FROM myBaseImage`), then if "myBaseImage" is in -the `imageList`, both "myBaseImage" and "myLocalImage" are allowed to mount the -Docker socket. +For tools like Paketo buildpacks that create ephemeral local images, you can +allow images derived from trusted base images. -For example, to enable Paketo buildpacks to work with Docker Desktop and ECI, -simply add the following image to the `imageList`: +### Enable derived images ```json "imageList": { @@ -172,192 +140,146 @@ simply add the following image to the `imageList`: } ``` -When the buildpack runs, it will create an ephemeral image derived from -`paketobuildpacks/builder:base` and mount the Docker socket to it. ECI will -allow this because it will notice that the ephemeral image is derived from an -allowed image. +When `allowDerivedImages` is true, local images built from allowed base images (using `FROM` in Dockerfile) also gain Docker socket access. -The behavior is disabled by default and must be explicitly enabled by setting -`"allowDerivedImages": true` as shown above. In general it is recommended that -you disable this setting unless you know it's required. +### Derived images requirements -A few caveats: +- Local images only: Derived images must not exist in remote registries +- Base image available: The parent image must be pulled locally first +- Performance impact: Adds up to 1 second to container startup for validation +- Version compatibility: Full wildcard support requires Docker Desktop 4.36+ -* Setting `"allowedDerivedImages" :true` will impact the startup time of - containers by up to 1 extra second, as Docker Desktop needs to perform - some more checks on the container image. +## Command restrictions -* The `allowDerivedImages` setting only applies to local-only images built from - an allowed image. That is, the derived image must not be present in a remote - repository because if it were, you would just list its name in the `imageList`. +### Deny list (recommended) -* For derived image checking to work, the parent image (i.e., the image in the - `imageList`) must be present locally (i.e., must have been explicitly pulled - from a repository). This is usually not a problem as the tools that need this - feature (e.g., Paketo buildpacks) will do the pre-pull of the parent image. +Blocks specified commands while allowing all others: -* For Docker Desktop versions 4.34 and 4.35 only: The `allowDerivedImages` setting - applies to all images in the `imageList` specified with an explicit tag (e.g., - `:`). It does not apply to images specified using the tag wildcard - (e.g., `:*`) described in the prior section. In Docker Desktop 4.36 and - later, this caveat no longer applies, meaning that the `allowDerivedImages` - settings applies to images specified with or without a wildcard tag. This - makes it easier to manage the ECI Docker socket image list. +```json +"commandList": { + "type": "deny", + "commands": ["push", "build", "image*"] +} +``` -### Allowing all containers to mount the Docker socket +### Allow list -In Docker Desktop version 4.36 and later, it's possible to configure the image -list to allow any container to mount the Docker socket. You do this by adding -`"*"` to the `imageList`: +Only allows specified commands while blocking all others: ```json -"imageList": { - "images": [ - "*" - ] +"commandList": { + "type": "allow", + "commands": ["ps", "container*", "volume*"] } ``` -This tells Docker Desktop to allow all containers to mount the Docker socket -which increases flexibility but reduces security. It also improves container -startup time when using Enhanced Container Isolation. +### Command wildcards -It is recommended that you use this only in scenarios where explicitly listing -allowed container images is not flexible enough. - -### Command list +| Wildcard | Blocks/allows | +| :---------------- | :---------- | +| "container\*" | All "docker container ..." commands | +| "image\*" | All "docker image ..." commands | +| "volume\*" | All "docker volume ..." commands | +| "network\*" | All "docker network ..." commands | +| "build\*" | All "docker build ..." commands | +| "system\*" | All "docker system ..." commands | -In addition to the `imageList` described in the prior sections, ECI can further -restrict the commands that a container can issue via a bind mounted Docker -socket. This is done via the Docker socket mount permission `commandList`, and -acts as a complementary security mechanism to the `imageList` (i.e., like a -second line of defense). +### Command blocking example -For example, say the `imageList` is configured to allow image `docker:cli` to -mount the Docker socket, and a container is started with it: +When a blocked command is executed: ```console -$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock sh -/ # +/ # docker push myimage +Error response from daemon: enhanced container isolation: docker command "/v1.43/images/myimage/push?tag=latest" is blocked; if you wish to allow it, configure the docker socket command list in the Docker Desktop settings. ``` -By default, this allows the container to issue any command via that Docker -socket (e.g., build and push images to the organization's repositories), which -is generally not desirable. +## Common configuration examples -To improve security, the `commandList` can be configured to restrict the -commands that the processes inside the container can issue on the bind-mounted -Docker socket. The `commandList` can be configured as a "deny" list (default) or -an "allow" list, depending on your preference. +### Testcontainers setup -Each command in the list is specified by its name, as reported by `docker ---help` (e.g., "ps", "build", "pull", "push", etc.) In addition, the following -command wildcards are allowed to block an entire group of commands: +For Java/Python testing with Testcontainers: -| Command wildcard | Description | -| :---------------- | :---------- | -| "container\*" | Refers to all "docker container ..." commands | -| "image\*" | Refers to all "docker image ..." commands | -| "volume\*" | Refers to all "docker volume ..." commands | -| "network\*" | Refers to all "docker network ..." commands | -| "build\*" | Refers to all "docker build ..." commands | -| "system\*" | Refers to all "docker system ..." commands | +```json +"dockerSocketMount": { + "imageList": { + "images": [ + "docker.io/testcontainers/ryuk:*", + "testcontainers/*:*" + ] + }, + "commandList": { + "type": "deny", + "commands": ["push", "build"] + } +} +``` -For example, the following configuration blocks the `build` and `push` commands -on the Docker socket: +### CI/CD pipeline tools + +For controlled CI/CD container management: ```json -"commandList": { - "type": "deny", - "commands": ["build", "push"] +"dockerSocketMount": { + "imageList": { + "images": [ + "docker:cli", + "your-registry.com/ci-tools/*:*" + ] + }, + "commandList": { + "type": "allow", + "commands": ["ps", "container*", "image*"] + } } ``` -Thus, if inside the container, you issue either of those commands on the -bind-mounted Docker socket, they will be blocked: +### Development environments -```console -/ # docker push myimage -Error response from daemon: enhanced container isolation: docker command "/v1.43/images/myimage/push?tag=latest" is blocked; if you wish to allow it, configure the docker socket command list in the Docker Desktop settings or admin-settings. +For local development with Docker-in-Docker: + +```json +"dockerSocketMount": { + "imageList": { + "images": [ + "docker:dind", + "docker:cli" + ] + }, + "commandList": { + "type": "deny", + "commands": ["system*"] + } +} ``` -Similarly: +## Security recommendations + +### Image allowlist best practices + +- Be restrictive: Only allow images you absolutely trust and need +- Use wildcards carefully: Tag wildcards (`*`) are convenient but less secure than specific tags +- Regular reviews: Periodically review and update your allowlist +- Digest pinning: Use digest references for maximum security in critical environments + +### Command restrictions + +- Default to deny: Start with a deny list blocking dangerous commands like `push` and `build` +- Principle of least privilege: Only allow commands your tools actually need +- Monitor usage: Track which commands are being blocked to refine your configuration + +### Monitoring and maintenance + +- Regular validation: Test your configuration after Docker Desktop updates, as image digests may change. +- Handle digest mismatches: If allowed images are unexpectedly blocked: ```console -/ # curl --unix-socket /var/run/docker.sock -XPOST http://localhost/v1.43/images/myimage/push?tag=latest -Error response from daemon: enhanced container isolation: docker command "/v1.43/images/myimage/push?tag=latest" is blocked; if you wish to allow it, configure the docker socket command list in the Docker Desktop settings or admin-settings. +$ docker image rm +$ docker pull ``` -Note that if the `commandList` had been configured as an "allow" list, then the -effect would be the opposite: only the listed commands would have been allowed. -Whether to configure the list as an allow or deny list depends on the use case. - -### Recommendations - -* Be restrictive on the list of container images for which you allow bind-mounting - of the Docker socket (i.e., the `imageList`). Generally, only allow this for - images that are absolutely needed and that you trust. - -* Use the tag wildcard format if possible in the `imageList` - (e.g., `:*`), as this eliminates the need to update the - `admin-settings.json` file due to image tag changes. - -* In the `commandList`, block commands that you don't expect the container to - execute. For example, for local testing (e.g., Testcontainers), containers - that bind-mount the Docker socket typically create / run / remove containers, - volumes, and networks, but don't typically build images or push them into - repositories (though some may legitimately do this). What commands to allow or - block depends on the use case. - - - Note that all "docker" commands issued by the container via the bind-mounted - Docker socket will also execute under enhanced container isolation (i.e., - the resulting container uses a the Linux user-namespace, sensitive system - calls are vetted, etc.) - -### Caveats and limitations - -* When Docker Desktop is restarted, it's possible that an image that is allowed - to mount the Docker socket is unexpectedly blocked from doing so. This can - happen when the image digest changes in the remote repository (e.g., a - ":latest" image was updated) and the local copy of that image (e.g., from a - prior `docker pull`) no longer matches the digest in the remote repository. In - this case, remove the local image and pull it again (e.g., `docker rm ` - and `docker pull `). - -* It's not possible to allow Docker socket bind-mounts on containers using - local-only images (i.e., images that are not on a registry) unless they are - [derived from an allowed image](#docker-socket-mount-permissions-for-derived-images) - or you've [allowed all containers to mount the Docker socket](#allowing-all-containers-to-mount-the-docker-socket). - That is because Docker Desktop pulls the digests for the allowed images from - the registry, and then uses that to compare against the local copy of the - image. - -* The `commandList` configuration applies to all containers that are allowed to - bind-mount the Docker socket. Therefore it can't be configured differently per - container. - -* The following commands are not yet supported in the `commandList`: - -| Unsupported command | Description | -| :------------------- | :---------- | -| `compose` | Docker Compose | -| `dev` | Dev environments | -| `extension` | Manages Docker Extensions | -| `feedback` | Send feedback to Docker | -| `init` | Creates Docker-related starter files | -| `manifest` | Manages Docker image manifests | -| `plugin` | Manages plugins | -| `sbom` | View Software Bill of Materials (SBOM) | -| `scout` | Docker Scout | -| `trust` | Manage trust on Docker images | - -> [!NOTE] -> -> Docker socket mount permissions do not apply when running "true" -> Docker-in-Docker (i.e., when running the Docker Engine inside a container). In -> this case there's no bind-mount of the host's Docker socket into the -> container, and therefore no risk of the container leveraging the configuration -> and credentials of the host's Docker Engine to perform malicious activity. -> Enhanced Container Isolation is capable of running Docker-in-Docker securely, -> without giving the outer container true root permissions in the Docker Desktop -> VM. +This resolves digest mismatches when upstream images are updated. + +## Next steps + +- Review [Enhanced Container Isolation limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). +- Review [Enhanced Container Isolation FAQs](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md). diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md new file mode 100644 index 000000000000..36b8a50c041a --- /dev/null +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md @@ -0,0 +1,166 @@ +--- +title: Enable Enhanced Container Isolation +description: Enable Enhanced Container Isolation to secure containers in Docker Desktop +keywords: enhanced container isolation, enable eci, container security, docker desktop setup +weight: 15 +--- + +{{< summary-bar feature_name="Hardened Docker Desktop" >}} + +This page shows you how to turn on Enhanced Container Isolation (ECI) and verify it's working correctly. ECI prevents malicious containers from compromising Docker Desktop while maintaining full developer productivity. + +## Prerequisites + +Before you begin, you must have: + +- A Docker Business subscription +- Docker Desktop 4.13 or later +- Enforced sign-in (for administrators managing organization-wide settings only) + +## Enable Enhanced Container Isolation + +### For developers + +Turn on ECI in your Docker Desktop settings: + +1. Sign in to your organizationin Docker Desktop. Your organization must have +a Docker Business subscription. +1. Stop and remove all existing containers: + + ```console + docker stop $(docker ps -q) + docker rm $(docker ps -aq) + ``` + +1. In Docker Desktop, go to **Settings** > **General**. +1. Select the **Use Enhanced Container Isolation** checkbox. +1. Select **Apply and restart**. + +> [!IMPORTANT] +> +> ECI doesn't protect containers created before turning on the feature. Remove existing containers before turning on ECI. + +### For administrators + +Configure Enhanced Container Isolation organization-wide using Settings Management: + +{{< tabs >}} +{{< tab name="Admin Console" >}} + +1. Sign in to [Docker Home](https://app.docker.com) and select your organization. +1. Go to **Admin Console** > **Desktop Settings Management**. +1. [Create or edit a setting policy](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md). +1. Set **Enhanced Container Isolation** to **Always enabled**. + +{{< /tab >}} +{{< tab name="JSON file" >}} + +1. Create an [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) and add: + + ```json + { + "configurationFileVersion": 2, + "enhancedContainerIsolation": { + "value": true, + "locked": true + } + } + ``` + +1. Configure the following as needed: + - `"value": true`: Turns on ECI by default (required) + - `"locked": true`: Prevents developers from turning off ECI + - `"locked": false`: Allows developers to control the setting + +{{< /tab >}} +{{< /tabs >}} + +### Apply the configuration + +For ECI settings to take effect: + +- New installations: Users launch Docker Desktop and sign in +- Existing installations: Users must fully quit Docker Desktop and relaunch + +> [!IMPORTANT] +> +> Restarting from the Docker Desktop menu isn't sufficient. Users must completely quit and reopen Docker Desktop. + +You can also configure [Docker socket mount permissions](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md) for trusted images that need Docker API access. + +## Verify Enhanced Container Isolation is active + +After turning on ECI, verify it's working correctly using these methods. + +### Check user namespace mapping + +Run a container and examine the user namespace mapping: + +```console +$ docker run --rm alpine cat /proc/self/uid_map +``` + +**With ECI turned on:** + +```text +0 100000 65536 +``` + +This shows the container's root user (0) maps to an unprivileged user (100000) in the Docker Desktop VM, with a range of 64K user IDs. Each container gets an exclusive user ID range for isolation. + +**With ECI turned off:** + +```text +0 0 4294967295 +``` + +This shows the container root user (0) maps directly to the VM root user (0), providing less isolation. + +### Check container runtime + +Verify the container runtime being used: + +```console +$ docker inspect --format='{{.HostConfig.Runtime}}' +``` + +With ECI turned on, it turns `sysbox-runc`. With ECI turned off, it returns +`runc`. + +### Test security restrictions + +Verify that ECI security restrictions are active. + +**Test namespace sharing:** + +```console +$ docker run -it --rm --pid=host alpine +``` + +With ECI turned on, this command fails with an error about Sysbox containers +not being able to share namespaces with the host. + +**Test Docker socket access:** + +```console +$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock alpine +``` + +With ECI turned on, this command fails unless you've configured Docker socket exceptions for trusted images. + +## What users see with enforced ECI + +When administrators enforce Enhanced Container Isolation through +Settings Management: + +- The **Use Enhanced Container Isolation** setting appears turned on in +Docker Desktop settings. +- If set to `"locked": true`, the setting is locked and greyed out. +- All new containers automatically use Linux user namepsaces. +- Existing development workflows continue to work without modification. +- Users see `sysbox-runc` as the container runtime in `docker inspect` output. + +## Next steps + +- Review [Configure Docker socket exceptions and advanced settings](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md). +- Review [Enhanced Container Isolation limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). \ No newline at end of file diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md index bdc77e4ef99e..eaf260d67a57 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md @@ -1,8 +1,8 @@ --- title: Enhanced Container Isolation FAQs linkTitle: FAQs -description: Frequently asked questions for Enhanced Container Isolation -keywords: enhanced container isolation, security, faq, sysbox, Docker Desktop +description: Frequently asked questions about Enhanced Container Isolation +keywords: enhanced container isolation, faq, troubleshooting, docker desktop toc_max: 2 aliases: - /desktop/hardened-desktop/enhanced-container-isolation/faq/ @@ -10,124 +10,77 @@ aliases: weight: 40 --- -### Do I need to change the way I use Docker when ECI is switched on? +{{< summary-bar feature_name="Hardened Docker Desktop" >}} -No, you can continue to use Docker as usual. ECI works under the covers by -creating a more secure container. +This page answers common questions about Enhanced Container Isolation (ECI) that aren't covered in the main documentation. -### Do all container workloads work well with ECI? +## Do I need to change the way I use Docker when ECI is switched on? -The great majority of container workloads run fine with ECI enabled, but a few -do not (yet). For the few workloads that don't yet work with Enhanced Container -Isolation, Docker is continuing to improve the feature to reduce this to a -minimum. +No. ECI works automatically in the background by creating more secure containers. You can continue using all your existing Docker commands, workflows, and development tools without any changes. -### Can I run privileged containers with ECI? +## Do all container workloads work well with ECI? -Yes, you can use the `--privileged` flag in containers but unlike privileged -containers without ECI, the container can only use it's elevated privileges to -access resources assigned to the container. It can't access global kernel -resources in the Docker Desktop Linux VM. This lets you run privileged -containers securely (including Docker-in-Docker). For more information, see [Key features and benefits](features-benefits.md#privileged-containers-are-also-secured). +Most container workloads run without issues when ECI is turned on. However, some advanced workloads that require specific kernel-level access may not work. For details about which workloads are affected, see [ECI limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). -### Will all privileged container workloads run with ECI? +## Why not just restrict usage of the `--privileged` flag? -No. Privileged container workloads that want to access global kernel resources -inside the Docker Desktop Linux VM won't work. For example, you can't use a -privileged container to load a kernel module. +Privileged containers serve legitimate purposes like Docker-in-Docker, Kubernetes-in-Docker, and accessing hardware devices. ECI provides a better solution by allowing these advanced workloads to run securely while preventing them from compromising the Docker Desktop VM. -### Why not just restrict usage of the `--privileged` flag? +## Does ECI affect container performance? -Privileged containers are typically used to run advanced workloads in -containers, for example Docker-in-Docker or Kubernetes-in-Docker, to -perform kernel operations such as loading modules, or to access hardware -devices. +ECI has minimal impact on container performance. The only exception is containers that perform many `mount` and `umount` system calls, as these are inspected by the Sysbox runtime for security. Most development workloads see no noticeable performance difference. -ECI allows the running of advanced workloads, but denies the ability to perform -kernel operations or access hardware devices. +## Can I override the container runtime with ECI turned on? -### Does ECI restrict bind mounts inside the container? -Yes, it restricts bind mounts of directories located in the Docker Desktop Linux -VM into the container. +No. When ECI is turned on, all containers use the Sysbox runtime regardless of any `--runtime` flags: -It doesn't restrict bind mounts of your host machine files into the container, -as configured via Docker Desktop's **Settings** > **Resources** > **File Sharing**. +```console +$ docker run --runtime=runc alpine echo "test" +# This still uses sysbox-runc, not runc +``` -### Can I mount the host's Docker Socket into a container when ECI is enabled? +The `--runtime` flag is ignored to prevent users from bypassing ECI security by running containers as true root in the Docker Desktop VM. -By default, ECI blocks bind-mounting the host's Docker socket into containers, -for security reasons. However, there are legitimate use cases for this, such as -when using [Testcontainers](https://testcontainers.com/) for local testing. +## Does ECI protect containers created before turning it on? -To enable such use cases, it's possible to configure ECI to allow Docker socket -mounts into containers, but only for your chosen (i.e,. trusted) container images, and -even restrict what commands the container can send to the Docker Engine via the socket. -See [ECI Docker socket mount permissions](config.md#docker-socket-mount-permissions). +No. ECI only protects containers created after it's turned on. Remove existing containers before turning on ECI: -### Does ECI protect all containers launched with Docker Desktop? +```console +$ docker stop $(docker ps -q) +$ docker rm $(docker ps -aq) +``` -Not yet. It protects all containers launched by users via `docker create` and -`docker run`. +For more details, see [Enable Enhanced Container Isolation](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md). -For containers implicitly created by `docker build` as well as Docker -Desktop's integrated Kubernetes, protection varies depending on the Docker -Desktop version (see the following two FAQs). +## Which containers does ECI protect? -### Does ECI protect containers implicitly used by `docker build`? +ECI protection varies by container type and Docker Desktop version: -Prior to Docker Desktop 4.19, ECI did not protect containers used implicitly -by `docker build` during the build process. +### Always protected -Since Docker Desktop 4.19, ECI protects containers used by `docker build` -when using the [Docker container driver](/manuals/build/builders/drivers/_index.md). +- Containers created with `docker run` and `docker create` +- Containers using the `docker-container` build driver -In addition, since Docker Desktop 4.30, ECI also protects containers used by -`docker build` when using the default "docker" build driver, on all -platforms supported by Docker Desktop except Windows with WSL 2. +### Version dependent -### Does ECI protect Kubernetes in Docker Desktop? +- Docker Build: Protected in Docker Desktop 4.30+ (except WSL 2) +- Kubernetes: Protected in Docker Desktop 4.38+ when using the kind provisioner -Prior to Docker Desktop 4.38, ECI did not protect the Kubernetes cluster -integrated in Docker Desktop. +### Not protected -Since Docker Desktop 4.38, ECI protects the integrated Kubernetes cluster -when using the new **kind** provisioner (see [Deploy On Kubernetes](/manuals/desktop/features/kubernetes.md)). -In this case, each node in the multi-node Kubernetes cluster is actually an ECI -protected container. With ECI disabled, each node in the Kubernetes cluster is -a less-secure fully privileged container. +- Docker Extensions +- Docker Debug containers +- Kubernetes with kubeadm provisioner -ECI does not protect the integrated Kubernetes cluster when using the -older **Kubeadm** single-node cluster provisioner. +For complete details, see [ECI limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). -### Does ECI protect containers launched prior to enabling ECI? +## Can I mount the Docker socket with ECI turned on? -No. Containers created prior to switching on ECI are not protected. Therefore, it is -recommended you remove all containers prior to switching on ECI. +By default, no. ECI blocks Docker socket bind mounts for security. However, you can configure exceptions for trusted images like Testcontainers. -### Does ECI affect the performance of containers? +For configuration details, see [Configure Docker socket exceptions](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md). -ECI has little impact on the performance of -containers. The exception is for containers that perform lots of `mount` and -`umount` system calls, as these are trapped and vetted by the Sysbox container -runtime to ensure they are not being used to breach the container's filesystem. +## What bind mounts does ECI restrict? -### With ECI, can the user still override the `--runtime` flag from the CLI ? - -No. With ECI enabled, Sysbox is set as the default (and only) runtime for -containers deployed by Docker Desktop users. If a user attempts to override the -runtime (e.g., `docker run --runtime=runc`), this request is ignored and the -container is created through the Sysbox runtime. - -The reason `runc` is disallowed is it lets users run as "true -root" on the Docker Desktop Linux VM, thereby providing them with implicit -control of the VM and the ability to modify the administrative configurations -for Docker Desktop. - -### How is ECI different from Docker Engine's userns-remap mode? - -See [How does it work](how-eci-works.md#enhanced-container-isolation-vs-docker-userns-remap-mode). - -### How is ECI different from Rootless Docker? - -See [How does it work](how-eci-works.md#enhanced-container-isolation-vs-rootless-docker) +ECI restricts bind mounts of Docker Desktop VM directories but allows host directory mounts configured in Docker Desktop Settings. diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md deleted file mode 100644 index c2d68f87fd59..000000000000 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/features-benefits.md +++ /dev/null @@ -1,252 +0,0 @@ ---- -title: Features and benefits of ECI -linkTitle: Features and benefits -description: Key security features and benefits of Enhanced Container Isolation for Docker Desktop -keywords: set up, enhanced container isolation, rootless, security, features, Docker Desktop -aliases: - - /desktop/hardened-desktop/enhanced-container-isolation/features-benefits/ - - /security/for-admins/hardened-desktop/enhanced-container-isolation/features-benefits/ -weight: 20 ---- - -{{< summary-bar feature_name="Hardened Docker Desktop" >}} - -Enhanced Container Isolation provides multiple layers of security protection that work together to prevent container breaches while maintaining full developer productivity. This page explains the key security features and their benefits. - -## Linux user namespace on all containers - -Enhanced Container Isolation automatically applies [Linux user namespaces](https://man7.org/linux/man-pages/man7/user_namespaces.7.html) -to every container. The root user inside containers maps to unprivileged users in the Docker Desktop Linux VM, preventing privilege escalation attacks. - -For example: - -```console -$ docker run -it --rm --name=first alpine -/ # cat /proc/self/uid_map - 0 100000 65536 -``` - -The output `0 100000 65536` shows that: - -- Container root user (0) maps to unprivileged user 100000 in the VM -- The mapping covers a continuous range of 64K user IDs -- The same principle applies to group IDs - -Each container gets an exclusive user ID range managed automatically by Sysbox: - -```console -$ docker run -it --rm --name=second alpine -/ # cat /proc/self/uid_map - 0 165536 65536 -``` - -In contrast, without Enhanced Container Isolation, the container's root user is -in fact root on the host (aka "true root") and this applies to all containers: - -```console -$ docker run -it --rm alpine -/ # cat /proc/self/uid_map - 0 0 4294967295 -``` - -This shows the container root user maps directly to VM root user (0), providing much less isolation. - -## Security benefits - -Enhanced Container Isolation provides the following security benefits: - -- Container processes never run with true root privileges in the Linux VM -- Processes don't run with any valid user ID in the Linux VM -- Linux capabilities are constrained to resources within the container only -- Significantly improved container-to-host and cross-container isolation - -## Secured privileged containers - -Privileged containers (`docker run --privileged`) normally pose significant security risks because they provide unrestricted access to the Linux kernel. Without Enhanced Container Isolation, privileged containers can: - -- Run as true root with all capabilities -- Bypass seccomp and AppArmor restrictions -- Access all hardware devices -- Modify global kernel settings - -Organizations securing developer environments face challenges with privileged containers because they can gain control of the Docker Desktop VM and alter security settings like registry access management and network proxies. - -Enhanced Container Isolation ensures privileged containers can only access resources within their container boundary. The Linux user namespace and Sysbox security techniques prevent privileged containers from breaching the Docker Desktop VM. - -> [!NOTE] -> -> Enhanced Container Isolation doesn't prevent users from running privileged containers, but makes them secure by containing their access to container resources only. Privileged workloads that modify global kernel settings (loading kernel modules, changing Berkeley Packet Filter settings) receive "permission denied" errors. - -For example, Enhanced Container Isolation ensures privileged containers can't -access Docker Desktop network settings in the Linux VM configured via BPF: - -```console -$ docker run --privileged djs55/bpftool map show -Error: can't get next map: Operation not permitted -``` - -Without Enhanced Container Isolation, privileged containers can access and modify these settings: - -```console -$ docker run --privileged djs55/bpftool map show -17: ringbuf name blocked_packets flags 0x0 - key 0B value 0B max_entries 16777216 memlock 0B -18: hash name allowed_map flags 0x0 - key 4B value 4B max_entries 10000 memlock 81920B -20: lpm_trie name allowed_trie flags 0x1 - key 8B value 8B max_entries 1024 memlock 16384B -``` - -Advanced container workloads like Docker-in-Docker and Kubernetes-in-Docker still work with Enhanced Container Isolation but run much more securely than before. - -## Namespace isolation enforcement - -Enhanced Container Isolation prevents containers from sharing Linux namespaces with the Docker Desktop VM, which would break isolation boundaries. - -For example, sharing the PID namespace fails: - -```console -$ docker run -it --rm --pid=host alpine -docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown. -``` - -Similarly sharing the network namespace fails: - -```console -$ docker run -it --rm --network=host alpine -docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown. -``` - -In addition, the `--userns=host` flag, used to disable the user namespace on the -container, is ignored: - -```console -$ docker run -it --rm --userns=host alpine -/ # cat /proc/self/uid_map - 0 100000 65536 -``` - -Finally, Docker build `--network=host` and Docker buildx entitlements -(`network.host`, `security.insecure`) are not allowed. Builds that require these -won't work properly. - -## Protected bind mounts - -Enhanced Container Isolation maintains support for standard file sharing while preventing access to sensitive VM directories. - -### Allowed: Host directory bind mounts - -Users can continue bind mounting host directories configured in **Settings** > **Resources** > **File sharing**: - -```console -$ docker run -it --rm -v $HOME:/mnt alpine -/ # ls /mnt -# Lists home directory contents successfully -``` - -### Blocked: VM configuration bind mounts - -Containers can't mount sensitive Docker Desktop VM directories that contain security configurations: - -``` -$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine -docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown -``` - -This prevents containers from reading or modifying: - -- Docker Engine configurations -- Registry access management settings -- Proxy configurations -- Other security-related VM files - -> [!NOTE] -> -> By default, Enhanced Container Isolation blocks bind mounting the Docker Engine socket (`/var/run/docker.sock`) as this would grant containers control over Docker Engine. Administrators can create exceptions for trusted container images. See [Docker socket mount permissions](config.md#docker-socket-mount-permissions). - -## Advanced system call filtering - -Enhanced Container Isolation intercepts and inspects sensitive system calls between containers and the Linux kernel, preventing containers from using legitimate capabilities maliciously. - -Even containers with CAP_SYS_ADMIN capability can't use mount operations to breach container boundaries: - -```console -$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine -/ # mount -o remount,rw /mnt /mnt -mount: permission denied (are you root?) -``` - -The read-only bind mount can't be changed to read-write from within the container, even with the appropriate capability. - -### Allowed: Internal container mounts - -Containers can still create and modify mounts within their own filesystem: - -```console -/ # mkdir /root/tmpfs -/ # mount -t tmpfs tmpfs /root/tmpfs -/ # mount -o remount,ro /root/tmpfs /root/tmpfs -/ # findmnt | grep tmpfs -├─/root/tmpfs tmpfs tmpfs ro,relatime,uid=100000,gid=100000 - -/ # mount -o remount,rw /root/tmpfs /root/tmpfs -/ # findmnt | grep tmpfs -├─/root/tmpfs tmpfs tmpfs rw,relatime,uid=100000,gid=100000 -``` - -### Performance optimization - -Enhanced Container Isolation performs system call filtering efficiently by: - -- Intercepting only control-path system calls (rarely used in most workloads) -- Avoiding interception of data-path system calls (frequent operations) -- Maintaining container performance in the majority of use cases - -This approach ensures that containers with all Linux capabilities still can't breach container boundaries while maintaining good performance. - -## Automatic filesystem user ID mapping - -Enhanced Container Isolation solves the challenge of sharing files between containers that use different user ID ranges through automatic filesystem mapping. - -The challenge is, each container gets exclusive user ID mappings (container 1: 100000-165535, container 2: 165536-231071). Without mapping, files created by one container would be inaccessible to others due to different user IDs. - -To solve this, Sysbox uses filesystem user ID remapping through: - -- ID-mapped mounts: Linux kernel feature (added in 2021) that maps filesystem accesses -- Alternative shiftsfs: Fallback module for older kernel versions - -### How it works - -Filesystem accesses from containers' real user IDs (e.g., 100000-165535) are mapped to the standard range (0-65535) in the Docker Desktop VM. This allows: - -- Volume sharing across containers with different user ID ranges -- Consistent file ownership regardless of container user ID mappings -- Transparent file access without user intervention - -Even though filesystem mapping allows containers to access VM files with user ID 0, the bind mount restrictions prevent containers from mounting sensitive VM directories. - -## Procfs and sysfs emulation - -Enhanced Container Isolation emulates portions of the `/proc` and `/sys` filesystems within containers to hide sensitive host information and provide per-container views of kernel resources. - -The `/proc/uptime` file shows container uptime instead of VM uptime: - -```console -$ docker run -it --rm alpine -/ # cat /proc/uptime -5.86 5.86 -``` - -Without Enhanced Container Isolation, this would show Docker Desktop VM uptime, potentially -leaking system information. - -Several `/proc/sys resources` that aren't namespaced by the Linux kernel are emulated per-container. Each container sees a separate view of these resources, and Sysbox coordinates values when programming kernel settings. - -## Performance and compatibility - -Enhanced Container Isolation is designed to provide strong security without impacting developer productivity: - -- No performance impact: System call filtering targets only control-path calls, leaving data-path operations unaffected -- Full workflow compatibility: Existing development processes, tools, and container images work unchanged -- Advanced workload support: Docker-in-Docker, Kubernetes-in-Docker, and other complex scenarios work securely -- Automatic management: User ID mappings, filesystem access, and security policies are handled automatically diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md deleted file mode 100644 index 6a3a9e14a52f..000000000000 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/how-eci-works.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: How ECI works -description: Technical details of how Enhanced Container Isolation provides additional security for Docker Desktop -keywords: set up, enhanced container isolation, rootless, security -aliases: - - /desktop/hardened-desktop/enhanced-container-isolation/how-eci-works/ - - /security/for-admins/hardened-desktop/enhanced-container-isolation/how-eci-works/ -weight: 10 ---- - -{{< summary-bar feature_name="Hardened Docker Desktop" >}} - -Enhanced Container Isolation uses the [Sysbox -container runtime](https://github.com/nestybox/sysbox) to provide stronger container security. Sysbox is a specialized fork of the standard OCI runc runtime that enhances container isolation without impacting developer workflows. - -When [Enhanced Container Isolation is turned on](index.md#how-do-i-enable-enhanced-container-isolation), containers -created through `docker run` or `docker create` automatically -use Sysbox instead of the standard runc runtime. Users can continue working with containers normally without any changes to their workflows. - -Even containers using the `--privileged` flag run securely with Enhanced Container Isolation, preventing them from breaching the Docker Desktop virtual machine or other containers. - -> [!NOTE] -> -> When Enhanced Container Isolation is turned on, the Docker CLI `--runtime` flag is ignored. Docker's default runtime remains `runc`, but all user containers implicitly launch with Sysbox. - -## How Enhanced Container Isolation secures containers - -Enhanced Container Isolation applies multiple security techniques simultaneously: - -- Linux user namespaces: Root user in containers maps to unprivileged users in the Docker Desktop VM -- Sensitive directory restrictions: Containers can't mount sensitive VM directories -- System call filtering: Sensitive system calls between containers and the Linux kernel are inspected and restricted -- Filesystem user/group mapping: User and group IDs are safely mapped between container namespaces and the Linux VM -- Filesystem emulation: Portions of `/proc` and `/sys` filesystems are emulated inside containers for security -- Exclusive namespace mappings: Each container gets unique user-namespace mappings automatically -- Namespace isolation enforcement: Containers can't share namespaces with the Docker Desktop VM (`--network=host`, `--pid=host` are blocked) -- Configuration protection: Containers can't modify Docker Desktop VM configuration files -- Docker socket restrictions: Containers can't access the Docker Engine socket by default -- VM console restrictions: Direct console access to the Docker Desktop VM is blocked -- Privileged container containment: `--privileged` containers only have privileges within their own namespace -- Workflow compatibility: No changes required to existing development processes, tools, or container images -- Docker-in-Docker security: DinD and Kubernetes-in-Docker work but run unprivileged within the VM - -These techniques use recent Linux kernel advances and complement Docker's existing security mechanisms including Linux namespaces, cgroups, restricted capabilities, seccomp, and AppArmor. Together, they create strong isolation between containers and the Linux kernel inside the Docker Desktop VM. - -> [!IMPORTANT] -> -> ECI protection varies by Docker Desktop version. Later versions include more comprehensive protection. ECI doesn't yet protect extension containers. - -## Enhanced Container Isolation versus user namespace remapping - -The Docker Engine includes [userns-remap mode](/engine/security/userns-remap/) -that turns on user namespaces in all containers. However, this feature has several -[limitations](/engine/security/userns-remap/) and isn't supported in Docker Desktop. - -Both userns-remap mode and Enhanced Container Isolation improve container isolation using Linux user namespaces, but Enhanced Container Isolation provides significant advantages: - -- Automatic exclusive mappings: Each container gets unique user-namespace mappings without manual configuration -- Advanced isolation features: Includes system call filtering, filesystem emulation, and other security enhancements beyond basic user namespace remapping -- Docker Desktop optimization: Designed specifically for Docker Desktop's virtual machine architecture -- Enterprise security focus: Built for organizations with stringent security requirements - -### Enhanced Container Isolation versus Rootless Docker - -[Rootless Docker](/engine/security/rootless/) allows Docker Engine and containers to run without root privileges on Linux hosts. This lets non-root users install and run Docker natively on Linux systems. - -Rootless Docker isn't supported in Docker Desktop because Docker Desktop already provides isolation through virtualization. Docker Desktop runs Docker Engine in a Linux VM, which already allows non-root host users to run Docker safely. - -Key differences between Enhanced Container Isolation and Rootless Docker: - -- Scope: Enhanced Container Isolation secures containers within the VM, while Rootless Docker secures the entire Docker Engine on the host -- Architecture: Enhanced Container Isolation works within Docker Desktop's VM architecture, while Rootless Docker modifies the host installation -- Limitations: Enhanced Container Isolation avoids the known limitations of Rootless Docker -- Security boundary: Enhanced Container Isolation creates stronger isolation between containers and the Docker Engine, while Rootless Docker focuses on isolating the Docker Engine from the host - -Enhanced Container Isolation ensures that containers can't breach the Docker Desktop Linux VM or modify security settings within it, providing an additional security layer specifically designed for Docker Desktop's architecture. diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md index 19b3d85b0af6..a6c3de35fc75 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md @@ -1,42 +1,27 @@ --- -title: Limitations -description: Limitations of Enhanced Container Isolation -keywords: enhanced container isolation, security, sysbox, known issues, Docker Desktop -toc_max: 2 -weight: 50 +linkTitle: Limitations +title: Enhanced Container Isolation limitations +description: Known limitations and platform-specific considerations for Enhanced Container Isolation +keywords: enhanced container isolation, limitations, wsl, hyper-v, kubernetes, docker build +toc_max: 3 +weight: 30 aliases: - /security/for-admins/hardened-desktop/enhanced-container-isolation/limitations/ --- -### ECI support for WSL +{{< summary-bar feature_name="Hardened Docker Desktop" >}} + +Enhanced Container Isolation has some platform-specific limitations and feature constraints. Understanding these limitations helps you plan your security strategy and set appropriate expectations. + +## WSL 2 security considerations > [!NOTE] > -> Docker Desktop requires WSL 2 version 2.1.5 or later. To get the current -> version of WSL on your host, type `wsl --version`. If the command fails or if -> it returns a version number prior to 2.1.5, update WSL to the latest version -> by typing `wsl --update` in a Windows command or PowerShell terminal. - -ECI on WSL is not as secure as on Hyper-V because: - -- While ECI on WSL still hardens containers so that malicious workloads can't - easily breach Docker Desktop's Linux VM, ECI on WSL can't prevent Docker - Desktop users from breaching the Docker Desktop Linux VM. Such users can - trivially access that VM (as root) with the `wsl -d docker-desktop` command, - and use that access to modify Docker Engine settings inside the VM. This gives - Docker Desktop users control of the Docker Desktop VM and lets them bypass Docker Desktop configs set by administrators via the - [settings-management](../settings-management/_index.md) feature. In contrast, - ECI on Hyper-V does not let Docker Desktop users to breach the Docker - Desktop Linux VM. - -- With WSL 2, all WSL 2 distributions on the same Windows host share the same instance - of the Linux kernel. As a result, Docker Desktop can't ensure the integrity of - the kernel in the Docker Desktop Linux VM since another WSL 2 distribution could - modify shared kernel settings. In contrast, when using Hyper-V, the Docker - Desktop Linux VM has a dedicated kernel that is solely under the control of - Docker Desktop. - -The following table summarizes this. +> Docker Desktop requires WSL 2 version 2.1.5 or later. Check your version with `wsl --version` and update with `wsl --update` if needed. + +Enhanced Container Isolation provides different security levels depending on your Windows backend configuration. + +The following table compares ECI on WSL 2 and ECI on Hyper-V: | Security feature | ECI on WSL | ECI on Hyper-V | Comment | | -------------------------------------------------- | ------------ | ---------------- | --------------------- | @@ -44,65 +29,143 @@ The following table summarizes this. | Docker Desktop Linux VM protected from user access | No | Yes | On WSL, users can access Docker Engine directly or bypass Docker Desktop security settings. | | Docker Desktop Linux VM has a dedicated kernel | No | Yes | On WSL, Docker Desktop can't guarantee the integrity of kernel level configs. | -In general, using ECI with Hyper-V is more secure than with WSL 2. But WSL 2 -offers advantages for performance and resource utilization on the host machine, -and it's an excellent way for users to run their favorite Linux distribution on -Windows hosts and access Docker from within. +WSL 2 security gaps include: + +- Direct VM access: Users can bypass Docker Desktop security by accessing the VM directly: `wsl -d docker-desktop`. This gives users root access to modify Docker Engine settings and bypass +Settings Management configurations. +- Shared kernel vulnerability: All WSL 2 distributions share the same Linux kernel instance. Other WSL distributions can modify kernel settings that affect Docker Desktop's security. + +### Recommendation + +Use Hyper-V backend for maximum security. WSL 2 offers better performance and resource +utilization, but provides reduced security isolation. + +## Windows containers not supported + +ECI only works with Linux containers (Docker Desktop's default mode). Native Windows +containers mode isn't supported. + +## Docker Build protection varies + +Docker Build proection depends on the driver and Docker Desktop version: + +| Build drive | Protection | Version requirements | +|:------------|:-----------|:---------------------| +| `docker` (default) | Protected | Docker Desktop 4.30 and later (except WSL 2) | +| `docker` (legacy) | Not protected | Docker Desktop versions before 4.30 | +| `docker-container` | Always protected | All Docker Desktop versions | + +The following Docker Build features don't work with ECI: + +- `docker build --network=host` +- Docker Buildx entitlements: `network.host`, `security.insecure` + +### Recommendation + +Use `docker-container` build driver for builds requiring these features: + +```console +$ docker buildx create --driver docker-container --use +$ docker buildx build --network=host . +``` + +## Docker Desktop Kubernetes not protected + +The integrated Kubernetes feature doesn't benefit from ECI protection. Malicious or privileged pods can compromise the Docker Desktop VM and bypass security controls. + +### Recommendation + +Use Kubernetes in Docker (KinD) for ECI-protected Kubernetes: + +```console +$ kind create cluster +``` + +With ECI turned on, each Kubernetes node runs in an ECI-protected container, providing stronger isolation from the Docker Desktop VM. + +## Unprotected container types + +These container types currently don't benefit from ECI protection: + +- Docker Extensions: Extension containers run without ECI protection +- Docker Debug: Docker Debug containers bypass ECI restrictions +- Kubernetes pods: When using Docker Desktop's integrated Kubernetes + +### Recommendation + +Only use extensions from trusted sources and avoid Docker Debug in security-sensitive environments. + +## Global command restrictions + +Command lists apply to all containers allowed to mount the Docker socket. You can't configure different command restrictions per container image. + +## Local-only images not supported + +You can't allow arbitrary local-only images (images not in a registry) to mount the Docker socket, unless they're: + +- Derived from an allowed base image (with `allowDerivedImages: true`) +- Using the wildcard allowlist (`"*"`, Docker Desktop 4.36 and later) + +## Unsupported Docker commands + +These Docker commands aren't yet supported in command list restrictions: + +- `compose`: Docker Compose commands +- `dev`: Development environment commands +- `extension`: Docker Extensions management +- `feedback`: Docker feedback submission +- `init`: Docker initialization commands +- `manifest`: Image manifest management +- `plugin`: Plugin management +- `sbom`: Software Bill of Materials +- `scout`: Docker Scout commands +- `trust`: Image trust management + +## Performance considerations -### ECI protection for Docker builds with the "docker" driver +### Derived images impact -Prior to Docker Desktop 4.30, `docker build` commands that use the buildx -`docker` driver (the default) are not protected by ECI, in other words the build runs -rootful inside the Docker Desktop VM. +Enabling `allowDerivedImages: true` adds approximately 1 second to container startup time for image validation. -Starting with Docker Desktop 4.30, `docker build` commands that use the buildx -`docker` driver are protected by ECI, except when Docker Desktop is configured to use WSL 2 -(on Windows hosts). +### Registry dependencies -Note that `docker build` commands that use the `docker-container` driver are -always protected by ECI. +- Docker Desktop periodically fetches image digests from registries for validation +- Initial container starts require registry access to validate allowed images +- Network connectivity issues may cause delays in container startup -### Docker Build and Buildx have some restrictions +### Image digest validation -With ECI enabled, Docker build `--network=host` and Docker Buildx entitlements -(`network.host`, `security.insecure`) are not allowed. Builds that require -these won't work properly. +When allowed images are updated in registries, local containers may be unexpectedly blocked until you refresh the local image: -### Kubernetes pods are not yet protected +```console +$ docker image rm +$ docker pull +``` -When using the Docker Desktop integrated Kubernetes, pods are not yet protected -by ECI. Therefore a malicious or privileged pod can compromise the Docker -Desktop Linux VM and bypass security controls. +## Version compatibility -As an alternative, you can use the [K8s.io KinD](https://kind.sigs.k8s.io/) tool -with ECI. In this case, each Kubernetes node runs inside an ECI-protected -container, thereby more strongly isolating the Kubernetes cluster away from the -underlying Docker Desktop Linux VM (and Docker Engine within). No special -arrangements are needed, just enable ECI and run the KinD tool as usual. +ECI features have been introduced across different Docker Desktop versions: -### Extension containers are not yet protected +- Docker Desktop 4.36 and later: Wildcard allowlist support (`"*"`) and improved derived images handling +- Docker Desktop 4.34 and later: Derived images support (`allowDerivedImages`) +- Docker Desktop 4.30 and later: Docker Build protection with default driver (except WSL 2) +- Docker Desktop 4.13 and later: Core ECI functionality -Extension containers are also not yet protected by ECI. Ensure you extension -containers come from trusted entities to avoid issues. +For the latest feature availability, use the most recent Docker Desktop version. -### Docker Debug containers are not yet protected +## Production compatibility -[Docker Debug](/reference/cli/docker/debug.md) containers -are not yet protected by ECI. +### Container behavior differences -### Native Windows containers are not supported +Most containers run identically with and without ECI. However, some advanced workloads may behave differently: -ECI only works when Docker Desktop is in Linux containers mode (the default, -most common mode). It's not supported when Docker Desktop is configured in -native Windows containers mode (i.e., it's not supported on Windows hosts, when -Docker Desktop is switched from its default Linux mode to native Windows mode). +- Containers requiring kernel module loading +- Workloads modifying global kernel settings (BPF, sysctl) +- Applications expecting specific privilege escalation behavior +- Tools requiring direct hardware device access -### Use in production +Test advanced workloads with ECI in development environments before production deployment to ensure compatibility. -In general users should not experience differences between running a container -in Docker Desktop with ECI enabled, which uses the Sysbox runtime, and running -that same container in production, through the standard OCI `runc` runtime. +### Runtime considerations -However in some cases, typically when running advanced or privileged workloads in -containers, users may experience some differences. In particular, the container -may run with ECI but not with `runc`, or vice-versa. +Containers using the Sysbox runtime (with ECI) may have subtle differences compared to standard OCI runc runtime in production. These differences typically only affect privileged or system-level operations. From 3cbb955f58ef899b76e264e630355718dd48406f Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Tue, 12 Aug 2025 14:18:35 -0400 Subject: [PATCH 03/10] add the rest of security --- .../enterprise/security/access-tokens.md | 148 +++++++------ .../hardened-desktop/air-gapped-containers.md | 195 +++++++++++++++--- .../image-access-management.md | 93 +++++++-- .../registry-access-management.md | 176 +++++++++------- .../troubleshoot/troubleshoot-provisioning.md | 12 +- .../troubleshoot/troubleshoot-sso.md | 28 ++- content/manuals/security/2fa/_index.md | 60 ++++-- content/manuals/security/2fa/disable-2fa.md | 22 -- .../manuals/security/2fa/new-recovery-code.md | 22 -- .../security/2fa/recover-hub-account.md | 31 ++- content/manuals/security/access-tokens.md | 100 +++++---- content/manuals/security/faqs/containers.md | 50 ++--- content/manuals/security/faqs/general.md | 91 +++----- .../security/faqs/networking-and-vms.md | 32 ++- .../faqs/single-sign-on/domain-faqs.md | 26 +-- .../faqs/single-sign-on/enforcement-faqs.md | 54 ++--- .../security/faqs/single-sign-on/faqs.md | 59 ++---- .../security/faqs/single-sign-on/idp-faqs.md | 57 ++--- .../faqs/single-sign-on/users-faqs.md | 102 +++------ layouts/shortcodes/admin-registry-access.html | 52 ----- 20 files changed, 704 insertions(+), 706 deletions(-) delete mode 100644 content/manuals/security/2fa/disable-2fa.md delete mode 100644 content/manuals/security/2fa/new-recovery-code.md delete mode 100644 layouts/shortcodes/admin-registry-access.html diff --git a/content/manuals/enterprise/security/access-tokens.md b/content/manuals/enterprise/security/access-tokens.md index ce84a1893e61..9b62c122c48b 100644 --- a/content/manuals/enterprise/security/access-tokens.md +++ b/content/manuals/enterprise/security/access-tokens.md @@ -1,69 +1,56 @@ --- title: Organization access tokens -description: Learn how to create and manage organization access tokens - to securely push and pull images programmatically. -keywords: docker hub, security, OAT, organization access token linkTitle: Organization access tokens +description: Create and manage organization access tokens to securely authenticate automated systems and CI/CD pipelines with Docker Hub +keywords: organization access tokens, OAT, docker hub security, programmatic access, automation aliases: - /security/for-admins/access-tokens/ --- {{< summary-bar feature_name="OATs" >}} +Organization access tokens (OATs) provide secure, programmatic access to Docker Hub for automated systems, CI/CD pipelines, and other business-critical tasks. Unlike personal access tokens tied to individual users, OATs are associated with your organization and can be managed by any organization owner. + > [!WARNING] > -> Organization access tokens (OATs) are incompatible with Docker Desktop, -> [Image Access Management (IAM)](/manuals/enterprise/security/hardened-desktop/image-access-management.md), and [Registry Access Management (RAM)](/manuals/enterprise/security/hardened-desktop/registry-access-management.md). -> -> If you use Docker Desktop, IAM, or RAM, you must use personal -> access tokens instead. - -An organization access token (OAT) is like a [personal access token -(PAT)](/security/access-tokens/), but an OAT is associated with -an organization and not a single user account. Use an OAT instead of a PAT to -let business-critical tasks access Docker Hub repositories without connecting -the token to single user. You must have a [Docker Team or Business -subscription](/subscription/core-subscription/details/) to use OATs. - -OATs provide the following advantages: - -- You can investigate when the OAT was last used and then disable or delete it - if you find any suspicious activity. -- You can limit what each OAT has access to, which limits the impact if an OAT - is compromised. -- All company or organization owners can manage OATs. If one owner leaves the - organization, the remaining owners can still manage the OATs. -- OATs have their own Docker Hub usage limits that don't count towards your - personal account's limits. - -If you have existing [service accounts](/docker-hub/service-accounts/), -Docker recommends that you replace the service accounts with OATs. OATs offer -the following advantages over service accounts: - -- Access permissions are easier to manage with OATs. You can assign access - permissions to OATs, while service accounts require using teams for access - permissions. -- OATs are easier to manage. OATs are centrally managed in the Admin Console. - For service accounts, you may need to sign in to that service account to - manage it. If using single sign-on enforcement and the service account is not - in your IdP, you may not be able to sign in to the service account to manage - it. -- OATs are not associated with a single user. If a user with access to the - service account leaves your organization, you may lose access to the service - account. OATs can be managed by any company or organization owner. +> Organization access tokens are incompatible with Docker Desktop, Image Access Management, and Registry Access Management. If you use these features, use [personal access tokens](/manuals/security/access-tokens.md) instead. + +## When to use organization access tokens + +Use OATs for automated systems that need Docker Hub access without depending on individual user accounts: + +- CI/CD pipelines: Build and deployment systems that push and pull images +- Production systems: Applications that pull images during deployment +- Monitoring tools: Systems that need to check repository status or pull images +- Backup systems: Tools that periodically pull images for archival +- Integration services: Third-party tools that integrate with your Docker Hub repositories + +## Prerequisites + +To create and use organization access tokens, you must have: + +- A Docker Team or Business subscription +- Owner permissions +- Repositories you want to grant access to + +## Key benefits + +Benefits of using organization access tokens include: + +- Organizational ownership: Not tied to individual users who might leave the company +- Shared management: All organization owners can create and manage OATs +- Separate usage limits: OATs have their own Docker Hub rate limits, not counting against personal accounts +- Better security audit: Track when tokens were last used and identify suspicious activity +- Granular permissions: Limit access to specific repositories and operations ## Create an organization access token -> [!IMPORTANT] -> -> Treat access tokens like a password and keep them secret. Store your tokens -> securely in a credential manager for example. +Owners can create tokens with these limits: -Company or organization owners can create up to: -- 10 OATs for organizations with a Team subscription -- 100 OATs for organizations with a Business subscription +- Team subscription: Up to 10 OATs per organization +- Business subscription: Up to 100 OATs per organization -Expired tokens count towards the total amount of tokens. +Expired tokens count toward your total limit. To create an OAT: @@ -71,51 +58,56 @@ To create an OAT: organization. 1. Select **Admin Console**, then **Access tokens**. 1. Select **Generate access token**. -1. Add a label and optional description for your token. Use something that -indicates the use case or purpose of the token. -1. Select the expiration date for the token. -1. Expand the **Repository** drop-down to set access permission -scopes for your token. To set Repository access scopes: - 1. Optional. Select **Read public repositories**. - 1. Select **Add repository** and choose a repository from the drop-down. - 1. Set the scopes for your repository — **Image Push** or - **Image Pull**. - 1. Add more repositories as needed. You can add up to 50 repositories. -1. Optional. Expand the **Organization** drop-down and select the -**Allow management access to this organization's resources** checkbox. This -setting enables organization management scopes for your token. The following -organization management scopes are available: +1. Configure token details: + - Label: Descriptive name indicating the token's purpose + - Description (optional): Additional details + - Expiration date: When the token should expire +1. Expand the **Repository** drop-down to set access permissions: + 1. Optional. Select **Read public repositories** for access to public repositories. + 1. Select **Add repository** and choose a repository from the drop-down. + 1. Set permissions for each repository: **Image Pull** or **Image Push**. + 1. Add up to 50 repositories as needed. +1. Optional. Configure organization management permissions by expanding the **Organization** drop-down and selecting the **Allow management access to this organization's resources**: - **Member Edit**: Edit members of the organization - **Member Read**: Read members of the organization - **Invite Edit**: Invite members to the organization - **Invite Read**: Read invites to the organization - **Group Edit**: Edit groups of the organization - **Group Read**: Read groups of the organization -1. Select **Generate token**. Copy the token that appears on the screen - and save it. You won't be able to retrieve the token once you exit the - screen. +1. Select **Generate token**. Copy the token that appears on the screen and save it. You won't be able to retrieve the token once you exit the screen. -## Use an organization access token +> [!IMPORTANT] +> +> Treat organization access tokens like passwords. Store them securely in a credential manager and never commit them to source code repositories. -You can use an organization access token when you sign in using Docker CLI. +## Use organization access tokens -Sign in from your Docker CLI client with the following command, replacing -`YOUR_ORG` with your organization name: +Sign in to the Docker CLI using your organization access token: ```console -$ docker login --username +$ docker login --username +Password: [paste your OAT here] ``` -When prompted for a password, enter your organization access token instead of a -password. +When prompted for a password, enter your organization access token. ## Modify existing tokens -You can rename, update the description, update the repository access, -deactivate, or delete a token as needed. +To manage existing tokens: 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. 1. Select **Admin Console**, then **Access tokens**. -1. Select the actions menu in the token row, then select **Deactivate**, **Edit**, or **Delete** to modify the token. For **Inactive** tokens, you can only select **Delete**. -1. If editing a token, select **Save** after specifying your modifications. +1. Select the actions menu in the token row, you can: + - **Edit** + - **Deactivate** + - **Delete** +1. Select **Save** after making changes to a token. + +## Organization access token best practices + +- Regular token rotation: Set reasonable expiration dates and rotate tokens regularly to minimize security risks. +- Principle of least privilege: Grant only the minimum repository access and permissions needed for each use case. +- Monitor token usage: Regularly review when tokens were last used to identify unused or suspicious tokens. +- Secure storage: Store tokens in secure credential management systems, never in plain text or source code. +- Immediate revocation: Deactivate or delete tokens immediately if they're compromised or no longer needed. diff --git a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md index 54d640486f6a..073b474a84a6 100644 --- a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md +++ b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md @@ -1,7 +1,7 @@ --- title: Air-gapped containers -description: Air-gapped containers - What it is, benefits, and how to configure it. -keywords: air gapped, security, Docker Desktop, configuration, proxy, network +description: Control container network access with air-gapped containers using custom proxy rules and network restrictions +keywords: air gapped containers, network security, proxy configuration, container isolation, docker desktop aliases: - /desktop/hardened-desktop/settings-management/air-gapped-containers/ - /desktop/hardened-desktop/air-gapped-containers/ @@ -10,22 +10,32 @@ aliases: {{< summary-bar feature_name="Air-gapped containers" >}} -Air-gapped containers let you restrict containers from accessing network resources, limiting where data can be uploaded to or downloaded from. +Air-gapped containers let you restrict container network access by controlling where containers can send and receive data. This feature applies custom proxy rules to container network traffic, helping secure environments where containers shouldn't have unrestricted internet access. -Docker Desktop can apply a custom set of proxy rules to network traffic from containers. The proxy can be configured to: +Docker Desktop can configure container network traffic to accept connections, reject connections, or tunnel through HTTP or SOCKS proxies. You control which TCP ports the policy applies to and whether to use a single proxy or per-destination policies via Proxy Auto-Configuration (PAC) files. -- Accept network connections -- Reject network connections -- Tunnel through an HTTP or SOCKS proxy +## Use cases for air-gapped containers -You can choose: +Air-gapped containers help organizations maintain security in restricted environments: -- Which outgoing TCP ports the policy applies to. For example, only certain ports, `80`, `443` or all with `*`. -- Whether to forward to a single HTTP or SOCKS proxy, or to have a policy per destination via a Proxy Auto-Configuration (PAC) file. +- Secure development environments: Prevent containers from accessing unauthorized external services +- Compliance requirements: Meet regulatory standards that require network isolation +- Data loss prevention: Block containers from uploading sensitive data to external services +- Supply chain security: Control which external resources containers can access during builds +- Corporate network policies: Enforce existing network security policies for containerized applications -## Configuration +## Prerequisites -Assuming [enforced sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) and [Settings Management](settings-management/_index.md) are enabled, add the new proxy configuration to the `admin-settings.json` file. For example: +Before configuring air-gapped containers: + +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure users authenticate with your organization +- Have a Docker Business subscription +- Configure [Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/_index.md) to manage organization policies +- Download Docker Desktop 4.29 or later + +## Configure air-gapped containers + +Add the container proxy to your [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md). For example: ```json { @@ -42,24 +52,66 @@ Assuming [enforced sign-in](/manuals/enterprise/security/enforce-sign-in/_index. } ``` -The `containersProxy` setting describes the policy which is applied to traffic from containers. The valid fields are: +### Configuration parameters + +The `containersProxy` setting controls network policies applied to container traffic: -- `locked`: If true, it is not possible for developers to override these settings. If false the settings are interpreted as default values which the developer can change. -- `mode`: Same meaning as with the existing `proxy` setting. Possible values are `system` and `manual`. -- `http`, `https`, `exclude`: Same meaning as with the `proxy` setting. Only takes effect if `mode` is set to `manual`. -- `pac` : URL for a PAC file. Only takes effect if `mode` is `manual`, and is considered higher priority than `http`, `https`, `exclude`. -- `transparentPorts`: A comma-separated list of ports (e.g. `"80,443,8080"`) or a wildcard (`*`) indicating which ports should be proxied. +| Parameter | Description | Value | +|-----------|-------------|-------| +| `locked` | Prevents developers from overriding settings | `true` (locked), `false` (default) | +| `mode` | Proxy configuration method | `system` (use system proxy), `manual` (custom) | +| `http` | HTTP proxy server | URL (e.g., `"http://proxy.company.com:8080"`) | +| `https` | HTTPS proxy server | URL (e.g., `"https://proxy.company.com:8080"`) | +| `exclude` | Bypass proxy for these addresses | Array of hostnames/IPs | +| `pac` | Proxy Auto-Configuration file URL | URL to PAC file | +| `transparentPorts` | Ports subject to proxy rules | Comma-separated ports or wildcard (`"*"`) | -> [!IMPORTANT] -> -> Any existing `proxy` setting in the `admin-settings.json` file continues to apply to traffic from the app on the host. -> If the PAC file download fails, the containers block the request to the target URL. +### Configuration examples -## Example PAC file +**Block all external access:** -For general information about PAC files, see the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file). +```json +"containersProxy": { + "locked": true, + "mode": "manual", + "http": "", + "https": "", + "exclude": [], + "transparentPorts": "*" +} +``` -The following is an example PAC file: +**Allow specific internal services:** + +```json +"containersProxy": { + "locked": true, + "mode": "manual", + "http": "", + "https": "", + "exclude": ["internal.company.com", "10.0.0.0/8"], + "transparentPorts": "80,443" +} +``` + +**Route through corporate proxy:** + +```json +"containersProxy": { + "locked": true, + "mode": "manual", + "http": "http://corporate-proxy.company.com:8080", + "https": "http://corporate-proxy.company.com:8080", + "exclude": ["localhost", "*.company.local"], + "transparentPorts": "*" +} +``` + +## Proxy Auto-Configuration (PAC) files + +PAC files provide fine-grained control over container network access by defining rules for different destinations. + +### Basic PAC file structure ```javascript function FindProxyForURL(url, host) { @@ -73,17 +125,92 @@ function FindProxyForURL(url, host) { } ``` -The `url` parameter is either `http://host_or_ip:port` or `https://host_or_ip:port`. +### PAC file return values -The hostname is normally available for outgoing requests on port `80` and `443`, but for other cases there is only an IP address. +| Return value | Action | +|--------------|--------| +| `PROXY host:port` | Route through HTTP proxy at specified host and port | +| `SOCKS5 host:port` | Route through SOCKS5 proxy at specified host and port | +| `DIRECT` | Allow direct connection without proxy | +| `PROXY reject.docker.internal:any_port` | Block the request completely | -The `FindProxyForURL` can return the following values: +### Advanced PAC file example + +```javascript +function FindProxyForURL(url, host) { + // Allow access to Docker Hub for approved base images + if (dnsDomainIs(host, ".docker.io") || host === "docker.io") { + return "PROXY corporate-proxy.company.com:8080"; + } + + // Allow internal package repositories + if (localHostOrDomainIs(host, 'nexus.company.com') || + localHostOrDomainIs(host, 'artifactory.company.com')) { + return "DIRECT"; + } + + // Allow development tools on specific ports + if (url.indexOf(":3000") > 0 || url.indexOf(":8080") > 0) { + if (isInNet(host, "10.0.0.0", "255.0.0.0")) { + return "DIRECT"; + } + } + + // Block access to developer's localhost to prevent data exfiltration + if (host === "host.docker.internal" || host === "localhost") { + return "PROXY reject.docker.internal:1234"; + } + + // Block all other external access + return "PROXY reject.docker.internal:1234"; +} +``` + +## How air-gapped containers work + +Air-gapped containers operate by intercepting container network traffic and applying proxy rules: + +1. Traffic interception: Docker Desktop intercepts all outgoing network connections from containers +1. Port filtering: Only traffic on specified ports (`transparentPorts`) is subject to proxy rules +1. Rule evaluation: PAC file rules or static proxy settings determine how to handle each connection +1. Connection handling: Traffic is allowed directly, routed through a proxy, or blocked based on the rules + +Some important considerations include: + +- The existing `proxy` setting continues to apply to Docker Desktop application traffic on the host +- If PAC file download fails, containers block requests to target URLs +- URL parameter format is `http://host_or_ip:port` or `https://host_or_ip:port` +- Hostname is available for ports 80 and 443, but only IP addresses for other ports + +## Verify air-gapped container configuration + +After applying the configuration, test that container network restrictions work: + +Test blocked access: + +```console +$ docker run --rm alpine wget -O- https://www.google.com +# Should fail or timeout based on your proxy rules +``` + +Test allowed access: + +```console +$ docker run --rm alpine wget -O- https://internal.company.com +# Should succeed if internal.company.com is in your exclude list or PAC rules +``` + +Test proxy routing: + +```console +$ docker run --rm alpine wget -O- https://docker.io +# Should succeed if routed through approved proxy +``` -- `PROXY host_or_ip:port`: Tunnels this request through the HTTP proxy `host_or_ip:port` -- `SOCKS5 host_or_ip:port`: Tunnels this request through the SOCKS proxy `host_or_ip:port` -- `DIRECT`: Lets this request go direct, without a proxy -- `PROXY reject.docker.internal:any_port`: Rejects this request +## Security considerations -In this particular example, HTTP and HTTPS requests for `internal.corp` are sent via the HTTP proxy `10.0.0.1:3128`. Requests to connect to IPs on the subnet `192.168.0.0/24` connect directly. All other requests are blocked. +- Network policy enforcement: Air-gapped containers work at the Docker Desktop level. Advanced users might bypass restrictions through various means, so consider additional network-level controls for high-security environments. +- Development workflow impact: Overly restrictive policies can break legitimate development workflows. Test thoroughly and provide clear exceptions for necessary services. +- PAC file management: Host PAC files on reliable internal infrastructure. Failed PAC downloads result in blocked container network access. +- Performance considerations: Complex PAC files with many rules may impact container network performance. Keep rules simple and efficient. -To restrict traffic connecting to ports on the developers local machine, [match the special hostname `host.docker.internal`](/manuals/desktop/features/networking.md#i-want-to-connect-from-a-container-to-a-service-on-the-host). diff --git a/content/manuals/enterprise/security/hardened-desktop/image-access-management.md b/content/manuals/enterprise/security/hardened-desktop/image-access-management.md index 06dd8dea425a..48a0c3cfc346 100644 --- a/content/manuals/enterprise/security/hardened-desktop/image-access-management.md +++ b/content/manuals/enterprise/security/hardened-desktop/image-access-management.md @@ -1,7 +1,7 @@ --- -description: Manage Docker Hub image access with Image Access Management, restricting developers to trusted images for enhanced security -keywords: image, access, management, trusted content, permissions, Docker Business feature, security, admin title: Image Access Management +description: Control which Docker Hub images developers can access with Image Access Management for enhanced supply chain security +keywords: image access management, docker official images, verified publisher, supply chain security, docker business tags: [admin] aliases: - /docker-hub/image-access-management/ @@ -14,35 +14,92 @@ weight: 40 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -Image Access Management gives you control over which types of images, such as Docker Official Images, Docker Verified Publisher Images, or community images, your developers can pull from Docker Hub. +Image Access Management lets administrators control which types of images developers can pull from Docker Hub. This prevents developers from accidentally using untrusted community images that could pose security risks to your organization. -For example, a developer, who is part of an organization, building a new containerized application could accidentally use an untrusted, community image as a component of their application. This image could be malicious and pose a security risk to the company. Using Image Access Management, the organization owner can ensure that the developer can only access trusted content like Docker Official Images, Docker Verified Publisher Images, or the organization’s own images, preventing such a risk. +With Image Access Management, you can restrict access to: + +- Docker Official Images: Curated images maintained by Docker +- Docker Verified Publisher Images: Images from trusted commercial publishers +- Organization images: Your organization's private repositories +- Community images: Public images from individual developers + +## Why use Image Access Management? + +Image Access Management helps prevent supply chain attacks by ensuring developers only use trusted container images. For example, a developer building a new application might accidentally use a malicious community image as a component. Image Access Management prevents this by restricting access to only approved image types. + +Common security scenarios include: + +- Prevent use of unmaintained or malicious community images +- Ensure developers use only vetted, official base images +- Control access to commercial third-party images +- Maintain consistent security standards across development teams ## Prerequisites -You first need to [enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure that all Docker Desktop developers authenticate with your organization. Since Image Access Management requires a Docker Business subscription, enforced sign-in guarantees that only authenticated users have access and that the feature consistently takes effect across all users, even though it may still work without enforced sign-in. +Before configuring Image Access Management, you must: + +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure users authenticate with your organization +- Use [personal access tokens (PATs)](/manuals/security/access-tokens.md) for authentication (Organization access tokens aren't supported) +- Have a Docker Business subscription > [!IMPORTANT] > -> You must use [personal access tokens (PATs)](/manuals/security/access-tokens.md) with Image Access Management. Organization access tokens (OATs) are not compatible. +> Image Access Management only takes effect when users are signed in to Docker Desktop with organization credentials. + +## Configure image access + +To configure Image Access Management: + +1. Sign in to [Docker Home](https://app.docker.com) and select your organization. +1. Select **Admin Console**, then **Image access**. +1. Use the **toggle** to enable image access. +1. Select which image types to allow: + - Organization images: Images from your organization (always allowed by default). These can be public or private images created by members within your organization. + - Community images: Images contributed by various users that may pose security risks. This category includes Docker-Sponsored Open Source images and is turned off by default. + - Docker Verified Publisher Images: Images from Docker partners in the Verified Publisher program, qualified for secure supply chains. + - Docker Official Images: Curated Docker repositories that provide OS repositories, best practices for Dockerfiles, drop-in solutions, and timely security updates. + +Once restrictions are applied, organization members can view the permissions page in read-only format. + +> [!NOTE] +> +> Image Access Management is turned off by default. Organization owners have access to all images regardless of policy settings. + +## Verify access restrictions + +After configuring Image Access Management, test that restrictions work correctly. + +When developers pull allowed image types: + +```console +$ docker pull nginx # Docker Official Image +# Pull succeeds if Docker Official Images are allowed +``` + +When developers pull blocked image types: -## Configure +```console +$ docker pull someuser/custom-image # Community image +Error response from daemon: image access denied: community images not allowed +``` -{{< tabs >}} -{{< tab name="Admin Console" >}} +Image access restrictions apply to all Docker Hub operations including pulls, builds using `FROM` instructions, and Docker Compose services. -{{% admin-image-access product="admin" %}} +## Security implementation -{{< /tab >}} -{{< tab name="Docker Hub" >}} +Start with the most restrictive policy and gradually expand based on legitimate business needs: -{{% include "hub-org-management.md" %}} +1. Start with: Docker Official Images and Organization images +2. Add if needed: Docker Verified Publisher Images for commercial tools +3. Carefully evaluate: Community images only for specific, vetted use cases -{{% admin-image-access product="hub" %}} +Other security recommendations include: -{{< /tab >}} -{{< /tabs >}} +- Monitor usage patterns: Review which images developers are attempting to pull, identify legitimate requests for additional image types, regularly audit approved image categories for continued relevance, and use Docker Desktop analytics to monitor usage patterns. +- Layer security controls: Image Access Management works best with Registry Access Management to control which registries developers can access, Enhanced Container Isolation to secure containers at runtime, and Settings Management to control Docker Desktop configuration. -## More resources +## Scope and bypass considerations -- [Video: Hardened Desktop Image Access Management](https://www.youtube.com/watch?v=r3QRKHA1A5U) +- Image Access Management only controls access to Docker Hub images. Images from other registries aren't affected by these policies. Use [Registry Access Management](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) to control access to other registries. +- Users can potentially bypass Image Access Management by signing out of Docker Desktop (unless sign-in is enforced), using images from other registries that aren't restricted, or using registry mirrors or proxies. Enforce sign-in and combine with Registry Access Management for comprehensive control. +- Image restrictions apply to Dockerfile `FROM` instructions, Docker Compose services using restricted images will fail, multi-stage builds may be affected if intermediate images are restricted, and CI/CD pipelines using diverse image types may be impacted. diff --git a/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md b/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md index 520cc71d58ea..ec4c53e96900 100644 --- a/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md +++ b/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md @@ -1,7 +1,7 @@ --- -description: Control access to approved registries with Registry Access Management, ensuring secure Docker Desktop usage -keywords: registry, access, management, permissions, Docker Business feature, security, admin title: Registry Access Management +description: Control access to approved container registries with Registry Access Management for secure Docker Desktop usage +keywords: registry access management, container registry, security controls, docker business, admin controls tags: [admin] aliases: - /desktop/hardened-desktop/registry-access-management/ @@ -14,94 +14,132 @@ weight: 30 {{< summary-bar feature_name="Registry access management" >}} -With Registry Access Management (RAM), administrators can ensure that their -developers using Docker Desktop only access allowed registries. This is done -through the Registry Access Management dashboard in Docker Hub or the -Docker Admin Console. +Registry Access Management (RAM) lets administrators control which container registries developers can access through Docker Desktop. This DNS-level filtering ensures developers only pull and push images from approved registries, improving supply chain security. -Registry Access Management supports both cloud and on-prem registries. This -feature operates at the DNS level and therefore is compatible with all -registries. You can add any hostname or domain name you’d like to include in the -list of allowed registries. However, if the registry redirects to other domains -such as `s3.amazon.com`, then you must add those domains to the list. +RAM works with all registry types including cloud services, on-premises registries, and registry mirrors. You can allow any hostname or domain, but must include redirect domains (like `s3.amazonaws.com` for some registries) in your allowlist. -Example registries administrators can allow include: +## Supported registries - - Docker Hub. This is enabled by default. - - Amazon ECR - - GitHub Container Registry - - Google Container Registry - - GitLab Container Registry - - Nexus - - Artifactory +Registry Access Management works with any container registry, including: + + - Docker Hub (allowed by default) +- Cloud registries: Amazon ECR, Google Container Registry, Azure Container Registry +- Git-based registries: GitHub Container Registry, GitLab Container Registry +- On-premises solutions: Nexus, Artifactory, Harbor +- Registry mirrors: Including Docker Hub mirrors ## Prerequisites -You must [enforce sign-in](../enforce-sign-in/_index.md). For Registry Access -Management to take effect, Docker Desktop users must authenticate to your -organization. Enforcing sign-in ensures that your Docker Desktop developers -always authenticate to your organization, even though they can authenticate -without it and the feature will take effect. Enforcing sign-in guarantees the -feature always takes effect. +Before configuring Registry Access Management, you must: + +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure users authenticate with your organization +- Use [personal access tokens (PATs)](/manuals/security/access-tokens.md) for authentication (Organization access tokens aren't supported) +- Have a Docker Business subscription + +> [!IMPORTANT] +> +> Registry Access Management only takes effect when users are signed in to Docker Desktop with organization credentials. + +## Configure registry permissions + +To configure registry permissions: + +1. Sign in to [Docker Home](https://app.docker.com) and select your organization. +1. Select **Admin Console**, then **Regsitry access**. +1. Use the **toggle** to enable registry access. By default, Docker Hub is enabled +in the registry list. +1. To add additional registries, select **Add registry** and provide +a **Registry address** and **Registry nickname**. Select **Create**. You can add +up to 100 registries. +1. Verify your registry appears in the registry list and select **Save changes**. + +Changes can take up to 24 hours to take effect. To apply them sooner, +have developers sign out and back in to Docker Desktop. > [!IMPORTANT] > -> You must use [personal access tokens (PATs)](/manuals/security/access-tokens.md) with Registry Access Management. Organization access tokens (OATs) are not compatible. +> Starting with Docker Desktop 4.36, if a developer belongs to multiple organizations with different RAM policies, only the policy for the first organization in the configuration file is enforced. + +> [!TIP] +> +> RAM restrictions also apply to Dockerfile `ADD` instructions that fetch content via URL. Include trusted registry domains in your allowlist when using `ADD` with URLs. +> +> RAM is designed for container registries, not general-purpose URLs like package mirrors or storage services. Adding too many domains may cause errors or hit system limits. + + +## Verify restrictions are working + +After users sign in to Docker Desktop with their organization credentials, Registry Access Management takes effect immediately. + +When users try to pull from a blocked registry: + +```console +$ docker pull blocked-registry.com/image:tag +Error response from daemon: registry access to blocked-registry.com is not allowed +``` + +Allowed registry access works normally: + +```console +$ docker pull allowed-registry.com/image:tag +# Pull succeeds +``` + +Registry restrictions apply to all Docker operations including pulls, pushes, +and builds that reference external registries. -## Configure Registry Access Management permissions +## Registry limits and platform constraints -{{< tabs >}} -{{< tab name="Admin Console" >}} +Registry Access Management has these limits and platform-specific behaviors: -{{% admin-registry-access product="admin" %}} +- Maximum allowlist size: 100 registries or domains per organization +- DNS-based filtering: Restrictions work at the hostname level, not IP addresses +- Redirect domains required: Must include all domains a registry redirects to (CDN endpoints, storage services) +- Windows containers: Windows image operations aren't restricted by default. Turn on **Use proxy for Windows Docker daemon** in Docker Desktop settings to apply restrictions +- WSL 2 requirements: Requires Linux kernel 5.4 or later, restrictions apply to all WSL 2 distributions -{{< /tab >}} -{{< tab name="Docker Hub" >}} +## Build and deployment restrictions -{{% include "hub-org-management.md" %}} +These scenarios are not restricted by Registry Access Management: -{{% admin-registry-access product="hub" %}} +- Docker buildx with Kubernetes driver +- Docker buildx with custom docker-container driver +- Some Docker Debug and Kubernetes image pulls (even if Docker Hub is blocked) +- Images previously cached by registry mirrors may still be blocked if the source registry is restricted -{{< /tab >}} -{{< /tabs >}} +## Security bypass considerations -## Verify the restrictions +Users can potentially bypass Registry Access Management through: -The new Registry Access Management policy takes effect after the developer -successfully authenticates to Docker Desktop using their organization -credentials. If a developer attempts to pull an image from a disallowed -registry via the Docker CLI, they receive an error message that the organization -has disallowed this registry. +- Local proxies or DNS manipulation +- Signing out of Docker Desktop (unless sign-in is enforced) +- Network-level modifications outside Docker Desktop's control -## Caveats +To maximize security effectiveness: -There are certain limitations when using Registry Access Management: +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to prevent bypass through sign-out +- Implement additional network-level controls for complete protection +- Use Registry Access Management as part of a broader security strategy -- You can add up to 100 registries/domains. -- Windows image pulls and image builds are not restricted by default. For -Registry Access Management to take effect on Windows Container mode, you must -allow the Windows Docker daemon to use Docker Desktop's internal proxy by -selecting the [Use proxy for Windows Docker daemon](/manuals/desktop/settings-and-maintenance/settings.md#proxies) -setting. -- Builds such as `docker buildx` using a Kubernetes driver are not restricted. -- Builds such as `docker buildx` using a custom docker-container driver are not -restricted. -- Blocking is DNS-based. You must use a registry's access control mechanisms to -distinguish between “push” and “pull”. -- WSL 2 requires at least a 5.4 series Linux kernel (this does not apply to -earlier Linux kernel series). -- Under the WSL 2 network, traffic from all Linux distributions is restricted. -This will be resolved in the updated 5.15 series Linux kernel. -- Images pulled by Docker Desktop when Docker Debug or Kubernetes is enabled, -are not restricted by default even if Docker Hub is blocked by RAM. -- If Docker Hub access is restricted by RAM, pulls on images originating from Docker Hub are restricted even if the image has been previously cached by a registry mirror. See [Using Registry Access Management (RAM) with a registry mirror](/manuals/docker-hub/image-library/mirror.md). +## Registry allowlist best practices -Also, Registry Access Management operates on the level of hosts, not IP -addresses. Developers can bypass this restriction within their domain -resolution, for example by running Docker against a local proxy or modifying -their operating system's `sts` file. Blocking these forms of manipulation is -outside the remit of Docker Desktop. +- Include all registry domains: Some registries redirect to multiple +domains. For AWS ECR, include: -## More resources + ```text + your-account.dkr.ecr.us-west-2.amazonaws.com + amazonaws.com + s3.amazonaws.com + ``` -- [Video: Hardened Desktop Registry Access Management](https://www.youtube.com/watch?v=l9Z6WJdJC9A) +- Practice regular allowlist maintenance: + - Remove unused registries periodically + - Add newly approved registries as needed + - Update domain names that may have changed + - Monitor registry usage through Docker Desktop analytics +- Test configuration changes: + - Verify registry access after making allowlist updates + - Check that all necessary redirect domains are included + - Ensure development workflows aren't disrupted + - Combine with [Enhanced Container Isolation](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md) for comprehensive protection + \ No newline at end of file diff --git a/content/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md b/content/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md index ba720ae8ec1f..e3c2d5373a74 100644 --- a/content/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md +++ b/content/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md @@ -1,17 +1,15 @@ --- -description: Learn how to troubleshoot common user provisioning issues. -keywords: scim, jit, provision, troubleshoot, group mapping title: Troubleshoot provisioning linkTitle: Troubleshoot provisioning +description: Troubleshoot common user provisioning issues with SCIM and Just-in-Time provisioning +keywords: SCIM troubleshooting, user provisioning, JIT provisioning, group mapping, attribute conflicts tags: [Troubleshooting] toc_max: 2 aliases: - /security/troubleshoot/troubleshoot-provisioning/ --- -If you experience issues with user roles, attributes, or unexpected account -behavior with user provisioning, this guide provides troubleshooting -recommendations to resolve conflicts. +This page helps troubleshoot common user provisioning issues including user roles, attributes, and unexpected account behavior with SCIM and Just-in-Time (JIT) provisioning. ## SCIM attribute values are overwritten or ignored @@ -20,7 +18,7 @@ recommendations to resolve conflicts. Typically, this scenario does not produce an error message in Docker or your IdP. This issue ususally surfaces as incorrect role or team assignment. -### Possible causes +### Causes - JIT provisioning is enabled, and Docker is using values from your IdP's SSO login flow to provision the user, which overrides @@ -68,7 +66,7 @@ in your IdP configuration. ## SCIM updates don't apply to existing users -### Possible causes +### Causes User accounts were originally created manually or via JIT, and SCIM is not linked to manage them. diff --git a/content/manuals/enterprise/troubleshoot/troubleshoot-sso.md b/content/manuals/enterprise/troubleshoot/troubleshoot-sso.md index 79a16a026374..3efb00b8f4e1 100644 --- a/content/manuals/enterprise/troubleshoot/troubleshoot-sso.md +++ b/content/manuals/enterprise/troubleshoot/troubleshoot-sso.md @@ -1,8 +1,8 @@ --- -description: Learn how to troubleshoot common SSO issues. -keywords: sso, troubleshoot, single sign-on title: Troubleshoot single sign-on linkTitle: Troubleshoot SSO +description: Troubleshoot common Docker single sign-on configuration and authentication issues +keywords: sso troubleshooting, single sign-on errors, authentication issues, identity provider problems tags: [Troubleshooting] toc_max: 2 aliases: @@ -10,13 +10,11 @@ aliases: - /security/troubleshoot/troubleshoot-sso/ --- -While configuring or using single sign-on (SSO), you may encounter issues that -can stem from your identity provider (IdP) or Docker configuration. The -following sections describe some common SSO errors and possible solutions. +This page describes common single sign-on (SSO) errors and their solutions. Issues can stem from your identity provider (IdP) configuration or Docker settings. ## Check for errors -If you experience issues with SSO, check both the Docker Admin Console and your identity provider (IdP) for errors first. +If you experience SSO issues, check both Docker and your identity provider for errors first. ### Check Docker error logs @@ -26,7 +24,7 @@ If you experience issues with SSO, check both the Docker Admin Console and your 1. For more details on specific errors, select **View error details** next to an error message. 1. Note any errors you see on this page for further troubleshooting. -### Check for errors in your IdP +### Check identity provider errors 1. Review your IdP’s logs or audit trails for any failed authentication or provisioning attempts. 2. Confirm that your IdP’s SSO settings match the values provided in Docker. @@ -34,7 +32,7 @@ If you experience issues with SSO, check both the Docker Admin Console and your 4. If applicable, verify that your IdP correctly maps Docker's required user attributes. 5. Try provisioning a test user from your IdP and verify if they appear in Docker. -For further troubleshooting, check your IdP’s documentation. You can also contact their support team for guidance on error messages. +For further troubleshooting, check your IdP's documentation or contact their support team. ## Groups are not formatted correctly @@ -45,7 +43,7 @@ When this issue occurs, the following error message is common: Some of the groups assigned to the user are not formatted as ':'. Directory groups will be ignored and user will be provisioned into the default organization and team. ``` -### Possible causes +### Causes - Incorrect group name formatting in your identity provider (IdP): Docker requires groups to follow the format `:`. If the groups assigned to a user do not follow this format, they will be ignored. - Non-matching groups between IdP and Docker organization: If a group in your IdP does not have a corresponding team in Docker, it will not be recognized, and the user will be placed in the default organization and team. @@ -80,7 +78,7 @@ When this issue occurs, the following error message is common: User '$username' is not assigned to this SSO organization. Contact your administrator. TraceID: XXXXXXXXXXXXX ``` -### Possible causes +### Causes - User is not assigned to the organization: If Just-in-Time (JIT) provisioning is disabled, the user may not be assigned to your organization. - User is not invited to the organization: If JIT is disabled and you do not want to enable it, the user must be manually invited. @@ -125,7 +123,7 @@ When this issue occurs, the following error message is common: IdP-Initiated sign in is not enabled for connection '$ssoConnection'. ``` -### Possible causes +### Causes Docker does not support an IdP-initiated SAML flow. This error occurs when a user attempts to authenticate from your IdP, such as using the Docker SSO app tile on the sign in page. @@ -148,7 +146,7 @@ When this issue occurs, the following error message is common: Not enough seats in organization '$orgName'. Add more seats or contact your administrator. ``` -### Possible causes +### Causes This error occurs when the organization has no available seats for the user when provisioning via Just-in-Time (JIT) provisioning or SCIM. @@ -171,7 +169,7 @@ When this issue occurs, the following error message is common: Domain '$emailDomain' is not verified for your SSO connection. Contact your company administrator. TraceID: XXXXXXXXXXXXXX ``` -### Possible causes +### Causes This error occurs if the IdP authenticated a user through SSO and the User Principal Name (UPN) returned to Docker doesn’t match any of the verified domains associated to the @@ -196,7 +194,7 @@ When this issue occurs, the following error message is common: We couldn't find your session. You may have pressed the back button, refreshed the page, opened too many sign-in dialogs, or there is some issue with cookies. Try signing in again. If the issue persists, contact your administrator. ``` -### Possible causes +### Causes The following causes may create this issue: - The user pressed the back or refresh button during authentication. @@ -221,7 +219,7 @@ When this issue occurs, the following error message is common: The name ID sent by the identity provider is not an email address. Contact your company administrator. ``` -### Possible causes +### Causes The following causes may create this issue: - The IdP sends a Name ID (UPN) that does not comply with the email format required by Docker. diff --git a/content/manuals/security/2fa/_index.md b/content/manuals/security/2fa/_index.md index 3008cfab1df3..158786274b2a 100644 --- a/content/manuals/security/2fa/_index.md +++ b/content/manuals/security/2fa/_index.md @@ -1,39 +1,57 @@ --- -description: Learn how to enable two-factor authentication on your Docker account -keywords: Docker, docker, registry, security, Docker Hub, authentication, two-factor - authentication, account security title: Enable two-factor authentication for your Docker account linkTitle: Two-factor authentication +description: Enable or disable two-factor authentication on your Docker account for enhanced security and account protection +keywords: two-factor authentication, 2FA, docker hub security, account security, TOTP, authenticator app, disable 2FA aliases: - /docker-hub/2fa/ - /security/for-developers/2fa/ + - /security/2fa/disable-2fa/ --- -Two-factor authentication adds an extra layer of security to your Docker -account by requiring a unique security code when you sign in to your account. The -security code is required in addition to your password. +Two-factor authentication (2FA) adds an essential security layer to your Docker account by requiring a unique security code in addition to your password when signing in. This prevents unauthorized access even if your password is compromised. -When you enable two-factor authentication, you are also provided with a recovery -code. Each recovery code is unique and specific to your account. You can use -this code to recover your account in case you lose access to your authenticator -app. See [Recover your Docker account](recover-hub-account/). +When you turn on two-factor authentication, Docker provides a unique recovery code specific to your account. Store this code securely as it lets you recover your account if you lose access to your authenticator app. + +## Key benefits + +Two-factor authentication significantly improves your account security: + +- Protection against password breaches: Even if your password is stolen or leaked, attackers can't access your account without your second factor. +- Secure CLI access: Required for Docker CLI authentication when 2FA is turned on, ensuring automated tools use personal access tokens instead of passwords. +- Compliance requirements: Many organizations require 2FA for accessing development and production resources. +- Peace of mind: Know that your Docker repositories, images, and account settings are protected by industry-standard security practices. ## Prerequisites -You need a mobile phone with a time-based one-time password (TOTP) authenticator -application installed. Common examples include Google Authenticator or Yubico -Authenticator with a registered YubiKey. +Before turning on two-factor authentication, you need: + +- A smartphone or device with a Time-based One-time password (TOTP) authenticator app installed +- Access to your Docker account password ## Enable two-factor authentication +To turn on 2FA for your Docker account: + +1. Sign in to your [Docker account](https://app.docker.com/login). +1. Select your avatar and then from the drop-down menu, select **Account settings**. +1. Select **2FA**. +1. Enter your account password, then select **Confirm**. +1. Save your recovery code and store it somewhere safe. You can use your recovery code to recover your account in the event you lose access to your authenticator app. +1. Use a TOTP mobile app to scan the QR code or enter the text code. +1. Once you've linked your authenticator app, enter the six-digit code in the text-field. +1. Select **Enable 2FA**. + +Two-factor authentication is now active on your account. You'll need to enter a security code from your authenticator app each time you sign in. + +## Disable two-factor authentication + +> [!WARNING] +> +> Disabling two-factor authentication results in decreased security for your Docker account. + 1. Sign in to your [Docker account](https://app.docker.com/login). 2. Select your avatar and then from the drop-down menu, select **Account settings**. 3. Select **2FA**. -4. Enter your account password, then select **Confirm**. -5. Save your recovery code and store it somewhere safe. You can use your recovery code to recover your account in the event you lose access to your authenticator app. -6. Use a Time-based One-time password (TOTP) mobile app to scan the QR code or enter the text code. -7. Once you've linked your authenticator app, enter the six-digit code in the text-field. -8. Select **Enable 2FA**. - -Two-factor authentication is now enabled. The next time you sign -in to your Docker account, you will need to enter a security code. +4. Enter your password, then select **Confirm**. +5. Select **Disable 2FA**. diff --git a/content/manuals/security/2fa/disable-2fa.md b/content/manuals/security/2fa/disable-2fa.md deleted file mode 100644 index c3e2ab06c21e..000000000000 --- a/content/manuals/security/2fa/disable-2fa.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Disable two-factor authentication on your Docker account -keywords: Docker, docker, registry, security, Docker Hub, authentication, two-factor - authentication, account security, -title: Disable two-factor authentication on your Docker account -linkTitle: Disable two-factor authentication -aliases: - - /docker-hub/2fa/disable-2fa/ - - /security/for-developers/2fa/disable-2fa/ -weight: 30 ---- - -> [!WARNING] -> -> Disabling two-factor authentication results in decreased security for your -> Docker account. - -1. Sign in to your [Docker account](https://app.docker.com/login). -2. Select your avatar and then from the drop-down menu, select **Account settings**. -3. Select **2FA**. -4. Enter your password, then select **Confirm**. -5. Select **Disable 2FA**. diff --git a/content/manuals/security/2fa/new-recovery-code.md b/content/manuals/security/2fa/new-recovery-code.md deleted file mode 100644 index 1ec904930ec9..000000000000 --- a/content/manuals/security/2fa/new-recovery-code.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Generate a new 2fa recovery code -keywords: Docker, docker, registry, security, Docker Hub, authentication, two-factor - authentication, account security -title: Generate a new recovery code -aliases: - - /docker-hub/2fa/new-recovery-code/ - - /security/for-developers/2fa/new-recovery-code/ -weight: 10 ---- - -If you have lost your two-factor authentication recovery code and still have -access to your Docker Hub account, you can generate a new recovery code. - -1. Sign in to your [Docker account](https://app.docker.com/login). -2. Select your avatar and then from the drop-down menu, select **Account settings**. -3. Select **2FA**. -4. Enter your password, then select **Confirm**. -5. Select **Generate new code**. - -This generates a new code. Select the visibility icon to view the code. Remember to save your recovery code -and store it somewhere safe. \ No newline at end of file diff --git a/content/manuals/security/2fa/recover-hub-account.md b/content/manuals/security/2fa/recover-hub-account.md index d4c9d7925284..4535b6b77741 100644 --- a/content/manuals/security/2fa/recover-hub-account.md +++ b/content/manuals/security/2fa/recover-hub-account.md @@ -1,17 +1,34 @@ --- -description: Recover your Docker account -keywords: Docker, docker, registry, security, Docker Hub, authentication, two-factor - authentication title: Recover your Docker account +description: Recover your Docker account and manage two-factor authentication recovery codes +keywords: account recovery, two-factor authentication, 2FA, recovery code, docker hub security aliases: - /docker-hub/2fa/recover-hub-account/ - /security/for-developers/2fa/recover-hub-account/ + - /security/2fa/new-recovery-code/ weight: 20 --- -If you have lost access to both your two-factor authentication application and your recovery code: +This page explains how to recover your Docker account and manage recovery codes for two-factor authentication. + +## Generate a new recovery code + +If you lost your two-factor authentication recovery code but still have access to your Docker Hub account, you can generate a new recovery code. + +1. Sign in to your [Docker account](https://app.docker.com/login) with your username and password. +1. Select your avatar and from the drop-down menu, select **Account settings**. +1. Select **2FA**. +1. Enter your password, then select **Confirm**. +1. Select **Generate new code**. + +This generates a new code. Select the visibility icon to view the code. Save your recovery code and store it somewhere safe. + +## Recover your account without access + +If you lost access to both your two-factor authentication application and your recovery code: 1. Sign in to your [Docker account](https://app.docker.com/login) with your username and password. -2. Select **I've lost my authentication device** and **I've lost my recovery code**. -3. Complete the [Contact Support form](https://hub.docker.com/support/contact/?category=2fa-lockout). - You must enter the primary email address associated with your Docker ID in the **Contact Support** form for recovery instructions. +1. Select **I've lost my authentication device** and **I've lost my recovery code**. +1. Complete the [Contact Support form](https://hub.docker.com/support/contact/?category=2fa-lockout). + +You must enter the primary email address associated with your Docker ID in the Contact Support form for recovery instructions. diff --git a/content/manuals/security/access-tokens.md b/content/manuals/security/access-tokens.md index 503491451734..2d78da8c2a71 100644 --- a/content/manuals/security/access-tokens.md +++ b/content/manuals/security/access-tokens.md @@ -1,71 +1,72 @@ --- -title: Create and manage access tokens -linkTitle: Access tokens -description: Learn how to create and manage your personal Docker access tokens - to securely push and pull images programmatically. -keywords: docker hub, hub, security, PAT, personal access token +title: Personal access tokens +linkTitle: Personal access tokens +description: Create and manage personal Docker access tokens for secure CLI authentication and automation +keywords: personal access tokens, PAT, docker cli authentication, docker hub security, programmatic access aliases: - /docker-hub/access-tokens/ - /security/for-developers/access-tokens/ --- -You can create a personal access token (PAT) to use as an alternative to your password for Docker CLI authentication. +Personal access tokens (PATs) provide a secure alternative to passwords for Docker CLI authentication. Use PATs to authenticate automated systems, CI/CD pipelines, and development tools without exposing your Docker Hub password. -Compared to passwords, PATs provide the following advantages: +## Key benefits -- You can investigate when the PAT was last used and then disable or delete it if you find any suspicious activity. -- When using an access token, you can't perform any administrative activity on the account, including changing the password. It protects your account if your computer is compromised. -- Access tokens are valuable for building integrations, as you can issue multiple tokens, one for each integration, and revoke them at -any time. +PATs offer significant security advantages over password authentication: -## Create an access token +- Enhanced security: Investigate token usage, disable suspicious tokens, and prevent administrative actions that could compromise your account if your system is compromised. +- Better automation: Issue multiple tokens for different integrations, each with specific permissions, and revoke them independently when no longer needed. +- Two-factor authentication compatibility: Required when you have two-factor authentication turned on, providing secure CLI access without bypassing 2FA protection. +- Usage tracking: Monitor when and how tokens are used to identify potential security issues or unused automation. + +## When to use personal access tokens + +Use PATs for these common scenarios: + +- Development workflows: Authenticate Docker CLI during local development +- CI/CD pipelines: Automate image builds and deployments in continuous integration systems +- Automation scripts: Push and pull images in automated deployment or backup scripts +- Development tools: Integrate Docker Hub access with IDEs, container management tools, or monitoring systems +- Two-factor authentication: Required for CLI access when 2FA is turned on + +> [!NOTE] +> +> For organization-wide automation, consider [organization access tokens](/manuals/enterprise/security/access-tokens.md) which aren't tied to individual user accounts. + +## Create a personal access token > [!IMPORTANT] > -> Treat access tokens like your password and keep them secret. Store your tokens securely in a credential manager for example. +> Treat access tokens like passwords and keep them secure. Store tokens in credential managers and never commit them to source code repositories. -Use the Docker Admin Console to create an access token. +To create a personal access token: 1. Sign in to [Docker Home](https://app.docker.com/). 1. Select your avatar in the top-right corner and from the drop-down menu select **Account settings**. 1. Select **Personal access tokens**. 1. Select **Generate new token**. -1. Add a description for your token. Use something that indicates the use case or purpose of the token. -1. Select the expiration date for the token. -1. Set the access permissions. - The access permissions are scopes that set restrictions in your - repositories. For example, for Read & Write permissions, an automation - pipeline can build an image and then push it to a repository. However, it - can't delete the repository. -1. Select **Generate** and then copy the token that appears on the screen and save it. You won't be able to retrieve the token once you close this prompt. +1. Configure your token: + - **Description:** Use a descriptive name that indicates the token's purpose + - **Expiration date:** Set an expiration date based on your security policies + - **Access permissions:** **Read**, **Write**, or **Delete**. +1. Select **Generate**. Copy the token that appears on the screen and save it. You won't be able to retrieve the token once you exit the screen. -## Use an access token +## Use personal access tokens -You can use an access token in place of your password when you sign in using Docker CLI. - -Sign in from your Docker CLI client with the following command, replacing `YOUR_USERNAME` with your Docker ID: +Sign in to the Docker CLI using your personal access token: ```console $ docker login --username +Password: [paste your PAT here] ``` -When prompted for a password, enter your personal access token instead of a password. - -> [!NOTE] -> -> If you have [two-factor authentication (2FA)](2fa/_index.md) enabled, you must -> use a personal access token when logging in from the Docker CLI. 2FA is an -> optional, but more secure method of authentication. - -### Fair use +When prompted for a password, enter your personal access token instead of your Docker Hub password. -When utilizing PATs, users should be aware that excessive creation of PATs could lead to throttling, or additional charges. To ensure fair resource usage and maintain service quality, Docker reserves the right to impose restrictions or apply additional charges to accounts exhibiting excessive use of PATs. - -## Modify existing tokens +## Modify personal access tokens > [!NOTE] > -> You can't edit the expiration date on an existing token. You must create a new PAT if you need to set a new expiration date. +> You can't edit the expiration date on an existing personal access token. You must create a new PAT if you need to set a new expiration date. You can rename, activate, deactivate, or delete a token as needed. You can manage your tokens in your account settings. @@ -83,6 +84,23 @@ You can rename, activate, deactivate, or delete a token as needed. You can manag ## Auto-generated tokens -When you sign in to your Docker account with Docker Desktop, Docker Desktop generates an authentication token on your behalf. When you interact with Docker Hub using the Docker CLI, the CLI uses this token for authentication. The token scope has Read, Write, and Delete access. If your Docker Desktop session expires, the token is automatically removed locally. +Docker Desktop automatically creates authentication tokens when you sign in, with these characteristics: + +- Automatic creation: Generated when you sign in to Docker Desktop +- Full permissions: Include Read, Write, and Delete access +- Session-based: Automatically removed when Docker Desktop session expires +- Account limits: Up to 5 auto-generated tokens per account +- Automatic cleanup: Older tokens are deleted when new ones are created + +You can manually delete auto-generated tokens if needed, but they'll be recreated when you use Docker Desktop. + +## Fair use policy + +When using personal access tokens, be aware that excessive token creation may result in throttling or additional charges. Docker reserves the right to impose restrictions on accounts with excessive PAT usage to ensure fair resource allocation and maintain service quality. + +Best practices for fair use include: -You can have up to 5 auto-generated tokens associated with your account. These are deleted and created automatically based on usage and creation dates. You can also delete your auto-generated tokens as needed. For more information, see [Modify existing tokens](#modify-existing-tokens). +- Reuse tokens across similar use cases instead of creating many single-purpose tokens +- Delete unused tokens regularly +- Use [organization access tokens](/manuals/enterprise/security/access-tokens.md) for organization-wide automation +- Monitor token usage to identify optimization opportunities diff --git a/content/manuals/security/faqs/containers.md b/content/manuals/security/faqs/containers.md index 45174ff6dfab..5c3496f338eb 100644 --- a/content/manuals/security/faqs/containers.md +++ b/content/manuals/security/faqs/containers.md @@ -1,53 +1,33 @@ --- -description: Find the answers to container security related FAQs -keywords: Docker, Docker Hub, Docker Desktop security FAQs, platform, Docker Scout, admin, security title: Container security FAQs linkTitle: Container +description: Frequently asked questions about Docker container security and isolation +keywords: container security, docker desktop isolation, enhanced container isolation, file sharing weight: 20 tags: [FAQ] aliases: - /faq/security/containers/ --- -### How are containers isolated from the host in Docker Desktop? +## How are containers isolated from the host in Docker Desktop? -Docker Desktop runs all containers inside a customized / minimal Linux virtual -machine (except for native Windows containers). This adds a strong layer of -isolation between containers and the host the machine, even if containers are -running rootful. +Docker Desktop runs all containers inside a customized Linux virtual machine (except for native Windows containers). This adds strong isolation between containers and the host machine, even when containers run as root. -However note the following: +Important considerations include: -* Containers have access to host files configured for file sharing via Settings - -> Resources -> File Sharing (see the next FAQ question below for more info). +- Containers have access to host files configured for file sharing via Docker Desktop settings +- Containers run as root with limited capabilities inside the Docker Desktop VM by default +- Privileged containers (`--privileged`, `--pid=host`, `--cap-add`) run with elevated privileges inside the VM, giving them access to VM internals and Docker Engine -* By default, containers run as root but with limited capabilities inside the - Docker Desktop VM. Containers running with elevated privileges (e.g., - `--privileged`, `--pid=host`, `--cap-add`, etc.) run as root with elevated - privileges inside the Docker Desktop VM which gives them access to Docker - Desktop VM internals, including the Docker Engine. Thus, users must be careful - which containers they run with such privileges to avoid security breaches by - malicious container images. +With Enhanced Container Isolation turned on, each container runs in a dedicated Linux user namespace inside the Docker Desktop VM. Even privileged containers only have privileges within their container boundary, not the VM. ECI uses advanced techniques to prevent containers from breaching the Docker Desktop VM and Docker Engine. -* If [Enhanced Container Isolation (ECI)](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md) - mode is enabled, then each container runs within a dedicated Linux User - Namespace inside the Docker Desktop VM, which means the container has no - privileges within the Docker Desktop VM. Even when using the `--privileged` - flag or similar, the container processes will only be privileged within the - container's logical boundary, but unprivileged otherwise. In addition, ECI protects - uses other advanced techniques to ensure they can't easily breach - the Docker Desktop VM and Docker Engine within (see the ECI section for more - info). No changes to the containers or user workflows are required as the - extra protection is added under the covers. +## Which portions of the host filesystem can containers access? -### To which portions of the host filesystem do containers have read and write access? +Containers can only access host files that are: -Containers can only access host files if these are shared via Settings -> Resources -> File Sharing, -and only when such files are bind-mounted into the container (e.g., `docker run -v /path/to/host/file:/mnt ...`). +1. Shared using Docker Desktop settings +1. Explicitly bind-mounted into the container (e.g., `docker run -v /path/to/host/file:/mnt`) -### Can containers running as root gain access to admin-owned files or directories on the host? +## Can containers running as root access admin-owned files on the host? -No; host file sharing (bind mount from the host filesystem) uses a user-space crafted -file server (running in `com.docker.backend` as the user running Docker -Desktop), so containers can’t gain any access that the user on the host doesn’t -already have. +No. Host file sharing uses a user-space file server (running in `com.docker.backend` as the Docker Desktop user), so containers can only access files that the Docker Desktop user already has permission to access. diff --git a/content/manuals/security/faqs/general.md b/content/manuals/security/faqs/general.md index 54405768457e..bdac91350ad3 100644 --- a/content/manuals/security/faqs/general.md +++ b/content/manuals/security/faqs/general.md @@ -1,92 +1,69 @@ --- -description: Find the answers to common security related FAQs -keywords: Docker, Docker Hub, Docker Desktop security FAQs, platform, Docker Scout, admin, security +description: Frequently asked questions about Docker security, authentication, and organization management +keywords: Docker security, FAQs, authentication, SSO, vulnerability reporting, session management title: General security FAQs -linkTitle: General +linkTitle: General weight: 10 tags: [FAQ] aliases: - /faq/security/general/ --- -### How do I report a vulnerability? +## How do I report a vulnerability? -If you’ve discovered a security vulnerability in Docker, we encourage you to report it responsibly. Report security issues to security@docker.com so that they can be quickly addressed by our team. +If you've discovered a security vulnerability in Docker, report it responsibly to security@docker.com so our team can quickly address it. -### How are passwords managed when SSO isn't used? +## Does Docker lockout users after failed sign-ins? -Passwords are encrypted and salt-hashed. If you use application-level passwords instead of SSO, you are responsible for ensuring that your employees know how to pick strong passwords, don't share passwords, and don't reuse passwords across multiple systems. +Docker Hub locks out users after 10 failed sign-in attempts within 5 minutes. The lockout duration is 5 minutes. This policy applies to Docker Hub, Docker Desktop, and Docker Scout authentication. -### Does Docker require password resets when SSO isn't used? +## Do you support physical MFA with YubiKeys? -Passwords aren't required to be periodically reset. NIST no longer recommends password resets as part of best practice. +You can configure physical MFA through SSO using your identity provider (IdP). Check with your IdP if they support physical MFA devices like YubiKeys. -### Does Docker lockout users after failed sign-ins? +## How are sessions managed and do they expire? -Docker Hub’s global setting for system lockout is after 10 failed sign in attempts in a period of 5 minutes, and the lockout duration is 5 minutes. The same global policy applies to authenticated Docker Desktop users and Docker Scout, both of which use Docker Hub for authentication. +Docker uses tokens to manage user sessions with different expiration periods: -### Do you support physical MFA with YubiKeys? +- Docker Desktop: Signs you out after 90 days, or 30 days of inactivity +- Docker Hub and Docker Home: Sign you out after 24 hours -You can configure this through SSO using your IdP. Check with your IdP if they support physical MFA. +Docker also supports your IdP's default session timeout through SAML attributes. For more information, see [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes). -### How are sessions managed and do they expire? +## How does Docker distinguish between employee users and contractor users? -By default, Docker uses tokens to manage sessions after a user signs in: +Organizations use verified domains to distinguish user types. Team members with email domains other than verified domains appear as "Guest" users in the organization. -- Docker Desktop signs you out after 90 days, or 30 days of inactivity. -- Docker Hub and Docker Home sign you out after 24 hours. +## How long are activity logs available? -Docker also supports your IdP's default session timeout. You can configure this by setting a Docker session minutes SAML attribute. For more information, see [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes). +Docker activity logs are available for 90 days. You're responsible for exporting logs or setting up drivers to send logs to your internal systems for longer retention. -### How does Docker attribute downloads to us and what data is used to classify or verify the user is part of our organization? +## Can I export a list of users with their roles and privileges? -Docker Desktop downloads are linked to a specific organization by the user's email containing the customer's domain. Additionally, we use IP addresses to correlate users with organizations. +Yes, use the [Export Members](../../admin/organization/members.md#export-members) feature to export a CSV file containing your organization's users with role and team information. -### How do you attribute that number of downloads to us from IP data if most of our engineers work from home and aren’t allowed to use VPNs? +## How does Docker Desktop handle authentication information? -We attribute users and their IP addresses to domains using 3rd party data enrichment software, where our provider analyzes activity from public and private data sources related to that specific IP address, then uses that activity to identify the domain and map it to the IP address. +Docker Desktop uses the host operating system's secure key management to store authentication tokens: -Some users authenticate by signing in to Docker Desktop and joining their domain's Docker organization, which allows us to map them with a much higher degree of accuracy and report on direct feature usage for you. We highly encourage you to get your users authenticated so we can provide you with the most accurate data. +- macOS: [Keychain](https://support.apple.com/guide/security/keychain-data-protection-secb0694df1a/web) +- Windows: [Security and Identity API via Wincred](https://learn.microsoft.com/en-us/windows/win32/api/wincred/) +- Linux: [Pass](https://www.passwordstore.org/). -### How does Docker distinguish between employee users and contractor users? +## How do we remove users who aren't part of our IdP when using SSO without SCIM? -Organizations set up in Docker use verified domains and any team member with an email domain other than what's verified is noted as a "Guest" in that organization. +If SCIM isn't turned on, you must manually remove users from the organization. SCIM can automate user removal, but only for users added after SCIM is turned on. Users added before SCIM was turned on must be removed manually. -### How long are activity logs available? +For more information, see [Manage organization members](/manuals/admin/organization/members.md). -Docker provides various types of audit logs and log retention varies. For example, Docker activity logs are available for 90 days. You are responsible for exporting logs or setting up drivers to their own internal systems. +## What metadata does Scout collect from container images? -### Can I export a list of all users with their assigned roles and privileges and if so, in what format? +For information about metadata stored by Docker Scout, see [Data handling](/manuals/scout/deep-dive/data-handling.md). -Using the [Export Members](../../admin/organization/members.md#export-members) feature, you can export to CSV a list of your organization's users with role and team information. +## How are Marketplace extensions vetted for security? -### How does Docker Desktop handle and store authentication information? +Security vetting for extensions is on our roadmap but isn't currently implemented. Extensions aren't covered as part of Docker's Third-Party Risk Management Program. -Docker Desktop utilizes the host operating system's secure key management for handling and storing authentication tokens necessary for authenticating with image registries. On macOS, this is [Keychain](https://support.apple.com/guide/security/keychain-data-protection-secb0694df1a/web); on Windows, this is [Security and Identity API via Wincred](https://learn.microsoft.com/en-us/windows/win32/api/wincred/); and on Linux, this is [Pass](https://www.passwordstore.org/). +## Can I prevent users from pushing images to Docker Hub private repositories? -### How does Docker Hub secure passwords in storage and in transit? - -This is applicable only when using Docker Hub's application-level password versus SSO/SAML. For users created through SSO Just-in-Time or SCIM provisioning, Docker Hub doesn't store passwords. For all other users, application-level passwords are salt-hashed in storage (SHA-256) and encrypted in transit (TLS). - -### How do we de-provision users who are not part of our IdP? We use SSO but not SCIM - -If SCIM isn't enabled, you have to manually remove users from the organization. -SCIM can automate this if your users are added after SCIM is enabled. Any users -added to your organization before SCIM is enabled must be removed manually. - -For more information on manually removing users, see -[Manage organization members](/manuals/admin/organization/members.md). - -### What metadata is collected from container images that Scout analyzes? - -For information about the metadata stored by Docker Scout, see [Data handling](/manuals/scout/deep-dive/data-handling.md). - -### How are extensions within the Marketplace vetted for security prior to placement? - -Security vetting for extensions is on our roadmap however this vetting isn't currently done. - -Extensions are not covered as part of Docker’s Third-Party Risk Management Program. - -### Can I disable private repos in my organization via a setting to make sure nobody is pushing images into Docker Hub? - -No. With [Registry Access Management](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) (RAM), administrators can ensure that their developers using Docker Desktop only access allowed registries. This is done through the Registry Access Management dashboard in the Admin Console. +No direct setting exists to disable private repositories. However, [Registry Access Management](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) lets administrators control which registries developers can access through Docker Desktop via the Admin Console. diff --git a/content/manuals/security/faqs/networking-and-vms.md b/content/manuals/security/faqs/networking-and-vms.md index 39df4646213b..3d9c89c59222 100644 --- a/content/manuals/security/faqs/networking-and-vms.md +++ b/content/manuals/security/faqs/networking-and-vms.md @@ -1,38 +1,30 @@ --- -description: Find the answers to FAQs related to networking and virtualization -keywords: Docker, Docker Hub, Docker Desktop security FAQs, security, platform, networks, vms title: Network and VM FAQs linkTitle: Network and VM +description: Frequently asked questions about Docker Desktop networking and virtualization security +keywords: docker desktop networking, virtualization, hyper-v, wsl2, network security, firewall weight: 30 tags: [FAQ] aliases: - /faq/security/networking-and-vms/ --- -### How can I limit the type of internet access allowed by the container when it runs, to prevent it from being able to exfiltrate data or download malicious code? +## How can I limit container internet access to prevent data exfiltration? -There is no built-in mechanism for that but it can be addressed by process-level firewall on the host. Hook into the `com.docker.vpnkit` user-space process and apply rules where it can connect to (DNS URL white list; packet/payload filter) and which ports/protocols it is allowed to use. +Docker Desktop doesn't have a built-in mechanism for this, but you can use process-level firewalls on the host. Apply rules to the `com.docker.vpnkit` user-space process to control where it can connect (DNS allowlists, packet filters) and which ports/protocols it can use. -### Can I prevent users binding ports on 0.0.0.0? +For enterprise environments, consider [Air-gapped containers](/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md) which provide network access controls for containers. -There is no direct way to enforce that through Docker Desktop but it would inherit any firewall rules enforced on the host. +## Can I apply firewall rules to container network traffic? -### What options exist to lock containerized network settings to a system? If not supported, are there any consequences to manipulating the settings? +Yes. Docker Desktop uses a user-space process (`com.docker.vpnkit`) for network connectivity, which inherits constraints like firewall rules, VPN settings, and HTTP proxy properties from the user that launched it. -The Docker network settings are entirely local within the VM and have no effect on the system. +## Does Docker Desktop for Windows with Hyper-V allow users to create other VMs? -### Can I apply rules on container network traffic via a local firewall or VPN client? +No. The `DockerDesktopVM` name is hard-coded in the service, so you cannot use Docker Desktop to create or manipulate other virtual machines. -For network connectivity, Docker Desktop uses a user-space process (`com.docker.vpnkit`), which inherits constraints like firewall rules, VPN, HTTP proxy properties etc, from the user that launched it. +## How does Docker Desktop achieve network isolation with Hyper-V and WSL 2? -### Does running Docker Desktop for Windows with Hyper-V backend allow users to create arbitrary VMs? +Docker Desktop uses the same VM processes for both WSL 2 (in the `docker-desktop` distribution) and Hyper-V (in `DockerDesktopVM`). Host/VM communication uses `AF_VSOCK` hypervisor sockets (shared memory) rather than network switches or interfaces. All host networking is performed using standard TCP/IP sockets from the `com.docker.vpnkit.exe` and `com.docker.backend.exe` processes. -No. The `DockerDesktopVM` name is hard coded in the service code, so you cannot use Docker Desktop to create or manipulate any other VM. - -### Can I prevent our users creating other VMs when using Docker Desktop on Mac? - -On Mac it is an unprivileged operation to start a VM, so that is not enforced by Docker Desktop. - -### How does Docker Desktop achieve network level isolation when Hyper-V and/or WSL2 is used? - -The VM processes are the same for both WSL 2 (running inside the `docker-desktop` distribution) and Hyper-V (running inside the `DockerDesktopVM`). Host/VM communication uses `AF_VSOCK` hypervisor sockets (shared memory). It does not use Hyper-V network switches or network interfaces. All host networking is performed using normal TCP/IP sockets from the `com.docker.vpnkit.exe` and `com.docker.backend.exe` processes. For more information see [How Docker Desktop networking works under the hood](https://www.docker.com/blog/how-docker-desktop-networking-works-under-the-hood/). +For more information, see [How Docker Desktop networking works under the hood](https://www.docker.com/blog/how-docker-desktop-networking-works-under-the-hood/). diff --git a/content/manuals/security/faqs/single-sign-on/domain-faqs.md b/content/manuals/security/faqs/single-sign-on/domain-faqs.md index 6f88ada90c50..48fa0d2ca850 100644 --- a/content/manuals/security/faqs/single-sign-on/domain-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/domain-faqs.md @@ -1,30 +1,22 @@ --- -description: Single sign-on domain FAQs -keywords: Docker, Docker Hub, SSO FAQs, single sign-on, domains, domain verification, domain management -title: FAQs for SSO and domains +title: SSO domain FAQs linkTitle: Domains +description: Frequently asked questions about domain verification and management for Docker single sign-on +keywords: SSO domains, domain verification, DNS, TXT records, single sign-on tags: [FAQ] aliases: - /single-sign-on/domain-faqs/ - /faq/security/single-sign-on/domain-faqs/ --- -### Can I add sub-domains? +## Can I add sub-domains? -Yes, you can add sub-domains to your SSO connection, however all email addresses should also be on that domain. Verify that your DNS provider supports multiple TXT records for the same domain. +Yes, you can add sub-domains to your SSO connection. All email addresses must use domains you've added to the connection. Verify that your DNS provider supports multiple TXT records for the same domain. -### Can the DNS provider configure it once for one-time verification and remove it later or will it be needed permanently? +## Do I need to keep the DNS TXT record permanently? -You can do it one time to add the domain to a connection. If your organization ever changes IdPs and has to set up SSO again, your DNS provider will need to verify again. +You can remove the TXT record after one-time verification to add the domain. However, if your organization changes identity providers and needs to set up SSO again, you'll need to verify the domain again. -### Is adding domain required to configure SSO? What domains should I be adding? And how do I add it? +## Can I verify the same domain for multiple organizations? -Adding and verifying a domain is required to enable and enforce SSO. See [Configure single sign-on](/manuals/enterprise/security/single-sign-on/configure.md) for more information. This should include all email domains users will use to access Docker. Public domains, for example `gmail.com` or `outlook.com`, are not permitted. Also, the email domain should be set as the primary email. - -### Is IdP-initiated authentication supported? - -IdP-initiated authentication isn't supported by Docker SSO. Users must initiate sign-in through Docker Desktop or Hub. - -### Can I verify the same domain on multiple organizations? - -You can't verify the same domain for multiple orgnaizations at the organization level. If you want to verify one domain for multiple organizations, you must have a Docker Business subscription, and [create a company](/manuals/admin/company/new-company.md). A company enables centralized management of organizations and allows domain verification at the company level. +You can't verify the same domain for multiple organizations at the organization level. To verify one domain for multiple organizations, you must have a Docker Business subscription and create a company. Companies allow centralized management of organizations and domain verification at the company level. diff --git a/content/manuals/security/faqs/single-sign-on/enforcement-faqs.md b/content/manuals/security/faqs/single-sign-on/enforcement-faqs.md index 20528c61e89f..8f52b7b84011 100644 --- a/content/manuals/security/faqs/single-sign-on/enforcement-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/enforcement-faqs.md @@ -1,57 +1,41 @@ --- -description: Single sign-on enforcement FAQs -keywords: Docker, Docker Hub, SSO FAQs, single sign-on, enforce SSO, SSO enforcement -title: FAQs for SSO and enforcement +title: SSO enforcement FAQs linkTitle: Enforcement +description: Frequently asked questions about Docker single sign-on enforcement and its effects on users +keywords: SSO enforcement, single sign-on, personal access tokens, CLI authentication, guest users tags: [FAQ] aliases: - /single-sign-on/enforcement-faqs/ - /faq/security/single-sign-on/enforcement-faqs/ --- -### I currently have a Docker Team subscription. How do I enable SSO? +## Does Docker SSO support authenticating through the command line? -SSO is available with a Docker Business subscription. To enable SSO, you must first upgrade your subscription to a Docker Business subscription. To learn how to upgrade your existing account, see [Upgrade your subscription](../../../subscription/change.md). +When SSO is enforced, [passwords are prevented from accessing the Docker CLI](/security/security-announcements/#deprecation-of-password-logins-on-cli-when-sso-enforced). You must use a personal access token (PAT) for CLI authentication instead. -### Is DNS verification required to enable SSO? +Each user must create a PAT to access the CLI. To learn how to create a PAT, see [Manage personal access tokens](/security/access-tokens/). Users who already used a PAT before SSO enforcement can continue using that PAT. -Yes. You must verify a domain before using it with an SSO connection. +## How does SSO affect automation systems and CI/CD pipelines? -### Does Docker SSO support authenticating through the command line? +Before enforcing SSO, you must [create personal access tokens](/security/access-tokens/) to replace passwords in automation systems and CI/CD pipelines. -When SSO is enforced, [passwords are prevented from accessing the Docker CLI](/security/security-announcements/#deprecation-of-password-logins-on-cli-when-sso-enforced). You can still access the Docker CLI using a personal access token (PAT) for authentication. +## Can I turn on SSO without enforcing it immediately? -Each user must create a PAT to access the CLI. To learn how to create a PAT, see [Manage access tokens](/security/access-tokens/). Users who already used a PAT to sign in before SSO enforcement will still be able to use that PAT to authenticate. +Yes, you can turn on SSO without enforcement. Users can choose between Docker ID (standard email and password) or domain-verified email address (SSO) at the sign-in screen. -### How does SSO affect automation systems and CI/CD pipelines? +## SSO is enforced, but a user can sign in using a username and password. Why is this happening? -Before enforcing SSO, you must [create PATs](/security/access-tokens/). These PATs are used instead of passwords for signing into automation systems and CI/CD pipelines. +Guest users who aren't part of your registered domain but have been invited to your organization don't sign in through your SSO identity provider. SSO enforcement only applies to users who belong to your verified domain. -### What can organization users who authenticated with personal emails prior to enforcement expect? +## Can I test SSO functionality before going to production? -Ensure your users have their organization email on their account, so that the accounts will be migrated to SSO for authentication. +Yes, you can create a test organization with a 5-seat Business subscription. When testing, turn on SSO but don't enforce it, or all domain email users will be forced to sign in to the test environment. -### Can I enable SSO and hold off on the enforcement option? +## What is enforcing SSO versus enforcing sign-in? -Yes, you can choose to not enforce, and users have the option to use either Docker ID (standard email and password) or domain-verified email address (SSO) at the sign-in screen. +These are separate features you can use independently or together: -### SSO is enforced, but a user can sign in using a username and password. Why is this happening? - -Guest users who are not part of your registered domain but have been invited to your organization do not sign in through your SSO Identity Provider. SSO enforcement only requires that users which do belong to your domain, must go through the SSO IdP. - -### Is there a way to test this functionality in a test tenant with Okta before going to production? - -Yes, you can create a test organization. Companies can set up a new 5 seat Business subscription on a new organization to test with. To do this, make sure to only enable SSO, not enforce it, or all domain email users will be forced to sign in to that test tenant. - -### Is the sign in required tracking at runtime or install time? - -For Docker Desktop, if it's configured to require authentication to the organization, it tracks at runtime. - -### What is enforcing SSO versus enforcing sign-in? - -Enforcing SSO and enforcing sign-in to Docker Desktop are different features that you can use separately or together. - -Enforcing SSO ensures that users sign in using their SSO credentials instead of their Docker ID. One of the benefits is that SSO enables you to better manage user credentials. - -Enforcing sign-in to Docker Desktop ensures that users always sign in to an account that's a member of your organization. The benefits are that your organization's security settings are always applied to the user's session and your users always receive the benefits of your subscription. For more details, see [Enforce sign-in for Desktop](/manuals/enterprise/security/enforce-sign-in/_index.md#enforcing-sign-in-versus-enforcing-single-sign-on-sso). +- Enforcing SSO ensures users sign in using SSO credentials instead of their Docker ID, enabling better credential management. +- Enforcing sign-in to Docker Desktop ensures users always sign in to accounts that are members of your organization, so security settings and subscription benefits are always applied. +For more details, see [Enforce sign-in for Desktop](/manuals/enterprise/security/enforce-sign-in/_index.md#enforcing-sign-in-versus-enforcing-single-sign-on-sso). diff --git a/content/manuals/security/faqs/single-sign-on/faqs.md b/content/manuals/security/faqs/single-sign-on/faqs.md index b59f5863c1bf..c9904bf7d889 100644 --- a/content/manuals/security/faqs/single-sign-on/faqs.md +++ b/content/manuals/security/faqs/single-sign-on/faqs.md @@ -1,7 +1,7 @@ --- -description: Single sign-on FAQs +description: Frequently asked questions about Docker single sign-on keywords: Docker, Docker Hub, SSO FAQs, single sign-on, administration, security -title: General FAQs on SSO +title: General SSO FAQs linkTitle: General weight: 10 tags: [FAQ] @@ -13,57 +13,22 @@ aliases: - /security/faqs/single-sign-on/saml-faqs/ --- -### Is Docker SSO available for all paid subscriptions? +## What SSO flows does Docker support? -Docker single sign-on (SSO) is only available with the Docker Business subscription. [Upgrade your existing subscription](../../../subscription/change.md) to start using Docker SSO. +Docker supports Service Provider Initiated (SP-initiated) SSO flow. Users must sign in to Docker Hub or Docker Desktop to initiate the SSO authentication process. -### How does Docker SSO work? +## Does Docker SSO support multi-factor authentication? -Docker SSO lets users authenticate using their identity providers (IdPs) to access Docker. Docker supports Entra ID (formerly Azure AD) and any SAML 2.0 identity providers. When you enable SSO, this redirects users to your provider’s authentication page to authenticate using their email and password. +When an organization uses SSO, multi-factor authentication is controlled at the identity provider level, not on the Docker platform. -### What SSO flows does Docker support? +## Can I retain my Docker ID when using SSO? -Docker supports Service Provider Initiated (SP-initiated) SSO flow. This means users must sign in to Docker Hub or Docker Desktop to initiate the SSO authentication process. +Users with personal Docker IDs retain ownership of their repositories, images, and assets. When SSO is enforced, existing accounts with company domain emails are connected to the organization. Users signing in without existing accounts automatically have new accounts and Docker IDs created. -### Where can I find detailed instructions on how to configure Docker SSO? +## Are there any firewall rules required for SSO configuration? -You first need to establish an SSO connection with your identity provider, and the company email domain needs to be verified prior to establishing an SSO connection for your users. For detailed step-by-step instructions on how to configure Docker SSO, see [Single Sign-on](/manuals/enterprise/security/single-sign-on/configure.md). +No specific firewall rules are required as long as `login.docker.com` is accessible. This domain is commonly accessible by default, but some organizations may need to allow it in their firewall settings if SSO setup encounters issues. -### Does Docker SSO support multi-factor authentication (MFA)? +## Does Docker use my IdP's default session timeout? -When an organization uses SSO, MFA is determined on the IdP level, not on the Docker platform. - -### Do I need a specific version of Docker Desktop for SSO? - -Yes, all users in your organization must upgrade to Docker Desktop version 4.4.2 or later. Users on older versions of Docker Desktop won't be able to sign in after SSO is enforced if the company domain email is used to sign in or as the primary email associated with an existing Docker account. Your users with existing accounts can't sign in with their username and password. - -### Can I retain my Docker ID when using SSO? - -For a personal Docker ID, a user is the account owner. A Docker ID is associated with access to the user's repositories, images, assets. A user can choose to have a company domain email on the Docker account. When enforcing SSO, the account is connected to the organization account. When enforcing SSO for an organization(s) or company, any user logging in without an existing account using verified company domain email will automatically have an account provisioned, and a new Docker ID created. - -### Does SAML authentication require additional attributes? - -You must provide an email address as an attribute to authenticate through SAML. The ‘Name’ attribute is optional. - -### Does the application recognize the NameID/Unique Identifier in the `SAMLResponse` subject? - -The preferred format is your email address, which should also be your Name ID. - -### Can I use group mapping with SSO and the Azure AD (OIDC) authentication method? - -No. Group mapping with SSO isn't supported with the Azure AD (OIDC) -authentication method because it requires granting the OIDC app the -Directory.Read.All permission, which provides access to all users, groups, and -other sensitive data in the directory. Due to potential security risks, Docker -doesn't support this configuration. Instead, Docker recommends [configuring SCIM -to enable group sync -securely](/manuals/enterprise/security/provisioning/group-mapping.md#use-group-mapping-with-scim). - -### Are there any firewall rules required for SSO configuration? - -No. There are no specific firewall rules required for configuring SSO, as long as the domain `login.docker.com` is accessible. This domain is commonly accessible by default. However, in rare cases, some organizations may have firewall restrictions in place that block this domain. If you encounter issues during SSO setup, ensure that `login.docker.com` is allowed in your network's firewall settings. - -### Does Docker use my IdP's default session timeout? - -Yes, Docker supports your IdP's default session timeout using a custom SAML attribute. -Instead of relying on the standard `SessionNotOnOrAfter` element from the SAML spec, Docker uses a custom `dockerSessionMinutes` attribute to control session duration. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes) for more information. \ No newline at end of file +Yes, Docker supports your IdP's session timeout using a custom `dockerSessionMinutes` SAML attribute instead of the standard `SessionNotOnOrAfter` element. See [SSO attributes](/manuals/enterprise/security/provisioning/_index.md#sso-attributes) for more information. diff --git a/content/manuals/security/faqs/single-sign-on/idp-faqs.md b/content/manuals/security/faqs/single-sign-on/idp-faqs.md index b4d5f8c899c4..ff76f5953567 100644 --- a/content/manuals/security/faqs/single-sign-on/idp-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/idp-faqs.md @@ -1,60 +1,47 @@ --- -description: Single sign-on IdP FAQs -keywords: Docker, Docker Hub, SSO FAQs, single sign-on, IdP -title: FAQs for SSO and identity providers +title: SSO and identity provider FAQs linkTitle: Identity providers +description: Frequently asked questions about Docker SSO and identity provider configuration +keywords: identity providers, SSO IdP, SAML, Azure AD, Entra ID, certificate management tags: [FAQ] aliases: - /single-sign-on/idp-faqs/ - /faq/security/single-sign-on/idp-faqs/ --- -### Is it possible to use more than one IdP with Docker SSO? +## Can I use multiple identity providers with Docker SSO? -Yes. Docker supports multiple IdP configurations. A domain can be associated with multiple IdPs. Docker supports Entra ID (formerly Azure AD) and identity providers that support SAML 2.0. +Yes, Docker supports multiple IdP configurations. A domain can be associated with multiple IdPs. Docker supports Entra ID (formerly Azure AD) and identity providers that support SAML 2.0. -### Is it possible to change my identity provider after configuring SSO? +## Can I change my identity provider after configuring SSO? -Yes. You must delete your existing IdP configuration in your Docker SSO connection and then [configure SSO using your new IdP](/manuals/enterprise/security/single-sign-on/connect.md). If you had already turned on enforcement, you should turn off enforcement before updating the provider SSO connection. +Yes. Delete your existing IdP configuration in your Docker SSO connection, then [configure SSO using your new IdP](/manuals/enterprise/security/single-sign-on/connect.md). If you had already turned on enforcement, turn off enforcement before updating the provider connection. -### What information do I need from my identity provider to configure SSO? +## What information do I need from my identity provider to configure SSO? -To enable SSO in Docker, you need the following from your IdP: +To turn on SSO in Docker, you need the following from your IdP: -* **SAML**: Entity ID, ACS URL, Single Logout URL and the public X.509 certificate +- SAML: Entity ID, ACS URL, Single Logout URL, and the public X.509 certificate +- Entra ID (formerly Azure AD): Client ID, Client Secret, AD Domain -* **Entra ID (formerly Azure AD)**: Client ID, Client Secret, AD Domain. +## What happens if my existing certificate expires? -### What happens if my existing certificate expires? +If your certificate expires, contact your identity provider to retrieve a new X.509 certificate. Then update the certificate in the [SSO configuration settings](/manuals/enterprise/security/single-sign-on/manage.md#manage-sso-connections) in the Docker Admin Console. -If your existing certificate has expired, you may need to contact your identity provider to retrieve a new X.509 certificate. Then, you need to update the certificate in the [SSO configuration settings](/manuals/enterprise/security/single-sign-on/manage.md#manage-sso-connections) in Docker Hub or Docker Admin Console. +## What happens if my IdP goes down when SSO is turned on? -### What happens if my IdP goes down when SSO is enabled? +If SSO is enforced, users can't access Docker Hub when your IdP is down. Users can still access Docker Hub images from the CLI using personal access tokens. -If SSO is enforced, then it is not possible to access Docker Hub when your IdP is down. You can still access Docker Hub images from the CLI using your Personal Access Token. +If SSO is turned on but not enforced, users can fall back to username/password authentication. -If SSO is enabled but not enforced, then users could fallback to authenticate with username/password and trigger a reset password flow (if necessary). +## Do bot accounts need seats to access organizations using SSO? -### How do I handle accounts using Docker Hub as a secondary registry? Do I need a bot account? +Yes, bot accounts need seats like regular users, requiring a non-aliased domain email in the IdP and using a seat in Docker Hub. You can add bot accounts to your IdP and create access tokens to replace other credentials. -You can add a bot account to your IdP and create an access token for it to replace the other credentials. +## Does SAML SSO use Just-in-Time provisioning? -### Does a bot account need a seat to access an organization using SSO? +The SSO implementation uses Just-in-Time (JIT) provisioning by default. You can optionally turn off JIT in the Admin Console if you turn on auto-provisioning using SCIM. See [Just-in-Time provisioning](/security/for-admins/provisioning/just-in-time/). -Yes, bot accounts need a seat, similar to a regular end user, having a non-aliased domain email enabled in the IdP and using a seat in Hub. +## My Entra ID SSO connection isn't working and shows a misconfiguration error. How can I troubleshoot this? -### Does SAML SSO use Just-in-Time provisioning? - -The SSO implementation uses Just-in-Time (JIT) provisioning by default. You can optionally disable JIT in the Admin Console if you enable auto-provisioning using SCIM. See [Just-in-Time provisioning](/security/for-admins/provisioning/just-in-time/). - -### Is IdP-initiated sign-in available? - -Docker SSO doesn't support IdP-initiated sign-in, only Service Provider Initiated (SP-initiated) sign-in. - -### Is it possible to connect Docker Hub directly with a Microsoft Entra (formerly Azure AD) group? - -Yes, Entra ID (formerly Azure AD) is supported with SSO for Docker Business, both through a direct integration and through SAML. - -### My SSO connection with Entra ID isn't working and I receive an error that the application is misconfigured. How can I troubleshoot this? - -Confirm that you've configured the necessary API permissions in Entra ID (formerly Azure AD) for your SSO connection. You need to grant administrator consent within your Entra ID (formerly Azure AD) tenant. See [Entra ID (formerly Azure AD) documentation](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/grant-admin-consent?pivots=portal#grant-admin-consent-in-app-registrations). +Confirm that you've configured the necessary API permissions in Entra ID for your SSO connection. You need to grant administrator consent within your Entra ID tenant. See [Entra ID (formerly Azure AD) documentation](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/grant-admin-consent?pivots=portal#grant-admin-consent-in-app-registrations). diff --git a/content/manuals/security/faqs/single-sign-on/users-faqs.md b/content/manuals/security/faqs/single-sign-on/users-faqs.md index 580ecf294531..c2b16dff8990 100644 --- a/content/manuals/security/faqs/single-sign-on/users-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/users-faqs.md @@ -1,107 +1,61 @@ --- -description: Single sign-on user management FAQs -keywords: Docker, Docker Hub, SSO FAQs, single sign-on -title: FAQs for SSO and user management +title: SSO user management FAQs linkTitle: User management +description: Frequently asked questions about managing users with Docker single sign-ons +keywords: SSO user management, user provisioning, SCIM, just-in-time provisioning, organization members tags: [FAQ] aliases: - /single-sign-on/users-faqs/ - /faq/security/single-sign-on/users-faqs/ --- -### How do I manage users when using SSO? +## Do I need to manually add users to my organization? -You can manage users through organizations in Docker Hub or Admin Console. When you configure SSO in Docker, you need to make sure an account exists for each user in your IdP account. When a user signs in to Docker for the first time using their domain email address, they will be automatically added to the organization after a successful authentication. +No, you don't need to manually add users to your organization. Just ensure user accounts exist in your IdP. When users sign in to Docker with their domain email address, they're automatically added to the organization after successful authentication. -### Do I need to manually add users to my organization? +## Can users use different email addresses to authenticate through SSO? -No, you don’t need to manually add users to your organization in Docker or Admin Console. You just need to make sure an account for your users exists in your IdP. When users sign in to Docker, they're automatically assigned to the organization using their domain email address. +All users must authenticate using the email domain specified during SSO setup. Users with email addresses that don't match the verified domain can sign in as guests with username and password if SSO isn't enforced, but only if they've been invited. -When a user signs in to Docker for the first time using their domain email address, they will be automatically added to the organization after a successful authentication. +## How will users know they're being added to a Docker organization? -### Can users in my organization use different email addresses to authenticate through SSO? +When SSO is turned on, users are prompted to authenticate through SSO the next time they sign in to Docker Hub or Docker Desktop. The system detects their domain email and prompts them to sign in with SSO credentials instead. -During the SSO setup, you’ll have to specify the company email domains that are allowed to authenticate. All users in your organization must authenticate using the email domain specified during SSO setup. Some of your users may want to maintain a different account for their personal projects. +For CLI access, users must authenticate using personal access tokens. -If SSO isn't enforced, users with an email address that doesn't match the verified email domain can sign in with username and password to join the organization as guests. +## Can I convert existing users from non-SSO to SSO accounts? -### Can Docker organization and company owners approve users to join an organization and use a seat, rather than having them automatically added when SSO is enabled? +Yes, you can convert existing users to SSO accounts. Ensure users have: -Organization owners and company owners can approve users by configuring their permissions through their IdP. If the user account is configured in the IdP, the user will be automatically added to the organization in Docker Hub as long as there’s an available seat. +- Company domain email addresses and accounts in your IdP +- Docker Desktop version 4.4.2 or later +- Personal access tokens created to replace passwords for CLI access +- CI/CD pipelines updated to use PATs instead of passwords -### How will users be made aware that they're being made a part of a Docker organization? +For detailed instructions, see [Configure single sign-on](/manuals/enterprise/security/single-sign-on/configure.md). -When SSO is enabled, users will be prompted to authenticate through SSO the next time they try to sign in to Docker Hub or Docker Desktop. The system will see the end-user has a domain email associated with the Docker ID they're trying to authenticate with, and prompts them to sign in with SSO email and credentials instead. +## Is Docker SSO fully synced with the IdP? -If users attempt to sign in through the CLI, they must authenticate using a personal access token (PAT). +Docker SSO provides Just-in-Time (JIT) provisioning by default. Users are provisioned when they authenticate with SSO. If users leave the organization, administrators must manually [remove the user](../../../admin/organization/members.md#remove-a-member-or-invitee) from the organization. -### Is it possible to force users of Docker Desktop to authenticate, and/or authenticate using their company’s domain? - -Yes. Admins can [force users to authenticate with Docker Desktop](/manuals/enterprise/security/enforce-sign-in/_index.md) using a registry key, `.plist` file, or `registry.json` file. - -Once SSO enforcement is set up on their Docker Business organization or company on Hub, when the user is forced to authenticate with Docker Desktop, the SSO enforcement will also force users to authenticate through SSO with their IdP (instead of authenticating using their username and password). - -Users may still be able to authenticate as a guest account using an email address that doesn't match the verified domain. However, they can only authenticate as guests if that non-domain email was invited. - -### Is it possible to convert existing users from non-SSO to SSO accounts? - -Yes, you can convert existing users to an SSO account. To convert users from a non-SSO account: - -- Ensure your users have a company domain email address and they have an account in your IdP. -- Verify that all users have Docker Desktop version 4.4.2 or later installed on their machines. -- Each user has created a PAT to replace their passwords to allow them to sign in through Docker CLI. -- Confirm that all CI/CD pipelines automation systems have replaced their passwords with PATs. - -For detailed prerequisites and instructions on how to enable SSO, see [Configure Single Sign-on](/manuals/enterprise/security/single-sign-on/configure.md). - -### What impact can users expect once we start onboarding them to SSO accounts? - -When SSO is enabled and enforced, your users just have to sign in using the verified domain email address. - -### Is Docker SSO fully synced with the IdP? - -Docker SSO provides Just-in-Time (JIT) provisioning by default, with an option to disable JIT. Users are provisioned when a user authenticates with SSO. If a user leaves the organization, administrators must sign in to Docker and manually [remove the user](../../../admin/organization/members.md#remove-a-member-or-invitee) from the organization. - -[SCIM](/manuals/enterprise/security/provisioning/scim.md) is available to provide full synchronization with users and groups. When you auto-provision users with SCIM, the recommended configuration is to disable JIT so that all auto-provisioning is handled by SCIM. +[SCIM](/manuals/enterprise/security/provisioning/scim.md) provides full synchronization with users and groups. When using SCIM, the recommended configuration is to turn off JIT so all auto-provisioning is handled by SCIM. Additionally, you can use the [Docker Hub API](/reference/api/hub/latest/) to complete this process. -### How does disabling Just-in-Time provisioning impact user sign-in? +## How does turning off Just-in-Time provisioning affect user sign-in? -The option to disable JIT is available when you use the Admin Console and enable SCIM. If a user attempts to sign in to Docker using an email address that is a verified domain for your SSO connection, they need to be a member of the organization to access it, or have a pending invitation to the organization. Users who don't meet these criteria will encounter an `Access denied` error, and will need an administrator to invite them to the organization. +When JIT is turned off (available with SCIM in the Admin Console), users must be organization members or have pending invitations to access Docker. Users who don't meet these criteria get an "Access denied" error and need administrator invitations. See [SSO authentication with JIT provisioning disabled](/manuals/enterprise/security/provisioning/just-in-time.md#sso-authentication-with-jit-provisioning-disabled). -To auto-provision users without JIT provisioning, you can use [SCIM](/manuals/enterprise/security/provisioning/scim.md). - -### What's the best way to provision the Docker subscription without SSO? - -Company or organization owners can invite users through Docker Hub or Admin Console, by email address (for any user) or by Docker ID (assuming the user has an existing Docker account). - -### Can someone join an organization without an invitation? Is it possible to add specific users to an organization with existing email accounts? - -Not without SSO. Joining requires an invite from an organization owner. When SSO is enforced, then the domains verified through SSO will let users automatically join the organization the next time they sign in as a user that has a domain email assigned. - -### When we send an invitation to the user, will the existing account be consolidated and retained? - -Yes, the existing user account will join the organization with all assets retained. - -### How can I view, update, and remove multiple email addresses for my users? - -We only support one email per user on the Docker platform. - -### How can I remove invitees to the organization who haven't signed in? - -You can go to the **Members** page for your organization in Docker Hub or Admin Console, view pending invites, and remove invitees as needed. - -### Is the flow for service account authentication different from a UI user account? +## Can someone join an organization without an invitation? -No, we don't differentiate the two in product. +Not without SSO. Joining requires an invite from an organization owner. When SSO is enforced, users with verified domain emails can automatically join the organization when they sign in. -### Is user information visible in Docker Hub? +## What happens to existing licensed users when SCIM is turned on? -All Docker accounts have a public profile associated with their namespace. If you don't want user information (for example, full name) to be visible, you can remove those attributes from your SSO and SCIM mappings. Alternatively, you can use a different identifier to replace a user's full name. +Turning on SCIM doesn't immediately remove or modify existing licensed users. They retain current access and roles, but you'll manage them through your IdP after SCIM is active. If SCIM is later turned off, previously SCIM-managed users remain in Docker but are no longer automatically updated based on your IdP. -### What happens to existing licensed users when SCIM is enabled? +## Is user information visible in Docker Hub? -Enabling SCIM does not immediately remove or modify existing licensed users in your Docker organization. They retain their current access and roles, but after enabling SCIM, you will manage them in your identity provider (IdP). If SCIM is later disabled, previously SCIM-managed users remain in Docker but are no longer automatically updated or removed based on your IdP. \ No newline at end of file +All Docker accounts have public profiles associated with their namespace. If you don't want user information (like full names) to be visible, remove those attributes from your SSO and SCIM mappings, or use different identifiers to replace users' full names. diff --git a/layouts/shortcodes/admin-registry-access.html b/layouts/shortcodes/admin-registry-access.html deleted file mode 100644 index 07364f8063b0..000000000000 --- a/layouts/shortcodes/admin-registry-access.html +++ /dev/null @@ -1,52 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $ram_navigation := "Select **My Hub**, your organization, **Settings**, and then select **Registry Access**." }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com/) and select your organization." }} - {{ $ram_navigation = "Select **Admin Console**, then **Registry access**." }} -{{ end }} - -To configure Registry Access Management permissions, perform the following steps: - -1. Sign in to {{ $product_link }}. -2. {{ $ram_navigation }} -3. Enable Registry Access Management to set the permissions for your registry. - - > [!NOTE] - > - > When enabled, the Docker Hub registry is set by default; however you can - > also restrict this registry for your developers. - -4. Select **Add registry** and enter your registry details in the applicable -fields, and then select **Create** to add the registry to your list. You can -add up to 100 registries/domains. -5. Verify that the registry appears in your list and select **Save changes**. - -Once you add a registry, it can take up to 24 hours for the changes to be -enforced on your developers’ machines. - -If you want to apply the changes sooner, you must force a Docker signout on your -developers’ machine and have the developers re-authenticate for Docker Desktop. -See the [Caveats](#caveats) section below to learn more about limitations. - -> [!IMPORTANT] -> -> Starting with Docker Desktop version 4.36, you can enforce sign-in for -multiple organizations. If a developer belongs to multiple organizations with -different RAM policies, only the RAM policy for the first organization listed -in the `registry.json` file, `.plist` file, or registry key is enforced. - -> [!TIP] -> -> Since RAM sets policies about where content can be fetched from, the -[ADD](/reference/dockerfile/#add) instruction of the Dockerfile when the -parameter of the ADD instruction is a URL is also subject to registry -restrictions. -> -> If you're using ADD to fetch an image or artifact from a trusted registry via -> URL, make sure the registry's domain is included in your organzation's -> allowed registries list. -> -> RAM is not intended to restrict access to general-purpose external URLs, for -> example, package mirrors or storage services. Attempting to add too many domains -> may cause errors or hit system limits. From 20a79d7317a8d29b19940b4bd85212a4a2641fdd Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Tue, 12 Aug 2025 15:06:34 -0400 Subject: [PATCH 04/10] add subscription pages --- .../security/faqs/single-sign-on/idp-faqs.md | 2 +- content/manuals/subscription/_index.md | 10 +- content/manuals/subscription/change.md | 58 ++++--- .../manuals/subscription/desktop-license.md | 36 +++-- content/manuals/subscription/details.md | 146 ++++++------------ content/manuals/subscription/faq.md | 27 ++-- content/manuals/subscription/manage-seats.md | 30 ++-- content/manuals/subscription/scale.md | 65 +++----- content/manuals/subscription/setup.md | 20 +-- 9 files changed, 164 insertions(+), 230 deletions(-) diff --git a/content/manuals/security/faqs/single-sign-on/idp-faqs.md b/content/manuals/security/faqs/single-sign-on/idp-faqs.md index ff76f5953567..90b5a344e1bb 100644 --- a/content/manuals/security/faqs/single-sign-on/idp-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/idp-faqs.md @@ -1,5 +1,5 @@ --- -title: SSO and identity provider FAQs +title: SSO identity provider FAQs linkTitle: Identity providers description: Frequently asked questions about Docker SSO and identity provider configuration keywords: identity providers, SSO IdP, SAML, Azure AD, Entra ID, certificate management diff --git a/content/manuals/subscription/_index.md b/content/manuals/subscription/_index.md index a3c9d4c6649a..bde65b93eeec 100644 --- a/content/manuals/subscription/_index.md +++ b/content/manuals/subscription/_index.md @@ -1,7 +1,7 @@ --- title: Subscription -description: Learn about subscription features and how to manage your subscription -keywords: Docker, pricing, billing, Pro, Team, business, subscription, tier +description: Learn about Docker subscription features and how to manage your subscription +keywords: docker subscription, pricing, billing, pro, team, business, subscription management weight: 50 params: sidebar: @@ -40,10 +40,8 @@ aliases: - /docker-hub/billing/faq/ --- -A Docker subscription includes licensing for commercial use of Docker products -including Docker Desktop, Docker Hub, Docker Build Cloud, Docker Scout, and -Testcontainers Cloud. +Docker subscriptions provide licensing for commercial use of Docker products including Docker Desktop, Docker Hub, Docker Build Cloud, Docker Scout, and Testcontainers Cloud. -Use the resources here to decide what subscription you need, or manage an existing subscription. +Use these resources to choose the right subscription for your needs or manage your existing subscription. {{< grid items="grid_subscriptions" >}} diff --git a/content/manuals/subscription/change.md b/content/manuals/subscription/change.md index dbefc587510c..13c67a556268 100644 --- a/content/manuals/subscription/change.md +++ b/content/manuals/subscription/change.md @@ -1,7 +1,7 @@ --- -description: Learn how to change your Docker subscription -keywords: Docker Hub, upgrade, downgrade, subscription, Pro, Team, business, pricing title: Change your subscription +description: Upgrade or downgrade your Docker subscription and understand billing changes +keywords: upgrade subscription, downgrade subscription, docker pricing, subscription changes aliases: - /docker-hub/upgrade/ - /docker-hub/billing/upgrade/ @@ -18,27 +18,20 @@ weight: 30 {{% include "tax-compliance.md" %}} -The following sections describe how to change plans when you have a Docker -subscription or legacy Docker subscription. +You can upgrade or downgrade your Docker subscription at any time to match your changing needs. This page explains how to make subscription changes and what to expect with billing and feature access. > [!NOTE] > -> Legacy Docker plans apply to Docker subscribers who last purchased or renewed -> their subscription before December 10, 2024. These subscribers will keep -> their current subscription and pricing until their next renewal date that falls on or -> after December 10, 2024. To see purchase or renewal history, view your -> [billing history](../billing/history.md). For more details about legacy -> subscriptions, see [Announcing Upgraded Docker -> Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). +> Legacy Docker subscribers have different interfaces for subscription changes. Legacy subscriptions apply to subscribers who last purchased or renewed before December 10, 2024. For details, see [Announcing Upgraded Docker Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). ## Upgrade your subscription -When you upgrade a Docker subscription, you immediately have access to all the features and entitlements available in your Docker subscription. For detailed information on features available in each subscription, see [Docker Pricing](https://www.docker.com/pricing). +When you upgrade your Docker subscription, you immediately get access to all features and entitlements in your new subscription tier. For detailed feature information, see [Docker Pricing](https://www.docker.com/pricing). {{< tabs >}} {{< tab name="Docker subscription" >}} -To upgrade your Docker subscription: +To upgrade your subscription: 1. Sign in to [Docker Home](https://app.docker.com/) and select the organization you want to upgrade. @@ -55,9 +48,7 @@ you want to upgrade. {{< /tab >}} {{< tab name="Legacy Docker subscription" >}} -You can upgrade a legacy Docker Core, Docker Build Cloud, or Docker Scout subscription to a Docker subscription that includes access to all tools. - -Contact [Docker sales](https://www.docker.com/pricing/contact-sales/) to upgrade your legacy Docker subscription. +To upgrade your legacy Docker subscription to a new Docker subscription that includes access to all tools, contact [Docker sales](https://www.docker.com/pricing/contact-sales/). {{< /tab >}} {{< /tabs >}} @@ -66,21 +57,26 @@ Contact [Docker sales](https://www.docker.com/pricing/contact-sales/) to upgrade You can downgrade your Docker subscription at anytime before the renewal date. The unused portion of the subscription isn't refundable or creditable. -When you downgrade your subscription, access to paid features is available until the next billing cycle. The downgrade takes effect on the next billing cycle. +You can downgrade your Docker subscription at any time before the renewal date. The unused portion isn't refundable, but you retain access to paid features until the next billing cycle. -> [!IMPORTANT] -> -> If you downgrade your personal account from a Pro subscription to a Personal subscription, note that [Personal subscriptions](details.md#docker-personal) don't include collaborators for private repositories. Only one private repository is included with a Personal subscription. When you downgrade, all collaborators will be removed and additional private repositories are locked. -> Before you downgrade, consider the following: -> - Team size: You may need to reduce the number of team members and convert any private repositories to public repositories or delete them. For information on features available in each tier, see [Docker Pricing](https://www.docker.com/pricing). -> - SSO and SCIM: If you want to downgrade a Docker Business subscription and your organization uses single sign-on (SSO) for user authentication, you need to remove your SSO connection and verified domains before downgrading. After removing the SSO connection, any organization members that were auto-provisioned (for example, with SCIM) need to set up a password to sign in without SSO. To do this, users can [reset their password at sign in](/accounts/create-account/#reset-your-password). +### Downgrade considerations + +Consider the following before downgrading: + +- Team size and repositories: You may need to reduce team members and convert private repositories to public or delete them based on your new subscription limits. +- SSO and SCIM: If downgrading from Docker Business and your organization uses single sign-on, remove your SSO connection and verified domains first. Organization members who were auto-provisioned through SCIM need to reset their passwords to sign in without SSO. +- Private repository collaborators: Personal subscriptions don't include collaborators for private repositories. When downgrading from Pro to Personal, all collaborators are removed and additional private repositories are locked. + +For feature limits in each tier, see [Docker Pricing](https://www.docker.com/pricing). {{< tabs >}} {{< tab name="Docker subscription" >}} -If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to downgrade your subscription. +> [!IMPORTANT] +> +> If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to downgrade your subscription. -To downgrade your Docker subscription: +To downgrade your subscription: 1. Sign in to [Docker Home](https://app.docker.com/) and select the organization you want to downgrade. @@ -91,9 +87,9 @@ the organization you want to downgrade. {{< /tab >}} {{< tab name="Legacy Docker subscription" >}} -If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to downgrade your subscription. - -### Downgrade Legacy Docker subscription +> [!IMPORTANT] +> +> If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to downgrade your subscription. To downgrade your legacy Docker subscription: @@ -103,8 +99,6 @@ To downgrade your legacy Docker subscription: 1. On the upgrade page, select **Downgrade** in the **Free Team** plan card. 1. Follow the on-screen instructions to complete your downgrade. -### Downgrade Docker Build Cloud subscription - To downgrade your Docker Build Cloud subscription: 1. Sign in to [Docker Home](https://app.docker.com) and select **Build Cloud**. @@ -115,6 +109,6 @@ To downgrade your Docker Build Cloud subscription: {{< /tab >}} {{< /tabs >}} -## Pause a subscription +## Subscription pause policy -You can't pause or delay a subscription. If a subscription invoice hasn't been paid on the due date, there's a 15 day grace period, including the due date. \ No newline at end of file +You can't pause or delay a subscription. If a subscription invoice isn't paid by the due date, there's a 15-day grace period starting from the due date. diff --git a/content/manuals/subscription/desktop-license.md b/content/manuals/subscription/desktop-license.md index a0c129a2ab97..f1271ad44fdb 100644 --- a/content/manuals/subscription/desktop-license.md +++ b/content/manuals/subscription/desktop-license.md @@ -1,20 +1,32 @@ --- title: Docker Desktop license agreement -description: Information about Docker Desktop's license agreement -keywords: license agreement, docker desktop, subscription +description: Information about Docker Desktop's license agreement and commercial use requirements +keywords: docker desktop license, subscription service agreement, commercial use, licensing terms weight: 40 --- -Docker Desktop is licensed under the Docker Subscription Service Agreement. When you download and install Docker Desktop, you will be asked to agree to the updated terms. +Docker Desktop is licensed under the [Docker Subscription Service Agreement](https://www.docker.com/legal/docker-subscription-service-agreement). When you download and install Docker Desktop, you're asked to agree to these terms. -Our [Docker Subscription Service Agreement](https://www.docker.com/legal/docker-subscription-service-agreement) states: +The Docker Subscription Service Agreement states: - - Docker Desktop is free for small businesses (fewer than 250 employees AND less than $10 million in annual revenue), personal use, education, and non-commercial open source projects. - - Otherwise, it requires a paid subscription for professional use. -- Paid subscriptions are also required for government entities. -- The Docker Pro, Team, and Business subscriptions include commercial use of Docker Desktop. + - Docker Desktop is free for: + - Small businesses (fewer than 250 employees AND less than $10 million in annual revenue) + - Personal use + - Education + - Non-commercial open source projects +- Docker Desktop requires a paid subscription for: + - Professional use in larger organizations + - Government entities + - Commercial use beyond the free tier limits +- Paid subscriptions that include Docker Desktop: + - Docker Pro, Team, and Business subscriptions -Read the [Blog](https://www.docker.com/blog/updating-product-subscriptions/) and [Docker subscription FAQs](https://www.docker.com/pricing/faq) to learn how this may affect companies using Docker Desktop. +## Understanding licensing terms + +For detailed information about how these terms may affect your organization, see: + +- [Subscription updates blog post](https://www.docker.com/blog/updating-product-subscriptions/) +- [Docker subscription FAQs](https://www.docker.com/pricing/faq) to learn how this may affect companies using Docker Desktop. > [!NOTE] > @@ -22,9 +34,7 @@ Read the [Blog](https://www.docker.com/blog/updating-product-subscriptions/) and Docker Desktop is built using open-source software. For information about the licensing of open-source components in Docker Desktop, select the whale menu > **About Docker Desktop** > **Acknowledgements**. +## Open source components + Docker Desktop distributes some components that are licensed under the GNU General Public License. Select [here](https://download.docker.com/opensource/License.tar.gz) to download the source for these components. - -> [!TIP] -> -> Explore [Docker subscriptions](https://www.docker.com/pricing/) to see what else Docker can offer you. diff --git a/content/manuals/subscription/details.md b/content/manuals/subscription/details.md index 5cf7a39fd903..bd9b5a920015 100644 --- a/content/manuals/subscription/details.md +++ b/content/manuals/subscription/details.md @@ -1,14 +1,14 @@ --- title: Docker subscriptions and features linkTitle: Subscriptions and features -description: Learn about Docker subscription tiers and their features +description: Learn about Docker subscription tiers and their key features keywords: subscription, personal, pro, team, business, features, docker subscription aliases: - /subscription/core-subscription/details/ weight: 10 --- -Docker subscriptions empower development teams by providing the tools they need to ship secure, high-quality apps — fast. These plans include access to Docker's suite of products: +Docker subscriptions provide licensing for commercial use of Docker products and include access to Docker's complete development platform: - [Docker Desktop](../desktop/_index.md): The industry-leading container-first development solution that includes, Docker Engine, Docker CLI, Docker Compose, @@ -22,29 +22,26 @@ Docker subscriptions empower development teams by providing the tools they need testing automation that provides faster tests, a unified developer experience, and more. -The following sections describe some of the key features included with your -Docker subscription or Legacy Docker subscription. +Choose the subscription that fits your needs, from individual developers to large enterprises. > [!NOTE] > -> Legacy Docker plans apply to Docker subscribers who last purchased or renewed their subscription before December 10, 2024. These subscribers will keep their current subscription and pricing until their next renewal date that falls on or after December 10, 2024. To see purchase or renewal history, view your [billing history](../billing/history.md). For more details about Docker Legacy subscriptions, see [Announcing Upgraded Docker Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). +> Legacy Docker plans apply to subscribers who last purchased or renewed before December 10, 2024. These subscribers keep their current subscription and pricing until their next renewal on or after December 10, 2024. {{< tabs >}} {{< tab name="Docker subscription" >}} ## Docker Personal -**Docker Personal** is ideal for open source communities, individual developers, -education, and small businesses. It includes the free use of essential Docker -tools as well as trials for powerful tools that'll level up your development loops. +**Docker Personal** is ideal for open source communities, individual developers, education, and small businesses. Docker Personal includes: -- 1 included repository with continuous vulnerability analysis in Docker Scout +- Essential Docker tools at no cost +- 1 Docker Scout repository with vulnerability analysis - Unlimited public Docker Hub repositories -- 200 pulls per 6 hours Docker Hub image pull rate limit for authenticated users -- 7-day Docker Build Cloud trial -- 7-day Testcontainers Cloud trial +- 200 pulls per 6 hours for authenticated users +- 7-day trials for Docker Build Cloud and Testcontainers Cloud Docker Personal users who want to continue using Docker Build Cloud or Docker Testcontainers Cloud after their trial can upgrade to a Docker Pro subscription at any @@ -57,112 +54,72 @@ For a list of features available in each tier, see [Docker Pricing](https://www. ## Docker Pro -**Docker Pro** enables individual developers to get more control of their -development environment and provides an integrated and reliable developer -experience. It reduces the amount of time developers spend on mundane and -repetitive tasks and empowers developers to spend more time creating value for -their customers. A Docker Pro subscription includes access to all tools, -including Docker Desktop, Docker Hub, Docker Scout, Docker Build Cloud, and -Testcontainers Cloud. +**Docker Pro** is ideal for individual developers who need full access to Docker's development platform. Docker Pro includes: -- 200 Docker Build Cloud build minutes per month. Docker Build Cloud minutes do not -rollover month to month. -- 2 included repositories with continuous vulnerability analysis in Docker Scout. -- 100 Testcontainers Cloud runtime minutes per month for use either in Docker Desktop or for CI. Testcontainers Cloud runtime minutes do not rollover month to month. -- No Docker Hub image pull rate limits. +- Full access to all Docker tools +- 200 Docker Build Cloud minutes per month, Docker Build Cloud minutes do not +rollover month to month +- 2 Docker Scout repositories with vulnerability analysis +- 100 Testcontainers Cloud runtime minutes per month, Testcontainers Cloud runtime minutes do not rollover month to month +- No Docker Hub pull rate limits For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). ## Docker Team -**Docker Team** offers capabilities for collaboration, productivity, and -security across organizations. It enables groups of developers to unlock the -full power of collaboration and sharing combined with essential security -features and team management capabilities. A Docker Team subscription includes -licensing for commercial use of Docker components including Docker Desktop, -Docker Hub, Docker Scout, Docker Build Cloud, and Testcontainers Cloud. +**Docker Team** is ideal for development teams that need collaboration and security features. Docker Team includes: -- 500 Docker Build Cloud build minutes per month. Docker Build Cloud minutes do not -rollover month to month. -- Unlimited Docker Scout repositories with continuous vulnerability analysis. -- 500 Testcontainers Cloud runtime minutes per month for use either in Docker Desktop or for CI. Testcontainers Cloud runtime minutes do not rollover month to month. -- No Docker Hub image pull rate limits. - -There are also advanced collaboration and management tools, including -organization and team management with [Role Based Access Control -(RBAC)](/security/for-admins/roles-and-permissions/), [activity logs](/admin/organization/activity-logs/), and more. +- 500 Docker Build Cloud minutes per month, Docker Build Cloud minutes do not +rollover month to month +- Unlimited Docker Scout repositories with vulnerability analysis +- 500 Testcontainers Cloud runtime minutes per month, Testcontainers Cloud runtime minutes do not rollover month to month +- No Docker Hub pull rate limits +- Advanced collaboration tools including organization management, [Role Based Access Control +(RBAC)](/security/for-admins/roles-and-permissions/), [activity logs](/admin/organization/activity-logs/), and more For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). ## Docker Business -**Docker Business** offers centralized management and advanced security features -for enterprises that use Docker at scale. It empowers leaders to manage their -Docker development environments and speed up their secure software supply chain -initiatives. A Docker Business subscription includes licensing for commercial use of -Docker components including Docker Desktop, Docker Hub, Docker Scout, Docker -Build Cloud, and Testcontainers Cloud. +**Docker Business** is ideal for enterprises that need centralized management and advanced security. Docker Business includes: -- 1500 Docker Build Cloud build minutes per month. Docker Build Cloud minutes do not -rollover month to month. -- Unlimited Docker Scout repositories with continuous vulnerability analysis. -- 1500 Testcontainers Cloud runtime minutes per month for use either in Docker Desktop or for CI. Testcontainers Cloud runtime minutes do not rollover month to month. -- No Docker Hub image pull rate limits. - -In addition, you gain access to enterprise-grade features, such as: -- [Hardened Docker Desktop](/manuals/enterprise/security/hardened-desktop/_index.md) -- [Image Access +- 1500 Docker Build Cloud minutes per month, Docker Build Cloud minutes do not +rollover month to month +- Unlimited Docker Scout repositories with vulnerability analysis +- 1500 Testcontainers Cloud runtime minutes per month, Testcontainers Cloud runtime minutes do not rollover month to month +- No Docker Hub pull rate limits +- Enterprise security features: + - [Hardened Docker Desktop](/manuals/enterprise/security/hardened-desktop/_index.md) + - [Image Access Management](/manuals/enterprise/security/hardened-desktop/image-access-management.md) which lets admins control what content developers can access -- [Registry Access + - [Registry Access Management](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) which lets admins control what registries developers can access -- [Company layer](/admin/company/) to manage multiple organizations and settings -- [Single sign-on](/security/for-admins/single-sign-on/) -- [System for Cross-domain Identity + - [Company layer](/admin/company/) to manage multiple organizations and settings + - [Single sign-on](/security/for-admins/single-sign-on/) + - [System for Cross-domain Identity Management](/security/for-admins/provisioning/scim/) For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). -## Self-serve - -A self-serve Docker subscription is where everything is set up by you. -You can: - -- Manage your own invoices -- Add or remove seats -- Update billing and payment information -- Downgrade your subscription at any time - -## Sales-assisted - -A sales-assisted subscription refers to a Docker Business or Team subscription where everything is set up and -managed by a dedicated Docker account manager. - {{< /tab >}} {{< tab name="Legacy Docker plans" >}} > [!IMPORTANT] > -> As of December 10, 2024, Docker Core, Docker Build Cloud, and Docker Scout -> subscriptions are no longer available and have been replaced by Docker subscription -> plans that provide access to all tools. If you subscribed or renewed -> your subscriptions before December 10, 2024, your legacy Docker -> plans still apply to your account until you renew. For more details, -> see [Announcing Upgraded Docker -> Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). -The following describes some of the key features included with your Legacy Docker plans: +> Legacy Docker plans apply to subscribers who last purchased or renewed before December 10, 2024. These subscribers keep their current subscription and pricing until their next renewal on or after December 10, 2024. -![Docker Core subscription diagram](./images/subscription-diagram.webp) +If you have a legacy subscription, you'll automatically upgrade to the new Docker subscription model when you renew. The new plans provide access to all Docker tools with increased limits and additional features. ## Legacy Docker plans @@ -261,19 +218,6 @@ When you upgrade your Legacy Docker Business subscription to a Docker Business s For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). -#### Self-serve - -A self-serve Docker Business subscription is where everything is set up by you. You can: - -- Manage your own invoices -- Add or remove seats -- Update billing and payment information -- Downgrade your subscription at any time - -#### Sales-assisted - -A sales-assisted Docker Business subscription where everything is set up and managed by a dedicated Docker account manager. - ## Legacy Docker Scout subscriptions This section provides an overview of the legacy subscriptions for Docker @@ -392,6 +336,16 @@ a Docker subscription, your subscription includes the following changes: {{< /tab >}} {{< /tabs >}} -## Support for subscriptions +## Subscription management options + +### Self-serve + +You manage everything directly including invoices, seats, billing information, and subscription changes. + +### Sales-assisted + +A dedicated Docker account manager handles setup and management for Docker Business and Team subscriptions. + +## Support All Docker Pro, Team, and Business subscribers receive email support for their subscriptions. \ No newline at end of file diff --git a/content/manuals/subscription/faq.md b/content/manuals/subscription/faq.md index b4713d9b6326..244195dec140 100644 --- a/content/manuals/subscription/faq.md +++ b/content/manuals/subscription/faq.md @@ -1,30 +1,31 @@ --- -description: FAQs on Docker subscriptions -keywords: Docker, Docker Hub, subscription FAQs, subscription, platform title: Subscription FAQs linkTitle: FAQs +description: Frequently asked questions about Docker subscriptions and billing +keywords: subscription faqs, docker billing, subscription transfer, academic pricing, docker programs tags: [FAQ] weight: 50 --- For more information on Docker subscriptions, see [Docker subscription overview](_index.md). -### Can I transfer my subscription from one user or organization account to another? +## Can I transfer my subscription from one user or organization account to another? -Subscriptions are non-transferable. +Subscriptions are non-transferable between accounts or organizations. -### Can I pause or delay my Docker subscription? +## Can I pause or delay my Docker subscription? -You can't pause or delay a subscription, but you can [downgrade](change.md). If a subscription invoice hasn't been paid on the due date, there's a 15 day grace period, including the due date. +You can't pause or delay a subscription, but you can downgrade your subscription. If a subscription invoice isn't paid by the due date, there's a 15-day grace period starting from the due date. -### Does Docker offer academic pricing? +## Does Docker offer academic pricing? -Contact the [Docker Sales Team](https://www.docker.com/company/contact). +Contact the [Docker Sales Team](https://www.docker.com/company/contact) for information about academic pricing options. -### What ways can I contribute to Docker content? +## How can I contribute to Docker content? -Docker offers two programs: -- [Docker-Sponsored Open Source Program (DSOS)](../docker-hub/repos/manage/trusted-content/dsos-program.md) -- [Docker Verified Publisher (DVP)](../docker-hub/repos/manage/trusted-content/dvp-program.md) +Docker offers two content contribution programs: -You can also join the [Developer Preview Program](https://www.docker.com/community/get-involved/developer-preview/) or sign up for early access programs for specific products to participate in research and try out new features. +- [Docker-Sponsored Open Source Program (DSOS)](../docker-hub/repos/manage/trusted-content/dsos-program.md) for open source projects +- [Docker Verified Publisher (DVP)](../docker-hub/repos/manage/trusted-content/dvp-program.md) for commerical publishers + +You can also join the [Developer Preview Program](https://www.docker.com/community/get-involved/developer-preview/) or sign up for early access programs to participate in research and try new features. diff --git a/content/manuals/subscription/manage-seats.md b/content/manuals/subscription/manage-seats.md index dfa6410478b9..0c095a48c54b 100644 --- a/content/manuals/subscription/manage-seats.md +++ b/content/manuals/subscription/manage-seats.md @@ -1,8 +1,8 @@ --- -description: Learn how to add or remove seats for an existing subscription -keywords: Docker, Docker Hub, subscription, update, add, seats, pricing title: Manage subscription seats linkTitle: Manage seats +description: Add or remove seats for Docker Team and Business subscriptions +keywords: manage seats, add seats, remove seats, subscription billing, team members aliases: - /docker-hub/billing/add-seats/ - /subscription/add-seats/ @@ -13,13 +13,11 @@ aliases: weight: 20 --- -You can add seats at anytime to your existing subscription. - -When you add seats to your subscription in the middle of your billing cycle, you are charged a prorated amount for the additional seats. +You can add or remove seats from your Docker Team or Business subscription at any time to accommodate team changes. When you add seats mid-billing cycle, you're charged a prorated amount for the additional seats. {{% include "tax-compliance.md" %}} -## Add seats +## Add seats to your subscription {{< tabs >}} {{< tab name="Docker subscription" >}} @@ -28,7 +26,7 @@ When you add seats to your subscription in the middle of your billing cycle, you > > If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to add seats to your subscription. -To add seats to your subscription: +To add seats: 1. Sign in to [Docker Home](https://app.docker.com/) and select your organization. @@ -50,14 +48,14 @@ You can now add more members to your organization. For more information, see [Ma > > If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to add seats to your subscription. -### Add seats to Legacy Docker subscription +To add seats to your Legacy Docker subscription: 1. Sign in to [Docker Hub](https://hub.docker.com). 1. Select your organization, then select **Billing**. 1. On the Billing page, select **Add seats**. 1. Select the number of seats you want to add, then select **Purchase**. -### Add seats to Docker Build Cloud +To add seats to Docker Build Cloud: 1. Sign in to [Docker Home](https://app.docker.com) and select **Build Cloud**. 1. Select **Account settings**, then **Add seats**. @@ -66,17 +64,15 @@ You can now add more members to your organization. For more information, see [Ma {{< /tab >}} {{< /tabs >}} -### Volume pricing +## Volume pricing Docker offers volume pricing for Docker Business subscriptions starting at 25 seats. Contact the [Docker Sales Team](https://www.docker.com/pricing/contact-sales/) for more information. -## Remove seats - -You can remove seats from your Team or Business subscription at anytime. +## Remove seats from your subscription -If you remove seats in the middle of the billing cycle, changes apply in the next billing cycle. Any unused portion of the subscription for removed seats isn't refundable or creditable. +You can remove seats from your Team or Business subscription at any time. Changes apply to your next billing cycle, and unused portions aren't refundable. -For example, if you receive your billing on the 8th of every month for 10 seats and you want to remove 2 seats on the 15th of the month, the 2 seats will be removed from your subscription the next month. Your payment for 8 seats begins on the next billing cycle. If you're on the annual subscription, the 2 seats are still available until the next year, and your payment for the 8 seats begins on the next billing cycle. +For example, if you're billed on the 8th of every month for 10 seats and remove 2 seats on the 15th, the 2 seats remain available until your next billing cycle. Your payment for 8 seats begins on the next billing cycle. {{< tabs >}} {{< tab name="Docker subscription" >}} @@ -102,14 +98,14 @@ You can cancel the removal of seats before your next billing cycle. To do so, se > > If you have a [sales-assisted Docker Business subscription](details.md#sales-assisted), contact your account manager to remove seats from your subscription. -### Remove seats from Legacy Docker subscription +To remove seats from your Legacy Docker subscription: 1. Sign in to [Docker Hub](https://hub.docker.com). 1. Select your organization, then select **Billing**. 1. On the Billing page, select **Remove seats**. 1. Follow the on-screen instructions to complete removing seats. -### Remove seats from Docker Build Cloud +To remove seats from Docker Build Cloud: 1. Sign in to [Docker Home](https://app.docker.com) and select **Build Cloud**. 1. Select **Account settings**, then **Remove seats**. diff --git a/content/manuals/subscription/scale.md b/content/manuals/subscription/scale.md index 5e73e79c97bb..b7b809b2adda 100644 --- a/content/manuals/subscription/scale.md +++ b/content/manuals/subscription/scale.md @@ -1,52 +1,31 @@ --- -description: Learn how to scale your Docker subscription -keywords: subscription, Pro, Team, business, pricing, build minutes, test container minutes, pull limit title: Scale your subscription +description: Scale Docker Build Cloud and Testcontainers Cloud consumption for your subscription +keywords: scale subscription, docker build cloud minutes, testcontainers cloud minutes, usage scaling weight: 17 --- -> [!NOTE] -> -> Owners of legacy Docker subscriptions must upgrade their subscription to a new -> Docker subscription in order to scale their subscription. -> -> Legacy Docker subscriptions apply to Docker subscribers who last purchased or renewed -> their subscription before December 10, 2024. These subscribers will keep -> their current subscription and pricing until their next renewal date that falls on or -> after December 10, 2024. To see purchase or renewal history, view your -> [billing history](../billing/history.md). For more details about legacy -> after December 10, 2024. For more details about legacy -> subscriptions, see [Announcing Upgraded Docker -> Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). - -Docker subscriptions let you scale your consumption as your needs evolve. Except -for legacy Docker subscriptions, all paid Docker subscriptions come with -access to Docker Hub, Docker Build Cloud, and Testcontainers Cloud with a base -amount of consumption. See [Docker subscriptions and features](./details.md) to -learn how much base consumption comes with each subscription. You can scale your -consumption at any time during your subscription period. - -You can scale consumption for the following: +Docker subscriptions let you scale consumption as your needs grow. All paid Docker subscriptions include base amounts of Docker Build Cloud build minutes and Testcontainers Cloud runtime minutes that you can supplement with additional capacity. +You can scale consumption for: - Docker Build Cloud build minutes -- Docker Testcontainers Cloud runtime minutes +- Testcontainers Cloud runtime minutes -To better understand your needs, you can view your consumption at any time. For -more details, see [View Docker product -usage](../admin/organization/manage-products.md#view-docker-product-usage). +To understand your usage patterns, [view your consumption](../admin/organization/manage-products.md#view-docker-product-usage) at any time. -> [!WARNING] +> [!NOTE] > -> The number of Docker Build Cloud and Testcontainers minutes included in your -subscription do not rollover. Additional minutes expire at the end of your -subscription period (monthly or annually). For example, if you have an annual -Docker Team subscription with 500 included minutes, and purchase 500 additional -minutes, only the 500 additional minutes rollover until the end of your annual -subscription period. +> Legacy Docker subscribers must upgrade to new Docker subscriptions to access scaling options. Legacy subscriptions apply to subscribers who last purchased or renewed before December 10, 2024. For details, see [Announcing Upgraded Docker Plans](https://www.docker.com/blog/november-2024-updated-plans-announcement/). + +## Usage considerations + +Minutes don't roll over. Base subscription minutes reset each billing period and don't accumulate. Additional purchased minutes expire at the end of your subscription period. + +For example, with an annual Docker Team subscription (500 included minutes), if you purchase 500 additional minutes, only the additional 500 minutes roll over until your annual renewal. ## Add Docker Build Cloud build minutes -You can pre-purchase Docker Build Cloud build minutes in the Docker Build Cloud Dashboard: +Purchase additional build minutes through the Docker Build Cloud Dashboard: 1. Sign in to [Docker Home](https://app.docker.com/) and choose your organization. @@ -56,13 +35,13 @@ your organization. 1. Enter your payment details and billing address. 1. Review your order and select **Pay**. -Your additional minutes will now display on the Build minutes page. +Your additional minutes appear on the Build minutes page immediately. ## Add Docker Testcontainers Cloud runtime minutes -You can pre-purchase Testcontainers Cloud runtime minutes by [contacting - sales](https://www.docker.com/pricing/contact-sales/). In addition to -pre-purchase, you are able to use as many minutes as you need on-demand. The -usage will be billed at the end of each monthly billing cycle. On-demand usage -is billed at a higher rate than pre-purchased capacity. To avoid on-demand -charges, pre-purchase additional minutes. \ No newline at end of file +You can add Testcontainers Cloud runtime minutes in two ways: + +- [Contact sales](https://www.docker.com/pricing/contact-sales/) to pre-purchase runtime minutes at discounted rates +- Use unlimited runtime minutes on-demand with billing at the end of each monthly cycle + +On-demand usage is billed at higher rates than pre-purchased capacity. To avoid higher on-demand charges, pre-purchase additional minutes if you expect consistent usage over your subscription's included minutes. diff --git a/content/manuals/subscription/setup.md b/content/manuals/subscription/setup.md index 22670088e3dc..eecdd6d80f46 100644 --- a/content/manuals/subscription/setup.md +++ b/content/manuals/subscription/setup.md @@ -1,26 +1,28 @@ --- -description: Learn how to set up your Docker subscription -keywords: subscription, Pro, Team, Business, pricing +description: Set up Docker subscriptions for personal accounts and organizations +keywords: subscription setup, docker pro, docker team, docker business, organization setup title: Set up your subscription weight: 15 --- -Docker subscriptions offer features and benefits to support both new and professional developers, as well as plans for individuals, teams, and enterprise businesses. To learn more about what's included with each tier, see [Docker subscriptions and features](./details.md) and [Docker Pricing](https://www.docker.com/pricing/). +Docker subscriptions provide features and benefits for individual developers, teams, and enterprise businesses. This page explains how to set up subscriptions for personal accounts and organizations. -In this section, learn how to get started with a Docker subscription for individuals or for organizations. Before you begin, make sure you have a [Docker ID](../accounts/create-account.md). +Before you begin, make sure you have a [Docker ID](../accounts/create-account.md). To learn more about what's included with each tier, see [Docker subscriptions and features](./details.md) and [Docker Pricing](https://www.docker.com/pricing/). {{% include "tax-compliance.md" %}} ## Set up a Docker subscription for a personal account -After you [create your Docker ID](../accounts/create-account.md), you have a Docker Personal subscription. To continue using this subscription, no further action is necessary. For additional features, you can upgrade to a Docker Pro subscription. +When you [create your Docker ID](../accounts/create-account.md), you automatically get a Docker Personal subscription. This subscription includes essential Docker tools at no cost. If you want to continue with Docker Personal, no further action is needed. You can start using Docker Desktop, Docker Hub, and other tools immediately. -To upgrade from Docker Personal to Docker Pro, see [Upgrade your subscription](./change.md#upgrade-your-subscription). +If you need additional features like Docker Build Cloud minutes and more Docker Scout repositories, see [Upgrade your subscription](./change.md#upgrade-your-subscription). ## Set up a Docker subscription for an organization -You can subscribe a new or existing organization to a Docker subscription. Only organization owners can manage billing for the organization. +You can subscribe a new or existing organization to Docker Team or Business subscriptions. Only organization owners can manage billing for the organization. -After you [create your Docker ID](../accounts/create-account.md), you have a Docker Personal subscription. You must then create an organization and choose a subscription for it. For more details, see [Create your organization](../admin/organization/orgs.md). +1. [Create your Docker ID](../accounts/create-account.md) if you don't already have one. +1. [Create your organization](../admin/organization/orgs.md) or use an existing organization you own. +1. Choose and purchase a Docker Team or Business subscription for the organization. -To learn how to upgrade a Docker subscription for an existing organization, see [Upgrade your subscription](./change.md#upgrade-your-subscription). \ No newline at end of file +To upgrade an existing organization's subscription, see [Upgrade your subscription](./change.md#upgrade-your-subscription). From 32ff57182183dc97bfe05301cd28b144344dab76 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Wed, 13 Aug 2025 10:19:08 -0400 Subject: [PATCH 05/10] proofreadinggit add . --- content/manuals/desktop/release-notes.md | 2 +- .../enterprise/security/access-tokens.md | 38 ++++++------- .../enterprise/security/domain-management.md | 30 +++------- .../security/enforce-sign-in/_index.md | 29 +++++----- .../security/enforce-sign-in/methods.md | 26 ++++----- .../security/hardened-desktop/_index.md | 8 +-- .../hardened-desktop/air-gapped-containers.md | 52 +++++++++--------- .../enhanced-container-isolation/_index.md | 12 ++-- .../enhanced-container-isolation/config.md | 38 ++++++------- .../enable-eci.md | 41 +++++++------- .../image-access-management.md | 10 ++-- .../registry-access-management.md | 6 +- .../settings-management/_index.md | 15 ++--- .../compliance-reporting.md | 10 ++-- .../configure-json-file.md | 9 +-- .../security/images/enforce-sign-in.png | Bin 140986 -> 0 bytes ...es-and-permissions-member-editor-roles.png | Bin 29758 -> 0 bytes .../security/provisioning/_index.md | 17 +++--- .../security/provisioning/group-mapping.md | 20 ++++--- .../security/provisioning/just-in-time.md | 22 +++++--- .../enterprise/security/provisioning/scim.md | 27 +++++---- .../security/roles-and-permissions.md | 7 +-- .../security/single-sign-on/_index.md | 11 ++-- .../security/single-sign-on/configure.md | 16 +++--- .../security/single-sign-on/connect.md | 18 +++--- .../security/single-sign-on/manage.md | 18 +----- .../manuals/scout/explore/metrics-exporter.md | 8 +-- content/manuals/security/2fa/_index.md | 1 + content/manuals/security/access-tokens.md | 7 +-- content/manuals/security/faqs/_index.md | 2 +- .../security/security-announcements.md | 1 + content/manuals/subscription/details.md | 16 +++--- .../images/subscription-diagram.webp | Bin 59342 -> 0 bytes hugo_stats.json | 4 +- layouts/shortcodes/admin-domains.html | 35 ------------ layouts/shortcodes/admin-image-access.html | 27 --------- layouts/shortcodes/admin-sso-config.md | 36 ------------ layouts/shortcodes/admin-sso-connect.md | 48 ---------------- .../admin-sso-management-connections.md | 27 --------- .../shortcodes/admin-sso-management-orgs.md | 27 --------- 40 files changed, 249 insertions(+), 472 deletions(-) delete mode 100644 content/manuals/enterprise/security/images/enforce-sign-in.png delete mode 100644 content/manuals/enterprise/security/images/roles-and-permissions-member-editor-roles.png delete mode 100644 content/manuals/subscription/images/subscription-diagram.webp delete mode 100644 layouts/shortcodes/admin-domains.html delete mode 100644 layouts/shortcodes/admin-image-access.html delete mode 100644 layouts/shortcodes/admin-sso-config.md delete mode 100644 layouts/shortcodes/admin-sso-connect.md delete mode 100644 layouts/shortcodes/admin-sso-management-connections.md delete mode 100644 layouts/shortcodes/admin-sso-management-orgs.md diff --git a/content/manuals/desktop/release-notes.md b/content/manuals/desktop/release-notes.md index 268039785d0d..4b4127d0acf2 100644 --- a/content/manuals/desktop/release-notes.md +++ b/content/manuals/desktop/release-notes.md @@ -68,7 +68,7 @@ We are aware of [CVE-2025-23266](https://nvd.nist.gov/vuln/detail/CVE-2025-23266 - Fixed an issue pulling images with zstd differential layers when the containerd image store is enabled. - Fixed a bug causing containers launching with the `--restart` flag to not restart properly when using Enhanced Container Isolation. -- Improved interaction between [Kubernetes custom registry images](/manuals/desktop/features/kubernetes.md#configuring-a-custom-image-registry-for-kubernetes-control-plane-images) and Enhanced Container Isolation (ECI), so the [ECI Docker Socket image list](/enterprise/security/hardened-desktop/enhanced-container-isolation/config/#image-list) no longer needs to be manually updated when using a custom registry for Kubernetes control plane images. +- Improved interaction between [Kubernetes custom registry images](/manuals/desktop/features/kubernetes.md#configuring-a-custom-image-registry-for-kubernetes-control-plane-images) and Enhanced Container Isolation (ECI), so the [ECI Docker Socket image list](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md) no longer needs to be manually updated when using a custom registry for Kubernetes control plane images. - Fixed a bug where a Docker Desktop Kubernetes cluster in kind mode fails to start after restarting Docker Desktop if the user is required to be signed in but is currently signed out. - Fixed a bug that prevented the mounting of MCP secrets into containers when [Enhanced Container Isolation](/enterprise/security/hardened-desktop/enhanced-container-isolation/) is enabled. - Fixed a bug preventing the use of `--publish-all` when `--publish` was already specified. diff --git a/content/manuals/enterprise/security/access-tokens.md b/content/manuals/enterprise/security/access-tokens.md index 9b62c122c48b..b275e8c956f4 100644 --- a/content/manuals/enterprise/security/access-tokens.md +++ b/content/manuals/enterprise/security/access-tokens.md @@ -15,7 +15,7 @@ Organization access tokens (OATs) provide secure, programmatic access to Docker > > Organization access tokens are incompatible with Docker Desktop, Image Access Management, and Registry Access Management. If you use these features, use [personal access tokens](/manuals/security/access-tokens.md) instead. -## When to use organization access tokens +## Who should use organization access tokens? Use OATs for automated systems that need Docker Hub access without depending on individual user accounts: @@ -25,14 +25,6 @@ Use OATs for automated systems that need Docker Hub access without depending on - Backup systems: Tools that periodically pull images for archival - Integration services: Third-party tools that integrate with your Docker Hub repositories -## Prerequisites - -To create and use organization access tokens, you must have: - -- A Docker Team or Business subscription -- Owner permissions -- Repositories you want to grant access to - ## Key benefits Benefits of using organization access tokens include: @@ -43,6 +35,14 @@ Benefits of using organization access tokens include: - Better security audit: Track when tokens were last used and identify suspicious activity - Granular permissions: Limit access to specific repositories and operations +## Prerequisites + +To create and use organization access tokens, you must have: + +- A Docker Team or Business subscription +- Owner permissions +- Repositories you want to grant access to + ## Create an organization access token Owners can create tokens with these limits: @@ -59,14 +59,14 @@ organization. 1. Select **Admin Console**, then **Access tokens**. 1. Select **Generate access token**. 1. Configure token details: - - Label: Descriptive name indicating the token's purpose - - Description (optional): Additional details - - Expiration date: When the token should expire + - Label: Descriptive name indicating the token's purpose + - Description (optional): Additional details + - Expiration date: When the token should expire 1. Expand the **Repository** drop-down to set access permissions: - 1. Optional. Select **Read public repositories** for access to public repositories. - 1. Select **Add repository** and choose a repository from the drop-down. - 1. Set permissions for each repository: **Image Pull** or **Image Push**. - 1. Add up to 50 repositories as needed. + 1. Optional. Select **Read public repositories** for access to public repositories. + 1. Select **Add repository** and choose a repository from the drop-down. + 1. Set permissions for each repository: **Image Pull** or **Image Push**. + 1. Add up to 50 repositories as needed. 1. Optional. Configure organization management permissions by expanding the **Organization** drop-down and selecting the **Allow management access to this organization's resources**: - **Member Edit**: Edit members of the organization - **Member Read**: Read members of the organization @@ -99,9 +99,9 @@ To manage existing tokens: organization. 1. Select **Admin Console**, then **Access tokens**. 1. Select the actions menu in the token row, you can: - - **Edit** - - **Deactivate** - - **Delete** + - **Edit** + - **Deactivate** + - **Delete** 1. Select **Save** after making changes to a token. ## Organization access token best practices diff --git a/content/manuals/enterprise/security/domain-management.md b/content/manuals/enterprise/security/domain-management.md index 6ddfd5297bf4..a4307582c98f 100644 --- a/content/manuals/enterprise/security/domain-management.md +++ b/content/manuals/enterprise/security/domain-management.md @@ -9,9 +9,9 @@ aliases: {{< summary-bar feature_name="Domain management" >}} -Domain management lets you add and verify domains for your organization, then enable auto-provisioning to automatically add users when they sign in with email addresses that match your verified domains. +Domain management lets you add and verify domains for your organization, then enable auto-provisioning to automatically add users when they sign in with email addresses that match your verified domains. This approach simplifies user management, ensures consistent security settings, and reduces the risk of unmanaged users accessing Docker without visibility or control. -This approach simplifies user management, ensures consistent security settings, and reduces the risk of unmanaged users accessing Docker without visibility or control. +This page provides steps to add and delete domains, configure auto-provisioning, and audit uncaptured users. ## Add and verify a domain @@ -29,23 +29,11 @@ and configure the domain for the organization at the company level. ### Verify a domain -Verification confirms that you own the domain by adding a TXT record to your Domain Name System (DNS) host. - -It can take up to 72 hours for the DNS change to propagate. Docker automatically -checks for the record and confirms ownership once the change is recognized. +Verification confirms that you own the domain by adding a TXT record to your Domain Name System (DNS) host. It can take up to 72 hours for the DNS change to propagate. Docker automatically checks for the record and confirms ownership once the change is recognized. > [!TIP] > -> The record name field determines where the TXT record is added in your domain -(root or subdomain). In general, refer to the following tips for -adding a record name: -> -> - Use `@` or leave the record name empty for root domains like `example.com`, -depending on your provider. -> - Don't enter values like `docker`, `docker-verification`, `www`, or your -domain name. These values may direct to the wrong place. -> -> Check your DNS provider's documentation to verify record name requirements. +> The record name field determines where the TXT record is added in your domain (root or subdomain). For root domains like `example.com`, use `@` or leave the record name empty, depending on your provider. Don't enter values like docker, `docker-verification`, `www`, or your domain name, as these may direct to the wrong place. Check your DNS provider's documentation to verify record name requirements. Follow the steps for your DNS provider to add the **TXT Record Value**. If your provider isn't listed, use the steps for "Other providers": @@ -113,8 +101,7 @@ When auto-provisioning is enabled for a verified domain: Auto-provisioning is configured per domain. To enable it: 1. Sign in to [Docker Home](https://app.docker.com) and select -your organization. If your organization is part of a company, select the company -and configure the domain for the organization at the company level. +your company or organization. 1. Select **Admin Console**, then **Domain management**. 1. Select the **Actions menu** next to the domain you want to enable auto-provisioning for. @@ -162,10 +149,9 @@ company. of uncaptured users. The CSV file contains the following columns: - - - Name: Docker user's display name - - Username: Docker ID of the user - - Email: Email address of the user +- Name: Docker user's display name +- Username: Docker ID of the user +- Email: Email address of the user ### Invite uncaptured users diff --git a/content/manuals/enterprise/security/enforce-sign-in/_index.md b/content/manuals/enterprise/security/enforce-sign-in/_index.md index c62acdc0ed3e..fac6594f7afd 100644 --- a/content/manuals/enterprise/security/enforce-sign-in/_index.md +++ b/content/manuals/enterprise/security/enforce-sign-in/_index.md @@ -14,9 +14,8 @@ weight: 30 {{< summary-bar feature_name="Enforce sign-in" >}} -By default, users can run Docker Desktop without signing in to your organization. -When users don't sign in as organization members, they miss out on [subscription benefits](/manuals/subscription/details.md) and can bypass -[security features](/manuals/enterprise/security/hardened-desktop/_index.md) configured for your organization. +By default, users can access Docker Desktop without signing in to your organization. +When users don't sign in as organization members, they miss out on subscription benefits and can bypass security features configured for your organization. You can enforce sign-in using several methods, depending on your setup: @@ -25,20 +24,21 @@ You can enforce sign-in using several methods, depending on your setup: - [`.plist` method (Mac only)](methods.md#plist-method-mac-only) - [`registry.json` method (All)](methods.md#registryjson-method-all) +This page provides an overview of how sign-in enforcement works. + ## How sign-in enforcement works When Docker Desktop detects a registry key, `.plist` file, or `registry.json` file: -- A **Sign in required!** prompt appears, requiring users to sign - in as organization members to use Docker Desktop. ![Enforce Sign-in - Prompt](../../images/enforce-sign-in.png?w=400) +- A `Sign in required!` prompt appears, requiring users to sign + in as organization members to use Docker Desktop. - If users sign in with accounts that aren't organization members, they're automatically signed out and can't use Docker Desktop. They can select **Sign in** to try again with a different account. - When users sign in with organization member accounts, they can use Docker Desktop normally. -- When users sign out, the **Sign in required!** prompt reappears and they can +- When users sign out, the `Sign in required!` prompt reappears and they can no longer use Docker Desktop unless they sign back in. > [!NOTE] @@ -47,16 +47,17 @@ When Docker Desktop detects a registry key, `.plist` file, or ## Enforcing sign-in versus enforcing single sign-on (SSO) -Enforcing Docker Desktop sign-in and [enforcing SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso) are different features that server different purposes: +Enforcing Docker Desktop sign-in and [enforcing SSO](/manuals/enterprise/security/single-sign-on/connect.md#optional-enforce-sso) are different features that serve different purposes: | Enforcement | Description | Benefits | |:----------------------------------|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Enforce sign-in only | Users must sign in before using Docker Desktop. | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. | -| Enforce single sign-on (SSO) only | If users sign in, they must sign in using SSO. | Centralizes authentication and enforces unified policies set by the identity provider. | -| Enforce both | Users must sign in using SSO before using Docker Desktop. | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. It also centralizes authentication and enforces unified policies set by the identity provider. | -| Enforce neither | If users sign in, they can use SSO or their Docker credentials. | Lets users access Docker Desktop without barriers, at the cost of reduced security and insights. | +| Enforce sign-in only | Users must sign in before using Docker Desktop | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. | +| Enforce single sign-on (SSO) only | If users sign in, they must sign in using SSO | Centralizes authentication and enforces unified policies set by the identity provider. | +| Enforce both | Users must sign in using SSO before using Docker Desktop | Ensures users receive the benefits of your subscription and ensures security features are applied. In addition, you gain insights into users’ activity. It also centralizes authentication and enforces unified policies set by the identity provider. | +| Enforce neither | If users sign in, they can use SSO or their Docker credentials | Lets users access Docker Desktop without barriers, at the cost of reduced security and insights. | + ## Next steps -- To set up sign-in enforcement, see [Configure sign-in enforcement](/manuals/enterprise/security/enforce-sign-in/methods.md) guide. -- To configure SSO enforcement, see [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md). \ No newline at end of file +- To set up sign-in enforcement, see [Configure sign-in enforcement](/manuals/enterprise/security/enforce-sign-in/methods.md). +- To configure SSO enforcement, see [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md). diff --git a/content/manuals/enterprise/security/enforce-sign-in/methods.md b/content/manuals/enterprise/security/enforce-sign-in/methods.md index 8c8c6e6f41e0..dcbe2ecd7ab1 100644 --- a/content/manuals/enterprise/security/enforce-sign-in/methods.md +++ b/content/manuals/enterprise/security/enforce-sign-in/methods.md @@ -44,7 +44,7 @@ To configure the registry key method manually: - Add each organization on a separate line - Do not use spaces or commas as separators 1. Restart Docker Desktop. -1. Verify the **Sign in required!** prompt appears. +1. Verify the `Sign in required!` prompt appears in Docker Desktop. > [!IMPORTANT] > @@ -154,7 +154,7 @@ Use this alternative method for macOS with Docker Desktop version 4.32 and later ``` 1. Set file permissions to prevent editing by non-administrator users. 1. Restart Docker Desktop. -1. Verify the **Sign in required!** prompt appears. +1. Verify the `Sign in required!` prompt appears in Docker Desktop. {{< /tab >}} {{< tab name="Shell script deployment" >}} @@ -202,14 +202,14 @@ Create the `registry.json` file at the appropriate location: 1. Ensure users are members of your Docker organization. 1. Create the `registry.json` file at the appropriate location for your platform. 1. Add this content, replacing organization names with your own: - ```json - { - "allowedOrgs": ["myorg1", "myorg2"] - } - ``` + ```json + { + "allowedOrgs": ["myorg1", "myorg2"] + } + ``` 1. Set file permissions to prevent user editing. 1. Restart Docker Desktop. -1. Verify the **Sign in required!** prompt appears. +1. Verify the `Sign in required!` prompt appears in Docker Desktop. > [!TIP] > @@ -219,20 +219,20 @@ they may need to update to the latest version. {{< /tab >}} {{< tab name="Command line setup" >}} -#### Windows (PowerShell as Administrator): +#### Windows (PowerShell as Administrator) ```shell Set-Content /ProgramData/DockerDesktop/registry.json '{"allowedOrgs":["myorg1","myorg2"]}' ``` -#### macOS: +#### macOS ```console sudo mkdir -p "/Library/Application Support/com.docker.docker" echo '{"allowedOrgs":["myorg1","myorg2"]}' | sudo tee "/Library/Application Support/com.docker.docker/registry.json" ``` -#### Linux: +#### Linux ```console sudo mkdir -p /usr/share/docker-desktop/registry @@ -244,7 +244,7 @@ echo '{"allowedOrgs":["myorg1","myorg2"]}' | sudo tee /usr/share/docker-desktop/ Create the registry.json file during Docker Desktop installation: -#### Windows: +#### Windows ```shell # PowerShell @@ -254,7 +254,7 @@ Start-Process '.\Docker Desktop Installer.exe' -Wait 'install --allowed-org=myor "Docker Desktop Installer.exe" install --allowed-org=myorg ``` -#### macOS: +#### macOS ```console sudo hdiutil attach Docker.dmg diff --git a/content/manuals/enterprise/security/hardened-desktop/_index.md b/content/manuals/enterprise/security/hardened-desktop/_index.md index 7275ce56bf58..44bba2cac39f 100644 --- a/content/manuals/enterprise/security/hardened-desktop/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/_index.md @@ -37,9 +37,7 @@ Hardened Docker Desktop provides a collection of security features designed to s With Hardened Docker Desktop, you can enforce strict security policies that prevent developers and containers from bypassing organizational controls. You can also enhance container isolation to protect against security threats like malicious payloads that might breach the Docker Desktop Linux VM or underlying host system. -## Key benefits - -Hardened Docker Desktop shifts configuration ownership from individual developers to your organization. This means security controls you establish can't be modified by Docker Desktop users. +## Who should use Hardened Docker Desktop? Hardened Docker Desktop is ideal for security-focused organizations that: @@ -47,9 +45,9 @@ Hardened Docker Desktop is ideal for security-focused organizations that: - Want centralized control over Docker Desktop configurations - Must meet specific compliance requirements -### How Hardened Docker Desktop protects your organization +## How Hardened Docker Desktop works -The Hardened Docker Desktop features work independently and together to create a defense-in-depth security strategy. They protect developer workstations against attacks across multiple layers, including Docker Desktop configuration, container image management, and container runtime security: +Hardened Docker Desktop features work independently and together to create a defense-in-depth security strategy. They protect developer workstations against attacks across multiple layers, including Docker Desktop configuration, container image management, and container runtime security: - Registry Access Management and Image Access Management prevent access to unauthorized container registries and image types, reducing exposure to malicious payloads - Enhanced Container Isolation runs containers without root privileges inside a Linux user namespace, limiting the impact of malicious containers diff --git a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md index 073b474a84a6..50446a347ea0 100644 --- a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md +++ b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md @@ -14,7 +14,9 @@ Air-gapped containers let you restrict container network access by controlling w Docker Desktop can configure container network traffic to accept connections, reject connections, or tunnel through HTTP or SOCKS proxies. You control which TCP ports the policy applies to and whether to use a single proxy or per-destination policies via Proxy Auto-Configuration (PAC) files. -## Use cases for air-gapped containers +This page provides an overview of air-gapped containers and configuration steps. + +## Who should use air-gapped containers? Air-gapped containers help organizations maintain security in restricted environments: @@ -24,14 +26,30 @@ Air-gapped containers help organizations maintain security in restricted environ - Supply chain security: Control which external resources containers can access during builds - Corporate network policies: Enforce existing network security policies for containerized applications +## How air-gapped containers work + +Air-gapped containers operate by intercepting container network traffic and applying proxy rules: + +1. Traffic interception: Docker Desktop intercepts all outgoing network connections from containers +1. Port filtering: Only traffic on specified ports (`transparentPorts`) is subject to proxy rules +1. Rule evaluation: PAC file rules or static proxy settings determine how to handle each connection +1. Connection handling: Traffic is allowed directly, routed through a proxy, or blocked based on the rules + +Some important considerations include: + +- The existing `proxy` setting continues to apply to Docker Desktop application traffic on the host +- If PAC file download fails, containers block requests to target URLs +- URL parameter format is `http://host_or_ip:port` or `https://host_or_ip:port` +- Hostname is available for ports 80 and 443, but only IP addresses for other ports + ## Prerequisites -Before configuring air-gapped containers: +Before configuring air-gapped containers, you must have: -- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) to ensure users authenticate with your organization -- Have a Docker Business subscription -- Configure [Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/_index.md) to manage organization policies -- Download Docker Desktop 4.29 or later +- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) enabled to ensure users authenticate with your organization +- A Docker Business subscription +- Configured [Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/_index.md) to manage organization policies +- Downloaded Docker Desktop 4.29 or later ## Configure air-gapped containers @@ -68,7 +86,7 @@ The `containersProxy` setting controls network policies applied to container tra ### Configuration examples -**Block all external access:** +Block all external access: ```json "containersProxy": { @@ -81,7 +99,7 @@ The `containersProxy` setting controls network policies applied to container tra } ``` -**Allow specific internal services:** +Allow specific internal services: ```json "containersProxy": { @@ -94,7 +112,7 @@ The `containersProxy` setting controls network policies applied to container tra } ``` -**Route through corporate proxy:** +Route through corporate proxy: ```json "containersProxy": { @@ -166,22 +184,6 @@ function FindProxyForURL(url, host) { } ``` -## How air-gapped containers work - -Air-gapped containers operate by intercepting container network traffic and applying proxy rules: - -1. Traffic interception: Docker Desktop intercepts all outgoing network connections from containers -1. Port filtering: Only traffic on specified ports (`transparentPorts`) is subject to proxy rules -1. Rule evaluation: PAC file rules or static proxy settings determine how to handle each connection -1. Connection handling: Traffic is allowed directly, routed through a proxy, or blocked based on the rules - -Some important considerations include: - -- The existing `proxy` setting continues to apply to Docker Desktop application traffic on the host -- If PAC file download fails, containers block requests to target URLs -- URL parameter format is `http://host_or_ip:port` or `https://host_or_ip:port` -- Hostname is available for ports 80 and 443, but only IP addresses for other ports - ## Verify air-gapped container configuration After applying the configuration, test that container network restrictions work: diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md index 3d837ad0d8d1..b10c3aabfa9b 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/_index.md @@ -34,14 +34,14 @@ Enhanced Container Isolation is designed for: Docker implements ECI using the [Sysbox container runtime](https://github.com/nestybox/sysbox), a security-enhanced fork of the standard OCI runc runtime. When ECI is turned on, containers created through `docker run` or `docker create` automatically use Sysbox instead of runc without requiring any changes to developer workflows. +Even containers using the `--privileged` flag run securely with Enhanced Container Isolation, preventing them from breaching the Docker Desktop virtual machine or other containers. + > [!NOTE] > > When ECI is turned on, the Docker CLI `--runtime` flag is ignored. -Docker's default runtime remains `runc`, but all user containers +Docker's default runtime remains runc, but all user containers implicitly launch with Sysbox. -Even containers using the `--privileged` flag run securely with Enhanced Container Isolation, preventing them from breaching the Docker Desktop virtual machine or other containers. - ## Key security features ### Linux user namespace isolation @@ -139,7 +139,7 @@ Docker build operations using `--network-host` and Docker buildx entitlements (` Enhanced Container Isolation maintains support for standard file sharing while preventing access to sensitive VM directories: -**Host directory mounts continue to work:** +Host directory mounts continue to work: ```console $ docker run -it --rm -v $HOME:/mnt alpine @@ -147,7 +147,7 @@ $ docker run -it --rm -v $HOME:/mnt alpine # Successfully lists home directory contents ``` -**VM configuration mounts are blocked:** +VM configuration mounts are blocked: ```console $ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine @@ -210,7 +210,7 @@ Several `/proc/sys` resources that aren't namespaced by the Linux kernel are emu ## Performance and compatibility -Enhanced Container Isolation maintains excellent performance and full compatibility: +Enhanced Container Isolation maintains optimized performance and full compatibility: - No performance impact: System call filtering targets only control-path calls, leaving data-path operations unaffected - Full workflow compatibility: Existing development processes, tools, and container images work unchanged diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md index 15f476b457e3..60e928268460 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md @@ -1,6 +1,6 @@ --- title: Configure Docker socket exceptions and advanced settings -linkTitle: Configure Docker socket exceptions +linkTitle: Configure advanced settings description: Configure Docker socket exceptions and advanced settings for Enhanced Container Isolation keywords: enhanced container isolation, docker socket, configuration, testcontainers, admin settings aliases: @@ -15,7 +15,7 @@ This page shows you how to configure Docker socket exceptions and other advanced ## Docker socket mount permissions -By default, Enhanced Container Isolation blocks containers from mounting the Docker socket to prevent malicious access to Docker Engine. However, some legitimate tools require Docker socket access. +By default, Enhanced Container Isolation blocks containers from mounting the Docker socket to prevent malicious access to Docker Engine. However, some tools require Docker socket access. Common scenarios requiring Docker socket access include: @@ -24,7 +24,6 @@ Common scenarios requiring Docker socket access include: - CI/CD tools: Tools that manage containers as part of deployment pipelines - Development utilities: Docker CLI containers for container management - ## Configure socket exceptions Configure Docker socket exceptions using Settings Management: @@ -44,8 +43,8 @@ command restrictions. Create an [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) and add: - ```json - { +```json +{ "configurationFileVersion": 2, "enhancedContainerIsolation": { "locked": true, @@ -65,8 +64,8 @@ Create an [`admin-settings.json` file](/manuals/enterprise/security/hardened-des } } } - } - ``` +} +``` {{< /tab >}} {{< /tabs >}} @@ -84,7 +83,7 @@ The `imageList` defines which container images can mount the Docker socket. ### Example configurations -**Basic allowlist for testing tools:** +Basic allowlist for testing tools: ```json "imageList": { @@ -96,7 +95,7 @@ The `imageList` defines which container images can mount the Docker socket. } ``` -**Wildcard allowlist (Docker Desktop 4.36 and later):** +Wildcard allowlist (Docker Desktop 4.36 and later): ```json "imageList": { @@ -177,12 +176,12 @@ Only allows specified commands while blocking all others: | Wildcard | Blocks/allows | | :---------------- | :---------- | -| "container\*" | All "docker container ..." commands | -| "image\*" | All "docker image ..." commands | -| "volume\*" | All "docker volume ..." commands | -| "network\*" | All "docker network ..." commands | -| "build\*" | All "docker build ..." commands | -| "system\*" | All "docker system ..." commands | +| `"container\*"` | All "docker container ..." commands | +| `"image\*"` | All "docker image ..." commands | +| `"volume\*"` | All "docker volume ..." commands | +| `"network\*"` | All "docker network ..." commands | +| `"build\*"` | All "docker build ..." commands | +| `"system\*"` | All "docker system ..." commands | ### Command blocking example @@ -271,11 +270,10 @@ For local development with Docker-in-Docker: - Regular validation: Test your configuration after Docker Desktop updates, as image digests may change. - Handle digest mismatches: If allowed images are unexpectedly blocked: - -```console -$ docker image rm -$ docker pull -``` + ```console + $ docker image rm + $ docker pull + ``` This resolves digest mismatches when upstream images are updated. diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md index 36b8a50c041a..ab151e971bc6 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/enable-eci.md @@ -1,5 +1,6 @@ --- title: Enable Enhanced Container Isolation +linkTitle: Enable ECI description: Enable Enhanced Container Isolation to secure containers in Docker Desktop keywords: enhanced container isolation, enable eci, container security, docker desktop setup weight: 15 @@ -7,7 +8,9 @@ weight: 15 {{< summary-bar feature_name="Hardened Docker Desktop" >}} -This page shows you how to turn on Enhanced Container Isolation (ECI) and verify it's working correctly. ECI prevents malicious containers from compromising Docker Desktop while maintaining full developer productivity. +ECI prevents malicious containers from compromising Docker Desktop while maintaining full developer productivity. + +This page shows you how to turn on Enhanced Container Isolation (ECI) and verify it's working correctly. ## Prerequisites @@ -15,7 +18,7 @@ Before you begin, you must have: - A Docker Business subscription - Docker Desktop 4.13 or later -- Enforced sign-in (for administrators managing organization-wide settings only) +- [Enforced sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) (for administrators managing organization-wide settings only) ## Enable Enhanced Container Isolation @@ -23,13 +26,13 @@ Before you begin, you must have: Turn on ECI in your Docker Desktop settings: -1. Sign in to your organizationin Docker Desktop. Your organization must have +1. Sign in to your organization in Docker Desktop. Your organization must have a Docker Business subscription. 1. Stop and remove all existing containers: ```console - docker stop $(docker ps -q) - docker rm $(docker ps -aq) + $ docker stop $(docker ps -q) + $ docker rm $(docker ps -aq) ``` 1. In Docker Desktop, go to **Settings** > **General**. @@ -57,15 +60,15 @@ Configure Enhanced Container Isolation organization-wide using Settings Manageme 1. Create an [`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md) and add: - ```json - { - "configurationFileVersion": 2, - "enhancedContainerIsolation": { - "value": true, - "locked": true - } - } - ``` + ```json + { + "configurationFileVersion": 2, + "enhancedContainerIsolation": { + "value": true, + "locked": true + } + } + ``` 1. Configure the following as needed: - `"value": true`: Turns on ECI by default (required) @@ -100,7 +103,7 @@ Run a container and examine the user namespace mapping: $ docker run --rm alpine cat /proc/self/uid_map ``` -**With ECI turned on:** +With ECI turned on: ```text 0 100000 65536 @@ -108,7 +111,7 @@ $ docker run --rm alpine cat /proc/self/uid_map This shows the container's root user (0) maps to an unprivileged user (100000) in the Docker Desktop VM, with a range of 64K user IDs. Each container gets an exclusive user ID range for isolation. -**With ECI turned off:** +With ECI turned off: ```text 0 0 4294967295 @@ -131,7 +134,7 @@ With ECI turned on, it turns `sysbox-runc`. With ECI turned off, it returns Verify that ECI security restrictions are active. -**Test namespace sharing:** +Test namespace sharing: ```console $ docker run -it --rm --pid=host alpine @@ -140,7 +143,7 @@ $ docker run -it --rm --pid=host alpine With ECI turned on, this command fails with an error about Sysbox containers not being able to share namespaces with the host. -**Test Docker socket access:** +Test Docker socket access: ```console $ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock alpine @@ -163,4 +166,4 @@ Docker Desktop settings. ## Next steps - Review [Configure Docker socket exceptions and advanced settings](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md). -- Review [Enhanced Container Isolation limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). \ No newline at end of file +- Review [Enhanced Container Isolation limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). diff --git a/content/manuals/enterprise/security/hardened-desktop/image-access-management.md b/content/manuals/enterprise/security/hardened-desktop/image-access-management.md index 48a0c3cfc346..66e4b5fc6a7d 100644 --- a/content/manuals/enterprise/security/hardened-desktop/image-access-management.md +++ b/content/manuals/enterprise/security/hardened-desktop/image-access-management.md @@ -23,7 +23,7 @@ With Image Access Management, you can restrict access to: - Organization images: Your organization's private repositories - Community images: Public images from individual developers -## Why use Image Access Management? +## Who should use Image Access Management? Image Access Management helps prevent supply chain attacks by ensuring developers only use trusted container images. For example, a developer building a new application might accidentally use a malicious community image as a component. Image Access Management prevents this by restricting access to only approved image types. @@ -54,10 +54,10 @@ To configure Image Access Management: 1. Select **Admin Console**, then **Image access**. 1. Use the **toggle** to enable image access. 1. Select which image types to allow: - - Organization images: Images from your organization (always allowed by default). These can be public or private images created by members within your organization. - - Community images: Images contributed by various users that may pose security risks. This category includes Docker-Sponsored Open Source images and is turned off by default. - - Docker Verified Publisher Images: Images from Docker partners in the Verified Publisher program, qualified for secure supply chains. - - Docker Official Images: Curated Docker repositories that provide OS repositories, best practices for Dockerfiles, drop-in solutions, and timely security updates. + - **Organization images**: Images from your organization (always allowed by default). These can be public or private images created by members within your organization. + - **Community images**: Images contributed by various users that may pose security risks. This category includes Docker-Sponsored Open Source images and is turned off by default. + - **Docker Verified Publisher Images**: Images from Docker partners in the Verified Publisher program, qualified for secure supply chains. + - **Docker Official Images**: Curated Docker repositories that provide OS repositories, best practices for Dockerfiles, drop-in solutions, and timely security updates. Once restrictions are applied, organization members can view the permissions page in read-only format. diff --git a/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md b/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md index ec4c53e96900..fa775f4a7fc3 100644 --- a/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md +++ b/content/manuals/enterprise/security/hardened-desktop/registry-access-management.md @@ -49,8 +49,8 @@ To configure registry permissions: 1. Use the **toggle** to enable registry access. By default, Docker Hub is enabled in the registry list. 1. To add additional registries, select **Add registry** and provide -a **Registry address** and **Registry nickname**. Select **Create**. You can add -up to 100 registries. +a **Registry address** and **Registry nickname**. +1. Select **Create**. You can add up to 100 registries. 1. Verify your registry appears in the registry list and select **Save changes**. Changes can take up to 24 hours to take effect. To apply them sooner, @@ -63,7 +63,7 @@ have developers sign out and back in to Docker Desktop. > [!TIP] > > RAM restrictions also apply to Dockerfile `ADD` instructions that fetch content via URL. Include trusted registry domains in your allowlist when using `ADD` with URLs. -> +>

> RAM is designed for container registries, not general-purpose URLs like package mirrors or storage services. Adding too many domains may cause errors or hit system limits. diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md index dfd20819db67..14b65497261b 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md @@ -14,7 +14,7 @@ weight: 10 Settings Management lets administrators configure and enforce Docker Desktop settings across end-user machines. It helps maintain consistent configurations and enhances security within your organization. -## Who is Settings Management for? +## Who should use Settings Management? Settings Management is designed for organizations that: @@ -22,8 +22,6 @@ Settings Management is designed for organizations that: - Want to standardize Docker Desktop environments across teams - Operate in regulated environments and must enforce compliance policies -This feature is available with a Docker Business subscription. - ## How Settings Management works Administrators can define settings using one of these methods: @@ -85,6 +83,13 @@ When settings are enforced: This ensures consistent environments while maintaining a clear visual indication of which settings are managed by administrators. +## Limitations + +Settings Management has the following limitations: + +- Doesn't work in air-gapped or offline environments +- Not compatible with environments that restrict authentication with Docker Hub + ## Next steps Get started with Settings Management: @@ -92,7 +97,3 @@ Get started with Settings Management: - [Configure Settings Management with the `admin-settings.json` file](configure-json-file.md) - [Configure Settings Management with the Docker Admin Console](configure-admin-console.md) -## More resources - -- To see how each Docker Desktop setting maps across the Docker Dashboard, `admin-settings.json` file, and Admin Console, see the [Settings reference](settings-reference.md). -- Read the [Settings Management blog post](https://www.docker.com/blog/settings-management-for-docker-desktop-now-generally-available-in-the-admin-console/). diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md index 976881b741a9..eb0d255100bb 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/compliance-reporting.md @@ -16,9 +16,9 @@ Desktop settings reporting tracks user compliance with Docker Desktop settings p Before you can use Docker Desktop settings reporting, make sure you have: -- Docker Desktop 4.37.1 or later installed across your organization -- A verified domain -- Enforced sign-in for your organization +- [Docker Desktop 4.37.1 or later](/manuals/desktop/release-notes.md) installed across your organization +- [A verified domain](/manuals/enterprise/security/single-sign-on/configure.md#step-one-add-and-verify-your-domain) +- [Enforced sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md) for your organization - A Docker Business subscription - At least one settings policy configured @@ -42,7 +42,7 @@ The reporting dashboard provides these tools: - Compliance status indicators - CSV export option to download compliance data -## Understanding compliance status +## User compliance statuses Docker Desktop evaluates three types of status to determine overall compliance: @@ -92,7 +92,7 @@ When you select a user's name, you'll see their detailed compliance information ## Resolve compliance issues -Follow these steps based on the user's compliance status: +You can select a non-compliant user's name in the dashboard for recommended status resolution steps. The following sections are general resolution steps for non-compliant statuses: ### Non-compliant or outdated users diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md index 8bac7d3d21c1..53095c84b5ac 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md @@ -28,13 +28,6 @@ Docker Desktop only applies settings from the `admin-settings.json` file when bo > > Users must be signed in and part of a Docker Business organization. If either condition isn't met, the settings file is ignored. -## Limitation - -Settings Management has the following limitations: - -- Doesn't work in air-gapped or offline environments -- Not compatible with environments that restrict authentication with Docker Hub - ## Step one: Create the settings file You can create the `admin-settings.json` file in two ways: @@ -71,7 +64,7 @@ a user has already customized that value in `settings-store.json`, ### Example configuration -The folloiwng sample is an `admin-settings.json` file with common enterprise settings configured: +The following sample is an `admin-settings.json` file with common enterprise settings configured. You can use this example as a template with the [`admin-settings.json` configurations](#admin-settingsjson-configurations): ```json {collapse=true} { diff --git a/content/manuals/enterprise/security/images/enforce-sign-in.png b/content/manuals/enterprise/security/images/enforce-sign-in.png deleted file mode 100644 index e60e12f39f485341e552edec7fdc82a079ed8a0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140986 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 diff --git a/content/manuals/enterprise/security/provisioning/_index.md b/content/manuals/enterprise/security/provisioning/_index.md index 4704e517d76c..fb5f329b931a 100644 --- a/content/manuals/enterprise/security/provisioning/_index.md +++ b/content/manuals/enterprise/security/provisioning/_index.md @@ -47,20 +47,17 @@ JIT provisioning may not provide sufficient control or security for some organiz When a user signs in through SSO, Docker obtains several attributes from your IdP to manage the user's identity and permissions. These attributes include: -- Email address: The unique identifier for the user. -- Full name: The user's complete name. -- Groups: Optional. Used for group-based access control. -- Docker Org: Optional. Specifies the organization the user belongs to. -- Docker Team: Optional. Defines the team the user belongs to within the organization. +- Email address: The unique identifier for the user +- Full name: The user's complete name +- Groups: Optional. Used for group-based access control +- Docker Org: Optional. Specifies the organization the user belongs to +- Docker Team: Optional. Defines the team the user belongs to within the organization - Docker Role: Optional. Determines the user's permissions within Docker -- Docker session minutes: Optional. Sets the session duration before users must re-authenticate with their IdP. Must be a positive integer greater than 0. If not provided, default session timeouts apply. +- Docker session minutes: Optional. Sets the session duration before users must re-authenticate with their IdP. Must be a positive integer greater than 0. If not provided, default session timeouts apply > [!NOTE] > -> Default session timeouts when Docker session minutes is not specified are -as follows: -> - Docker Desktop: 90 days, or 30 days of inactivity -> - Docker Hub and Docker Home: 24 hours +> Default session timeouts apply when Docker session minutes is not specified. Docker Desktop sessions expire after 90 days or 30 days of inactivity. Docker Hub and Docker Home sessions expire after 24 hours. ## SAML attribute mapping diff --git a/content/manuals/enterprise/security/provisioning/group-mapping.md b/content/manuals/enterprise/security/provisioning/group-mapping.md index 222fa079c173..4e47b0d617e0 100644 --- a/content/manuals/enterprise/security/provisioning/group-mapping.md +++ b/content/manuals/enterprise/security/provisioning/group-mapping.md @@ -15,14 +15,18 @@ weight: 30 Group mapping automatically synchronizes user groups from your identity provider (IdP) with teams in your Docker organization. For example, when you add a developer to the "backend-team" group in your IdP, they're automatically added to the corresponding team in Docker +This page explains how group mapping works, and how to set up group mapping. + > [!TIP] > -> Group mapping is ideal for adding users to multiple organizations or multiple teams within one organization. If you don't need to set up multi-organization or multi-team assignment, you can use SCIM [user-level attributes](scim.md#set-up-role-mapping). +> Group mapping is ideal for adding users to multiple organizations or multiple teams within one organization. If you don't need to set up multi-organization or multi-team assignment, SCIM [user-level attributes](scim.md#set-up-role-mapping) may be a better fit for your needs. ## Prerequisites -- SSO is configured for your organization -- You have administrator access to Docker Home and your identity provider +Before you being, you must have: + +- SSO configured for your organization +- Administrator access to Docker Home and your identity provider ## How group mapping works @@ -50,7 +54,7 @@ user lifecycle management. Create groups in your IdP using the format: `organization:team`. -Examples: +For example: - For the "developers" team in the "moby" organization: `mobdy:developers` - For multi-organization access: `moby:backend` and `whale:desktop` @@ -61,10 +65,10 @@ Docker creates teams automatically if they don't already exist when groups sync. | Attribute | Description | |:--------- | :---------- | -| id | Unique ID of the group in UUID format. This attribute is read-only. | -| displayName | Name of the group following the group mapping format: `organization:team`. | -| members | A list of users that are members of this group. | -| members(x).value | Unique ID of the user that is a member of this group. Members are referenced by ID. | +| `id` | Unique ID of the group in UUID format. This attribute is read-only. | +| `displayName` | Name of the group following the group mapping format: `organization:team`. | +| `members` | A list of users that are members of this group. | +| `members(x).value` | Unique ID of the user that is a member of this group. Members are referenced by ID. | ## Configure group mapping with SSO diff --git a/content/manuals/enterprise/security/provisioning/just-in-time.md b/content/manuals/enterprise/security/provisioning/just-in-time.md index 00a3bc55e114..db2eb79e8ca7 100644 --- a/content/manuals/enterprise/security/provisioning/just-in-time.md +++ b/content/manuals/enterprise/security/provisioning/just-in-time.md @@ -10,16 +10,20 @@ aliases: {{< summary-bar feature_name="SSO" >}} -Just-in-Time (JIT) provisioning streamlines user onboarding by automatically creating and updating user accounts during SSO authentication. This eliminates manual account creation and ensures users have immediate access to your organization's resources. JIT verifies that users belong to the organization and assigns them to the appropriate teams based on your identity provider (IdP) configuration. When you [create your SSO connection](../single-sign-on/_index.md), JIT provisioning is turned on by default. +Just-in-Time (JIT) provisioning streamlines user onboarding by automatically creating and updating user accounts during SSO authentication. This eliminates manual account creation and ensures users have immediate access to your organization's resources. JIT verifies that users belong to the organization and assigns them to the appropriate teams based on your identity provider (IdP) configuration. When you create your SSO connection, JIT provisioning is turned on by default. + +This page explains how JIT provisioning works, SSO authentication flows, and how to disable JIT provisioning. ## Prerequisites -- SSO is configured for your organization -- You have administrator access to Docker Home and your identity provider +Before you beging, you must have: + +- SSO configured for your organization +- Administrator access to Docker Home and your identity provider ## SSO authentication with JIT provisioning enabled -When a user signs in with SSO and your SSO configuration has JIT provisioning enabled, the following steps occur automatically: +When a user signs in with SSO and you have JIT provisioning enabled, the following steps occur automatically: 1. The system checks if a Docker account exists for the user's email address. @@ -42,7 +46,7 @@ The following graphic provides an overview of SSO authentication with JIT enable ## SSO authentication with JIT provisioning disabled -When JIT provisioning is disabled in your SSO connection, the following actions occur during authentication: +When JIT provisioning is disabled, the following actions occur during SSO authentication: 1. The system checks if a Docker account exists for the user's email address. @@ -73,13 +77,13 @@ You may want to disable JIT provisioning for reasons such as the following: Users are provisioned with JIT by default. If you enable SCIM, you can disable JIT: -1. In [Docker Home](https://app.docker.com/), select your organization. +1. Go to [Docker Home](https://app.docker.com/) and select your organization. 1. Select **Admin Console**, then **SSO and SCIM**. 1. In the **SSO connections** table, select the **Action** icon, then select **Disable JIT provisioning**. 1. Select **Disable** to confirm. ## Next steps -- Configure [SCIM provisioning](/manuals/enterprise/security/provisioning/scim.md) for advanced user management -- Set up [group mapping](/manuals/enterprise/security/provisioning/group-mapping.md) to automatically assign users to teams -- Review [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md) +- Configure [SCIM provisioning](/manuals/enterprise/security/provisioning/scim.md) for advanced user management. +- Set up [group mapping](/manuals/enterprise/security/provisioning/group-mapping.md) to automatically assign users to teams. +- Review [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md). diff --git a/content/manuals/enterprise/security/provisioning/scim.md b/content/manuals/enterprise/security/provisioning/scim.md index 1662b310c4f4..f60d81c232f8 100644 --- a/content/manuals/enterprise/security/provisioning/scim.md +++ b/content/manuals/enterprise/security/provisioning/scim.md @@ -12,12 +12,16 @@ weight: 20 {{< summary-bar feature_name="SSO" >}} -This page shows you how to automate user provisioning and de-provisioning for Docker using System for Cross-domain Identity Management (SCIM). +Automate user management for your Docker organization using System for Cross-domain Identity Management (SCIM). SCIM automatically provisions and de-provisions users, synchronizes team memberships, and keeps your Docker organization in sync with your identity provider. + +This page shows you how to automate user provisioning and de-provisioning for Docker using SCIM. ## Prerequisites -- SSO is configured for your organization -- You have administrator access to Docker Home and your identity provider +Before you begin, you must have: + +- SSO configured for your organization +- Administrator access to Docker Home and your identity provider ## How SCIM works @@ -42,7 +46,7 @@ SCIM automates: > [!NOTE] > > SCIM only manages users provisioned through your identity provider after SCIM is enabled. It cannot remove users who were manually added to your Docker organization before SCIM was set up. -> +>

> To remove those users, delete them manually from your Docker organization. For more information, see [Manage organization members](/manuals/admin/organization/members.md). @@ -56,10 +60,10 @@ Docker supports the following SCIM attributes: | Attribute | Description | |:---------------------------------------------------------------|:-------------------------------------------------------------------------------------------| -| userName | User’s primary email address, used as the unique identifier | -| name.givenName | User’s first name | -| name.familyName | User’s surname | -| active | Indicates if a user is enabled or disabled, set to “false” to de-provision a user | +| `userName` | User’s primary email address, used as the unique identifier | +| `name.givenName` | User’s first name | +| `name.familyName` | User’s surname | +| `active` | Indicates if a user is enabled or disabled, set to “false” to de-provision a user | For additional details about supported attributes and SCIM, see [Docker Hub API SCIM reference](/reference/api/hub/latest/#tag/scim). @@ -69,7 +73,7 @@ For additional details about supported attributes and SCIM, see [Docker Hub API enabled, JIT values still take precedence and will overwrite attribute values set by SCIM. To avoid conflicts, make sure your JIT attribute values match your SCIM values. -> +>

> Alternatively, you can disable JIT provisioning to rely solely on SCIM. For details, see [Just-in-Time](just-in-time.md). @@ -127,6 +131,8 @@ officially document this setup, it is widely used and supported in practice. - Family name - Email +Next, [set up role mapping](#set-up-role-mapping). + {{< /tab >}} {{< tab name="Entra ID (OIDC)" >}} @@ -377,4 +383,5 @@ To disable SCIM: ## Next steps -- [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md) +- Set up [Group mapping](/manuals/enterprise/security/provisioning/group-mapping.md). +- [Troubleshoot provisioning](/manuals/enterprise/troubleshoot/troubleshoot-provisioning.md). diff --git a/content/manuals/enterprise/security/roles-and-permissions.md b/content/manuals/enterprise/security/roles-and-permissions.md index d64f61681deb..7a7fa6c10dc6 100644 --- a/content/manuals/enterprise/security/roles-and-permissions.md +++ b/content/manuals/enterprise/security/roles-and-permissions.md @@ -12,6 +12,8 @@ weight: 40 Roles control what users can do in your organization. When you invite users, you assign them a role that determines their permissions for repositories, teams, and organization settings. +This page provides an overview of Docker roles and permissions for each role. + ## Organization roles Docker organizations have three main roles: @@ -48,14 +50,11 @@ These permissions apply organization-wide, including all repositories in your or | Assign team permissions to repositories | ❌ | ✅ | ✅ | When you add members to teams, you can grant additional repository permissions -beyond their organization role. The following diagram shows how permissions -work: +beyond their organization role: 1. Role permissions: Applied organization-wide (member or editor) 2. Team permissions: Additional permissions for specific repositories -![User repository permissions within an organization](../images/roles-and-permissions-member-editor-roles.png) - ### Organization management permissions | Permission | Member | Editor | Owner | diff --git a/content/manuals/enterprise/security/single-sign-on/_index.md b/content/manuals/enterprise/security/single-sign-on/_index.md index 9e2772969d69..d918a69e8926 100644 --- a/content/manuals/enterprise/security/single-sign-on/_index.md +++ b/content/manuals/enterprise/security/single-sign-on/_index.md @@ -16,8 +16,7 @@ weight: 10 Single sign-on (SSO) lets users access Docker by authenticating through their identity providers (IdPs). SSO can be configured for an entire company, including all associated organizations, or for a single organization that has a -Docker Business subscription. To upgrade, see -[Upgrade your subscription](/manuals/subscription/change.md). +Docker Business subscription. ## How SSO works @@ -65,8 +64,8 @@ users accessing Docker through the CLI must [create a personal access token (PAT Using a PAT ensures continued CLI access. For more information, see the [security announcement](/manuals/security/security-announcements.md#deprecation-of-password-logins-on-cli-when-sso-enforced). -## What's next? +## Next steps -- Start [configuring SSO](configure.md) -- Read the FAQs [FAQs](/manuals/security/faqs/_index.md) -- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues +- Start [configuring SSO](configure.md). +- Read the FAQs [FAQs](/manuals/security/faqs/_index.md). +- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues. diff --git a/content/manuals/enterprise/security/single-sign-on/configure.md b/content/manuals/enterprise/security/single-sign-on/configure.md index 6dfa9cf9f311..cda92ecd6473 100644 --- a/content/manuals/enterprise/security/single-sign-on/configure.md +++ b/content/manuals/enterprise/security/single-sign-on/configure.md @@ -25,6 +25,8 @@ and verifying the domains your members use to sign in. > Docker supports multiple identity provider (IdP) configurations. You can associate one domain with more than one IdP. +To add a domain: + 1. Sign in to [Docker Home](https://app.docker.com) and choose your organization. If it's part of a company, select the company first to manage the domain at that level. @@ -41,28 +43,27 @@ host using the TXT Record Value from Docker. DNS propagation can take up to > [!TIP] > -> Use these guidelines when adding a record name: -> -> - Use `@` or leave the record name empty for root domains like `example.com`. -> - Avoid values like `docker`, `docker-verification`, `www`, or your domain name itself. -> - Check your DNS provider's documentation to verify record name requirements. +> When adding a record name, **use `@` or leave it empty** for root domains like `example.com`. **Avoid common values** like `docker`, `docker-verification`, `www`, or your domain name itself. Always **check your DNS provider's documentation** to verify their specific record name requirements. {{< tabs >}} {{< tab name="AWS Route 53" >}} 1. To add your TXT record to AWS, see [Creating records by using the Amazon Route 53 console](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html). +1. Wait up to 72 hours for TXT record verification. 1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< tab name="Google Cloud DNS" >}} 1. To add your TXT record to Google Cloud DNS, see [Verifying your domain with a TXT record](https://cloud.google.com/identity/docs/verify-domain-txt). +1. Wait up to 72 hours for TXT record verification. 1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} {{< tab name="GoDaddy" >}} 1. To add your TXT record to GoDaddy, see [Add a TXT record](https://www.godaddy.com/help/add-a-txt-record-19232). +1. Wait up to 72 hours for TXT record verification. 1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} @@ -70,6 +71,7 @@ host using the TXT Record Value from Docker. DNS propagation can take up to 1. Sign in to your domain host. 1. Add a TXT record to your DNS settings and save the record. +1. Wait up to 72 hours for TXT record verification. 1. After the record is live, go to **Domain management** in the [Admin Console](https://app.docker.com/admin) and select **Verify**. {{< /tab >}} @@ -77,5 +79,5 @@ host using the TXT Record Value from Docker. DNS propagation can take up to ## Next steps -- [Connect Docker and your IdP](connect.md) -- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues +- [Connect Docker and your IdP](connect.md). +- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues. diff --git a/content/manuals/enterprise/security/single-sign-on/connect.md b/content/manuals/enterprise/security/single-sign-on/connect.md index 9bb91701ad6a..c380676d58d8 100644 --- a/content/manuals/enterprise/security/single-sign-on/connect.md +++ b/content/manuals/enterprise/security/single-sign-on/connect.md @@ -10,7 +10,7 @@ aliases: {{< summary-bar feature_name="SSO" >}} Setting up a single sign-on (SSO) connection involves configuring both Docker -and your identity provider (IdP). This guide walks you through each step: setup +and your identity provider (IdP). This guide walks you through setup in Docker, setup in your IdP, and final connection. > [!TIP] @@ -28,9 +28,9 @@ Before you begin: ## Step one: Create an SSO connection in Docker ->[!NOTE] +> [!NOTE] > -> You must verify at least one domain before creating an SSO connection. +> You must [verify at least one domain](/manuals/enterprise/security/single-sign-on/configure.md) before creating an SSO connection. 1. Sign in to [Docker Home](https://app.docker.com) and choose your organization. @@ -172,7 +172,7 @@ If you're using the CLI, you must authenticate using a personal access token. Docker supports multiple IdP configurations. To use multiple IdPs with one domain: -- Repeat Steps 1-4 for each IdP. +- Repeat Steps 1-4 on this page for each IdP. - Each connection must use the same domain. - Users will select **Continue with SSO** to choose their IdP at sign in. @@ -185,7 +185,7 @@ Docker supports multiple IdP configurations. To use multiple IdPs with one domai Enforcing SSO requires users to use SSO when signing into Docker. This centralizes authentication and enforces policies set by the IdP. 1. Sign in to [Docker Home](https://app.docker.com/) and select -your organization. Note that when an organization is part of a company, you must select the company and configure the domain for the organization at the company level. +your organization or company. 1. Select **Admin Console**, then **SSO and SCIM**. 1. In the SSO connections table, select the **Action** menu, then **Enable enforcement**. 1. Follow the on-screen instructions. @@ -197,7 +197,7 @@ Docker Hub. If you want to use 2FA, you must enable 2FA through your IdP. ## Next steps -- [Provision users](/manuals/enterprise/security/provisioning/_index.md) -- [Enforce sign-in](../enforce-sign-in/_index.md) -- [Create access tokens](/manuals/enterprise/security/access-tokens.md) -- [Troubleshoot](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) SSO issues +- [Provision users](/manuals/enterprise/security/provisioning/_index.md). +- [Enforce sign-in](../enforce-sign-in/_index.md). +- [Create personal access tokens](/manuals/enterprise/security/access-tokens.md). +- [Troubleshoot SSO](/manuals/enterprise/troubleshoot/troubleshoot-sso.md) issues. diff --git a/content/manuals/enterprise/security/single-sign-on/manage.md b/content/manuals/enterprise/security/single-sign-on/manage.md index 71433516362a..f2f3b46a1f6f 100644 --- a/content/manuals/enterprise/security/single-sign-on/manage.md +++ b/content/manuals/enterprise/security/single-sign-on/manage.md @@ -12,25 +12,9 @@ aliases: {{< summary-bar feature_name="SSO" >}} This page covers how to manage single sign-on (SSO) after initial setup, -including managing organizations, domains, connections, users, and provisioning +including managing domains, connections, users, and provisioning settings. -## Manage organizations - -> [!NOTE] -> -> You must have a [company](/admin/company/) to manage more than one organization. - -To manage SSO for organizations in your company: - -1. Sign in to [Docker Home](https://app.docker.com) and select your company. -1. Select **Admin Console**, then **SSO and SCIM**. -1. In the **Organizations** section, you can: - - - View all organizations in your company - - Turn SSO on or off for each organization - - Configure organization-specific SSO settings - ## Manage domains ### Add a domain diff --git a/content/manuals/scout/explore/metrics-exporter.md b/content/manuals/scout/explore/metrics-exporter.md index 5a4222e6ad31..f78b195ec7a1 100644 --- a/content/manuals/scout/explore/metrics-exporter.md +++ b/content/manuals/scout/explore/metrics-exporter.md @@ -40,7 +40,7 @@ To export metrics from your organization, first make sure your organization is e Then, create a Personal Access Token (PAT) - a secret token that allows the exporter to authenticate with the Docker Scout API. The PAT does not require any specific permissions, but it must be created by a user who is an owner of the Docker organization. -To create a PAT, follow the steps in [Create an access token](/security/access-tokens/#create-an-access-token). +To create a PAT, follow the steps in [Create an access token](/manuals/security/access-tokens.md). Once you have created the PAT, store it in a secure location. You will need to provide this token to the exporter when scraping metrics. @@ -108,7 +108,7 @@ alongside Grafana with a pre-configured dashboard to visualize the vulnerability $ cd scout-metrics-exporter/prometheus ``` -2. [Create a Docker access token](/security/access-tokens/#create-an-access-token) +2. [Create a Docker access token](/manuals/security/access-tokens.md) and store it in a plain text file at `/prometheus/prometheus/token` under the template directory. ```plaintext {title=token} @@ -241,7 +241,7 @@ and a Datadog site. $ cd scout-metrics-exporter/datadog ``` -2. [Create a Docker access token](/security/access-tokens/#create-an-access-token) +2. [Create a Docker access token](/manuals/security/access-tokens.md) and store it in a plain text file at `/datadog/token` under the template directory. ```plaintext {title=token} @@ -347,7 +347,7 @@ To change the scrape interval: ## Revoke an access token If you suspect that your PAT has been compromised or is no longer needed, you can revoke it at any time. -To revoke a PAT, follow the steps in the [Create and manage access tokens](/security/access-tokens/#modify-existing-tokens). +To revoke a PAT, follow the steps in the [Create and manage access tokens](/manuals/security/access-tokens.md). Revoking a PAT immediately invalidates the token, and prevents Prometheus from scraping metrics using that token. You will need to create a new PAT and update the Prometheus configuration to use the new token. diff --git a/content/manuals/security/2fa/_index.md b/content/manuals/security/2fa/_index.md index 158786274b2a..cd6c9806f0d4 100644 --- a/content/manuals/security/2fa/_index.md +++ b/content/manuals/security/2fa/_index.md @@ -3,6 +3,7 @@ title: Enable two-factor authentication for your Docker account linkTitle: Two-factor authentication description: Enable or disable two-factor authentication on your Docker account for enhanced security and account protection keywords: two-factor authentication, 2FA, docker hub security, account security, TOTP, authenticator app, disable 2FA +weight: 20 aliases: - /docker-hub/2fa/ - /security/for-developers/2fa/ diff --git a/content/manuals/security/access-tokens.md b/content/manuals/security/access-tokens.md index 2d78da8c2a71..380b93383dd6 100644 --- a/content/manuals/security/access-tokens.md +++ b/content/manuals/security/access-tokens.md @@ -3,6 +3,7 @@ title: Personal access tokens linkTitle: Personal access tokens description: Create and manage personal Docker access tokens for secure CLI authentication and automation keywords: personal access tokens, PAT, docker cli authentication, docker hub security, programmatic access +weight: 10 aliases: - /docker-hub/access-tokens/ - /security/for-developers/access-tokens/ @@ -19,7 +20,7 @@ PATs offer significant security advantages over password authentication: - Two-factor authentication compatibility: Required when you have two-factor authentication turned on, providing secure CLI access without bypassing 2FA protection. - Usage tracking: Monitor when and how tokens are used to identify potential security issues or unused automation. -## When to use personal access tokens +## Who should use personal access tokens? Use PATs for these common scenarios: @@ -73,9 +74,7 @@ You can rename, activate, deactivate, or delete a token as needed. You can manag 1. Sign in to [Docker Home](https://app.docker.com/login). 1. Select your avatar in the top-right corner and from the drop-down menu select **Account settings**. 1. Select **Personal access tokens**. - - This page shows an overview of all your - tokens, and lists if the token was generated manually or if it was + - This page shows an overview of all your tokens, and lists if the token was generated manually or if it was [auto-generated](#auto-generated-tokens). You can also view the scope of the tokens, which tokens are activate and inactive, when they were created, when they were last used, and their expiration date. diff --git a/content/manuals/security/faqs/_index.md b/content/manuals/security/faqs/_index.md index 3a881d91a410..4aebbca68bbb 100644 --- a/content/manuals/security/faqs/_index.md +++ b/content/manuals/security/faqs/_index.md @@ -2,5 +2,5 @@ build: render: never title: FAQs -weight: 30 +weight: 70 --- diff --git a/content/manuals/security/security-announcements.md b/content/manuals/security/security-announcements.md index 103f9cfb1805..2150af089bc4 100644 --- a/content/manuals/security/security-announcements.md +++ b/content/manuals/security/security-announcements.md @@ -3,6 +3,7 @@ description: Docker security announcements keywords: Docker, CVEs, security, notice, Log4J 2, Log4Shell, Text4Shell, announcements title: Docker security announcements linkTitle: Security announcements +weight: 80 toc_min: 1 toc_max: 2 --- diff --git a/content/manuals/subscription/details.md b/content/manuals/subscription/details.md index bd9b5a920015..09a25316ca2a 100644 --- a/content/manuals/subscription/details.md +++ b/content/manuals/subscription/details.md @@ -28,6 +28,8 @@ Choose the subscription that fits your needs, from individual developers to larg > > Legacy Docker plans apply to subscribers who last purchased or renewed before December 10, 2024. These subscribers keep their current subscription and pricing until their next renewal on or after December 10, 2024. +## Subscriptions + {{< tabs >}} {{< tab name="Docker subscription" >}} @@ -121,9 +123,7 @@ Pricing](https://www.docker.com/pricing/). If you have a legacy subscription, you'll automatically upgrade to the new Docker subscription model when you renew. The new plans provide access to all Docker tools with increased limits and additional features. -## Legacy Docker plans - -### Legacy Docker Pro +## Legacy Docker Pro **Legacy Docker Pro** enables individual developers to get more control of their development environment and provides an integrated and reliable developer @@ -143,7 +143,7 @@ Legacy Docker Pro includes: For a list of features available in each legacy tier, see [Legacy Docker Pricing](https://www.docker.com/legacy-pricing/). -#### Upgrade your Legacy Docker Pro subscription +### Upgrade your Legacy Docker Pro subscription When you upgrade your Legacy Docker Pro subscription to a Docker Pro subscription, your subscription includes the following changes: @@ -154,7 +154,7 @@ When you upgrade your Legacy Docker Pro subscription to a Docker Pro subscriptio For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). -### Legacy Docker Team +## Legacy Docker Team **Legacy Docker Team** offers capabilities for collaboration, productivity, and security across organizations. It enables groups of developers to unlock the @@ -174,7 +174,7 @@ There are also advanced collaboration and management tools, including organizati For a list of features available in each legacy tier, see [Legacy Docker Pricing](https://www.docker.com/legacy-pricing/). -#### Upgrade your Legacy Docker Team subscription +### Upgrade your Legacy Docker Team subscription When you upgrade your Legacy Docker Team subscription to a Docker Team subscription, your subscription includes the following changes: @@ -187,7 +187,7 @@ When you upgrade your Legacy Docker Team subscription to a Docker Team subscript For a list of features available in each tier, see [Docker Pricing](https://www.docker.com/pricing/). -### Legacy Docker Business +## Legacy Docker Business **Legacy Docker Business** offers centralized management and advanced security features for enterprises that use Docker at scale. It empowers leaders to manage their @@ -206,7 +206,7 @@ Legacy Docker Business includes: For a list of features available in each tier, see [Legacy Docker Pricing](https://www.docker.com/legacy-pricing/). -#### Upgrade your Legacy Docker Business subscription +### Upgrade your Legacy Docker Business subscription When you upgrade your Legacy Docker Business subscription to a Docker Business subscription, your subscription includes the following changes: diff --git a/content/manuals/subscription/images/subscription-diagram.webp b/content/manuals/subscription/images/subscription-diagram.webp deleted file mode 100644 index 58ef49cc4acd4506a01e20ec06a6ad7d88425ff6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59342 zcmZ^~V~{R9&>%WC&)BwYpRsMvJY(Co?K8G*+qP}n`+mFk?)`O>bUM|Q?o?8#G?FMu ziiwS!0s*Ou3M;57aB9E+0RbWX2dBV5D6`m^B6%(_ zMGFiKILD4(1dhmaa#Q=8INA7qteI)5nfh;farF57 zpnkvNog?>C$nUY!^0$rm)7`h-{GVHe;13$B@;EX3J`=%Kz!& zf@oRY{6CHVs{aRf1XSQpViEHFA)U;@zOK&(UO)j}Xx6%xe*Sa-4u29Nly2Tivs5nj zccw_MUUu*GT{MC?mx`}i4qSDT5bx8naZeNCMy6d3SMS7K2rwuC=-eoU3*Bd)*)xv}`v{h57W(s{lF*hGug74Nam-tyg+!IMGXRG(Xcr9RksX?TOY(N9VgQ)iv z<12;izLL?4SrGdsikKyMTG`6C#2p#SMS1#lWIfMGSQ@uVq?&qwlU!k|?Pg>;7#l+} z&;V+_8m1vDt>jnG@aBPh%Xs(K+;SL$F#&+26dd4K5Q>0`3CaA52Jxo>2)Mu=rS(YJ zGN0qTvct(5Pk918EPniQ_;O_lJY&~^AD0R8K|BmkLr9{D9~VjZ83!!-p#5aN!d@zq z@E8V2m+nw>uRj#mSA>RWPNM-10T`S{+4MMUO(rsDAxZt{xX7-<&_+ zhTF#Vr>UtEKq}VG!W6zhcw#RWWEFpSgS+3fj~8UnDng3!Ng#DiOVFoS7PS^vBeiz_ zRCY$cs$~Xl667Xk10tJTEVPYr+iPp}+{Qw5N6MfZflq$M`lS`USmZ?W2db~01>nCD zRFnb!1G(hO-gIcQy1$RWS@`0}+Ay4@%i6fJyX%@Qq<77Dg(;^GLa5ZMJK)+>@#fJA zGEF-WI?fadEKfA2EQXJvFyD+eHI;$&|H75jBKpjf0pLF{dr&L(H&7V*gDV{ z>hFt~Pz(aNn(FznHeSA;Okb0L*T#i$Gh)K68g%*?$gpDx;_Bc*)+`|YZgX>bbAWdd zV{#dNUu)u5ngf8b6U+hqpA+GLlPmzbrri$z`LirbXXdU`eunNO0pQ&lAmE2;>esdy z3jpNdqt~vO1BfJ9aNZGryX(bRq8jmgy5vP!a2~!nn$o5fuAXl=_Nb87ct)t?go5!y zr+Z=xGKQBsBh3N-ECBaxN^?^+3yg&s&zXReT!3rHW=&*KWWuN26@yeOq1qx zbe#-=OtFj3!}6Net({>QESvK9(^XW{w9MLCKb`>qKvPg&2G(`h@6OeK!k^UnSsN+8 zD?$P6iCuz^k-4vv-ex8UyXBhSwt%qDNX%1CQNEH4(J6&ISxlR=xhbQEN{F3IMZ4+b zR)7jk{kk^=@HdhUT@G z`8p(``QIy{F1YG+94*$ybSpD#&uA)(HPPk&CeaAWd$rqDn1OYbqp6~rsUfYDLYh+g zy$ANiAr*2F_IopyuD$N?5(*}X5W5OodTwfP1)fsMy#UuRV%=BowA@Gg=*yj%(e3+o z`vN?R91`$~swn*Fn?4AtC5BENLtAEyG)UfRdb0nC z=MsJ)uQ^;rW^HV{-9MGg3t6*y@eBo^PcPmVP+$+7&YMrL@S@!Fd1L46Ele4`;W+MY zdrnVV0|1X}e_3GH)EJw>TK|+y{LDEQ{5k;KZZ?w{3-JCl;S;$2Swv*^Ra=|Mz_OjI z>zFmY)Plxuz6obnhVM7uP1ep_Kk%tXy9vBxo1T)B4Z&4`&Ol-}1QkmTkeA+yb28z< zUS{p}Q%hezK&S6LuCO~~j#8TTnWDQmj&BA{%n{-vIN{eZRaj;Zm`&kZ?p2)$GBA{1 zE(v~xTpOqDj!tW1Q9n)O>wjb* zsZY>)M?Xe)erf}A4<6Qx_g$_fyr;{^qcOia3X=olNU~Ae0$l_PmC9Zeh6Sc8kU8fH zA@tgNKJQ%t7C3`vlE0$OD>x?tsab{(Un&JGq~BYq5+~-QL5}pa0xY189r=Hh+5hM? z7lxM(yZY7c8<$$I?MuB^2L4>0A1lOM9DY85|1S&h^{Oy1EDxvoe0u8NUi$d>!nI6- zAw8`Dzr9-!Kpeh#U9xRn+HN{DSIf2fRB6>BUOof5HSJcio=*-O8`te#vc3Vo*IgBA zsxBw`r4+x{B|Rz}>*(d6V0>;sJ)d949=Hf$gZr#X~N$>|EKz())kf`VyQhJ_TZL3eWaajpq+gD zk4<#2fi|+>Kh1w^*|~Y$!lQ2!7iQU<%>xt&%$?2e{d&GwIxA4B*+V%oSvk2pe4T$@ zzi;T(Q&C~LTt_=u;IYFky*ab!!7YtFn@P@jImG24myL2d6yZcH$1MxNll3Xz7-ca? zYuBkmn}so1K$&V5Wu%OnRj`JdHQlj)bG2_@Mqf*xnie%|lyJIEi`*v!2I?}izZ3z5 z4NKoSIc_R>(l}|639!g4(aZ#R9GXTI&`$i{;&|=Ss&~86`E1**eY+y-w%B>&w%%Z# z#qenQ??337Y79N^vT)R-KPNgFWoZ$+{4(sDWKK-lX#Oj8>ulmO# zQzzBLlkER4*#BNSFg;zXCO3rAgQ19|MkF_Cxoi=qu#p99yl7s8wg0@4I~Gc z`V4p#gg=2hRf4RLIG+x4I=$`>w5jbnFWJ}mcj>Kuzn|ZC(a-0n z{%h|^>$?ExFZ7SwxBdfv;V;W)&fD)z@6qqsulq;)x82w6!w=KX@vHui_$$Fz+8D!8 z?sV_)ui5v=FX-ptJIQ-)Q}+&^-$&f*zr3C%ACB+U*V{*dPk|{PaPPQJhKHSIKkc8| z@71@so!wgk1A&R(I=|*$(07*SurGnH9tnPjPvbktui4MIZ-IM(D?fYRQi1*7<)6WC z{j1Z?-}T52|_utK%!`HOm-VTbZ+aDL2ZW;^0 zU-|;BLD!TDdNrMJ*kbUV%~U2=iUFx8L6}gQu%U5L&JC7A19}w+N>5=xN`)N`77YV1 zjVG4;tD#P#dN_=}So3(UINYA9+=Y+?#nDjxJUlcgSoD}tCnxtMo1$G#$|7n_deJr( zO;w~1-x;=q8&W5Zqiifm-&}adDTu?~4?Lt5$%aeG2J2vRxD`~Y>FN!?1_mtLVH(#x zu8)h_Kod4>OGRIOIq^i*T$m@vdv@+_((k%D@}k!+ky9)T)h&i-K_fHe^C=rZMl4_m zs`-ksgoOk@<0&9Jp|Ot2pOI8z2HJWD6XS{eY?)tS*=RVE1+oRh0A?JGf0?S1ugQ!SFh=l1`U-`KF^y4~B`cO|;5??k_UQ5~XUCd}w zE&)k@jEa%jgX}}FM(7Cfcz&oxYskGmxBqE#h1DBw+bp8|WUT#R7v8P;U3FF^=8ynb zR|t6aU#tV4LfzlP_fA)I`oF_+#nN+eGRtXW)ud0N{Vq}-V5pjO7II7c$9eLTlAoJJ zE%~IO=wBDnI;C7QFRJ)gO_DIXSdKUVg<~t~z!CFmXm>%%L+WyOJv3smFKujcshmLdhD{jRY^wDz^#D7B0jY z{lD!q5DGL-bys?;mSn)15$pp$oi<5SL06Fjl0xDo9%B*`q#39A(r5YM#>M9Q{vI>DsqY zEF-uc<(}fb3fs|yH`nqQIB`dcHMh5p26c6N-v+J<;&ottWM?}_gp@YUOn73<7DyZ1ZY8edS%Z{?;s10Z%o!Iom?fs-qPCtV>J=q3ICbx%x@Zd!F2Li?f&AKj`8PotPzsb?@>{9xIA&JNda!79 z82?~jQ$Kqr+H*6FH@uSHD05*@({fL9_xQUY@66CEJ9Ad&k#G@C45ZGpYi40r;a*`b z9@~)43ytqXP?40nRPcsBfdDswyhkgL_beF=%c?%NfR#vR-l2x^>4B|#a0ose<+9a0ifqTbg_ zmJu>Viuo1&b#Xx?B|`5^sSW`UQr&|_cyk&!b%pvqw9#tt_oKBw8XWc++!=)0N46KO%Xeht=rr-Z4APGzz+F!N&DlJrXWp61#-Mybk%Ft>KQwewT=l zH>NWm4^V>lvIa1hxpE@thFX)UEBMF*NAsb=d(nR)0V8*z{=`swz`ng`xNj;e2UG3R zv9OyQCK?XFTgTkX*-HDf#A`=%&tMEIoL$0>8w@^HuwMOsv>Zu47=>x7r6tHNfbPX| z`PJxUT-dSDTCn(<(X%-$!d$)VyOj=L#@Lst`!uuFxdtx8H}vrDK$mNt`BHOkbatQ+ zgM*v@yZ3(K=71g1Y!A)F<}$8gK|JvjjQR2@!Y&u;RAlgKG1q$g4gbsUUPk%-6Z@=k zey#PoVRbU3pb7N^MnVNqOA69WOc@8AHt=A$UDm!ZQ6yXY{KG=A5Ee%T8Bx z6FzWB4&${Hgqho^SEqPRBr4LF3~!Xk)Rti*^LbY~=;do`um8?2YTdpwYKi!@)dQ{W zO$D|YR(s54L#|S$h2(@^A)Y9Fn)diR>}yuN@tn@{2TsG;`ox3|2S=?bfILyGBBcn4 zQi5|{p=Agq3-p!&_Rzm7x!2NBWm(2%Kg%GPJRAyGcP@qY#S&s!Q+wMjF|UryD9(;f z2G~efcpzJh@&HzA&$ZSS!%@T5(TPC;L(|ngRvUfBy_h*eB$?N4@iQMYpTx8ae!jnE z9$6L!K$nyTDflKW?}lT2@Fy;pK0$G@2EoNqDg6dz(&v6y$c6hx;KJ@&3Nux&3`r-v zyaeQNZS*z0$PwADu@CW?^xW?u@jK!KDDvF}D&l!2Zl))8mdp2dBG>N0Uu+StDP7@> zBLvvs?O5rCwp!a~WLPYi($-my<=(z@DcY>KfY9yJ0Zb$9b0q5LG8XSII=MVPLm3JE zO^^c%nBnH{Ah?zQf)u&Y1AuHwm~AiCMwAE6)%&_4zHQw&X29ws%^>IuoBQtrIvvV~ zpfF2h0Qb&0YpG=KJGmuD)qv^GZ4@V!VHvIa#hU2@|0pH084pI=@Rxu*)p5~z?`t?o zDMYLoQG~JlZ?rW#hhQ_EHK1J8owd3PC;fEi^jIx3NB(&Z3qzX~ET@;xTd>{eaMO3Ve1TXi zwP;4^=Ku79vg52V9Y9)sjNS=U%wsxhXQum9E@cOpDi*Bh9oml9v=|thGh!Exmeu%< z7vKTgUv^C8ftBIZs)R}s-^=pZi`?G*HQErI6Yh_R_HJ2e%d{Hr(-;gvfpHj50~yL4 z(8;a?mQZN<;}s4P^Yf8sn^`}BJ|p&p#j64jR|V#&H8Ku52MIxWt~&Tn#l^Lug*e5l zc$4GMJR82Ex4@E32LMY~dCzg!qUxQ$Do7lceLmPCk{v+rz8*Py$r!sF@)|a zK?KT&Q0PqwLWXVVL!mNyr2bqaysP?_8Gg`@MxJQ;ALNA8DT`OAD&Ie_zo1muFJ`Qx zzI_1#23B3LSrcSpWVMQ<;-bubxTH3HYG~D7n%t#^nkw2px^E?^^(yqS0{4-nHMWx}zSJoj2wfJt%Nt zb&#czOYrj4op~$|Fg!5b8cPX4%h(ws*ogFr=;hz_*eP(%4 zzO>;LsC~RqsB2}AtZ^Y&)_xIM@lEe&p*|xP*kakIE<^c~}$qAaAf7xp`o2O{I7_8EUUJmVX4h zX8YkhH)~gImuI+T^>nT$rQC~yY()u-PAyw~We6euem=2yjRtP*%|+kI>$;yNX-yXC zRGujBa&EZrUl)?Er5vq7uc&Euar`n$c%ZyoFk>xdVCNI!V<+eP#B*_yKQ>CXko&pk z2Kj>%-UO`w{koyM1KP2F2rs!K(xO`Cw#+cYN3DTFFHPT7My)~n$6scm<2%JEGmFA{EOT$r)Si;%OeK|a_@C?Pk2fUWq?>mig-r}?)-W9%N$K>@c+;E#5 zvw7C?$R}2z)j~#3`mdeAzCd>u-*<}ZBY|}bA+q5gobSzcBJY!mB)NBpeCHB(+WiEw z%c6IaAXU}$lspU0JNVOlpwQ!(kRJW)LJ5IOClh>nGF^_AoDYP0NW*JSuZ!kX#=u-u zndgD_>u!=ma@sQ)J*cA{y+uYuH%TO?+6GH$%~` zwRn`Vbd)Imq9EIX0ctp_V&bw>?$OijQXB0tUg8qQfDlA}%~K)t6Yt7jT6CX|$?o5fWyC-O>{}b7A!7MYVAk+_?bGd~X*Y3F0e-1DwE~)!q~C2_jSPEXCZ4J8~1W z$>xLJf9uzufAC6}iIl9Q#hFh9K<5ySjzkhCT{(l%5sbIG=?j&>h}8G&B@f&{>+Vwd zC*WGq?Ys7MvPPG=DJ0Zhm1xwdvAroQ4>M?Tv2|w>qXliUY6VDWcq-FNe89IU{4Iau zXm=67C~lw7vr_Y!9I0hQ4l0}+kwrr0O%mn}Bcyn0nizj^M$a}&IDQhZE@Mq~k_8(O zDFmDt^g_Z2iYxf)0r_UV4kO1Ft8FtoAspQ%O?CHwJcH+P%Qhb0A9&_chf+OrwfyF}^>;~7N)j%#uX)Ijzc6G~i@ z82H%x(IaPOAP*G&$E>;bI`I*9I44V00XDY&x2vxLSbIRiBBdQ&>!Vy zf<&rmVTqSkrelnJ#)q^B(VJmOS;fI^AH>Gwf>fuO_vwicryhQs%HP>a+DeQKd2q)y z(jG%2=+{w~G2!&4+U^gxV9AnvcKDb*pG@djWkM#}!}EgKRHQn&02cL?q$?yc!^l}m zyt%T}4vY-;0C) zO6!>M(Fh>X<+}&WnX>5CiWfD;<*DqI-6ss#9PR4 zFQ?`%d9XV-zC2j&R&9s6uI7W~q%XD?^}a7ja==CO57rmoyR?!4u_7>SN(K*)=YO+YuBXAOi(SEQ^d}u- zCC@o+Y__oPuHDT*Ww%auT|M;vI9LkorF<5|{xa$H$UmXBscrJSCJJUX^i(42p>W4Ru;8 z9TG>x`!}fxKQG_yp^|kzV6FSh$Cd#Kwm*>8%h=D{u{IfgN}&JN_l>w7mL5vy2uJ~~ za%5@t3puU)<+K_M1QFkO<>~)ZE-HW_mX>s;fW7tM7go#?jhYz$)ZcTV= zFuOcnwNM8W9DbB3?v(}PWO9@Omdyf0FCjtF;v^!qe|G)Wj3Ad$Gyn5dNXZ3U zctaFO%}oR4ip-HTi-fh-)n>6HtwQyHfL3UG(UDK9&u13h1@h$2D?lgS9^jFONpKRB zaMfnmMT%I(+P)x75uS^g8kIE(H_h|V$M)sEmkDgEH-i0Khai*3xkZCmYmNDFjaRZwvZI4HPl3ORmhTvfB zn;$Y(!qQPt_(GT-7U^IU%U*_%`R9Ym8REa_Dgw0#l+US?kyMlYRmR}v^)EOsAKlj5 z!tZRyL#s(f(<07mhplGfZLwsJl}tv$L*Q}IHXT#(+rp`G31SQ&Afr=>k#9PPf%5q& zxhW?VV_;}?R@g^02(1rJ@J7t&x`T{7G#Djs6icDS58Do)LB+hFzI;kI(7TS|U6oRj zh1V)!=s5zFM8|06{$ByKZI3bhG~*1D{s|8_Mo$ahejOv%y8bxmsBQ4_!z#T-Ew`)( zv>urCD|GTby;`C89#5BDHCO*dQco-wZLkeD#$88)-dORf;*8spV(L)A=Y7XD%smUf zkegc}j;iS$U&f}T;Uab}x(J4a;=VK^w}z#idj>&lOGK@}zT|VVU!3$HAJ7MhjX{Ws zU+2)ue7b?kFgk|%y=f0j%}8W`esv7A7}<|&(Jv%ToCc_r%cvaU{8Ht_#jZW)({X zvl5CAPGu-Y2OI3hT^GR*GsoUo!D9n)M(m@wDU5a_rc_%OHej^sx(wHV(KfZ~69cP4 zo!D}|xZs#U>hoj?Exk1l$=(HJcYxv&QQHL$e}8`|@-!Ai8uj6Vk5ZK8QbhrE=`yLbN(jv_)(+iwQ}x#_K!B zYUdfiPL$JwkcXnWjgb?KN^@8U2^e1dgGu}^j_a;VjJ%x;womRhrKT)6a-)uQpy!M( z*UOQEtBE0{^x^*Dpw08MmD%shpMOWY_qJ`!Y#Qy=Wsr$x9ZC~Ecl@tMRhImz ziKFCQkRy|{xy!QIiXOE`hMj;}9t!tlH~_?M3l_vJx{JGPmkDbz^(M;2X(u=0t74I* zqEu_ONfd6eac=g<7@g}?71H;JvV|yMCJQ#**YSi50m1?OdL4h!l5+y+rNUIWT=k7n zX$TDHP?FL>ql{yQn-e?>zJMD8S(;m9lcT{<5jQ(3;2!U?bRagt>1z7|!=|0iO@i>! zQBK1XmZm09koWic_7}6BPXNwg#o(#Tkvb$GLI?OUfmv~6V8Vn;5HA2$G-#<0=vL&s zrCpo=31FTuR~~_tkRvhNc>mv)MMXk)|DQKbP-RJaoZH)2_P{A5j`#0;F5?4v3eevz7|Y6UE=NB7y>JeS#0~V z8Y0q z9Q$XQ0X_Kav;8^qh&}g@eHvtt#VzxCdl9=B8%+nc4m`N@K$W+pGfG<&oNmZ z=lXf!vR^j3tud83-hb3U@o^53h=revLAvJ#;r#aPm2zU2m$%lN>QS2_gb_ z&7$yu8K{lPDmTHR^-?gq%)#xU!GPF|k>Q#}QyAvn3ZC1Sekx9!lh-*|?&me%6&<$G zF<>>|FcR%Kzv$r*S%Z4xm84)I= zkCTy0K;F92>m(fnDZ>M}skz+B3~$NKV<8w(9cQ8W`Pm{Xnrwg*QOhgubAtHx4L;UNL1?_z zAsvCxOqoLOlU-R8jI_i)6Oz#7V~y<(7H$9FT)rGH}%-n~mMp219Q{&LFadE17!begagB?eNn= z0C}8U%Tfb7sxl%Bhl26L@tzA8g*`-*+bNpyWQ!}QhY>3q15`R zQNo_xql+~;q_FuFkGzIIWVVc_ZlY2z8eLd!dkc*ruco~&Em(YaH1h1W^iEl7!1<_G zcQzrza@>D}k2UI_k)#95CBjtmC2sTEVnag?8DX_l&xa<7zw@t!<0YN?MsLfxn%(r% zb^mww-2jd*=Itaj4&f`4<{{YAd9={+k;Kj|%V?vKQ^g{T%IS7%F_=5)+VvowV6IBy z+IHo1p~XbE*4N}FrzH2y^(VCYmX(B}!3N{(9ww|^f==!7*+4sMFEU^8WF^>}*LGYc z%gn-Pw;IF&k%_;XE64F2Jc&oK(~(8bR;;XjIW2*xy&pY{8+39@g}_spS-&>*=W>fHmir=U{K~_V>cKPQd}#_s zD|hBt!dPUyyfAyk!xzA*|kBu}J6euo5S$G-lCz^3_)f|H-pB?w70^??D zRru(sokf;X=mA8hI+4;h->;4#YJw)X%_I&FU+8rYg&D)|#HmrHtOQXEh9S%g-teCG^vqnye)=%KFDbJ-n5lkHK(jxn zPIJ0L=J_q{Fs*c$y4NqCN(60jKG%8>Tiyg6AJ0i<&{4lvN##m9Pd3vBeK=RULWbnT z7+zYV21aJ-uChR0xEmR;sb!`~iI|VRMgU>^(R~VhPUAv8XS?&d23v7i3*1o=c5tU$ z<|6K7kr9NJQNxOt6vrVylt>66Q}w)ShUYbI6eO$3zrw}We?H~x_V{fWVnBL}kp?JZ zy#|-k@+}R1dI`L#QxKCqryF_;UNjxzAE(m6idqcV)qLDv&IeZA-h;lyskj;3$(mUc zXW3!;_rsRm$Cr6h=9YMCTDk`Ir*GhI@ead5;VU$5ZEoDJv@X^H2~xCqlSwuUsM;P= zIOUz%Rx{;of;Pr&Fmp=DVDA>{7mAR%@zn}bu>ccrO?3Zw+3bW8Ob7Wvg>6*%iW3N>?PcP>7y%AIS!< zC!GF{;D$Jyqenh|8>Uw)0^8baHnm$Pum8lOl-1{L6DB z2$8RxQCa>P=AvIsBibknrQED7&6wm32;KeKgpk&n$?#*?g@``L_~SU zws(~Y;u!`n6~J)Rfv~l~kD*Csu9rPmXNHrJI<0w)sF27Nh23u8N}fLjfC?e9hfN{; zl$f8)DU5079m9?3^_QN<8R8bM|6rH|isARNwaI%!wqC!yWDKzhK2=K?#ArIgt=l1_ zK#GscGSIm)xleFQ<|`5`-D|?#*L|r9X7r+}BrM@R4lylp#r>C418eU0QHuGKoI#-= z_6t9aUfG>)7-rBf&sj|B;Nq{yzuboN%9hZ(qo3YDD#H`t0insPK&%#$#ztYpNC~>- zgYy|e&0ApctDF80@k#C1A{X5CP&fA@E$;^w-^XPGlBR;TU?nqri2}ky*HOMn^lD0?oI`>6=X4n&+xJ_k^bA!-w?a=oeOWnp}}fvSk5?Wpi(WKS;W)>w=xl*I%k zW5EDKFxY;er1yeQKQlq4lpu5=N{(ZLXY2;pqTm@VgrC(S;g23w|EIN*1KtqCXN%rs zaas>Z1RwjMt?EXB_AFtl3)6)QQ(4^2^XnXr@)|k4R$DFxO_m_&30xeD%#0##+WcMV z>ANI%t!2Xcinf$L>8BVx|3=GNv0g$_H`0Q=1gC$7K1`+v^#?7r^bfiDzThC$6Eac= zJ5cRLFwAlmn1(A@fp=wg{T;c|j5*-D>GnYDdPZtBj#Efjtuy0zk5>pLV2@Gm2gP^w zYsluKv;GSc70*Ne+N4;`k|plM=Nsv8)N&e3;^qcWYb9Cqf47-}3C&2}EZNU~j1Io_ z)!9fajWBEyEt)Q)FTEXZnhsWStN0FiEum#EiGFM>$bBNH_DlEfHUZi4<`vC;J=!n> zAMS|#Zt91w`Dl5Y@W>B%)10oSb#=kVW@)sGG;2_y<`jW`vcG*;%yBoA`Gq&P`|-5? z&ExA@Ze8-hD$?xWR_QolYeZDGVJsUJQyMmR211)S+i_`{u1LKD0~&8hm~lp3|FY#< zZC;@K*B7r`77%}VVF)Fp1+2a<=f?~~C>J(+DNE}n0=GRt&ex?SU}Tx~(e?7PJSsm@ z3f=F$Ir9-lmUfzsfk(iy$k3(wm^CCrE5e8fCW#+B51`wIU3QUzCR~m+Lj--vwzL*z z^ylyWXyYoMs7e$Nxs0@NwaIP9=}INH)jBo0kf8)515#bLnr zyTvLC?c-Qr+IW737`7V$c7&sp(?ww{BuvC(=ulP+(w;+yPbC#-7k zhxPH$`?XvFi?drAl|$)F_H^#e{?)>Ua@C5Nn>ha9z74+QWzsD2gv4DKMiU?==)Y{# z{k*-wV!lmC)VH0p>PCY6hcSBthY7bA)G)|JyDu z;=XYAJPxfRXj&02QJTTD$e=;Zc2ki&jz>0)nlEs^(YYMi*6$^S4Z4a8l+2& zdS+3ge{UhxFl?>PLQLG9Ye6P|fTy2A=u;u8b5;!2-?Hc%g5`n2^Wy1@2FU^sN(A#H z-V8TyVX)dGNK&MMDQmEVXV-ncdBQl_qUo0NBN$6tTeUOWJ;XbY?xnaQNq%kcDeN(EmJ z0iflM=C_w_`zJ{R_@CUp3z%I^G(4s zk}{!P^;F=v8fmw6mZ-EJ2TUS!KJ(5JcM>;Es+Eym=c1@u`CS)496q@Bo*nFIN*tT= zA!vdNkMj{IW{p6Jb;fE6+M$y7-%E?pp$xr`T4)A( zdq@RJOE)wo)%6WWrE-3~kgQVpw?Geu?sOvmt~5{fF-lZ8lIA*q%84;2PFs?O30lf$ znSEBt#JqVK-jDAsDGXs$gcE?$CZU<-Mjv*x`!Q0|m^@-a3V}3n-zYG9)79Zi`$RYS z_YQ=yJzX1#V$|Q@j->rb@JdLVuyJ%L_c%*OwPZuQ&A9S=+e-#Z-2&^F zBd_4q?>K<*;Tmqf>Wrk*Fdq)x*c_(-j=Cs-g97g=70(ld!39y~F8kMRLZZdyOsFXI zx8uI9m=dhT?`H-=3@JdQ6;@TN+uhZve$;_?C#=SqiuR|lg63NUMd7W!MVUh3xWWEn(1tv!Jx$+(Np3udRxnMNtt(+AAEfDG&gRHMx) z?F`3^H6sQdeQ7n%-*>3puwc0f1n}4LGRMitF51@ev~q!$_yw z$IViec$kUU31_ky{`6K*i&7m=kM>c>8hH%=o|Qe3!9kp*$}wWQ$aYtrzKs16*}io@ zwFrl0SmIJ>sL%b5KU!1u=VKotjkO0kbdpL|U>>c-O>;YQzzefl^PC0c{n!(g_Lp98 z4rV8!Zk*6|E`&s}X<9R<_R2Y6ugg)~FNkmX*yu>se7Q$9F}Xlx;Z5V|cYN;0tDOn> zL;yL~#eHiRWU|`c-}IWf3kL9jGCYa$KS8-fKY!>*_j83Q!ITRVn}rGnu22j>LNHFI z?1WUCBN zQ3%4eLd2sctZ5GK6i_F$GIX=vn<{CU7<9+M1Ut;S1Q`2j-Im4as*ApbR%ReHaRsM0 zhga;hN1P3ogHbWe+ce8I8hxxH&wTIUnXTdwZkJ`DTkfQaxvB$wbJ;0ibF95p%(YR z!2!ItYK;)6SvK*vgI*Bxo;vt`6w-@stf>nqS zveQun%a|8QS!{lVd;fDV(OZ04&(!n282O3_+s(~WQ9A;vFpk#EjJ9D*!A>?qpHyW+ zaL9n*9wNKTEX+HPPMGtG{ntj|whq#?$Kqdcc;14@VkR`*4V9CO*(>S5 z3FgGsRKp1QKl6;Ad`gu5K{O3|o^>3;cC;B%2q)U7%>lQ+!@4{ijb}XdkU)LAT!+uN zH}_J^5c%hm3y`17sFd<}z7K63_i=UG>lmaT=R-jwcU|+Pwg+cnC69?B6x6BG6g^9_caK#oU@Ab*6w@zY3c?)h+jp` z=D6O(mTV#lH0L-4y@ljKgBaQS`@`%Upc37_xS>z?-`T-tf66Ksm7Sw6AA>ah9Tn;o z$C9R`779Eao7$`#ICuWSt{NxN&)%qFJoo!%vU|Q=K(-)WkfS?S1}|MpiRtiePHhPP zpAVrm7KoXR!Ppg?d(L(<(9I+HLB(NpgfG*h_gbi5vKOw40j{2GA7;#~&$tP?L)0Vm z0QXQ>fHiKE++Oe}1xpP8{yL(uHMsSKudFMBpt;#f9w!?4S+YZ?cLYNSX_$?=2MqnS z4S2X!yN>4)s86bh>vlncQ6zT53XoI!l37BiIMX33%{`d$OojIBL~toU+gJV^XN1XB zN~O0dhAW8qYxwMT?JXTEZHBJMPor_vP6fPb7_D2d)EZSgWUU5x)j2qMSCor9ON%Ur zpqy|KBDjfV^FgjkyAVsrAc#BVEQ~ZY{z~qVMO}Gp%!N&x$4DsT7Tq{Q&9zh?KUHw7 z#foJTdmB5|K5jO2-eW0VRoiwD7)?P^b&>HqxOeAOYm22+<5b;-k`^Yz&vjRR2|2Cr zr)*+|89n-fa7<>n`u^*O)s}e0tcRn5l1==5jmSqcCtMwM5TNjKIXQ5wli&wium!67eDzD`aRok{HT8Mz{_ z`9;4#qs_o2HhlF9h+C32v8W@eY!lm;qw>aP$19qTYm-9#n%4;hM!gK7Gi?K02Lr7vvg9zFnkuCZ`}^m@i%Y6I zoNN^=<>AdHY;u2b9&pWpb4YJ)ADzrg?ROkdDZkcB9M-f$$TfXKdZDv?mB?&0%-X6I zLw3}qpB6kGNIR+nX@vLDvrfFsFE+(Jj+NirKvpi@&KX^Mf+r^**BT+$A-j_Sii>m{ zcL#Rq8?yTL>tmvN_?C~4@WS4xDhB0${v18te59sWWohi-{%G$GCTBcqS^H(d`k21; zmEHxUSs=`^5dIGqV}G9JJ^1QNgRL6s8x??`8c|GA8`O7W3~J(viRg ze#m9&c%zw$dGp^teb{e{CtGL91p&O^Y@OF17Wrct!~^<12o+Y5cQ|jQU@YNXSZL@U!Ix$OXaLP6M|=_rX;@ZZYN!af$iIii-rem#Mfz>W?jY66 z6F77laIWD*zw#nv7Wuh>yI2$twrZxiJu&|aFF?@0W*19%_FacN1kZqniG*B`tK`>K zEqpwgm7@L|QV=ml7or*ilv++^S>>d#fUV*l(1OR+^I*X-4Y)-t=}|bKt$osO#G~$$ z!FUQ^mieo`Vus5QPW+6}005*G6vOcmcW>J5$yMdz!*J-MKk(mR03HTjcX0_%_F=eD zuN1o6Csh!NY*MFf*J$+fge9jBTx!|lQ$z_pg<{SX#mo(4JU{MmsA;KQRR~v}&X^F= z!L_ZqC=m@MaD;y;uOC%vq&)iAsVwBXg!3~YfU?CY22?O>?;P7YQ#Ket(O25=!(;(% z*$0&snf0#)ZK4$<$fSO{7upmxc)B7jJc>a|Z-rb|=!>l-9TcKLXteMD+MVFtz^;u`5rrDjoEW7f_@FH<%xwz3M+ zmQ!R7IsN52bHl)o1s`wrgk7?H^EKD1nOHng{v0vzQxA5B@K|I}d#tMowX}OB4oUcU zoQ!KP2)n>i$GyI5X>-w?gm6B#> z>;3|=#*$`zm`X#=mMiHWGpV~)?p>~{)TyT3it;z>SSD`|@z9beX+I+1z|y1j^dE}eL< zqsRPUsZLRH!en$Hj6SjtQHHuB>hiwSSY}gPzcl^mV*3>o+;`3?rMi)~J=3T9tI4P=IYGEY z?!l|$#bm6N&>Q$|v5_k*m8#-ark$yr-5F?5FrE%YP{Xc!zpQQ+p(i#OLue{D2wJ*L zdBa}Rc5Y1&K3=sTW=tsk>(Lj*^hTah_IEEEN^v#KqnYB$=h9E z3=Y|3z-@sc&06$Mm}D3&whsQr;MjekwX!>mc7b z)5Z{gt;I)vGN{U(F_xZ*^+T-ai|pDsHcO@qlDN?Y?!nVPoa>)cKz3h$d;QnW&GH>t zCukZJ&5J7<&)3}av$LD@zeyufAhlNb{Ivls`1=)I-Os=nuG$pnH69kqNWn*;CF$%D zHTN}ojN)0Y^U`5IP8Ro8iI{wfZK`xli4=kh4$yFzVShAvR=nE>&wH0bkE<5Zi=2jt z_NmyuA=!BBk@DZ=AbKB=6+V$QGmF@zMk(XrV)cbR6t=CUsp(S@!m0-Yib|i+%0Jhs z0gQnR9b^lC6!xlmx(JI!*$xnCU9=@&9Xurx1D6FmK6*IQ34K+Nm%f<|O$qX?%r@xl zx{2;XkS>l~Rt3w77_Hvch{T`w!gx8?Mi?JP46rEBn1FzGXcaPKk z9*|07q^7X1?_kS+rl(Ny^wx5%;9tfINRR9`2Pi@gD&d%f0e;z(U&SW)MfwwF9XAA`L- z$(pSFXk{gzu>p%P+d2@beP(`^Ba-^5Ge}-b(+LZJTx-Yf`Oja5`Z3jY_h8G8!ILeb zkn)T{S%*-GoTrC07+5vyp_o$Nvb$rgAYJbXat-})UL4(%w;#DU0gnDHi<=0aJV+2USKTPj`g-i)WAzGuD#wmRQrDj!4vBgMVY#m5^b3}JQUHtR; z2m)YX-F9g#n$1(#A6mX#Ocg6-iwP_fYHn;P{n!NOXj)c2Hml39`$kG(x=u$M$vhIB z7t|fr-l>PI&itAJTzoY@DPssUQ>YX%7d+aE=0bM*SUCz$!}vuhf8uaz4}YfXkA3~` z;WrK0l(V*6j&wKMVMOmYZv=U_z0EMup0ibA{xsb(p9!5B=P3_4uhNK3s~3)62F^9l zHe%fix8NO?+0H4N`SYIvlHbxkqIKHm zUK+)G;}l_5WUL%a}^pGXOr8|64m z^Se^R-QsY6?XZVf_BEj14&?)6!QWEyu}&;*x!v_5F@*nHv;)N_841OnhWQOQpA8140LR?@9S5!u7Hb@V1#@gG6I z+q2rj+h%&<7?Ju`gLG%^L%?k1UGIeB$|trX>sdhjujsfw5g}Hxt71x1>VJgG95Qo2 zl&deSLbJ}?s`9jyliy5T98r-~`xNjvkqBv!3YMl6#MXDBbIxefayo%B>w+n?Y%v3x z%?TJ-jV^=OAXxMOh)7;Ek-UIc#d@Ixxtq;g{JG!!cO(<`Af(w(s=F^zF;dTDczpXK zR=zge4FAnGM~8PXV%04)saKCnBKC@>*J`p?8zEy*%eAz{?Bhc(x$lNPz%4RI!eANz-ZJxbDnM_W}`r=Ps~n$1|syC#n$XQMWFGn-?_g;RlqIqEFp>K)*9zyi7G)Dnx60wto{6Pfkg7!4m^m?uKMW@da$xySzEu;BtG1Le<5pU30e}y>$j3T! zDNhI@q81qzK;4|uB>9$0)GX$0(&p!nD-(>sYPSnpjH6`7rS{F+6{lh~AU5uY%Dhx+ zj9GGKW_Mkdti=-clS3c$iEvUxZMe94FKnMHProlT07bU);rzq8rOiR#4Qc(=oFAq} z#ot1o3mSF{Uuk)exPx?MJt+>%ri#+g3)2+{st!W596x^KDSgLEQYm;VSR)m&1;Jig z_fB-h3M~<+_$3AuRZ!GDZZZ>Eah4co^d)B0oJBzFp9aPuj-hoJKjDA8et+ky`UQ@c z0TI#q_?$}~9m$Z#QP+n7I)K>^?CA=Ty^3%rprx`8Or}a}7>jd0RMrb5kRMC3tFU(W zPX0$I)nw@(N=_2nE?k9|+->)4Xf=FN1DE(6{R{3WX}F)p4`6Yh)SyJ(VJrWlG{~nM zby4;Uo0F{GjJjz*EQ)DWqq%LvQ4$hJE&%2f9LKKu=x5e90yYWDq;d?1MXo`155C^p zWtI64DD?0so?>`&0M*g28rD;b1=Fdt9P}R$;Q|(9gOG^Tk=h!)4llYR>ZePjK+-^8 zhA-RW5SEwhceE|NTPg-Yv0$xJqbW41U+-$1S>ZFaLGV$2D*C_IW?>uB*wUHIXPjh>U#J*`4NsZ0gc@9Qic(|1cI>0jk zZ^}zts36HMV0jeFJcWzY&mnL4H!RF!0|(6tR&&+&t8X$GjCRCImgk@JRp`!B>tcW3 zFbqBWl&7WO2pXSsPecYC;XU@^F0?N7u;4wm-~AB1S<_)yK_MBhq|9bQ<$so}0Eq3w zM`7C}WV8Ogx*z|%^8fqGc?kn~TEx3Hw;eUmZ8KfMhMV>(M~!x&{tb+N$=U#P69W+U zJtJ}i6+e;B9$iGm*<|-~%W16^{B_sI&+StltFL1-%NaQW_n6(4<|apW-T*l|B#q2L zGI3+UGCgQ>K+Uax-y*b7?}S|BBiz1i=lKi}_@pHuSgyFm$$~MY#=6;Qpqxm&SCQ_f z7nT=^*Vrd)(R-zh(XMv*f$-m`3H1edsT|JDGi@aD+Yy3NXkkIaKQ{ttWQ}3tWnXp6 zH5!i5VV4Q+No`_Rp~8&8K4EyN7)a_;+KAPp4Lq%BhWd(Cuj)z%+IzL7fkm>E20 zk$gs1GQD{4g2H=IG}E3clfF4)Rof$iWcb@Axvv z>~O$W6QYHAY156UVyX7Hf0$&b$TctIY$Ld8ebLw(vulslK9+8Q!^AgXcbAF_|0)2& zb=~By^3t`TZ>F<8iMFuG=96EGq%d>V3Q{slF~nYugU=Rqc@FN_L^xC%?%R z+K18Wv3lxLQIICMi_O`PeO=c1)5&iz?8T<>E1q{pk~FfCOeKZ>en87?vI z0Q-D8k}{pd7uuHif}3p_8QwKjmEU>JU}Bm76~7_zICUba{Ab``AnfKB>*nl+;Z3l9 zHVJd|4F&eLM%Ux)mUmAh@=UDyXX8wCHUL%~b}^lQF88R#>(n{Cc`P9+QYfz0r=dJb z9KJXSokhHsN4Q;!AU~@prpsKhRIlOX%45KM=KZj;wADFvRnHtN7M8 zJDu`MSXYA~Yxm&c(dZ@R$7QrWER)3JF4s^amqc^{Jpfvw}U*3k7z#}76+vi6P z?S8aW*&>NdIjlISC3_*&k+2%E^k(Bvxi>NG;orWmG`%#WSt`u8rymGa%n3j0!UnpD zhn8^`ZdnhKqSpR*BggaVnyW`M?-Sp@!m=|{gK-nq8Byw5u8C1V1PNWLfH5CffF=gF z>4<4$ARhqTzQh*O^S(e&oXNvt9V)9AF3=u*afbD>MA9jn13|E;SRMFgm@X$!jQ8f; zRkqpRB(ib}-oN%r>I=M2%Os|+j>5dkj*>RXsUh*pGZY9KdW+s1541Ni)=<4Ye69fM ze7E>3AzePXFHG4i^Mrm_ejuQAMU<^ne_EycywMy+@Fkr0bzJc8^%A#aqe8_IeO0^A zu|2gd=u<-uq|t@ zB=zu8M5;@R%YErB`gU=M3nJoi=7DTj6BBU@Af5B=A$l- zR>R#L^&tx3S=^@4TRw|EKeD>@5pu(&8mDIbJpLpiqO=$-xP>w=<=d2GM!Wc(R(Xct znBL{l#iQ!A%tk93!AtW=tY&=1vRox)PuM8He&;= z$?m}dsxg);6T-A1Z{$Z^nIl>a|K1UPdq9(6J@KYd)BLM%QfeL09?XuJs7w;iPKiYu z2i%ljN~~kqJxX+IlDcm=(Qrk#))D3*>GHygwL1S;;E^HXJ3kB~StlG9=Qu85GyInB zJcfJA^T1sE4GZ?|k`ITDFv+nL-6{78ThaL%WqpKe^i~8o&ece@n`16qn&2U6K?xcU zsG1aLH441i`oYXD&8}bA{P|M+BU+MWx0u;x-=dFwOa1waBT=+d&NX0!-GcL)5JS#P&d=VPu{TsCv6sO(GjIdhg>Z0di17 z0=JmL^EPfmLL4(6|3xKy@QG;82fMSue!3dGA6~JU@@yF=7@M#nRqP!1Mlei*&1}p_ z@^~L5bN%n~Oft0U^~9Gvu|mRt^`2gDn->V6_HJmbC)5vpDRK^xMQnZ>&fJOYdAFC^ zzUXzGL^d?{9VZ6Xs%@Gz0x$I+gzKM>SyFKV0D@%`gPa$Qx^Dz5J>l9Oh~sBhmkNp} zg!Aw3rz@Bn1$Qhal&~m8_wCXC*8$i38Co}{gUVpEKDAZStion1W`)9cfS!G#i3wh@ zAmTn;U}q)Hg4rJ+abMOwKAOB*+het5t@MTe-aRJwFpWUv_!2=BuHbJPlFQ#If9N}C z&2EX*Z~|N(qEhuy-vRmmXqgHaxWa-&L@V%#fVQ9Z>77WzM?$%#sjV_##Gq9acNO@2 z#2^3vcEek`sY_mMSO=sI0}rh=SF7Z@H+4ljE%b-kaiJM_YjO9fq=iBola)*1wh?|? zoDv48&5D-C(6wPNmn(d8o+s&@6A4!7Ud(Nh_Y3{52Bb!|9(~wU4z#_P44WK zt-^^4)))|*75Kqqwt(-P<2&siS#-Q?JM5HoEYTz{B!Wg%3#d+Qv%npi87GJ0xnpUP}8se3ukU z447#mCq{_zfX{v5Lh~N22B)%f-Hn&0rdaPpciiB@AG>cf67J8c{^$~|Dzp_K5w6@A z^`)H_Ic9O^4mwm&UeBh&T)A6|>GK+ZC0bZov_tK4^_X!|nD%=~zduv%e-$B4}` zMm6L&%(__1RjbBVEBGahSeJN&R^6cOmw3ZRnVw$Fl)bOKm&MfC)5Q|MPpg>3cv2rp z?Ju{?VP3}q2O+!A##7>lK^Qq;ZEYbT_l7o4)_YDqGV~>!I{;m;C=h#W;8S#i$Vmst zrcT||4O`rgJRqi|(4*ij9{^^f#Di+Y`R}%x*+O|A=h3`Fgr9U08hbv;0i$&EjEgJ& zz~5P{#}K=I26UhHU?U(nooBv=_liTH4t#c_e+F#3r*3u`tDGaa#kWENF1|WXz!7Fg znyP~`qWBz)$MLYYM>Z<$k#J14InD54ux>l+>@`)*p?lPPDO&(Xd~v(ID_iPQupjv` zAHtPfP;2`$^xsUU5S!!{&p{4u!o2s2cOyH9J10cCUl+0c;A1>)~D@p%U@`+di(t@0IfW%uJnX51F5qi;&1bRc>*-t{;kJ*4LbZb}HV}$=|G-XMP zs0CG<)`-9~4#h$eGtWZ8FXKsYeobH0;mT#~TO=j*n<5o_gnLT0%-|#qmH7N&XX(8w z6NW>g_85=TOT4ti*ry&U=(r`C0^&vMr?Y#Y{!vhIPk47e6-PBF?R{XSo$yNI$m)%- zNOzDoP1Rp&W%hfHr8QOzgr_@0ep8nW%;owGZ2a@`(!BYNuH|vqeM<5%c4wmEG&0oK zvz#N!IWM+#i?9nNL<*Cu6cq0n;VyN;h~dbSJx77iigw$3tASmg>LF#}%8lW^_8|!C zp}m~@r?a_<_eSO6HR4R)%m^tVWa0TzxL*CksnILc^=V@F>{zss9QDupv0;%S_y3B3 z39hr2V3V1Yi}t`1ChwgEpaze$at%7cwPcU#@~HVY5dHgFGEB?fH`%iEoF{P|TZ2pj zd=p!n%Kf&HlGg^Z#Bpoj&8?ul>>`E?sV6#;m`Mb51%XMz4381aAGiNf( zZV|{gyWqy>8@1J>Omm3R8zRq`eL$pS>T2m5$*Q{GSF`Y+)Kd`3QMm12K57a~?zp`O z)^Qsv!dx+AX;c62-dc6yBj4CJBNskw^rT<^Kg!3x6X}LkF=4r!H)JdwR7uLY9_882 z2pxpdBz0X`Fu6ZlNv_U)K*h?dKe|C#08SMA^RH89u63a2BWuz;p`afbkb#uL@LvAr z90jOO^2EX=uKldsOJQ4%7B!0Cz|z65b~~c(f2q*jnRZQ+48(A3F8QT2wO8w{0IB{e zJhDbdMJ9H&=$Ksy>aN(nt!def1mQN8p%%yB_1svDz04@IM*eS1LwWJ62mIzEr>hz_ z7d`K#;$~BjdIa7y&GMO%`O&^cYd*8`I+DL)=Z#B!D8o%OIra?v(q{&-_E8bT(3t)? zrC6Nx?J>OhJ8Aw|LKz14H}qQAQPJj3ht*m|)_4?w+BAxoH- z#yX$#GFEBuC4LoV7YCzTx2Wevf8(B-*UAuVgoIiOd(q!EBN+JT4H>pzoIpVFQ~@KL zoN?p44KYCXTp^^vhwnx!2WxT=k1@YBJHN{?io1K1!Y>DYWEV!OzgAVECWi&OO;(FL zJPxqyy1d%z9UhTc`#nD5c^9)y;?|{DRwKHpUI42Tn_`+-OpLXvm<-i2LAfI!#53)r zw=|qJd3Wu0)46+jm?#eq<9?G1mL3PNLU@>0(nlKZ?Mlwfd97q9tCQc?h2)^+aa6Hz zEB&Nj1#3N{U);mo(eu@7_U0Y^kFqG<#hbP+#t^`E_{XtNLiK-rv0C07VSQ}pu1pKE zjkkf9=|sqypN!A2ya|zxBWJ#SauO<;FhBQfnpOH zZ>%Nsn~NWRoZ0c8D@}?xNz~Kq)-^J)#lbY}cTy~962WZe_?YQ%0SQUJ$cyQZ(_79Q zTXPg<-kkvDErVDY3ZmkZfLmD@w^=l|5nE0Csjgh++AloaK(7_6%)S^M^=t}ST=GjY$@=3F(X%vP%#+~ockEb?=&j4Y}DoqY@L7BdSWEj1! z&F`3RTC4P8eC^u$+a|*YkVL7LqZ&ONUnf@0Vn!_ zy=7;AU+URu$kEs87ovP$l{FQFl_%t{nS@> z*Z}_r%ZK1U-g*Nkf-cljjRt zL{Vlf(PC+jMOzd!U5^BVq3=lk9Kqu0r-XY6fA>fO29&Z?DQRDeQJYwGg$+9J}0 zXy@GN|DuG0BEL3)_h%53-1^*w)={(Q6T|;YY2zmkk;l)33CL$ZA95Nw)Fl>syLTnj zW5;_^cAEt1k0q&|A=UQ2nxt<~tGnP249H z3qQ^Hv+ndXzo(m{xIDT#!T}xt&b?MSFd1g9(AMHpEFAxj=CmhWGt6wPEuh zK!)*i*q>sb#wNZ*mq1dC@o`*Si%!gc3Eh!(Xi(F8KHb`>tG(?B@!)VLx@hPxI0Ag0 z!|rtW@+nf|Gm_w57r+a+1iJ9QLF$gnPiXM^(pi1}Z1CzD&W6~^fZqZJapx0uBET-O zoq_w=@{Z{d5?I1ZpWiaVlIiApSci0Yc+bL+q@R=f{ze=$56s{u6Zy4VwLzae(0?G* zSGL9a!-}9H7RRD zxWaTqtWTL)A4s`XPZaukIHjUNqFkQrKkg5W0aCoaM*F=bCdW>$h1SM z`Q~LK_=pBTY&6vw8g$qh5zcRC5;k;c)__W8{*<+5=Rn{{+tL%Wfz#b~T1?~LN+-iGreqbkWk9%+7ssntBfq|^XM}y44 zpT~nPaXB+wq`(G3Qt*(+%pg1$pqgVpW>SXdme{&{;fIegDP4;g!{M9%CxiAL+W+Th zvfl2zu)TjAe-HX}2l!#7kuCUGG(@H*GRbK?Q)BS^4i0p$fCIYxhV)`bB<5C`A+FJ5 zkVq2*I}hLWN>{mp0xcf+Wq zQdXZ^z3Z~St9Am}RZZ8F(;0jcJOoq`$}EHn?Sj+b9KD%f$s0fvZuzS)3p9pn@eJE& zpRew5N!4DWj8F)i9HpE++2OFvAm82`#$*K6ZkxhwiMg0nOy?5<|Y<^!bWp~G|7$o8ZQRxJP)_ytx$5)=A5&M(k`3>m!5F$ukm4+6Z_Gy0m|vf~OcrcAz++ldfe zzcXEL8{)adF}B`c-fR2gs%kGKNiF*m_@X=x*ZcC^^Jq-vp&?!(cR-6gho0d4vKV_* zsuVfelk=uKXa)~TZoOf}s&Wx1p5<#DbEXH?pFN#A)X(47a0gTPfeqTLV0~zkz(}>6 zLdwu@gINMHg?Jqg;siHs(2~}J+7l|3kYRUjNs4uiFL9-V^OM}CpV8M2E*u#16)=$u z`d?oDtlIw!jUXof7aRa=&5hBY)Q(*GR_?xmCP+~t0&bbXdEO^D#Z%Fhum>zVl8hFp zyp2l>0Go#;kuj#^lO_$|;S(keu(jrjn#+l45g-q}Rp%1!&2zi>`_+XJQev35O&6Dr z#Xt+>SYS*WdDY5*?l(Uw_#c-qxz|7mjxhL;`)7L_#E-vZbIgT^PjdNZP)>9A!_U@8 zQB!@YZagwxmfM+wDjRgzNQ9DW0pbNW)9u3mH;23+R#W9@PjPFpi^M{CV85ZOQp(3m zv!>g{wwtb*%#q+TM*+c~y;wpDQIE9+ZnGZU?N_#n4WRPEh~!1jR;YxN8yHy z9e5&uA*OETaB(u*2>}TJfd70$6pp}UZ4dCb2OT;tSqj}hmv8MW9mHGQ9(BO27*LZN ztm`DUgx(bq|L$lvL$4LDp4bp1;7e7@a{(MaxLVZn!oDKxdJ1T)lxHL6R}1SBiyyDi(NLZ zpyOK1z8Jpnth=50T7)AK4yRzA-ZG|3O-A|4EmDhu!ot}unBtt}oi}HJHjs+i%7jl2 z262m`KJ*-{4~Ru^IPUBwDxCPhD3`$#%&WydHV7}l-24h(@GE_Oz6Ucz!|aM3{yX_h6Ocu$%@2!r_?yM=9#_zVR;D6=); zGL$fz)@|~KnV+vbqi4F9@Q7c0*L-TSLOkX*c0ADMPLh3Otqx2uf(9UphaM(;79LKkj(IhmR`C5hHX>?us4gpD?j_z0<2 zr^uGh8Jn&&eKw7|BKj)v|JI3yV9k%qs&HpchjZD^oCE)LTvQ_WeX8xxIqBcL{zey` zrI`!?`&={OVmL;3KyYC~%9gGkaV;;84p5;+h6_j6$V?7pDOH35Xi4nBT3j}Q9wPwQ zGLnJD(I+2W%@tYF4ym4CU50xM-RbayXfgw9C!Dh`BI>yHNbU# ziY#lc4_!jmI>k`%VkyPVXyZJUVqC*-C_Q8h*}F*1+_4HvKdAhbbR0^sT%#hf@Zjqw z6N6xI!6}Fpx!J!~tFMErNtPT2%vLKXC#gN=#m*yz4Bew(ZXwFxeJ9Z~j>HSb#Obl` zOBw9U0RH)&#(lCG%@gAz68|R{=l|Hop;UBlVM0Y*0lwr)`98b$)C4*Y<(c!3Ph7fL zs&VAw3ybu>SrR-EQU?lH4IEZp+oX5S#7egYx`R6MNKcpXj&n7<1*VEHh^7@b1MuUGizv~u@iq*IQzquU_?wCHmVw87PtLWc{gch?dm=EL{U7>Nw=^Abm?ISw!>FkVP zw~4xbgp|a*1yewib=|54n%M>u{73XvaB9EKib!f*-e9z@7T`<=5hn%XmG$bK=AGos zt{0Al?I`QmfH|oBl+_6~Z^dHqh4IKiF4_cj+w2ZU4-k42A)l%}5`x&ikrq)F$JrU6 z3m-HZEYWr-yM-V#X=Zm5c*72N!(!7IGQ1*r?p1rw@J=9iWz6Emj{L__Ato8Y=Qwri zB2Q6_Y!9d|L=eJysZdebnaWR-s4u~ah8$T!rr_DsiS?*TM*OpLpc36g-x0q-c-J}_ zE`t5T=pRdt#J6hYyr$0AM>==y#XQk=#VMo1rLn&Le5_2Ne4enPZE=b?Yz@Y5#vEF+ z-k7w)kqrZcuQi#+tB=)QT@8}fjtOjC*$!yHK7EEObSf#=mP(?#|I=}4V)eF=y@uGb zi4`UYvG*aTrFARClz_66U9z33w78Bz-(OZ$B;J7nCq$y^%&Qc_eLgiq0OrneDRiK) z9`<~sma&Pr27%5$dPtD4qtmfAStHmph@4Oo)(I~Pbc>9?v+H*aCHWpMr$lR1uiPaM7%VCo-R_iu4#RXfZ*6y{W*c z)(eIM$Xr87bsFyUM*Y11$Z>(+tymSk59ZXijs9b9e4Iga z%_>H9I}pBj`8jicAP!2@ZnpSVNU={^C^hOf@8H1?XP>Jg&IwYzsTUUkbplHI9w=kr@B7?i5*$(nkk0V-(%kuP9#<^s^OA?^>>%JJtA%!74s#%SB`ANjo+yrI?5mS%rwYa|%1 zgdB&BI;WPE>y$irecJHBr6wU)IRZ^j>F@*0Hr49fA%!SQh_4vd5sQ=1=t^zS!cuz} zE-4?U#c9dx0cdqA1uQIn>yRZ*jTISEpkqQ)QEz$|z~g<~+~{)j6MUuyd0$M|13r>i zdKU97jwI%MBZlG=iEt3`9;I&6tIym5vr^oM-t(%$ufC^4 zH4jVeI6VChnOn~)t{@^S4}ZK0JK@QkWN$c=(ab#HsBnW6v7S|wvL zs#8w+)O6LazZU-vnu23H*yo)3l(tIHv%qW%7X)Q)!qQ*mu&1lt=@{ahnsP!i8 zMR?YE6g4SZX+@F-r&c}UqfgH`VUh!40S@7tq%?N$P)C89^@1!kK|1K2rMeCb-t+X@ zfv)ai2tIbi2)`Z(u#r`c@OftX8K|{#M9@@8XBQlESc@PcuE_X_54qVszYBT%J!u(4 z(16+}u?I<;na5yX2zPNiq-MOU-(K-y=6A8JiK)YrKTa5sP4ZVubzQNLhUr7L+o*5f zb$FIq_?9MKGir>(m^|6bW#o`jl0L_O0RRCdCch3?82kO5b5z-T^9ZF6`S5aPW`uu9 zK~l!C>=oo*$JWpw;^KdZ;T&Ks*{>m0zQ_aLZ$X76v_S^3yUFe7_P(nXVUGO~@apZlwq-Q>Iz6v_;u{Ricv%H)9#W@erO)NYxE?tb(pYOn$gyUz5HD{DmgpR- zp3FNka;S)lkNg!&CNe20bZQ5qla~z@LZf+HD}+{gN^QsR zhg`b&^L5-Phx7^O{$#1IblU$E2L4NGQ?Dx6?l!Ac7UA8kh&MLYfZ@z3^^?&+Is@&&;B*Wb@nKuMZr-kF zaGirAGku#iv(9q~+8r1eJ|{_s`?1W8R@x~`2+{P0q|;QtO>wjNG=bRT-u0D{O-+pd z3Ta3{3VID;*(HFqlRTchTIw11*x7xR$uv(RQ=(1-{9d38HAPP!SR$~{(00D!NE0Uju-Q>@PX70KH6$j6B{{e!M13+&O*}8{-FV=ss@zxkMz#X?Z@Jqp8n-S(lX5~8IH;;M*9lnHqQ zu@_m4(I~v*ysbppmqy}amjM={i22n}c;L04#C95}G+w<_fS4K|hQ!Ad^qsYtlBD$b zY*cuuUqe2H~5W-gPvP>rysmV2((3E0%N2zN*7|aaDz^!*XT^@UgWurRsm;iy0Ov? ziJDx8iKcM4u-PYQJvxqOZ7`@}MO43Tf_x9wnpRX<0%%A^`#7#szyYS@*-(8n?WWxV zsxqStQ=zP<`4)AbS{~&TAz-Fv$lk6kKDzrEl)|5McB~rdBsUYwn26sD9~E&TyGdaX zetR41tS2)b^z-?!YLg4=A+x2Z`XGX4>Bh1fS;Sr_AaWNH7wiA6rl_(WRZeoez{wmJ z0}!-SBAT|psY)@>OEUgluny#1K+zGPZB^9t+u5!Zsp8Fx5JAHO1#1Yzh;**5t)kU#ka|7;E~zdRC?*ZV89e*r|68W&8*eYf`h(N+ zU9;OAdtMH9#`3$Pqp*i`R8Q=YW1npsETBJVS6u!Leu>;x$*Ltro}{~z{h(tL9?2-J z4ep#~W!5|H%Y2 zE8`fHfhlY0VlB)%Ki7M#c;|UlCL`<+OjPl@C8vbc3c(!WeB&*_{?X;B2S(u3W~@_gn)wd=k>(s8?iy2Z^owj9u?kHHIY`h?i^bP_vm`{L^gC_)5ZXzYSECH-&^+rDOZ_```6`oQT_$V!>eKrEYfK zxk2ZjFrMt$-YFn7>S8;^Zq(S*P5?Zi{kEnf_4Cl2fFqOKb7M!`F;EIiN`0yUDIT zxMDyI{8cCZ}tE;2Bl7^){M7KIs*^$F1jghAL zG%&7Cl7CANnc2>>xJb#;tu2SZT-}}CT+d@J#0MjfJbb~DY^ zVAVubKw$|4A2M=UK#u%eQ1Dv53ZhNm3|&{wSrE(|t~y~)$+Rm;)sG*Ey_Etk;1BJ~ z&YgnJYCJq$hdCn)-;P1cI}eS^Qi9>>U7r+;Gv$|ryZ|Fdo6?FfNJ|EAD-n8jcp6g)}6rzMgVoDe#N$~Po z9sDx^b@%QN0>2{S7iUfYfiBw@jm6cQ&>cRFD?a#yA_;XZiW>^p#6rMUbMIAn0R zwLm>>7&+^DIrch4P|b1`3ARLviUr(xx#(&U(Kn?K9) zJC;M$?Au5Hp`=hDB(K&{B;$l}euP$IV;=?@YpWUnJwU?0g$uxf%~}hD;Qa!68+^@- z?0@cMsOF5RxNzrGDq0q)v@Twq{B9J1jk2AWEd1qLK=^$ifmOdahp`MbA%Ux3@s0W% zl$F-(k{o4$9(`;a87WBy6Y{;iLT8B_lAk_R#gG>z+lkEN$2SDKh`>~EkiotOuq42* zC~Ql7Mpog0@qRgfaIUyG z$tR%Yj)+9z<6Z_3SpV-O31K#>s}*-&H38o2-_BBhV5KJ4Z4glx%I{oMqK@nvy3QcJQDedcO9J2^0Svt zR-gh=uQBfw+z>Y=pLeBe_{z@9CjW5staxl=1U>k)$^8G72y@ue44|C$QR9JVvEgzuff8$yEN+>uTCoUKLj-Op-VT(Ymk*WP4^i_-sX%}7K^RJ z12T%jB4?zvCOXgt!A6xk26;!7s&HbcK%!j5YIuiK`Ee00do%!f)b$5;OZN}$j=eLf zUlJ1d3q4gbWQnX>f_{M-(Zjvy9Jky8DKy^@M;WphoCy$&$2~P{L_1Znq@L6$*P_7k ze;&pJiKe%>nJww^!sG4r#VIRuZ;Hcqo34Z%H$d0PB>URO%CGq6{toXV#Op9{CNnwXpfN%-(3R~I@3Y!R^PVHh0EkX$i z@{wIC2mee0v1KC}c`|4b{YJ{l{5Us=o~@Bo{mXWA&@Q!Xylgq;%5nzL;pK5c;rSKV z1yKcRHGvb(cOAx4oWG?PMr(jDKy0Yp-6%~Li?6QNP~Phg9+!cdB3NlEN?Fja zV$OPk_j})O&g3GgpaN_=q39j$SK9?KMJ-nF75gWP@q=+ZcNzgk9d840TP%rah-)9s zR)L5@0i;k-i#|tZ{9I4fD-N9S^_*|FZ8hluO*Zdr9EYJyD2Q;uc-hRK z%VzO#E5nbtL+iP=Yv=1jw;1;LcYyRHD$2fpLX8rY@%eLDsWKe&lKPh_^yVa}z{j)g zSYQ-maGrsJxLsFt3ut*~brmi_=a2T9cn&7FMsQv3s|p9Q7yydU{~Eo@TYTvlH8i2O zdDRf1K&5$3OgckF-GCj}ab@o|+nVDFX$McgEFpP-Kp7q))*Jm7Ilfju;5R!xq+}_n zUayWq#GMH-t=~7M6L55@6}bpog=rXQqPA8nDR_{izG8(<=@4e9Of_44#{j5W#>wa9 z8l1%VV=|AX(7mEX47jj)4ZY(L+Q=B}pNYKVjnrr8lgwao4MXw3agMvi7oJI#LZeIj zoMa|7n)%B)$sr(UyloJ5?K569TiUtwcGg)q7d7{qX-`j(V=-O9m-LaC`Q6cpz&Z{z zzPBVL(qK=vz8WsslzV`rdmb5tW19Bv9)3A=>I^0tA58VMw#>!$ zr6P*Q0CDBb(}f>Ez_w>TEkUE%LRdnb+OUsVJUC9t^HUVRKyu1QQt z#{Fxe3&KB?2ALh*0atPBzL=V)_Taej5}P7lorf!_Mj-yO1nB+n_Dn8jV&U)?3mokLtgAa=$d<(~hi5 zB4`|BM2`6f%NNd^{gCd^_;$sNaNT*g@gi9ECCV=^j)#V5S(>#XH1*?--|W99Jdb8# zP=h%>qbVV}Vt2pFVyD?Hu$Imq;lY7^j2g2d!lR_!YY%5SLU5wHSefSb`%)LT`4i=b zw2LWX`@d?&0KrtpWgI4{!t|(hgX0&0#L%peLZaCERUC}Amb1k|Dqoqt$GRNZ4^Xo+ zQi^N!SnO)kb)-Dv3NTs+)BHn(oTHlzw=_Oq#CF|lNR2l`fZ7ScA$#`ppDiwP(*ZHy zC9z!K_GYlJ4uaN(=iyassk3;aeB8d6L+L|L^gPJpL_m?8`P7OP9-})KEiMPnX%;Jm z2Tc#F6X`sacnN?nmFQvBJAtL*kw`++o3@BA9vHI6uKG@(u6X1K!fGE^e?KYL&`-{S zHd(^iJ-&dEComyuV&v(_n^nqbx}rA0A31wo04cT#1K+G{6MbbP>E<4HM`|U2`xvm#Tf3j4(4FOwaqa*1tAgPbR58KEEOTQX(z4_BYYy9UT6ndsImbyA-41pf(Donn))CQ&MURQ1KHj z<8Xd%P#@xekl3#M>^W3LPw7M`*!Ux!=1imP(pE>d4coypHxe5KwGMv7GPwo@qTP9A zi@JTBM=do+973W0b4N{{!Fy#?GU~&4@S6ACJ`WMux|rHtizK+NlK!7m)h7JzQKKr# z;XTn619lRh)#8Zk%ZI$&y3(s_lUl0&|7gy<_I7mh<FJt(y$ug&jOC|S%8gF<;7g1 z+=+C9Vkbwe5lq7D$wAa^y`JYA;ny0^9qq2U9u8Gm>RfVt%~cqH5`j@HU#aNMMTz9g z5s;X5);tUuZ+_w?1GulP({qxOO$$2u1&07hG#c-WKzuCBrX===c`l2;RW^@0;Aj92 z4sQlmTt-b`<-Pf(YJhS&|4Li4gWPQ`5eJqlmSahz%iFkD)Rgxvy>9_^!m-hO_nv%o z!2SKM{ao5Y%`47W3oX8?P-2np8J;_S`AyApynjkrZ<{k^`m(r44b21LzX;y}X%C7* z*S_ia;Nn@CX74eCAFAcgkTiw#bg%YvbgQ(@Bkblv%a7ZWaBnKr3ZUCuenvD?>$7zv ztXU#az*W)~bOXDQ;VHnr@7EDkDO-loD0!(DVh2<2afcpj=qnE6H z&41dzfH<;d8vDOy|D6t=;xu^T8_x;>M6BReB*gEM{H^P3J)#vLn{paA6JGCN04jSF-R^I&6V!nh@kg=IPiP%iHSX zORJfU-To8q{;FfeH4!|MQ%;;f1!$kV5S)po1=VBKBR41J&gB05MLL%D2h`h z)rF>KYeW*wEH7yQ$45E-aV_y8m}iJqZW`?3{|M;#)-w9vxu0zy0vB_fVMb8H_wJah zToVatq{(vGjU}mBJOC))GX?s+C7!GL%Wx208$v(jzuuhVL49brcDA}|MoD8>=@c|i zsJ1?ga9w_Dh3TE|dY^vYp*b`9b1L@>YSo>5FPS^GR+iQbvh2_QKkM z1auht)Sa2cbQ2a1EzqjyuBD2Jyo&Yh8`EgTzM6(^C5U7PB1|hT1pzhImOE)6>RW-~;_jw(;Aj z`dcjt-$9AHWf^mKTR*Dp?CY66>2V@*CTId~{BoYrpupp1 znU&vLX`62f=6D=#&(dvIcdP1=SbaITd^g+tB`l8$)?r8yrGo62o0#;ro=P+vamCN@ z)xW%D2}8OboWFTFdxCn!v#!;Fxnv#VmEW)lxbZ3z+(a@WrFG|Q8zhTjT+^LRd&l=a z9r64xnutQ+KD;f97`=}6Na%Y*-9-=mK%{JF6qzcegECB5*>{zs^y8zx zZT3n7;mX?0dD1o~;QaxX*>~pHnx}#G)|Z3)$ARK55h<>~ z?t>%f4h-U?k-9MB1`Kd6pE`sd|KB>GW4i^`mqEXLkI#l+#>b9SAL-4<{-y7f@rTSJ zr*0l7^LHW)y9p0({N>&073dcz5+@Csh%1f%$AK@WbM8`}mT1CzUHpYLMstbNrlq%; z3)d?J0k)TENC#|GB(rnt3lelgbSk1UmTF!f(i$&|z8P28Zi`p(n2DuC0Tx?%ztQoI zbRQL?x+~p!w%f;z#Z;PBo3UFki7uZ*o-`bj9{V}0{#y!0F_6(a9g@X&*z)qsH$ltf zLq*%X`mIgO9@SJOPDH8V@384hPL`b8m`13lX)<&{akyj%u1ff2O<$o6U@@9Gx_LxC)Qc`&mlc^ zc`BO8bjzzyL||N|*V9G9^fsppGco~lxoy79iAV|bCGk~vIUfwJW;h*`7r~h8;;YmA zxQLh3qf!%_8{8P}(8Q;OZJAHaN~!2N+k2;Phz$27M5gqgwucK+r{_oS+VT0 z`!#yMbH)O8^I241DZs{mb_Ie#9iRIfPHNpwWtJI_+3{juP?r_?={(^tE&>E)e8&8a zS(*E6_u;qXf#b|U&z@tzABCc#6ek*>W}VbZ{;hG(I>cb8Q;sw=E4oN|5Vg4fS1?n=F9qin+QhogV-} zZu9VLP-9IXnIZmVXHrLlRj=0^ezDph^lJ$ECA2Zaz4Vuep#>zueI%`CEx7y!p4iV? zZsjO@shSU`!zsu|u{eRVPY&7l&k&tv**W=KI3@}vD6(hSr4^NWkxOIT22`o&CV zMX$>PO5ZP9{hkUZv~^g5a7TE;Ikspne`r0lAyqB$n5_6=<9TqL^d>_T(6SEEM>oc+ zDlR8%qTPG=I_-oOQj3y9SOO)5(+z1JmZjW&pfXE>2_n zCb;4$NO5X~pe{$VxVui5P|<^*Q4%Ajq-KkBUnq-y#S6uZA z6icxv^&w@GPqxzfztml<0DDY*n=I;xZY?%01>GM$&^EkhlX)3g)e3E&>ZI*7Mb~|r z^i6{WFFEe!ZiZrAL+--*EVOW*O!|5NuIru_!31_R*I3F2^h~}9v*+#FETd68TABm6 zK3v{yrd&mS84P}8T~Yf8FvNZwbRf@ctOuSm)AuCT^^0b$89lv2FV6x)0leE2gc8o8 zR+l7!3S^}EHDDP$1}O3OPbr$fJ)F!a^u!h|WW})^%fJRWi_!Eku6NsY0Z3&xdp22D zkyd+4(gu{Wq&#!!(`V#2E3r%Z9r_IyLa{fPJ(CrQO}(jTyv3s~`jiWmlY+W5yjjpS z?*QaLfp>y8z(=@SZhZ6|?vXT(@V6{Qr!1ny)<}>U;IvePvsi;}pQqS00*ozdrx;2l zvM7)uf%IRoAF0#oHj(QWG*^qE?N(t#z_Bqw!is7PT)D4ROr=FQ_tMSTXV0Al?B~&f zU0771tVUS^@G&L(r4Jls_|gTG`l>I*F&iVO1r$#MNdrsrU_+{d`O8|XfEH_p^l~OD zn9$>t#KSsP(JJjJ_w18;`S@+C#X0WDp274vR&|acC&xi zR~%i*Qf(=FP$>t#YeUzMUl;#-U z6rlE5btb;NgAKypjA>=j$(5?os5iea285WxDlw@XjX7F>@IlG-%1`449H<$vS`a(U6bms6V%w2b#=`Y)0;4$RGHx`U={^6H#$nzS(y2jOKq zNGA}O*k`o$tz!D(X92fa7jp{g-e-hc1)llsr!{Tk%_At!M=(oKLL!o_+*8#ocApb# zHmmiO&B=7>lzGJu-vl$D^R!RQ6^U$7@$L14zu%*N7#WIzr!O$XSk}y9@J-nPm&NF< zNj_9BtYL*6;s-+w*;T==egAcZxWkRk6!PK-n)VNxoeRK3e_L&h21dcR`+fYE9-<*W z#Nhm?TsI6Ul}_90dxz$A)kt%xmX^agi1(Arao~ib zFRDA_TS3k3%()tGnxQhu;!3^n%-oNi9R8~eUkSn$$!q)D)?@B-4SE6n9a8-&frKFje^3PN!5y3$CC|B{0`tf z`0s3p=gSRUde-9GEj2QROIuxP;oH%;x2sB`;(?gtM!v_4&8Q8nDJ6tbU;}6QB0_*x z%O2uYUw}HijU*r}-Npr-WP!qYAt*~u8jmAuTPK`|a#Q5%enGpGwH+*Ql6?tR(3R@) z64k$5eW7=$7kO?(xyd)zvc8~@sHt;IwA|a3yfGv1=59NXlQAFpWhuj;)iQeHWz3}zJN7^^oGN|jgMaD;e%272yL4i#_u}t zxIVHDp2T9Q&*k#yx3hy@1xIwHa}a z(#q9Bf++Wn|4*ex3MlcFO~Jhhk1smMTlVdbkQrccJTSBrO-z(0&t+6O>@Q0{6w~&3 z&{zENf(tG*ex}AWm*(&xU{NYvdLRU&d3x1PQ-;fiBG*mXApf)&ii%;c;ckK49;qW_ zI%KY{z^}NqQ|%brXqO)ns}|$=JNI9baYR5U4xQFO8& z2~z;l6PII;{c^O?@j_Q~20a!iWPfk#!Sfp%B^qD!r@?m%Vy1PD8=&(mAJ%-=&nR}_ zQvseYIU+>hIB4^3i3jY_ro6bXn^=7Am8zz3wdZ5~as=k&C)f|NIU-b1$(~;Y28&XD zh7De;bj|?ud%OnT?7zzqvtZYCuzJgeVfrSy{i7{4Wqtm%$TfPbom8Mi+bbit96lI1 z!LS5WKx(<+YSE8xTP-(3G@;vEht%F~lVE?Ia$J-32-mK70t%wAw-u}Hw6pDpI}Xen z3tzdnFy&NdBAaXptU;qEQ&LOc4u%3!q-VFpz;ej)p3kBJ))ye?UOUYhQQ$;{>VX$H z%%$)PRfY~muWvCk5)Pr2Ai8Kf76BO%9)}ok5DcATRVVk>F%#Mh-jI|V{5sS<0azrHB3U34N6>o~5E{_%?dS6fac?hM zy_Gis{9xlYkMY{-zrR+YM{_FDL`PULU^-Pc>fzRbW|yq^lL`6jz&(XTtUp3yq>pY; z#p}os60pXLTUYH+lrCza&&9( zU*Djc+T&xz$a#N@#2fDV)saY2RWVi=q}UCnvWeiR_eOzeJ>#z}7#SRhq3^0b0J;O7 zl}+N=gfZ_9h%6>_tv3B$Vm9IVPY*^|-OC(r=#hPP{rc#Fw9GL(g3_oCpxJjGtl&^X$jB=THqZL`} z0oReJKYn~JQfsCX8lDAIkv4QWj56B(Np?lJduZvos;rzh=;vlxPbqlxY>E(`9IQNJ zY=u>Fg7X?#99*tmvW=_TOdF*ItAUNKJ?ws96qk6`R{r3mI?IiSD=g>)7|3hXVdvS- zgjEb$=*?HVO?Rvthzpb!5uDpo^%S(~UYubmWmPexL07qTo+&2iNC+Xa6~f;cq{#z) zL()pS*}-CZrQunODbdjw2g{xC9zz5IdUZhx^&;H%cPpQw_Z(m}NR~8o<9lDN6KrT? zE!ypoX=iZ^ffaxj*_=_r@x^iz9xVW^1gq?*GCs{W)$7AYqv7(Xj! zS1j;v__!^cPq!*6@2nGFBpA$K0GKf@r{HhEG_TEciK;r--!f!HN&@D11Q`52LTIS3 z+gQ1`67_dJei{ zIoKE|Bj7tN49EXu)rhK9-^J)}0|6&W25d-9;ysb(@8ARP9!7YAE82^T<_vPjr_g%` z`3c|%P=?}$Y>SZX7m(4gVjl=4r|Nim^o0SCp*M-4wJSY7^+DDT&qZd#6WKqP2gEMs zUPxFqp6$GU(n3TCYZW>=!}c|;lJI1te{ zN|Hw(18g5$O+>mm%jE_hUXm64{kyQ}CKRcq$KR%;le;iR?(=%-q*Oer1a7i6DYQV_$nG@j=8kn%-kr_4ByP5GpK{o!jya~Cd8mD z^!8DN5DOjQ_l$HF&UAnYPhbu-|8CR>5Bg6T^_|^Xn%S-NcMZc%N;6gujBCOt;?UQn zb%s}%`!9DfU=McmJ#$XgXF7a4&T@;hfQ96%TAdY;c?3ED9FWFXb?a%N3;;+YmptvA~hNisBM zL>wi72a=W((tl0~zyN8(&e=mcFr4m1iH1dSpDhvJM36=k8^&0gS$=vOICe zC6p2!KhbTqM{26Pz({ZO)i9TB)4s3Q8A+=$(Z>4ol2hmHK|~1(VqAsIZ{hE;tOg* zADtM0-%N;C8eQW&E=`U-iGqeVe}2{0BX(BB3djSZ2+P~YP<#U52YKg3^p7PmlWh&b z`E`<3!RPf3MfsDRYO27n0+R}wQ`JVTdNTYA6*FiDoMNv8!Hf}SpwrZSO*&iSr7s$g zs+RM|=E-04-w3^JnLYf~Tor?a0~JgP<3W@<>ic#NWtB7xn=eF6Qo z8Ya|U_=y6RXnJ;@R0vc^fuw8M%yC|-Q`go?U9L&Q)8xUo|0Ys08F}$89tW|!jYoT* zvY*5Wd2Tl$c73|Io{NZXdzzCnrifVJ1Q1vjBSoq)REY!jYck z=6bUJYKj;(sal3<0iwt-N-_Kal$|30Qm-y`Loy9h3tLozu|on`Bz||g1Vy%!VAbJ( zAt!(CQjH&cv-{)Iz)w0EIjv}5BFB79&Y3z3JKzHk6NTmi8sR1u9N z=z5|kq)?`&lg|r#Bh+Oxo@o1A@O!VOtxP@o@*3`LSj07tI3H8Xs+I!ZLzSBjg-~k2T)^U$r)}A5=dNf+i2Ax%=-tQ2qX$<1OjLT%QGx3 zpav85t+|=_!XlUj$w9~#z3L!KwhUY*37kXx!yyYC9Hk`)T#)Ixjlw-8_2d2P4 z`@4LXSUn7Mgu-E)n$?tlGD}T|IcVs|*CLp+7DQcGuNB{(bCf6Hz;8t)U6!1;0rFE> zc*<2B_|Oj?K#~(5DOlCav0<7Q$jQ2I15&4<&Rz?^wJc1*gUM(xte=$d^&085Hs;2% zbwa=`jY@u~(>vDirpfRy?Ch<3L@Di_sFr6LSDc{UWdD&>7)5{ZU_LvbwSV>OU3(8N zgVCX=dNas9V5rE9cF#12{f_NcIxl9tus+wh3XLrmUZGdb#l1YepcPAye!~JJh*0N- zHzll6+}d1F=Ho4PMl5KXPtmAlGcoU()MS?{3rUJg?>7wHWhR!Coc3GVzMu(EEXbSn zM?>2`)hIoqJXQa-I|(Nw4Pi7sGxmuF(T?RwRQ(ECecJWl=i6~6#{L%7rpnOh>ik>+ zE1tvqpn6K(Ul57v35yRg3e)-cIOkUd)S4qTVqqgv?BhyhmDpSF%aH3zF0>M&ye;}k z>kkQUph@+oCOcWeRorvbJixO&sXk4>&~>Y%b9<-CWp{ZrIy$%VDXKM8wWqkz*gk($ zhXYEJAYeeM6=P$@Tq<&Tj#wXhS3t>knp2;P-g+T%!ngE4eAXyft`n{vAzHOA8oqut z9FI^N=CmVv6kCiL9OCnwgj8z62CTDby5e7gsrBCLs6u!lVS*=w6cEv0gm=MeWFd0y zWCjs^#;VTBsSk$gUQQx-gV7ToQzl?N_)jJg^f^4O4DQ==c#K~H%+x7cF)uld1Oe~5 zldqeidvzT0w}C+$s)Uz*gYS3Mj))VUUMnA~q+@r)8`WCgW;j*(;mzs8LW2vwu@2!# z`X^qke40@UyoIIMpNV#E1ey8x{sjlBQ`%C%g*Vq8X>YD>xr^Y_Cf0lSgbzwAB(dF)G|U2 z4w(ULQj)Dw+fd!rvYkt4B`%e}kt@7u;?1f?qD z-1pF#?ed=*>6o|N_@$*+<9{VMg&dT`S+hb(uLu$W0N(KAQCPHa(8BLVTbkan7 zlZcTJ^cHmK2m+rB{a8xJS=h4Ukslk{pv7{pDqak1&7l7k`{op$KD>KCn>iA{GP5zm z+oN37G+xtQ%dn8K8+3Af`D@tSfa@qHa6N!fIgtk(LH}-3iKlxZNX~}-PBA77nBW!Y z10c1rcSEFdaud{2=uoOmIG_XEpi)AqTw|+9=5zIsZ(106Q$j_=Ok}AkGtMb5HyR@b zVCzNlb<(3rgKc93N=qX#JK((Ygz(6}fB>X3HyF-LXf{5)F3AsaEt!`|eTqW9ut&yJ znZs9g#E(uB!<@UkJb`TzL!5t$+6+<~FBJJU&MKy4cAF82bw_M|-B^gptWT6q7+xp4 zb7IHjsGjDMKP5|hZ`cG1u)xBHcVD04Hk0@G7oq>hE^+bQuL75n!5@dF7g^rC~xj1LimoXZn*X%8tPj|UUIk!HV@r@*|C!ZFfwbr!EV8zRxMkVpZ zBl$vVn6u+LGj?wGC4I^~M=rK+0K9A}N^@8h@{-#(e{q-eCFzwY-E0_m?fAqc8NbD& zyoh#_qIwDs2EBTqG(-4-qvDnv_2&B+Op6BJCZIUhdxG|(4R{6Uea@~j%j@Tx`4hCO zo(+iVE1$f=E_r<-Ni!9{R$+upDY|bEM7FhGgB}BjBz}|jLW1}QbcQ2MwD<2j!C0I% z)P5+VccsOaxj@e1QPYRSB-+;aa4MYpGJh2gvDnI+*P|k_{|Xzw7SMjY&DRK735cht zXiOKz)k`kStW{KMW~937yC$wDJAIHxUxAQk_qi)C{EIHST`kU}WYR}CFATRT$cgoh zK%qPV2c$WRk3UcV?lvm~xZK}*Fd1F@C~*366(%Xk_rcSNO;engj-fFS`5J<%R>^F|rAitAd@Pw)L#VRnp8tVqw5 zslkZX!&dC7Y9ENgsPptM$ie;7mk|yUiC?pF5@SO5O;0~z=za9LP_z;xPT5U3C*2A+ zOH53mYKHRl37={5eF6 z_MaefDUqQurJmKK)`{V;`sdL`VG|XEN`gNa00@(*jgGwlPold%tu`@=F%6yy+#`c7 z^ALwuRK9vxciav}5@Rj%{pr{$HA0G9+t;Z)P8rn)ib)ST36YQlx=oD}yEK<~iIm-eHa-+g@_Mc6d}U;|R}iVArOAky2_+uC@szr=5=VPGuVNL7rek=v4CpV(^& ze&drA_`oMG$WrGBz9zc+b36WK{WTBqdRXKM3f#8R>hPBFHSqp7d{6P&t}DX@0OCrM z_xZNUui5c|=2J6$i=)FPndzoEJmo!(Oc%*q35)}j6_P$?7}U2l?z6D;w=y{lB1=L*szrG(hqOtXWP%;CcvChq7?8SLJl+;nu9X>bSB4d zAy3Q4Nv;$Z2dAjN!lw%{N&ycoQ_wBFCZ${^#DRVTfJCR2B{~(+`SH zN-(@fZH5OBbGwLps`_2J|MKCokrfv4h+C!u%3B^*b=(E*AnZ3b+oj9U+L10x-YCEI z)IBoTd!g>ai+Vxp_`!CC2wJN-_EszSzW=muDYzXcb2bsZtrbN!X_fxnaO;Y^e{QTs zpTj}1ABYDe;oy_IcwF$FQRkp?UCA4fKNDz1-X2ReErERMrZG_c*(1QSKg4(3tFIe} zy!199jNoWw#S%r+^|%9pz43?s%0wC6Jc#2rLy>a%cEuIFF^|3PUr053V@j~Z!nv(& z`O-6;{haNpzuUF+hAi@WTR<#}xYxFN|)NZ=Q3nD%G*=&KZl;db9-7k8l8nZ~6k6SP%q1YZ%p% z&B!b9wnnvFqv8XY=^-5(g3gfyBzJKehK?ejzKi15cm{`$Svwx@Y0Q>_JBkw}WHC;e z?9*otO&AjoRbmqS#h!TnI+`fyW;dvS#i$ymj{Qvt-a^Iy2wyk z>2d-i35=D)#4OI@uT3m2Mgw^?>9~|g> z-=HVu=y&&u-bWF3S-8g;ou@dl#LE)$FpC5U&ujj)c#+n(g)I&deh)&J7j@Msbh>6R zPZ9E&sME>%NsWCkr`=IM)=*HpLukRs+Tv_nUC=q5DY#e=NH|++TvbPoB;cqazLY0MZhlS?s=CA5$Ye_#y3igD1S^WaY_4A8}$2xB|rsY@CBIT0My$|!|zI>6$A zngeC2M{#^nFAc&G@MmM@5RNhI%rSre&j0!FD zUh6fXsxgw~KWroV>-$RJy=U|#_+*q8j5u#UhSmrR8gfARv;e=t6W82>$qc*NqQS~o z3Ms?7+g$_UTolb>m1@NHh%SiX|v@dBS-Sb!b@r{0&ENta0q5aJ2)s9(;+Miy~A9F^FV=y zp4kskoX8;U%6s%cePFZW!(JRw?VCWg9lK*=hSeYoSa;A-X42A*S1G;?%y+;k0MLy8)~YvtRoFB?jb6V}ak$MtptOhJPl(=__`bKBm1)_$4mNweXEk$) zag#g=7Dw5RcxfXg(uaPiA)#!Q+!G1i`+njA`=33=o#cNs6M^LhY**B}o4kqJ31*1I z4yDP@GeJi8!4kVz^>=kLt-MXGSP;ve67x0Jy&L`ANe5SwE=mna5CH=}ZU59OtXdaz z*zc|IeL=_5sEIQj2!_hwVh%G0sNQ+d`n5yg`jF_-16ANSO^?B~J~bHeff}>-ui9(7 z`*dfr#lH6Un+OcQ5a}hH1q(Gd^l*c!R3agQ&X`&Fqqv>f;mS?&jYppa|E$|JGjIFX zd&Tx>A?0)I-a=&JCwuPiN$|t#^$_YS3!eZ%#t(?8N_NC8dz(hS_OOmiVy%EwCz0=a zCG%@_Qj#6ys^}9yzn*mdnchlZlsw=CuwJYkz^E4bcUQ45O5+umFhuaQz7{oMZdQjD^e?otp8fA5;E9g+u&? zejd9J0VPOXVex{Tk~HL=jfXJJIlztaT~UPlh87ne`dj1=tk!r)I=)rLkec9mW*l7? z2A&I$ut|6L)aMpK^-`!B<(p4m(V|rGNaMOXZQr0oq4xCs8X7S?sPQS^FrpWeedJO* zB(4;4LQr9EGWUPzCZfdlPStxB)I=s1(7dzSTa7P7wBb>j-O-zQi3Rh4e9~@=$2wa2Ym|Lo;~W2ZdBiJC&J`E&VCytD70|-8gSU^U0UwtkVtZM&{XEF-LbAYef*{Iu*&z3+1)&&#n?w4e?N^D{X_3}MV!V%q|W?=u)z&VS0OpPJj*a0KDtul zBGZs4kh?d>#pFj_i;nvBw7~}@?HnITguVC^=c2O?L+)}g^1*ZV|K<|}44%TB{u2&#U#izU&rnfd_nL5ZL zFa2g(*Hx`UkYXGVji3rXVq%&ro|Y45kU~D8@!rwJZl&q=ER?+jk`7`IOJvLk!IVZn zh1fHSdkoS_#al~U3W5t@9ygcj&FDSItVF$3u2_W5#22%wj64aHJ7`uX97B>`Tzc9B zhQ8pLd(BnmLf7D?tlbiSGXL1uGyaslv7f8nrR>J8*=b~e#^zs;vXV&AWEI@u}pVTjBunHe68<~z`v5K<+8XGQ2dbSt8* zUV`aY{10ZU2IxoPPqcDiR=C*Yb;F7E+E$?Kvz38~g^uClUtz4z!3|k~M2M{~Y0pr4@SyvePuDR?vy_U~D{Wsn^-~QMKnEd(gmrF82ix$Fa z=ArK+ZT4H4HnPZ4HJ{W4NOj!y3@Uml+wJDhkWN}4y&CpQFjHtC`AF1`Ur z8`E2Gc7#r3^JyCYjEo-&{S7J4x!Mo_3d{P%U67ukMZV@K=Z0Nc-JToTl2}hBis@f4n2(iK~55BSi5! z3Or=FMI$Q6-Ic-e{KElK(}CYjC5My?>_DkFh46~vH?lxN`dbgMDe*IJ4Bjbd+B<|;^Y38@u1 zU434Cxi7EuOt+wWR<3OK(!@9jv!+c-8q*Oqv(P-YN3WJ$JgOb+uy924qngdj8=;`` zj3V9elvD-(yx?NJOLut^?wpj;<+2;f1J}*UZ4wJ;I>-xux@u~E5?TI3_v-KCgodsu z*fp&_f>FY6eUu=vUZB6>>Cyg8AdZ}nm^}ivVh)zksqO)>`-3Ro&t)2*+z`%83H zJ2Utvc1UX>ZKucs+IWg690OK)RcO3*;_wn-$5+Lr)5(oux_>1ZBC@Y z$FxlmNx~MBOkEA#L^J6-ZEfDRTFQ0Bv|Dg zVnE(KwGB?0VwU~PXQA9p zun1ya?bzEfWTJ$JiVF?Oa!&Qg!XO7;pmaOMUfkL?D;J z7xU=S7L=B}b392i`vF(OT1?j)fi*h4%4_I6Cun533#BN%r1e=wF+m&Bpw$?tsYfMu z*PLL@;4r;pt2ata{A96^mM#~5>@TiW4a40v|5VWol7i-&NpL5{7{incq8ikQq?#Xe zybH_76RtPZC4Ed?yiIl8+CH2ar#m#sGANP_@dI-U1+cKj9pQ^+@;7D>=tY(IQuu_*1`cJ}i z{Cf9Y=1M38W~PGLMk(pj;{BJO^S0E-=PxTA8zldSmN@Z=CxZ9;Tu^RT_N3b%hCR<8 zEodov7zez(*=;JVwJM`VVBAg*|s9%qJ?k1mu$G z{DBVpTHDLqCXo!e!qjdUS`kwj1YX(LIM<2d>nj756@8nzGygt!RBX_Nc@+=cX?T$w zlO@A{`5Rrz{n0B)7p~n+N#1(9dxa$zoN`7Op@C{#FzV-hN%K_Vba1kd&h{w8V3czfL1W!%R%DL z6wIrh$^+e`Pr@wEb|;TNqUg_{>s}`!IPu3WLx4xB6c%IvD?%qS4S<+dm{{pSR@Ak) zlF!13^dO>Cx#>v0(0UNBntQ-6%C|@gCO{vRr>N$W9B1Y8fd*b34&9Ls$dh%ERSQ4U zHIrhx?jO1Qb_eHPj+n24*l!Bc(=}!IeARCulbM9IrvQ2c^FE~y~})odIT&k{mbI@P0C3a)5^uYTs89*AK|EutyJW|tb@d)63;UJ~L5t)mkz>5^YyAVB7m6P3 zG5?SmiQwD-gwQz>%WJAP(nJ<+jFe;ctUX?y)W?0b`ooZp zY^JtI0se@h)b|jKe)JZMS2Cm#aFrF>!<=v4q))FZ>r{=0m6PgFC+%7Kmm!Pl&pyWQ zy>6dgZ0Lv;J3HPR;WHJuDQVzCUk0gpC0oFAn_`H`za^e*C^_!-Gt4j4S<=;UqIglP zun1(Bn(2H1&EcfO&(Hyy{FazbnsZRCATLWb329i13QvJ>*R%%!+FLmCX_~ai|Fx zzIo;csbECmY>F`w%gJ?}U48h>3oPy71zD;=%YTB}jnu~&w&cr^%|(bvY)?@jrcB=2 z>-+2tr-`NGyfZV3Yxr*8swYZ^X~X*|ls@-Y@6f zca;SDP{&gYDC~iEW(ex=I_Jjh9R^`pPe&<|%<`ZZjZ#)l!jbu)9*q|aeGN<_gt30c zR<$19;M*W>%TE7AP8lqsMsR6FZTwzyZw)&b@t~hpg*x{C%#Kl_gcj~4WM5OL&Ezmq zZlvf{)j0oM)-B~^^~rxt$i2ID|NT$4Z=){DSXUB7%IfNvlp`v`Zn=V$mrTnTcro;G z6JOrP8M45G@P7Uoj@j0@==Ip;!Dc&XQI)+y@9_<6)CTiZ)9=p#{{_bD@e#$&CIDsVgEo^8QLivGZPRAC zw54QXM=5Y>oD^$N7VzjCT?T}H>fwruZiEY2oL;0_IYotWf2d7tS^+F$F@2!uUH%26Xxs0KD388GK%SxHFg`jV% zfI+vT&5PI&pT}`=!tnZ^#y5xkEipyvV{|NSX43q~jby9ra!!B0&!qa8=hmx`^uH*waMjNsAcUIqZ01p*$$y>4B`VGq<4v_*!`pkq6 z)Igy$%P*%0C`U7U>oJJ;qTc|7nzyu?sEQk9J%y~~iDVGLH$1}o?h4lWZW@+E@MFF9 zfTE0am-@*QGyt=MDg%nimRHh^bG#Lz#6`hstgj;pKcE!*ru-dAMt z8=e{#2P<&jN2Dk9%90Kj;18KQL-~%zv;>+>AOVqvzC`vh znxU>ap&%Du(6$-EUHz)|KMs2O(EjOdY3AO@)qsOu6~#s+=_NJ|(Muq1S&b{(blYU4@`gy=zk0J2nRds6ofY)>rv zklC}=>16Yu;Jy2cLmZ)rA7njPaX#;fUoWqyUg6Q6#UtmOe((Midn@0X5q8v)Uxn3t z!(Q3wc}$`-s^Vvx?Y zd3Wtq9e;X;&WX)3{m+I8Yj`$u&aocZzsEs|RjI!)Eu#$PF8?-}YA`>->e~?1m#^+{ zWBejpI-9ymP!n&VmyuYw^q9M2>A@kDH*R0OrsxaP5z)-cZc|TKvI&@<75Lq*IxFtZ z&V2~C2fM#9u`+_w$4}pCtM3MLO{5$HI=fayN>kE*2IFv`Qh=T}ivbB~a;L}+C{LMw zi|-9@jyX%gD({Mxf0KD{E7nZ6y^7|uK-Bx@B|Da0ZgJMrDu;E;%g5d2rBKwX8(?m` zO-@z<{u-lk%$g#CNt!$8qS~gtx=@1ex>YnR`$DunKwgP_R&!r$1q%o?CAZ^pd@8zB zYQS&)bxLFv{kbuiNlNCEXghD zIrv59^;g-=a5KPZFb5plcQ(U{|LwD=Q`zHx!!s%z>zevjHkGG$z56??95CX(zpF{5 zEPPJ|-jKFbva{bRMqUa7#};EOe(3m^TW~}F%3s>xE_f@%w~Wem?c74fruq3yL~T>W z$K5>lq=0X5tv*M88SSzUIf0*eg0PNLe56P5JA0~?js557X#wjE2A2<}m*h<#By1e$ z-Falkno_EB#HBvfB=z05-NWjc{-bVfam|%*8WrIbgiFA@6&{wl*Klbmm_tY#qN42B z6Pm#0?IDg}CC2-|%$r4z<+Qv@L;&i<_{ojhr!V0|n9|ZAp zD@2Z9zupW2dZA6C%7eeQy$e%=;0#9vh!L#Od1mq<@n*6-2d2t<;5C=?f)JhcVsfSG zCRm?1pGtduw=nZvED8pqL$1yIQlB5Z0E*MWR@qv%!kIfD^mAX3aZK6#c{+HCM*f0lO(G|kpRs;nQ4H!}_4RA{m zjG~NNm4N7L0;THOUFvLnZ(qx&bo6(Psd8(%f-Ku*`9$K6e1uwNCV4|aV6|0d&rYI+m?E5QOadLceE_bx zC*3he*%XcCOdHBk9i}?Nv@e*r-;ly%a9NuNtO@nsEDqM4s7vT?@r7%kl8jnxN0R~` z_44vg;b64zG=h8XhZDw}L#_HLH8|Bs5yLN>wz1=b?aaY8YGQrjZ%E5-23shN7;a?$N%nSo| z$_o)klTC@rFN2ztRwUw`X>R_tXt3qRPw3p%g8+tAy=Y9x})>#rhV|;*5J4>V80! z)dd98){>JvukbJ7!?cyEXu$LrGE=OrS9iSTCLz^De@wZh7~~U%pxHr6EN-^u0Iywv z>LJf_jO}Hx9agQ5M)=7y3Vg_ei0G_!BdK-es=g_9Mfpc~x6~u1CqiQxIR}m7Qoxs!xS;Oyg0qOL#+0?Ngc*l*Dm@74z0UR>TtYn<;!1PeZ+e7 zN?9_KolU>c#Gt}Kivw&Ji4hognH*s18+MkLT?A{Z+8v{b`CVd(guX6zRUVj^*o({> zSI&r2;E~3BC_(LO;#jWhF9WKESQbMA8TN+mApPxlR>2y8=XobIuU#ct;#VIu**Uqu zP#wYQ^*n>AVe16ctEr6`MMe*aJ1(}s08xW^%{q2k7`TW!(XMk%1Y5>HA@_-1c3opg z&Or0ddi- zZD-@H9sf#BdfX}2mfpr_{mAUdx!EtjPm^>cPbRJ1>5nvS=6vq6&n@D&`)@an& zwSe*ZuJEhq{YQh!6LJ-Ze!!Z7-Vwt_>o;4GU-Z6nVI$ziHB(AMFV+L_D7rqqR#6%7 zud8 zFx2KqF*^ZpTOt$la+{GqQ4QfJB8J}j9CK`Cy!gfLS=ht@NGRwLKr-QGBMN; zs@wq$Lm1m{)5A{IT*q(2oo{AAbOph-&GLEyN@Xhh))30tz>HKt#~C-;B~kh}X--tg zCVPV5KBRFD7$R{2Q=<6YL0k$r3U&z3&e0rdgD=0lc6MRupN-ach{O>xF>6&5*~?(a zrl$)&ht{?y;pvAm8t1;~&tU^n%+=FQ_9)d9m2ZC5$e?ccn4m88>*22bLEX1vJ^?mD zn898~=Mr3>TJM?RR$Rc-9j9vl2YR}OrzyJWK2DpsD81*$k$U|pdN6OuYpV5kMb_#o zBS&BC4nr(+*;thlKdGhU9=(3bDq>fCoiP}qsdQ53sfvMuwX_$ z?Q-<3k#qS+eFtf|GkrLARs&bL6ubwXZu4OG*31EcE+F8Drei7*U|;j~$jQV$6a)jJ zJHUfHxVN-iOgU)yY4nXOu={&6DJuuaocMI=7TfyzO#u;}u2%}oIl8Z;+eZKbN!#Si zZcvXk=*#kvu!Kxu(#C(sE!=8|n7vD2X^h4JC%+%*(HuzfUS-|=ClL`cqe8V=ntt%d zoU?9AEug}@H7EhqX=wL%p!2pMBy`CMdyD(~I1&Hk#pHKyK0>p0y1~%Rt`kWHr@VN@ zKOweVdjl+iHKw49pk47XwdDZ^AIy~Q7U%guios7%NIpq$wVrKA8KB_r*^rtP{iSJ! z4k{1w8?TpQWUaU7*lfpn?N5m1_~Q|;66~bIgH9fAnN7^IIDq>N)h7NJgEztdC zuvrB3P7$zyp*366qGg&fxcE|JB}_WyhW46gtNYZ~*J+WH&eMCg9@1~jDqo#=FOY?) z3-QXdVy0@Zgy$RFCI4@J_VdsS148I@jT6s&pVO`ewIsZjYO@JuD^Dx}|MpEcy%5VQWeGwI ziwh_{&8Jjv-?~qoEXDZe@@Pc1{aJ5gy}YD-qOQ-S&XX)odsq}Uzj}NmB;S>+UMKq- zW6>RB6lT^6#RQ|Ugc+m8cYq2ctBMTh;cFn}C~-E>#I)-LTIRh>!RY9#E^_6yFFRMy z8-KNq9yfg6hn!2)B#(1n=_VD&7>(0pKFUWDKrZQ2BvLM11-xM8+yrsA8c$?Ey<)Vu-q*1J4Xq1YxKnXZEGZ;Ef3l9s0(IYL zO+AI}$B=)Kfzw&2p2Q5Bl3hoND+XrP0$wM7%K4_e;qW z4cg9d^--(%)Jz0gz+JP`A^F`5(3=S=PYoltpl#m*_ z2CCtN3)%A@Y}=7%nwuq1tFNX<7nOo)Ut1jC33Zc`p~Ptg;o9z0%ll*Q!xn&d0M;am zdG0u+(C|ri)=b`}3dhei?}B)Am>5h?iHDd^$gXP{dqOb_(=Vp;= zh{OA^VpAH#ir`4NBKB2vO!lrvmI@$^Qj6Wz%yxMr2x6oD1~bCEyYxr3UULC$0eG+m zkhc-AvSv9a(O;I>iSy^dVh%SajVJ;d#3nS6OIdVFKScX{dNz$|j8gHdzU2el;Z#A* zSr#_KjK078$g$IGJ|8QpDk=7#HTfE6Q_Wg9Bd;=Wx!Z_(6^~d1dCvST;1wq2A!? ztlPb1b?oc8QTU$&Z|9P!=w+-JIO96vM-v z-i?{a#jKZY{L(MPyX)xZMh6kdp$(VjeyB0e|0Q&VG2)VKfe3F(78X0gjkKMn22;Rc zdet-($u5f>EtZZR$L$zgcUxsf7P8y|MXLzy3xZEzO)I6)V%5!=BS0E8){&ATPQw_O zehACisKJaB!UdoiYTIgXt$(~fmJQ4ne)`rl5>wvnzYx%l*a~3S^P)EjBP@qQDUsyrdraa(jN13jicAfm*IUP zyaIlzVBs=|b~Fy_glS@lxp_BTPZgpLCSxGPNp4tZ7WUH+KX~EfTw4Rx`r)Z>fxL6e zQT6Wc$2+gl@4*e5aXScd+4$J|mDr| z{!{!6$w(K4N_&m3pY!~F$G&?ZrCGAT-#qYZTI81n*K&!(%ykVi?aC@l)fj{17xO2M+r7jiXc_c4Gi zDtS`0hnvo*uYVA=@7E#cClET*;S?;TrtMDALr5=PEAU_)+*0=0j^i&ee5&SZy3cP* zzdG!-an;7Ev1%vM5byvJLP_Jr$)2rr@qh!I&Mo$*$zU%WuLm+QF1$=4cDH2jibwkB z`n!$ag5=OMp|#A$ZG0O7xCDx9fRh7RsMY>x$s{-LB~kTaCF_4vp{rxg0DIoueE`KY zd`rqDv{MRz#T&{8#e=vKryGnYKW>RUMQ7A4LwoYb`c@`!b{h_4%ySMg-O3Xi(jtWg zjD4Hs=RDc1EcP*G(1pqiXrZKrx0UyN&rI+Z_p&t5XD-UmYu1{Dn#$#7m+e8}!|{RC z9L}sPcQnJ+a{4oI@78HW``AY9nhZW#6H@b2cC+&e7Fr#ASjPeX?V(yuQSJ8nU8-R1 z9{S4)l#}&ve|z@VMmv;A`M3S<4uaNTnZjc$pv3%3&_oYG@Z7HpVl(4moDEDRK^AVB z#)q&%R`*U(lX28O4k*sfhUc|PyS7VUX#b2U5KCxo2t1OE?uK|w-eC8Vi(!M*CI^WR z@p^UhCoiAOeo%!)oB(spKue5jb4Vo}O7pp|x!?dyJKF;cyTxId2p#u9cRF5i@M@49 z=(^+6H0i)aeHA|%59qY?;GE8e``3Y&K|dtwPqV#h zbdn)R@mVWkg|Cfda^Z{siP>6+4Vh0AohQAtM4`ZS%6tG$-nE2p|43|kEk0yWr?>#o z^(vP}P`(2GR=t++ShU5?I9D1;Qf}9-h5hNdWsd?f_^BKkz_QlB#PJWbZOJNgWx81? ztYgrA4NWxb9IygVlcQh6Ar@d6uJBCzzAmLx;Mmqt;!*|^!FZnD%-u=I>yhi0$eqlG zMPekgAE9&gn&5TG$9|t+>Pf*LkFXy9#lhv*&~&M{9k(_0i_Ym9uhg5~01G3^6sTJB zv(UBF^5wGu4g5YPQ?tiCeC?=&3vH5j_by# zT`pasyiz$nSKOJB?{w4S&4H;8$eZEj!3<$0un&;q;MxXSB$3HopRe`E$8e?gLOz7W z%EOF@c>TC=^l0mW{F*jia!^>-dF)<6ItJ<_sAEyT>9i4e8?@}mbyE|7CV|3=VQt7} z7ty7jZzcqNc)#cW{cOzfEG`^yf%Ro0HZ-8|%tWro%kgR+G( zjoc$h7AGLiq#<(QH=$t{bK;?1aZKLXJ*6Su$X=qfLCN&NK$AE?!*u{41j|?72d^7+0&bETU{*>uhgqJ(qc{REDt#6iRV( zlO=x@c3XWbU=eOWOU0aBt)X8Bt1fBS*0ftXyTAYqJOCL8+yDgF08u~y6)va_PIl>_ zo1sMNAB}!Gzz3ff#X$t{ZOW=&I2F1&X8in&-p%tTy|Tv%f8q3HseMUs2slQS4q-( zoz(-TE7r>~5HiLoYy$~TLiw*Z?UZauE+^)C6v*i`@@9^SRoP`X;tyW z%lx2*{jO+W4x-&2uWlbA(=sM4L{s9r*vJvxP54n0k8A(A;(3r}W@XuF?5PNMjb$p1 zmG&&?yD4Q?CJyGUa?#n{o!gDF+HL!3ui)O+ae985(CzeM;#Dt85gxuBKO_i=W?8SY z^#B1|G2&J$eU`NL!IX#w`-QWte5Df{C*0S|^8uVCB&j6Jw+r=mj2(E2xb#lqq6Ogd z>(9u@ZSbuYp70sWkkD=fez6mizrH>b9x;olT1c8d1ZI))aYPv^_NAx-P&txqtZqf3 zLul84iGPfPf^NmT1o%xSJJkPh@7OWXO7!I%h;+?puN|K=X=gX)J5}4)($Qx^win}f zC^cT}Z-OSZo0#3mEPu?gpG#B;`097V@F!zzak>PzSllUkmzP*Gh>7r9Ujpb_(#dg^ zr<;!^kq=|8`SZ?&M(yj$PcRSMb`}P%VZCt7l*0UUoKWL*7krx~a3)1@(cHEm^ay76 zN|p(k+-%l*)iRs@-qlM{YK@j1Y0!%ERt6b4W6Y4OPd#eB@uCg9gepv$o~ZrycERgc zv~(ONlz+O-1VRPxvr(=HB3a}hf&1&)%PlEkgZ=1DEolIOv@X;hV^! zAfxx`N%Mhzd2&On#uuy8#Xt{?JwHPFImS#su-gF4%_!=p=cCqAXS^>QQ4E_o8zg+@ za?;LISW}1E_C(*{130z(m^4BXR#!bdtaxEN&ySuWwhCyZzcFXmqI1M=R8+(u1ONar}Ds}=&R`UhDZt%tg%^F{M~~!s#Q;49X3nF9kn;t zUIN3>$GGub{ws@AdCYk<@r`dhU$&F}WVk+$m [!NOTE] - > - > Format your domains without protocol or www information, for example, - > `yourcompany.example`. This should include all email domains and - > subdomains users will use to access Docker, for example - > `yourcompany.example` and `us.yourcompany.example`. Public domains such as - > `gmail.com`, `outlook.com`, etc. aren’t permitted. - - > [!TIP] - > - > Make sure that the TXT record name that you create on your DNS matches - > the domain you registered on Docker in Step 4. For example, - > if you registered the subdomain `us.yourcompany.example`, - > you need to create a TXT record within the same name/zone `us`. - > A root domain such as `yourcompany.example` needs a TXT record on the - > root zone, which is typically denoted with the `@` name for the record. - -5. Once you have waited 72 hours for the TXT record verification, - you can then select **Verify** next to the domain you've added, - and follow the on-screen instructions. diff --git a/layouts/shortcodes/admin-image-access.html b/layouts/shortcodes/admin-image-access.html deleted file mode 100644 index 11bd7d5ad54a..000000000000 --- a/layouts/shortcodes/admin-image-access.html +++ /dev/null @@ -1,27 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $iam_navigation := "Select **My Hub**, select your organization in the left navigation drop-down menu, and then select **Image access**." }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com/) and select your organization." }} - {{ $iam_navigation = "Select **Admin Console**, then **Image access**." }} -{{ end }} - -1. Sign in to {{ $product_link }}. -2. {{ $iam_navigation }} -3. Enable Image Access Management to set the permissions for the following categories of images you can manage: - - - **Organization Images**: Images from your organization are always allowed by default. These images can be public or private created by members within your organization. - - **Docker Official Images**: A curated set of Docker repositories hosted on Hub. They provide OS repositories, best practices for Dockerfiles, drop-in solutions, and applies security updates on time. - - **Docker Verified Publisher Images**: Images published by Docker partners that are part of the Verified Publisher program and are qualified to be included in the developer secure supply chain. - - **Community Images**: These images are disabled by default when Image Access Management is enabled because various users contribute them and they may pose security risks. This category includes Docker-Sponsored Open Source images. - - > [!NOTE] - > - > Image Access Management is turned off by default. However, owners in your organization have access to all images regardless of the settings. - -4. Select the category restrictions for your images by selecting **Allowed**. - Once the restrictions are applied, your members can view the organization permissions page in a read-only format. - -## Verify the restrictions - -The new Image Access Management policy takes effect after the developer successfully authenticates to Docker Desktop using their organization credentials. If a developer attempts to pull a disallowed image type using Docker, they receive an error message. diff --git a/layouts/shortcodes/admin-sso-config.md b/layouts/shortcodes/admin-sso-config.md deleted file mode 100644 index 4695913d8942..000000000000 --- a/layouts/shortcodes/admin-sso-config.md +++ /dev/null @@ -1,36 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com) and select your organization. Note that when an organization is part of a company, you must select the company and configure SSO for that organization at the company level. Each organization can have its own SSO configuration and domain, but it must be configured at the company level." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -> [!IMPORTANT] -> -> If your IdP setup requires an Entity ID and the ACS URL, you must select the -> **SAML** tab in the **Authentication Method** section. For example, if your -> Entra ID (formerly Azure AD) Open ID Connect (OIDC) setup uses SAML configuration within Azure -> AD, you must select **SAML**. If you are [configuring Open ID Connect with Entra ID (formerly Azure AD)](https://docs.microsoft.com/en-us/powerapps/maker/portals/configure/configure-openid-settings) select -> **Azure AD (OIDC)** as the authentication method. Also, IdP initiated connections -> aren't supported at this time. - -After your domain is verified, create an SSO connection. - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table select **Create Connection**, and create a name for the connection. - - > [!NOTE] - > - > You have to verify at least one domain before creating the connections. - -4. Select an authentication method, **SAML** or **Azure AD (OIDC)**. -5. Copy the following fields to add to your IdP: - - - SAML: **Entity ID**, **ACS URL** - - Azure AD (OIDC): **Redirect URL** - - ![SAML](/docker-hub/images/saml-create-connection.png) - - ![Azure AD](/docker-hub/images/azure-create-connection.png) diff --git a/layouts/shortcodes/admin-sso-connect.md b/layouts/shortcodes/admin-sso-connect.md deleted file mode 100644 index 6d61bb7c83c4..000000000000 --- a/layouts/shortcodes/admin-sso-connect.md +++ /dev/null @@ -1,48 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com) and select your organization. Note that when an organization is part of a company, you must select the company and configure SSO for that organization at the company level. Each organization can have its own SSO configuration and domain, but it must be configured at the company level." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -1. In {{ $product_link }}, select the verified domains you want to apply the connection to. -2. To provision your users, select the organization(s) and/or team(s). -3. Review your summary and select **Create Connection**. - -## Test your SSO configuration - -After you’ve completed the SSO configuration process in Docker, you can test the configuration when you sign in to {{ $product_link }} using an incognito browser. Sign in to {{ $product_link }} using your domain email address. You are then redirected to your IdP's login page to authenticate. - -1. Authenticate through email instead of using your Docker ID, and test the login process. -2. To authenticate through CLI, your users must have a PAT before you enforce SSO for CLI users. - -> [!IMPORTANT] -> -> SSO has Just-in-Time (JIT) provisioning enabled by default, unless you have [disabled it](/security/for-admins/provisioning/just-in-time/#sso-authentication-with-jit-provisioning-disabled). This means your users are auto-provisioned to your organization. -> -> You can change this on a per-app basis. To prevent auto-provisioning users, you can create a security group in your IdP and configure the SSO app to authenticate and authorize only those users that are in the security group. Follow the instructions provided by your IdP: -> -> - [Okta](https://help.okta.com/en-us/Content/Topics/Security/policies/configure-app-signon-policies.htm) -> - [Entra ID (formerly Azure AD)](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-restrict-your-app-to-a-set-of-users) -> -> Alternatively, see [Manage how users are provisioned](/security/for-admins/single-sign-on/manage/). - -The SSO connection is now created. You can continue to set up SCIM without enforcing SSO log-in. For more information about setting up SCIM, see [Set up SCIM](/security/for-admins/provisioning/scim/). - -## Optional: Enforce SSO - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon and then **Enable enforcement**. - - When SSO is enforced, your users are unable to modify their email address and password, convert a user account to an organization, or set up 2FA through Docker Hub. You must enable 2FA through your IdP. - -4. Continue with the on-screen instructions and verify that you’ve completed the tasks. -5. Select **Turn on enforcement** to complete. - -Your users must now sign in to Docker with SSO. - -> [!IMPORTANT] -> -> If SSO isn't enforced, users can choose to sign in with either their Docker ID or SSO. diff --git a/layouts/shortcodes/admin-sso-management-connections.md b/layouts/shortcodes/admin-sso-management-connections.md deleted file mode 100644 index 022ca6ccbce3..000000000000 --- a/layouts/shortcodes/admin-sso-management-connections.md +++ /dev/null @@ -1,27 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := `Navigate to the SSO settings page for your organization. Select **My Hub**, your organization, **Settings**, and then **Security**.` }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com) and select your organization. Note that when an organization is part of a company, you must select the company and configure SSO for that organization at the company level. Each organization can have its own SSO configuration and domain, but it must be configured at the company level." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -### Edit a connection - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon. -4. Select **Edit connection**. -5. Follow the on-screen instructions to edit the connection. - -### Delete a connection - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon. -4. Select **Delete connection**. -5. Follow the on-screen instructions to delete a connection. - -### Deleting SSO - -When you disable SSO, you can delete the connection to remove the configuration settings and the added domains. Once you delete this connection, it can't be undone. If an SSO connection is deleted, Docker users must authenticate with their Docker ID and password. \ No newline at end of file diff --git a/layouts/shortcodes/admin-sso-management-orgs.md b/layouts/shortcodes/admin-sso-management-orgs.md deleted file mode 100644 index e22ee8b567f7..000000000000 --- a/layouts/shortcodes/admin-sso-management-orgs.md +++ /dev/null @@ -1,27 +0,0 @@ -{{ $product_link := "[Docker Hub](https://hub.docker.com)" }} -{{ $sso_navigation := "Select **My Hub**, your organization, and then **Settings**." }} - -{{ if eq (.Get "product") "admin" }} - {{ $product_link = "[Docker Home](https://app.docker.com) and select your organization. Note that when an organization is part of a company, you must select the company and configure SSO for that organization at the company level. Each organization can have its own SSO configuration and domain, but it must be configured at the company level." }} - {{ $sso_navigation = "Select **Admin Console**, then **SSO and SCIM**." }} -{{ end }} - -### Connect an organization - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon and then **Edit connection**. -4. Select **Next** to navigate to the section where connected organizations are listed. -5. In the **Organizations** drop-down, select the organization to add to the connection. -6. Select **Next** to confirm or change the default organization and team provisioning. -7. Review the **Connection Summary** and select **Update connection**. - -### Remove an organization - -1. Sign in to {{ $product_link }}. -2. {{ $sso_navigation }} -3. In the SSO connections table, select the **Action** icon and then **Edit connection**. -4. Select **Next** to navigate to the section where connected organizations are listed. -5. In the **Organizations** drop-down, select **Remove** to remove the connection. -6. Select **Next** to confirm or change the default organization and team provisioning. -7. Review the **Connection Summary** and select **Update connection**. From 4717a0bfb6f9215b6784bee84b548a0446546c51 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Wed, 13 Aug 2025 10:20:48 -0400 Subject: [PATCH 06/10] remove unused images --- .../images/azure-create-connection.png | Bin 21300 -> 0 bytes .../docker-hub/images/create-connection.png | Bin 30061 -> 0 bytes .../images/saml-create-connection.png | Bin 24191 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 content/manuals/docker-hub/images/azure-create-connection.png delete mode 100644 content/manuals/docker-hub/images/create-connection.png delete mode 100644 content/manuals/docker-hub/images/saml-create-connection.png diff --git a/content/manuals/docker-hub/images/azure-create-connection.png b/content/manuals/docker-hub/images/azure-create-connection.png deleted file mode 100644 index 207a4d629c5df599d119b4fb90b57ed60429a9ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21300 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 A!T Date: Wed, 13 Aug 2025 10:26:14 -0400 Subject: [PATCH 07/10] vale errors --- _vale/config/vocabularies/Docker/accept.txt | 3 +++ content/manuals/enterprise/security/domain-management.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/_vale/config/vocabularies/Docker/accept.txt b/_vale/config/vocabularies/Docker/accept.txt index 8fde615fd509..26e75e113fe9 100644 --- a/_vale/config/vocabularies/Docker/accept.txt +++ b/_vale/config/vocabularies/Docker/accept.txt @@ -20,6 +20,7 @@ cgroup Chrome Chrome DevTools Citrix +CI/CD cli CLI CloudFront @@ -183,6 +184,8 @@ ufw ui uid umask +uncaptured +Uncaptured undeterminable Unix unmanaged diff --git a/content/manuals/enterprise/security/domain-management.md b/content/manuals/enterprise/security/domain-management.md index a4307582c98f..3e649601dbc5 100644 --- a/content/manuals/enterprise/security/domain-management.md +++ b/content/manuals/enterprise/security/domain-management.md @@ -94,7 +94,7 @@ When auto-provisioning is enabled for a verified domain: - Auto-provisioning only adds existing Docker users to your organization, it doesn't create new accounts. - Users experience no changes to their sign-in process. - Company and organization owners receive email notifications when new users are added. -- You may need to [manage seats](/manuals/subscription/manage-seats.md) to accomodate new users. +- You may need to [manage seats](/manuals/subscription/manage-seats.md) to accommodate new users. ### Enable auto-provisioning From 4e6d2aec7dea8f7ccc543223709f485056a3ac00 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Wed, 13 Aug 2025 10:35:53 -0400 Subject: [PATCH 08/10] vale corrections --- _vale/config/vocabularies/Docker/accept.txt | 3 +++ .../troubleshoot-and-support/troubleshoot/topics.md | 4 ++-- .../security/hardened-desktop/air-gapped-containers.md | 2 +- .../enhanced-container-isolation/config.md | 2 +- .../enhanced-container-isolation/faq.md | 2 +- .../enhanced-container-isolation/limitations.md | 2 +- .../hardened-desktop/settings-management/_index.md | 2 +- .../settings-management/settings-reference.md | 4 ++-- .../enterprise/security/provisioning/just-in-time.md | 2 +- .../manuals/enterprise/security/provisioning/scim.md | 2 +- .../enterprise/security/single-sign-on/connect.md | 2 +- .../enterprise/security/single-sign-on/manage.md | 2 +- content/manuals/security/faqs/general.md | 10 +++++----- .../manuals/security/faqs/single-sign-on/idp-faqs.md | 2 +- content/manuals/subscription/faq.md | 2 +- 15 files changed, 23 insertions(+), 20 deletions(-) diff --git a/_vale/config/vocabularies/Docker/accept.txt b/_vale/config/vocabularies/Docker/accept.txt index 26e75e113fe9..9fb5c354da85 100644 --- a/_vale/config/vocabularies/Docker/accept.txt +++ b/_vale/config/vocabularies/Docker/accept.txt @@ -9,6 +9,7 @@ Artifactory auditable autolock Azure +Azure AD bootup Btrfs Bugsnag @@ -142,6 +143,7 @@ osxfs OTel Paketo pgAdmin +plist PKG Postgres PowerShell @@ -172,6 +174,7 @@ Syft syntaxes Sysbox sysctls +sysctl Sysdig systemd Testcontainers diff --git a/content/manuals/desktop/troubleshoot-and-support/troubleshoot/topics.md b/content/manuals/desktop/troubleshoot-and-support/troubleshoot/topics.md index 17d946d1a8e1..1cba673645c0 100644 --- a/content/manuals/desktop/troubleshoot-and-support/troubleshoot/topics.md +++ b/content/manuals/desktop/troubleshoot-and-support/troubleshoot/topics.md @@ -491,8 +491,8 @@ To use Docker Desktop with Windows Containers, ensure that FDVDenyWriteAccess is **Computer Configuration** > **Administrative Templates** > **Windows Components** > **BitLocker Drive Encryption** > **Fixed Data Drives** > **Deny write access to fixed drives not protected by BitLocker** > [!NOTE] -> -> Modifying Group Policy settings may require administrator privileges and should comply with your organization's IT policies. If the setting gets reset after some time this usually means that it was overriden by the centralized configuration of your IT department. Talk to them before making any changes. +> +> Modifying Group Policy settings may require administrator privileges and should comply with your organization's IT policies. If the setting gets reset after some time this usually means that it was overridden by the centralized configuration of your IT department. Talk to them before making any changes. ### `Docker Desktop Access Denied` error message when starting Docker Desktop diff --git a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md index 50446a347ea0..91a77e9a2736 100644 --- a/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md +++ b/content/manuals/enterprise/security/hardened-desktop/air-gapped-containers.md @@ -174,7 +174,7 @@ function FindProxyForURL(url, host) { } } - // Block access to developer's localhost to prevent data exfiltration + // Block access to developer's localhost if (host === "host.docker.internal" || host === "localhost") { return "PROXY reject.docker.internal:1234"; } diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md index 60e928268460..bfbee58448e4 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/config.md @@ -115,7 +115,7 @@ Docker Desktop validates allowed images by: 1. Comparing container image digests against the allowlist when containers start 1. Blocking containers whose digests don't match allowed images -This prevents bypassing restrictions by retagging unauthorized images: +This prevents bypassing restrictions by re-tagging unauthorized images: ```console $ docker tag malicious-image docker:cli diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md index eaf260d67a57..d9dde83bb98c 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/faq.md @@ -71,7 +71,7 @@ ECI protection varies by container type and Docker Desktop version: - Docker Extensions - Docker Debug containers -- Kubernetes with kubeadm provisioner +- Kubernetes with Kubeadm provisioner For complete details, see [ECI limitations](/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md). diff --git a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md index a6c3de35fc75..2419fc369a9c 100644 --- a/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md +++ b/content/manuals/enterprise/security/hardened-desktop/enhanced-container-isolation/limitations.md @@ -47,7 +47,7 @@ containers mode isn't supported. ## Docker Build protection varies -Docker Build proection depends on the driver and Docker Desktop version: +Docker Build protection depends on the driver and Docker Desktop version: | Build drive | Protection | Version requirements | |:------------|:-----------|:---------------------| diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md index 14b65497261b..5e6ebb4a82ec 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/_index.md @@ -54,7 +54,7 @@ When multiple policies exist, Docker Desktop applies them in this order: 1. User-specific policies: Highest priority 1. Organization default policy: Applied when no user-specific policy exists -1. Local `admin-settings.json` file: Lowest priority, overriden by Admin Console policies +1. Local `admin-settings.json` file: Lowest priority, overridden by Admin Console policies ## Set up Settings Management diff --git a/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md b/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md index ac6bcaca10b3..8a0ffbb17f36 100644 --- a/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md +++ b/content/manuals/enterprise/security/hardened-desktop/settings-management/settings-reference.md @@ -23,7 +23,7 @@ methods are indicated with these labels: - Desktop GUI: Configurable through Docker Desktop settings interface - Admin Console: Configurable through the Docker Admin Console using Settings Management -- JSON file: Configurable htrough `admin-settings.json` using Settings Managemet +- JSON file: Configurable through `admin-settings.json` using Settings Management - CLI: Configurable through command-line tools ## General settings @@ -344,7 +344,7 @@ if needed. - **Description:** Automatic SBOM indexing for images without requiring user interaction. - **OS:** {{< badge color=blue text="All" >}} -- **Use case:** KKeep image metadata current by indexing during idle time or after image operations. +- **Use case:** Keep image metadata current by indexing during idle time or after image operations. - **Configure this setting with:** - **General settings** in [Docker Desktop GUI](/manuals/desktop/settings-and-maintenance/settings.md) diff --git a/content/manuals/enterprise/security/provisioning/just-in-time.md b/content/manuals/enterprise/security/provisioning/just-in-time.md index db2eb79e8ca7..9c2cc95e908c 100644 --- a/content/manuals/enterprise/security/provisioning/just-in-time.md +++ b/content/manuals/enterprise/security/provisioning/just-in-time.md @@ -16,7 +16,7 @@ This page explains how JIT provisioning works, SSO authentication flows, and how ## Prerequisites -Before you beging, you must have: +Before you begin, you must have: - SSO configured for your organization - Administrator access to Docker Home and your identity provider diff --git a/content/manuals/enterprise/security/provisioning/scim.md b/content/manuals/enterprise/security/provisioning/scim.md index f60d81c232f8..215bf0cade22 100644 --- a/content/manuals/enterprise/security/provisioning/scim.md +++ b/content/manuals/enterprise/security/provisioning/scim.md @@ -83,7 +83,7 @@ To enable SCIM: 1. Sign in to [Docker Home](https://app.docker.com). 1. Select **Admin Console**, then **SSO and SCIM**. -1. In the **SSO connections** table, select the **Actions** icon for your conection, then select **Setup SCIM**. +1. In the **SSO connections** table, select the **Actions** icon for your connection, then select **Setup SCIM**. 1. Copy the **SCIM Base URL** and **API Token** and paste the values into your IdP. ## Enable SCIM in your IdP diff --git a/content/manuals/enterprise/security/single-sign-on/connect.md b/content/manuals/enterprise/security/single-sign-on/connect.md index c380676d58d8..7ea91559c7f7 100644 --- a/content/manuals/enterprise/security/single-sign-on/connect.md +++ b/content/manuals/enterprise/security/single-sign-on/connect.md @@ -113,7 +113,7 @@ Use the following tabs based on your IdP provider. ## Step three: Connect Docker to your IdP -Complet the integration by pasting your IdP values into Docker. +Complete the integration by pasting your IdP values into Docker. {{< tabs >}} {{< tab name="Okta SAML" >}} diff --git a/content/manuals/enterprise/security/single-sign-on/manage.md b/content/manuals/enterprise/security/single-sign-on/manage.md index f2f3b46a1f6f..0c2185097db2 100644 --- a/content/manuals/enterprise/security/single-sign-on/manage.md +++ b/content/manuals/enterprise/security/single-sign-on/manage.md @@ -117,7 +117,7 @@ your organization. 1. Select **Invite**. 1. Follow the on-screen instructions to invite the user. -The uesr receives an email invitation and can create a Docker account or sign +The user receives an email invitation and can create a Docker account or sign in with their existing account. ### Remove users diff --git a/content/manuals/security/faqs/general.md b/content/manuals/security/faqs/general.md index bdac91350ad3..d532e5b3f884 100644 --- a/content/manuals/security/faqs/general.md +++ b/content/manuals/security/faqs/general.md @@ -11,15 +11,15 @@ aliases: ## How do I report a vulnerability? -If you've discovered a security vulnerability in Docker, report it responsibly to security@docker.com so our team can quickly address it. +If you've discovered a security vulnerability in Docker, report it responsibly to security@docker.com so Docker can quickly address it. ## Does Docker lockout users after failed sign-ins? Docker Hub locks out users after 10 failed sign-in attempts within 5 minutes. The lockout duration is 5 minutes. This policy applies to Docker Hub, Docker Desktop, and Docker Scout authentication. -## Do you support physical MFA with YubiKeys? +## Do you support physical multi-factor authentication (MFA) with YubiKeys? -You can configure physical MFA through SSO using your identity provider (IdP). Check with your IdP if they support physical MFA devices like YubiKeys. +You can configure physical multi-factor authentication (MFA) through SSO using your identity provider (IdP). Check with your IdP if they support physical MFA devices like YubiKeys. ## How are sessions managed and do they expire? @@ -50,7 +50,7 @@ Docker Desktop uses the host operating system's secure key management to store a - Windows: [Security and Identity API via Wincred](https://learn.microsoft.com/en-us/windows/win32/api/wincred/) - Linux: [Pass](https://www.passwordstore.org/). -## How do we remove users who aren't part of our IdP when using SSO without SCIM? +## How do I remove users who aren't part of my IdP when using SSO without SCIM? If SCIM isn't turned on, you must manually remove users from the organization. SCIM can automate user removal, but only for users added after SCIM is turned on. Users added before SCIM was turned on must be removed manually. @@ -62,7 +62,7 @@ For information about metadata stored by Docker Scout, see [Data handling](/manu ## How are Marketplace extensions vetted for security? -Security vetting for extensions is on our roadmap but isn't currently implemented. Extensions aren't covered as part of Docker's Third-Party Risk Management Program. +Security vetting for extensions is on the roadmap but isn't currently implemented. Extensions aren't covered as part of Docker's Third-Party Risk Management Program. ## Can I prevent users from pushing images to Docker Hub private repositories? diff --git a/content/manuals/security/faqs/single-sign-on/idp-faqs.md b/content/manuals/security/faqs/single-sign-on/idp-faqs.md index 90b5a344e1bb..bb571ca2acf9 100644 --- a/content/manuals/security/faqs/single-sign-on/idp-faqs.md +++ b/content/manuals/security/faqs/single-sign-on/idp-faqs.md @@ -42,6 +42,6 @@ Yes, bot accounts need seats like regular users, requiring a non-aliased domain The SSO implementation uses Just-in-Time (JIT) provisioning by default. You can optionally turn off JIT in the Admin Console if you turn on auto-provisioning using SCIM. See [Just-in-Time provisioning](/security/for-admins/provisioning/just-in-time/). -## My Entra ID SSO connection isn't working and shows a misconfiguration error. How can I troubleshoot this? +## My Entra ID SSO connection isn't working and shows an error. How can I troubleshoot this? Confirm that you've configured the necessary API permissions in Entra ID for your SSO connection. You need to grant administrator consent within your Entra ID tenant. See [Entra ID (formerly Azure AD) documentation](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/grant-admin-consent?pivots=portal#grant-admin-consent-in-app-registrations). diff --git a/content/manuals/subscription/faq.md b/content/manuals/subscription/faq.md index 244195dec140..3e330daa0f08 100644 --- a/content/manuals/subscription/faq.md +++ b/content/manuals/subscription/faq.md @@ -26,6 +26,6 @@ Contact the [Docker Sales Team](https://www.docker.com/company/contact) for info Docker offers two content contribution programs: - [Docker-Sponsored Open Source Program (DSOS)](../docker-hub/repos/manage/trusted-content/dsos-program.md) for open source projects -- [Docker Verified Publisher (DVP)](../docker-hub/repos/manage/trusted-content/dvp-program.md) for commerical publishers +- [Docker Verified Publisher (DVP)](../docker-hub/repos/manage/trusted-content/dvp-program.md) for commercial publishers You can also join the [Developer Preview Program](https://www.docker.com/community/get-involved/developer-preview/) or sign up for early access programs to participate in research and try new features. From 90ff7ab8288aa2d78920dc2c7a6ba67bb0327cc2 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Wed, 13 Aug 2025 10:37:53 -0400 Subject: [PATCH 09/10] one final vale spelling.. --- content/manuals/security/faqs/networking-and-vms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/manuals/security/faqs/networking-and-vms.md b/content/manuals/security/faqs/networking-and-vms.md index 3d9c89c59222..668697d482a5 100644 --- a/content/manuals/security/faqs/networking-and-vms.md +++ b/content/manuals/security/faqs/networking-and-vms.md @@ -9,7 +9,7 @@ aliases: - /faq/security/networking-and-vms/ --- -## How can I limit container internet access to prevent data exfiltration? +## How can I limit container internet access? Docker Desktop doesn't have a built-in mechanism for this, but you can use process-level firewalls on the host. Apply rules to the `com.docker.vpnkit` user-space process to control where it can connect (DNS allowlists, packet filters) and which ports/protocols it can use. From b20238c99bd37602e4c47cbdde05112191b56b43 Mon Sep 17 00:00:00 2001 From: Sarah Sanders Date: Thu, 14 Aug 2025 14:08:11 -0400 Subject: [PATCH 10/10] Update content/manuals/enterprise/security/domain-management.md Co-authored-by: Craig Osterhout <103533812+craig-osterhout@users.noreply.github.com> --- content/manuals/enterprise/security/domain-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/manuals/enterprise/security/domain-management.md b/content/manuals/enterprise/security/domain-management.md index 3e649601dbc5..5b169ea0b70c 100644 --- a/content/manuals/enterprise/security/domain-management.md +++ b/content/manuals/enterprise/security/domain-management.md @@ -173,6 +173,6 @@ To delete a domain: your organization. If your organization is part of a company, select the company and configure the domain for the organization at the company level. 1. Select **Admin Console**, then **Domain management**. -1. For the domain you want to delete, section the **Actions** menu, then +1. For the domain you want to delete, select the **Actions** menu, then **Delete domain**. 1. To confirm, select **Delete domain** in the pop-up modal.