やりたいこと
SSHのパスワード認証方式を禁止したい。それをcloud-initで設定したい。
前提条件
- 機種: Raspberry Pi 2 Model B
- OSイメージ: ubuntu-18.04.2-preinstalled-server-armhf+raspi2.img.xz
- https://wiki.ubuntu.com/ARM/RaspberryPi からダウンロードできる。
- Raspberry Pi 2用にUbuntuがインストールされた状態のディスクイメージ。これをSDカードに焼くと、そのまま起動できる。
うまくいかなかったこと
cloud-initが /etc/ssh/sshd_config で PasswordAuthentication no と設定してくれることを期待して、
/etc/cloud/cloud.cfg.d/999_my.cfg を次のように設定した。
ssh_pwauth: False
ところが、初回起動時に PasswordAuthentication yes と設定されてしまった。
/var/log/cloud-init.log においてもその形跡が確認できる(option PasswordAuthentication updated no -> yes)。
$ fgrep -5 PasswordAuthentication /var/log/cloud-init.log 2019-04-28 09:18:11,706 - helpers.py[DEBUG]: Running config-set-passwords using lock (<FileLock using file '/var/lib/cloud/instances/nocloud/sem/config_set_passwords'>) 2019-04-28 09:18:11,710 - cc_set_passwords.py[DEBUG]: Changing password for ['ubuntu']: 2019-04-28 09:18:11,712 - util.py[DEBUG]: Running command ['chpasswd'] with allowed return codes [0] (shell=False, capture=True) 2019-04-28 09:18:11,948 - util.py[DEBUG]: Reading from /etc/ssh/sshd_config (quiet=False) 2019-04-28 09:18:11,951 - util.py[DEBUG]: Read 3262 bytes from /etc/ssh/sshd_config 2019-04-28 09:18:11,955 - ssh_util.py[DEBUG]: line 56: option PasswordAuthentication updated no -> yes 2019-04-28 09:18:11,957 - util.py[DEBUG]: Writing to /etc/ssh/sshd_config - wb: [644] 3263 bytes 2019-04-28 09:18:11,962 - util.py[DEBUG]: Running command ['service', 'ssh', 'restart'] with allowed return codes [0] (shell=False, capture=True) 2019-04-28 09:18:12,226 - cc_set_passwords.py[DEBUG]: Restarted the ssh daemon. 2019-04-28 09:18:12,228 - handlers.py[DEBUG]: finish: modules-config/config-set-passwords: SUCCESS: config-set-passwords ran successfully 2019-04-28 09:18:12,229 - stages.py[DEBUG]: Running module grub-dpkg (<module 'cloudinit.config.cc_grub_dpkg' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_grub_dpkg.py'>) with frequency once-per-instance
原因
/etc/cloud/cloud.cfg.d/999_my.cfg よりもデータソース"NoCloud"の設定の方が優先されたため。
Ubuntuをインストール済みのディスクイメージには /var/lib/cloud/seed/nocloud-net/user-data と /var/lib/cloud/seed/nocloud-net/meta-data が存在していた。
$ cat var/lib/cloud/seed/nocloud-net/user-data #cloud-config password: ubuntu chpasswd: ubuntu ssh_pwauth: True
$ cat var/lib/cloud/seed/nocloud-net/meta-data instance_id: cloud-image
var/lib/cloud/seed/nocloud-net/user-data には ssh_pwauth: True と記載されており、この設定が優先されたため、 PasswordAuthentication yes に書き換えられてしまった。
解決策
データソースリストから"NoCloud"を消して"None"だけにする。
そのために、 /etc/cloud/cloud.cfg.d/999_my.cfg の先頭に次の行を追記する。
datasource_list: [None]
この修正を加えたSDカードを改めて作った。初回起動時のログを見ると PasswordAuthentication は no のままになっていることがわかる。
ubuntu@raspi:~$ fgrep PasswordAuthentication /var/log/cloud-init.log 2019-04-28 15:26:15,960 - ssh_util.py[DEBUG]: line 56: option PasswordAuthentication already set to no 2019-04-28 15:26:15,961 - cc_set_passwords.py[DEBUG]: No need to restart ssh service, PasswordAuthentication not updated.
参考情報
/etc/cloud/ のファイル構成
ubuntu@raspi:/etc/cloud$ tree
.
├── build.info
├── cloud.cfg
├── cloud.cfg.d
│ ├── 05_logging.cfg
│ ├── 90_dpkg.cfg
│ ├── 99-fake_cloud.cfg
│ └── README
└── templates
├── chef_client.rb.tmpl
├── chrony.conf.debian.tmpl
├── chrony.conf.fedora.tmpl
├── chrony.conf.opensuse.tmpl
├── chrony.conf.rhel.tmpl
├── chrony.conf.sles.tmpl
├── chrony.conf.ubuntu.tmpl
├── hosts.debian.tmpl
├── hosts.freebsd.tmpl
├── hosts.redhat.tmpl
├── hosts.suse.tmpl
├── ntp.conf.debian.tmpl
├── ntp.conf.fedora.tmpl
├── ntp.conf.opensuse.tmpl
├── ntp.conf.rhel.tmpl
├── ntp.conf.sles.tmpl
├── ntp.conf.ubuntu.tmpl
├── resolv.conf.tmpl
├── sources.list.debian.tmpl
├── sources.list.ubuntu.tmpl
└── timesyncd.conf.tmpl
/etc/cloud/cloud.cfg の中身
# The top level settings are used as module
# and system configuration.
# A set of users which may be applied and/or used by various modules
# when a 'default' entry is found it will reference the 'default_user'
# from the distro configuration specified below
users:
- default
# If this is set, 'root' will not be able to ssh in and they
# will get a message to login instead as the default $user
disable_root: true
# This will cause the set+update hostname module to not operate (if true)
preserve_hostname: false
# Example datasource config
# datasource:
# Ec2:
# metadata_urls: [ 'blah.com' ]
# timeout: 5 # (defaults to 50 seconds)
# max_wait: 10 # (defaults to 120 seconds)
# The modules that run in the 'init' stage
cloud_init_modules:
- migrator
- seed_random
- bootcmd
- write-files
- growpart
- resizefs
- disk_setup
- mounts
- set_hostname
- update_hostname
- update_etc_hosts
- ca-certs
- rsyslog
- users-groups
- ssh
# The modules that run in the 'config' stage
cloud_config_modules:
# Emit the cloud config ready event
# this can be used by upstart jobs for 'start on cloud-config'.
- emit_upstart
- snap
- snap_config # DEPRECATED- Drop in version 18.2
- ssh-import-id
- locale
- set-passwords
- grub-dpkg
- apt-pipelining
- apt-configure
- ubuntu-advantage
- ntp
- timezone
- disable-ec2-metadata
- runcmd
- byobu
# The modules that run in the 'final' stage
cloud_final_modules:
- snappy # DEPRECATED- Drop in version 18.2
- package-update-upgrade-install
- fan
- landscape
- lxd
- puppet
- chef
- mcollective
- salt-minion
- rightscale_userdata
- scripts-vendor
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- phone-home
- final-message
- power-state-change
# System and/or distro specific settings
# (not accessible to handlers/transforms)
system_info:
# This will affect which distro class gets used
distro: ubuntu
# Default user name + that default users groups (if added/used)
default_user:
name: ubuntu
lock_passwd: True
gecos: Ubuntu
groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/bash
# Automatically discover the best ntp_client
ntp_client: auto
# Other config here will be given to the distro class and/or path classes
paths:
cloud_dir: /var/lib/cloud/
templates_dir: /etc/cloud/templates/
upstart_dir: /etc/init/
package_mirrors:
- arches: [i386, amd64]
failsafe:
primary: http://archive.ubuntu.com/ubuntu
security: http://security.ubuntu.com/ubuntu
search:
primary:
- http://%(ec2_region)s.ec2.archive.ubuntu.com/ubuntu/
- http://%(availability_zone)s.clouds.archive.ubuntu.com/ubuntu/
- http://%(region)s.clouds.archive.ubuntu.com/ubuntu/
security: []
- arches: [arm64, armel, armhf]
failsafe:
primary: http://ports.ubuntu.com/ubuntu-ports
security: http://ports.ubuntu.com/ubuntu-ports
search:
primary:
- http://%(ec2_region)s.ec2.ports.ubuntu.com/ubuntu-ports/
- http://%(availability_zone)s.clouds.ports.ubuntu.com/ubuntu-ports/
- http://%(region)s.clouds.ports.ubuntu.com/ubuntu-ports/
security: []
- arches: [default]
failsafe:
primary: http://ports.ubuntu.com/ubuntu-ports
security: http://ports.ubuntu.com/ubuntu-ports
ssh_svcname: ssh
/etc/cloud/cloud.cfg.d/99-fake_cloud.cfg の中身
# configure cloud-init for NoCloud datasource_list: [ NoCloud, None ]
ここでデータソースが"NoCloud"、"None"の順に定義されている。