本人新书上市,请多多关照:《SQL Server On Linux运维实战 2017版从入门到精通》
数据库及数据的安全在今时今日的重要性已经不用多说,那么作为成熟的数据库管理系统,SQL Server特别是SQL Server On Linux上对安全性又作出了什么的改进呢?接下来几篇将向大家介绍一下。在本篇中,主要介绍的是以AD授权方式登录Linux上的SQL Server。
安全简介
下面先看个图,下图的右边是近8年来安全方面的统计,可以看到SQL Server远比其他产品低。左边是SQL Server的纵深防御体系,其中包含了不少从SQL 2016引入的新功能,接下来会介绍。
首先,要多次提醒,安全性永远不是单方面的,它是一整套的安全系统,可以粗略分为平台、身份验证、对象(包含数据)和访问系统的应用程序。这部分可以参考微软的官方文档保护 SQL Server
Active Directory Authentication
如果用过Windows平台上的SQL Server,应该对AD授权有所熟悉,简单来说就是Windows身份验证登录,只是你必须先以AD域的Windows账号登录到Windows,然后再用Windows身份验证连接SQL Server,但是我们知道,AD域是Windows的东西(Linux当然也有域),在Linux上就要多做点事情,幸好Linux也不是绝对地抗拒Windows,所以Linux也有很多必要的包和软件用于加域ad域。可以使用Kerberos,以AD用户身份访问Linux上的SQL Server。这样不仅具有更高的安全性和可管理性,从使用感受上也方便很多,以Windows组的形式管理账号远比使用SQL 身份验证登录并创建大量账号功能项目组和运维人员使用好得多。
由于演示的截图较多,所以本文专门讲这部分的搭建,其他安全方面的功能放到后面的文章中介绍。
工作原理
在开始搭建之前,有必要先介绍一下背景知识,AD授权包含了以下命令很对象:
- realm:Linux上的命令,用于把Linux服务器加入到AD域。需要安装realmd包。
- Ticket Granting Ticket(TGT):一个加密文件发送到票证授予服务器 (tgs) 以请求访问域中的服务 (如 sql server) 的票证。tgs 功能由 windows 域控制器实现。
- kinit:Linux上的命令,用于获取和缓存一个域用户需要用到的TGT。
- Service Principal Name(SPN):一个服务如SQL Server在AD域中的唯一标识。
- keytab:Linux上的文件用于存储加密密钥,这个加密密钥用于校验入站Kerberos授权请求。
- Domain Controller:Windows的域控制器。简称DC。
下面看看在Linux上,SQL Server 的AD认证流程:
- 用户在Linux机器上使用域用户的账号密码执行kinit,kinit会发送信息到DC中。
- DC在验证账号密码是有效之后发起一个TGT。这个过程在Windows机器上使用域用户操作是一样的。
- 使用工具如sqlcmd连接SQL Server,如
SQLCMD -E -S主机名
,-E参数表明使用Windows身份验证。这个时候客户端会发送TGT和SQL Server的SPN到DC上告知用户正常尝试使用AD授权连接Linux上的SQL Server。 - DC返回一个ticket告知现在已经可以连接了。
- SQLCMD使用来自DC的ticket尝试连接SQL Server,SQL Server使用keys验证ticket并放行,当然前提是在SQL Server中已经创建了这个域账号的登录名。
- 进行常规操作。
AD环境搭建
接下来会创建一个AD域,然后使用SQL Server On Linux(1)——CentOS 7 安装SQL Server2019中搭建的环境进行连接。但是要提前说明,由于这个操作相对较新,所以过程很容易出错,建议读者严格按照步骤并小心操作以免出现奇奇怪怪的错误。
现在先安装一台Windows Server,我选用2016,一般建议2012或以上的版本较为合适,毕竟SQL Server已经是2019了,再使用低版本的配套软件不是很合适,当然我也没测试过Windows Server 2008是否可行。安装过程很简单就不截图了,因为本文已经太多图。
安装过后,先配置IP地址,可以参考以下的配置,建议IP段跟Linux所在的IP段相同。
然后用powershell输入ServerManager.exe ,或者图形化界面操作打开服务器管理。如下图,点击【Add roles and features】,因为Linux上用的是英文,所以这里的Windows也使用了英文版,但是读者应该很容易在中文版上找到:
然后按照下图点击【Active Directory Domain Services】,并选择【Add Features】:
注意接下来这里不要勾选重启,因为安装完还要进行操作。直接按【Install】即可:
安装完毕之后,点击下图红框部分:
输入域名,本次演示使用sqlonlinux.net。这个在后续会多次用到,所以这些信息在搭建过程就应该记录下来:
输入恢复用的密码
直接下一步
输入NetBIOS域名:SQLONLINUX
这里保留默认即可。
安装完毕之后重启服务器,你应该会看到下图的样子:
到这里,我们的AD环境已经初步搭建好,本人并没有尝试过,但是作为好习惯,我还是在AD和Linux上添加对应的hosts信息。接下来是对Linux服务器的配置。
Linux配置
首先在Linux上安装realmd:sudo yum install realmd krb5-workstation
。
编辑/etc/sysconfig/network-scripts/ifcfg-eth0文件,如果是其他Linux版本,参考加入SQL Server到AD域的主机,把下图第二个红框的内容填上,DNS1是AD的IP地址。而第一个红框如果没出现问题可以不改,但是作者建议还是修改一下。
修改完/etc/sysconfig/network-scripts/ifcfg-eth0文件之后,使用下面命令重启网络服务:
sudo systemctl restart network
在搭建过程,作者频繁出现下面的报错,经过各种尝试,最终发现不知道什么原因多了个缓存,把它清了即可,缓存的问题在搭建过程出现很多次。
然后检查/etc/resolv.conf文件,是否已经有DNS1的值。
cat /etc/resolv.conf
如果没有出现DNS1的值,那就直接vi /etc/resolv.conf并把这个值写进去。
加入域
本人搭建环境的时候发生了很多问题,最后发现需要先在AD上创建用户,再进行加域,搭建过程参照教程:Linux 上的 SQL Server 使用 Active Directory 身份验证,其中提到realm join会创建用户,但是有时候也需要手动创建,很不幸我遇到了。那么接下来先在AD上创建一个用户sql:
在Linux上执行sudo realm join 域名 -U 'user@realm name' -v
,域名是小写,realm name是大写,如果不知道这个信息,可以执行realm list
,如下图,注意大小写。
在本例中,按照下图输入:
realm join sqlonlinux.net -U 'sql@SQLONLINUX.NET' -v
然后会提示输入在AD上新建的sqlonlinux\sql这个账号的密码,输入完毕后,就可以进行入域过程,成功之后会出现下图红框的内容。证明已经加域成功。
如果加入不成功,可以考虑检查一下两边的host文件、防火墙等配置。
加域之后,顺带验证一下信息,可以使用下面命令检验,还可以使用klist获取Kerberos票证
id sql@sqlonlinux.net
kinit sql@SQLONLINUX.NET #注意后面是大写。执行后这一步会提示输入密码
klist
本机结果如下,暂时先不深究这些内容
设置SPN
这一步是在AD上进行,上面工作原理处说过。SPN是在AD中一个服务的唯一标识,如果没有这个SPN,那么识别域中多个SQL Server将非常麻烦。接下来按照步骤进行:
创建AD上的新用户
在DC(在非专业的情况下,其实AD和DC可以混一下,不过AD是活动目录,DC则是活动目录下的一个域控)上使用powershell输入以下命令,其中除了第二行的mssql可以改成你随意的名字之外,其他原样输入即可,由于SQL On Linux的默认启动账号就是mssql,所以本人也习惯使用mssql来作账号:
Import-Module ActiveDirectory
New-ADUser mssql -AccountPassword (Read-Host -AsSecureString "Enter Password") -PasswordNeverExpires $true -Enabled $true
输入之后,系统会提示你输入mssql的新密码。在AD上有专用的SQL账号而不跟其他服务公用是安全方面的推荐操作。
设置SPN
使用setspn工具进行,但是必须使用完全限定的域名(fully qualified domain name,FQDN),这个可以在Linux上使用hostname --all-fqdns来获取:
获取之后,在powershell中输入格式为setspn -A MSSQLSvc/: mssql的内容,本环境如下,如果改过端口,也要同步修改端口号:
setspn -A MSSQLSvc/sqlcentos:1433 mssql
配置 SQL Server服务的keytab
获取上一步在AD中创建的账号的密钥版本编号(kvno),注意这里是sql而不是mssql这个账号。通常这个值是2,但是有可能不一样,在Linux上运行kinit sql@SQLONLINUX.NET 然后输入密码,再运行kvno MSSQLSvc/sqlcentos:1433,命令的原始格式如下:
kinit user@CONTOSO.COM
kvno MSSQLSvc/**<fully qualified domain name of host machine>**:**<tcp port>**
结果如下图:
使用ktutil工具,在Linux创建keytab文件,前两步会出现提示,此时输入对应的密码即可,原始格式如下,需要修改的地方是“MSSQLSvc/:@CONTOSO.COM”和“”
sudo ktutil
ktutil: addent -password -p MSSQLSvc/**<fully qualified domain name of host machine>**:**<tcp port>**@CONTOSO.COM -k **<kvno from above>** -e aes256-cts-hmac-sha1-96
ktutil: addent -password -p MSSQLSvc/**<fully qualified domain name of host machine>**:**<tcp port>**@CONTOSO.COM -k **<kvno from above>** -e rc4-hmac
ktutil: wkt /var/opt/mssql/secrets/mssql.keytab
quit
本例的具体代码:
使用ktutil工具吧计算机账号加到keytab中,如下:
ktutil
rkt /etc/krb5.keytab
list
quit
由于默认情况下该文件是完全开放的,为了避免被误操作或者恶意攻击,应该修改权限,仅对mssql账号可用:
sudo chown mssql:mssql /var/opt/mssql/secrets/mssql.keytab
sudo chmod 400 /var/opt/mssql/secrets/mssql.keytab
然后使用这个keytab文件作为SQL Server的Kerberos身份验证文件,并重启SQL Server服务:
sudo /opt/mssql/bin/mssql-conf set network.kerberoskeytabfile /var/opt/mssql/secrets/mssql.keytab
sudo systemctl restart mssql-server
如下图:
测试效果
下面就可以测试是否成功,首先需要在SQL Server中创建账号,为了简单期间,作者直接使用SQLCMD实现,并且检查sys.server_principals视图是否已经创建成功,结果如下:
为了方便起见,作者直接在DC上安装SSMS客户端,注意这一步是不合理的,DC应该尽可能保持干净,这里仅作为实验所需,正式环境下应该使用域中的某些服务器来完成。注意下图,这里使用sqlonlinux\sql这个域用户登录到Windows,然后使用Windows身份验证连接。
从下图可以看到连接成功,证明已经可以实现我们的初步功能,后续的操作在需要的时候再进行深化。
总结
基于Active Directory授权的登录SQL On Linux的操作到此为止,截图和步骤都很多。很容易出现问题,所以建议读者根据步骤一步一步进行,其实官方教程中还有更多的步骤和异常提示,不过作者没遇到的话有些不好模拟,读者在搭建过程中如果发现问题,可以参考一下官方文档:教程:Linux 上的 SQL Server 使用 Active Directory 身份验证。下一文开始聊一下其他SQL Server On Linux或者SQL Server 2016开始引入的心的安全特性。