Shogo's Blog

Aug 21, 2019 - 1 minute read - Comments - perl lambda

AWS Lambda Perl Runtime で AWS X-Ray を使えるようになりました

AWS Lambda 上で Perl を動かす AWS::Lambda で、 AWSの分散アプリケーションの分析サービスである AWS X-Ray をサポートしました! AWS X-Ray って何? Perl からどう使うの? という人は @fujiwara さんの記事とYAPC::Tokyo 2019での発表スライドをどうぞ。 第56回 AWS X-Rayによる分散トレーシング―マイクロサービスのボトルネック,障害箇所の特定(1) 第56回 AWS X-Rayによる分散トレーシング―マイクロサービスのボトルネック,障害箇所の特定(2) 第56回 AWS X-Rayによる分散トレーシング―マイクロサービスのボトルネック,障害箇所の特定(3) 使ってみる Perl Runtime だけでなくX-Ray SDK 側でも対応が必要だったので、プルリクエストを送って取り込んでもらいました。 このプルリクエストがマージされた最新の AWS::XRay を Perl Runtime Layer にプリインストールしたので、あなたのアプリケーションですぐに使えます。 例えばこんな感じのコードを書いて、 use utf8; use warnings; use strict; use AWS::XRay qw/ capture /; sub handle { my ($payload, $context) = @_; capture "myApp" => sub { capture "hogehoge" => sub { sleep 1; }; capture "fugafura" => sub { my $segment = shift; $segment->{metadata} = $payload; }; }; return +{"hello" => "lambda"}; } 1; Layer に X-Rayに対応した最新の Perl Runtime arn:aws:lambda:ap-northeast-1:445285296882:layer:perl-5-30-runtime:3 を追加、 マネージドコンソールの「Debugging and error handling」セクションにある「Enable AWS X-Ray」を有効化し、実行してみます。

Jul 24, 2019 - 2 minute read - Comments - go golang

Goのバイナリに静的ファイルを埋め込むツール assets-life を書いた

日本語の Go コミュニティだと go-bindata (なんか乗っ取り騒動とか色々あってメンテナンスされてない), go-assets (最近メンテナンス滞りがち) が有名(要出典)なやつです。 これらのライブラリに関してたくさん日本語記事が書かれて、今もたくさん検索に引っかかるのですが、残念ながら最近はメンテナンスが滞っています。 最近は statik の名前もよく見るようになりました。 その他は Resource Embedding - Awesome Go からどうぞ。 で、まあ、今回も完全に車輪の再発明なんですが、他の実装には色々と思うところがあり書いてみました。 shogo82148/assets-life USAGE なにはともあれ、まずは go get してきます。 $ go get github.com/shogo82148/assets-life assets-life というコマンドがインストールされるので、 バイナリに組み込みたいディレクトリと出力先を指定します。 $ assets-life /path/to/your/project/public public 出力先のディレクトリは Go のパッケージとしてインポートできるようになってます。 Root という変数のなかにファイルが埋め込まれており、http.FileSystem インターフェースを介してアクセスできます。 import ( "net/http" "example.com/your/project/public" ) func main() { http.Handle("/", http.FileServer(public.Root)) http.ListenAndServe(":8080", nil) } 特長 コードの再生成にコマンドのインストールが不要 これが一番の特長です。 バイナリにファイルを埋め込む都合上、静的ファイルを修正した場合にコードの再生成が必要です。 assets-life は go:generate ディレクティブを埋め込んだコードを出力するので、コードの再生成は go generate でできます。 # /path/to/your/project/public に修正を加える # コードの再生を行う $ go generate example.

Jul 22, 2019 - 3 minute read - Comments - go golang

Goで指数的バックオフをやってくれるgo-retryを書いた

完全に車輪の再発明なんですが、他の実装には色々と思うところがあり書いてみました。 shogo82148/go-retry MOTIVATION カッコいいインターフェースが欲しい インターフェースは lestrrat さんのこの資料を参考にしています。 GoらしいAPIを求める旅路 (Go Conference 2018 Spring) from lestrrat 「これ、Loop Condition だ」のあたりで、なるほど!と思ってインターフェースを真似てみました。 このインターフェースに沿って、lestrratさん自身が実装した lestrrat-go/backoff があります。 しかし、個人的にちょっと実装が複雑だなと感じたので、もうちょっとシンプルに書けないかとやってみました。 Context サポート 先行実装たちは Context がGoに取り込まれる前からあるので、 Contextに対応したインターフェースが後付だったり、 そもそもContextに対応していなかったりします。 Context未対応の Go 1.5 はすでにサポート対象外なので、もう Context が存在しない実行環境は考えなくてよいはずです。 SYNOPSIS Loop Condition Interface 使い方は lestrrat-go/backoff と大体一緒。 指数的バックオフに必要な各種パラメーターをポリシーとして与え、リトライのためのループを回します。 // 指数的バックオフの各種パラメーターをポリシーとして定義 var policy = retry.Policy{ // 初回待ち時間 MinDelay: 100 * time.Millisecond, // 最大待ち時間 MaxDelay: time.Second, // 最大試行回数 MaxCount: 10, } func DoSomethingWithRetry(ctx context.

Jul 16, 2019 - 2 minute read - Comments - perl aws lambda

AWS SDK for Perl Lambda Layerを公開しました

ハイラルからこんにちは。 AWS LambdaでCGIを蘇らせる で作成した Perl Custom Runtime 用の AWS Lambda Layer ですが、 中でイベントのハンドリングをしているモジュールを AWS::Lambda として CPAN で公開したところ、 AWS SDKを入れて欲しい との要望が来ました。 完全にネタとして作成したモジュールですが、いるんですね使う人。 というわけで AWS SDK を含んだ AWS Lambda Layer を公開しました。 使い方 公開レイヤーを使う AWS公式ではPerl用のSDKは提供していないので、Pawsという非公式SDKを使いました。 何も考えずにテキトウにインストールしてみたらSDKだけで121MBありました。 Perl本体が85MBなのでSDKのほうがでかい。 AWS Lambdaで作成できる関数は250MBが上限なので、流石に半分SDKに持っていかれるのはつらかろうと、Perl本体とは別のレイヤーに分けてあります。 レイヤーは最大5つまで登録できるので、Perl本体(例: arn:aws:lambda:ap-northeast-1:445285296882:layer:perl-5-30-runtime:2 )に加えて 以下のレイヤーを追加することで、Paws を呼び出すことができるようになります。 arn:aws:lambda:ap-east-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ap-northeast-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ap-northeast-2:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ap-south-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ap-southeast-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ap-southeast-2:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:ca-central-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:eu-central-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:eu-west-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:eu-west-2:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:eu-west-3:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:sa-east-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:us-east-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:us-east-2:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:us-west-1:445285296882:layer:perl-5-30-paws:1 arn:aws:lambda:us-west-2:445285296882:layer:perl-5-30-paws:1 いつの間にかマネージドコンソールから編集ができるようになっていたので、開発がはかどりますね。 カスタムランタイムでもAWS Lambdaのマネージドコンソールから内容の編集ができる・・・? Perl も編集できるぞ・・・ pic.twitter.com/4228rG0hca — Ichinose Shogo (@shogo82148) July 16, 2019 ZIP アーカイブを使う ビルド済みのZIPアーカイブも公開しています。 以下のURLを指定して新規レイヤーを作成することで利用できます。

Jul 2, 2019 - 1 minute read - Comments - go golang perl php ruby

GoのバイナリをRubyスクリプトとしても扱う

$ ruby --help Usage: ruby [switches] [--] [programfile] [arguments] (中略) -x[directory] strip off text before #!ruby line and perhaps cd to directory (後略) なんか Ruby にも -x あるらしいので。 package main import ( "fmt" "runtime" ) const script = ` #!ruby puts "Hello Ruby World!!\n" __END__ ` func init() { runtime.KeepAlive([]byte(script)) } func main() { fmt.Println("This is Go world!!") } はい。 $ go build -o main main.go $ ./main This is Go world!

May 27, 2019 - 1 minute read - Comments - go golang

サーバーの時刻を伝える time wellknown uri を実装してみた

インターネットをさまよっていたら、 /.well-known/time の存在を知ったので、雑に実装してみました。 使い方 うまいこと共存できそうだったので、HTTP/WebSocketで時刻同期するWebNTPを書いた で作成した WebNTP の一部として実装してあります。 shogo82148/go-webntp $ go get github.com/shogo82148/go-webntp/cmd/webntp $ webntp -serve :8080 $ curl -I localhost:8080/.well-known/time HTTP/1.1 204 No Content X-Httpstime: 1558915632.285965 Date: Mon, 27 May 2019 00:07:12 GMT 仕様 HTTPには「予約済みのURI」というものが定義されています。(RFC5785)。 Well-Known URIs Let’s Encrypt でドメインの所有権確認に使用される ACMEプロトコル(RFC8555) や、 Mastodon のユーザーディスカバリーに使用する WebFinger(RFC7033)等々、 近年話題になったサービスの裏方で使われています。 /.well-known/acme-challenge ACMEプロトコル(RFC8555) /.well-known/webfinger WebFinger(RFC7033) Time over HTTPS も Well-Known URIs を利用するプロトコルのひとつです。 /.well-known/time Time over HTTPS specification 仕様としては非常に単純で、サーバー側は HTTP の HEAD に対して、 Date ヘッダーをつけたリクエストを返すだけ。 より高精度な時刻を得るために X-HTTPSTIME ヘッダーに秒未満の情報を入れた Unix タイムスタンプ を返すこともできます。

Apr 17, 2019 - 2 minute read - Comments - go golang aws cloudformation mackerelio

CloudFormationのMackerel用インテグレーションを作ってる話

Mackerel は mkr コマンドを用いて cli から操作ができます。 mkr コマンドを用いると 監視ルールを GitHub で管理 したり、 カスタムダッシュボードを管理したり、といったことができます。 しかし、個人的に以下のような不満があります。 サービス、ロール、ホスト、新ダッシュボード等々、監視設定以外のリソースに対応していない 旧ダッシュボードは対応しているんだけど、新ダッシュボード対応がまだ 新ダッシュボードのUIは使いやすくてすごくいいんだけど、コピペや一斉置換ができないので、テキストで管理したい 出力がJSONなのつらい JSON手で書くの難しくないですか? メトリックスの送信設定と監視設定の管理が別になってしまう カスタムメトリックス送っているのに監視設定を忘れた、みたいなことが起こる メトリックスの送信設定については、以前 サーバーレスでCloudWatchメトリクスをMackerelに転送する で CloudFormation上での管理を実現しました。 ここにさらに Mackerel の監視設定を追加できれば、最強なのでは?とやってみました。 例 あれこれ説明する前に例を見てもらったほうがわかりやすいと思うので、こんなことができますよ、という設定例から。 例1: レスポンスタイムの99%パーセンタイルを監視する Mackerel の AWSインテグレーション は ALB に対応していますが、 レスポンスタイムのメトリックスは平均レスポンスタイムだけです。 「平均」は代表的な統計値ですが、全体としては速いんだけど一部のリクエストだけ遅い、という状況を見逃してしまいます。 レスポンスタイムの大まかな分布をパーセンタイルで把握したい、ということはよくありますよね? (K社でZabbixを使って監視していたときによくお世話になった) 今回作ったインテグレーションを使えば、以下のように「Mackerelのサービス定義」「メトリックスの転送設定」「監視設定」が CloudFormation のテンプレートとして表現できます。 AWSTemplateFormatVersion:2010-09-09# Type: Mackerel::* を使うためのおまじないTransform:- AWS::Serverless-2016-10-31- Mackerel- JSONStringResources:MackerelService:Type:Mackerel::ServiceProperties:Name:"awesome-service"# メトリックスを転送する Lambda 関数MetricsForwarder:Type:AWS::Serverless::ApplicationProperties:Location:ApplicationId:arn:aws:serverlessrepo:us-east-1:445285296882:applications/mackerel-cloudwatch-forwarderSemanticVersion:0.0.9Parameters:ParameterName:"/api-keys/api.mackerelio.com/headers/X-Api-Key"ForwardSettings:!GetAtt MetricsForwarderSettings.Query# CloudWatch から99%パーセンタイルを取得するMetricsForwarderSettings:Type:JSON::StringProperties:Query:- service:!GetAtt MackerelService.

Feb 28, 2019 - 1 minute read - Comments -

新元号の候補約4510万件が漏洩!!

平成の次の元号候補、4510万4656件の漏洩が確認された。 テキスト形式 (301MB) gz圧縮版 (108MB) 政府は「新元号、情報管理を徹底へ 漏洩なら差し替え」との方針を示しており、 早急な差し替え対応を行うと思われる。 2019-04-01 追記: $ curl -s https://t.co/OCaFAriJIt | cat -n | grep 令和 726041令和 無事漏洩してました!!! — Ichinose Shogo (@shogo82148) 2019年4月1日 追記ここまで と、まあ、二番煎じなわけですが。 新元号は漏洩すると変更されるということなので常用漢字2文字の全組み合わせ約228万通りをすべて記載したテキストファイルを作成しました。漏洩させていきましょう。https://t.co/G06utDbgka pic.twitter.com/8UcPDqNdXo — いんぐらむ (@kazuokiriyama) 2019年2月26日 ただ、このツイートのリプライのもあるとおり漏洩漏れがあるようですし、 新元号に使われる可能性のある漢字は常用漢字ではない可能性だってあると僕は考えいます。 だって、お国のやることですからね。下手したら改元に合わせて「常用漢字の見直しもやる」ということだって考えられます。 というわけで、僕は ShiftJIS, EUC-JP で表現可能な文字列まで範囲を広げることにしました。 Unicodeへの統一が進んでいるとはいえ、 ShiftJIS, ECU-JP で動いているレガシーなシステムもあるでしょうし、この範囲に収めるだろうなという予想です。 ShiftJISからUnicodeへの変換には規則性がないので、変換テーブルを使う必要があります。 Goのコードを漁った ら以下の変換表を参照していたので、これを利用しました。 https://encoding.spec.whatwg.org/index-jis0208.txt 非漢字も含まれているので、雑に漢字を絞ったあと、 curl https://encoding.spec.whatwg.org/index-jis0208.txt | grep CJK | cut -f3 | cut -d' ' -f1 | sort | uniq > kanji.

Feb 12, 2019 - 2 minute read - Comments - go golang aws lambda

外部サービスでもIAM Roleで認証がしたい!

背景 外部サービスのAPIやWebHookを叩くときには、多くの場合 API トークンが必要になります。 もちろん API トークン無しでも叩けるサービスはありますが、GitHub APIのようにトークン無しではリクエスト数が大きく制限されたり、 一部機能が制限されてしまう場合があります。 外部連携サービスが増えてくると、このAPIトークンをどうやって管理するかが問題になってきます。 プロダクションに投入されているサービスは普通複数のサーバーから構成されており、各サーバーにAPIトークンを配布するのはちょっと面倒です。 この問題に対して、以下のようなことが行われて来ました。 プライベートネットワークからのアクセスに限定した Proxy を立てる APIトークンの管理は Proxy に任せる DevOpsが注目され、Slackの利用が広まったころに、このような目的で書かれたProxyサーバーがよく登場しました。 社内IRCをSlackに移行した時にやったこと この記事で紹介されている kayac/nopaste Slackboard〜Slackプロキシサーバ in Go〜 Slackプロキシサーバ〜slackboard〜を利用したメルカリのSlack活用法 App::Ikachan - 様々なサーバのバッチ処理の結果等を IRC のチャンネルに通知するサーバ (IRCはHTTPで動いているわけではないし、大本の目的もコネクション維持だけど、認証も代理でやってくれる) しかし、これらのサーバーはSlack専用だったりIRC専用だったりします。 Slackだけじゃなくって、GitHubにコメント登録したり、Mackerelのグラフアノテーションを投稿したり、 他のサービスとも連携したい! 最近はどんなAPIもHTTPで提供されるようになったので(IRCは・・・ウッ・・・そんなのなかった)、もっと汎用的に書けるのではとやってみました。 実装 APIトークンの保管場所として AWS Systems Manager Parameter Store を採用しました。 Parameter Store からAPIトークンを取り出す部分と、実際にAPIを叩く部分は AWS Lambda を使用します。 各サーバーに Forward Proxy デーモンを立てておき、APIを使いたいアプリケーションはこのProxyを経由するようにします。 この図ではEC2インスタンスを例にしていますが、IAM Roleを付与できるAWSのサービスであれば何でも (ECS, Lambda, CodeBuild, etc.) APIにアクセスすることができます。

Feb 7, 2019 - 3 minute read - Comments - acme python aws lambda

Let's Encrypt の証明書取得を AWS Lambda でやってみた

背景 ここ数年で暗号化されていないHTTPは減り、常時TLSが当たり前になってきました。 公開用のページはもちろん、開発段階のページでもTLSは必須です。 普段はAWS上で開発をしているので、AWS Certificate Managerを利用することが多いのですが、 ちょっとしたお遊びにELBやCloudFormationを使うのはオーバーキルです。 そこで EC2 にもインストールできて、無料で使える Let’s Encrypt を使って証明書を発行することを考えました。 Let’s Encrypt で発行できる証明書は期間が90日と短く、60日ごとの自動更新が推奨されています。 証明局とAPIとAPIクライアントの実装例は提供するから、あとの自動化部分は自前で頑張ってねという感じなので、自動化部分を頑張らないといけません。 今回は実行環境として AWS Labda、ACME(Automatic Certificate Management Environment)クライアントとして certbot、 認証方法に dns-01、認証に必要なDNSレコードの書き換えに AWS Route 53 を使用する、という構成にしました。 ソースコードをGitHubに挙げたのと、前回と同様に AWS Serverless Application Repository へ上げたので、ぜひご利用ください。 shogo82148/acme-cert-updater shogo82148/acme-cert-updater on AWS Serverless Application Repository 関連手法 Amazon Linux 2 に certbot をインストールして使う Amazon Linux 2 のドキュメントに TLS 対応のウェブサーバーを立てる例が載っています。 Let’s Encrypt で証明書を取る方法も紹介されているので、まずはこれを利用することを考えました。 付録: Amazon Linux 2 での Let’s Encrypt と Certbot の使用 - チュートリアル: Amazon Linux 2 で SSL/TLS を使用できるように Apache ウェブサーバーを設定する この方法は以下の理由から見送りました。