暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Ozone 安全认证简介及实践

数据湖技术 2020-05-14
1991

Apache Ozone是基于Hadoop分布式数据存储服务构建的分布式对象存储。它可以管理其他分布式文件系统难以处理的数十亿个大小文件。数据和用户的增长要求Ozone必须要能够保证数据的安全性。Ozone 在0.4.0版本以后已经增加了安全相关的支持,本文将重点介绍Ozone中的安全身份认证这个过程。所谓身份认证就是为Ozone的各个组件提供用户身份识别的功能。Ozone 与Hadoop的安全框架是兼容的,同样支持Kerberos以及Security Token的身份认证。下面的内容会介绍基本的身份认证概念流程以及在Ozone中的Kerberos认证实践。

1. 基于 Kerberos 的认证

Kerberos 认证简介

Kerberos是一种由MIT(麻省理工大学)提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。在Kerberos认证中,最主要的问题是如何证明“你是你”的问题。当一个Client去访问Server服务器上的某服务时,Server如何判断Client是否有权限来访问自己主机上的服务,同时保证在这个过程中的通讯内容即使被拦截或篡改也不影响通讯的安全性。

Kerberos认证体系中包含三个重要的角色,分别是访问服务的Client,提供服务的Server以及密钥分发中心KDC(Key Distribution Center)。在Kerberos中,Client是否有权限访问Server的服务需要通过KDC的Ticket来决定。KDC分为Authentication Server(AS) 和Ticket Granting Server (TGS) 两部分

  • AS的作用是验证Client的身份,即证明client是其本人,验证通过就会发给一张TGT(Ticket Granting Ticket)给Client。
  • TGS的作用是通过TGT来获得访问Server端的Ticket。

整个过程如下图所示

Ozone Kerberos认证架构

如下图所示,Ozone 中的各个服务OM,SCM以及Datanode 都通过Kerberos进行相互认证。Ozone中的各个服务组件都需要配置对应的Kerberos Principal以及Keytab文件以用于服务在启动阶段的安全认证。在下面的小节会介绍Ozone中关于Kerberos安全认证相关的配置以及实践。从上一小节可以得知,作为Ozone的Client必须要有合法的Kerberos Tickets才能访问Ozone集群的任何资源,比如通过访问OzoneManager来获得对象的信息或者是对Datanode进行读写操作。

访问Token

Ozone Manager的Token机制跟Hadoop的Delegation Token类似,Ozone Manager为那些通过Kerberos 认证的用户发放Delegation Token以及Block Token。Token 验证者可以验证令牌的签名,以验证发行者的身份,这样一个合法的Token持有者就能访问集群中的service资源,因为他们的Token是从这个合法的发行者处获得的。

Ozone Manager颁发的Delegation Token 允许Token持有者能够访问OM的Metadata服务,例如创建volume或者是查看一个bucket里面有多少的key。Ozone Manager会对来自客户端的请求中携带的Delegation Token进行校验签名。

与Delegation Token类似,Ozone Manager 会为些需要在Datanode上进行Block读写操作的请求分配Block Token,Block Token在Datanode上进行校验,Client无法显式对Block Token进行Renew操作,一旦Block Token过期,Client必须重新获取block的信息并获得到一个新的Block Token。

S3密钥的生成

Ozone支持S3协议通过Ozone S3 Gateway来访问Ozone。在安全模式下,Ozone Manager会生成S3所需的ID和KEY,其中ID即为认证的用户名,在一次生成后这些安全的信息会被记录到OM的metadata信息中。

Ozone Token 如何工作

Hadoop的Delegation Token的工作流程如下图所示,这种类对称加密的方式,Delegation Token和Block Token 在Token发放者和Token校验者之间都依赖一个共享的秘钥。因此,Token 发放者和校验者在不同的实例上的时候,token共享的秘钥必须在两个实例之间保持同步。

Ozone采用类似非对称加密的认证的方式,如下图所示,Token发送方和校验方被完全解耦,在这种方式下,Token发送方生成一个Private Key,然后Token验证方会使用Public Key进行校验,这种方式相比于Hadoop需要在网络中传播密钥的对称加密方式更加的安全。

在安全模式下,SCM会作为CA(Certificate Authority)启动并创建自身的CA认证,Datanode和OM必须通过SCM的CA进行注册。SCM通过Kerberos对Datanode和OM进行校验后,发放对应的证书给OM以及Datanode,使其能够证明自己的身份。

对于Block Token来说,OM用自身的Private Key对Token进行签名,随后Datanode使用Public Key对Token进行校验,OM和Datanode都授信于SCM这个CA,因此这步校验是可信的。

对于Delegation Token来说,OM即是Token的发放者也是校验者。当OM开启HA的情况的时候,会有多个OM实例,此时OM1发放并签名的Delegation Token依然可以被OM2校验,因为这些OM实例都授信于SCM这个CA。

2. Ozone Kerberos实践

  1. KDC准备工作
  • 安装Kerberos相关组件
root@ubuntu1:~$ apt install krb5-kdc krb5-admin-server krb5-config
  • 在图形化界面按提示输入realm,kdc域名以及管理员密码
  • 修改/etc/krb5.conf
[realms]
TEST.COM = {
kdc = UBUNTU.COM:88
admin_server = ubuntu1
}
  • 修改/etc/hosts,增加kdc域名映射
172.16.12.133 TEST.COM krb5 UBUNTU.COM
  • 验证校验
root@ubuntu1:~$ kadmin.local 
Authenticating as principal root/admin@TEST.COM with password.
kadmin.local: addprinc user2/admin
Enter password for principal "user2/admin@TEST.COM":
Re-enter password for principal "user2/admin@TEST.COM":
Principal "user2/admin@TEST.COM" created.
kadmin.local: exit


# 输入上步中的密码
root@ubuntu1:~$ kinit user2/admin
Password for user2/admin@TEST.COM:


# klist 查看
root@ubuntu1:~$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user2/admin@TEST.COM


Valid starting Expires Service principal
2020-05-14T19:15:31 2020-05-15T05:15:31 krbtgt/TEST.COM@TEST.COM
renew until 2020-05-15T19:15:17

# 生成keytab后续分发使用
kadmin.local: ktadd -k test.keytab user1/admin
Entry for principal user1/admin with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:test.keytab.
Entry for principal user1/admin with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:test.keytab.
Entry for principal user1/admin with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:test.keytab.
Entry for principal user1/admin with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:test.keytab.


# 验证keytab
root@ubuntu1:~$ kinit -kt test.keytab user1/admin
root@ubuntu1:~$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user2/admin@TEST.COM


Valid starting Expires Service principal
2020-05-14T19:15:31 2020-05-15T05:15:31 krbtgt/TEST.COM@TEST.COM
renew until 2020-05-15T19:15:17


  1. ozone-site.xml 安全配置
<!-- Security config -->
<property>
<name>ozone.security.enabled</name>
<value>true</value>
</property>


<property>
<name>ozone.security.http.kerberos.enabled</name>
<value>true</value>
</property>


<property>
<name>hadoop.security.authentication</name>
<value>KERBEROS</value>
</property>


<!-- SCM ,ozone.keytab 为事先生成好,加入不同服务的principal -->
<property>
<name>hdds.scm.kerberos.principal</name>
<value>scm/localhost@TEST.COM</value>
</property>
<property>
<name>hdds.scm.kerberos.keytab.file</name>
<value>/data/keytab/ozone.keytab</value>
</property>
<property>
<name>hdds.scm.http.kerberos.principal</name>
<value>scm/localhost@TEST.COM</value>
</property>
<property>
</property>
<property>
<name>ozone.om.http.kerberos.keytab</name>
<value>/data/keytab/ozone.keytab</value>
</property>
<!-- DN -->
<property>
<name>dfs.datanode.kerberos.principal</name>
<value>dn/localhost@TEST.COM</value>
</property>
<property>
<name>dfs.datanode.keytab.file</name>
<value>/data/keytab/ozone.keytab</value>
</property>
<property>
<name>hdds.datanode.http.kerberos.principal</name>
<value>dn/localhost@TEST.COM</value>
</property>
<property>
<name>hdds.datanode.http.kerberos.keytab</name>
<value>/data/keytab/ozone.keytab</value>
</property>


<!-- S3G -->
<property>
<name>ozone.s3g.http.auth.type</name>
<value>kerberos</value>
</property>
<property>
<name>ozone.s3g.http.auth.kerberos.principal</name>
<value>s3http/localhost@TEST.COM</value>
</property>


<property>
<name>ozone.s3g.http.auth.kerberos.keytab</name>
<value>/data/keytab/ozone.keytab</value>
</property>


<property>
<name>hadoop.security.auth_to_local</name>
<value>
RULE:[2:$1/$2@$0](scm/localhost@TEST.COM)s/.*/scm/
RULE:[2:$1/$2@$0](om/localhost@TEST.COM)s/.*/om/
RULE:[2:$1/$2@$0](s3http/localhost@TEST.COM)s/.*/s3http/
RULE:[2:$1/$2@$0](dn/localhost@TEST.COM)s/.*/dn/
DEFAULT
</value>
</property>
  1. 启动验证

SCM 日志输出

....
2020-05-14 19:35:06,114 INFO security.UserGroupInformation (UserGroupInformation.java:loginUserFromKeytab(1009)) - Login successful for user scm/localhost@TEST.COM using keytab file /data/keytab/ozone.keytab
2020-05-14 19:35:06,115 INFO server.StorageContainerManager (StorageContainerManager.java:loginAsSCMUser(540)) - SCM login successful.
....

OM 日志输出

...
2020-05-14 19:37:51,444 INFO security.UserGroupInformation (UserGroupInformation.java:loginUserFromKeytab(1009)) - Login successful for user om/localhost@TEST.COM using keytab file /data/keytab/ozone.keytab
2020-05-14 19:37:51,444 INFO om.OzoneManager (OzoneManager.java:loginOMUser(790)) - Ozone Manager login successful.
...

S3Gateway 日志输出

....
2020-05-14 19:39:22,195 INFO http.BaseHttpServer (BaseHttpServer.java:newHttpServer2BuilderForOzone(205)) - Starting Web-server for s3gateway at: http://0.0.0.0:9878
2020-05-14 19:39:22,196 INFO http.BaseHttpServer (BaseHttpServer.java:<init>(106)) - Hadoop Security Enabled: true Ozone Security Enabled: true Ozone HTTP Security Enabled: true
2020-05-14 19:39:22,196 INFO http.BaseHttpServer (BaseHttpServer.java:<init>(117)) - HttpAuthType: ozone.s3g.http.auth.type = kerberos
....

生成安全的S3 Secret Key 并创建bucket

# 登录client用户
root@ubuntu1:~$ kinit -kt ozone_client.keytab ozone_client/localhost@TEST.COM
root@ubuntu1:~$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: ozone_client/localhost@TEST.COM
Valid starting Expires Service principal
2020-05-14T19:15:31 2020-05-15T05:15:31 krbtgt/TEST.COM@TEST.COM
renew until 2020-05-15T19:15:17


root@ubuntu1:~$ ozone s3 getsecret
awsAccessKey=ozone_client/localhost@TEST.COM
awsSecret=68e04f20d77c80d05839c47a67815a9147a329b2a37e48e773001a77a9bdbe60


root@ubuntu1:~$ export AWS_ACCESS_KEY_ID=ozone_client/localhost@TEST.COM
root@ubuntu1:~$ export AWS_SECRET_ACCESS_KEY=68e04f20d77c80d05839c47a67815a9147a329b2a37e48e773001a77a9bdbe60
root@ubuntu1:~$ [ozoneadmin@host-9-180-8-67 ~]$ aws s3api --endpoint-url http://localhost:9878 create-bucket --bucket=bucket1
{
"Location": "http://localhost:9878/bucket1"
}

至此 Ozone 安全的集群启动验证完成。

结束语

Apache Ozone作为一个强一致的分布式对象存储,本文介绍了Ozone的安全认证的工作原理以及如何打开一个安全的Ozone集群,帮助大家认识Ozone安全认证的原理以及实践,后续可结合ACL权限访问,审计等进一步对Ozone的安全进行实践。

欢迎阅读其他Ozone系列文章

如何利用Multi-Raft优化写入吞吐量

Ozone Native ACL的特性及应用

浅谈Ozone的HA能力

浅谈配置化的Ozone网络拓扑结构

Ratis代码解析之一-gRPC


参考资料:

[1] https://blog.cloudera.com/apache-hadoop-ozone-security-authentication/ 

[2] https://juejin.im/post/5abb6c8651882555784e051d


欢迎关注我们公众号

腾讯大数据诚招计算,存储,消息中间件,调度,中台等各方向的大数据研发工程师,请私信或联系jerryshao@tencent.com

文章转载自数据湖技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论