保护 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 容器的详细信息,请参阅配置安全性。
下载适用于非根 SQL Server 容器的示例 Dockerfile,并将其另存为
dockerfile
。在 dockerfile 目录的上下文中运行以下命令,生成非根 SQL Server 容器:
cd <path to dockerfile> docker build -t 2017-latest-non-root .
启动容器。
重要
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
标志来生成用于排除故障的转储。检查是否以非根用户的身份运行容器:
docker exec -it sql1 bash
运行
whoami
,这将返回容器中运行的用户。whoami
在主机上以其他非根用户的身份运行容器
若要以其他非根用户的身份运行 SQL Server 容器,请将 -u
标志添加到 docker run
命令。 非根容器具有以下限制:必须作为 root
组的一部分运行,除非已将卷装载到非根用户可以访问的 /var/opt/mssql
。 root
组不向非根用户授予任何额外的根权限。
以具有 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 容器具有命名用户,如 mssql
或 root
,否则 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
下默认创建多个文件(例如密钥表、证书和计算机密钥),并且默认仅限 mssql
和 root
用户访问。 为 SQL Server 容器配置永久性存储时,请使用相同的访问策略,确保映射到容器中的 /var/opt/mssql/secrets
文件夹的主机或共享卷上的路径受到保护,并且仅供主机上的 mssql
和 root
用户访问。 如果对此路径/文件夹的访问受到威胁,恶意用户可能会获得对这些关键文件的访问权限,从而破坏加密层次结构和/或 Active Directory 配置。
若要加密与 SQL Server Linux 容器的连接,需要具有以下要求的证书。
下面的示例展示了如何加密与 SQL Server Linux 容器的连接。 现在,我们使用自签名证书,此证书不应用于生产方案。 对于此类环境,应改用 CA 证书。
创建自签名证书,该证书仅适用于测试和非生产环境。
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/
已存在。确保为
mssql.key
和mssql.pem
文件设置正确的权限,以避免在将文件装载到 SQL Server 容器时出现错误:chmod 440 /container/sql1/mssql.pem chmod 440 /container/sql1/mssql.key
现在,创建包含以下内容的
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.conf
、mssql.key
和mssql.pem
。使用以下命令部署 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.conf
、mssql.pem
和mssql.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) 容器映像