6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AnsibleAdvent Calendar 2022

Day 1

ansible でEC2 (Amazon Linux2) の SSH ポート番号を冪等性を担保しつつ変更する

Last updated at Posted at 2022-11-30

はじめに

冪等性を担保しつつ、ansibleでec2のSSH port番号を22から50001する手順をまとめました。

環境

  • ローカル環境
    • M1 Mac
    • MacOS Monterey 12.6
  • サーバ
    • Amazon Linux2

ansibleインストール

ローカルにansibleをインストールします。
Homebrewでもインストールできますが、pipだと細かいバージョン指定ができるため、pipでのインストールを採用しました。

最新バージョンをインストール場合
$ pip install ansible

バージョン指定
$ pip install ansible==6.5.0

インストールできたか確認するため、バージョンを確認します。

$ pip list
Package      Version
------------ -------
ansible      6.5.0
ansible-core 2.13.6

EC2を起動

EC2を起動しますが、起動方法は、省略します。
セキュリティーグループは、SSHポート番号の22とカスタムポート番号50001のインバウンドルールを許可します。
また、パブリック IP の自動割り当ては、有効化します。

スクリーンショット 2022-11-22 23.24.42.png

ansibleのプロジェクトを作成

playbookというディレクトリを作成し、その中に、hostsファイル、playbook.ymlファイル、sshdのrolesディレクトリを作成します。

$ mkdir playbook
$ cd playbook
$ touch hosts playbook.yml
$ ansible-galaxy init --init-path="roles" sshd

$ tree     
.
├── hosts
├── playbook.yml
└── roles
    └── sshd
        ├── README.md
        ├── defaults
        │   └── main.yml
        ├── files
        ├── handlers
        │   └── main.yml
        ├── meta
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        ├── templates
        ├── tests
        │   ├── inventory
        │   └── test.yml
        └── vars
            └── main.yml

使わないディレクトリを削除し、以下のようにします。

$ tree
.
├── hosts
├── playbook.yml
└── roles
    └── sshd
        ├── handlers
        │   └── main.yml
        └── tasks
            └── main.yml

4 directories, 4 files

hostsファイル作成

以下のように記載します。
本来なら、rolesのvarsのmain.ymlにcustom_ssh_port=50001などを書くのがよいですが、面倒なので、hostsファイルにまとめました。
IPは、サーバーのパブリックIPを記載してください。

hosts
[web] # 記載されたIPに対して接続
11.11.11.11

[web:vars] #[web]で使う変数を定義
ansible_ssh_port=22
ansible_user=ec2-user
__working_user=ec2-user
ansible_python_interpreter=/usr/bin/python2

# custom ssh port (49152~65535)
custom_ssh_port=50001

# pem key path
ansible_ssh_private_key_file=~/.ssh/test.pem

playbook.yml作成

playbool.yml
- name: Change port
  hosts: web
  become: yes
  gather_facts: false
  roles:
    - sshd

次の節でlocal_actionモジュールを使用するため、gather_factsは、falseにする必要があります。

  • gather_facts
    • 対象ホストの情報をansible_facts変数というものに格納し、tasks内の変数で使用することができます。

rolesのsshdディレクトリ配下を作成

tasksとhandlersのmain.ymlのみ記載します。ほかは使いません。

roles/sshd/tasks
# port22 でSSH接続する。タイムアウトは5秒で、接続失敗しても次に進む
- name: Connect default ssh port
  local_action: wait_for port={{ansible_ssh_port}} timeout=5 host={{inventory_hostname}}
  register: default_port
  ignore_errors: true
  become: False

# port22 で失敗した場合、port 50001でSSH接続する。タイムアウトは5秒
- name: Connect custom ssh port
  local_action: wait_for port={{custom_ssh_port}} timeout=5 host={{inventory_hostname}}
  register: custom_port
  when: default_port.elapsed >= 5
  become: False

# port22 でタイムアウトし、port50001でSSH接続成功した場合、ansible_ssh_portを50001に変える
- name: set ansible_ssh_port custom_ssh_port
  set_fact: ansible_ssh_port={{custom_ssh_port}}
  when: default_port.elapsed >= 5 and custom_port.elapsed < 5
  become: False

# 現在port22でSSH接続している場合、/etc/ssh/sshd_configのPortを50001に書き換える
- name: Rewrite custom_ssh_port
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^#Port'
    line: 'Port {{custom_ssh_port}}'
  notify: Restart sshd
  when: ansible_ssh_port == 22

# ssh接続時のパスワード認証を無効
- name: Disabling password authentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^PasswordAuthentication'
    insertafter: '^#PasswordAuthentication'
    line: PasswordAuthentication no
  notify: Restart sshd
# ssh接続時のチャレンジ/レスポンス認証を無効
- name: Disabling Challenge-Response Authentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^ChallengeResponseAuthentication'
    insertafter: '^#ChallengeResponseAuthentication'
    line: ChallengeResponseAuthentication no
  notify: Restart sshd

# rootユーザーのログイン無効
- name: Disabling root user login
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    insertafter: '^#PermitRootLogin'
    line: PermitRootLogin no
  notify: Restart sshd
roles/sshd/handlers
# sshdの設定が変更された場合、再起動する
- name: Restart sshd
  service:
    name: sshd
    state: restarted

モジュールの説明

  • local_action
    • リモートホストではなくローカルで実行したい場合に使用します。今回であれば、ローカルからSSH接続できます。
  • wait_for
    • SSH接続のアクション時、ポートが応答あるまで待つために使用します
      • timeoutやhost先を指定できます。
  • register
    • 処理結果を変数の中に一時的に保管できます
    • elapsed
      • 経過時間を示します
  • become
    • そのモジュールを root 権限で実行できます
  • set_fact
    • 新たな変数を定義できます。
      • 今回は、ansible_ssh_portの値が元々22だったのをcustom_ssh_port(50001)に上書きしました
  • lineinfile
    • ファイルを行単位で編集できます
    • dest
      • 編集するファイルのパスを指定
    • line
      • 置換または挿入する文字列を指定
    • regexp
      • 指定した正規表現にマッチした行を、lineで指定した文字列に置き換えます
      • lineで指定した文字列と、同じ場合は何もしません
    • insertafter
      • regexp にマッチする行が無かった場合、ここに指定した正規表現にマッチした次の行に、lineで指定した文字列を挿入する。
        • それにもマッチしない場合はファイル末尾に、lineで指定した文字列が挿入されます。
  • notify
    • notifyを付与したタスクがchangedになった場合、handlers内に定義されたタスクが実行されます。
      • 同じhandlersの呼び出しは1回にまとめらます。notifyを付与している複数のタスクがchangedになっても1度しか実行されません。

ansible実行

ルートディレクトリ配下で、下記コマンドにより、ansibleを実行できます。

$ ansible-playbook -i hosts playbook.yml

詳細なログを出力したい場合、-vvをつけます

$ ansible-playbook -i hosts playbook.yml -vv

1回目を実行します。

$ ansible-playbook -i hosts playbook.yml -vv

PLAY [Change port] ************************************************************************************************************

TASK [sshd : Connect default ssh port] ****************************************************************************************
ok: [13.231.201.67 -> localhost]

TASK [sshd : Connect custom ssh port] *****************************************************************************************
skipping: [13.231.201.67]

TASK [sshd : set ansible_ssh_port custom_ssh_port] ****************************************************************************
skipping: [13.231.201.67]

TASK [sshd : Rewrite custom_ssh_port] *****************************************************************************************
The authenticity of host '13.231.201.67 (13.231.201.67)' can't be established.
ED25519 key fingerprint is SHA256:SgTQf176TUJ/wSqlWH4inIAZ7NWU+eAQrewxa+aqEns.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
changed: [13.231.201.67]

TASK [sshd : Disabling password authentication] *******************************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling Challenge-Response Authentication] *********************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling root user login] ***************************************************************************************
changed: [13.231.201.67]

RUNNING HANDLER [sshd : Restart sshd] *****************************************************************************************
changed: [13.231.201.67]

PLAY RECAP ********************************************************************************************************************
13.231.201.67              : ok=6    changed=3    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0

1回目は、port22が使用されていることが分かります。
2回目を実行します。

$ ansible-playbook -i hosts playbook.yml

PLAY [Change port] ************************************************************************************************************

TASK [sshd : Connect default ssh port] ****************************************************************************************
fatal: [13.231.201.67 -> localhost]: FAILED! => {"changed": false, "elapsed": 5, "msg": "Timeout when waiting for 13.231.201.67:22"}
...ignoring

TASK [sshd : Connect custom ssh port] *****************************************************************************************
ok: [13.231.201.67 -> localhost]

TASK [sshd : set ansible_ssh_port custom_ssh_port] ****************************************************************************
ok: [13.231.201.67]

TASK [sshd : Rewrite custom_ssh_port] *****************************************************************************************
skipping: [13.231.201.67]

TASK [sshd : Disabling password authentication] *******************************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling Challenge-Response Authentication] *********************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling root user login] ***************************************************************************************
ok: [13.231.201.67]

PLAY RECAP ********************************************************************************************************************
13.231.201.67              : ok=6    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1

2回目は、custom ssh portである50001ポートが使用されている事がわかります。

3回目を実行しましょう。

ansible-playbook -i hosts playbook.yml

PLAY [Change port] ************************************************************************************************************

TASK [sshd : Connect default ssh port] ****************************************************************************************
fatal: [13.231.201.67 -> localhost]: FAILED! => {"changed": false, "elapsed": 5, "msg": "Timeout when waiting for 13.231.201.67:22"}
...ignoring

TASK [sshd : Connect custom ssh port] *****************************************************************************************
ok: [13.231.201.67 -> localhost]

TASK [sshd : set ansible_ssh_port custom_ssh_port] ****************************************************************************
ok: [13.231.201.67]

TASK [sshd : Rewrite custom_ssh_port] *****************************************************************************************
skipping: [13.231.201.67]

TASK [sshd : Disabling password authentication] *******************************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling Challenge-Response Authentication] *********************************************************************
ok: [13.231.201.67]

TASK [sshd : Disabling root user login] ***************************************************************************************
ok: [13.231.201.67]

PLAY RECAP ********************************************************************************************************************
13.231.201.67              : ok=6    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1

3回目もport 50001が使用されていますね。
また、changed=0であり、冪等性があることが分かります。

次回、ansibleのansible-lintを使用してコードをリファクタリング致します。

参考

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?