2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel】本番環境で絶対に実行してはいけないコマンドを防ぐシンプルな方法

Posted at

はじめに

本番環境でphp artisan migrate:fresh実行して真っ青になった経験、ありませんか?
私はあります。(小声)

今回はLaravelで提供されているprohibitDestructiveCommandsメソッドを使って、本番環境での破壊的コマンドの実行を防ぐ方法を紹介します。

何が怖いのか

Laravelには便利だけど本番環境で絶対に実行してはいけないコマンドがいくつかあります。

# データベースの全テーブルを削除
php artisan db:wipe

# マイグレーションをリセットして再実行
php artisan migrate:fresh

# マイグレーションをロールバックして再実行
php artisan migrate:refresh

# マイグレーションを全てロールバック
php artisan migrate:reset

# 最後のマイグレーションをロールバック(Laravel 11.39以降)
php artisan migrate:rollback

これらのコマンドは開発環境では超便利なんですが、本番環境で実行してしまうと...
まぁ、想像したくないですね。

解決策

実はLaravelには、こういった事故を防ぐための仕組みが用意されています。

AppServiceProviderに以下のコードを追加するだけです。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\DB;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        DB::prohibitDestructiveCommands(
            $this->app->isProduction()
        );
    }
}

たったこれだけ。

仕組み

DB::prohibitDestructiveCommands()メソッドは、引数にtrueが渡されると、以下のコマンドの実行を禁止します。

  • db:wipe
  • migrate:fresh
  • migrate:refresh
  • migrate:reset
  • migrate:rollback(Laravel 11.39以降)

$this->app->isProduction()は、APP_ENVproductionの時にtrueを返すので、本番環境でのみこれらのコマンドが禁止される仕組みです。

実際に試してみる

本番環境での動作

# .envで APP_ENV=production に設定した状態で
php artisan migrate:fresh

実行すると以下のようなエラーが出ます。

Destructive commands are prohibited in production.

うん、安心。

開発環境での動作

# .envで APP_ENV=local の状態で
php artisan migrate:fresh

通常通り実行されます。開発環境では今まで通り使えるので、開発効率が落ちる心配もありません。

さらなる安全対策

基本的には上記の設定だけで十分ですが、さらに安全性を高めたい場合は以下の対策も検討してください。

1. 環境変数での追加制御

特定の環境変数がある場合のみ破壊的コマンドを許可する、みたいな実装も可能です。

public function boot()
{
    $shouldProhibit = $this->app->isProduction() 
        && !env('ALLOW_DESTRUCTIVE_COMMANDS', false);
    
    DB::prohibitDestructiveCommands($shouldProhibit);
}

2. カスタムミドルウェアの実装

特定のIPアドレスからのみ実行を許可するとか、そういった制御も可能です。

3. データベースユーザーの権限設定

本番環境のデータベースユーザーには、そもそもDROP権限を与えない、というのも有効な対策です。

-- 必要最小限の権限のみ付与
GRANT SELECT, INSERT, UPDATE, DELETE ON database.* TO 'app_user'@'localhost';

まとめ

DB::prohibitDestructiveCommands()を使うと、本番環境での破壊的コマンドの実行を簡単に防げます。

実装も簡単だし、開発環境には影響しないし、導入しない理由がないですね。

まだ設定していない方は、この記事を読み終わったらすぐにAppServiceProviderに追加しておきましょう。
未来の自分(とチームメンバー)を守るために。

参考

2
3
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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?