03丨项目部署:如何快速部署IAM系统?

思考并回答以下问题:

部署过程分成2大步。

1,安装和配置数据库:我们需要安装和配置MariaDB、Redis和MongoDB。

2,安装和配置IAM服务:我们需要安装和配置iam-apiserver、iam-authz-server、iam-pump、iamctl和man文件。

下载iam项目代码

因为IAM的安装脚本存放在iam代码仓库中,安装需要的二进制文件也需要通过iam代码构建,所以在安装之前,我们需要先下载iam代码:

1
2
3
4
$ mkdir -p $WORKSPACE/golang/src/github.com/marmotedu
$ cd $WORKSPACE/golang/src/github.com/marmotedu
$ git clone --depth=1 https://github.com/marmotedu/iam
$ go work use ./iam

其中,marmotedu和marmotedu/iam目录存放了本实战项目的代码,在学习过程中,你需要频繁访问这2个目录,为了访问方便,我们可以追加如下2个环境变量和2个alias到$HOME/.bashrc文件中:
1
2
3
4
5
6
7
8
$ tee -a $HOME/.bashrc << 'EOF'
# Alias for quick access
export GOSRC="$WORKSPACE/golang/src"
export IAM_ROOT="$GOSRC/github.com/marmotedu/iam"
alias mm="cd $GOSRC/github.com/marmotedu"
alias i="cd $GOSRC/github.com/marmotedu/iam"
EOF
$ bash

之后,你就可以先通过执行alias命令mm访问$GOSRC/github.com/marmotedu目录;通过执行alias命令i访问$GOSRC/github.com/marmotedu/iam目录。

这里我也建议你善用alias,将常用操作配置成alias,方便以后操作。

安装和配置数据库

在安装配置之前需要执行以下命令export going用户的密码,这里假设密码是iam59!z$

1
export LINUX_PASSWORD='iam59!z$'

安装和配置MariaDB

IAM会把REST资源的定义信息存储在关系型数据库中。

首先,我们可以通过以下命令安装和配置MariaDB,并将Root密码设置为iam59!z$

1
2
$ cd $IAM_ROOT
$ ./scripts/install/mariadb.sh iam::mariadb::install

然后,我们可以通过以下命令,来测试MariaDB是否安装成功:
1
2
$ mysql -h 127.0.0.1 -u root -p 'iam59!z$'
MariaDB [(none)]>

安装和配置Redis

在IAM系统中,由于iam-authz-server是从iam-apiserver拉取并缓存用户的密钥/策略信息的,因此同一份密钥/策略数据会分别存在2个服务中,这可能会出现数据不一致的情况。数据不一致会带来一些问题,例如当我们通过iam-apiserver创建了一对密钥,但是这对密钥还没有被iam-authz-server缓存,这时候通过这对密钥访问iam-authz-server就会访问失败。

为了保证数据的一致性,我们可以使用Redis的发布订阅(pub/sub)功能进行消息通知。同时,iam-authz-server也会将授权审计日志缓存到Redis中,所以也需要安装Redis key-value数据库。我们可以通过以下命令来安装和配置Redis,并将Redis的初始密码设置为iam59!z$

1
2
$ cd $IAM_ROOT
$ ./scripts/install/redis.sh iam::redis::install

这里我们要注意,scripts/install/redis.sh脚本中iam::redis::install函数对Redis做了一些配置,例如修改Redis使其以守护进程的方式运行、修改Redis的密码为iam59!z$等,详细配置可参考函数iam::redis::install函数。

安装完成后,我们可以通过以下命令,来测试Redis是否安装成功:

1
$ redis-cli -h 127.0.0.1 -p 6379 -a 'iam59!z$' # 连接 Redis,-h 指定主机,-p 指定监听端口,-a 指定登录密码

安装和配置MongoDB

因为iam-pump会将iam-authz-server产生的数据处理后存储在MongoDB中,所以我们也需要安装MongoDB数据库。主要分两步安装:首先安装MongoDB,然后再创建MongoDB账号。

第1步,安装MongoDB

首先,我们可以通过以下4步来安装MongoDB。

1,配置MongoDB yum源,并安装MongoDB。

CentOS 8.x系统默认没有配置安装MongoDB需要的yum源,所以我们需要先配置好yum源再安装:

1
2
3
4
5
6
7
8
9
10
11
$ sudo tee /etc/yum.repos.d/mongodb-org-5.0.repo<<'EOF'
[mongodb-org-5.0]
name=MongoDB Repository
# baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/5.0/x86_64/
baseurl=https://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodb-org/5.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
EOF

$ sudo yum install -y mongodb-org

2,关闭SELinux。

在安装的过程中,SELinux有可能会阻止MongoDB访问/sys/fs/cgroup,所以我们还需要关闭SELinux:

1
2
$ sudo setenforce 0
$ sudo sed -i 's/^SELINUX=.*$/SELINUX=disabled/' /etc/selinux/config # 永久关闭 SELINUX

3,开启外网访问权限和登录验证。

MongoDB安装完之后,默认情况下是不会开启外网访问权限和登录验证,为了方便使用,我建议你先开启这些功能,执行如下命令开启:

1
2
$ sudo sed -i '/bindIp/{s/127.0.0.1/0.0.0.0/}' /etc/mongod.conf
$ sudo sed -i '/^#security/a\security:\n authorization: enabled' /etc/mongod.conf

4,启动MongoDB。

配置完MongoDB之后,我们就可以启动它了,具体的命令如下:

1
2
3
$ sudo systemctl start mongod
$ sudo systemctl enable mongod # 设置开机启动
$ sudo systemctl status mongod # 查看 mongod 运行状态,如果输出中包含 active (running)字样说明 mongod 成功启动

安装完MongoDB后,我们就可以通过mongo命令登录MongoDB Shell。如果没有报错,就说明MongoDB被成功安装了。
1
2
$ mongosh --quiet "mongodb://127.0.0.1:27017"
test>

第2步,创建MongoDB账号

安装完MongoDB之后,默认是没有用户账号的,为了方便IAM服务使用,我们需要先创建好管理员账号,通过管理员账户登录MongoDB,我们可以执行创建普通用户、数据库等操作。

1,创建管理员账户。

首先,我们通过use admin指令切换到admin数据库,再通过db.auth("用户名", "用户密码")验证用户登录权限。如果返回1表示验证成功;如果返回0表示验证失败。具体的命令如下:

1
2
3
4
5
6
7
$ mongosh --quiet "mongodb://127.0.0.1:27017"
test> use admin
switched to db admin
admin> db.createUser({user:"root",pwd:"iam59!z$",roles:["root"]})
{ ok: 1 }
admin> db.auth("root", "iam59!z$")
{ ok: 1 }

此外,如果想删除用户,可以使用db.dropUser("用户名")命令。

db.createUser用到了以下3个参数。

  • user:用户名。
  • pwd:用户密码。
  • roles:用来设置用户的权限,比如读、读写、写等。

因为admin用户具有MongoDB的Root权限,权限过大安全性会降低。为了提高安全性,我们还需要创建一个iam普通用户来连接和操作MongoDB。

2,创建iam用户,命令如下:

1
2
3
4
5
$ mongosh --quiet mongodb://root:'iam59!z$'@127.0.0.1:27017/iam_analytics?authSource=admin # 用管理员账户连接 MongoDB
iam_analytics> db.createUser({user:"iam",pwd:"iam59!z$",roles:["dbOwner"]})
{ ok: 1 }
iam_analytics> db.auth("iam", "iam59!z$")
{ ok: 1 }

创建完iam普通用户后,我们就可以通过iam用户登录MongoDB了:

1
$ mongosh --quiet mongodb://iam:'iam59!z$'@127.0.0.1:27017/iam_analytics?authSource=iam_analytics

至此,我们成功安装了IAM系统需要的数据库MariaDB、Redis和MongoDB。

安装和配置IAM系统

准备工作

在开始安装之前,我们需要先做一些准备工作,主要有5步。

1,初始化MariaDB数据库,创建iam数据库。

2,配置scripts/install/environment.sh。

3,创建需要的目录。

4,创建CA根证书和密钥。

5,配置hosts。

第1步,初始化MariaDB数据库,创建iam数据库。

安装完MariaDB数据库之后,我们需要在MariaDB数据库中创建IAM系统需要的数据库、表和存储过程,以及创建SQL语句保存在IAM代码仓库中的configs/iam.sql文件中。具体的创建步骤如下。

1,登录数据库并创建iam用户。

1
2
3
4
5
6
$ cd $IAM_ROOT
$ mysql -h127.0.0.1 -P3306 -uroot -p'iam59!z$' # 连接 MariaDB,-h 指定主机,-P 指定监听端口,-u 指定登录用户,-p 指定登录密码
MariaDB [(none)]> grant all on iam.* TO iam@127.0.0.1 identified by 'iam59!z$';
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.000 sec)

2,用iam用户登录MariaDB,执行iam.sql文件,创建iam数据库。

1
2
3
4
5
6
7
8
9
10
$ mysql -h127.0.0.1 -P3306 -uiam -p'iam59!z$'
MariaDB [(none)]> source configs/iam.sql;
MariaDB [iam]> show databases;
+--------------------+
| Database |
+--------------------+
| iam |
| information_schema |
+--------------------+
2 rows in set (0.000 sec)

上面的命令会创建iam数据库,并创建以下数据库资源。

  • 表:user是用户表,用来存放用户信息;secret是密钥表,用来存放密钥信息;policy是策略表,用来存放授权策略信息;policy_audit是策略历史表,被删除的策略会被转存到该表。
  • admin用户:在user表中,我们需要创建一个管理员用户,用户名是admin,密码是Admin@2021。
  • 存储过程:删除用户时会自动删除该用户所属的密钥和策略信息。

第2步,配置scripts/install/environment.sh。

IAM组件的安装配置都是通过环境变量文件scripts/install/environment.sh进行配置的,所以我们要先配置好scripts/install/environment.sh文件。这里,你可以直接使用默认值,提高你的安装效率。

第3步,创建需要的目录。

在安装和运行IAM系统的时候,我们需要将配置、二进制文件和数据文件存放到指定的目录。所以我们需要先创建好这些目录,创建步骤如下。

1
2
3
4
5
6
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ sudo mkdir -p ${IAM_DATA_DIR}/{iam-apiserver,iam-authz-server,iam-pump} # 创建 Systemd WorkingDirectory 目录
$ sudo mkdir -p ${IAM_INSTALL_DIR}/bin #创建 IAM 系统安装目录
$ sudo mkdir -p ${IAM_CONFIG_DIR}/cert # 创建 IAM 系统配置文件存放目录
$ sudo mkdir -p ${IAM_LOG_DIR} # 创建 IAM 日志文件存放目录

第4步,创建CA根证书和密钥。

为了确保安全,IAM系统各组件需要使用x509证书对通信进行加密和认证。所以,这里我们需要先创建CA证书。CA根证书是所有组件共享的,只需要创建一个CA证书,后续创建的所有证书都由它签名。

我们可以使用CloudFlare的PKI工具集cfssl来创建所有的证书。

1,安装cfssl工具集。

我们可以直接安装cfssl已经编译好的二进制文件,cfssl工具集中包含很多工具,这里我们需要安装cfssl、cfssljson、cfssl-certinfo,功能如下。

  • cfssl:证书签发工具。
  • cfssljson:将cfssl生成的证书(json格式)变为文件承载式证书。

这两个工具的安装方法如下:

1
2
$ cd $IAM_ROOT
$ ./scripts/install/install.sh iam::install::install_cfssl

2,创建配置文件。

CA配置文件是用来配置根证书的使用场景(profile)和具体参数(usage、过期时间、服务端认证、客户端认证、加密等),可以在签名其它证书时用来指定特定场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cd $IAM_ROOT
$ tee ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"iam": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876000h"
}
}
}
}
EOF

上面的JSON配置中,有一些字段解释如下。

  • signing:表示该证书可用于签名其它证书(生成的ca.pem证书中CA=TRUE)。
  • serverauth:表示client可以用该证书对server提供的证书进行验证。
  • clientauth:表示server可以用该证书对client提供的证书进行验证。
  • expiry:876000h,证书有效期设置为100年。

3,创建证书签名请求文件。

我们创建用来生成CA证书签名请求(CSR)的JSON配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cd $IAM_ROOT
$ tee ca-csr.json << EOF
{
"CN": "iam-ca",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "marmotedu",
"OU": "iam"
}
],
"ca": {
"expiry": "876000h"
}
}
EOF

上面的JSON配置中,有一些字段解释如下。

  • C:Country,国家。
  • ST:State,省份。
  • L:Locality(L) or City,城市。
  • CN:Common Name,iam-apiserver从证书中提取该字段作为请求的用户名(UserName),浏览器使用该字段验证网站是否合法。
  • O:Organization,iam-apiserver从证书中提取该字段作为请求用户所属的组(Group)。
  • OU:Company division(or Organization Unit–OU),部门/单位。

除此之外,还有两点需要我们注意。

  • 不同证书csr文件的CN、C、ST、L、O、OU组合必须不同,否则可能出现PEER'S CERTIFICATE HAS AN INVALID SIGNATURE错误。
  • 后续创建证书的csr文件时,CN、OU都不相同(C、ST、L、O相同),以达到区分的目的。

4,创建CA证书和私钥

首先,我们通过cfssl gencert命令来创建:

1
2
3
4
5
6
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$ ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
$ sudo mv ca* ${IAM_CONFIG_DIR}/cert # 需要将证书文件拷贝到指定文件夹下(分发证书),方便各组件引用

上述命令会创建运行CA所必需的文件ca-key.pem(私钥)和ca.pem(证书),还会生成ca.csr(证书签名请求),用于交叉签名或重新签名。

创建完之后,我们可以通过cfssl certinfo命名查看cert和csr信息:

1
2
$ cfssl certinfo -cert ${IAM_CONFIG_DIR}/cert/ca.pem # 查看 cert(证书信息)
$ cfssl certinfo -csr ${IAM_CONFIG_DIR}/cert/ca.csr # 查看 CSR(证书签名请求)信息

第5步,配置hosts。

iam通过域名访问API接口,因为这些域名没有注册过,还不能在互联网上解析,所以需要配置hosts,具体的操作如下:

1
2
3
4
$ sudo tee -a /etc/hosts <<EOF
127.0.0.1 iam.api.marmotedu.com
127.0.0.1 iam.authz.marmotedu.com
EOF

安装和配置iam-apiserver

完成了准备工作之后,我们就可以安装IAM系统的各个组件了。首先我们通过以下3步来安装iam-apiserver服务。

第1步,创建iam-apiserver证书和私钥。

其它服务为了安全都是通过HTTPS协议访问iam-apiserver,所以我们要先创建iam-apiserver证书和私钥。

1,创建证书签名请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ tee iam-apiserver-csr.json <<EOF
{
"CN": "iam-apiserver",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "marmotedu",
"OU": "iam-apiserver"
}
],
"hosts": [
"127.0.0.1",
"localhost",
"iam.api.marmotedu.com"
]
}
EOF

代码中的hosts字段是用来指定授权使用该证书的IP和域名列表,上面的hosts列出了iam-apiserver服务的IP和域名。

2,生成证书和私钥:

1
2
3
4
5
$ cfssl gencert -ca=${IAM_CONFIG_DIR}/cert/ca.pem \
-ca-key=${IAM_CONFIG_DIR}/cert/ca-key.pem \
-config=${IAM_CONFIG_DIR}/cert/ca-config.json \
-profile=iam iam-apiserver-csr.json | cfssljson -bare iam-apiserver
$ sudo mv iam-apiserver*pem ${IAM_CONFIG_DIR}/cert # 将生成的证书和私钥文件拷贝到配置文件目录

第2步,安装并运行iam-apiserver。

iam-apiserver作为iam系统的核心组件,需要第一个安装。

1,安装iam-apiserver可执行程序:

1
2
3
4
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ make build BINS=iam-apiserver
$ sudo cp _output/platforms/linux/amd64/iam-apiserver ${IAM_INSTALL_DIR}/bin

2,生成并安装iam-apiserver的配置文件(iam-apiserver.yaml):

1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh configs/iam-apiserver.yaml > iam-apiserver.yaml
$ sudo mv iam-apiserver.yaml ${IAM_CONFIG_DIR}

3,创建并安装iam-apiserver systemd unit文件:

1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh init/iam-apiserver.service > iam-apiserver.service
$ sudo mv iam-apiserver.service /etc/systemd/system/

4,启动iam-apiserver服务:

1
2
3
4
$ sudo systemctl daemon-reload
$ sudo systemctl enable iam-apiserver
$ sudo systemctl restart iam-apiserver
$ systemctl status iam-apiserver # 查看 iam-apiserver 运行状态,如果输出中包含 active (running)字样说明 iam-apiserver 成功启动

第3步,测试iam-apiserver是否成功安装。

测试iam-apiserver主要是测试RESTful资源的CURD:用户CURD、密钥CURD、授权策略CURD。

首先,我们需要获取访问iam-apiserver的Token,请求如下API访问:

1
2
$ curl -s -XPOST -H'Content-Type: application/json' -d'{"username":"admin","password":"Admin@2021"}' http://127.0.0.1:8080/login | jq -r .token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA

代码中下面的HTTP请求通过-H 'Authorization:Bearer <Token>'指定认证头信息,将上面请求的Token替换。

用户CURD

创建用户、列出用户、获取用户详细信息、修改用户、删除单个用户、批量删除用户,请求方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建用户
$ curl -s -XPOST -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"password":"User@2021","metadata":{"name":"colin"},"nickname":"colin","email":"colin@foxmail.com","phone":"1812884xxxx"}' http://127.0.0.1:8080/v1/users

# 列出用户
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' 'http://127.0.0.1:8080/v1/users?offset=0&limit=10'

# 获取 colin 用户的详细信息
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/users/colin

# 修改 colin 用户
$ curl -s -XPUT -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"nickname":"colin","email":"colin_modified@foxmail.com","phone":"1812884xxxx"}' http://127.0.0.1:8080/v1/users/colin

# 删除 colin 用户
$ curl -s -XDELETE -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/users/colin

# 批量删除用户
$ curl -s -XDELETE -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' 'http://127.0.0.1:8080/v1/users?name=colin&name=mark&name=john'

密钥CURD

创建密钥、列出密钥、获取密钥详细信息、修改密钥、删除密钥请求方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建 secret0 密钥
$ curl -s -XPOST -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"metadata":{"name":"secret0"},"expires":0,"description":"admin secret"}' http://127.0.0.1:8080/v1/secrets

# 列出所有密钥
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/secrets

# 获取 secret0 密钥的详细信息
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/secrets/secret0

# 修改 secret0 密钥
$ curl -s -XPUT -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"metadata":{"name":"secret0"},"expires":0,"description":"admin secret(modified)"}' http://127.0.0.1:8080/v1/secrets/secret0

# 删除 secret0 密钥
$ curl -s -XDELETE -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/secrets/secret0

这里我们要注意,因为密钥属于重要资源,被删除会导致所有的访问请求失败,所以密钥不支持批量删除。

授权策略CURD

创建策略、列出策略、获取策略详细信息、修改策略、删除策略请求方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建策略
$ curl -s -XPOST -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"metadata":{"name":"policy0"},"policy":{"description":"One policy to rule them all.","subjects":["users:<peter|ken>","users:maria","groups:admins"],"actions":["delete","<create|update>"],"effect":"allow","resources":["resources:articles:<.*>","resources:printer"],"conditions":{"remoteIPAddress":{"type":"CIDRCondition","options":{"cidr":"192.168.0.1/16"}}}}}' http://127.0.0.1:8080/v1/policies

# 列出所有策略
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/policies

# 获取 policy0 策略的详细信息
$ curl -s -XGET -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/policies/policy0

# 修改 policy0 策略
$ curl -s -XPUT -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' -d'{"metadata":{"name":"policy0"},"policy":{"description":"One policy to rule them all(modified).","subjects":["users:<peter|ken>","users:maria","groups:admins"],"actions":["delete","<create|update>"],"effect":"allow","resources":["resources:articles:<.*>","resources:printer"],"conditions":{"remoteIPAddress":{"type":"CIDRCondition","options":{"cidr":"192.168.0.1/16"}}}}}' http://127.0.0.1:8080/v1/policies/policy0

# 删除 policy0 策略
$ curl -s -XDELETE -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2MTc5MjI4OTQsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MTc4MzY0OTQsInN1YiI6ImFkbWluIn0.9qztVJseQ9XwqOFVUHNOtG96-KUovndz0SSr_QBsxAA' http://127.0.0.1:8080/v1/policies/policy0

安装iamctl

上面,我们安装了iam系统的API服务。但是想要访问iam服务,我们还需要安装客户端工具iamctl。具体来说,我们可以通过3步完成iamctl的安装和配置。

第1步,创建iamctl证书和私钥。

iamctl使用https协议与iam-apiserver进行安全通信,iam-apiserver对iamctl请求包含的证书进行认证和授权。iamctl后续用于iam系统访问和管理,所以这里创建具有最高权限的admin证书。

1,创建证书签名请求。

下面创建的证书只会被iamctl当作client证书使用,所以hosts字段为空。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ cat > admin-csr.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "marmotedu",
"OU": "iamctl"
}
],
"hosts": []
}
EOF

2,生成证书和私钥:

1
2
3
4
5
6
7
$ cfssl gencert -ca=${IAM_CONFIG_DIR}/cert/ca.pem \
-ca-key=${IAM_CONFIG_DIR}/cert/ca-key.pem \
-config=${IAM_CONFIG_DIR}/cert/ca-config.json \
-profile=iam admin-csr.json | cfssljson -bare admin
$ mkdir -p $(dirname ${CONFIG_USER_CLIENT_CERTIFICATE}) $(dirname ${CONFIG_USER_CLIENT_KEY}) # 创建客户端证书存放的目录
$ mv admin.pem ${CONFIG_USER_CLIENT_CERTIFICATE} # 安装 TLS 的客户端证书
$ mv admin-key.pem ${CONFIG_USER_CLIENT_KEY} # 安装 TLS 的客户端私钥文件

第2步,安装iamctl。

iamctl是IAM系统的客户端工具,其安装位置和iam-apiserver、iam-authz-server、iam-pump位置不同,为了能够在shell下直接运行iamctl命令,我们需要将iamctl安装到$HOME/bin下,同时将iamctl的配置存放在默认加载的目录下:$HOME/.iam。主要分2步进行。

1,安装iamctl可执行程序:

1
2
3
4
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ make build BINS=iamctl
$ cp _output/platforms/linux/amd64/iamctl $HOME/bin

2,生成并安装iamctl的配置文件(iamctl.yaml):

1
2
3
$ ./scripts/genconfig.sh scripts/install/environment.sh configs/iamctl.yaml> iamctl.yaml
$ mkdir -p $HOME/.iam
$ mv iamctl.yaml $HOME/.iam

因为iamctl是一个客户端工具,可能会在多台机器上运行。为了简化部署iamctl工具的复杂度,我们可以把config配置文件中跟CA认证相关的CA文件内容用base64加密后,放置在config配置文件中。具体的思路就是把config文件中的配置项client-certificate、client-key、certificate-authority分别用如下配置项替换client-certificate-data、client-key-data、certificate-authority-data。这些配置项的值可以通过对CA文件使用base64加密获得。

假如,certificate-authority值为/etc/iam/cert/ca.pem,则certificate-authority-data的值为cat "/etc/iam/cert/ca.pem" | base64 | tr -d '\r\n',其它-data变量的值类似。这样当我们再部署iamctl工具时,只需要拷贝iamctl和配置文件,而不用再拷贝CA文件了。

第3步,测试iamctl是否成功安装。

执行iamctl user list可以列出预创建的admin用户,如下图所示:

安装和配置iam-authz-server

接下来,我们需要安装另外一个核心组件:iam-authz-server,可以通过以下3步来安装。

第1步,创建iam-authz-server证书和私钥。

1,创建证书签名请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ tee iam-authz-server-csr.json <<EOF
{
"CN": "iam-authz-server",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "marmotedu",
"OU": "iam-authz-server"
}
],
"hosts": [
"127.0.0.1",
"localhost",
"iam.authz.marmotedu.com"
]
}
EOF

代码中的hosts字段指定授权使用该证书的IP和域名列表,上面的hosts列出了iam-authz-server服务的IP和域名。

2,生成证书和私钥:

1
2
3
4
5
$ cfssl gencert -ca=${IAM_CONFIG_DIR}/cert/ca.pem \
-ca-key=${IAM_CONFIG_DIR}/cert/ca-key.pem \
-config=${IAM_CONFIG_DIR}/cert/ca-config.json \
-profile=iam iam-authz-server-csr.json | cfssljson -bare iam-authz-server
$ sudo mv iam-authz-server*pem ${IAM_CONFIG_DIR}/cert # 将生成的证书和私钥文件拷贝到配置文件目录

第2步,安装并运行iam-authz-server

安装iam-authz-server步骤和安装iam-apiserver步骤基本一样,也需要4步。

1,安装iam-authz-server可执行程序:

1
2
3
4
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ make build BINS=iam-authz-server
$ sudo cp _output/platforms/linux/amd64/iam-authz-server ${IAM_INSTALL_DIR}/bin

2,生成并安装iam-authz-server的配置文件(iam-authz-server.yaml):

1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh configs/iam-authz-server.yaml > iam-authz-server.yaml
$ sudo mv iam-authz-server.yaml ${IAM_CONFIG_DIR}

3,创建并安装iam-authz-server systemd unit文件:

1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh init/iam-authz-server.service > iam-authz-server.service
$ sudo mv iam-authz-server.service /etc/systemd/system/

4,启动iam-authz-server服务:

1
2
3
4
$ sudo systemctl daemon-reload
$ sudo systemctl enable iam-authz-server
$ sudo systemctl restart iam-authz-server
$ systemctl status iam-authz-server # 查看 iam-authz-server 运行状态,如果输出中包含 active (running)字样说明 iam-authz-server 成功启动。

第3步,测试iam-authz-server是否成功安装

1,重新登陆系统,并获取访问令牌

1
$ token=`curl -s -XPOST -H'Content-Type: application/json' -d'{"username":"admin","password":"Admin@2021"}' http://127.0.0.1:8080/login | jq -r .token`

2,创建授权策略

1
$ curl -s -XPOST -H"Content-Type: application/json" -H"Authorization: Bearer $token" -d'{"metadata":{"name":"authztest"},"policy":{"description":"One policy to rule them all.","subjects":["users:<peter|ken>","users:maria","groups:admins"],"actions":["delete","<create|update>"],"effect":"allow","resources":["resources:articles:<.*>","resources:printer"],"conditions":{"remoteIPAddress":{"type":"CIDRCondition","options":{"cidr":"192.168.0.1/16"}}}}}' http://127.0.0.1:8080/v1/policies

3,创建密钥,并从命令的输出中提取secretID和secretKey

1
2
$ curl -s -XPOST -H"Content-Type: application/json" -H"Authorization: Bearer $token" -d'{"metadata":{"name":"authztest"},"expires":0,"description":"admin secret"}' http://127.0.0.1:8080/v1/secrets
{"metadata":{"id":23,"name":"authztest","createdAt":"2021-04-08T07:24:50.071671422+08:00","updatedAt":"2021-04-08T07:24:50.071671422+08:00"},"username":"admin","secretID":"ZuxvXNfG08BdEMqkTaP41L2DLArlE6Jpqoox","secretKey":"7Sfa5EfAPIwcTLGCfSvqLf0zZGCjF3l8","expires":0,"description":"admin secret"}

4,生成访问iam-authz-server的token

iamctl提供了jwt sigin命令,可以根据secretID和secretKey签发Token,方便你使用。

1
2
$ iamctl jwt sign ZuxvXNfG08BdEMqkTaP41L2DLArlE6Jpqoox 7Sfa5EfAPIwcTLGCfSvqLf0zZGCjF3l8 # iamctl jwt sign $secretID $secretKey,替换成上一步创建的密钥对
eyJhbGciOiJIUzI1NiIsImtpZCI6Ilp1eHZYTmZHMDhCZEVNcWtUYVA0MUwyRExBcmxFNkpwcW9veCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXV0aHoubWFybW90ZWR1LmNvbSIsImV4cCI6MTYxNzg0NTE5NSwiaWF0IjoxNjE3ODM3OTk1LCJpc3MiOiJpYW1jdGwiLCJuYmYiOjE2MTc4Mzc5OTV9.za9yLM7lHVabPAlVQLCqXEaf8sTU6sodAsMXnmpXjMQ

如果你的开发过程中有些重复性的操作,为了方便使用,也可以将这些操作以iamctl子命令的方式集成到iamctl命令行中。

5,测试资源授权是否通过

我们可以通过请求/v1/authz来完成资源授权:

1
2
$ curl -s -XPOST -H'Content-Type: application/json' -H'Authorization: Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6Ilp1eHZYTmZHMDhCZEVNcWtUYVA0MUwyRExBcmxFNkpwcW9veCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXV0aHoubWFybW90ZWR1LmNvbSIsImV4cCI6MTYxNzg0NTE5NSwiaWF0IjoxNjE3ODM3OTk1LCJpc3MiOiJpYW1jdGwiLCJuYmYiOjE2MTc4Mzc5OTV9.za9yLM7lHVabPAlVQLCqXEaf8sTU6sodAsMXnmpXjMQ' -d'{"subject":"users:maria","action":"delete","resource":"resources:articles:ladon-introduction","context":{"remoteIPAddress":"192.168.0.5"}}' http://127.0.0.1:9090/v1/authz
{"allowed":true}

如果授权通过会返回:{"allowed":true}

安装和配置iam-pump

安装iam-pump步骤和安装iam-apiserver、iam-authz-server步骤基本一样,具体步骤如下。

第1步,安装iam-pump可执行程序。

1
2
3
4
$ cd $IAM_ROOT
$ source scripts/install/environment.sh
$ make build BINS=iam-pump
$ sudo cp _output/platforms/linux/amd64/iam-pump ${IAM_INSTALL_DIR}/bin

第2步,生成并安装iam-pump的配置文件(iam-pump.yaml)。
1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh configs/iam-pump.yaml > iam-pump.yaml
$ sudo mv iam-pump.yaml ${IAM_CONFIG_DIR}

第3步,创建并安装iam-pumpsystemdunit文件。
1
2
$ ./scripts/genconfig.sh scripts/install/environment.sh init/iam-pump.service > iam-pump.service
$ sudo mv iam-pump.service /etc/systemd/system/

第4步,启动iam-pump服务。
1
2
3
4
$ sudo systemctl daemon-reload
$ sudo systemctl enable iam-pump
$ sudo systemctl restart iam-pump
$ systemctl status iam-pump # 查看 iam-pump 运行状态,如果输出中包含 active (running)字样说明 iam-pump 成功启动。

第5步,测试iam-pump是否成功安装。

1
2
$ curl http://127.0.0.1:7070/healthz
{"status": "ok"}

经过上面这5个步骤,如果返回{"status": "ok"}就说明iam-pump服务健康。

安装man文件

IAM系统通过组合调用包:github.com/cpuguy83/go-md2man/v2/md2man和github.com/spf13/cobra的相关函数生成了各个组件的man1文件,主要分3步实现。

第1步,生成各个组件的man1文件。

1
2
$ cd $IAM_ROOT
$ ./scripts/update-generated-docs.sh

第2步,安装生成的man1文件。

1
$ sudo cp docs/man/man1/* /usr/share/man/man1/

第3步,检查是否成功安装man1文件。

1
$ man iam-apiserver

执行man iam-apiserver命令后,会弹出man文档界面,如下图所示:

至此,IAM系统所有组件都已经安装成功了,你可以通过iamctlversion查看客户端和服务端版本,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ iamctl version -o yaml
clientVersion:
buildDate: "2021-04-08T01:56:20Z"
compiler: gc
gitCommit: 1d682b0317396347b568a3ef366c1c54b3b0186b
gitTreeState: dirty
gitVersion: v0.6.1-5-g1d682b0
goVersion: go1.16.2
platform: linux/amd64
serverVersion:
buildDate: "2021-04-07T22:30:53Z"
compiler: gc
gitCommit: bde163964b8c004ebb20ca4abd8a2ac0cd1f71ad
gitTreeState: dirty
gitVersion: bde1639
goVersion: go1.16.2
platform: linux/amd64

总结

课后练习

请你试着调用iam-apiserver提供的API接口创建一个用户:xuezhang,并在该用户下创建policy和secret资源。最后调用iam-authz-server提供的/v1/authz接口进行资源鉴权。

彩蛋:一键安装

你可以直接执行如下脚本,来完成IAM系统的安装:

1
2
3
$ export LINUX_PASSWORD='iam59!z$' # 重要:这里要 export going 用户的密码
$ version=latest && curl https://marmotedu-1254073058.cos.ap-beijing.myqcloud.com/iam-release/${version}/iam.tar.gz | tar -xz -C / tmp/
$ cd /tmp/iam/ && ./scripts/install/install.sh iam::install::install

IAM一键部署指南

0%