为Windows客户端配置Kerberos

为Windows客户端配置Kerberos

可以配置微软的Windows客户端应用来连接一个配置为用Kerberos认证的Greenplum数据库系统。

有关在Greenplum数据库中配置Kerberos认证的信息请见使用Kerberos认证

在Windows上为Greenplum数据库客户端配置Kerberos

当一个Greenplum数据库系统被配置为用Kerberos作认证后,可以为微软Windows系统上的Greenplum数据库客户端工具gploadpsql配置Kerberos认证。Greenplum数据库的客户端直接使用Kerberos认证,而不使用微软的活动目录(AD)。

这一节包含下列信息。

这些主题假设Greenplum数据库系统已经被配置为用Kerberos和微软的活动目录认证。见用活动目录配置客户端认证

在一个Windows系统上安装Kerberos

要对一个Windows系统上的Greenplum数据库客户端使用Kerberos认证,该系统上必须安装MIT Kerberos Windows客户端。可以在http://web.mit.edu/kerberos/dist/index.html上获得并且安装MIT Kerberos for Windows 4.0.1 (for krb5)来得到这些客户端。

在Windows系统上,用户使用Kerberos的kinit工具管理Kerberos的ticket。

Kerberos服务没有被设置为自动启动。该服务不能被用来认证Greenplum数据库。

为来自Greenplum数据库的Master的Kerberos配置文件/etc/krb5.conf创建一个拷贝并且把它放在Windows系统的默认Kerberos位置C:\ProgramData\MIT\Kerberos5\krb5.ini。在文件小节[libdefaults]中,移除Kerberos的ticket缓冲的位置default_ccache_name

在Windows系统上,使用环境变量KRB5CCNAME指定Kerberos ticket的位置。这个环境变量的值是一个文件而不是目录,并且它应该对服务器上的每一个登录都是唯一的。

这是一个移除了default_ccache_name的样例配置文件。还有,小节[logging]也被移除。

[libdefaults]
 debug = true
 default_etypes = aes256-cts-hmac-sha1-96
 default_realm = EXAMPLE.LOCAL
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

[realms]
 EXAMPLE.LOCAL = {
  kdc =bocdc.example.local
  admin_server = bocdc.example.local
 }

[domain_realm]
 .example.local = EXAMPLE.LOCAL
 example.local = EXAMPLE.LOCAL

在用KRB5CCNAME指定一个Kerberos ticket时,可以在一个本地用户环境或者一个会话中设置该值。这些命令设置KRB5CCNAME、运行kinit并且运行批处理文件来为Greenplum数据库的客户端设置环境变量。

set KRB5CCNAME=%USERPROFILE%\krb5cache
kinit

"c:\Program Files (x86)\Greenplum\greenplum-clients-<version>\greenplum_clients_path.bat"

运行psql工具

在Windows系统上安装并且配置Kerberos及其ticket之后,可以运行Greenplum数据库的命令行客户端psql

如果得到警告指出控制台代码页与Windows代码页不同,可以运行Windows工具chcp来改变代码页。这是一个该警告的例子及修正。

psql -h prod1.example.local warehouse
psql (8.3.23)
WARNING: Console code page (850) differs from Windows code page (1252)
 8-bit characters might not work correctly. See psql reference
 page "Notes for Windows users" for details.
Type "help" for help.

warehouse=# \q

chcp 1252
Active code page: 1252

psql -h prod1.example.local warehouse
psql (8.3.23)
Type "help" for help.

创建一个Kerberos的keytab文件

在连接到Greenplum数据库系统时,可以创建并使用一个KerberosKerberos keytab文件来避免在命令行输入密码或者在脚本文件中列出密码。可以用这些工具创建keytab文件:
  • Windows Kerberos工具ktpass
  • Java JRE keytab工具ktab

    如果使用AES256-CTS-HMAC-SHA1-96加密,需要从Oracle下载并安装Java扩展Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE。这个命令创建keytab文件svcPostgresProd1.keytab

作为一个AD域管理员运行ktpass工具。这个工具期望一个用户账户有一个被定义为AD用户属性的服务主体名称(SPN),不过这似乎并不是必需的。可以指定它作为ktpass的一个参数并且忽略它不能被设置的警告。

Java JRE的ktab工具不要求AD域管理员并且不要求SPN。

注意: 当输入密码来创建keytab文件时,密码在屏幕上是可见的。

这个例子运行ktpass工具来创建keytab文件dev1.keytab

ktpass -out dev1.keytab -princ dev1@EXAMPLE.LOCAL -mapUser dev1 -pass your_password -crypto all -ptype KRB5_NT_PRINCIPAL

它会不顾警告消息Unable to set SPN mapping data工作下去。

这个例子运行Java的ktab.exe来创建一个keytab文件(-a选项)并且列出该keytab的名称和条目(-l -e -t选项)。

C:\Users\dev1>"\Program Files\Java\jre1.8.0_77\bin"\ktab -a dev1
Password for dev1@EXAMPLE.LOCAL:your_password
Done!
Service key for dev1 is saved in C:\Users\dev1\krb5.keytab

C:\Users\dev1>"\Program Files\Java\jre1.8.0_77\bin"\ktab -l -e -t
Keytab name: C:\Users\dev1\krb5.keytab
KVNO Timestamp Principal
---- -------------- ------------------------------------------------------
 4 13/04/16 19:14 dev1@EXAMPLE.LOCAL (18:AES256 CTS mode with HMAC SHA1-96)
 4 13/04/16 19:14 dev1@EXAMPLE.LOCAL (17:AES128 CTS mode with HMAC SHA1-96)
 4 13/04/16 19:14 dev1@EXAMPLE.LOCAL (16:DES3 CBC mode with SHA1-KD)
 4 13/04/16 19:14 dev1@EXAMPLE.LOCAL (23:RC4 with HMAC)

You can then use a keytab with the following:

kinit -kt dev1.keytab dev1
or
kinit -kt %USERPROFILE%\krb5.keytab dev1

gpload YAML文件实例

这是一个以dev1用户运行gpload任务的例子,该用户通过AD域登录到Windows桌面。

test.yaml控制文件例子中,USER:行已经被移除。这里使用了Kerberos认证。

---
VERSION: 1.0.0.1
DATABASE: warehouse
HOST: prod1.example.local
PORT: 5432

GPLOAD:
   INPUT:
    - SOURCE:
         PORT_RANGE: [18080,18080]
         FILE:
           - /Users/dev1/Downloads/test.csv
    - FORMAT: text
    - DELIMITER: ','
    - QUOTE: '"'
    - ERROR_LIMIT: 25
    - LOG_ERRORS: true
   OUTPUT:
    - TABLE: public.test
    - MODE: INSERT
   PRELOAD:
    - REUSE_TABLES: true

这些命令运行kinit,接着用test.yaml文件运行gpload并且显示成功的gpload输出。

kinit -kt %USERPROFILE%\krb5.keytab dev1

gpload.py -f test.yaml
2016-04-10 16:54:12|INFO|gpload session started 2016-04-10 16:54:12
2016-04-10 16:54:12|INFO|started gpfdist -p 18080 -P 18080 -f "/Users/dev1/Downloads/test.csv" -t 30
2016-04-10 16:54:13|INFO|running time: 0.23 seconds
2016-04-10 16:54:13|INFO|rows Inserted = 3
2016-04-10 16:54:13|INFO|rows Updated = 0
2016-04-10 16:54:13|INFO|data formatting errors = 0
2016-04-10 16:54:13|INFO|gpload succeeded

问题和可能的解决方案

  • 这个消息表示Kerberos无法找到缓冲文件:
    Credentials cache I/O operation failed XXX
    (Kerberos error 193)
    krb5_cc_default() failed

    要确保Kerberos能找到该文件,应该设置环境变量KRB5CCNAME并且运行kinit

    set KRB5CCNAME=%USERPROFILE%\krb5cache
    kinit
  • 这个kinit消息表示kinit -k -t命令不能找到keytab。
    kinit: Generic preauthentication failure while getting initial credentials

    确认该Kerberos keytab文件的完整路径和文件名是正确的。

用活动目录配置客户端认证

可以用一个微软活动目录(AD)账号配置一个微软Windows用户用于单点登录到Greenplum数据库系统。

可以配置一个AD用户账号来支持用Kerberos认证登录。

通过AD单点登录,一个Windows用户可以使用活动目录证书和一个Windows客户端应用来登入Greenplum数据库系统。对于使用ODBC的Windows应用,ODBC驱动能使用活动目录证书来连接到Greenplum数据库系统。

注意: gpload这样的运行在Windows上的Greenplum数据库客户端直接连接Greenplum数据库而不使用活动目录。有关用Kerberos认证把Windows上的Greenplum数据库客户端连接到Greenplum数据库系统的信息,请见在Windows上为Greenplum数据库客户端配置Kerberos

先决条件

启用对Greenplum数据库系统的AD单点登录要求这些项目。

  • Greenplum数据库系统必须配置为支持Kerberos认证。有关配置Greenplum数据库支持Kerberos认证的信息,请见为Windows客户端配置Kerberos
  • 必须知道Greenplum数据库的Master主机的全称域名(FQDN)。还有,Greenplum数据库的Master主机名必须有一个域名部分。如果系统没有域,必须配置系统使用一个域。

    这个Linux的hostname命令显示FQDN。

    hostname --fqdn
  • 必须把Greenplum数据库系统配置为与活动目录域具有相同的日期和时间。例如,可以把Greenplum数据库系统的NTP时间源设置为一个AD域控制器,或者把Master主机设置为使用和AD域控制器相同的外部时间源。
  • 要支持单点登录,需要把一个AD用户账户配置为一个AD中的托管服务账号。对于Kerberos认证有这些要求。
    • 需要对用户账户信息增加服务主体名称(SPN)属性,因为Kerberos工具在Kerberos认证期间会要求该信息。
    • 还有,由于Greenplum数据库能够无人值守启动,还必须在一个Kerberos keytab文件中提供账号登录细节。
    注意: 设置SPN和创建keytab要求AD的管理权限。

活动目录设置

AD命名习惯应该支持多个Greenplum数据库系统。在这个例子中,我们会为Greenplum数据库系统prod1的Master主机创建一个新的AD托管服务账户svcPostresProd1

活动目录的域是example.local

Greenplum数据库的Master主机的全称域名是prod1.example.local

我们将把SPN postgres/prod1.example.local添加到这个账户。其他Greenplum数据库系统的服务账户都将是postgres/fully.qualified.hostname的形式。



在这个例子中,AD的密码被设置为永不过期并且用户不能更改。只有在创建Kerberos keytab文件时才需要AD账户的密码。不需要把它提供给数据库管理员。



AD管理员必须用Windows的setspn命令从命令行把服务主体名称属性添加到账户。这个示例命令把AD用户svcPostgresProd1的SPN属性值设置为postgres/prod1.example.local

setspn -A postgres/prod1.example.local svcPostgresProd1

如果在活动目录的用户和计算机视图中设置了高级特性,用户可以看到这个SPN。如果有必要,可以在属性编辑器页面找到servicePrincipalName并且编辑它。



下一步是创建一个Kerberos keytab文件。

如果安全性需求要求一种特定的加密方法,可以选择它,但如果该方法不存在,最好是先让它能用然后再移除其他不想要的加密方法。

作为一个AD域管理员,可以用这个ktpass命令列出AD域控制器支持的加密类型:

ktpass /? 
作为一个AD域管理员,可以运行ktpass命令来创建一个keytab文件。这个示例命令用下面的信息创建文件svcPostgresProd1.keytab
  • ServicePrincipalName (SPN): postgres/prod1.example.local@EXAMPLE.LOCAL
  • AD用户: svcPostgresProd1
  • 加密方法: AD上所有可用的方法
  • 主体类型: KRB5_NT_PRINCIPAL
ktpass -out svcPostgresProd1.keytab -princ postgres/prod1.example.local@EXAMPLE.LOCAL -mapUser svcPostgresProd1
   -pass your_password -crypto all -ptype KRB5_NT_PRINCIPAL
注意: AD域@EXAMPLE.LOCAL会被追加到该SPN。

复制keytab文件svcPostgresProd1.keytab到Greenplum数据库的Master主机。

另一种作为AD域管理员运行ktpass的方法是,如果在桌面机上安装了Java JRE,则可以运行Java的ktab.exe工具来生成一个keytab文件。当使用ktpass或者ktab.exe输入密码时,密码将会作为一个命令行参数被显示在屏幕上。

这个示例命令创建这个keytab文件svcPostgresProd1.keytab
"c:\Program Files\Java\jre1.8.0_77\bin\ktab.exe" -a svcPostgresprod1 -k svcPostgresProd1.keytab
Password for svcPostgresprod1@EXAMPLE.LOCAL:your_password
Done!
Service key for svcPostgresprod1 is saved in svcPostgresProd1.keytab
注意: 如果使用AES256-CTS-HMAC-SHA1-96加密,必须从Oracle下载并安装Java扩展Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE

活动目录的Greenplum数据库设置

这些指令假定在Greenplum数据库的Master主机上安装了Kerberos工作站工具krb5-workstation

用一个AD域控制器的AD域名细节和位置更新/etc/krb5.conf。这是一个配置的例子。

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.LOCAL
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

[realms]
 EXAMPLE.LOCAL = {
 kdc = bocdc.example.local
 admin_server = bocdc.example.local
 }

[domain_realm]
 .example.local = EXAMPLE.LOCAL
 example.com = EXAMPLE.LOCAL

把含有AD用户信息的Kerberos keytab文件复制到Greenplum数据库的Master目录中。这个例子复制在活动目录设置中创建的svcPostgresProd1.keytab

mv svcPostgresProd1.keytab $MASTER_DATA_DIRECTORY
chown gpadmin:gpadmin $MASTER_DATA_DIRECTORY/svcPostgresProd1.keytab
chmod 600 $MASTER_DATA_DIRECTORY/svcPostgresProd1.keytab

把这一行作为最后一行添加到Greenplum数据库的pg_hba.conf文件。对于不匹配之前任何一行的连接尝试,这一行配置Greenplum数据库为它使用活动目录认证。

host all all 0.0.0.0/0 gss include_realm=0

用keytab文件的位置细节以及要使用的主体名称更新Greenplum数据库的postgresql.conf。全称主机名和来自/etc/krb5.conf的默认realm构成了完整的服务主体名称。

krb_server_keyfile = '/data/master/gpseg-1/svcPostgresProd1.keytab'
krb_srvname = 'postgres'

为这个AD用户创建一个数据库角色。这个例子登入到默认数据库并且运行CREATE ROLE命令。用户dev1活动目录设置中创建keytab文件时指定的用户。

psql
create role dev1 with login superuser;

重启数据库以使用更新后的认证信息:

gpstop -a
gpstart  
注意: Greenplum数据库的库可能会与Kerberos工作站工具(如kinit)发生冲突。如果在Greenplum数据库的Master上运行这些工具,可以运行一个不引用$GPHOME/greenplum_path.sh脚本的gpadmin shell,或者像这个例子一样复位LD_LIBRARY_PATH环境变量:
unset LD_LIBRARY_PATH
kinit
source $GPHOME/greenplum_path.sh

用Kerberos认证确认Greenplum数据库访问:

kinit dev1
psql -h prod1.example.local -U dev1

单点登录实例

这些使用AD和Kerberos的单点登录实例假设配置为单点登录的AD用户dev1被登入到Windows桌面。

这个例子为Greenplum数据库配置Aginity Workbench。在使用单点登录时,请启用“Use Integrated 安全性”。



这个例子配置一个ODBC源。在设置该ODBC源时,不要输入用户名或密码。这个DSN接着可以被应用程序用作一个ODBC数据源。



可以用一个R客户端使用这个DSN testdata。这个例子配置R来访问该DSN。

library("RODBC")
conn <- odbcDriverConnect("testdata")
sql <- "select * from public.data1"
my_data <- sqlQuery(conn,sql)
print(my_data)

活动目录的问题和可能的解决方案

  • Kerberos的ticket含有的版本号必须匹配AD的版本号。

    要显示keytab文件中的版本号,可使用klist -ket命令。例如:

    klist -ket svcPostgresProd1.keytab

    要从AD域控制器得到相应的值,可作为一个AD管理员运行这个命令:

    kvno postgres/prod1.example.local@EXAMPLE.LOCAL
  • 当Windows ID和Greenplum数据库用户角色ID不匹配时会发生这个登录错误。这个日志文件项显示了该登录错误。用户dev22尝试从一个Windows桌面登录,而该桌面上登录了一个不同的Windows用户。
    2016-03-29 14:30:54.041151 PDT,"dev22","gpadmin",p15370,th2040321824,
      "172.28.9.181","49283",2016-03-29 14:30:53 PDT,1917,con32,,seg-1,,,x1917,sx1,
      "FATAL","28000","authentication failed for user ""dev22"": valid 
      until timestamp expired",,,,,,,0,,"auth.c",628,

    当用户能被认证但没有一个Greenplum数据库用户角色时,也会发生这个错误。

    确保该用户是用的是正确的Windows ID并且为该用户ID配置了一个Greenplum数据库用户角色。

  • 当Kerberos keytab不含有一种与正在尝试连接的客户端相匹配的加密类型时,会发生下面这种错误。
    psql -h 'hostname' postgres
    psql: GSSAPI continuation error: Unspecified GSS failure. Minor code may provide more information
    GSSAPI continuation error: Key version is not available

    解决方案是使用ktutil增加额外的加密类型到该keytab或者用来自AD的所有加密系统重新创建postgres的keytab。