Open6

Linuxユーザー移住計画

oshimazakuraoshimazakura

目標

oldserver.netからnewserver.netにユーザーを移動させるとする。
ssh username@oldserver.net
でログインできたユーザーが、
ssh username@newserver.net
で新しいサーバーにログインできる状態にする。
ファイルの引っ越しは各自でやる。

oshimazakuraoshimazakura

目標達成のためのステップ

  1. 新サーバーに旧サーバーと同じ名前のユーザーを追加する
  2. 新サーバーに旧サーバーと同じ名前のグループを追加する
  3. ユーザーをグループに所属させる
  4. ユーザーhomeに旧サーバーと同じ公開鍵を置く

これでOK???

oshimazakuraoshimazakura

下調べ1

linuxのお勉強

ユーザー情報の場所

  • /etc/passwd
    ユーザー基本情報
  • /etc/shadow
    ユーザーのパスワードが暗号化されて記載されている

passwdの中身

/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
・・・

各行がユーザー各人に対応。
ユーザー名:x:ユーザーID:グループID:コメント:ホームディレクトリ:ログインシェル
を表しているらしい。コメント書けるんや。
xのところは昔はパスワードが書いてあったけど、誰でも見れてしまうので別ファイルに記載した名残っぽい。その別ファイルというのがshadowファイル。

dockerのcentos7イメージで実験しているが、最初から上記のようにrootユーザー以外のユーザーがいるみたい。システム用と思われる。

shadowの中身

/etc/shadow
root:locked::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
adm:*:18353:0:99999:7:::
lp:*:18353:0:99999:7:::
sync:*:18353:0:99999:7:::
shutdown:*:18353:0:99999:7:::
・・・

各列の意味はいろいろあるが、今回重要そうなのは最初の2列
ユーザー名:パスワード:その他
* は パスワードが設定されておらず、ログインできない。

[root@9b63f4a8bc59 /]# su - bin
This account is currently not available.

↑ログインしようとしたら怒られた。

ちなみに3列目はパスワードの更新日時らしく
18353はunixtimeで1970-01-01 14:05:53に相当している。

ていうかユーザーIDがあるのに、shadowファイルはユーザー名で管理するのか...

oshimazakuraoshimazakura

下調べ2

linuxのお勉強

ユーザーの追加

useradd ユーザー名 コマンドでユーザーを追加できる。 adduser でも同じ(ん?🤔)。

ユーザー oshimazakuraを追加

useradd oshimazakura

結果

/etc/passwd
oshimazakura:x:1000:1000::/home/oshimazakura:/bin/bash

最初のユーザーはID 1000番からスタート。これはcentosの仕様で、他のOSだと変わることもあるらしい。なのでユーザーを移住させる際に、passwdまるまるコピーは危険。

/etc/shadow
oshimazakura:!!:18988:0:99999:7:::

パスワードの部分が!!になっている。これはロックされた状態らしく、たぶんrootユーザーからでないとログインできない。

パスワードの設定

passwd コマンド(/etc/passwd ファイルとは別)でパスワードを設定できる。

passwd oshimazakura

このように入力すると

Changing password for user oshimazakura.
New password: 

と聞かれるので、パスワードを入力。ここでは2021年人気第4位の qwerty をパスワードとして入力。
BAD PASSWORD: The password is shorter than 8 characters と警告がでてきたが、気にせず確認用に再入力。警告がThe password is too popular とかでなくて残念。

結果

/etc/shadow
oshimazakura:$6$Rlt7om9.$uxHzOOLjSfI4rnStn3OPTCJTVeNWnWxCVIbCMPFcehu9CIftflKq1Mk0T6gE8XYSTtCe/4f2inL1RsrJ4kv8v0:18988:0:99999:7:::

shadowファイルには暗号化されて記載される。あれ最終更新日時が18988のまま変わっていない。この数字は最終更新日時ではなかったんかな???

パスワードの設定2

useradd コマンドにユーザーを作るときに、オプション引数 -p でパスワードを入力できる。

ユーザー oshimaを パスワードを指定して追加

useradd oshima -p qwerty

さっきと同様に大人気パスワードqwerty を設定。

結果

/etc/shadow
oshima:qwerty:18988:0:99999:7:::

この方法の場合、引数で指定した文字列がそのままshadowファイルに反映される。
なのでログイン時にqwertyと入力してもログインできない。ていうかlinuxパスワードのハッシュ関数の仕様は知らないが、おそらく固定長のハッシュ値になると思うので、実質ログイン不可能!

普段パスワード設定のときには絶対に使わない引数だけど、今回のようなユーザー移住では役に立ちそう。
旧サーバー内のshadowファイルのパスワード部分をコピーして、新サーバーでuseraddするときに使えば、暗号化方式が同じ場合はこれでパスワードを移行できたことになる。

Home ディレクトリ

useradd コマンドでユーザーを作ると、自動的にhome ディレクトリも作られる。

ll /home/
total 12
drwx------ 2 oshima        oshima        4096 Dec 27 11:04 oshima
drwx------ 2 oshimazakura  oshimazakura  4096 Dec 27 10:41 oshimazakura

あとはここに.sshフォルダ作って公開鍵いれたらユーザー情報の移動は終わり?
(グループはちょっと面倒くさくなってきた)

oshimazakuraoshimazakura

ユーザー作成スクリプト作成スクリプトの作成

下調べの結果、
旧サーバーの /etc/passwd と /etc/shadow から、ユーザー名とパスワード(暗号化)を読み取って、useraddコマンドを使えばできるんじゃないかという見通しが立った。
上記操作を自動化したい。

いろいろ選択肢はあると思うけど、centos7にデフォで入ってたpythonを使ってみる。

つまりpythonでuseraddが必要なだけ書かれたシェルスクリプトを作成する。

create_useradd.py
passwd_file = "/etc/passwd"
shadow_file = "/etc/shadow"
id_min = 1000

user_dict = {}

# Read "passwd" file and create a user dictionary
with open(passwd_file, "r") as f:
    for line in f:
        columns = line.split(":")
        name = columns[0]
        user_id = int(columns[2])
        if user_id >= id_min:
            user_dict[name] = "x"

# Read "shadow" file and the encrypted password
with open(shadow_file, "r") as f:
    for line in f:
        columns = line.split(":")
        name = columns[0]
        password = columns[1]
        if name in user_dict:
            user_dict[name] = password

# print useradd command
for key, val in user_dict.items():
    print("useradd {0} -p {1}".format(key, val))


実行すると次のようなテキストが標準出力される。

useradd oshimazakura -p $6$Rlt7om9.$uxHzOOLjSfI4rnStn3OPTCJTVeNWnWxCVIbCMPFcehu9CIftflKq1Mk0T6gE8XYSTtCe/4f2inL1RsrJ4kv8v0
useradd oshima -p qwerty

python create_useradd.py > addusers.sh とかでシェルスクリプトのできあがり。
このpythonを旧サーバーで実行してシェルスクリプトを作り、新サーバーで実行するだけ😀

oshimazakuraoshimazakura

追記
ここに書いた方法はセキュリティ的によろしくないので実行しないように。
最後にも書いたけど、ここに書いてあるコマンドを実行するためには、新サーバーに旧サーバーの秘密鍵をアップしないといけない。
ということで方法を変えます。ただやりたいことは一緒なので投稿は残しておきます。

公開鍵のコピー

新サーバーnewserver.netにも秘密鍵を使ってssh接続できるようにしたい。
そのために旧サーバーoldserver.netの各ユーザーの公開鍵をコピーする。

が、これが権限の問題でなかなか大変そう。。。
他人のディレクトリのファイルをコピーするにはroot権限が必要になる。
copy_problem
他人のファイルのコピーは、読み込み/書き込み 両方root権限が必要

つまり次のように、両方rootでログインするコマンドはOK

scp root@oldserver.net:他人ファイル root@newserver.net:他人ファイル

そして次のコマンドはエラーになると思われる(試してない)。

scp oshimazakura@oldserver.net:他人ファイル root@newserver.net:他人ファイル
scp root@oldserver.net:他人ファイル oshimazakura@newserver.net:他人ファイル
scp oshimazakura@oldserver.net:他人ファイル oshimazakura@newserver.net:他人ファイル

コピーコマンドをサーバーにログインして行えば、sudoで片方の権限はクリアできる。
つまり次のコマンドは通る。

[oshimazakura@oldserver.net]$sudo scp 他人ファイル root@newserver.net:他人ファイル

だけどコピー先もrootでログインしたくない。
いろいろ調べてたらrsyncコマンドのオプションに--rsync-pathというのがあって、これは相手先のrsyncコマンドのパスを指定するオプションらしい。これを"sudo rsync"にすると相手先でもroot権限で書き込みするみたい。

つまり

[oshimazakura@oldserver.net]$sudo rsync -vr --rsync-path="sudo rsync" 他人ファイル oshimazakura@newserver.net:他人ファイル

とすれば、
他人のファイルを他人のディレクトリにコピーができそう。

これで終わり。。。ではなくコピーしてきたファイルの所有権を対応するユーザーに変える作業がまだある。。。

追記
newserverでrsyncコマンドでoldserverのファイルをコピーしようと考えていたけど、
そのためにはnewserverにoldserberの秘密鍵を置かないとならない
一時的であっても、秘密鍵はリモートサーバー上に置きたくないので、作戦変えます。