2017年7月19日水曜日

田胡研のサーバ紹介 2017年ver

# 田胡研のサーバ紹介 2017年ver 最近は早期配属の3年生も入ってきていろいろ楽しげなことが始まりそうな田胡研です. 今日は田胡研のサーバ(物理)の紹介をしようと思います # 田胡研のサーバ 田胡研は片柳研究所塔の11Fの角に部屋を持っていてそこをサーバルームにしています. ここにはCSCと同じ数ほどのサーバがあります. サーバは用途別にいくつかの系統に分かれていて * VM用サーバ * Fileサーバ * 実験用サーバ * Dockerクラスタサーバ などの目的ごとに配置しています. # VMサーバ,Fileサーバ IBM製(古い)のラックにブレードサーバが4枚とFileServerが1台あります. IBMのThinkPadのようなKVMがありそれぞれにアタッチできるのですがとても時代を感じます. このラック内のブレードサーバは主に研究室の主要サービスに使われており * FrontWebServer(Nginx) * DNS * Mail * Wiki * Gate * LDAP 等サービスをホストするVMサーバと * Zabbix * backup 等の監視・重要ファイルのミラーリングに使われています. ファンがうるさいです. 一番下にあるのがFileServerで自作したものになっています. FreeNASを入れてありRAID6構成ZFSでストレージプールとしiSCSIやNFSでVM等にファイルやボリュームを供給しています. FireServerはリプレイス計画があり1ヶ月内に倍以上の容量になる予定です. # 実験VMサーバ IBM製ラックの横にはアルミラック上にまな板で組んだサーバがありこれらは実験用のVMを供給するサーバとして使われています. 実験用VMサーバは現在2台あり,1台は個人で使ったり、いろいろな用途に使うよう,もう一台は学生PortalのコピーをホストするVMとして利用しています 本学で8000人が利用している学生Portalは田胡研製なので田胡研内でも学生ポータルが開発用にホストできるようになっています. 学生Portalの他にもCSCで運用しようとしている開発中のサービス等もこのVM上のリソースを利用したりしています. 下にあるPCケース入りのPCはCS学部のサーバになっていて田胡研の管轄外なのですがおいてあります. 学部サーバはカーネルのバージョンがとても古いと聞いたことがあります. # 実験サーバ, Dockerクラスタサーバ etc VMサーバがあるアルミラックの横に更にアルミラックがありそこにはたくさんのまな板のサーバがあります, これらは個人の実験用に使われています. 現在では * DockerCluster(Kubernetes)のノードとして6台 * 田胡研の次期インフラ基盤として期待しているOpenStakサーバ(in Gentoo) * 田胡研が作ったFileSystem(Elton)が動くサーバ 等に使われています. このラックにも追加するサーバをこの前発注したので近いうちにPCが増える予定です. PCはどんどん移り変わっていくのでこの時こんなんだったんやでってのが残ってるといいなって記事にしてみました. 今日はこれでおしまい. あまり期間があかないように書いていけたらなぁ...

2017年7月11日火曜日

田胡研SlackBot その2

# 田胡研SlackBotその2 ちまちま間が空いてしまいますができる限り書いていこうかなって 今日は前回に続いて田胡研Slackで使えるBotの紹介と東京工科大生は使えるかもしれないAPIの紹介をします. # 田胡研SchoolBusBot 田胡研のSlackではバスの時刻を知ることができます. 大学のスクールバスの時刻は http://www.teu.ac.jp/campus/access/006644.html#bus で公開されていますが正直見づらくアクセスしに行くのも大変です. そこで田胡研ではSlackBotに話しかけることでバスの時間を知ることができるようになっています ![slack_bot](https://gyazo.com/32c09eff219b2b93d4d0cb13ab334e3c.png) こんな感じに. * 行こうか => 八王子駅-大学 * 帰ろうか => 大学-八王子駅 * 買い出しかな => 大学-八王子みなみの * 歩こうか => 八王子みなみの-大学 という感じにラッキービーストに話しかければ時間がわかります. バスの時間知りたい時に使ってくれれば幸いです. # 東京工科大学スクールバスAPI このSlackBotは大したことないのですがバスの時刻データAPIを作るのが少し大変でした. 時刻表は大学のホームページで公開されているだけなのですが臨時運行があったりするので決め打ちだとよろしくありません. そこで時刻表のページをスクレイピングしてDBに保存しておきそのデータを問い合わせ可能なAPIを作りました. APIは公開しており, ソース: https://github.com/namazu510/teu-school-bus-api APIDoc: https://namazu510.github.io/teu-school-bus-api/ な感じです. 利用はフリーです. 弊学学生でなんか面白いもの作るのに使えそうなら使ってください. サーバ側で日1回新着のデータがないかチェックしています.

2017年7月8日土曜日

田胡研SlackBot その1

# はじめに この記事は田胡研初夏のAdventCalendar 8日目の記事です. 前回から間が微妙に空いてしまいましたが今日は前回のluuvaくんのvoiceroid apiに被せてそのapiを利用して田胡研SlackBotを作った話を書こうと思います. # 田胡研Slack 田胡研ではSlackをコミュニケーションツールとして使っています. 昔はIRCを使っていたらしいですがSlackに一本化しました. 基本コミュ障の集団なのでよくSlackで喋ったりしています. Slackはその便利さに加えてエンジニアとしてはいろいろなBotを作ることができるのが楽しいところです. 田胡研SlackにもいろいろBotが作られていて * Logger * ラーメン屋決定機 * 大学スクールバス時刻案内 * Voiceroid音声を研究室内で流せるBot などあります. スクールバス時刻案内BotはまたこのAdventCalendar期間中に書くとして,今日はVoiceroid音声をSlackから流せるBotについて書きます. # voiceroid-slackbot ## 利用手順 はじめにこのBotの利用ステップと動作を示します. 1. Slack上でBotにメンション付きで喋ってほしいテキストを送信する 1. SlackBotがVoiceroidAPIをcall 1. VoiceroidAPIから音声データがバイナリで飛んでくるので保存 1. 音声データを再生する (Botは研究室内のサーバで動いているのでそのスピーカから音声が流れる) という感じです. ## ソース slackbotはnodeで動かすことにしました. エコシステムのおかげでslackbotはほんと一瞬で作れてしまいます. ```js const RtmClient = require('@slack/client').RtmClient const WebClient = require('@slack/client').WebClient const RTM_EVENTS = require('@slack/client').RTM_EVENTS const exec = require('child_process').exec const axios = require('axios') const fs = require('fs') const token = process.env.API_TOKEN || 'DEBUG-TOKEN-HERE' const rtm = new RtmClient(token, { logLevel: 'error', autoReconnect: true, autoMark: true }) rtm.start() const web = new WebClient(token) rtm.on(RTM_EVENTS.MESSAGE, function handleRtmMessage(message) { console.log(message); let text = message.text // DM check if (text.indexOf('<@U5QCWJ64B>') === -1) { console.log('this is not direct message') return } text = text.replace('<@U5QCWJ64B>','') // play special sound if(text.indexOf('あけて') > -1){ randomNumber = Math.random(); let file_name = 'open_1.wav' if(randomNumber < 0.1){ file_name = 'open-gd.wav' } play(file_name) return } // play voiceloid sound axios.get('http://192.168.133.40:60334/voice', { params: { msg: text } }).then((res) => { return res.data }).then((data) => { // decode and save let sound = Buffer.from(data.sound, 'base64') let filename = `response.wav` fs.writeFile(filename, sound, (err) => { play(filename) }) }) }) function play (filename) { exec(`aplay -D plughw:1,0 ${filename}`, (err, stdout, stderr) => { if (err) { console.log(err) } console.log(stdout) }) } ``` ただ書き連ねたコードですが, あけて(研究室のカードロックを解除して!)というSlackのメッセージだけはVoiceroidを使わずたまにアニメ音声が流れるようになっています. こういうのは他にもいくつか追加できたらと思います. ## 使ってみて感想 * 深夜とかにスピーカーから音声を流せて中にいる人をおどかせる * ルイズコピペをどっからか流してテロが起こせる * カードキーを忘れて開けてほしいケースだとスマホも忘れていて結局Slackメッセージ経由で開けてもらえない * 研究室の中にいる人に確実に気づいてほしいメッセージを飛ばすのに便利 面白いものを思いついたらまたどんどんSlackBotを作って遊んでみたいですね. 今回はここでおしまい.

2017年7月6日木曜日

VoiceroidAPI

# VoiceroidAPI
B17のLuuvaです。
VoiceroidをAPIサーバーとして外部に音声を出力する機構を作りました。
![VOICEROID+ 結月ゆかり EX](https://lh3.googleusercontent.com/-8Pj3DV-7SgE/WVnFyNK_NvI/AAAAAAAAABM/IABZq2IZeoA_Ah5XJ9i0a6f0GfMfBbsIACEwYBhgL/w140-h51-p/mainimage.jpg "結月ゆかりさん")

# APIサーバーの使い方
以下のサイトにAPIドキュメントがあります。
研究室内のネットワークのみアクセス可能です。
[VoiceroidAPI(Network_KenA)](http://192.168.133.40:60334/)
場合によっては動いていなかったり、移転されている可能性もあります。

2017年7月4日火曜日

LDAPをRubyから触る

# はじめに この記事は田胡研初夏のAdventCalendar2017 4日目の記事です. 今日はRubyでLDAPの認証を利用したりしたときの話とちょっとしたサンプルコードを晒します. # RubyでLDAPを使うとき RubyでLDAPを使う際便利なGemはいくつかあります. * ruby-ldap (http://ruby-ldap.sourceforge.net/) * net-ldap ( https://github.com/ruby-ldap/ruby-net-ldap ) * active-ldap ( https://github.com/activeldap/activeldap ) などです. この内どれを使うか悩んだのですがnet-ldapを使うことにしました. 理由としては * なんか一番情報が多かった( コードサンプルとか ) * LDAPの問い合わせ操作がLDAPに近くLDAPを触るようにRuby上のコードがかける ことです. まず先にどんな感じで書けばLDAPの情報が引けるのか示します. # 単純にログインチェック net-ldapはgemで公開されているのでGemfileに書いて持ってきます. そしてこんな感じのコードを書きます. ```ruby require 'net/ldap' ldap = Net::LDAP.new ldap.host = LDAP_SERVER_HOST ldap.port = LDAP_PORT # アクセスのベースディレクトリを指定 ldap.base = LDAP_BASE # ログインするldapidとpassword username = params[:username] password = params[:password] # LDAP上での名前に luname = "uid=#{username},LDAP_BASE" ldap.auth luname, password # このbindがtrueならログインできる, falseはログインできない. ldap.bind ``` 思ったより複雑ではなかったです, ライブラリ様様ですね. # ユーザの属性取得 ログイン試行のコード例はいろいろあるのですがそれ以外があまり情報がなく少し手間取りました. ユーザの属性取得はFilterを利用してこんな感じ. ```ruby # 前述コードのldap.authのあとから ldap.open do |conn| filter = Net::LDAP::Filter.eq('uid', username) @entry = conn.search(filter: filter).first end # @entryはMapで回すと属性が取れる. @entry do |key, value| p key p value end ``` LDAPのクエリを少し調べないといけないのですがLDAPのクエリのサンプルはそこそこ転がっていて,それをRuby上のコードにするのは簡単でした. あるユーザの所属するグループ一覧を出すクエリなどは実現方法がわからずLDAPのデータを引いてきたあとにRuby側でフィルタするということを行って実現しました. # 田胡研のLDAPサーバのラッパーAPI ここまで示したようなコードを使ってLDAPのクエリを書いていけばRubyからLDAPの情報を引いてくることができます. ただLDAP自体メジャーな技術ではなかったり触るのが少し癖があったりで皆が手軽に利用するのは大変なので, 田胡研では今回書いたような方法でLDAPにアクセスし認証を行ったり,LDAPの情報をJSONで返す(WebAPI)を用意しています. APIでは以下の情報が取得できます. * ログイン試行 (userid+password or token) * 自分の情報 * 自分の所属するグループのリスト * 任意の人の情報(セキュアなものはないので弊研のLDAPはログインさえできれば他人の属性も引けます) このAPIを利用しいくつかのサービスを田胡研では開発しています. ( 田胡研メンバでLDAP認証系利用したいような人がいればswagger-doc等のリンクはnamazuさんのwiki個人ページにあるので参照してください. )

2017年7月3日月曜日

田胡研のGA

# はじめに この記事は田胡研初夏のAdventCalendar2017 3日目の記事です. 昨日はcut-terさんが書くとか言っていたけれど忘れていて空いてしまったようです. (´・ω・`) 3日目今日はしょうもないのですが田胡研WebのGAのレポートを軽く晒してみようとおもいます. # 田胡研のGA 田胡研のオフィシャルなWebサイトは基本的にはGA(GoogleAnalitycs)でアクセス解析をしています * 田胡研web ( http://www.t-lab.cs.teu.ac.jp ) * iot webサイト ( http://iot.k.t-lab.cs.teu.ac.jp ) などです # 最近の傾向とか 最近は研究室公開期間なこともありぐんと(しょぼいけど)アクセスがありました. こんな感じです. 一気に伸びたときには3年生への研究室配属説明のページがアップされた時と重なっていて意外とみんな田胡研のサイト見に来てるんだなーってわかります. ページリストは こんなかんじになっていましてみんながどこ見てるか分かります. 田胡研WEBサイトには田胡研診断っていうしょうもない問題があるのですがそのアクセス数が意外に多いのが面白いです. アクセス元ISPは弊学からのアクセスが全体の6割程度で後はまばらでした. ブラウザ分布に面白いところが見られてFirefox(37%)Chrome(30%) Safari(25%)程度で最もFirefoxが多く面白いです. 端末はモバイルが20%程でした. 意外とみんなスマホから大学の情報見てるんだなーってわかります. 私個人としては大学の情報なんてみんなPC持ってるんだからそれで見るだろうと思っていたのですがモバイルで研究室サイトにアクセスする人も多く, 大学のポータルとか(これから)触る私としてはモバイルの重要性はかなり重要なんだと再発見できました. 今日はこんなんで終わりにしようと思います.

2017年7月1日土曜日

田胡研のnginxとシングルサインオン

# はじめに この記事は田胡研初夏のAdventCalendar2017 1日目の記事です. ここに記事を書くのは12月のAdventCalendar以来になります, 最近やったことをあまり整理できていなかったので整理するためにも, またナレッジを少しでも溜めていくためにも7月にAdventCalendarをやることにしました! 1ヶ月間色々書いていけたらと思います. 1日目はnamazuさんです. # 田胡研のnginx 田胡研ではReverseProxyを行うWebServerとしてNginxを利用しています。 Nginxを流行始めたらしい2012年頃から利用しており、 現在田胡研Domain(t-lab.cs.teu.ac.jp)で外部公開するWebサービスについてはすべてNginxを利用して内部の各サービスへReverseProxyすることで公開しています。 公開している物としては * 田胡研web ( http://www.t-lab.cs.teu.ac.jp ) * iotプロジェクト ( http://iot.k.t-lab.cs.teu.ac.jp ) * lifehubプロジェクト ( http://lifehub.t-lab.cs.teu.ac.jp ) など外向きのものや * wiki * gitlab * webcam streaming など内向けのサービスを数え切れないくらい公開しています. これらはすべてnginxを経由しインターネットに公開しています. # シングルサインオン 田胡研では内向けの外部秘なサービスもインターネット経由でアクセス可能にしているため,内向けのサービスでは認証が必要です. 田胡研では所属メンバーに対してLDAPのアカウントを発行しているため,LDAPサーバへの問い合わせを行うことで正規アクセスかどうかを判定できます. このLDAP問い合わせを内向けサービスにそれぞれ実装すればいいのですが,実装が面倒だったりサービス毎にそれぞれログインが必要と非常に勝手が悪いので **一度LOGINサーバでログインしておけばあとは田胡研の内向けすべてのサービスをログイン処理なしで閲覧・操作できる**というシングルサインオンを用意しています. # 田胡研のシングルサインオンの歴史 前に田胡研では2012年頃からnginxを利用していると言いました, 当時nginxにはシングルサインオンを実現するためのモジュールは存在しておらず, 独自にmoduleを開発しperl製のLDAP認証ページと組み合わせたシングルサインオンを利用していました. 2017年になってnginxの更新に取り組んだのですがビルドコンフィグやnginxのmoduleのソースコードが失われていてこの再利用は困難でした. またモジュールも増えておりnginxに独自モジュールを組み込まなくても狙いのシングルサインオンは実現可能になっていることが分かりました. そのためnginxは正規(centos用の最新リリース物)をそのまま利用し,新しく追加された機能を用いてシングルサインオンを実現するようにしました. # nginxのシングルサインオン 現在nginxを利用したシングルサインオンの実現方法は数種存在します. nginx_auth系のmoduleには例として * nginx_auth_basic_module * nginx_auth_ldap_module のようなものがあってbasicではbasic認証を,ldapではldap認証を利用可能です. ただしこのようなものはカスタマイズ性に欠けるのが難点です. 見た目もブラウザのダイアログが出てくるような物なのであまり望ましくありません. そこで今回は [nginx_auth_request_module](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) を利用することとしました. このモジュールは公開サービスへReverseProxyする前にサブリクエストを任意のサーバに送信することができ, サブリクエストのステータスコードが200外である場合公開サービスへのReverseProxyを行わないようにすることが出来ます. つまりサブリクエストの送付先にLDAPを利用したログインページ兼認証サーバを置き,ReverseProxy前に認証サーバで既にログイン済みかをチェックし, ログイン済み(認証サーバが200応答)であればそのままReverseProxy, 非ログイン(認証サーバが401応答)であればログインページへリダイレクトするという処理が可能です. 田胡研は現在この方法でシングルサインオンを行っています. サブリクエストの送付先を田胡研ではRails製のLDAPサーバへ問い合わせるアプリケーションに設定していますが, サブリクエストの送付先は任意で設定可能なのでGoogleOpenID認証を利用したり等色々と幅が広いmoduleです. # nginx側の具体的設定例 LDAP認証を利用するログインページ等はまた後日記事を書こうと思っているのでどんな感じにnginxの設定がなされているかだけ今回では書いておきます. ```internal.conf auth_request /auth; error_page 401 = @auth_redirect; location /auth { internal; proxy_set_header Host LOGIN_SERVER_INTERNAL_URL; real_ip_header X-Forwarded-For; proxy_set_header Content-Length ""; proxy_pass LOGIN_SERVER_INTERNAL_URL; proxy_pass_request_body off; } location @auth_redirect { return 302 http://login.t-lab.cs.teu.ac.jp/login?request_uri=https://$host$request_uri; } ``` auth_requestでLOGIN_SERVERの/authを叩くようにし 401エラー時はloginページにリダイレクトするようにします. この設定ファイルを各サービス側で読み込んで使ってやることでどんなサービスでも簡単に田胡研のLDAP認証を掛けられるようにしています. 後日LDAPの認証ページをRailsで作る話など書けたらと思います. 明日のカレンダー担当はcut-terさんです.