docker-composeでボリュームマウントした際にパーミッションを指定したかった

開発環境のdocker化しているときに当たった壁の話です。

プロジェクトのディレクトリ配下にNFSマウントし、他のロール(サーバ)とデータを共有しそれぞれ読み書きしているような箇所を開発環境のdockerでは、volumeを使ってやろうと思っています。

volumeをマウントする際、パーミッション周りで困ったのでメモしておきます。

開発環境について

php(php-fpm)のOfficial Imageを使っています。 https://hub.docker.com/_/php/

phpの実行ユーザは www-data

困っていること

簡潔に書くと、こういう構成で、php側から、hogedata 以下に読み書きしたいけど、

version: '3.5'

services:
  php-fpm:
    image: php:7.3-fpm-stretch
    volumes:
      - ./:/var/www/hoge-project/current/hogedata/
      - hogedata:/var/www/hoge-project/current/hogedata/
    environment:
      TZ: Asia/Tokyo
      LANG: ja_JP.UTF-8

volumes:
  hogedata:

パーミッションがこうなので、www-data からは書き込めない

drwxr-xr-x 2 root root 4096 Feb 16 19:55 hogedata

といった状況

回避策

先に、Dockerfileの方でパーミッションを設定しておくと、その設定が上書きされるので、先に作っておくことで回避できそう。 https://github.com/docker/compose/issues/3270#issuecomment-363478501

FROM php:7.3-fpm-stretch
RUN install -o www-data -g www-data -d /var/www/hoge-project/current/hogedata/
drwxr-xr-x 2 www-data www-data 4096 Feb 16 20:06 hogedata

でも、なんか、うーん。今回のケースのような場合は、Dockerfileの方にぐちゃぐちゃプロジェクト依存のものを書くのは嫌な気持ち。ライブラリのインストールとかだけにしたい。(あくまで気持ちの問題であって、Dockerfileとdocker-composeの住み分けは自分のなかで整理できてなく課題なのである。)

まとめ

ちょっとスッキリしないので、次のステップとして、今回はそもそも、volumeでやるのが良いんだっけ?というそもそも論を確認することと、docker の volume がちゃんと理解できてないのでする。(dockerの問題なのか、docker-composeの問題なのかなど)


こういうのがあったら、良いのかな。

SOURCE:TARGET:RW:OWNER

https://github.com/docker/compose/issues/3270#issuecomment-451862361

packer + puppet を使ってdockerのイメージを作成してみる

開発環境の構築にpackerを使うともっと楽にできるという噂を聞いたので試してみます。 最近軽く試してみる系のエントリばかりなのですが、今回もそれ系です。

packerとは

マシンイメージの構築を自動で行ってくれるツールです。HashiCorp製。

www.packer.io

Docker の他には、AWS(AMI), VMware, VirtualBox などに対応しています。 https://www.packer.io/intro/index.html

また、Ansible・Chef・Puppetといった構成管理ツールを使って環境構築することができます。

インストール

次(以下リンク)の3つの方法で、インストールすることができます。

Install Packer - Getting Started - Packer by HashiCorp

このうち今回は、2.Installing from source This method is only recommended for advanced users. で行いました。

実行してみる

今回はお試しなので、 puppet(Masterless)を使って、rubyがインストールされた dockerのイメージを作りました。

参考:

Puppet Masterless - Provisioners - Packer by HashiCorp

Docker - Builders - Packer by HashiCorp

できたpackerの設定はこのようになりました。

packer.json

{
  "builders": [{
    "type": "docker",
    "image": "centos:7",
    "export_path": "image.tar",
    "pull": false
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "rpm -q puppet5-release || rpm -Uvh https://yum.puppet.com/puppet5/puppet5-release-el-7.noarch.rpm",
      "rpm -q puppet-agent || yum install -y puppet-agent"
    ]
  }, {
    "type": "puppet-masterless",
    "manifest_file": "ruby.pp",
    "puppet_bin_dir": "/opt/puppetlabs/bin",
    "prevent_sudo": true
  }],
  "post-processors": [{
    "type": "docker-import",
    "repository": "centos-ruby-image"
  }]
}

ruby.pp

package { "ruby":
  provider => "yum",
  ensure => "latest"
}

設定した内容に対して、以下でビルドを行います。

packer build packer.json

実行した結果

docker run -it centos-ruby-image /bin/bash

rubyが入ったことを確認

ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]

packerを使ってみて

  • Dockerfileで良いのでは?と思っていたが

今回イメージしたものくらいの範囲であれば、Dockerfileでピッと作ったほうが楽かもしれないが、環境構築に必要なタスクが多くなってくると、Dockerfileに RUNADD の嵐になりメンテもしにくくなってきてしまう。そんなとき、packerでpuppetなどの構成管理ツールを使ってイメージ化できると大変便利ということがわかった。

  • ちょっと面倒なこと

しかし、packerでは、type: shell で記述したコマンドをDockerfileのようにキャッシュしてくれないため、例えば、yum install ruby 環境を作成するとき・失敗してリトライするときは何度も実行されてしまう。

※ Dockerfileは RUNADD の内容をキャッシュしてくれている。

RUN yum install -y vim がキャッシュされている例

docker build -t test:1 .
Sending build context to Docker daemon  98.82kB
Step 1/2 : FROM centos:7
 ---> 1e1148e4cc2c
Step 2/2 : RUN yum install -y vim
 ---> Using cache
 ---> 57027d76839e

今回は、初回簡単なイメージを作成し、次回以降生成されたイメージを使って、コマンド、manifest_file を追加していくという方法で作成したが、良い感じの作成方法・デバッグ方法があれば教えてください。

Dockerfileとの住み分け

dockerでpull したimageをちょっと変更を加えるくらいで良いケース、例えば、アーキテクチャごとにコンテナを分けて連動して使いたい場合などは、すでに各コンテナ側にミドルウェアが搭載されており、変更する箇所も少ないのでDockerfileで十分かもしれない。

逆にアプリケーション自体をコンテナ化する場合、一つのイメージにアプリケーションに必要なすべてのアーキテクチャを入れることから、ガッツリ手を入れると思うので、そういうときは、packer + 構成管理ツールで行うのが良いかと思った。

参考:

マシン・イメージを自動構築し、作業効率を高めるPacker入門 | Think IT(シンクイット)

Dockerfile の代わりに Packer を使って Docker に再々入門してみている - えいのうにっき

sqlmapを使ってSQLインジェクションの診断をする

気になったので、軽くどういったものなのか自分のローカル環境で試してみました。

sqlmap とは

sqlmapはオープンソースのペネトレーションテスティングツールです。SQLインジェクションの脆弱性の検出、活用、そしてデータベースサーバ奪取のプロセスを自動化します。 強力な検出エンジン、ペネトレーションテスターのための多くのニッチ機能、持続的なデータベースのフィンガープリンティングから、データベースのデータ取得やアウトオブバンド接続を介したオペレーティング・システム上でのコマンド実行、ファイルシステムへのアクセスなどの広範囲に及ぶスイッチを提供します。

SQLインジェクションに特化した脆弱性の診断ツールのようです。

※ 自分の管理外のサーバに使うと攻撃となるので注意が必要です。(絶対しないこと)

インストール

こちらの手順で、インストールできます。

sqlmap/README-ja-JP.md at master · sqlmapproject/sqlmap · GitHub

自分の環境には(Ubuntu 18.04 LTS)、sudo apt install sqlmap で入れることができました。

以下のバージョンが入りました。

sqlmap --version
1.2.4#stable

mac の場合は、brew install sqlmap でも入るそうです。

使い方

-u で検査対象のURLを指定 --data を付けるとリクエストBODYの内容を含めてPOSTします。JSON形式もよしなにやってくれます。

例:

sqlmap -u http://www.example.com/users --data '{"id":2,"name":"taro"}'

その他のオプション

  • --dbms DBMSを指定します。
  • --dump テーブルのデータを取得します。(怖っ)
    • -T --dump で出力するテーブルを指定します。

ローカル環境で、わざと脆弱なコードを追加したりするなど、自分のサービス宛に実行したり試してみましたが、 検出からデータの取得まで一連の機能が備わっており、便利な反面、悪用されるとホントに怖いなという気持ちになりました。

phpcon2018に参加してきた

phpcon2018 に参加してきました。

PHP Conference 2018 - #phpcon2018

以下4セッションを拝聴させていただきました。

ランサーズのCakePHP1.3→Cake2.8移行

スライド: CakePHP1.3 → CakePHP 2.8バージョンアップ - Speaker Deck

PHPCakePHPのバージョンアップに、2,3名体制で、おおよそ2年かかったとのこと。

PHPよりも、フレームワークのバージョンアップのほうが辛そうな印象。

CakePHP1.3 => CakePHP2.8 を同居する(コントローラをindex.phpでスイッチする)作戦は、リソースが取れなくガッとバージョンアップできないかつ平行で開発が進んでいる場合でも、少しずつリリースできるので、よさそうと思った。

ユニットテストが入れられないレガシーなソースでCIが回せるようになった

スライド:

ユニットテストが入れられないレガシーなソースでCIが回せるようになった - Speaker Deck

codeception, Seleniumを使って、受け入れテスト(End-to-Endのテスト)をCIで回すようにしたお話。

Codeception はPHPのテストフレームワークとのことですが、知らなかったので今度調べてみよう。 https://codeception.com/

PHPを検査するPHPを書く

スライド:

PHPを検査するPHPを書く / Write PHP inspection by PHP - Speaker Deck

Linterが内部でどのようにソースコード解析を行っているのか、仕組みの発表だった。 GitHubのコードレビューを自動化できるサービスを作られている Siderさんのお話。

phpは触り始めたのが、最近なのですが、 こういう観点からも学んでいけると良さそうと思った。

PHPバージョンアップと決済テストを支えたユニットテスト

スライド:

PHPバージョンアップと決済リプレイスを支えたユニットテスト #phpcon - Speaker Deck

レガシーコードの改善に積極的に取り組まれているBASEさん レガシーコードの課題としてよくあるのが、 ユニットテストを導入したいがそもそも、そういう構造になっていない。 ということ。 それをどう乗り越えてきたかがわかる発表だった。 ユニットテストがないロールにガッと導入するようなタイミングがあれば、このスライドを改めて見直すようにしよう。

まとめ

PHPカンファレンスは実はSIer時代に一度来ていて、今回2回目なのですが、前回よりも現場の苦労やつらみ(しかし楽しいみたいな)が気持ちがわかる分、色々なことが身に沁みた一日だった。

開発環境のMySQLをdockerで動かすようにしたときのメモ

開発環境では、ローカル(PC)にMySQL使っていたのですが、dockerで動かすようにしました。 そのときのメモを残しておきます。

  • OS: Ubuntu 18.04 LTS
  • 事前準備: docker, docker-compose をインストールしておく

ローカルにインストールしているmysqlを削除する

参考: https://askubuntu.com/questions/172514/how-do-i-uninstall-mysql

sudo apt-get remove --purge 'mysql-server*' 'mysql-common'
sudo rm -r /etc/mysql
sudo rm -r /var/lib/mysql
sudo apt-get autoremove --purge

docker-compose を設定・起動

以下に合わせて、ディレクトリの構成をしておく、できたら、docker-compose up する

version: '3'
services:
  mysql:
    image: mysql:5.7
    volumes:
      - ./etc/mysql/conf.d:/etc/mysql/conf.d
      - ./var/lib/mysql:/var/lib/mysql
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    ports:
      - 3306:3306
  • 今回は、root(パスワードなし)を前提に構築しているが、ユーザ・パスワードを指定したい場合は environment を設定する必要がある。environment の値はこちらを参考にする https://hub.docker.com/_/mysql?tab=description

  • MySQLの設定 /etc/mysql/conf.dmysql.cnf を置くようにし、その中で設定する

MySQLのクライアントをインストール

sudo apt install mysql-client libmysqlclient-dev

mysql clientは localhost を指定するとunix socketで接続しようとするので、

mysql -u root
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
mysql -u root -h localhost
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

vim ~/.my.cnf に以下を設定し、localhostを指定したときはtcpで接続するようにする。 (接続時、明示的に127.0.0.1を設定すれば問題ないので任意)

[client]
protocol=TCP

以上〜

SonarQubeを試してみる

こちらの続きです。

takapi86.hatenablog.com

セキュリティの診断ができる静的解析ツールを探していましたが、前回絞り込みを行った結果以下、3つのツールが残りました。

2018-12-09 現在、それぞれ、以下のような状況でした。

Parse: A PHP Security Scanner

https://github.com/psecio/parse

  • Star: 229
  • 最終更新: 2018-08-02
  • contributors: 7
  • その他

Pixy

https://github.com/oliverklee/pixy

  • Star: 85
  • 最終更新: 2018-01-24
  • contributors: 1
  • その他
    • JUnit が必要らしい

SonarQube

https://github.com/SonarSource/sonarqube

  • Star: 3164
  • 最終更新: 2018-12-04
  • contributors: 75
  • その他
    • phpの他に20種類以上の言語に対応しているらしい
    • 管理サーバを立てる必要があるらしい

SonarQube を試す

パッと見で、3つの内だと SonarQube が良さそうなので試してみる。

以下の方法で試せる

1. webサービスから

https://sonarcloud.io/about/sq

2. HomeBrew から

brew install sonarqube

でいけるらしい。

参考: https://qiita.com/thankkingdom/items/8abb0b329dc575f5b281

3. docker から

Docker Hub に公式のリポジトリがあるので、それを使う

https://hub.docker.com/_/sonarqube/

4. サーバをちゃんと構築

サーバにちゃんと構築するなら、この方法でやる。 https://docs.sonarqube.org/latest/setup/overview/

参考: https://dev.classmethod.jp/ci/sonarqube-source-analytics-1/

dockerで立ち上げる

一番手軽そうな docker を選びました。

今回は docker-compose を使いました。

docker-compose.yml

version: '3'
services:
  sonarqube:
    image: sonarqube:lts
    ports:
      - 9000:9000

これだけ書いて、

docker-compose up

で、ピッとサービスが上がるはずです。

その他、設定などはこちらに書いてあります。 https://hub.docker.com/_/sonarqube/

初期設定

  • ログイン

http://localhost:9000/ へアクセス

id, password は、DockerHubのページに書いてあります。

tokenの生成 と 診断したいプロジェクトの言語を選択するウィザードがでるのでよしなに入力します。

f:id:takapi86:20181210005855p:plain

次の画面のリンク先から SonarQube Scanner というソースコードの解析を行い、サーバに結果を通知するツールをダウンロードします。そして、パスの通ったディレクトリから呼び出せるように設定します。

次に、Execute the SonarQube Scanner from your computer の欄にあるコマンドを、静的解析したいコードのあるディレクトリで実行します。(なければ、ウィザード画面上部にある Skip Tutorial を押します。)

f:id:takapi86:20181210005950p:plain

Administration -> Marketplace から、phpの解析プラグインSonarPHP)を更新します。

f:id:takapi86:20181210010059p:plain

Update to XXX の部分が Update Pending になったら、画面上部に出てくる Restart ボタンを押し再起動します。

静的解析してみる

手元に静的解析したい良い感じのPHPのコードが無かったので、GETのパラメータの値を直接 shell_exec コマンドに入れてみたり、SQL文に入れてみたり(PreparedStatementなし)ないかにもヤバそうなコードを書いてテストしてみました。

先程チュートリアルで実行したものと同じコマンドを実行しました。

結果

1件

Define a constant instead of duplicating this literal "hoge_id" 3 times.

コードの内部で $_GET['hoge_id'] を3回つかっていたのですが、そこだけ怒られました。 もう少し怒ってくれることを期待していたのですが。

rulesを確認する

セキュリティに関する rules は以下、合わせて28でした。

https://rules.sonarsource.com/php/type/Vulnerability https://rules.sonarsource.com/php/type/Security%20Hotspot

これは一般的にみて、多いのか少ないのか比較していないのでわかりませんが、とりあえず今日はここまで

PHPのソースコードから脆弱性をチェックするツールの洗い出しを行ってみた

なぜか唐突にPHPソースコードから良い感じに脆弱性を検出できるようなツールがないか調べたくなったので、軽く調査しました。 ひとまず、どんなものがあるか洗い出しまで。

やりたいこと

  • タイトルの通り、PHPソースコードから脆弱性を検出できるようにしたい。
  • 最終的には、CIなどで継続的に検出しコード修正時に把握できるようにしたい。
  • ついでに、品質チェックもできれば、なおgood。
  • 有償のツールが多いが、ひとまず継続的に脆弱性を検出できるようにしたいと思っているので、最初は無償/OSSのツールを導入してみる。

選定するツールのイメージ

ずばりこれのPHP版のようなもののイメージ

https://blog.ohgaki.net/security-check-tool-for-rails-brakeman

インターネットを使って洗い出してみる

ちょっと古そうなものもあるが、このあたりを参考にしてみる

参考:

https://www.ipa.go.jp/security/technicalwatch/20140306.html http://algo13.net/php/tips/security-check.html http://kiban.nict.go.jp/annual_report/report/report20/20-20-03.pdf https://www.sonarqube.org/ https://blog.ohgaki.net/php-script-analyzers

・・・いっぱいある。

このうち、以下は除外

RIPS

  • OSS版(RIPS 0.55)は開発終了
  • また、OSS版はPHP 3, 4しかサポートしていない

PHP-Sat

  • 安定版なし、更新されていない

phpvulhunter

  • 更新が4年前から止まっている
  • ドキュメントが中国語で読めない

VisualCodeGrepper, Eir

  • 使用言語が、VB, C#ということで、Windows環境でないとダメそう

PHP-Reaper, Side Channel Analyzer, XSS code sniffer

  • 一部の脆弱性に特化したツールなので、今回の選定基準とは異なる

TaintPHP, RATS(Rought Auditing Tool for Security

  • あまり活発ではない様子

今日はここまで、何かおすすめのツールがあれば教えてください。