You are here
Home > Posts tagged "sftp"

パブリックキーを使用してsftp (2) sftponlyの環境で

前回では、Laravel Collective Remoteを利用して、sftpでファイルをアップロード・ダウンロードする話をしました。それだけで事はほとんど足りるのですが、1つ困ったことがありました。

sftpを使用するのは、たいてい自社のサーバーとではなく、他社とのサーバーとです。注文データを取得してくるのも、こちらのデータをアップロードするのも。御存知のように、sftpはsshと同じプロトコルであり、sshが使用できるならsftpも使用可能。しかし、先のような状況だと、セキュリティのために、sftpは使用できるけれど、sshは使用できないようにサーバーが設定されています。また、sftpでは、勝手に他のディレクトリへ行ったりできないように、閲覧できるディレクトリを特定して、jailします。

このような制限された設定となると、例えば以下のように、lsコマンドの実行が不可能となり、ファイルのリストさえ取ってくることできなくなります。

Psy Shell v0.7.2 (PHP 5.6.26 — cli) by Justin Hileman
>>> use SSH;
=> null
>>> SSH::into('acme')->run(['ls data']);
[foo@acme] (acme) This service allows sftp connections only.
..

かと言って、

>>> SSH::into('acme')->list('data');
PHP Fatal error:  Call to undefined method Collective\Remote\Connection::list()

のように、listのコマンドがあるわけでもありません。

いろいろ、探ってみると、

Laravel Collective Remoteは、

https://github.com/LaravelCollective/remote/blob/5.3/src/SecLibGateway.php

では、

以下のphpseclibというパッケージを使用しています。

https://github.com/phpseclib/phpseclib/blob/master/phpseclib/Net/SFTP.php

これらを参考にすると、

>>>SSH::into('acme')->getGateway()->getConnection()->nlist('data');
=> [
     "base-invoice.csv",
     "base-product.csv",
     ".",
   ]
..

というように、nlistを実行できます。

他にも、chdirとも実行できるようです。オープンソースのおかげでこういう問題自分で解決できます。

パブリックキーを使用してsftp

中規模のECを営む私のお客さんのところでは、自社製品を持ち出荷するゆえに、自社のウェブで販売するのみではなく、他社でのウェブサイトでも製品が売られています。となると、そこからも注文データが来ます。

その発注データは、ウェブサービスを使用したAPIを使用して取得、というようなものではなく、彼らが生成した注文データをCSVファイルとして指定のサーバーに置かれ、それを毎日sftpでダウンロードして、システム内に取り込みます。

また、逆に自社サイトで販売した注文情報を、出荷や解析の目的で他のサーバーにsftpでアップロードというケースもあります。

ここで重要なのは、パブリックキーを使用したsftpのコミュニケーションが必要なことです。

そこで登場するのが、以前会員編集フォーム紹介した、Laravel Collectiveです。

Laravel Collectiveのインストール

最初に、以下をコマンドラインで実行します。

$ composer require "laravelcollective/remote":"^5.3.0"

この実行で、必要なライブラリがインストールされ、composer.jsonが更新されます。

次に、config/app.phpのファイルをエディタで開き、以下を追加します。

  'providers' => [
    // ...
    Collective\Remote\RemoteServiceProvider::class,
    // ...
  ],

  'aliases' => [
    // ...
    'SSH' => Collective\Remote\RemoteFacade::class,
    // ...
  ],

設定

SSHのパッケージがインストールされたところで、次は設定です。Laravel用に開発されたパッケージでは、たいていはパッケージ独自の設定ファイルを、config/ディレクトリに作成します。

以下を、コマンドラインで実行してください。

$ php artisan vendor:publish --provider="Collective\Remote\RemoteServiceProvider"

この実行により、config/remote.phpの設定ファイルが作成されます。

エディターで、そのファイルを開き、acmeエントリーを追加します。acmeでなくても、名前はなんでもよいです。

  'default' => 'production',

  'connections' => [
        'production' => [
            'host'      => '',
            'username'  => '',
            'password'  => '',
            'key'       => '',
            'keytext'   => '',
            'keyphrase' => '',
            'agent'     => '',
            'timeout'   => 10,
        ],

        'acme' => [
            'host'      => env('ACME_HOST'), // sftp先
            'username'  => env('ACME_USERNAME'), // ログイン名
            'password'  => '', // 
            'key'       => base_path(env('ACME_KEY')), // パブリックキーファイルのパス名',
            'keytext'   => '',
            'keyphrase' => '', 
            'agent'     => '',
            'timeout'   => 10,
        ],
    ],

見ての通り、このファイルにはデフォルトとして、すでにproductionがありますが、それには触らず、ここではacmeの配列を新設しました。開発サイトでのテストも考えて、いろいろな情報をここで設定できるのは便利です。

今回は、バージョン管理にプライベートの値が入らないように、.envで指定するようにしました。特に、大きい値のパブリックキーを含むファイルを、keyで指定できるのも便利です。このファイルは、.gitignoreで必ずバージョン管理から排除が必要ですね。

keyphraseは、パブリックキーを生成したときに指定したパスワードを入れますが、パスワード指定なしで作成することが多いです。それでも十分セキュアであるのでここでは空とします。

.envでは、以下のような変数を追加します。

..
ACME_HOST=foo.google.com
ACME_USERNAME=foo
ACME_KEY=config/keys/test.pem
..

以上でテスト可能となります。もし、sftp先でsftpのみで設定されていないなら、

$ php artisan tinker

を実行して、接続テストができます。以下では、sshでacmeに接続して、lsコマンドを実行しました。

Psy Shell v0.7.2 (PHP 5.6.25 — cli) by Justin Hileman
>>> use SSH;
=> null
>>> SSH::into('acme')->run(['ls']);
[foo@acme] (acme) data.csv
=> null
>>> 

sftpでファイルのダウンロード・アップロード

ここまで来たら、あとは簡単です。プログラムの中で以下を実行するだけです。

ファイルのダウンロードは、

SSH::info('acme')->get('data.csv', storage_path('data.csv'));

ファイルのアップロードは、

SSH::info('acme')->put(storage_path('data.csv'), 'data.csv');

あたかも、コマンドラインで実行するような軽さですね。

Top