TTTAttributedLabelでUILabelの一部をリンクにする

利用規約に同意してログインする」的な UILabel で、タップしたら遷移するようにする。TTTAttributedLabel を使う。

Podfile に TTTAttributedLabel を追加

# Podfile

pod 'TTTAttributedLabel'

InterfaceBuilder

UILabel を配置するのと同じように、適当に配置する。Class を、 TTTAttributedLabel にしておく。

Linkをコードで設定する

var label : TTTAttributedLabel!

的なプロパティが設定してあるという前提で、文字列は「利用規約に同意してログインする」になってるとします。

Linkの設定

class SomeViewController: UIViewController, TTTAttributedLabelDelegate {

// ...

label.delegate = self
        
label.linkAttributes = [
    kCTForegroundColorAttributeName: UIColor.grayColor(),
    NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleNone.rawValue
]
        
legalLabel.activeLinkAttributes = [
    kCTForegroundColorAttributeName: UIColor.lightGrayColor(),
]
        
if let text = legalLabel.text {
    let termsRange = NSString(string: text).rangeOfString("利用規約")
    legalLabel.addLinkToURL(termsUrl, withRange: termsRange)
}

とする。 linkedAttributes でリンクが設定された文字列の見た目を規定して、activeLinkAttributes でリンクがタップされている間の文字列の見た目を設定できる。

delegateメソッドの設定

// MARK: TTTAttributedLabelDelegate
    
func attributedLabel(label: TTTAttributedLabel!, didSelectLinkWithURL url: NSURL!) {
    if url == termsUrl {
        // ここで某かの処理をすればOK
        performSegueWithIdentifier("goToTerms", sender: nil)
    }
}

WKWebViewでnetworkActivityIndicatorVisibleを表示

(追記) iOS10 になって色々変わっていたので、書き直した。

networkActivityIndicatorVisible (iPhoneの上部のステータスバーで読込中にぐるぐるさせるやつ) を表示する方法。UIWebView は、html,js,css,画像などの区別がつかなくて結構たいへんだったけど、そういうの気にせずだいぶ楽に実装できる。

Controller に直接書くパターン

KVOを監視する

Controller に直接書く場合は、viewDidLoad とかで、addObserver する。

var webView : WKWebView!

的なプロパティが設定してあるという前提で

webView.addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)

とする。

controller がなくなるタイミングで

webView.removeObserver(self, forKeyPath: "loading")

を呼ぶのを忘れずに。

KVOの変化にフックさせる

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == "loading" {
        UIApplication.sharedApplication().networkActivityIndicatorVisible = webView.loading
    }
}

loading状態が変わると、このメソッドが呼ばれるので、そのタイミングで webView.loading (BOOL) がどうなっているのかを見るだけで良い。

WKWebView のサブクラスを作るパターン

WKWebView を使って、特に何もせず networkActivityIndicatorVisible だけを変えたい場合は、下記のようなサブクラスを作って WKWebView を呼んでるところに置き換えれば良い。

import UIKit
import WebKit

class CustomWebView: WKWebView {
    init() {
        super.init(frame: CGRectZero, configuration: WKWebViewConfiguration())
        self.translatesAutoresizingMaskIntoConstraints = false

        addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)
    }
    
    deinit {
        removeObserver(self, forKeyPath: "loading")
    }
    
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "loading" {
            UIApplication.sharedApplication().networkActivityIndicatorVisible = loading
        }
    }
}

使い方

全画面表示で、特定のURLを読み込むというもの。

let webView = CustomWebView()

view.addSubview(webView)
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["webView": webView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["webView": webView]))

webView.loadRequest(NSURL(string : "https://memo.ecp.plus/"))

AJAXでファイルダウンロード

バイナリでもテキストでも、AJAX でリクエストしたら JavaScript で受けることになるので、ブラウザにファイルをダウンロードさせるように処理を作る必要がある。

Blob オブジェクトはファイルに似たオブジェクトで、immutable な生データです。データを表す blob は必ずしも JavaScript ネイティブなフォーマットではありません。File インターフェースは Blob を基礎にしており、その機能を継承する一方で、ユーザのシステム上のファイルをサポートするための機能を拡張しています。

https://developer.mozilla.org/ja/docs/Web/API/Blob

とのことです。レスポンスから Blob オブジェクトを作って、createObjectURL すれば、ダウンロード可能なURLを生成する事ができます。

よくありがちな、CSVデータを管理画面からダウンロードさせたい、みたいなパターンを jQuery + ES6 で書いた場合の例。

IEの場合、IE10以上であれば msSaveBlob という、Blob をダウンロードするという機能を使うことが出来る。それ以外のブラウザは、createObjectURL を使って URL を生成したら、a タグの href にセットしてそれにクリックイベントを発火させるという方法で実現できます。

$.ajax({
  url: 'https://example.com/api/admin/users.csv',
  type: 'GET',
}).done((data, status, jqXHR) => {
  let downloadData = new Blob([data], {type: 'text/csv'});
  let filename = 'users.csv'

  if (window.navigator.msSaveBlob) {
    window.navigator.msSaveBlob(downloadData, filename); // IE用
  } else {
    let downloadUrl  = (window.URL || window.webkitURL).createObjectURL(downloadData);
    let link = document.createElement('a');
    link.href = downloadUrl;
    link.download = filename;
    link.click();
    (window.URL || window.webkitURL).revokeObjectURL(downloadUrl);
  }
}).fail((data, status, jqXHR) => {
  alert('OMG!');
});

HamlでTextarea(Rails)

Rails + Haml で textarea を出力しようとすると、textarea 内に表示しようとしたテキストまでインデントされてしまう。

find_and_preserve というヘルパーメソッドを使えば、中身のインデントは保持されるようだ。

= find_and_preserve(f.text_area)

Simple Form を使ってる場合も、同様にいける。

= find_and_preserve(f.input :comment, as: :text)

参考URL: How do I stop Haml from indenting the contents of my pre and textarea tags?

MacでIEの確認をリモートで行う

IEの確認で、Azure の RemoteIE というのが知らないうちに出てた。これだと、手元に virtual machines のイメージを置いておかなくて良いので、ディスク容量の節約になる。

登録すれば無料で使えるようだが、inactive な時間が10分続くか、 active な状態でも60分経過すると切断される制限がある。短時間の確認なら問題無さそうだが、長時間の確認は繋ぎ直す必要がありそう。

まずは、RemoteIE で Register for access して、自分の Region を選ぶ。日本なら East Asia が良い。

Mac で使う場合は、Microsoft Remote Desktop アプリを App Store からダウンロードして、Azure RemoteApp というところをクリックすると、ログイン画面になるので、ログインする。 すると、InternetExplorer(email: iewebeco@microsoft.com) という Invitations があるので、チェックを入れると自動的に起動する。いきなり IE の画面が開いているので検証できる。

kswapd0 プロセスが CPU を食ってた

Load average が高いので、top でプロセスを見たら kswapd0 というプロセスが CPU を使いまくってた。

メモリがスワップアウトしたときに、ディスクに書き込んだりするプロセスらしいけれど、貧弱なサーバだとその処理が重くて Load average が上がってサーバが遅くなって…のループでつらそうだった。

vm.drop_caches の値を変えることで、メモリ内にあるキャッシュを削除して、このプロセスがやるべきことをなくしてあげれば CPU は解放されるようだ。

例えば、ページキャッシュだけ解放するときは、下記のようにする。sync をして、強制的にキャッシュの内容をディスクに書き込んだ後に実行します。

sudo sync
sudo /sbin/sysctl -w vm.drop_caches=1

数字は、下記の中から適切なものを選ぶ必要がある。

  • [0] 初期値
  • [1] ページキャッシュ解放
  • [2] dentry、inode 解放
  • [3] ページキャッシュ、dentry、inode 解放

Linux におけるメモリの解放

なお、0 を指定するとエラーになって設定が出来ないのだが、よく分かっていない。

$ sudo /sbin/sysctl -w vm.drop_caches=0
sysctl: setting key "vm.drop_caches": Invalid argument
vm.drop_caches = 0

Ubuntuを14.10->15.10へアップデート

Ubuntuを14.10->15.10へアップデートした。

sudo vi /etc/update-manager/release-upgrades

として、Prompt=ltsとなっているところを、Prompt=normalに変更する。

[DEFAULT]
Prompt=normal

その後、下記コマンドを実行すればアップグレードが対話形式で始まるので、表示されるメッセージを見ながら進めればよい。

sudo do-release-upgrade

AWS API Gateway で ifconfig API を作ってみる

サーバが自分自身のグローバルIPアドレスを調べるとき面倒なことがよくあるので、API Gateway を使って ifconfig のようなことをする。単純に、リクエストしてきたIPアドレスを返すだけ。(こういうサービスは他にもあるけど、レスポンスが遅めだったり、信用できるか分からなかったりするので、自分で作るのが安全そう)

curl https://ip.ecp.plus

としたら自分のIPアドレスが返るというのがゴール。ブラウザで見ても同じ。ちなみに↑はもう動いているのでご自由にお使いください。

最初、API Gateway -> Lambda として、Lambda に IPアドレスを渡して、Lambda はそれを返して、API Gateway はレスポンスをそのままスルーする。というのをやったが、実は Lambda なしで出来たようだ。

はじめ Lambda を使ったバージョンをやったので、両方書く。

API Gateway の設定

Create Method

URLは短くしたいので、ドメイン直下をGETしたときに返したい。 / に対して Create Method で GET を指定する。

Method Request は認証などしないのでそのまま。

/ - GET - Method Execution

API Gateway にアクセスしてきた IP アドレスは、下記のようにして取れる。

{
  "ipaddress" : "$context.identity.sourceIp"
}

のだが、API Gateway のデフォルトで割り振られる URL は非常に長く、自分のドメインで使いたい。Custom Domain Names を使うためには、TLS の証明書が必要なのだが、お手軽さが無いのでやめた。既に動いている Caddy でリクエストを転送することにした。

ただ、そうするとリクエスト元のIPアドレスが Caddy が動いているサーバの IPアドレスになってしまうため、ヘッダーの X-Forwarded-For を見ることにする。ここの先頭に、オリジナルのIPアドレスが入ってる。

{
  "ipaddress" : "$input.params().header.get('X-Forwarded-For')"
}

Lambda

ipaddress として渡ってきたデータの中から、一番最初のIPアドレスを返すだけの処理を書く。

exports.handler = function(event, context) {
    context.succeed([event.ipaddress.split(/\s*,\s*/)[0], "\n"].join(''));
};

/ - GET - Integration Response

再び API Gateway に戻ってきて、レスポンスの加工をする。一見、Output passthrough で良さそうだが、これだとダブルクオーテーションで囲まれたものが返ってしまう。

Content-Type: application/json で Mapping Template として下記のようにする。

$input.path('$')

これでAWS側の実装は完了。

Caddy の設定

ip.ecp.plus に来たものを API Gateway に飛ばす。API Gateway 側で GET / を叩くために、転送先の末尾にスラッシュを忘れず付ける必要がある。

ip.ecp.plus {
  proxy / https://EXAMPLE.execute-api.ap-northeast-1.amazonaws.com/prod/
}

とりあえずここまでで完成。

だが、Lambda がどう見てもあまり意味がなさそうだったので、API Gateway だけで出来ないか見ていたところ、開発中に使う用途と思っていた Mock Integration を使えば出来た。

API Gateway の設定(再)

/ - GET - Method Execution

Integration type として Mock Integration を選択。Mapping template として

{
  "statusCode" : 200
}

のようなものが定義されてるが、これがないと勝手にエラーにされてしまうのでそのままにしておく。

/ - GET - Integration Response

どうやら、Response 側でも、リクエストで渡ってきた値がそのまま取れるようなので、こちらにIPアドレスを返す処理を書けば良い。

#set($ipAddresses = $input.params().header.get('X-Forwarded-For').split(','))
$ipAddresses[0]
#set($dummy = "dummy")

最後の行でよくわからないことをしているが、レスポンスの末尾に改行を入れたいためこうしている。"\n" をどうにか入れたかったが、うまく行かずバッドノウハウ的な解決方法になっている…。本当は良い方法があるはずだ。

ここまでで完成。

尤も、こんな単純なものなら Caddy 動かしてるサーバで処理しろよという感じだけれど、最近 API Gateway にハマっているので作ってみた。API Gateway 単体で動かないと、Caddy のサーバが落ちたときに使えなくて激しく意味がないが、Custom Domain Names の設定までやるのは面倒であった。Route53 使ってたらシームレスに連携出来たりすれば良いのに、と思った。

(追記)CloudFront を使ってサーバレスに出来た

その後、Caddy の代わりに CloudFront を使えば、TLS証明書も無料で、好きなドメインで出来ることが分かった。

CloudFront の画面から、Create Distribution -> Web の Get Started で、作成画面へ入る。

Origin Domain Name は、API Gateway の Invoke URL を指定する。https:// を付けても勝手に外してくれるので、URLコピペで良い。stage名は消す。つまりドメイン部分だけを記述する。 Origin Path は、stage名を入れる。 prod なら /prod とする。

あとは項目を読みながら設定すれば良い。CloudFront は独自ドメインのTLS証明書が無料なので、とてもありがたい。注意点としては、 CloudFront にキャッシュされると前に実行した人のIPアドレスが返ってしまうので、キャッシュさせないようにしなければいけない。 Behaviors のタブで、初期から存在しているものを編集して、Object Caching : Customizeとして、Minimum TTL : 0, Maximum TTL : 0, Default TTL : 0 とすれば良い。

これで、自己管理するインフラ無しで、当初のやりたかったことが出来た。

API Gateway から Export した Swagger 用の YAML

Let's Encrypt を Caddy で簡単に使う

Caddy という web server がデフォルトTLSというポリシーで、Let’s Encrypt を簡単に設定出来て、証明書の自動更新をしてくれるようだったので使ってみた。Let’s Encrypt は無料でTLS証明書使えるサービスです。

VultrのVPSを使ってみたら、DocumentsにCaddyのインストールについて載ってたので知りました。Vultr の Tokyo リージョン良さそうですね。

Caddy のインストール

https://caddyserver.com/download から、ダウンロードするとバイナリが落ちてくるので、それを実行するだけです。バイナリ生成時に、Select Features として、追加機能を入れる事ができます。

Caddy の設定

/path/to/caddy.conf

hoge.example.com {
  tls hoge@example.com
}

最小構成だと、ドメインに対して自分のメールアドレスを設定したら動くみたいです。ecpplus.net のドメインだと動いたけれど、 ecp.plus のドメインだと動かなかった。あまり調べていないけれど、Let’s Encrypt 側で何かやる必要がありそう。

Caddy の起動

80, 443 ポートをListenするので、setcap しておくか、sudo での実行が必要です。

sudo setcap cap_net_bind_service=+ep /path/to/caddy
/path/to/caddy --conf /path/to/caddy.conf -agree=true

-agree は、Agree to Let’s Encrypt Subscriber Agreement で、-emailは Default Let’s Encrypt account email address とのことです。

これで、 https://hoge.example.com としてサーバが立ち上がります。http でアクセスしても自動的に https に遷移します。

Caddy のコマンド引数

$ caddy --help
Usage of caddy:
  -agree=false: Agree to Let's Encrypt Subscriber Agreement
  -ca="https://acme-v01.api.letsencrypt.org/directory": Certificate authority ACME server
  -conf="": Configuration file to use (default=Caddyfile)
  -cpu="100%": CPU cap
  -email="": Default Let's Encrypt account email address
  -grace=5s: Maximum duration of graceful shutdown
  -host="": Default host
  -http2=true: HTTP/2 support
  -log="": Process log file
  -pidfile="": Path to write pid file
  -port="2015": Default port
  -quiet=false: Quiet mode (no initialization output)
  -revoke="": Hostname for which to revoke the certificate
  -root=".": Root path to default site
  -version=false: Show version

Caddy の機能

https://caddyserver.com/docs に、ドキュメントがあります。

気になった機能

  • markdown で、Caddy 自体が Markdown を HTML に変換してくれる。テンプレートの指定もできる。デフォルトで入ってるのは面白いかも。
  • gitで、git push で自動的にサイト更新出来るので、markdown と合わせてお手軽なサイトに便利そう。
  • gzip は使えるぽいですが、キャッシュ系の機能はまだないっぽいので、現状だと別で用意する必要がありそうです。
  • fastcgi で指定すれば、裏でWordpressとか動かしても大丈夫そうです。
  • proxy でリバースプロキシの設定もできるので、Rails とか裏においても大丈夫そうです。
  • websocket で、WebSocket のコネクションが張られたときに実行するコマンドが指定できる。
  • startup, shutdown で、起動・停止時に任意のコマンドを実行できる。例えば Rails のアプリケーションサーバを立ち上げるとか。

安いTLS証明書使ってたけど、失効したら乗り換えても良いかもという感じがしました。

Rails5 で使う場合

ActionCable 試してないけど、Websocket の設定も出来るので多分いけそう。とりあえず、 /assets /system だけ Caddy で返して、バックエンドは Unicorn とか Puma とかを 9292 番ポート動かしてる場合の設定例。proxy_header を適切に設定しないと、 redirect_to とかさせたときにおかしなことになるので注意。

example.com {
  gzip
  tls caddy@example.com
  log /var/log/access.log

  root /var/www/rails_root/current/public

  proxy / localhost:9292 {
    proxy_header Host {host}
    proxy_header X-Real-IP {remote}
    proxy_header X-Forwarded-Proto {scheme}
    except /assets /system
  }
}

Daemonize

caddy 自身ではデーモンとして起動出来ないようだ。 supervisord を使って daemon にしてみた。

/etc/supervisord.d/caddy.ini

[program:caddy]
command=/usr/local/bin/caddy -conf="/etc/Caddyfile" -agree=true
directory=/var/www/rails_root/current/public
autostart=true
user=root
redirect_stderr=true
stdout_logfile=/var/log/caddy.log
stderr_logfile=/var/log/caddyerr.log

/etc/supervisord.conf

[supervisord]
minfds=4096

caddy を起動するとき、少なくとも ulimit -n 4096 にしろと言われるので、supervisord の方で指定しておくと良い。

Heroku で exiftool を使う

Railsが動いているサーバで exiftool を使った時のメモ。buildpacks を使う。

erhhung/heroku-buildpack-exiftool を使った。

heroku buildpacks:add heroku/ruby
heroku buildpacks:add https://github.com/erhhung/heroku-buildpack-exiftool.git

このあと git push heroku master 等でデプロイすると、exiftool がインストールされて PATH が設定され、exiftool とすれば使えるようになる。

buildpacks を設定しないと、デフォルトで ruby などの buildpacks が裏で使われているようで、追加する分だけ指定してしまうと、元々動いていた ruby 等が動かなくなってしまうので注意が必要だった。

Load Average をワンライナーで取るコマンド

uptime コマンドから、load averages の直近1分の値をワンライナーで取る。uptime コマンド(CentOS7で実行)は、load average: の後に過去1分間、5分間、15分間のロードアベレージが出る。

Linux の出力例

$ uptime
12:53:16 up  3:26,  1 user,  load average: 0.00, 0.03, 0.61

OSX の出力例

$ uptime
23:11  up 11:10, 1 users, load averages: 1.85 1.70 2.15

awk の $1 を、$2,$3とすると過去5分、15分の値になる。OSXでuptimeすると、load average: (最後のsがない) のと、数字がLinuxはカンマ付きでOSXはカンマなしなので、下記のような正規表現で差異を吸収する。

uptime | sed -E 's/.*load averages?:(.*)/\1/' | awk '{print $1}' | sed -e 's/,//'

AWSCognitoで認証情報の自動取得が動くようになってた

今まで iOS版の Cognito 使ってたのだが、60分経ったら credential が無効になって認証エラーになってしまうという問題があった。開発者は何もしなくても裏で勝手に refresh される、と書いてあったけど実際はされていなかったように見えたが(そういう報告をフォーラムに上げてる人も何人かいた)、直ってようやく気軽に使えそうな感じがする。 AWS Cognito の iOS SDK が 2.3.5 になって、修正された模様。

iOS版は、AWS MobileHub でテンプレートを作って試してみるのが手っ取り早かった。一番良いと思うのが、Cognito で認証してるときのid的なものをIAM側で変数として埋め込めるので、それと AWS APIGateway の URL をマッピングさせると、REST API と相性が良すぎる。

APIGateway は、Swagger で書いてインポートすると良い感じだが、完全に Swagger のフォーマットだけで出来るのかはよくわからない。APIGateway 側からエクスポートするとき、APIGateway 用の拡張情報込みのエクスポートというのが出来るので、それを使えば良いのかもしれない。

APIGateway のバックエンドに S3, DynamoDB, Lambda を使ってみたところ、ec2 (Rails)でやってた処理を大部分移すことが出来た。APIGateway を挟んでおけば、複雑なことをやりたくなったら、URL単位で処理を Rails に持ってくればよいのだが、Rails外にある様々な処理についてのテストをどのように書くかというのが悩みである。

LinuxでSwapファイルを作る

AWS で t2.nano, t2.micro とか使っていると、コンパイルするとき等にメモリがよく足りなくなる。Swap ファイルの作り方をメモっておく。

2GBのSwap領域を作る

初期状態

$ free
              total        used        free      shared  buff/cache   available
Mem:         501016      205836      187680         524      107500      214100
Swap:             0           0           0

# fallocate -l 2g /swapfile
# chmod 600 /swapfile
# mkswap /swapfile
# swapon /swapfile

その後(Rubyビルド中…)

free
              total        used        free      shared  buff/cache   available
Mem:         501016      413360       42420         536       45236       28164
Swap:       2097148      143324     1953824

再起動後も有効にする

/etc/fstab に追記する。

/swapfile  swap   swap    defaults   0 0

EC2 の g2.2xlarge の Ubuntu 14.04 に CUDA7.5 をインストール

AWS の g2.2xlarge インスタンスで Ubuntu14.04 を動かして、CUDA 7.5 をインストールした時のメモ。多分そのままで動く。

wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_7.5-18_amd64.deb

sudo locale-gen ja_JP.UTF-8
sudo dpkg -i cuda-repo-ubuntu1404_7.5-18_amd64.deb

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y opencl-headers build-essential protobuf-compiler \
    libprotoc-dev libboost-all-dev libleveldb-dev hdf5-tools libhdf5-serial-dev \
    libopencv-core-dev  libopencv-highgui-dev libsnappy-dev libsnappy1 \
    libatlas-base-dev cmake libstdc++6-4.8-dbg libgoogle-glog0 libgoogle-glog-dev \
    libgflags-dev liblmdb-dev git python-pip gfortran

sudo apt-get clean

sudo apt-get install -y linux-image-extra-`uname -r` linux-headers-`uname -r` linux-image-`uname -r`

sudo apt-get install -y cuda
sudo apt-get clean

AWS CodeCommitの設定

AWS CodeCommit を使いはじめる方法。ポリシーの設定があるので、最初ちょっとめんどくさい感じがする。

Policy の設定

細かく設定せず、とりあえずどのレポジトリにも push 出来るようにする。 AWSCodeCommitFullAccess のポリシーを、IAMユーザかグループに付与する。

CodeCommit 用の SSH 公開鍵を設定するために、 IAMUserSSHKeys のポリシーを、アップロード操作をするIAMユーザかグループに割り当てる。自分でアップロードさせたかったら本人に、という感じ。

アクセス可能なレポジトリを制限

下記は、hello_world というレポジトリに、読み取り許可だけ与える場合の設定。デプロイするサーバ側にキーを置いて、git pull だけしたい場合などを想定。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codecommit:BatchGetRepositories",
                "codecommit:Get*",
                "codecommit:GitPull",
                "codecommit:List*"
            ],
            "Resource": "arn:aws:codecommit:us-east-1:1234567890:hello_world"
        }
    ]
}

SSH公開鍵の設定

git に ssh でアクセスするための、ssh公開鍵を設定する。 []IAMの画面](https://console.aws.amazon.com/iam/home)を開き、左ペインのユーザ → 公開鍵を設定するユーザを選択 → 認証情報内の AWS CodeCommit の SSH キー というところから、公開鍵を設定する。

設定すると、SSH キー ID というのが発行されるので、この文字列を覚えておく。 APKAEIBAERJR2EXAMPLE みたいな文字列。

~/.ssh/config の設定

先ほどの SSH キー ID を User にして、下記のように設定する。似てるが AWS の AccessKeyId とは別物なので注意。

Host git-codecommit.*.amazonaws.com
  User APKAEIBAERJR2EXAMPLE

SSHの接続確認

ssh してみて、successfully 的なメッセージが出たら成功。あとは普通にレポジトリを作成して自由に push 等出来る。

% ssh git-codecommit.us-east-1.amazonaws.com

You have successfully authenticated over SSH. You can use Git to interact with AWS CodeCommit. Interactive shells are not supported.Connection to git-codecommit.us-east-1.amazonaws.com closed by remote host.
Connection to git-codecommit.us-east-1.amazonaws.com closed.