保护 SQL Server Linux 容器

适用于: SQL Server - Linux

SQL Server 2017 (14.x) 容器默认以根用户身份启动,这可能会导致一些安全问题。 本文介绍了在运行 SQL Server Linux 容器时具有的安全选项,以及如何以非根用户身份生成 SQL Server 容器。

本文中的示例假设你使用的是 Docker,但你可以将相同的原则应用于包括 Kubernetes 在内的其他容器业务流程工具。

生成并运行非根 SQL Server 2017 容器

按照以下步骤生成一个以 mssql(非根)用户身份启动的 SQL Server 2017 (14.x) 容器。

注意

SQL Server 2019 (15.x) 及更高版本容器以非根用户的身份自动启动,而 SQL Server 2017 (14.x) 容器在默认情况下以根用户的身份启动。 有关以非根用户的身份运行 SQL Server 容器的详细信息,请参阅配置安全性

  1. 下载适用于非根 SQL Server 容器的示例 Dockerfile,并将其另存为 dockerfile

  2. 在 dockerfile 目录的上下文中运行以下命令,生成非根 SQL Server 容器:

    cd <path to dockerfile>
    docker build -t 2017-latest-non-root .
    
  3. 启动容器。

    重要

    SA_PASSWORD 环境变量已弃用。 请改用 MSSQL_SA_PASSWORD

    docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyStrongPassword@" --cap-add SYS_PTRACE --name sql1 -p 1433:1433 -d 2017-latest-non-root
    

    注意

    非根 SQL Server 容器需要 --cap-add SYS_PTRACE 标志来生成用于排除故障的转储。

  4. 检查是否以非根用户的身份运行容器:

    docker exec -it sql1 bash
    

    运行 whoami,这将返回容器中运行的用户。

    whoami
    

在主机上以其他非根用户的身份运行容器

若要以其他非根用户的身份运行 SQL Server 容器,请将 -u 标志添加到 docker run 命令。 非根容器具有以下限制:必须作为 root 组的一部分运行,除非已将卷装载到非根用户可以访问的 /var/opt/mssqlroot 组不向非根用户授予任何额外的根权限。

以具有 UID 4000 的用户身份运行

可使用自定义 UID 启动 SQL Server。 例如,以下命令使用 UID 4000 启动 SQL Server:

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyStrongPassword" --cap-add SYS_PTRACE -u 4000:0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest

警告

确保 SQL Server 容器具有命名用户,如 mssqlroot,否则 sqlcmd 将无法在容器中运行。 可通过在容器中运行 whoami 来检查是否以命名用户的身份运行 SQL Server 容器。

以根用户的身份运行非根容器

如有必要,可以以根用户身份运行非根容器,这也会自动向容器授予所有文件权限,因为它具有更高的特权。

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyStrongPassword" -u 0:0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest

在主机计算机上以用户的身份运行

可使用以下命令在主机计算机上以现有用户身份启动 SQL Server:

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyStrongPassword" --cap-add SYS_PTRACE -u $(id -u myusername):0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest

以其他用户和组的身份运行

可使用自定义用户和组启动 SQL Server。 在此示例中,已装载的卷具有为主机计算机上的用户或组配置的权限。

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyStrongPassword" --cap-add SYS_PTRACE -u $(id -u myusername):$(id -g myusername) -v /path/to/mssql:/var/opt/mssql -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest

为非根容器配置持久存储权限

若要允许非根用户访问已装载卷上的数据库文件,请确保以可读取/写入永久性文件存储的用户身份或组成员身份运行容器。

可通过此命令获取数据库文件的当前所有权。

ls -ll <database file dir>

如果 SQL Server 无权访问持久数据库文件,请运行以下命令之一。

授予根组对数据库文件的读/写访问权限

授予对以下目录的根组权限,使非根 SQL Server 容器有权访问数据库文件。

chgrp -R 0 <database file dir>
chmod -R g=u <database file dir>

将非根用户设置为文件的所有者

这可以是默认的非根用户,也可以是要指定的任何其他非根用户。 在此示例中,我们将 UID 10001 设置为非根用户。

chown -R 10001:0 <database file dir>

加密与 SQL Server Linux 容器的连接

重要

配置 Active Directory 身份验证或加密选项(例如透明数据加密 (TDE) 和用于 Linux 或容器上的 SQL Server 的 SSL)时,文件夹 /var/opt/mssql/secrets 下默认创建多个文件(例如密钥表、证书和计算机密钥),并且默认仅限 mssqlroot 用户访问。 为 SQL Server 容器配置永久性存储时,请使用相同的访问策略,确保映射到容器中的 /var/opt/mssql/secrets 文件夹的主机或共享卷上的路径受到保护,并且仅供主机上的 mssqlroot 用户访问。 如果对此路径/文件夹的访问受到威胁,恶意用户可能会获得对这些关键文件的访问权限,从而破坏加密层次结构和/或 Active Directory 配置。

若要加密与 SQL Server Linux 容器的连接,需要具有以下要求的证书。

下面的示例展示了如何加密与 SQL Server Linux 容器的连接。 现在,我们使用自签名证书,此证书不应用于生产方案。 对于此类环境,应改用 CA 证书。

  1. 创建自签名证书,该证书仅适用于测试和非生产环境。

    openssl req -x509 -nodes -newkey rsa:2048 -subj '/CN=sql1.contoso.com' -keyout /container/sql1/mssql.key -out /container/sql1/mssql.pem -days 365
    

    在上述代码示例中,sql1 是 SQL 容器的主机名,因此,连接到此容器时,连接字符串中使用的名称将为 sql1.contoso.com,port。 运行上述命令之前,还请确保文件夹路径 /container/sql1/ 已存在。

  2. 确保为 mssql.keymssql.pem 文件设置正确的权限,以避免在将文件装载到 SQL Server 容器时出现错误:

    chmod 440 /container/sql1/mssql.pem
    chmod 440 /container/sql1/mssql.key
    
  3. 现在,创建包含以下内容的 mssql.conf 文件以启用服务器发起的加密。 对于客户端发起的加密,将最后一行更改为 forceencryption = 0

    [network]
    tlscert = /etc/ssl/certs/mssql.pem
    tlskey = /etc/ssl/private/mssql.key
    tlsprotocols = 1.2
    forceencryption = 1
    

    注意

    对于某些 Linux 分发版,存储证书和密钥的路径还可以分别为 /etc/pki/tls/certs/ 和 /etc/pki/tls/private/。 更新 SQL Server 容器的 mssql.conf 之前,请先验证路径。 SQL Server 将根据你在 mssql.conf 中设置的位置在容器中搜索证书及其密钥。 在本例中,该位置是 /etc/ssl/certs//etc/ssl/private/

    还会在同一文件夹位置 /container/sql1/ 下创建 mssql.conf 文件。 运行上述步骤后,sql1 文件夹中应有三个文件:mssql.confmssql.keymssql.pem

  4. 使用以下命令部署 SQL Server 容器:

    docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=P@ssw0rd" -p 5434:1433 --name sql1 -h sql1 -v /container/sql1/mssql.conf:/var/opt/mssql/mssql.conf -v   /container/sql1/mssql.pem:/etc/ssl/certs/mssql.pem -v /container/sql1/mssql.key:/etc/ssl/private/mssql.key -d mcr.microsoft.com/mssql/server:2019-latest
    

    在前面的命令中,我们已将 mssql.confmssql.pemmssql.key 文件装载到容器中,并将容器中的 1433 端口(SQL Server 默认端口)映射到主机的 5434 端口。

    注意

    如果使用 RHEL 8 和更高版本,则还可以使用 podman run 命令来代替 docker run

按照客户端启动的加密中的“在客户端计算机上注册证书”和“示例连接字符串”部分的说明,开始加密与 Linux 上的 SQL Server 容器的连接。

  • 通过查看快速入门,开始在 Docker 上使用 SQL Server 2017 (14.x) 容器映像
  • 通过查看快速入门,开始在 Docker 上使用 SQL Server 2019 (15.x) 容器映像
  • 通过查看快速入门,开始在 Docker 上使用 SQL Server 2022 (16.x) 容器映像