AnsibleでCisco機器に公開鍵を一斉に配ってみた

# はじめに
自宅でCisco機器を4台ほど稼働させているのですが、全部と公開鍵認証でSSH接続したいと思いました。
ただCisco機器に公開鍵を登録するのってものすごく面倒なんですよね。
一気に文字列入れられればいいんですが、5回ぐらいに分けないと受け付けてくれません。

そこでAnsibleを使って全部まとめて公開鍵を配信してみました。


# 環境
Ansibleサーバ：Ubuntu20.04
Ansible Coreバージョン：2.13.1
Pythonバージョン：3.8.10

Cisco機器①(2台)
　モデル：WS-C3560CG-8TC-S
　IOS：15.2(2)E10

Cisco機器②(2台)
　モデル：WS-C2960CG-8TC-L
　IOS：15.2(2)E9

# 前提条件
・Ansibleを構築済みであること。
・Ansibleサーバから各Cisco機器にPing疎通が確認できていること。
・Cisco機器にパスワード認証でSSH接続できる状態であること。
・基本的なhostsファイルの記載方法を理解していること。
・基本的な公開鍵認証方式について理解していること。

ここではAnsibleの構築方法は割愛します。
もしAnsible構築方法から始めたい場合は下記記事から構築してみてください。

https://qiita.com/rat-engineer755/items/7b4d07b8759a745d7404

また、公開鍵認証方式ってなんじゃって方は下記を参考にしてみるといいかもしれません。

https://wa3.i-3-i.info/word17549.html

https://www.infraexpert.com/study/security4.html

# 鍵ペア作成
公開鍵認証方式をするにあたり、公開鍵と秘密鍵を作成する必要があります。
そのペアを作製していきましょう。

作成方法は2つあります。
- コマンドプロンプトから作成する方法
- TeraTermで作成する方法

私はネットワーク機器やサーバへ接続する際にTeraTermマクロを利用しているので、今回はTeraTermで作成していきたいと思います。

## TeraTermで鍵を生成する
まずTeraTermを開きます。
開いたら設定のSSH鍵生成をクリックしましょう。
「設定>SSH鍵生成(N)」
![スクリーンショット 2022-07-17 225237B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/45f72069-a7b7-66a2-10b4-a42bc8bf278d.png)

鍵生成のための画面が開きます。
基本的に鍵の種類はRSAでビット数は2048で問題ないと思います。
鍵の種類とビット数を設定したら、「生成」ボタンをクリックします。

![スクリーンショット 2022-07-17 225309B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/67da3fda-5112-09b9-8449-caa49e92f488.png)


しばらくすると「鍵のパスフレーズ」入力欄が解放されます。
パスフレーズを入力しましょう。
安全性を考えると出来るだけ桁数が長くて、英数字記号を混ぜたものがいいとは思いますが、個人の裁量です。
![スクリーンショット 2022-07-17 225346.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/b0b754e8-afe1-5b79-16c5-4ee7da08fbc7.png)

パスフレーズが入力出来たら、「公開鍵の保存(I)」と「秘密鍵の保存(P)」をクリックしましょう。
別途エクスプローラが現れて、それぞれの鍵の保存場所を聞かれます。
デフォルトではユーザ配下の[.ssh]フォルダに保存されるかと思います。

![スクリーンショット 2022-07-17 225407B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/9c5f305f-c187-bf96-7124-31ae73e1fc49.png)

保存されたファイルを確認するとこんな感じです。
![スクリーンショット 2022-07-17 225504.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/767d38a9-a0c4-c31a-2f68-c98b52d045da.png)
id_rsa：秘密鍵
id_rsa.pub：公開鍵

これで鍵ペアの作成は完了です。

# Ansibleサーバへ公開鍵を保存する
鍵ペアを作製出来たら、公開鍵をAnsibleに保存します。
鍵の転送方法はTeraTermの[SSH SCP]機能を使います。

TeraTermのSCP機能の使い方をご存知の方は飛ばしてください。

まず、Ansibleサーバへログインします。
ログインしたら、TeraTermのファイルからSSH SCPを選択します。
「ファイル(F)>SSH SCP...」
![スクリーンショット 2022-07-17 231230.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/f90b82b1-b611-7405-ee3b-973aa2b6743e.png)

SCPの画面が表示されます。
ここではサーバからローカルへ、ローカルからサーバへの送受信が可能ですが、今回は公開鍵をサーバへ送るため、送信機能を使います。
まず、送るファイルを選択するため、下記の[...]をクリックしてください。
![スクリーンショット 2022-07-17 231530B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/121895ea-120e-8435-1a0b-e9d5ab9b3864.png)

別途ファイル選択のウィンドウが表示されるため、「\user\.ssh」に保存した「id_rsa.pub」を選択しましょう。


次に送信先のフォルダ指定ですが、権限の問題があるためログインしているユーザのhomeディレクトリに一旦保存しましょう。

![スクリーンショット 2022-07-17 233134B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/7593b280-b936-dd1c-4e75-8506eec72922.png)

これで「Send」ボタンをクリックすれば指定したフォルダに保存されているはずです。確認してみましょう。

[コマンド]`ls -la | grep id_rsa`で見てみましょう。
```
user@ansi101v:~$ ls -la | grep id_rsa
-rw-r--r-- 1 rat  rat   405 Jul 17 00:12 id_rsa.pub
user@ansi101v:~$
```
ちゃんと保存されていますね。

## 公開鍵ファイルの移動
では次に[/etc/ansible/]ディレクトリに保存しましょう。
コマンドはmvを使います。また、[/etc]ディレクトリになるので、sudoを付けてあげましょう。
[コマンド]`sudo mv id_rsa.pub /etc/ansible/`

移動できたか確認しましょう。
[コマンド]`ls -la /etc/ansible | grep id_rsa`
```
user@ansi101v:~$ ls -la /etc/ansible | grep id_rsa
-rw-r--r--  1 rat  rat   405 Jul 17 00:12 id_rsa.pub
user@ansi101v:~$
```
ちゃんと移動していますね。

## /etc/ansible/.sshディレクトリ作成

ansible直下に置いておくとごちゃごちゃして嫌なので、[.ssh]ディレクトリを作成して、そこに保存しましょう。
[コマンド]`mkdir /etc/ansible/.ssh/`

作成できたか確認していきましょう。
[コマンド]`ls -la /etc/ansible/ | grep ssh`
```
user@ansi101v:~$ ls -la /etc/ansible/ | grep ssh
drwxr-xr-x  2 root root 4096 Jul 17 11:32 .ssh
user@ansi101v:~$
```

## 公開鍵ファイルの移動と名前変更
公開鍵を[.ssh]ディレクトリに移動するついでにファイル名も変更していきます。(別に変更しなくてもいいです)

[コマンド]`sudo mv /etc/ansible/id_rsa.pub /etc/ansible/.ssh/authorized_keys`

ちゃんと移動と名前変更が出来ているか確認しましょう。
[コマンド]`ls -la /etc/ansible/.ssh/`
```
user@ansi101v:~$ ls -la /etc/ansible/.ssh/
total 12
drwxr-xr-x 2 root root 4096 Jul 17 11:32 .
drwxr-xr-x 7 root root 4096 Jul 17 23:46 ..
-rwx------ 1 root root  405 Jul 17 11:32 authorized_keys
user@ansi101v:~$
```
ちゃんと移動と名前変更が出来ていますね。

# hostsの準備
公開鍵を配布する対象機器を指定します。
今回はtestというグループを作成し、Cisco機器のIPアドレス(もしくはhost名)を記載していきます。
hostsファイルの最後に下記の様に追記してあげます。
```
[test]　←グループ名
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4

[test:vars]　←グループ[test]の変数
ansible_user=ansible　←Cisco機器ログイン時のユーザ名
ansible_password=password　←パスワード認証時のパスワード
ansible_connection=network_cli　←接続方法
ansible_network_os=cisco.ios.ios　←対象機器のOS
ansible_port=22　←SSH接続のポート指定
ansible_become=yes　←特権モードを許可
ansible_become_method= enable　←特権モード昇格コマンド
ansible_become_password=password　←特権モード昇格時のパスワード
```
私なりの理解で記載しているので、認識間違いがあると思いますがご了承ください。

# Playbooksの準備
ここまで準備してやっとPlaybooksを記述していきます。
任意のファイル名でファイルを作成して、下記を参考に記述しましょう。
私は「create_user_public-key.yaml」というファイル名にしました。
[コマンド]`vim /etc/ansible/<任意のファイル名>.yaml`
```
---
- hosts: test
  gather_facts: false

  tasks:
    - name: Create New User Public-key
      cisco.ios.ios_user:
        name: ansible-public
        sshkey: "{{ lookup('file', '/etc/ansible/.ssh/authorized_keys')}}"
        state: present
...
```
簡単な設定項目と解説
上から順に記載
|項目|値|
|--|--|
|hosts|対象機器指定|
|gather_facts|facts変数の使用可否|
|tasks|タスクを記述する宣言|
|name|taskの名前を指定|
|cisco.ios.ios_user|ciscoのuser設定を変更するモジュールを使用|
|name|SSH接続用のユーザ名指定|
|sshkey|公開鍵ファイルの内容を指定する。ここではディレクトリパスを指定している|
|state|存在する状態(present)にするか、削除した状態(absent)にするか指定。デフォルトはpresent|


こんな感じです。
Playbooksが記述出来たらいよいよ設定していきます。

# Playbooksの実行
ただ実行するだけです。
[コマンド]`sudo ansible-playbook /etc/ansible/create_user_public-
key.yaml -i /etc/ansible/hosts`
[実行ログ]
```
PLAY [test] ***********************************************************

TASK [Create New User Public-key] **********************************************
[WARNING]: Module did not set no_log for update_password
[WARNING]: Module did not set no_log for password_type
changed: [192.168.1.1]
changed: [192.168.1.2]
changed: [192.168.1.3]
changed: [192.168.1.4]

PLAY RECAP *********************************************************************
192.168.1.1         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.1.2         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.1.3         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.1.4         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

user@ansi101v:~$
```

あとは公開鍵認証で各機器にログインできるか確認してみてください。