Cloud9がAWSの一部になってしまったので利用方法を動画にしてみました

Cloud9はとても便利なWEB上の開発環境です。
元々はOSSのプロジェクトで基本料金無料で環境を提供してくださっていたのですが、Amazonに買収されて現在はAWSの一部として提供されています。買収後はAWSのアカウントを作ってから利用する形になったのですが、ちょっと億劫になってしまった人もいるかもしれません。

利用方法を動画にしてみましたので参考にしてください。

新しくAWSアカウントを作れば無料枠のおかげでリーズナブルに学べる仕組みができていると思いますが、用法・用量を守って正しくお使いください。AWSがどういう仕組みで課金されるかなどは知ってから進められることをオススメします(この辺りの課金についてのトラブルが起きた場合でも責任は持てませんのでご注意くださいませ)。

AWSのアカウント
Cloud9の環境構築

JavaScriptデバッグ作業の効率があがる!? 〜 ブレークポイントを使ってみよう 〜

こんにちわ。最近寒くなりましたね。 皆様はいかがお過ごしでしょうか?

本記事は、7歳のクリスマスイブにお母さんとサンタさんがキスをしている現場に遭遇して以来、何かが欠けてしまったTECH DRIVEの小笠原がお送りいたします。

今回はJavaScriptのデバッグ方法についてご紹介します。 ※ Google Chromeの開発者ツールを使用したデバッグ方法
以降はブレークポイントを使用したデバッグ方法の紹介がメインとなります。
↓のような感じでお悩みの方が対象となりますので、ご了承くださいませ。

1. JavaScriptのデバッグ方法がわからない
2. console.log以外のデバッグ方法がわからない

また、サンプルコードに関する前提条件は以下の通りです。
実行環境: Google Chrome
使用ライブラリ: jQuery

JavaScriptのデバッグ

JavaScriptが期待通りに動作しなかった時、皆さんはどこをみるでしょうか?

そうですね。開発者ツールのConsoleですね。

基本的にJavaScriptのコードにバグがあると、以下のようにConsoleにエラーメッセージとその原因となっているファイルの情報が出力されます。

f:id:kabaneshi:20171215163355p:plain

エラーの内容にもよりますが、上記のようなケースは該当箇所の確認やエラーメッセージでの検索等、解決のためのファーストアクションは取りやすいかと思います。
しかし、バグの中にはエラーが発生しないケースも存在します。

どういった場合でしょうか?
実際のコードを見ながら解説していきます。
以下のコードは ボタンをクリックするとテキストが表示される(pタグにテキストが挿入される)という処理になります。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>sample</title>
</head>
<body>
<button class="btn">テキストを表示</button>
<p class="text"></p>

<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="./script.js"></script>
</body>
</html>

script.js

$(function(){
    var $btn = $('.btn'),
        $text = $('.txt');

    $btn.on('click', function(){
        $text.text('ボタンがクリックされたよ');
    });
});

上記のコードは期待通りに動きませんが、エラーが発生しません。
ボタンをクリックしても何も起こらない状態です。

このバグを解決しようと思った時にまずは何をするでしょうか?
console.log で怪しい箇所を出力!と思った方、それも一つの解決方法であることは間違いありません。
しかし、もう少しだけ効率良くデバッグを行える方法があります。

ブレークポイントを使用したデバッグ

ブレークポイントというものをご存知でしょうか?
wikipediaを見ると以下のように書いてあります。

ブレークポイント(英: breakpoint)は、ソフトウェア開発のデバッグ作業において実行中のプログラムを意図的に一時停止させる箇所である。

なにやら難しそうですが、 実行中のコードを一時停止させる際に使われるものらしいです。
はて、実行中のコードが停止できると何がうれしいのでしょうか?

それでは、このバグをブレークポイントを使って潰してみたいと思います。
まず問題のページを実際にブラウザで開いてみます。

f:id:kabaneshi:20171215175922p:plain

テキストを表示というボタンをクリックしても何も起こりません。
開発者ツールからConsole(キャプチャ内の右側)を見てもエラーメッセージも表示されていません。

ではこのコードのどこに問題があるのか、調査していきたいと思います。

まずはConsoleの並びにあるSourcesというメニューを選択してみましょう。
選択後、以下のように現在表示中のページに関連するソースファイルの一覧が表示されるはずです。

f:id:kabaneshi:20171215164945p:plain

JavaScriptのコードを確認したいので、ソースファイルの一覧からコードが記載されているscript.jsを選択します。
すると、以下のように開発者ツール右側に表示されているソースがscript.jsの内容に変わります。

f:id:kabaneshi:20171215172342p:plain

次にこのJavaScriptコードを途中で停止させるためのブレークポイントを入れます。
ブレークポイントの挿入は簡単で、以下のようにコードの行数が記載された箇所をクリックするだけです。
まずは、変数の定義をしている2行目で処理を停止したいと思います。

f:id:kabaneshi:20171215172221p:plain

↑のように停止したい行数をクリックしブレークポイントが入ると青くハイライトされるた状態になります。
それでは、この状態で画面をリフレッシュしてみましょう。

リフレッシュ後に画面が↓のキャプチャと同じ状態になっていれば、ブレークポイントでコードが停止していることになります。

f:id:kabaneshi:20171215172752p:plain

先程script.jsの2行目にブレークポイントを挿入したので、JavaScriptの実行はそこで止まっています。
次に開発者ツール右下のScopeという項目をみてみましょう。
するとLocalと書かれた情報にネストしていくつかの情報が表示されていることがわかります。

f:id:kabaneshi:20171215173052p:plain

このLocalの解説を厳密にすると、それだけで1記事余裕で書けてしまうので、今回は割愛します。
Local中の情報で着目すべきは、script.jsの中で定義した変数の情報になります。
↑のキャプチャ内の枠で囲われた箇所から現在変数に入っている情報を確認することができます。

今は2行目で処理が停止しているので、まだ変数に値は代入されておらず、undefined(変数を宣言した際に入る初期値)が入っていることがわかります。

次に開発ツール上でscript.jsの2行目を実行してみましょう。
開発ツール左下のメニューバーにあるアーチ状の矢印をクリックしてください。

f:id:kabaneshi:20171215174817p:plain

矢印をクリックするとscript.jsの2行目が実行され再び3行目で止まります。
この状態で再度右側のLocalの中を確認してみましょう。
2行目が実行されたことにより、変数$btnに値が入っているのが確認できます。

f:id:kabaneshi:20171215174937p:plain

この容量でデバッグを進めていくと、わざわざconsole.logで出力しなくとも変数の値が確認できるので、デバッグが捗りそうです。
また、このアーチ状の矢印はステップ実行と呼ばれ、クリックするとブレークポイント挿入箇所から1行ずつコードを実行してくれます。
それでは、再度ステップ実行を行いLocalの中を見てみましょう。

f:id:kabaneshi:20171215175227p:plain

次は3行目の処理を実行されました。
再度Localを確認すると、先程までundefinedだった$textの中にも値が入っていることが確認できます。
しかし、$textの中に要素の情報が入っていません。。。
ここが怪しそうですね。

このデバッグ方法の素晴らしいところは、現在の停止した状態でConsoleからJavaScriptが実行できる点です。
それでは、なぜ$textに期待した値が入っていないのか、開発者ツール下部のConsoleから$('.txt')を実行してみましょう。 ※ 開発者ツールの下部にConsoleが表示されていない場合はEscキーを押してみてください。

f:id:kabaneshi:20171215175631p:plain

Consoleから$('.txt')を実行するとLocal->$textの結果と同様に要素の情報が取得できていないことがわかります。
もうお気づきとは思いますが、今回はタイポがバグの原因となっていました。
script.jsの3行目で.textとすべきところが.txtとなっていました。
.txtというクラス名を持った要素は存在しないため、要素が取得できていなかったんですね。

それでは、ブレークポイントを解除し、該当箇所を修正した上でもう一度動作を確認してみましょう。
先程ブレークポイントを挿入した際に青くハイライトされた行数の箇所を再度クリックすると解除が行えます。

ページのリフレッシュ後、ブラウザ上のボタンをクリックしてみましょう。
以下のように「ボタンがクリックされたよ」というテキストが表示されれば、デバッグ成功です。

f:id:kabaneshi:20171215175819p:plain

まとめ

今回は解説のため、かなり極端なバグを例にデバッグ方法をご紹介しました。
しかし、ブレークポイントを活用することで効率よくデバッグが行えることは、お分かりいただけたかと思います。
また、今回エラーの発生しないバグを例に記事を書きましたが、ブレークポイントを活用すると以下のようなこともできます。

  1. エラー発生時、その前後で実行されている処理の動作確認
  2. 複数の変数に代入されている値の確認

この他にもデバック時の様々なシーンで役立ちますので、本記事でブレークポイントを知ったという方は、是非今後も活用してみてください!

PR

TECH DRIVE協賛企業のサークルアラウンド株式会社では、プログラマーの成長を加速させるためのトレーニングを行なっています。フロントサイドからバックエンドまで各種バリエーションがございますので、ご興味がある方は是非以下のリンクより詳細をご覧ください。

JavaScript Climbing

JavaScriptに特化したトレーニング「JavaScript Climbing」を行なっています。
this、クロージャ、Class等、中〜大規模のフロントエンドの開発に臨にあたり、必須となるスキル習得を現役のWEBエンジニアが徹底してサポートします。
2週間の無料体験期間がございますので、ご興味がある方は是非以下のリンクより詳細をご覧ください。

circlearound.co.jp

個別トレーニング

短期間でぐっと成長したい方は弊社主催の個別トレーニングがおすすめです。 トレーニング内容は、受講者の方の課題/要望をお伺いした上で、フルオーダメイドで作成させていただきます。 詳細は以下のリンクよりご確認ください。(応募者多数の場合には時間を別途ご用意する予定です)。

WEBプログラミング個別トレーニング

チーム開発トレーニング

既にある程度コーディングが可能なのでチーム開発を経験してみたいという方にはチーム開発トレーニングがおすすめです。 GitHub Flowを使用し、実践の開発フローを体験していただきながらスキルアップ可能なトレーニングとなっています。

WEBサービスチーム開発トレーニング

Mastodonを2週間ほどHeroku運用した日報まとめ

https://top-techdrive-mastodon-assets.s3-ap-northeast-1.amazonaws.com/media_attachments/files/000/002/757/original/f13ba52f77560603.png?1493429954

はじめに

流行りそうって言うより、面白そうだったのでやり始めたら結構続けているのでまとめてみます。Herokuさんとはなんの関係もございません。

経緯

4/15 〜 おっかなびっくりの初期

4/15 くらいから興味を持ってとりあえず運用してみたくてちょっと調べたら「ユーザ名とパスワードを抜かれるから野良インスタンスはウンタラカンタラ」というような運営者の信用の話があったので、OAuthで解決するのが妥当かと考えました。そして私や私の周囲の人で楽しめる形にするにはGitHubでのOAuthが最善で、その後の個人的な改造にも楽しみが増えると思っていました。もともとこういうサービスを自分で作りたかったことも動機の一つです。

GitHubでのログインを対応させて下記を4/16に書いていますね。とりあえずぼっちだったんですね。 www.facebook.com

HerokuのFreeDynoは早々に見切りを付けて1Dyno使い出しました。FreeDynoはSwapが実装されていないので、少しアクセスが増えるとメモリ不足のエラーが出てしまうのですね。そのままだと利用に支障をきたすと考えて課金生活を始めました。周囲の情報からメモリの使用が尋常ではないと知ったので、そのままでは難しいと思いました。

mstdn.techdrive.top

最初に日報を書いたのが 4/17らしいです。このころは「じゃじゃ馬馴らし」的な気持ちでやっていたと思います。設定できそうなのが下記です。

  • WEB_CONCURRENCY
  • MAX_THERADS
  • Sidekiq concurrency

WEB_CONCURRENCY × MAX_THERADS の分だけスレッドが利用されるはず(その分並行処理が増えるのでメモリも使うはず。Puma環境詳しくないですが https://github.com/puma/puma#clustered-mode あたりを見るとその様子です)で、それとは別にSidekiq concurrency も並行処理分メモリを使うだろうということらしいです。

なので、やばそうになるとこの辺りの数値を調整してメモリ利用をし過ぎないように調整していました。かなり絞りまくっていたのがこの時期です。

mstdn.techdrive.top

mstdn.techdrive.top

ちなみにこの時点でほとんどお一人様インスタンスなので、通常のWEBサービスと求められることがだいぶ違うと感じていました。全然利用者がいなくてもリソースを食いまくり、課金までさせられるので、あまり得したような気がしません。

4/18 〜 workerを作成して安定

結局、一台での安定は難しいと判断して(常時9割近くメモリを消費する状態では安心できません)、workerを立ててみたところだいぶ安定してきました。worker自体の負荷が高かったわけではなく、webの方なのかと感じたのもこのあたりです。また、DBへの負荷が高いとよく言われていますが、Heroku Postgresを利用しているので私が関知するところではなくなっているのは幸運でした(Herokuさんごめんなさい)。Rollbarなども入れてエラーがわかるようになったのはこの頃です(あまりに多くて若干引きました。Slackに流すとかしなくて良かったです)。

mstdn.techdrive.top mstdn.techdrive.top mstdn.techdrive.top mstdn.techdrive.top

理屈では、WEB_CONCURRENCY × MAX_THERADS + Sidekiq concurrencyでDB接続をすると思うので、DB_POOLの値はそれを超えて少し余裕をつけるようにしています。この辺り最初の頃は乱暴に設定していたのでDBに接続できないエラーがRollbarに通知されていました。

ちなみにストリーミングサーバーの構築に全く触れていませんが、Herokuのアプリケーション一つでは難しそうです。みなさん工夫されている様子です。 qiita.com

4/22 初めてのVerup

最初どこかのmasterをforkして持ってきてしまったので自分が運用しているバージョンすら知らなかったのですが、ver1.2.2が出たとのことでバージョンアップ。怖かったのでstagingを用意して、これでうまくいくか確認してから行いました。Herokuには特定のGitHubのブランチを監視して変更があれば自動デプロイする仕組みがあるので、今はこれを生かしてマージ=デプロイの運用をしています(本当はCircleCIなどで環境作りたいですがちょっと時間が足らずできていません)。

mstdn.techdrive.top mstdn.techdrive.top mstdn.techdrive.top

ここではmastodon:dailyを仕掛けないとやばいという話が伝え聞こえていたので、それだけは忘れずにやろうと決意して臨みました。

4/23 〜 安定期

この辺りでやっと諸々落ち着いてきた感があり、淡々としています。日報の変化少ないので巻末に入れます。気付いたり思ったこととしては下記です。

  • 無差別フォローBotはサーバーの負荷になるのでブロックすること(フォローされると、トゥートの度にこちらのサーバーがアクションしなければならなくなるのでリソースを食います)。
  • テキストばかりのインスタンスでローカルTLに2〜3人のせいか、ポツポツ人が増えてもそれほど大きな負荷にはなっていません。
  • Herokuはこれくらいならひょっとすると人数捌けるのかもしれません。人数増えないのでGitHubのアカウントお持ちの方は https://mstdn.techdrive.top/ へ遊びに来てくださいー。
  • チューンするならWebからやりたいです。
  • 改造は少しずつが良いです。GitHubログインだけできれば良いと思ってガサッと機能を削ってみたのですが、アプリにログインするのにOAuthだと邪魔になるケースなどがあり、結局かなり戻しています。
  • サインアップを1秒ごとに狙ってくる輩がいます。これをブロックしておかないとメアドログインのインスタンスは荒らされそうな気がします(OAuthログインなのでエラーログに出てきます)。

これまでの人数の増減などは下記で見ると良いかもしれません。 https://dashboards.mnm.social/dashboard/db/instance-detail?var-instance=mstdn.techdrive.top&refresh=30m&orgId=1

お礼など

Herokuでの工夫はzunda氏のトゥートやGitHubを大変参考にさせていただきました。まだまだ私の知らない工夫をされているので、追いついていきたいです。

mastodon.zunda.ninja github.com

付録

23日以降の日報

mstdn.techdrive.top mstdn.techdrive.top mstdn.techdrive.top

mstdn.techdrive.top mstdn.techdrive.top mstdn.techdrive.top

「HTML+CSS入門ハンズオン!ゆるーくWebサイトを作ってみる会」好評でした!

f:id:ms2sato:20170420192349j:plain

TECH DRIVE佐藤です。TECH DRIVE ではブログだけではなくて、勉強会やセミナーも開催しています!
4/18に行われた「HTML+CSS入門ハンズオン!ゆるーくWebサイトを作ってみる会」もその活動の一つです。メンバーの小笠原氏によるハンズオンで、これまでにも何度か開催された実績のある会です。

最初はライブコーディングを交えたデモンストレーションと共にGoogleChromeのデベロッパー・ツールの扱い方をお伝えしました。
その後、会場のみなさんは資料を参考にしながらHTML/CSSを作り込んで行きます。途中でわからないことがあっても、講師が傍まできて一緒に考え、理解が深まるように丁寧にレクチャーをしてくれます。

f:id:ms2sato:20170420194940p:plain

ご参加いただいた方からは
「作り込まれている資料だったので凄いと思った」
「丁寧に説明受けられてわかりやすかった」
などの声をいただけました。

また、こういったセミナーでは「セミナー当日はわかったと思ったんだけど、いざやってみたらよく理解できていなかった」ということはよくあると思います。TECH DRIVEではそういった困りごとにお答えするために「【初心者歓迎】プログラミング相談所【もくもく作業でもOK】」を開いています。わからないことは再度講師に対面で質問できるので、フォローアップも万全です!
次回は 4/25、場所は同じ高田馬場 CASE Shinjukuさんにお借りして開催します。参加されて疑問点のある方も、参加できなかったけれども相談事のある方も奮ってご参加ください。
techdrive.connpass.com

初心者向けにできるだけ噛み砕いてみるオブジェクト指向 vol.3 コードの変更に対応する

はじめに

これまで、vol.0vol.1vol.2とたとえ話が続いているので「で、実際にコードではどうなるの?」と気になってくるのではないかと思います。これから複数回に分けて、実際にコードを書いていきながら確かめていきましょう。今回はコードに起こる変更のイメージを感じていただけたらと思っています。オブジェクトっぽいコードはまだ出てきませんので「こんなの楽勝!」という方は読み飛ばせるかもしれません。

シチュエーション

私は先輩プログラマに依頼されて、システムの一部の処理を書いています。まだ仕様は確定していないそうで、サンプルのコードを書いておき、そこから都合のいい部分を本当のシステムに移植するらしいです。先輩は「移植しやすいように作れよ」と言っていました。

ある規則に則って文字列を加工するのが私の担当箇所です。

ストーリー

お題0: カンマ区切り

「カンマで区切られている文字列を、標準出力に出す」 とりあえずこれを言われたので、下記のようなコードを書いてみました。

# 準備された入力の文字列をカンマ区切りで区切って一行ずつ出力する
str = "りんご,みかん,バナナ,いちご"

# ここの処理を作る
puts str.split(',')

どうやらこれはこれで良さそうです。初歩的な内容で書ける処理でしたね。

お題1: 数字と一緒に出力する

どうやら出力のフォーマットが決まってきた様子で、見やすいように行の先頭にインデクスを付けて出すようです。 というわけで、コードを変えてみました。

# 準備された入力の文字列をカンマ区切りで区切って
# 一行ずつインデクスと一緒に出力する
str = "りんご,みかん,バナナ,いちご"

# ここの処理を作る
str.split(',').each_with_index do |fruit, index|
  puts "#{index}:#{fruit}"
end

each_with_indexがわかれば大丈夫でした。

お題2: カンマとコロンに対応する

今度は入力の文字列のフォーマットも変わる様子です。カンマだけではなくて、コロンで区切られることもあるらしいです。 splitは正規表現にも対応している様子なので、一箇所の変更で済みました。

# 準備された入力の文字列をカンマまたはコロン区切りで区切って
# 一行ずつインデクスと一緒に出力する
str = "りんご:みかん,バナナ:いちご"

# ここの処理を作る
str.split(/[,:]/).each_with_index do |fruit, index|
  puts "#{index}:#{fruit}"
end

先輩によると、入力の文字列のフォーマットと、出力のフォーマットはまだ変更されるかもしれないとのことです。

お題3: HTMLタグとして出力する

出力をHTMLで出せないかと依頼があったので、次はこんなコードを書きました。ちょっとした改変でulタグにできて良かったです。

# 準備された入力の文字列をカンマまたはコロン区切りで区切って
# HTMLのULタグとして出力する
str = "りんご:みかん,バナナ:いちご"

# ここの処理を作る
puts '<ul>'
str.split(/[,:]/).each do |fruit|
  puts "<li>#{fruit}</li>"
end
puts '</ul>'

お題4: 状況によって出し分ける

先のお題はちょっと勘違いをしてしまいました。「HTMLでも出せるように」ということで、出し分けが必要だったんですね。条件分岐をするのだろうと思い、下記のようなコードを書きました。

# 準備された入力の文字列をカンマまたはコロン区切りで区切って
# HTMLのULタグとして出力する
str = "りんご:みかん,バナナ:いちご"
output_type = :ul
# output_type = :indexed # インデクス付きならこちら

fruits = str.split(/[,:]/)

if output_type == :ul
  puts '<ul>'
  fruits.each do |fruit|
    puts "<li>#{fruit}</li>"
  end
  puts '</ul>'
elsif output_type == :indexed
  fruits.each_with_index do |fruit, index|
    puts "#{index}:#{fruit}"
  end
end

先輩はあんまりいい反応ではなくて「これはこれで良いけれど、今後、出力の方法が増えるとif文がずっと続くの?ブツブツ…」みたいな感じなんですね。うーん、どうしたら良いんでしょう。

おしまいに

説明しやすいようにお題の内容はかなり簡単な処理です。本来はもっと複雑な処理の方が恩恵はあるのですが、最初は理解しやすいコードで感覚をつかんでいただければと思い、上記のような内容にしています。 実際の現場でお題4のコードでダメ出しされるのは、出力方法が余程変化するシステムでなければ無いと思います。長くなったので次回から上記のコードをより良い形に変えていきます。

一連のコードは下記から取得できます。

github.com

PR

TECH DRIVE協賛企業のサークルアラウンド株式会社では、プログラマーの成長を加速させるためのトレーニングを行なっています。フロントサイドからバックエンドまで各種バリエーションがございますので、ご興味がある方は是非以下のリンクより詳細をご覧ください。

JavaScript Climbing

JavaScriptに特化したトレーニング「JavaScript Climbing」を行なっています。
this、クロージャ、Class等、中〜大規模のフロントエンドの開発に臨にあたり、必須となるスキル習得を現役のWEBエンジニアが徹底してサポートします。
2週間の無料体験期間がございますので、ご興味がある方は是非以下のリンクより詳細をご覧ください。

circlearound.co.jp

Ruby Climbing

週1からはじめられる「Ruby」でWEB開発の基礎が習得できる塾です。現役のプログラミング講師&Rubyエンジニアがプログラミング入門からフレームワーク(Sinatra/Ruby on Rails)を使用した本格的なWEB開発の学習までをしっかりとサポートします。

ruby climbing

個別トレーニング

短期間でぐっと成長したい方は弊社主催の個別トレーニングがおすすめです。 トレーニング内容は、受講者の方の課題/要望をお伺いした上で、フルオーダメイドで作成させていただきます。 詳細は以下のリンクよりご確認ください。(応募者多数の場合には時間を別途ご用意する予定です)。

WEBプログラミング個別トレーニング

チーム開発トレーニング

既にある程度コーディングが可能なのでチーム開発を経験してみたいという方にはチーム開発トレーニングがおすすめです。 GitHub Flowを使用し、実践の開発フローを体験していただきながらスキルアップ可能なトレーニングとなっています。

WEBサービスチーム開発トレーニング

【セキュリティ対策は大丈夫 ?】SSL証明書の新規発行、更新手順をまとめてみた。【POODLE, RC4, etc.】

こんにちは。TECH DRIVEの齋藤です。

先日、管理しているサイトのSSL証明書の期限が切れそうになっているのに気づき慌てて更新しました。

毎回思うのですがSSLの更新って結構面倒ですよね。
私自身も手順を忘れることがあるのでまとめてみました。

今回は更新でしたが新しくCSR*1を発行するので新規発行と手順にほぼ変わりはないです。

環境

  • OS - Amazon Linux
  • SSL認証局・種別 - COMODO・PositiveSSL
  • Web Server - Apache + OpenSSL
  • 証明書の販売サイト - SSLストア

 ※ 下記手順はCentOS、他の認証局でも使えるかと思います。

AWS Certificate Manager

AWS使っているならACM(AWS Certificate Manager) 使えよって思うかもしれません。

私も最初はACMを使おうと思いました。
ただACM利用には下の条件があります。

f:id:shoheis:20170313115403p:plain

今回設定するインスタンスはElastic Load Balancingを使っていませんでした。
なのでこれから書く手順が必要だったわけです。

バックアップをとる

運用しているサイトでSSL証明書の設定をする時は必ず事前にサーバーや編集するファイルのバックアップをして、いつでも元に戻せるようにしてから作業してください。

発行手順

  1. 証明書の購入(新規 or 更新)とアクティベート
  2. アクティベートに必要なCSRの作成
  3. ホスト証明書の設置
  4. 中間証明書の作成
  5. 中間証明書の設置
  6. SSLの設定
  7. セキュリティのテストと強化

証明書の購入とアクティベート

まずはお使いのSSLを管理しているウェブサイトで証明書を購入しましょう。
購入後は証明書のアクティベート(署名の申請)が必要です。

私はSSLストアというサイトを使っているので、証明書の購入とアクティベートは表の流れになりました。

項目 購入の参考サイト アクティベート
新規証明書の購入 こちら*2の手順7まで 左記「購入の参考サイト」の手順8から
更新用証明書の購入 こちら 新規証明書の「購入の参考サイトの手順8」から

またアクティベートの際にはCSRが必要になります。

CSRの作成

まずはCSR作成に必要なプライベートキーを作成します*3

サーバーに接続し、 /etc/pki/tls/private/ に移動しましょう。

$ cd /etc/pki/tls/private/

新しいプライベートキーを作成します*4

$ sudo openssl genrsa -out private.key 2048

プライベートキーにアクセス制限をかけます*5

$ sudo chown root.root private.key
$ sudo chmod 600 private.key

作成したプライベートキーを使いCSRを作成します。

$ sudo openssl req -new -key private.key -out csr.pem

CSR作成のための情報の入力します(下表はCSRの入力例)。

項目 意味
Country Name 国コード JP
State or Province Name 都道府県名 Tokyo
Locality Name 市区町村名 Chuo-Ku
Organization Name 組織名 Example Corp
Organizational Unit Name 部署名 Example Dept
Common Name コモンネーム*6 www.example.com
Email Address 管理者のメールアドレス someone@example.com

参考

アクティベート時に貼り付けるので作成したCSRの中身をコピーしておきましょう。

CSRが作成できたらそれを使ってアクティベート を完了します。
アクティベートが完了するとSSL認証局からメールが届きます。
メールに添付してある証明書(ウェブの管理画面からでもダウンロードできます)を設置していきましょう。

ホスト証明書の設置

ホスト証明書はCOMODOのPositiveSSLではメールでYour PositiveSSL Certificate となっているファイルです。 「www_example_co_jp.crt」のような名前かと思います。
/etc/pki/tls/certs に移動します。*7

$ cd /etc/pki/tls/certs

ホスト証明書をこのディレクトリにあげて*8、アクセス制限をかけます。

$ sudo chown root.root www_example_co_jp.crt
$ sudo chmod 600 www_example_co_jp.crt

ホスト証明書の設置は以上です。

中間証明書の作成

認証局によっては中間証明書(または、つなげて一つのファイルにする作業)が必要になります*9
つなげる際は順番が大事なようです(このままコピーして使えばOKです、中間証明書の名前は任意です)。

$ cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > intermediate.crt

中間証明書の設置

再度サーバーに接続後、 /etc/pki/tls/certs に移動します。
中間証明書をこのディレクトリにあげて
ホスト証明書より緩い形ですが、アクセス制限をかけます。

$ sudo chown root.root intermediate.crt
$ sudo chmod 644 intermediate.crt

中間証明書の設置は以上になります。

SSLの設定

mod_ssl の設定ファイル/etc/httpd/conf.d/ssl.conf を編集します。
ssl.conf をエディタで開き、下記の設定を追加しましょう*10

SSLCertificateFile /etc/pki/tls/certs/www_example_co_jp.crt
SSLCACertificateFile /etc/pki/tls/certs/intermediate.crt

念のためhttpdの文法チェックをしておきましょう。

$ apachectl configtest

「Syntax OK」と出たらサーバーを再起動します。

$ sudo service httpd restart

SSLの設定は以上になります。


参考として、別のサイトではSSLの設定を下記のようにしていました。
場合によってはこの書き方をしないと設定できないのかもしれません。

SSLCertificateFile /etc/pki/tls/certs/www_example_co_jp.crt
SSLCertificateKeyFile /etc/pki/tls/private/private.key
SSLCertificateChainFile /etc/pki/tls/certs/intermediate.crt

これで「https」でサイトにアクセスできるようになっているはずです。

セキュリティのテストと強化

デフォルトの状態だとセキュリティが弱い場合があります。Qualys SSL Labs などを使用して現在のセキュリティの強さをチェックしましょう。


Amazon Linuxのデフォルトの設定だと下記の脆弱性に対処できていません。

  • POODLE脆弱性
  • RC4 暗号化方式の脆弱性
  • 前方秘匿性の欠落による脆弱性

私も最初にチェックした時はこのような状態でした(Future Grade やばいですね)。

f:id:shoheis:20170313200218p:plain

上から順に対処していきます*11

POODLE脆弱性

/etc/httpd/conf.d/ssl.conf を編集します。SSLProtocol ディレクティブをコメントアウトします。

# SSLProtocol all -SSLv2

その行のしたに下記を追加します。

SSLProtocol -SSLv2 -SSLv3 +TLSv1 +TLSv1.1 +TLSv1.2
RC4 暗号化方式の脆弱性、前方秘匿性の欠落による脆弱性

「前方秘匿性の欠落による脆弱性」の対処が「RC4 暗号化方式の脆弱性」の対処を含む形になるので、変更は1箇所で大丈夫です。
SSLCipherSuite ディレクティブを探し、コメントアウトされていた場合はそのままの状態でその下に下記を追加します。

SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA


また再起動の前にはhttpdの文法チェックをしておきましょう。

$ apachectl configtest

「Syntax OK」と出たらサーバーを再起動します。

$ sudo service httpd restart

この状態で再度Qualys SSL Labs でチェックしてみましょう。ランクが上がっているはずです。

f:id:shoheis:20170313200958p:plain

以上でSSL証明書の設定は完了になります。お疲れ様でした!

主な参考サイト

今回は特にAWSのチュートリアルにお世話になりました。セキュリティの強化(特にRC4と前方秘匿性)は前回の更新時にはわからなかったので助かりました。下記サイト以外にも様々なサイトの助けを得ながら設定しました。

*1:認証局に提出する署名リクエストです。作成にはプライベートキーが必要で、セキュリティ上長年同じプライベートキーを利用するのは好ましくないのでそのキーと合わせて再作成します。参考

*2:RapidSSLですがPositiveSSLと手順に変わりはありません。

*3: Amazon Linux をお使いの方かつ新規作成時は既存のホストキー 「/etc/pki/tls/private/localhost.key」 をプライベートキーとして使ってもOKです

*4: よりセキュリティの強いキーの生成方法もあります。参考

*5: すでに private.key の所有者はrootなはずなので chownはやらなくていいのですが念のため書いています

*6:ユーザーがブラウザに入力するウェブアドレス

*7: 元の自己署名ホスト証明書 localhost.crt がある場合はそれを /etc/pki/tls/certs ディレクトリから削除します。

*8: 自分は scp でアップロードしました。 参考

*9:COMODOのPositiveSSLでは必要でした。他の認証局では必要がないかもしれません。適宜調べてみてください。

*10: 更新時に「ホスト証明書や中間証明書、プライベートキー」の「設置場所・ファイル名」が、前回の設定時と変わらない場合はssl.confを編集する必要はありません

*11:詳細はこのページを参考にしてください

ざっくりWebpack入門 Vol.2 babelでES6のトランスパイル

f:id:kabaneshi:20170307123107p:plain

こんにちは。TECH DRIVEの小笠原です。 Vol1につづき、本記事でもWebpackについてご紹介させていただきます。

今回はWebpackを使いES6で書かれたファイルのトランスパイルを行いたいと思います。

前提条件

  • 1.node.jsが導入済みのMac OSであること
  • 2.ES6やbabelが何か理解していること

Webpackについては、Vol1で触れておりますのでこちらに目を通していただければと。 dev.techdrive.top

また、本記事はWebpackでES6のトランスパイルを行うことに重きを置いておりますので、ES6やbabelの詳細に関しては割愛させていただきます。

Webpackの導入

今回はプロダクトが以下のディレクトリ構造であることを前提に進めます。

├── dist  // HTMLから呼び出されるJSファイル   
├── index.html  
├── src  
   └── js-es6 // ES6で書かれたJSファイル   
       └── person.js

まずは、前回同様にpackage.jsonファイルを作成しましょう。

npm init

つづけてWebpackのインストールを行います。

npm install --save-dev webpack

次に今回トランスパイルを行うために必要なloaderを導入します。

loaderについて

現状ES6を使用するには、babel等のトランスパイラが必要になります。
Webpackでは、loaderという機能を通しトランスパイラを使用します。

loaderは複数種類があり、npmとして提供されています。

loaderの導入

それでは、Webpack上でbabelを利用するために必要なloaderをインストールします。

npm install --save-dev babel-loader babel-preset-es2015

次にES6の文法を用いて書いたJSファイルを用意します。

src/js-es6/person.js

module.exports = function() {
    class Person {
        constructor(name) {
            this.name = name;
        }
        hello() {
            alert('My name is ' + this.name);
        }
    }

    var kevin = new Person('kevin')
    kevin.hello();
}

※ ES6の文法(class)を使用するため仰々しい書き方をしていますが、処理自体はブラウザ上でコードが実行された際、アラートダイアログが表示されるシンプルなものです。

設定ファイルの作成

続けてルートディレクトリ直下に設定ファイルを作成し、前回と同じようなノリでトランスパイル対象のファイル情報と出力先の情報等を書いていきます。
今回はloaderを使用するので、前回より設定項目が増えています。

webpack.config.js

module.exports = {
  // トランスパイル起点となるファイル(複数指定可)
  entry: {
    'person': './src/js-es6/person.js',
  },
  // トランスパイルされたファイルの出力先の情報
  output: { 
    path: __dirname + '/dist',  // パス情報
    filename: '[name].js'   // [name]には 、entryで指定したkey名が入る(今回の場合はperson)
  },
  module: {
    loaders: [  // 使用するloaderに関する情報を記載
      { 
        test: /\.js$/,  // トランスパイルを行うファイルの正規表現
        exclude: /node_modules/, // 除外ファイル 
        loader: "babel", // 使用するローダー
        query:{
          presets: ['es2015']
        }
      }
    ]
  }
};

loaderを扱うためmoduleloadersというプロパティを記載しています。
Webpackでは複数のloaderを利用することができるため、loadersの値は配列となり、loader毎に設定情報を記載します。

トランスパイル実行

これでトランスパイルを行うための準備ができました。
webpackコマンドを実行してみましょう。

webpack

dist直下にトランスパイルされたファイルが入っていれば成功です!
試しに出力されたJSファイルをHTMLファイルから呼び出し、期待通り動作することを確認してみましょう。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>Document</title>
</head>
<body>

<script src='./dist/person.js'></script>
</body>
</html>

アラートダイアログで「'My name is kevin」と出力されれば、今回の目的は達成です!

まとめ

いかがでしょうか?今回ご紹介させていただいたloaderという機能は、Webpackの核となる機能といっても過言ではありません。
今回は触れませんでしたが、loaderを使用することでJSファイルからHTML/CSSファイルや画像ファイルを呼び込むことができ、HTML/CSS/JSをまとめたコンポーネントを作成することも可能です。

loaderの詳細に関しては、今後の連載の中でも触れていきますが、まずは入門編として本記事をお役立ていただけたのなら幸いです。

TECH DRIVEについて

TECH DRIVEは「技術者の成長を加速させる」をキーワードに都内で活動をしているコミュニティです。
TwitterやFacebookにて技術ネタやイベント情報の発信を行っていますので、ご興味があれば、いいねやフォローをお願いいたします。