Github + CircleCI + DockerでGCEを動かす - デプロイ編
- 今日はデプロイするところまで.
- 基本的にはKubernetesのチュートリアルを参考にしつつ作った.
- 説明はしないスタイルで。
Kubernetes関連用語
- 説明はしないと言ったな。アレは嘘だ。
- Kubernetesはコンテナ化されたアプリをClusterにデプロイしたり、配布をスケジュール化したりする。今風に言うとオーケストレーションツール?
- Cluster -> 複数のリソース群が1つのユニットとして接続されたもの。2種類のリソースから構成される
- Pod: 正直捉えづらかった。現在進行系で捉えきれてない。デプロイのタイミングで作られるコンテナの集合体 + 共通リソースの集合体。Logical Host. PodはNodeの上で走る。
- Services: Podsの集合。Podsの外部ネットワークへ公開、ロードバランス、サービスディスカバリを出来るようにする
- Labels: そのまんま。PodやServiceにラベリングできる。環境、バージョン、サービスタイプ(front, backend,db)などの情報を負荷できる
Gophishのデプロイ
> kubectl run gophish-deploy --image=asia.gcr.io/${PROJCET_ID}/gophish:latest --port=3333 # gophishアプリをClusterにデプロイ(ポート3333ではしらせる)。デプロイノードは1つ > export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') # Podの名前を取得 > kubectl expose deployment/gophish-deploy --type="NodePort" --port 3333 # 今回は1インスタンスしか立てない > export NODE_PORT=$(kubectl get services/gophish-deploy - ate='{{(index .spec.ports 0).nodePort}}') # Portを取得
さて、ここまでやれば外部公開されているはずなのだが、curl "$NODE_IP":"$NODE_PORT"してもtime outする。nmapしたところfilterとの結果が帰ってきたのでFirewall系とあたりをつける。
Firewallの設定
なのでコンピュートサービス > ネットワーキング > ファイアウォールルールで見ると、任意のIPから対象のノード:$NODE_PORTへのアクセス許可設定がされていなかったので、以下で設定
> gcloud compute --project "gophish-150317" firewall-rules create "external2gophish" --allow tcp:NODE_PORT --network "default" --source-ranges "0.0.0.0/0" --target-tags "gke-gophish-cluster-bc6565eb-node"
これで、curl "$NODE_IP":"$NODE_PORT"したら無事アクセスできた。でも、毎回NODE_PORT指定するのダルいなぁ...と思ったので、kubectl exposeでオプションがないか探したが見つからなかった(targetPortオプションは使ってみたが駄目だった)。ただ、yamlファイルでの方法なら指定が可能らしいのでyamlファイルを作成。
http://kubernetes.io/docs/user-guide/services/#type-nodeport
apiVersion: v1 kind: Service metadata: labels: name: gophish name: gophish spec: ports: - port: 3333 #targetPort: 3333 protocol: TCP nodePort: 30333 selector: name: gophish type: NodePort
一旦、過去のサービスを消して再設定. 又、今回は指定したポートを指定してFirewallに穴を開ける。無事通る
% kubectl delete svc/gophish % kubectl create -f gophish-service.yaml % gcloud compute --project "gophish-150317" firewall-rules create "external2gophish" --allow tcp:30333 --network "default" --source-ranges "0.0.0.0/0" --target-tags "gke-gophish-cluster-bc6565eb-node" % curl 104.199.208.112:30333 <a href="/login">Found</a>.
ブラウザ側からも大丈夫
NodePortじゃなくてLoadBalancingも試す
yamlを書き換えるだけ
apiVersion: v1 kind: Service metadata: labels: name: gophish name: gophish spec: ports: - port: 3333 targetPort: 3333 <- ★ protocol: TCP selector: name: gophish type: LoadBalancer <- ★
ロードバランサーが作成される過程でFirewallの穴あけもやってくれるらしいので、ロードバランサーに公開IPが付与され次第、アクセスできる。NodePortは手動でやらなきゃいけないからメンドクサイ。
[Kengo@Mac] ~/workspace/docker_gophish % kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE gophish 10.3.249.184 104.155.214.128 3333/TCP 3m kubernetes 10.3.240.1 <none> 443/TCP 4d [Kengo@Mac] ~/workspace/docker_gophish % curl 104.155.214.128:3333 <a href="/login">Found</a>.
スケールアップ
折角ロードバランサー形態にしたので、スケールアップしてみる。おk。
# Before % kubectl get deploy NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE gophish-deployment 1 1 1 1 1h % kubectl scale deployment gophish-deployment --replicas=2 # After NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE gophish-deployment 2 2 2 2 1h
余談 - お金の話
24日の記事を含めて、このコンピュートエンジンを立ち上げたのが約1週間前。それから立ち上げっぱなしで、利用料金はトータルで1102円。為替とかはもろもろ無視すると、ロードバランサー・ストレージもあるものの、90%がCompute Engineにかかった費用と考えられる。内訳は以下の通り。
でも、あれれ?GCEって5node/clusterまで無料じゃなかったっけ?って思ったら、それはCluster管理の価格だった。ノード料金はそのままかかる。個人だと結構いたいかなあ。こまめに管理しないと。
Google Container Engine Pricing and Quotas | Container Engine Documentation | Google Cloud Platform
下記で計算もできる。 cloud.google.com
次は
- CircleCIでデプロイしようと思う。一旦サービスはおとそう。
デバッグ
> kubectl cluster-info # > kubectl get nodes # Cluster内でアプリをホストできるノード > kubectl get deployment > kubectl proxy & # ローカルでいながらClusterのAPIに接続できる -> ブラウザからhttp://localhost:8001/uiで管理コンソールを開ける。便利。 > kubectl get pods # 存在しているpodsをリスト > export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') # Podの名前を取得 > curl http://localhost:8001/api/v1/proxy/namespaces/default/pods/$POD_NAME # 接続テスト > kubectl describe pods # podsの情報(構成情報・イベント)を取得 > kubectl logs ${POD_NAME} # 対象Podのログを取得 > % kubectl exec -it $POD_NAME COMMAND #対象Pod上でCommandを実行。docker execみたいなもん。 > kubectl describe svc/gophish-deploy # サービスの情報
参考資料
Kubernetes - kubectl Overview * 安定の本家ドキュメント GKEで半年運用してみた * お金を調べてるうちにみつけた...最初からこれをみつけていたかった...
Github + CircleCI + DockerでGCEを動かす - レジストリ編
- 2017/08/31: コメントでの指摘を受け、一部コマンドを変更
背景:
- 今、(ほぼ)1人チームで継続性が強く必要な仕事をしているので、あらゆる面で運用を楽にしていきたい。なのでコードで楽に管理でき、デプロイまで自動でやってくれて、オフィスアカウント(googleアカウント)との連携もできるGCPに強く興味がある。特にContainer周りやGCEは深くほっていきたいエリア。
- 最終目標はDockerイメージをGCPで動かすところだが、今回はイメージをGithub + CircleCIを用いてレジストリにPushするところまでが目的
- コードはこちらです。
Cloud SDKインストール & セットアップ
https://cloud.google.com/sdk/docs/quickstart-mac-os-x
% tar xvzf google-cloud-sdk-121.0.0-darwin-x86_64.tar.gz % ./google-cloud-sdk/install.sh % gcloud init % gcloud components update kubectl // Instal kubectl
GKE setup
% export PROJECT_ID=gophish-150317 % gcloud config set project ${PROJECT_ID} % gcloud config set compute/zone asia-east1-a % gcloud config set container/cluster gophish-cluster % gcloud container clusters get-credentials gophish-cluster
- Dockerイメージのビルド
% docker build -t asia.gcr.io/${PROJECT_ID}/gophish:v1 .
- ビルドしたイメージをGKEのContainer RegistryにPush
% gcloud docker -- push asia.gcr.io/${PROJECT_ID}/gophish:v1 % gcloud docker -- search asia.gcr.io/${PROJECT_ID}
- 問題なくできていれば下記のようにイメージがタグ付きで表示される
自動ビルドをする
Github + CircleCIの構成で。
事前準備
- Githubにリポジトリを作る。ローカルで作ったファイルをPushしておく
- GithubとCircleCIを連携する。circle.ymlはない状態だがとりあえずビルド一回ぐらい回す
- GCPプロジェクトのサービスアカウントキー(JSON)を取得する
- プロジェクト > API Manager > 認証情報 > 認証情報を作成 > サービスアカウントキー
- 役割は「編集者」の役割 をもっているメンバーだけが可能みたいだ。とりあえずCompute Engine default service accountを使っといた。
- https://cloud.google.com/container-registry/docs/access-control
circle.yml作成
- Githubフローに似た流れのジョブを作る。つまり…
ブランチを切ってMaster向けPRを作成。 ↓ Dockerイメージをビルド + テスト ↓ レビュー ↓ マージ && テスト環境デプロイ ↓ リリースtagをきる on Github ↓ 本番環境デプロイ
真のGithubフローだとprを送った時点でデプロイされる、といったことをどこかで読んだ事が、切り戻しまでの時間を考えるとアグレッシブだな、と思う。切り戻しまでの時間 < Maximum Tolerant Downtimeであればいい、という発想なのだろうか。組織と個人のレベルが高ければ実現できそうだな。
このフローを作るには、Github > Settings > Webhooksのイベントで以下を設定しておけばいい
- Push, Pull request, Deployment, Release
どう動くか
- BranchをきってPRを作った時にはテストまで実行されてデプロイはされない
- MergeするとMasterブランチでのビルドが走る。デプロイまでされる. GCPでみるとlatestタグのついたイメージが更新されていることがわかる
- GithubでReleaseをすると、WebHookしてくれて、やはりデプロイまでしてくれる。ただdeploy.shにリリースタグがある場合の追加処理があり、それによりリリースタグが付与されたDockerイメージがレジストリにpushされる。以下は v1.0.1をリリースした例。こういう形で変更管理を楽にできそう。
- 以上。
その他
- CircleCI内でgcloudをupdateしてるけど、デフォルトで最新化しててくれませんかね…15秒もかかっとんぞ
- Dockerイメージをビルドするのが遅い。これはCircleCIのコンテナ内でビルドしてるので、キャッシュされないから。対策としてはdependenciesで、ジョブ開始時点での最新イメージをGKEからpullしてくること。これをすると30秒くらい早くなる。
- CircleCI 2.0でなんとかするらしい。
- deploy.shって, deploymentのタイプ毎に分けた方がいいのかな〜
DockerイメージをGKEのレジストリにアップロードする
背景:
- 今、(ほぼ)1人チームで継続性が強く必要な仕事をしているので、あらゆる面で運用を楽にしていきたい。なのでコードで楽に管理でき、デプロイまで自動でやってくれて、オフィスアカウント(googleアカウント)との連携もできるGCPに強く興味がある。特にContainer周りやGCEは深くほっていきたいエリア。
- 最終目標はDockerイメージをGCPで動かすところだが、今回はイメージをGithub + CircleCIを用いてアップロードさせるところまで
- コードはこちらです。
Cloud SDKインストール & セットアップ
https://cloud.google.com/sdk/docs/quickstart-mac-os-x
% tar xvzf google-cloud-sdk-121.0.0-darwin-x86_64.tar.gz % ./google-cloud-sdk/install.sh % gcloud init % gcloud components update kubectl // Instal kubectl
GKE setup
- Clusterの作成をGUIで。gcloudかRESTでも作成可能
- gophish-clusterをasia-east1-a上に作った
- コマンド環境の設定
% export PROJECT_ID=gophish-150317 % gcloud config set project ${PROJECT_ID} % gcloud config set compute/zone asia-east1-a % gcloud config set container/cluster gophish-cluster % gcloud container clusters get-credentials gophish-cluster
- Dockerイメージのビルド
% docker build -t asia.gcr.io/${PROJECT_ID}/gophish:v1 .
- ビルドしたイメージをGKEのContainer RegistryにPush
% gcloud docker push asia.gcr.io/${PROJECT_ID}/gophish:v1 % gcloud docker search asia.gcr.io/${PROJECT_ID}
- 問題なくできていれば下記のようにイメージがタグ付きで表示される
自動ビルドをする
Github + CircleCIの構成で。
事前準備
- Githubにリポジトリを作る。ローカルで作ったファイルをPushしておく
- GithubとCircleCIを連携する。circle.ymlはない状態だがとりあえずビルド一回ぐらい回す
- GCPプロジェクトのサービスアカウントキー(JSON)を取得する
- プロジェクト > API Manager > 認証情報 > 認証情報を作成 > サービスアカウントキー
- 役割は「編集者」の役割 をもっているメンバーだけが可能みたいだ。とりあえずCompute Engine default service accountを使っといた。
- https://cloud.google.com/container-registry/docs/access-control
circle.yml作成
- Githubフローに似た流れのジョブを作る。つまり...
ブランチを切ってMaster向けPRを作成。 ↓ Dockerイメージをビルド + テスト ↓ レビュー ↓ マージ && テスト環境デプロイ ↓ リリースtagをきる on Github ↓ 本番環境デプロイ
真のGithubフローだとprを送った時点でデプロイされる、といったことをどこかで読んだ事が、切り戻しまでの時間を考えるとアグレッシブだな、と思う。切り戻しまでの時間 < Maximum Tolerant Downtimeであればいい、という発想なのだろうか。組織と個人のレベルが高ければ実現できそうだな。
このフローを作るには、Github > Settings > Webhooksのイベントで以下を設定しておけばいい
- Push, Pull request, Deployment, Release
どう動くか
- BranchをきってPRを作った時にはテストまで実行されてデプロイはされない
- MergeするとMasterブランチでのビルドが走る。デプロイまでされる. GCPでみるとlatestタグのついたイメージが更新されていることがわかる
- GithubでReleaseをすると、WebHookしてくれて、やはりデプロイまでしてくれる。ただdeploy.shにリリースタグがある場合の追加処理があり、それによりリリースタグが付与されたDockerイメージがレジストリにpushされる。以下は v1.0.1をリリースした例。こういう形で変更管理を楽にできそう。
- 以上。
その他
- CircleCI内でgcloudをupdateしてるけど、デフォルトで最新化しててくれませんかね...15秒もかかっとんぞ
- Dockerイメージをビルドするのが遅い。これはCircleCIのコンテナ内でビルドしてるので、キャッシュされないから。対策としてはdependenciesで、ジョブ開始時点での最新イメージをGKEからpullしてくること。これをすると30秒くらい早くなる。
- CircleCI 2.0でなんとかするらしい。
- deploy.shって, deploymentのタイプ毎に分けた方がいいのかな〜
VagrantとAnsibleを触ってみたのでメモ
構成管理に手を出してみたので、メモ。 AnsibleとVagrantで。 本ドキュメントでは手順とハマリポイントを紹介しますが、手順は他の本やブログでもさんざん上がってるので、最小限にとどめます。
目的
実践的な意味での構成管理、プロビジョニングの勘所を探したい
Ansibleを選んだ理由
最初、Itamae かAnsible で迷ってたが、以下の観点からAnsibleを選択
記述方法
ItamaeじゃなくてAnsibleを選択したのは、rubyに詳しくなく、多少離れてるyaml記述の方が学習コストが少なそうだったから。docker fileもyml記述だし。複雑なことをするとツライっぽいけど、そこまで複雑じゃないからいいかな、とも。ここらへんは感覚値です。
ドキュメント
ドキュメントの総数やSOFの記事数も多かったのがポイント。公式ドキュメントの充実度もAnsibleが上だった。
後、moduleがAnsibleのが充実してたし、Andsible-Galaxyもよさげだった。
とか、色々言ったけど、結局決定打はない。というか決定できるほど知らないので、Ansible暫くやってつまったらitamaeでゴニョゴニョしに行く方針。
構成
Mac + VM on VirtualBox + Vagrant + Ansible
構築
Vagrant構築
作業ディレクトリの作成と移動
mkdir ~/workspace/ansibleDemo cd ~/workspace/ansibleDemo
- Vagrantボックスを取得
% vagrant box add centos6-7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box
- Vagrant初期化
vagrant init centos6-7
- Vagrantfile作成(下記を追加)
# vim Vagrantfile実行 config.vm.box = "centos6-7 config.vm.network "private_network", ip: "192.168.33.10"
- VM起動
vagrant up
- Ansibleインストール
brew install ansible
- Inventory登録
echo "[TestServer]" > hosts echo "192.168.33.10" >> hosts
- ssh接続先設定
vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config
% ansible -i hosts 192.168.33.10 -m ping 192.168.33.10 | SUCCESS => { "changed": false, "ping": "pong" }
- playbook作成
# vim playbook.yml - hosts: TestServer become: yes tasks: - ping:
- playbook実行
% ansible-playbook -i hosts playbook.yml
とりあえず、出来たところはここまで
ハマりポイント
Guest VMにpingが通らない
- ansible経由どころか、hostマシン(Mac)からもできなかった
- vagrantのVagrantFileにprivate_networkを記述すれば、staticにIPを決定出来るのかと思ったが、vagrant upしても接続できない。VM内でifconfigうつも、private_networkに記述したIPは表示されず
- VirtualBoxからみるとVMのネットワークのアダプタ1にhost_onlyのインターフェースがあるはず。
- 仕方ないので /etc/sysconfig/network-scripts/ifcfg-eth1を直接編集して、ネットワーク再起動
BOOTPROTO=none ADDR=192.168.33.10 NETMASK=255.255.255.0 ONBOOT=yes DEVICE=eth1
/etc/init.d/networks restart
- 上記で解決
Vagrant up時にWarning: Authentication failure. Retrying...が出る
- sshの設定を調査
% vagrant ssh-config --host 192.168.33.10 Host 192.168.33.10 HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/Kengo/workspace/ansibleDemo/.vagrant/machines/default/virtualbox/private_key IdentitiesOnly yes LogLevel FATAL
- IdentifyFile内のprivate_keyにマッチするpublic_keyがゲスト側にいなければいけないので、作る
% ssh-keygen -yf .vagrant/machines/default/virtualbox/private_key > public_key % cat public_key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCg4qWCq3mPom9TzcAdDoDHt61s7tjsmeHaD0pLePYW0p4+qZCr2u8cLk0gJElB7BQc3c3mMuo5iCsYoxrjXbVHpNNUDmRHNLdSxNVO3Z7qLY7VzyQWwoqyqrCcbN3fG/MV+6cs+8d0dcvHGrEYnR9O6Q81VS4sdBucM0J8jQ2oyzumr8QZdXFEEeQbG9SKOVIFpuPHBiOFV+skc22VfgZNlxANBizFV7uguCxhEoQs74L1XMvC1ae7TjVhnIZbZ1063QyXtPgO25TwFqZUsCltqFxgBA032YKZFAtFXyF5vu0pootG91biS9f43dccp8cFuizgLc5FkUYUhjDtNRLV
- ゲスト側にpublic_keyを登録....けど、すでに存在した。
% vagrant ssh Last login: Sun Aug 7 18:41:24 2016 from 10.0.2.2 [vagrant@localhost ~]$ cat .ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCg4qWCq3mPom9TzcAdDoDHt61s7tjsmeHaD0pLePYW0p4+qZCr2u8cLk0gJElB7BQc3c3mMuo5iCsYoxrjXbVHpNNUDmRHNLdSxNVO3Z7qLY7VzyQWwoqyqrCcbN3fG/MV+6cs+8d0dcvHGrEYnR9O6Q81VS4sdBucM0J8jQ2oyzumr8QZdXFEEeQbG9SKOVIFpuPHBiOFV+skc22VfgZNlxANBizFV7uguCxhEoQs74L1XMvC1ae7TjVhnIZbZ1063QyXtPgO25TwFqZUsCltqFxgBA032YKZFAtFXyF5vu0pootG91biS9f43dccp8cFuizgLc5FkUYUhjDtNRLV vagrant <- ★あれこれはssh-keygenして作ったものと同じ...
- ぐぐったら.sshの設定がいけなかったらしい
[vagrant@localhost ~]$ chmod 0700 /home/vagrant/.ssh/ [vagrant@localhost ~]$ chmod 0600 /home/vagrant/.ssh/authorized_keys
これでおk
ansibleでpingができない
% ansible -i hosts 192.168.33.10 -m ping 192.168.33.10 | UNREACHABLE! => { "changed": false, "msg": "SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue", "unreachable": true }
vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config
- これでpingができた
% ansible-playbook -i hosts playbook.yml PLAY *************************************************************************** TASK [setup] ******************************************************************* ok: [192.168.33.10] TASK [ping] ******************************************************************** ok: [192.168.33.10] PLAY RECAP ********************************************************************* 192.168.33.10 : ok=2 changed=0 unreachable=0 failed=0
以上。ヨサそう
JTB不正アクセス & 個人情報流出についてまとめてみた
更新履歴
- (6/15更新)下記にてpiyologが更新されているので、そちらを見つつ足りてない情報を加え、情報を再整理d.hatena.ne.jp
- (6/16更新)6/15午前から6/16 0時までに公表された情報を追加
- (6/16 18:20更新)タイムラインを更新
- (6/17 01:30更新)6/16から6/17 0時までに公表された情報を追加
- (6/20 01:17更新)6/17から6/20 0時までに公表された情報を追加
- (6/27 19:00更新)6/20から6/27 までに公表された情報を追加
イントロ
タイムライン*1*2
- ここではすべて2016年内での出来事とします
日時 | 出来事 | 備考 |
---|---|---|
3/15 | i.JTBの従業員がメール上の添付ファイルを開いたことでパソコンが感染 | 取引先を装ったメール。この時点で感染は認知されず。最終的にサーバー |
3/19 | JTB情報システム(JSS)が |
当該サーバは本来個人情報を含まない。システム監視会社によって検知。継続的な不信通信をブラックリストに登録する作業をおこなっていた。遮断に関する報告はi.JTBからJTBにはなかった*5*63連休 |
3/20 | Webサーバーを社内ネットワークから物理的に切り離し。不審通信は別経路で継続 | 「当該日に不審通信を全遮断することは業務的にも技術的にも可能だった」*7 3連休 |
3/21 | 不正侵入者はデータベースにアクセスしCSVファイルを生成。制御サーバにCSVファイル設置し、その日の内に削除.*8 | | データファイルが作成された制御サーバと不審通信を発したサーバは別*9。3連休 |
3/24 | 内部サーバから外部への不審通信を最後に確認 | |
3/25 | 遮断作業を終了。JSSがJTB IT企画部門に報告 | *10 |
3/XX~3/YY | ネットワーク内の全サーバとパソコンを調査 | 3/19 ~ 3/30? |
4/1 | 不正侵入者が作成・削除したデータファイルの存在を確認。CSIRT立ち上げ。 | |
X/XX~5/13 | 外部セキュリティ専門会社と共同で、ウイルスを駆除・データファイルの復元と不正アクセスの調査・分析・対応を実施 | 調査開始のタイミングの記述はない。復元対象のデータファイルは不正侵入者が作成・削除したデータファイルかと思われる |
5/13 | 復元したデータファイルに個人情報が含まれることを確認。i.JTBよりJTBにエスカレーション*11 。個人情報流出の可能性を認定。事故対策本部を設置。 | |
5/13~X/XX | 直ちにデータを正規化し、 |
*12 |
5/17 | JTB 高橋社長が情報を認知 | |
5/30 | 警察に相談 | |
5/31 | 観光庁に相談 | *14 |
X/XX | 問い合わせ窓口を設置 | |
6/10 | 対象顧客が判明 | *15 |
X/XX~ | 対象のユーザーへメールによる通知を開始 | 1ヶ月以内に連絡するとのこと*16 |
6/14 | 発表 && 調査継続。警察による操作開始 | 不正アクセス禁止法違反や不正指令電磁的記録供用の容疑にて操作中*17 |
6/15 | 個人情報流出の可能性があるユーザーへの注意喚起 *18 | 送信元メールアドレス、添付ファイル、ヒアリング内容に関して通達。観光庁が再発防止策の提出依頼*19 |
6/17 | 国交省、再発防止策を検討する有識者検討会の設置を発表 | *20 |
6/24 | 観光庁への再発防止策の報告期限。該当する顧客への連絡は24日午前までに、ほぼすべて終了 | 「さまざまな企業や団体で個人情報が流出した事案の教訓が生かされておらず、大変遺憾だ」「全体的に遅すぎる」 |
7/1 | 末永安生専務をCISOに任命。社長直下のITセキュリティ専任統括部門を設置 | *21 |
攻撃の概要
当時のJTBの体制
発覚以前
- セキュリティを横断的に見る部門は存在せず *23
5.対策: (中略)ジェイティービー(グループ本社)内にITセキュリティ専任統括部門を設置いたします
- CSIRTも存在せず *24
サイバー攻撃の緊急対応チームも当時は存在しなかった
- 一部ログを取得していなかった*25
- すぐ情報を公開しなかったのは「不安と混乱を招くと考え、特定できた段階で公表する方針を取った」*26
- 対象データを暗号化していなかった。*27
- 実績データベースへアクセス可能な社員は1人だが、そのPCは乗っ取られていない*28
- 実績データベースのデータを使うBI(ビジネスインテリジェンス)ツールは25人の社員がアカウントを持っていたが、今事案との関連性は薄いと見られる*29
発覚後
- 問い合わせ窓口を設置
- スタッフ300名規模*30
- 6/14時点で数千件の問い合わせ
- 警察への相談済み(調査中)
- 7/1までにITセキュリティ専任統括部門を設置
「外部流出について可能性があるという表現にとどめたという。JTBは通信ログの一部を取っていなかった。」とあるので事実がないのではなく事実を確認する術がないというのが正しいかもしれませんね。 https://t.co/fkvewFVs7P
— nobuhiro tsuji (@ntsuji) 2016年6月14日
送信された標的型メール*31*32*33*34*35
- 件名: 航空券控え添付のご連絡
- メアド: ごくごく普通のありがちな日本人の苗字@全日本空輸のドメイン*36
- 署名: 取引先の署名
- 添付ファイル名:
- 添付ファイル種別: PDF。
- 実態はELIRKS(の亜種?)とPluX(の亜種?)に当該PCを感染させる新種マルウェア
- オペレータから返信。エラーメールがかえってくる
- 開封すると航空券のeチケットが表示される
- メールヘッダー: 海外のレンタルサーバー(香港を経由)*39
- 本文内容
- 添付ファイル開封者: オペレータ
- 標的型メールの訓練済み
- JTB全体では定期的に訓練していたようだが、当該オペレータが複数回の訓練を受けていたかは不明
- 標的型メールの訓練済み
被害範囲
- 個人情報悪用の報告もない
流出は確定されていない- 流出に関するログが確認できないため、わからない*42
- 尚、一部ログを取得していなかったとのこと
- 可能性は否定されていない*43
- 知らない宛先から不審なメールマガジンが届いた」といった指摘がおよそ100件よせられた
- 詳細調査中*44
個人情報の項目
以下の一部か全て
- 氏名(漢字、カタカナ、ローマ字)
- 性別
- 生年月日
- メアド
- 住所
- 郵便番号
- 電話番号
- パスポート番号
- パスポート取得日
- 現在で有効なものは
約4300件4359件*45
- 現在で有効なものは
訪日外国人の情報も含む*46
- 以下の情報は含まれない*47
- 予約した旅行の内容
- クレカ情報
対象となるユーザー
JTB関連のサービス
- 以下のサービスでオンライン予約したユーザー679万人
- "ネットで予約後、店舗でご清算のお客様の情報は対象となります。" <- ??
- 予約 && オンライン清算が対象??
期間についての記述はない- 2007/9/28 ~ 2016/3/21*48
別会社
NTTドコモのdトラベルユーザー*49*50
- 対象ユーザー: 2014/2/27~2016/3/21に予約したユーザー
- 対象範囲: 33万人
- 窓口設置済み
- ドコモの吉澤和弘新社長が謝罪と対策の強化を表明
auトラベル by DeNAトラベルを*51
対策
不正アクセス対策
- 特定された外部への不審な通信の遮断
- 感染範囲の特定とウイルスの駆除
- 個人情報へのアクセス制御の強化
グループ全体の対策
被害額試算
不明な点
ウイルス感染からの流れ
- 最初に不審通信を確認してから何をしたのか*52
- 感染したパソコンがどの様な用途で使われたか。
- 踏み台もしくは直接操作されたのか
- 内部パスワードを取得されたのか
- 取得したパスワードで社内ツールを使ったのか
- 取得したパスワードでサーバにログインしたのか
- サーバ上でどうファイル作成・削除の操作する権限を得たか。
サーバ上に普段はないデータをどの様に取得したか。
不審通信はどの様な内容なのか => 不審なパケットデータだったか*57
- 宛先・通信種別は一定なのか
- ファイルを送信するような通信なのか
- 単純にいままでに観測されていない通信だったのか
普段の通信量とどれぐらい違うか(ちがわなそう)
- 何をもってして流出の可能性があると判断したか
- 不正アクセス者が作成・削除したファイルの存在で判断したか
- ファイルを外部に送信するような不審通信があったのか
- ウイルスの解析結果をもって判断したのか
業務推進がミッションの実務担当者に、標的型攻撃につながるメールを開いてしまったことに責任など負わせられない。「そこは訓練していたんです」なんてことは、記者会見で言い訳として言及することですらない。むしろ、その後の攻撃の連鎖への対応に何が欠けていたのかが、スタディには必要。
— riotaro okada (@okdt) 2016年6月14日
インパクト
事後対応
- なぜ情報公開が認知後すぐでなかったか
- CSVデータを復元しても正規化が必要で、それだけではユーザーの特定ができず、余計な混乱をまねきたくなかったから
- パスポート情報漏洩(の可能性)に対するエンドユーザーの対策
- 対策をJTBがしめすのか。外務省がしめすのか。
- 可能性であれば対応不要で終わらせるのか。
その他
- ホームページのニュースリリース配下に「不正アクセスによる個人情報流出の可能性について」がないのはなぜ?
- 公表した日付と警察が捜査に着手した日付が同じ
- 一部のログが取得されてなかッタ理由
- 意図的ではなく様々なWebサイトを運営する中で統一できなかったとみられる*61
その他
- 後でpiyologと答え合わせする。
- (2016/6/15追記) piyologと初期情報の量が異なるので、piyologが取得している情報ソースのリストを作る
- 見せ方に関しては、それをまとめてどう使うかは作成者によって違うので、これはこれでよし
- (2016/6/20追記)2日置いてみたが特にめぼしい新情報がなかった(非営業日だからか?)。とりあえずここまでの振返りをする
振返り
まず最初に
- 今回はJTBがいちはやく整理された公式報告を公表していたので、概要が掴みやすかった。
- 恐らく、こういうタイプのインシデントはレアなのだと思うが、今後のインシデントを気にする(いや、起こらないのがベストなのだが)
情報ソースについて
- Googleでの検索"JTB 情報流出 情報漏洩"
- Feedlyでのニュース登録: Security NEXT, ITmedia, ITpro, Jpcert/CC, ZDNet, @IT, INTERNET Watch
- piyologを見て利用したニュースサイト: 日経、毎日、朝日、産経、時事通信、読売
- 上記のサイトをウォチしてて思ったことは、大手ニュース(日経、毎日...)の情報提供は早く且つ頻繁だということ。
- ただし各ニュースが全てを完結しているのではなく、欠けていたり、定義が異なったりしていた
- 当たり前だけど複数の情報ソースを通じてフィルターするのは大事。仮に共通点がない場合は、確定していないということで、断定めいた文脈にしないよう本エントリでは意識した。
- 産経の記事がどの大手ニュースよりも初情報で踏み込んだ内容をリリースしていたイメージ
- 日経の記事が最速だったイメージ
- 日経と毎日の記事は更新頻度が高いイメージ
- まとめを作りたいなら、大手ニュースをくまなく見るのがヨイ
- 逆に、非大手ニュースはリリース時期も後ろで、内容はほぼ共通していた
- まとめだけをみたいなら、非大手ニュースを数個見ればヨサそう
情報整理について
- まあまあ出来たのではないかと。できるだけpiyologを見ずに情報収集・整理したが(途中みてしまったが...)、取りこぼしたものはあまり無かったので。
- 勿論、取りこぼしたものもある。ので、更新頻度が高く、また情報密度も濃いpiyologはやっぱり凄かった
まとめの構成
GotSome \W+ech?
- 更新内容 -> イントロ -> タイムライン -> 攻撃の概要 -> JTBの体制(発覚前と後) -> 流出した可能性のある情報の項目 -> 対象となる可能性のあるユーザー ->対策 ->被害額 -> 不明点
piyolog
公式発表 -> タイムライン(提携先も含む) -> 被害状況 -> 発端 -> 原因 -> 対策…対応 -> ユーザーへの対応 -> 更新履歴
まず最初に更新内容を持ってくるのはやめる。更新が増えれば増える分だけ、リーダーが欲しい情報に到達するまでの距離と時間が長くなるから
- タイムラインを直後に持ってきたのは良かった。提携先を別テーブルに切り出すことはまでは考えつかなかったけど....備考カラムを作ったのは良い
- 此処から先が明確にpiyologの構成と大きく異なってくる。piyologの場合は"被害状況"と軸をユーザーと現在の時間に置いてるが、本エントリの場合は「攻撃の概要」と環境に軸を置いている。これは本エントリが、この話を自分の担当する環境とのdiffをとり改善ポイントを洗い出せることを目的としているので、この書き方になっている。逆にpiyologは広範囲への情報共有が主目的である(気がする)から、軸が異なるのではないかと推測する。よって、どっちが良い悪いではないと思う。
それを踏まえた上でいうと、本エントリの流れと粒度は若干ぎこちない。攻撃内容ときたからには、攻撃結果(攻撃成否, 攻撃対象,..)が次にくるべきではないか。で、その後に対策がくるのがキモチイと思われる。よって、今後新しく書くとしたら...
- イントロ -> タイムライン -> 攻撃の概要 -> 攻撃の成否 -> 攻撃の影響(範囲、期間、被害額) -> 原因 -> 対策 -> 不明点 -> 更新内容
という訳で、次は構成にもうちょっと気をつかって書いてみる
- ミニネタとして、はてなでは大見出しと中見出し2つで構成したほうがよさそう。少見出しと中見出しの見た目に違いがないように思える
- piyologの標的型メールのみやすさが圧倒的だった
- 問い合わせ窓口は想定リーダーが異なるから本ブログではいいかな...
今後
- 本件について引き続きウォチ
- 現在わかっていることを元に、仮説を立ててみたいと思う
- 今後のインシデントもまとめていけたらおもう。どれを線引にするかは自分の匙加減次第で、自分にもわからない。何となくじゃないかな。
- piyologはやっぱり凄い
*2:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*3:JTB情報流出、感染サーバー3台以上 再発防止策など公表 - 産経ニュース
*4:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*5:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*6:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*7:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*8:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*9:JTB、最大793万人分の情報流出か 不正アクセスで:朝日新聞デジタル
*10:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*11:記者の眼 - (4/5)JTBの情報漏洩事故報告は遅すぎだ! ではいつだったら良かったのか?:ITpro
*12:JTB、情報流出で再発防止策など報告 観光庁に :日本経済新聞
*13:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*14:JTB情報漏洩、国交省が有識者委設置へ :日本経済新聞
*15:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*16:JTBの端末、海外サーバーと不審通信 顧客情報流出 :日本経済新聞
*17:不正アクセス容疑で捜査=JTB情報流出-警視庁:時事ドットコム
*18:http://www.jtbcorp.jp/jp/160615.html
*19:http://www3.nhk.or.jp/news/html/20160615/k10010557611000.html
*20:全文表示 | 国交省へ「批判の矛先」向く可能性も JTB個人情報流出と「対応の遅さ」 : J-CASTニュース
*21:JTB、情報流出で再発防止策を報告 外部調査委を設置 :日本経済新聞
*24:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*25:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*26:JTB:不正アクセス、最大793万人分の情報流出か - 毎日新聞
*27:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*28:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*29:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*30:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*31:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*32:JTB、外部侵入者が閲覧の可能性 「標的型メール」か :日本経済新聞
*33:JTB情報流出:また「標的型メール」 巧妙偽装、防げず - 毎日新聞
*34:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*35:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(1/2ページ) - 産経ニュース
*36:JTBの顧客情報流出、ウイルス発信源は中国か :日本経済新聞
*37:【情報流出】あなたは見抜けるか JTB がはまった「巧妙なメール」の罠とは (BuzzFeed Japan) - Yahoo!ニュース
*38:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*39:【JTB情報流出】全日空装うメールで感染 香港を経由 - 産経ニュース
*40:【情報流出】あなたは見抜けるか JTB がはまった「巧妙なメール」の罠とは (BuzzFeed Japan) - Yahoo!ニュース
*41:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*42:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*43:JTB、外部侵入者が閲覧の可能性 「標的型メール」か :日本経済新聞
*44:http://www3.nhk.or.jp/news/html/20160624/k10010570411000.html
*45:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*46:JTB、顧客情報793万人分流出か 取引先装うメール :日本経済新聞
*47:JTB、最大793万人分の情報流出か 不正アクセスで:朝日新聞デジタル
*48:http://www.yomiuri.co.jp/national/20160614-OYT1T50095.html
*49:報道発表資料 : 提携先のJTB社のグループ会社サーバーへの不正アクセスに伴う「dトラベル」の個人情報流出の可能性について | お知らせ | NTTドコモ
*50:ドコモ、JTBへの不正アクセスに伴う「dトラベル」の33万人の個人情報流出か | マイナビニュース
*51:株式会社i.JTBへの不正アクセスによる個人情報流出の可能性に関するお知らせ|auトラベル
*52:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*53:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*54:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*55:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*56:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*57:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*58:JTB社長、情報流出問題「補償は個別対応」 一律は考えず :日本経済新聞
*59:JTB個人情報流出事件「パスポート番号」は悪用できるのか調べてみたときのメモ
*60:http://www.nikkei.com/article/DGXLASDZ24HHZ_U6A620C1000000/
2016年Hardening 100 Value x Valueを振り返ってみる
2016/6/4~2016/6/5に沖縄県宜野湾市で開催されたHardening 100 Value x Valueにチームリーダーとして参加したので、振り返って見ようと思う。ただし、技術情報やシステム構成は秘密扱いなので、どんな攻撃があったかは話さない(話せない)のでご容赦を。ちなみに自費でいった。
まずは
- ともに戦ってくれたチームメンバーの皆様、ありがとうございました。これ以上のメンツは望めないでしょう。
- 多くの学びと困難を準備してくださった運営委員の皆様、ありがとうございました。
Hardening 100 Value x Valueとは?
- 堅牢化(Hardening)の腕を競う大会
- これには開発・運用・検知といった技術の軸に加え、マネジメント・広報などの非技術部の連携も必要
- また、運営により準備されているリソースに投資し、チームを強化・補強することが可能
- アプライアンスからコンサル、事務対応まで含む
- これら役割・手法を最適に組み合わせValueを最大化することを試みる
- 今回のValueは、eコマースサイトの見込み販売力(Sales Potential)を含む複数の指標が計測された。
- 技術点 - Technical Merit
- 顧客点 - Customer Impression
- 対応点 - Incident Response
- 経済点 - Market Creation
- 協調点 - Information Sharing
目的: 何故参加(応募)したか
- 前職(SI)でもIRやってたけど総合判断が不要だった。なので俯瞰的なIR対応をしたかった
- 実際の攻撃によって、どのような被害をうけるかシミュレートしたかった
- 非技術的な部分も含めたマネージメントの経験も
- 目標としてはあわよくば1位をとる気概
流れ
現地入り前
- Slack上にチャネルを作り、そこでやりとり
- エクセル上でメンバーのスキルマップを作成。それを元に担当を決め。
- サーバ堅牢化の確認と設定手順を作成。
- 特にハングアウトなどによる顔合わせは行っておらず。
Hardening 前日(0日目)
- メンバーと顔合わせ
- 食事処で作戦会議
- 運営から指示されたことの対応
- 資料の読み合わせ
- 担当の確認
- 初期動作の設定割り振り
Hardening Day(1日目)
- 序盤(最初の2時間くらい?)は防御力向上を目指す
- あわせてマーケットプレイスから必要なリソースを購入
- しかけられた攻撃をいかに検知・復旧させるか
- 売上があがるような施策をうつ
Softening Day(2日目)
- 振り返り発表
- 結果発表
- その他のプレゼン
結果
- ビリ out of 12 (KBC賞)
- 他チームとの最終スコアを比較すると、販売力に大きな差があった
- 他のスコアについても平均より下回っている
振返り
- 後で、もうちょっと綺麗に整理する
現地入り前
- 通常Linuxサーバのハードニング手順を作成したことはおk
- それにあわせてメンバーの役割をそれぞれ分割していたこともナイス
- 細かいサービスの調査概要は書いてたけど、もっと詳細な手順は書いてなかったのがマイナス
- 細かいサービスは機密に触れそうなのでぼかしてる。
- これらの内容はスプレッドシートに書いた。それはよい。
- だが遅すぎた。もっと各担当者が準備できる期間をもたせておけばよかった
- 3weeksほど前にやっておけばよかったかもしれない。who knows.
- 後、システム運用の面に偏りすぎた。ビジネス面の対応(テンプレ作成)がなかった。
- Windowsは作業端末として持っておこう。VM越しのファイルやりとり・キーボード配列、どれをとっても作業端末としてMacよりベター
- 又、できればもう一台、調査用としてあったほうが良い。VMとブラウザを行き来するのはめんどいぞ!
Hardening 前日(0日目)
- 可能であればこの日は夕方くらいには到着した方がいい
- 宿泊先はメンバー間で統一ないしは近場にしたほうがいい
- 移動するのはダルい。
- 次やるのであれば、会議室かります
- ここで何故かスプレッドシートに記載した手順の共有をしなかった。何故だ。疲れていたからか。
- 痛恨のミスその1
- タスク管理+優先順位決め担当者を置かなかった
- 痛恨のミスその2
- 勿論、その担当者が何をやるか具体化も必要
- X時間に1回、広告を買う、タスク整理する、売上状況を確認する etc etc
- この判断の根拠はチーム人数の総数。「前回は10人超だったけど、今回は5人だから皆手を動かさなきゃね」という考え
- システム運用だけでなく"ビジネス"の視点がすっぽり抜け落ちてた証拠。
- ユーザー企業に務める自分がこれを抜かしてたのが驚異。
- 広報も担わせるか、それは難しい。判断がわかれると思う。だが、経験上、この人に集約すべきだろう。
- この競技において最もスコアに関わる基本方針についてメンバー間で落とし込めてなかった
- 痛恨のミスその3
- 資料の読み込みはしたが、中途半端だった
- 読み込む為の観点が整理されてなかった
- 読み込み自体も役割をわけて重要箇所をまとめる事がよいかもしれない
- 企業(仮)情報、評価方法、環境構成(含むシステム運用ルール)、マーケットプレイスといった形でやるのがよいのではないか。
- 全員で1ページ目から順に読むのは無駄が多い。
- やっぱり紙媒体が最強ですわ
- プリントアウトできる宿泊先にする
- マーケットプレイスにおける購入内容・優先順位を決めたのはナイス
- この時点で環境構成がわかっていたので、ネットでマニュアル等を探すべきだった
Hardening Day(1日目)
- 事前準備した手順の共有がなかったことによる問題
- バックアップがとれず!
- 事前に準備していたことが9割がたできなかった
- 痛恨のミスその1−1
- 基本的にタスク管理+優先順位決め担当者を置かなかったことによる問題
- 購入担当の導入後フォローをせず、購入物の置物化
- インシデント発生時の場当たり的対応化。レイヤーごとの切り分けをせず。
- 痛恨のミスその2−1。
- 冷静にやれば、もっと早く対応できてたはず。
- 1)NW構成図を書いて 2)影響範囲を特定し 3)各タスクに落としこむ切り分け作業をしなければいけない
- 「こういう対応したらいいんじゃない?」と言うナイスアイディアをスルー(皆手を動かすのに忙しすぎた)
- 「え、今それやるの?」「え、やること変えちゃったの?」と言った事態が発生。
- 在庫管理をせず!なんということか
- サーバ乗っ取られにより売上があがってないと、実は考えていたのではないか。在庫の管理をしてないのに。
- 売上をちゃんと追ってたのはよい。
- 資産と広告単価率と比較して、常に広告をうちまくる判断をしたのもよい
- あるメンバーが気づいていた脆弱性を他のメンバーに共有されない事象が発生!ちゃんとエスカレーションしよう!
- 基本方針を共通認識化出来てなかったことによる問題
- システム優先な判断になりすぎた。ビジネスへのリソース比重が少なかった。
- 乗っ取られたサーバを復旧するためのサービスを敢えて使わない選択をしたこと。
- 毎度のことだが、乗っ取られた手法はかけない
- 痛恨のミスその3−1
- その他
- ユーザーへの報告・とあるセキュリティ組織への報告など、メンバー間情報共有だけでなく、一般的な組織がする情報共有も足りてなかった
- 対処方法が分からなかった場合、ダメ元で運営に質問してみたら教えてくれた。聞くべし。周りを巻き込むべし。これも大事な能力だ!
- コレが一番できてたのがチーム: アンセキュアだった。凄い巻き込み力だった。
Hardening Day(2日目)
- 特に無し
- iPhone落として割ったぐらい
- 帰宅!
- 気持ちをリセットするために、もう1日ステイすることをおすすめする。
他のチーム
- グランプリ: No. Bee。技術と顧客対応が頭一つ抜けていた印象です。また、プレゼンを聞く限りチーム分けが綿密に出来ていた印象
- CTC賞: Love Winner。スポンサーであるCTC様の賞。No. Beeについで全体のスコアが高く、かつ投資額も物凄かった。
- LAC賞: アンセキュア。スポンサーであるLAC様の賞。Love Winnerよりも投資額が高いこともそうだが、周辺の巻き込み力が非常に高いことが印象的。
参加した感想
- 最高だった。自分のチームだけでなく、他のチームとも関われて楽しかった
- 自分に足りないのは以下
- タスク管理、マネジメント、linux系の操作、実際のエグゼキューション
- 自分でやり過ぎようとする部分
- チームビルディング大事。
- アンチパターンの塊だったのではないか。これを是非、業務に活かして欲しい。これだけで次の半年のLTができそう。
- 本競技はプラクティカルな極みなので、是非、企業の人間には参考にしてほしい。マジで。
- 昨年度のチームにヒアリングしたのにそれを活用できなかった(というよりしなかった)
- 判断のミス。
- 逆に良かったことは
- 事前準備には結構力をいれたのではないだろうか。ただこの事前準備もシステム運用に偏りすぎてた気がする。
- KBC賞は辛かった。すでにスコア発表でライフはもうゼロだったので、これは相当キタ。
- KBC賞: 国際電子ビジネス専門学校の紹介パンフ・入学願書・割引券のセットと激励の言葉
その他
おまけ
- 沖縄の海は最高だった。入れてないけど。
RecyclerViewAdapterのnotifyDataSetChangedとnotifyItemRangeChangedの違い
- notifyDataSetChangedでリスト(recyclerView)を更新したい時に、意図しない挙動になってた
- このリスト内の値がかわることはあるけども、構成自体は固定だっった。
- このリストはnestedScrollViewの中にある
- 例えばあるモデルを選択して、そのモデルをリストにbindしnotifyDataSetChangedをすると、一瞬だけ順番が入れ替わった後に戻るような挙動
- つまりリスト内のモデルをまるっと更新したときに"ちらつき"が発生していた
- 最初はynzmさんのRecyclerView の notifyItemChanged() 時のちらつきを止めるかと思ったが、解決できず
- notifyItemRangeChangedにしたら、"ちらつき”がなくなった
- 直感的だが、notifyDataSetChangedは下記の通りViewをrelayoutをするので、そこに差分があるように思えた。ので中身をみてみた。
private class RecyclerViewDataObserver extends AdapterDataObserver { @Override public void onChanged() { // notifyDataSetChanged内部で呼び出される assertNotInLayoutOrScroll(null); if (mAdapter.hasStableIds()) { // TODO Determine what actually changed. // This is more important to implement now since this callback will disable all // animations because we cannot rely on positions. mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } else { mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } if (!mAdapterHelper.hasPendingUpdates()) { requestLayout(); } } @Override public void onItemRangeInserted(int positionStart, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) { triggerUpdateProcessor(); } } }
- このrequestLayout内部で、ViewのrequestLayoutを呼んでいる
- ViewのrequestLayoutはリファレンスにもある通り、レイアウト構成が変わったときにView階層を再計算させるために呼び出すべきものらしい
Call this when something has changed which has invalidated the layout of this view. This will schedule a layout pass of the view tree.
- よって構成が固定されているリストのアイテムの更新において、notifyDasetChangedの使用は望ましくないので、notifyItemRangeChangedを使うべし。
- ただ今までrecyclerViewの更新でnotifyDasetChangedを使用してたこともあったが、今回のようなことはおきなかった。これはnestedScrollViewの中にrecyclerViewを入れていることが関係するかもしれない(再描画が走ってしまいnestedScrollViewの高さが変化してた?)
- 深く調べるならnestedScrollView及びrecyclerViewをフカボルべき