0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WEBアクセスでSUDO実行

Last updated at Posted at 2024-04-21

はじめに

会社のHPをWordPressで構築していますが、「最近(忘れたころに)」DB接続エラーが起きてしまって困ることがありました(サーバー: SakuraVPS/AlmaLinuxベース)。1年ぶりに接続エラーが起きると『何事だ』と焦りますよね。

NEOKI

お休み中で油断して自宅でまったりとしているとき(お昼寝中)に『閲覧できないんですけど...』とトラブル連絡が来てびっくり仰天、ページ閲覧不可の状態を長引かせるわけにもいかずで焦る、とイヤな感じがしますよね。

NEOKI  NEOKI  NEOKI

本来は DB接続エラーにつながる原因を排除していきトラブル可能性を低くしてことがが王道だと思いますが、それをしたからといってトラブルは起こるときは起こるものです。

とりあえずHP(WP)を復旧させたい、「急ぐ、どうしよう」と思うわけです。

復旧させるにはサーバーにログインしてコンソールでSUDOでDBサービス再起動させるのが本来の手段ですが(予想外の理由でmysqlが落ちている、とりあえず起動だけさせておきたい!の前提)
image.png

自宅にいるときなどパスワード(機密情報)を入手できずであせったりしますね。しかも作業を頼めるようなLinuxに詳しい人にも連絡つかないしの状態。これから仕事場に向かわないといけないの?いつもなら職場にVPN接続してなんとかするけど今は自宅にパソコンがないようぅぅぅ(泣)

サーバーログインをしないで気軽にDBサービス再起動できたらいいな、Linuxコマンド不慣れな人へも「DB再起動ぐらい」は頼める状態にあってほしい!が切実な願いなのです。

image.png

思い

ブラウザで特定のURLをたたくだけで、DBサービス再起動させたい、つまりブラウザ経由でsystemctl restart mariadbを実行したい。ブラウザでたたくだけだから誰でもできるよね(お休みのときは他の人に任せてゆっくりと過ごしたい)。

今回のサーバー構成

  • SakuraVPS
  • OS: Almalinux 8.6 (Sky Tiger)
  • WEBサーバ: Apache/2.4.37 (AlmaLinux)
  • PHP: PHP 8.1.6 (cli) (built: May 11 2022 01:14:18)
  • DB: mysql Ver 15.1 Distrib 10.3.32-MariaDB

考慮するべき点

APACHEを通してシェルコマンドを実行することはできるのですが、そのときのシェルコマンドの実行ユーザは APACHEユーザになります。今回の場合、APACHEユーザは apache と設定されていました。ubuntu系OSでよく見ますがwww-dataの場合もあります。APACHEユーザは設定により異なりますので念のために事前確認しておきましょう。

ここで問題となることがあります。APACHEユーザにはROOT権限がありませんしSUDOもできません(標準ではのお話しですが)。

そのため(そのままでは)APACHEユーザではROOT権限を必要とする『システム管理』コマンドなどを実行することができません。

ではどうしましょうか?

APACHEユーザを rootにする案

APACHEの設定でAPACHEユーザに ROOTを指定する方法です。
危険すぎるので候補として考えたくもないですね。

APACHEユーザが普通にSUDOできるようにしてあげる案

visudo で設定を与える方法です。

apache    ALL=(ALL:ALL) ALL

これでsudoをつけたら何でも実行できてしまいます。
rootと同じく危険すぎて候補から除外ですね。
それとsudo をすると 実行ユーザのパスワードを求められますが、apacheユーザにはパスワードがないので実行できないかもしれません(試してないからわからない)。

特定の管理CMD限定で SUDOできるようにする案

特定の管理CMD(例: systemctl ) 限定で、sudoできるようにする方法です。

apache ALL=(ALL) NOPASSWD: systemctl

NOPASSWORDをつけているので SUDOをしたときにパスワードを求めてこないですが、WEB経由でsystemctlを実行できてしまいます。何でもできてしまう状態からは脱しているのですが、systemctlという強力なコマンド(システムに与える影響が広すぎるコマンド)を直接に実行できてしまうことが『気持ちわるい』です。
できればこの方法は採用したくないです。

特定のシェルスクリプト限定でSUDOできる案

apache ALL=(ALL) NOPASSWD: /home/hoge/fuga.sh

この設定をして、fuga.shのなかで、sudo で 管理CMDを実行する!を書いてみたらよさそうなのかな?

それでは実験で apacheユーザになってみましょう

hoge@pc:~$ sudo su - apache --shell=/bin/bash
apache@pc:~$ 

apacheユーザになった状態で sudo fuga.shを実行してみます
apache@pc:~$ sudo /home/hoge/fuga.sh

でもエラーになります。/home/hoge の参照権限が apacheにはないからです。場所が悪かった。

apacheユーザの状態から、ユーザ=hogeとして /home/hoge/fuga.sh を実行してみましょう

apache@pc:~$ sudo -u hoge /home/hoge/fuga.sh

はい。これで、/home/hoge/fuga.sh が実行できました(Apacheユーザで SUDO が実行されました)。

apache→hoge→SUDO実行

hogeユーザで SUDOをすると、パスワードを求められます。

/home/hoge/fuga.sh
#!/bin/bash
sudo systemctl restart mariadb

WEBページ経由で fuga.shを起動しているのですが、パスワードを自動的に付与してみましょう。SUDOにオプション-Sをつけてみます。

/home/hoge/fuga.sh
#!/bin/bash
echo "PASSWORD" | sudo -S systemctl restart mariadb

スクリプトのなかにパスワードを書くことにためらいがあるのであれば、こうしましょう

/home/hoge/passCode.txt
PASSWORD
/home/hoge/fuga.sh
#!/bin/bash
cat /home/hoge/passCode.txt | sudo -S systemctl restart mariadb

パスワード文字列とスクリプトを分離できました。多分、気休程度ですけどこれがよさそう。

まとめ

PHPスクリプト

/var/www/html/dbRestarter.php
<?php
exec('/var/www/kick.sh'); // USER( apache )

PHPスクリプトのなかに USER=hogeを書くことに抵抗があるので、kick.shをはさみます。kick.sh は apacheユーザに参照権限があるところにおきましょう。

kick.sh

ここでユーザhogeに化かします。

/var/www/kick.sh
#!/bin/bash
sudo -u hoge /home/hoge/fuga.sh     # USER = apache ⇒ hoge

fuga.sh ( 目的である systemctlを実行する )

/home/hoge/fuga.sh
#!/bin/bash
cat ~/passCode.txt | sudo -S systemctl restart mariadb   # USER(hoge)

passCode.txt

/home/hoge/passCode.txt
PASSWORD

最後に

念の為にいっておきますが、WEBブラウザからApache経由でDB再起動はすこし危険です。
危険を承知のうえで「もしものときに備えたい」気持ちが強いのであれば「メリットとリスク」をよく考えてみてから採用してみてください。会社のサーバー運用体制陣充実しているのであれば本ページで説明した方法を検討する必要性は全くありませんからね。

ブラウザでたたくURLは特定の人だけで共有するべきです。社内の誰でも勝手にいつでもDB再起動ができる状態というのは「ゼッタイニダメ」です。社外に公開するのは論外です。

キャッシュされたURLで「間違えてたたいた」も回避したいですね。
例えば、GETパラメータで 現在「日時分」を与えて、「現在日時分」でないときは無視するように、PHPスクリプトを工夫したらよいでしょう。

?code=2404211320
<?php
$params = $_GET['code']; // 2404211320 が入っている
if( isset($params) ) {
    if( $params == date('ymdHi') ) {
        exec("/var/www/kick.sh");
    }
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?