astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

Play Framework 2.6でFilterに触れてみる

f:id:astamuse:20170815181256p:plain

こんにちは、開発部のyanagita@リモートワーク中です。
宮崎はだんだん暖かくなり、もうすこしで桜が咲き出しそうな雰囲気が漂ってます。
桜といえば春、春といえば出会いの季節です。
アスタミューゼでは多くの方との出会いを心待ちにしています。

前回は弊社のWeb Framework asta4dのscala対応について書きましたが、今回は元に戻ってPlay Frameworkに関する事でFilterについて書きたいと思います。

前提

今回もPlay Framework 2.6のScala版で説明します。Javaの方はJavaに読み替えて頂ければとm(_ _)m

Play Frameworkの標準Filterと設定

Play Framework 2.6では前バージョンの2.5から新しいFilterが一つ追加になり、5つのFilter機能が標準で使用可能になっています。

  1. Gzip encoding filter
  2. Security headers filter
  3. CORS filter
  4. CSRF filter
  5. Allowed hosts filter
  6. Redirect HTTPS filter ← 2.6から追加

このうち、Security header filter、CSRF filter、AllowedHostFilterはデフォルトで適用されるFilterになります。
もし、残りのFilterも適用したい場合はapplication.confにFilterの追加定義を行います。

# conf/application.conf
# Gzip filterを追加する例
play.filters.enabled += "play.filters.gzip.GzipFilter"

逆にFilterを外す場合

# conf/application.conf
#CORS filterを削除する例
play.filters.disabled += "play.filters.csrf.CSRFFilter"

次に各Filterのについて触れます。

Gzip encoding filter

Gzip encoding filterは、レスポンスデータのgzip圧縮をサポートするFilterです。
詳細な設定はapplication.confで行います。

# conf/application.conf
play.filters.gzip.contentType {

    # Gzip圧縮を行なうContent-Typeを設定(デフォルト値:空)
    whiteList = [ "text/*", "application/javascript", "application/json" ]

    # Gzip圧縮を行わないContent-Typeを設定(デフォルト値:空)
    blackList = []
}

whiteList、blackListが共に空の場合、全レスポンスがgzip圧縮の対象となります。
whiteListのみ設定した場合、設定したContent-Typeのレスポンスのみがgzip圧縮の対象となります。
blackListのみ設定した場合、設定したContent-Type以外のレスポンスがgzip圧縮の対象となります。 whiteList、blackList共に設定した場合、whiteListが優先されblackListは適用されないのでご注意下さい。

Security headers filter

セキュリティに関するHeaderパラメータを自動設定します。
各セキュリティパラメータの設定は下記の通りです。

# conf/application.conf
play.filters.headers {

    # X-Frame-Options設定。nullの場合は指定なし(デフォルト値:"DENY")
    frameOptions = "DENY"

    # X-XSS-Protection設定。nullの場合は指定なし(デフォルト値:"1; mode=block")
    xssProtection = "1; mode=block"

    # X-Content-Type-Options設定。nullの場合は指定なし(デフォルト値:"nosniff")
    contentTypeOptions = "nosniff"

    # X-Permitted-Cross-Domain-Policies設定。nullの場合は指定なし(デフォルト値:"master-only")
    permittedCrossDomainPolicies = "master-only"

    # Content-Security-Policy設定。nullの場合は指定なし(デフォルト値:"default-src 'self")
    contentSecurityPolicy = "default-src 'self'"

    # Referrer-Policy設定。nullの場合は指定なし(デフォルト値:"origin-when-cross-origin, strict-origin-when-cross-origin")
    referrerPolicy = "origin-when-cross-origin, strict-origin-when-cross-origin"
}

CORS filter

CORS(Cross-Origin Resource Sharing)は、ドメインの異なるWebアプリケーション間のリクエスト制御設定を行います。
こちらもapplication.confで設定を行います。

# conf/application.conf
play.filters.cors {

    # CORSを適用するルートパス(デフォルト値:/)
    pathPrefixes = ["/"]

    # アクセス許可するドメイン。nullの場合は制限無し(デフォルト値:null)
    # 指定する場合は、["astamuse.com", ...]
    allowedOrigins = null

    # preflightリクエストで許可するメソッド。nullの場合は制限なし(デフォルト値:null)
    # 指定する場合は、["GET", "POST"]
    allowedHttpMethods = null

    # preflightリクエストで許可するHttpヘッダ。nullの場合は制限なし(デフォルト値:null)
    # 指定する場合は、["Accept"]
    allowedHttpHeaders = null

    # 許可する独自のHttpヘッダ。nullの場合は制限なし(デフォルト値:null)
    exposedHeaders = []

    # Credentials情報の使用の有無(デフォルト値:true)
    supportsCredentials = true

    # CORSメタデータのキャッシュ有効期間(デフォルト値:1 hour)
    # 設定値はduration
    preflightMaxAge = 1 hour

    # pathPrefixesに該当しないパスへのアクセス許可有無(デフォルト値:false)
    serveForbiddenOrigins = false
  }

CSRF filter

CSRF (cross-site request forgeries) は、 2.6からデフォルトFilterに追加されたので2.5以前から移行される場合は対応が必要になります。
CSRFのチェックはForm内にtoken情報を含む必要があります。一般的なtoken情報の設定方法は下記の2パータンがあります。

  • action属性のパスにtoken情報を付加するケース

template.scala.html

@import helper._

@form(CSRF(routes.SampleController.index())) {
    ...
}

HTML

<form method="POST" action="/index?csrfToken=1234567890abcdef">
   ...
</form>

 
* formタグ内にパラメータを付加するケース

template.scala.html

@import helper._

@form(routes.SampleController.index()) {
   @CSRF.formField
    ...
}

HTML

<form method="POST" action="/index">
  <input type="hidden" name="csrfToken" value="1234567890abcdef"/>
   ...
</form>

Allowed hosts filter

有効host以外からのアクセスを遮断するFilterです。遮断時はHTTP codeは400を返します。
有効hostの設定もapplication.confで行います。

# conf/application.conf
play.filters.hosts {
    # 有効なホスト名を設定(デフォルト値:localhost, .local)
    allowed = ["localhost", ".local"]
  }

Allowed hosts filterはデフォルト設定のFilterになります。confファイルを環境別に用意している場合に、有効hostの設定が漏れていると環境を変えた時にアクセスできない問題が発生するので注意が必要です。
開発中などホスト制限を行わない場合は、"."を設定することでホスト制限なくアクセスできます。
サブドメインも含めてた制限を行なう場合は、"." + ホスト名で行えます。
(".astamuse.com"と設定した場合、"astamuse.com"、"sub.astamuse.com"が該当します。)
ポートが変更されている場合は、ポート番号を含んで設定します。
(localhostで8080ポートの場合、"localhost:8080")

Redirect HTTPS filter

httpでのアクセスをhttpsにリダイレクトするFilterです。リダイレクト時のHTTP codeはデフォルトで308になります。
308であればリダイレクト時のリクエストメソッドが変更されないので予期しないリクエストケースはなくなりますが古いブラウザでは動かない欠点があります。
別のcodeへの変更は下記の通り設定します。

# conf/application.conf(デフォルト値:308)
play.filters.https.redirectStatusCode = 301

さいごに

至れり尽くせりのFilterが揃ってます。
Play Frameworkに触れた際にはFilterにも是非触ってみて下さい。

アスタミューゼではまだまだエンジニア&デザイナを募集しています。
気になる方は下からご応募下さい!新しい出会いをメンバー一同お待ちしてます!

特許とその制度について 拒絶査定後または特許登録後

お久しぶりです。主に特許関連のデータ処理を担当しているBTと申します。
今回は拒絶査定後または特許登録後の流れについてご説明したいと思います。
宜しくお願いいたします。

拒絶査定後

特許出願が審査によって拒絶査定された場合、出願人そこで諦める必要はありません。
出願人は拒絶査定について納得がいかない場合は、特許庁に対して拒絶査定不服審判を請求することが出来ます。
また、この拒絶査定不服審判の請求と同時に出願内容を補正する事も可能で、この場合は拒絶査定不服審判の前に前置審査が行われます。

前置審査

拒絶査定不服審判の請求と同時に出願内容の補正が有る場合、これが実質上出願人にとって最後の補正のチャンスであることから拒絶査定において指摘された拒絶理由に全てについて、その拒絶理由を解消するような大幅な補正を行うことが多くなります。
このため、わざわざ拒絶査定不服審判を行うよりも、すでに審査の過程で内容を理解しているはずの拒絶査定をした審査官が、拒絶査定不服審判を請求と共にした補正内容を確認することで拒絶理由が全て解消しているか否かの判断が容易に可能です。
そこで、拒絶査定不服審判を請求と共に補正があった場合は、拒絶査定をした審査官に補正内容を確認させ、特許査定が可能かどうかの判断をします。これを前置審査と言います。
拒絶査定をした審査官が補正後の出願内容で特許査定が可能と判断した場合は、拒絶査定不服審判を行うこと無く出願人に対して特許査定を通知します。

拒絶査定不服審判

拒絶査定不服審判の請求と同時に出願内容の補正が無い場合、又は補正があっても前置審査の結果拒絶査定をした審査官が特許査定は出来ない(拒絶査定における拒絶理由が解消していないか、補正によって新たな拒絶理由が生じた場合)と判断した場合は、拒絶査定不服審判が開かれます。
拒絶査定不服審判は、3人ないしは5人の審判官(審査官を長年勤めたベテランの特許庁職員の方々)の合議で、拒絶査定をした審査に誤りは無いか、拒絶査定不服審判を請求と共に補正があった場合はその補正後の内容で特許査定が可能か等を判断します。
審判官の判断の結果、主に審決(成立)、審決(不成立)、審査に差し戻しのいずれかの結果が出されます。
審決(成立)の場合は、特許査定と同じですので、出願人は特許登録料と3年分の年金を納めることで特許権を取得できます。
審決(不成立)の場合は、知的財産高等裁判所(東京高等裁判所の特別の支部で、知的財産権に関する裁判を専門的に受け持つ裁判所)に出訴することにより、出願人は裁判で争うことも可能です。
審査に差し戻しの場合は、審査が再度やり直しになります。これは審査の内容に不備や間違いがあった場合にそれを審査のやり直しで正すためですが、審判官が審査官を教育する目的で行われることもあり、出願人にとっては特許になった場合の特許権の有効期間がさらに減ってしまうことになります。

特許登録後

特許出願が審査によって特許査定された後に、出願人は特許登録料と3年分の年金を納めることで特許権を取得できます。
しかし、特許権は一度取得すれば出願から最大20年の間ずっと安泰というわけではありません。最初の3年間を除いてその後の毎年の年金を納め忘れると特許権は消滅しますし、競合者等の請求により特許権が消滅する事もあります。 それらを見ていきます。

特許異議の申し立て

特許登録がなされて特許公報が発行されてから6ヶ月の間は、誰でも自由にその特許登録された内容について異議申し立てをすることが出来ます。
6ヶ月の間に異議が申し立てられた(複数の場合も有り)場合、3人ないしは5人の審判官により異議申し立ての審理及び決定が行われます(異なる複数の異議申し立ての異議の内容が同じだったりすることもあるので、整理分類して同一内容の異議申し立て毎に行われる)。
異議申し立てを認める場合は、その特許は消滅し、特許権は最初から存在しなかったものと見なされます。
異議申し立ても認めない場合は、その特許はそのまま維持されます。

訂正審判

すでに登録された特許について、その特許権者は特許の内容について何らかの不備や後で説明する特許無効審判によって特許を無効にされる可能性が高い場合、特許権者はすでに登録済みの特許の内容について訂正を行う訂正審判を特許庁に要求することが出来ます。
上記の特許異議申して立てで申し立てたれた内容について特許の内容について訂正が必要と特許権者が判断した場合も同様です。
訂正審判は、3人ないしは5人の審判官により審理されて、審決(成立)となった場合は特許の内容は訂正後のものに変わります。但し、訂正後の内容は訂正前の特許の内容を超えるものであってはなりません。

特許無効審判

登録された特許に対して、利害関係者等がその特許がで無効であることを確認するために、特許庁に対して特許無効審判を請求することが出来ます。
無効となる理由は、審査等の過程で拒絶すべき事情があったにもかかわらず特許となった場合等が多いです。
特許無効審判は、3人ないしは5人の審判官により審理及び決定が行われます。
審決(成立)の場合は、その特許は無効となり、特許権は最初から存在しなかったものと見なされます。
審決(不成立)の場合は、その特許はそのまま維持されます。
どちらの場合でも、審決の結果に不服がある場合は、知的財産高等裁判所(東京高等裁判所の特別の支部で、知的財産権に関する裁判を専門的に受け持つ裁判所)に出訴することにより、特許権者と特許無効審判の請求人は裁判で争うことも可能です。

その他の裁判

特許権者はその特許発明について、原則その発明を実施する権利を独占的に有していますが、他人にまねされることもあります。
このような場合は、その他人に対して東京地方裁判所または大阪地方裁判所に対して特許侵害訴訟を提訴することが出来ます。
また、その他人の行為によって損害が生じている場合は、同じく東京地方裁判所または大阪地方裁判所に対して損害賠償請求を提訴することが出来ます。

まとめ

以上、拒絶査定後または特許登録後について説明をしてきました。
今回で「特許とその制度について」の一連のシリーズは終了となります。
長い間有難うございました。

最後になりましたが、 アスタミューゼでは現在、エンジニア・デザイナーを募集中です。 興味のある方はぜひ 採用サイト からご応募ください。

参考にした資料など

Linuxでinodeが枯渇した場合にどうやって調査するか

f:id:astamuse:20180314195322j:plain

こんにちは。並河(@namikawa)です。

最近はすっかり暖かい日が続いておりまして、花粉が飛散して本当に悲惨な感じになってしまっているアカウントがこちらになります。

さて、近頃は、GCPへの移行を終えたり、新しいメンバーが続々とジョインしてきてくれていることもあり、本業のインフラ職人業が随分と減ってきていて、やっぱり最近力を入れている採用の話を書こうかなと思ったのですが、そういえば前回は採用向けの話(アスタミューゼの開発組織と採用に関するQAアレコレ)を書いたところだったので、今日はLinux運用環境での小ネタでも書こうかと思います。

「なぜかサーバに書き込めません!」

ある日、とあるサーバのディスク関連のアラートが飛んできて、エンジニアがサーバの状況を確認したところ、ディスクの容量には空きがあるが、なぜか書き込めないという状態になっていました。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       9.9G  5.5G  3.9G  59% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
udev            286M  8.0K  286M   1% /dev
tmpfs            59M  348K   59M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            295M     0  295M   0% /run/shm
none            100M     0  100M   0% /run/user

dfコマンドでディスクの使用量を確認するも空き容量はまだ残っている感じ。 エラーを確認すると "No space left on device" とな。

# df -i
Filesystem     Inodes  IUsed IFree IUse% Mounted on
/dev/sda1      655360 654754   606  100% /
none            75426      2 75424    1% /sys/fs/cgroup
udev            72973    405 72568    1% /dev
tmpfs           75426    327 75099    1% /run
none            75426      3 75423    1% /run/lock
none            75426      1 75425    1% /run/shm
none            75426      4 75422    1% /run/user

というわけで、定番の inode 枯渇問題でありました。

たくさんのファイルがどこにあるのかを探す

やり方は色々あるかと思うのですが、地道にルートからたくさんあるディレクトリを探していきます。 地味なやり方ですが、まずは1階層目のレベルで、どこの配下に大量のファイルがあるか探索します。

# find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -nr
 489278 usr
  14308 lib
   3287 var
   1818 data
    826 etc
    293 boot
    130 sbin
    128 bin
     94 home
      5 root
      3 tmp
      1 swap

こんな感じで、"/usr"配下のどこかにたくさんファイルが存在していることがわかりました。 あとは同じ要領で機械的に2階層目・・・と探していけばよいです。

# find /usr -xdev -type f | cut -d "/" -f 3 | sort | uniq -c | sort -nr
 460742 src
  15060 share
  12806 lib
    544 bin
    121 sbin
      5 include

"/usr"配下を対象に2階層目を探索した結果がこちら。"/usr/src"にたくさん溢れている、、、というところでピンときますね。

# ll /usr/src
total 188
drwxr-xr-x 47 root root 4096 Dec 15 06:45 ./
drwxr-xr-x 10 root root 4096 Nov 14  2015 ../
drwxr-xr-x 24 root root 4096 Jul 15  2016 linux-headers-3.16.0-77/
drwxr-xr-x  7 root root 4096 Jul 15  2016 linux-headers-3.16.0-77-generic/
drwxr-xr-x 27 root root 4096 Nov 21 06:33 linux-headers-4.4.0-101/
drwxr-xr-x  7 root root 4096 Nov 21 06:33 linux-headers-4.4.0-101-generic/
drwxr-xr-x 27 root root 4096 Dec  8 06:50 linux-headers-4.4.0-103/
drwxr-xr-x  7 root root 4096 Dec  8 06:50 linux-headers-4.4.0-103-generic/
drwxr-xr-x  7 root root 4096 Dec 15 06:45 linux-headers-4.4.0-104-generic/
drwxr-xr-x 27 root root 4096 Feb 23  2017 linux-headers-4.4.0-64/
drwxr-xr-x  7 root root 4096 Feb 23  2017 linux-headers-4.4.0-64-generic/
drwxr-xr-x 27 root root 4096 Mar  9  2017 linux-headers-4.4.0-66/
drwxr-xr-x  7 root root 4096 Mar  9  2017 linux-headers-4.4.0-66-generic/
drwxr-xr-x 27 root root 4096 Mar 16  2017 linux-headers-4.4.0-67/
drwxr-xr-x  7 root root 4096 Mar 16  2017 linux-headers-4.4.0-67-generic/
drwxr-xr-x 27 root root 4096 Mar 28  2017 linux-headers-4.4.0-70/
drwxr-xr-x  7 root root 4096 Mar 28  2017 linux-headers-4.4.0-70-generic/
drwxr-xr-x 27 root root 4096 Mar 31  2017 linux-headers-4.4.0-71/
drwxr-xr-x  7 root root 4096 Mar 31  2017 linux-headers-4.4.0-71-generic/
drwxr-xr-x 27 root root 4096 Apr  5  2017 linux-headers-4.4.0-72/
drwxr-xr-x  7 root root 4096 Apr  5  2017 linux-headers-4.4.0-72-generic/
drwxr-xr-x 27 root root 4096 Apr 25  2017 linux-headers-4.4.0-75/
drwxr-xr-x  7 root root 4096 Apr 25  2017 linux-headers-4.4.0-75-generic/
drwxr-xr-x 27 root root 4096 May 18  2017 linux-headers-4.4.0-78/
drwxr-xr-x  7 root root 4096 May 18  2017 linux-headers-4.4.0-78-generic/
drwxr-xr-x 27 root root 4096 Jun  7  2017 linux-headers-4.4.0-79/
drwxr-xr-x  7 root root 4096 Jun  7  2017 linux-headers-4.4.0-79-generic/
drwxr-xr-x 27 root root 4096 Jun 20  2017 linux-headers-4.4.0-81/
drwxr-xr-x  7 root root 4096 Jun 20  2017 linux-headers-4.4.0-81-generic/
drwxr-xr-x 27 root root 4096 Jun 29  2017 linux-headers-4.4.0-83/
drwxr-xr-x  7 root root 4096 Jun 29  2017 linux-headers-4.4.0-83-generic/
drwxr-xr-x 27 root root 4096 Jul 25 06:41 linux-headers-4.4.0-87/
drwxr-xr-x  7 root root 4096 Jul 25 06:41 linux-headers-4.4.0-87-generic/
drwxr-xr-x 27 root root 4096 Aug  4 06:32 linux-headers-4.4.0-89/
drwxr-xr-x  7 root root 4096 Aug  4 06:32 linux-headers-4.4.0-89-generic/
drwxr-xr-x 27 root root 4096 Aug 12 06:55 linux-headers-4.4.0-91/
drwxr-xr-x  7 root root 4096 Aug 12 06:55 linux-headers-4.4.0-91-generic/
drwxr-xr-x 27 root root 4096 Aug 16 06:35 linux-headers-4.4.0-92/
drwxr-xr-x  7 root root 4096 Aug 16 06:35 linux-headers-4.4.0-92-generic/
drwxr-xr-x 27 root root 4096 Aug 29 06:34 linux-headers-4.4.0-93/
drwxr-xr-x  7 root root 4096 Aug 29 06:34 linux-headers-4.4.0-93-generic/
drwxr-xr-x 27 root root 4096 Sep 19 06:32 linux-headers-4.4.0-96/
drwxr-xr-x  7 root root 4096 Sep 19 06:32 linux-headers-4.4.0-96-generic/
drwxr-xr-x 27 root root 4096 Oct 11 06:49 linux-headers-4.4.0-97/
drwxr-xr-x  7 root root 4096 Oct 11 06:49 linux-headers-4.4.0-97-generic/
drwxr-xr-x 27 root root 4096 Oct 31 06:39 linux-headers-4.4.0-98/
drwxr-xr-x  7 root root 4096 Oct 31 06:39 linux-headers-4.4.0-98-generic/

はい、このサーバはセキュリティ関連の自動アップデートが動いているサーバでしたね・・・。

ということで、不要なパッケージを apt-get purge 等で綺麗にしたのでした。

おわりに

弊社には大量のデータがあるので、本当はファイルがたくさんあって大変、みたいな話に無理やり結びつけようとも思ったのですが、そもそも基本的には各種データストアに入れているし、Rawデータの置き場はGCSのお世話になっているので、inodeに影響を及ぼす様なことは基本的にはありません。

ということで、割とありきたりなネタで恐縮でしたが、何かのお役に立てれば幸いです。

最後に、弊社ではエンジニア・デザイナーを絶賛大募集しておりますので、少しでも気になれば、カジュアルにランチでもしながらお話ししましょう。疑問・質問などございましたら、お手数ですが (@namikawa) まで気軽にDM等いただければと思います。

それでは!=͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́

Copyright © astamuse company, ltd. all rights reserved.