RestrictedPython。

RedashやPloneで使われているRestrictedPython。使う機会あったのでまとめる。

とりわけ、自前RestrictionTransformerクラスによるpolicyの設定方法は情報がネット上に皆無だったので、残しておけれればと思う次第。

...諸兄姉においては、RestrictedPythonさらにはexec、evalを使わざるおえない局面が来ないことを祈る(セキュリティ観点で)

環境

RestrictedPython

概要

Pythonソースコード文字列の実行時評価(e.g. exec、eval)する際に、評価するコードに制約(e.g. for statementの禁止)をかけるためのライブラリ。

CPython 2.7、3.4、3.5、3.6がサポートされている。PyPyをはじめとしたCPython以外のPython処理系は、サポート外。*1

注意点・観点

第一に、exec、evalは使うのは避けるのがよい。

理由としては、安全性・セキュリティの観点から、そもそもexec、evalは使うのは避けるるべきである。

避ける方法としては、VMを実装するのが一つ。
それ以外にも、ast.literal_eval使う方法や、別プロセスやコンテナの中など、限定された環境で評価を行うのがよい。

もし、言語ランタイムがサンボドックス実行の手段を提供してくれているのであれば、検討すること。

たとえば、言語ランタイムが提供するサンドボックスで知っている限りだと、Javaアプレット時代のサンドボックスや、PyPyが実験的に実装したサンドボックス*2

インストール

pip install RestrictedPython

今回は、4.0βで試した。

pip install RestrictedPython==4.0b4

from RestrictedPython import compile_restricted

source_code = """                                                               
def add(x):                                                                     
  return x + 1                                                                  
"""

context = {}
try:
    byte_code = compile_restricted(source_code, '<inline>', 'exec')
    exec(byte_code, None, context)
except SyntaxError as e:
    raise e
assert 2 == context['add'](1)

制約をかける

文・式の制約を加えたい。
RestrictedPythonではPolicyという概念があり、事前定義された組み込み関数が3つ(safe_builtins、limited_builtins、utility_builtins)を使うことで制約をかけられる。

safe_builtinsを使う

execの第二引数のdictで__buildins__にsafe_builtinsを設定する。

from RestrictedPython import compile_restricted
from RestrictedPython import safe_builtins

source_code = """                                                               
def add(x):                                                                     
  return x + 1                                                                  
"""

context = {}
try:
    byte_code = compile_restricted(source_code, '<inline>', 'exec')
    exec(byte_code, {'__builtins__': safe_builtins}, context)
except SyntaxError as e:
    raise e
assert 2 == context['add'](1)
safe_builtinsで制約がかけられているimport文を呼び出す

さて、safe_builtinsでは、import文が禁止されている。
試してみよう。

from RestrictedPython import compile_restricted
from RestrictedPython import safe_builtins

source_code = "import this"

context = {}
try:
    byte_code = compile_restricted(source_code, '<inline>', 'exec')
    exec(byte_code, {'__builtins__': safe_builtins}, context)
except SyntaxError as e:
    raise e

上記を実行した際はImportErrorが排出される。

ImportError: __import__ not found
本題。Policyに自前のRestrictingNodeTransformerを指定し制約をかける

RestrictedPythonの提供するcompile関数群(compile_restricted、compile_restricted_exec、compile_restricted_eval、compile_restricted_single)は、policyにRestrictingNodeTransformerを指定できる。

RestrictedPythonはRestrectedPytohnが提供している。親クラスは、標準モジュールastが提供するast.NodeTransformer。このクラスを継承して、自前のクラスを作ることによって制約をかけることができる。

例えば、import文を自前のOwnRestrictingNodeTransformerクラスで禁止したい場合は下記。

from RestrictedPython import compile_restricted
from RestrictedPython import RestrictingNodeTransformer

class OwnRestrictingNodeTransformer(RestrictingNodeTransformer):
    def visit_Import(self, node):
        self.error(node, 'Import statements are not allowed.')
    visit_ImportFrom = visit_Import

source_code = "import this"

try:
    byte_code = compile_restricted(
        source=source_code,
        filename='<inline>',
        mode='exec',
        policy=OwnRestrictingNodeTransformer)
    exec(byte_code)
except SyntaxError as e:
    raise e

実行すると下記となる。

SyntaxError: ('Line 1: Import statements are not allowed.',)

この要領で文、式の制約をかければいい。むろん特定のモジュールがインポートされた場合に対してだってなんだってやりたい放題。Pythonのビルドインライブラリast様様。

私感

astモジュール駆使して、制約かけるのはgoodではあるが...やはりそもそも論として、RestrictedPythonさらにはexec、evalを使わざるおえない局面が来ないことを祈る(セキュリティ観点で)

それるが、RestrictedPythonは、Zope Foundationが提供している。個人的な推測だが、Ploneで使う前提で作られ、ライブラリとして切り出されたと思われる。

Pythonを使ってるとZopeは避けられない。

*1:ソースコードぱっと見た限りはPyPyのサポートを頑張っている痕跡はある

*2:PyPy’s sandboxing features — PyPy documentation。現状使える状態なのかは不明。

macのセットアップ

連れ添った先代mac book airが不慮の事故で、使用不可となったので、新たなmac book airをセットアップ。

mac book air

- macOS Sierra 10.12.4
- MacBook Air (13-inch, Early 2015)
- 1.6 GHz Intel Core i5
- 8 GB 1600 MHz DDR3

インストールしたソフトウェア

- Chrome
- Google IME
- Slack(from App store
- XCode(from App store)
- Python 3.6.5
- g01.10.12(from go1.10.2.darwin-amd64.pkg )
- Steam

設定

ダッシュボードの不要ショートカットを全削除

IME

標準のIMEはoff。

キーボード/ショートカット

control + ↑↓←→はすべて外す。emacsとバッティングするため。

ssh key

ssh-keygenしなおした。

ターミナル

Proが好き。ちょっとフォントサイズ大きくして保存。

brew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

OpenSSL

brew install openssl

Python3

curl -O https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz
tar zxf Python-3.6.5.tgz 
cd Python-3.6.5
vi Modules/Setup

Modules/Setup修正前

#SSL=/usr/local/ssl
#_ssl _ssl.c \
#        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
#        -L$(SSL)/lib -lssl -lcrypto

Modules/Setup修正後

SSL=/usr/local/Cellar/openssl/1.0.2o_1
_ssl _ssl.c \
        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
        -L$(SSL)/lib -lssl -lcrypto

./configure & make & make install

./configure --prefix=/path/to/bin/Python-3.6.5 --with-ssl
make
make install

venv & virtualenvwrapperの設定

デフォルトPython3系にしてしまう。

/path/to/bin/Python-3.6.5/bin/python3 -mvenv ~/.virtualenv/python3.6.5
source ~/.virtualenv/python3.6.5/bin/activate

.bash_profile

export WORKON_HOME=~/.virtualenv
export VENV=python3.6.5
source $WORKON_HOME/$VENV/bin/activate
source $WORKON_HOME/$VENV/bin/virtualenvwrapper.sh

GNU Emacs

emacsはひとまず、ビルドインので我慢できる...と思ってバージョン確認したらemacs22.11.1...流石に24以降使いたいから、インストール。

手抜きしてbrewで入れる。

brew install emacs --with-cocoa

.bash_profile以下を追加

export PATH=$PATH:/usr/local/Cellar/emacs/25.3/bin/
alias  emacs='emacs -nw'

その他

- ただの個人的な習慣だが、~/wok/以下に原則置く(例えばPythonは~/work/bin/Python3.6.5)。一部.dotfiesは~/以下はやむを得ない
- 話それるが、連れ添った携帯も移行しないとならない局面に

直近読んだ技術書籍

更新が滞っていたので一括で。

エキスパートPythonプログラミング改訂2版

改訂2版が出版されたので、読了。
Python3の時代になったんんだなぁ。と思う次第。
C/C++による拡張や、散らばって述べられる処理系の話は興味あるだけに楽しかった。

仕事ではじめる機械学習

基礎教養として読了。

みんなのGo言語【現場で使える実践テクニック】

Goになれるために読了。
ツール、文化を学んだ点が大きい。

プログラミング言語Go

Goの公式こなしたあとに読了。きっちりまとまっている良著。
言語の文法、基本的なライブラリを学ぶって意味だとこの書籍一冊で良さそう。

プロフェッショナルSSL/TLS

特に公開鍵ピンニングを学ぶ必要があったので、その周辺に絞って、部分的に読了。

ユビキタス時代の著作権管理技術―DRMとコンテンツ流通

DRM、コンテンツの秘匿、管理技術を学ぶ必要があったので、読了。
2006年出版と若干古い書籍では有るが、大系だって学べる良著。

画像電子学会が電子透かし関連の書籍を出版していることを知る。

ビットコインはどのようにして動いているのか?

基礎教養を得る意味で読了。

暗号技術のすべて

暗号技術に関する書籍でよいとの評判を聞
き、基礎教養を得る意味で読了。

プログラミングMICROSOFT ASP.NET MVC

dot net/dot net coreを触る機会があったので、技術習得のために。
msdn最強なのは否めない。

プログラミング MICROSOFT ASP.NET4

同上。

Learning NGUI for Unity

UnityのNGUIを学ぶ必要あったので、キャッチアップ目的で。流し読み。
なかなかNGUIに特化した情報リソースないので助かる。

NGUI for Unity

同上。

改訂3版 パーフェクトC#

C#を大系だって書籍使って学びたかったので、読了。

Learn Pixi.js

Pixi.jsチュートリアルこなし終わったので、購入した。
実際にはPixi.jsLearning Pixi を元に加筆、修正して出版されているので、
Learning Pixi以上に得れたものがあったかといえば、微妙。

Game Programming Patterns ソフトウェア開発の問題解決メニュー

かなりおすすめ。ゲームプログラミングでよく使わせるパターンがきれいにまとめられている。
実際にgameのメインループや、コマンドパターン、VM実装はかなり楽しかった。

一覧

エキスパートPythonプログラミング改訂2版

エキスパートPythonプログラミング改訂2版

仕事ではじめる機械学習

仕事ではじめる機械学習

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プロフェッショナルSSL/TLS

プロフェッショナルSSL/TLS

ユビキタス時代の著作権管理技術―DRMとコンテンツ流通

ユビキタス時代の著作権管理技術―DRMとコンテンツ流通

暗号技術のすべて

暗号技術のすべて

プログラミングMICROSOFT ASP.NET MVC (Microsoft Press)

プログラミングMICROSOFT ASP.NET MVC (Microsoft Press)

プログラミング MICROSOFT ASP.NET4 (Microsoft Press)

プログラミング MICROSOFT ASP.NET4 (Microsoft Press)

Learning NGUI for Unity

Learning NGUI for Unity

NGUI for Unity

NGUI for Unity

改訂3版 パーフェクトC# (PERFECT SERIES 1)

改訂3版 パーフェクトC# (PERFECT SERIES 1)

Learn Pixi.js

Learn Pixi.js

Game Programming Patterns ソフトウェア開発の問題解決メニュー (impress top gear)

Game Programming Patterns ソフトウェア開発の問題解決メニュー (impress top gear)

所感

時間経った後に一括でまとめるのは、だめだ。だめな理由は、

  1. 一冊一冊に対する書評や、行ったことのまとめの質が極めて低下
  2. そもそも何冊も抜け漏れがある
  3. 以上の結果から、行動履歴残すために記事化しているという目的を持っているのだけど、満たせてない。これは書評とは言えない。

よって、

  1. 小分け、一冊一冊に注力し記事にまとめる

例えば、下記ぐらいの密度でかければ満足。
e.g. http://rokujyouhitoma.hatenablog.com/entry/20120512/1336824901


放送大学の2017下期の受講候補

下期の受付けが始まるので、受講候補を整理。

所感

さて、時間は有限(予算もまた...)なので、どれを優先しようか。いくつ選択しようか。

UnityとGodot。とりわけUnity C#とGodot GDScriptまたはC++

こんばんわ、ゲームプログラマー3年生のrokujyouhitomaです。リアルタイムレンダリング周りは未修と言っていいほどなのが大きな課題です。

Godot調査二日目で気になる点があったので、ざっくりした考察だけど、一度脳内から忘れたいので書き出しちゃいます。

UnityとGodot

Godotプロジェクトが、同じゲームエンジンであるUnityと機能を比較しつつ、Godotの機能を紹介しているドキュメントがあります。

目を通して思うところを書き残すなど。

シーンシステム

Unityでもシーンの合成を行うけどなぁと思いました。まさにドキュメントで述べられてるGodotの使い方の通りに。
具体的には、SceneManager.LoadScene APIを使って。

SceneManager.LoadScene

スクリプティング

スクリプト数について

  • Godotだと、1Nodeに1Scriptしかアタッチできない
  • Unityだと、1Nodeに複数Scriptをアタッチできる

これは決め事なので、Godotでは、ドキュメントでもある通り、1Nodeに子ノードぶら下げてスクリプトアタッチすればいいかなー。と思った。

スクリプト言語について

  • UnityはUnity C#(それ以外にもJavaScriptPython likeなのはあるが...)
  • GodotはGDScript、C++

Unity C#

Godot GDScriptはまだ触れていないが、Unity C#について先に語るとすると、

  • Unity C#MonoDevelopのサポート受けれる。それ以上にVisualStudioのサポートを受けれて、強力。
  • Unity C#は.NET使えて、既存のライブラリを使えて、強力。

Godot GDScript

一方、Godot GDCScriptを語ると、

  • Godot GDCScriptは、Pythonライクと言っているが、Pythonとは異なる言語
  • Godot GDCScriptは、エディタサポート絶望的
  • Godot GDCScriptは、既存ライブラリ?そんなものはない。辛い。

という...。

Godot C++

GodotではC++で書くこともできるそうなので、C++がGodotスクリプトよりましか?(どこで拡張するんだろか、ランタイムの実装言語はC++なのはわかってるけど、差し込みやすいようになっているのか??

自分で組み込む?

個人的な感想だが、C++は慣れてなく、難しい言語なのでできるだけ使いたくないところ。できるだけ軽量な言語、例えばLua, Ruby(mruby), Python(micropython?CPython??、あれCythonでも行けるかしら?!)あたりを自前で組み込むか。

おっと、公式ドキュメントに過去にLuaPythonが組み込まれててたけど、自前でハンドリングしたいから、独自言語にたどり着いたって記載があった。うーむ。

Unityの.meta相当

Unityには.metaというアセットファイルとついになるメタ情報のテキストファイルがある。
あれ、結構便利で、テキストなので、ある程度git diffとかで読める。慣れてくると読めるし、ツールで活用するケースがある。

要確認事項では有るが、Godotは全部シリアライズされてバイナリデータになってるようなので、困る点がありそう。

Godotは一応ドキュメント上は、

but Godot approach is simpler, with a single configuration file, minimalist text format, and no metadata.

と述べている以上は、テキストファイルで必要十分であると、信じている。

GodotでHTML5エクスポート

Godot(ゴドー)、君は何者なんだい。Godotとの付き合いは二日目。まだ正体をつかめていない。

どうもrokujyouhitomaです。引き続きGodotを触ってる。

HTML5のエクスポートをサポートしているとのことなので、試した。

実行結果

結果を先に。ちゃんとビルドできた。

エクスポートしたアプリはGithub Pagesでホスティングしたので実行できるようにしといた。

godot-tutorial で実行できる。

f:id:rokujyouhitoma:20170611170720p:plain

環境情報

  • Mac OSX 10.10.5
  • Godot Engine 2.1.3-stable
  • Chrome 58.0.3029.110 (64-bit)

エクスポートの設定

デフォルトのGodotは、ビルドターゲットの設定が不十分なので、設定を行う。

  • Godot Engine - Download で配布されている をインポート。Godotエディタの"Setting" -> "Install Export Template"。Fileで落としたGodot_v2.1.3-stable_export_templates.tpzを指定。
  • エクスポートの実行は、"Export" -> "HTML5" -> "Export Project"

f:id:rokujyouhitoma:20170611170802p:plain

事前に、メインシーンの設定がまだの場合は、"Project Settings" -> "General"で"main scene"の設定をお忘れなく。

f:id:rokujyouhitoma:20170611170818p:plain

所感

すんなりできた。

一方で、templatesを自前でemscripten使ってビルドしようと思ったんだけど、Macにemsdkのインストールでハマった。ハマってる最中にドキュメント読んでたら、templatesが公式配布されてたからヽ(・ω・)/ズコー

ただ、テンプレートのインポートはハマりどころだと思ってて、エディタ環境にそもそも最初からバンドルされてる状態でもよかったんじゃないかな。なんで別なんだろか。