在Ansible的ONTAP模块中使用SSL客户端认证

使用Ansible的ONTAP模块可以简化各种重复的设置。

然而,由于担心模块使用的API身份验证信息(用户名/密码)的安全性问题,我们将其作为变量嵌入到文件中,并通过Vault进行加密。

在ONATP模块20.06中,现在可以使用SSL客户端认证,因此我想进行相应的设置。

在netapp.io上有一篇相似的文章1,但在这里我想稍微详细地用日语解释一下。如果您英语和ONTAP知识都很好的话,可以直接阅读netapp.io的文章。

顺便提一下,下面提到的代码示例、playbook等内容已经放在了Github上。

更新

    2022/10/06 Typo修正, Org投稿に変更

汇总

    1. 使用CN将用户名放入并创建客户端认证密钥对。

 

    1. 在ONTAP中设置客户端证书CA的公共密钥(文章中提到使用自签名证书)。

 

    1. 在ONTAP的SVM和管理员帐户中启用基于客户端证书的认证。

 

    通过Playbook的Task,在cert_filepath/key_filepath处指定证书文件并执行。

前提 tí)

以下是确认操作软件的版本等的信息。

    • ONTAP: 9.7

 

    • Ansible Control Machine

OS: Debian 10
Software: openssl, curl, jq, python3-pip
Python: 3.7.3
Ansible: 2.10.1
netapp-lib 2020.7.16
NetApp ONTAP Collection : 20.10.0

需要安装的额外软

sudo apt-get install openssl curl jq python3-pip
sudo pip3 install ansible netapp-lib
ansible-galaxy collection install netapp.ontap

设定

在生成证书时,有时会使用openssl来进行操作,因此我们将在Linux系统上进行。

作为准备,大致需要完成两个任务。

    1. 生成和安装客户端证书

 

    激活API使用时的客户端证书

1. 安装客户端证书

需要将客户端证书设置给ONTAP管理员用户。

使用API认证的用户

在这里设置客户端认证是指利用Ansible模块从ONTAP的API中使用的用户的认证方式。

在ONTAP中,有一种名为SVM2的思想,可以在集群中实现多租户。因此,根据API进行的管理操作分为两个级别:一个是基于SVM(租户)级别的操作,另一个是基于整个集群级别的操作。

如果在Ansible的模块中用于登录的用户是集群管理员,那么他可以执行所有的操作。如果是SVM管理员,则只能在SVM内执行所允许的操作。

无论使用哪个级别,都需要具备集群管理员权限来进行准备工作。在接下来在ONTAP上进行的操作,请使用具有集群管理权限的admin用户来执行。

另外,集群管理用户 admin 的 SVM 名称通常与集群名称相同,为 SVM4,并且可以通过 CLI 的 vserver show 命令进行确认。

在下面的例子中,Vserver(= SVM)的类型是admin,可以确定它是一个集群管理的SVM。

ontapsim::> vserver show
                               Admin      Operational Root
Vserver     Type    Subtype    State      State       Volume     Aggregate
----------- ------- ---------- ---------- ----------- ---------- ----------
ontapsim    admin   -          -          -           -          -
ontapsim-01 node    -          -          -           -          -
2 entries were displayed.

因为在说明中出现了各种参数,让人感到混乱,所以我希望在接下来的工作中先准备一个将所有必要参数设置为变量的文件(params),然后开始工作。

#
# Ansibleで使う、ONTAP APIの認証ユーザ(クラスタ管理者またはSVM管理者)
#
ANSIBLE_USER=AnsibleでAPIを認証するユーザ名(通常はadminかvsadmin)
ANSIBLE_SVM=Ansibleで管理しようとするSVMの名前/クラスタ全体ならクラスタ管理SVM

#
# 設定に使う ONTAPのクラスタ管理者情報
#
ONTAP_CLUSTER=クラスタ管理SVMの名前
ONTAP_ADMIN=admin
ONTAP_CLUSTER_MGMT_IP=xxx.xxx.xxx.xxx

#
# 証明書のファイル名
#
PUBLICKEY_FILE=$ANSIBLE_SVM-$ANSIBLE_USER.pem
PRIVATEKEY_FILE=$ANSIBLE_SVM-$ANSIBLE_USER.key

1.2 证书的制作

如果有一个单独的客户端认证机构,可以使用自签名证书。您可以在该认证机构上颁发客户端证书,并将其公共密钥注册为客户端认证机构的注册中心。

由于这是用于ANSIBLE_USER的自签名客户端证书,所以将ANSIBLE_USER作为主题的通用名称(CN)进行指定。主题中最重要的是通用名称(CN),所以将集群名称或SVM名称设置为组织(O)。其他选项包括有效期3年(-days 1095)和不对私钥进行加密(-nodes)。

openssl req -x509 -nodes -days 1095 -newkey rsa:2048 -keyout $PRIVATEKEY_FILE -out $PUBLICKEY_FILE -subj "/O=$ONTAP_CLUSTER/OU=$ANSIBLE_SVM/CN=$ANSIBLE_USER"

现在我已经生成了自签名证书。

1.3 安装客户端证书

完成后,将公钥安装到ONTAP以用于客户端认证。

如果想通过CLI安装证书,可以使用”security certificate install”命令。

在使用ssh等方式登录为集群管理员后,执行命令security certificate install -vserver SVM名 -type client-ca,将pem文件内容粘贴到终端,然后按Enter键即可完成。

ssh $ONTAP_ADMIN@$ONTAP_CLUSTER_MGMT_IP security certificate install -vserver $ANSIBLE_SVM -type client-ca

如果你不想使用SSH,而是通过API调用的话,可以这样做。

curl -k -u $ONTAP_ADMIN -X POST "https://$ONTAP_CLUSTER_MGMT_IP/api/security/certificates" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"svm\":{\"name\":\"$ANSIBLE_SVM\"},\"type\":\"client-ca\",\"public_certificate\":\"`cat $PUBLICKEY_FILE`\"}"

在这里,我们将其类型设置为 client-ca,这意味着我们将信任由该证书签名的证书作为客户端证书。
由于这个证书是由自己签名(自签名)的,所以它将成为有效的客户端证书(有点复杂)。

蛇足的解释是,type: client 不是用于客户端认证访问ONTAP,而是用于ONTAP自身通过https连接访问其他服务器时设置的客户端证书。

启用SSL客户端认证。

在这里需要进行两个设置。

    1. 在ONTAP侧的SSL设置中启用客户端认证

 

    将客户端证书作为使用API和HTTP时的身份验证方法,启用它作为目标用户。

如果通过CLI进行操作,您需要以群集管理员身份使用 ssh 或类似的方法登录,并执行三个命令。

# SVMへ https でアクセスした時の、クライアント認証を有効にする
ssh $ONTAP_ADMIN@$ONTAP_CLUSTER_MGMT_IP security ssl modify -vserver $ANSIBLE_SVM -client-enabled true
# SVM上のユーザが、ONTAP API/httpsでアクセスしたときに SSLのクライアント認証を使う設定
ssh $ONTAP_ADMIN@$ONTAP_CLUSTER_MGMT_IP security login create -vserver $ANSIBLE_SVM -user-or-group-name $ANSIBLE_USER -application ontapi -authentication-method cert
ssh $ONTAP_ADMIN@$ONTAP_CLUSTER_MGMT_IP security login create -vserver $ANSIBLE_SVM -user-or-group-name $ANSIBLE_USER -application http   -authentication-method cert

如果使用API进行操作,请注意以下三点。

    1. ANSIBLE_SVM的UUID是必需的,您需要通过API进行查询,然后才能执行实际操作。

 

    1. 用于获取SVM列表的API是GET /svm/svms API,仅适用于DATA SVM(租户所使用的SVM)。如果ANSIBLE_SVM是针对租户的,则没有问题,但无法使用此API获取集群管理SVM的UUID。如果没有专用API,您将需要使用cli passthrough API。

 

    1. 在ONTAP 9.7中,也没有专用API可以启用SVM的客户端身份验证,因此您将需要使用cli passthrough API。

 

    关于通过PATCH /security/accounts/UUID/NAME API传递的应用程序和身份验证方式的组合,它会覆盖整个应用程序。因此,如果仅传递http/certificate作为附加内容,则其他身份验证将被禁用(但是,例如对于管理员等用户,无法删除控制台访问的密码身份验证)。您需要检查当前的Applications,然后在其上添加要添加的身份验证方式,并向API发送请求。

因此,关于调用API的脚本会稍微庞大一些。

由于您正在使用 jq 命令,如果未安装,请使用 sudo apt-get install jq 等命令进行安装。

{

# SVMへ https でアクセスした時の、クライアント認証を有効にする
curl "https://$ONTAP_CLUSTER_MGMT_IP/api/private/cli/security/ssl?vserver=$ANSIBLE_SVM" \
    -k \
    -X PATCH \
    -H "accept: application/json" \
    -H "Content-Type: application/json" \
    -u "$ANSIBLE_USER" \
    -d '{ "client-enabled": true }'

echo .

# ANSIBLEがアクセスするSVMのUUIDを取得
ANSIBLE_SVM_UUID=`curl -s -k -u $ONTAP_ADMIN -X GET -H "accept: application/json" "https://$ONTAP_CLUSTER_MGMT_IP/api/private/cli/vserver?vserver=$ANSIBLE_SVM&fields=uuid" | jq -r ".records[0].uuid"`

echo "ANSIBLE SVM UUID = $ANSIBLE_SVM_UUID"

# 現在有効な認証情報について取得
CURRENT_APPS=`curl -s -k -u $ONTAP_ADMIN -X GET -H "accept: application/json" "https://$ONTAP_CLUSTER_MGMT_IP/api/security/accounts/$ANSIBLE_SVM_UUID/$ANSIBLE_USER" | jq -r ".applications"`

echo "Current applications for $ANSIBLE_USER@$ANSIBLE_SVM = "
echo "$CURRENT_APPS" | jq

read -p "Hit any key to continue: " -n 1 -r
echo

# 新しく設定する認証情報について念のため確認メッセージ
NEW_APPS=`echo "$CURRENT_APPS" | jq -r '. + [{ "application": "ontapi", "authentication_methods": ["certificate"] },{ "application": "http", "authentication_methods": ["certificate"] }]'`
echo "New applications for $ANSIBLE_USER@$ANSIBLE_SVM = "
echo "$NEW_APPS" | jq

read -p "Please confirm the applications and hit any key to continue: " -n 1 -r

JSON="{\
    \"applications\": $NEW_APPS
}"

curl "https://$ONTAP_CLUSTER_MGMT_IP/api/security/accounts/$ANSIBLE_SVM_UUID/$ANSIBLE_USER" \
    -k \
    -X PATCH \
    -H "accept: application/json" \
    -H "Content-Type: application/json" \
    -u "$ONTAP_ADMIN" \
    -d "$JSON"

}

这样的设置已经完成了。

关于Playbook的撰写方式

将Playbook的修改从之前使用用户名和密码的方式更改为使用cert/key_filepath。

将下面的句子用中文进行一次本地化改写。只需要一种选项:
↓これを↓

将下面的句子翻译成中文,只要给一个选项:
↓这个↓

hostname: Ansible01
username: admin
password: netapp123
https: true
validate_certs: false

↓像这样↓

hostname: Ansible01
cert_filepath: name.pem
key_filepath: name.key
validate_certs: false

如果客户端认证已启用,则一定会使用”https:true”,因此可省略。关于”cert_filepath/key_filepath”,只需将证书文件放置在Playbook所在的位置,并设置文件名即可。

设定的示例

将访问ONTAP所需的信息定义为group_vars/ontap.yml作为Ansible。

ansible_host: localhost
ansible_connection: local
ansible_python_interpreter: "/usr/bin/python3"

ontap_hostname: "xxx.xxx.xxx.xxx"
ontap_cert_filepath: "ontap-admin.pem"
ontap_key_filepath: "ontap-admin.key"
ontap_validate_certs: false

在库存中定义ontap组,并将需要的主机(只使用集群/ svm /节点等)全部放入其中。

由于实际的API网络连接是针对传递给(设置为ontap_hostname变量的)模块的主机名进行的,因此可以使用无法进行名称解析等的名称。

#
# ontap group:
#   all ontap hosts that shared group vars 'group_vars/ontap.yml'
#
ontap:
  hosts:
    cluster:
    svm01:
    node01:
    node02:

在Playbook中,可以将登录信息整理到vars变量中,并使用&login作为锚点来编写。

在任务中,使用别名 *login_info 来调用 login信息作为模块的参数。

在以下示例Playbook中,在安装所有许可证(关于ontap_licenses role的说明稍后)之后,收集并显示ONTAP信息。

- hosts: cluster
  collections: netapp.ontap
  gather_facts: no
  vars:
    cert_login: &login
      hostname: "{{ ontap_hostname }}"
      cert_filepath: "{{ ontap_cert_filepath }}"
      key_filepath: "{{ ontap_key_filepath }}"
      validate_certs: "{{ ontap_validate_certs }}"

  roles:
    - role: ontap_licenses
      licenses:
        - "xxxxxxxxxxxxxxxxxAAAAAAAAAAA"
        - "xxxxxxxxxxxxxxxxxAAAAAAAAAAA"

  tasks:
    - name: Gather ONTAP facts.
      na_ontap_rest_info:
        <<: *login
        state: info
      register: result

    - debug: var=result

由于在Roll内部无法展开别名,我们已采取将变量命名为”ontap_”加上前缀的方式来解决该问题。

- name: ensure ontap licenses
  loop: "{{ licenses }}"
  na_ontap_license:
    state: present
    hostname: "{{ ontap_hostname }}"
    cert_filepath: "{{ ontap_cert_filepath }}"
    key_filepath: "{{ ontap_key_filepath }}"
    validate_certs: "{{ ontap_validate_certs }}"
    license_codes: "{{ item }}"

只需要将生成的客户端认证用的.pem/.key文件放置在Playbook所在的文件夹即可。

在GitHub上存放的playbooks的内容

    • group_vars/ontap.yml を適宜変更する

 

    • cluster.ymlのlicensesのライセンスコードを修正するか、roleを削除する

 

    • ontap-admin.pem / ontap-admin.key ファイルを設定したクライアント認証ファイルに置き換える

 

    run.sh を実行する

你可以试试看。

因此

如果你对SSL客户端认证非常了解,那么只需设置client-ca,再通过cert/key_filepath传递认证信息,就可以使用客户端认证来进行API利用,就像这样简单。

使用证书而不是用户名/密码对Ansible ONTAP模块进行身份验证存储虚拟机(SVM)的使用目的

除了API的范围之外,还可以通过RBAC进行详细设置,如管理员认证和RBAC

集群管理服务器是什么

GET /svm/svms “重要提示:REST APIs只将数据SVM公开为一个SVM”

bannerAds