omohayui blog

おも‐はゆ・い【面映ゆい】[形][文]おもはゆ・し[ク]《顔を合わせるとまばゆく感じられる意》きまりが悪い。てれくさい。

Cloud KMS で暗号化

Cloud KMS とは

cloud.google.com

Cloud KMS は GCP で提供されている鍵管理サービスです。(Cloud Key Management Service )
GAE上で秘匿情報を管理したいときに Datastoreにそのまま入れるのも...
secret.yaml を作ってリポジトリ管理外にして app.yaml で include してというのも...
と思っていたら、Cloud KMS がとっくにSLA適用されていて結構使っている人が多いので触ってみることにしました。

Cloud KMS のオブジェクト階層

アクセス制御を管理するために設計された階層構造に、CryptKey(暗号鍵)を格納します。

  • Project - プロジェクト
  • Location - ロケーション
  • KeyRing - キーリング
  • Key - 鍵
  • Key Version - 鍵バージョン

この構造のリソース (KeyRing, CryptKey) へのアクセスは、Cloud IAM で制御できます。

手順

※ 注意点

  • KeyRing と Key は無効化はできますが削除ができないので、自分みたいに適当な KeyRing を作成してしまうとゴミが残ってしまうので気をつけましょう...

Cloud KMS API を有効にする

KeyRing を作成する

  • GCP Console > Security > Cryptographic Keys を開く
  • [Create Key Ring] をクリック
  • Key ring name を入力し Key ring location を選択して [Create]
    • KeyRing は、Key をグルーピングする粒度の名前
    • KeyRing Location は基本 global で良いらしいが、公式ドキュメント を見るとパフォーマンスを考慮するなら特定region(サービスを提供する地域)を選択せよとのこと

f:id:omohayui:20181021200508p:plain:w500

Key を作成

  • KeyRing を作成したら [Create Key] クリック
  • Key Name、Purpose、Rotation 等を入力して [Create]
    • Rotation は、新しく Key Version が作成されるスケジュールの設定
    • Rotation を設定しても古い Version の Key が使えなくなるわけではない
    • 古い Key Version を無効化するには、 破棄のスケジュール登録 が別途必要になる

作成フォーム

f:id:omohayui:20181021211257p:plain:w500

作成後

f:id:omohayui:20181021200157p:plain:w600

Key を使って暗号化/復号化

Cloud KMS のクラインアントライブラリ には C#/Go/Java/Node.js/PHP/Python/Ruby が用意されてます。

Goで書くとこんなイメージ

base64エンコード/デコードする必要があるくらいです。

import (
    "encoding/base64"
    "fmt"

    "golang.org/x/net/context"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/cloudkms/v1"
)

// KMSClient is a client to access Cloud KMS
type KMSClient struct {
    keypath string
    service *cloudkms.ProjectsLocationsKeyRingsCryptoKeysService
}

// KMSOptions means the options for constructor
type KMSOptions struct {
    ProjectID, Location, KeyRing, CryptoKey string
}

// NewKMSClient makes KMS client
func NewKMSClient(ctx context.Context, opt *KMSOptions) (*KMSClient, error) {
    client, err := google.DefaultClient(ctx, cloudkms.CloudPlatformScope)
    if err != nil {
        return nil, fmt.Errorf("failed DefaultClient. error: %v", err)
    }
    cloudkmsService, err := cloudkms.New(client)
    if err != nil {
        return nil, fmt.Errorf("failed cloudkms.New. error: %v", err)
    }

    keyPath := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s",
        opt.ProjectID, opt.Location, opt.KeyRing, opt.CryptoKey)

    return &KMSClient{
        keypath: keyPath,
        service: cloudkmsService.Projects.Locations.KeyRings.CryptoKeys,
    }, nil
}

// Encrypt encrypts plaintext
func (k *KMSClient) Encrypt(plaintext string) (string, error) {
    resp, err := k.service.Encrypt(k.keypath, &cloudkms.EncryptRequest{
        Plaintext: base64.StdEncoding.EncodeToString([]byte(plaintext)),
    }).Do()
    if err != nil {
        return "", fmt.Errorf("failed to encrypt. error: %v", err)
    }
    return resp.Ciphertext, nil
}

// Decrypt decrypts ciphertext
func (k *KMSClient) Decrypt(ciphertext string) (string, error) {
    resp, err := k.service.Decrypt(k.keypath, &cloudkms.DecryptRequest{
        Ciphertext: ciphertext,
    }).Do()
    if err != nil {
        return "", fmt.Errorf("failed to ecrypt. error: %v", err)
    }
    text, err := base64.StdEncoding.DecodeString(resp.Plaintext)
    if err != nil {
        return "", fmt.Errorf("failed base64 decode. error: %v", err)
    }
    return string(text), nil
}

16進数でポケモンの個体値を表示する

ポケモンgoネタ第二弾。
前回同様、ポケgoに興味ない方は読むことを推奨しません...

なぜ16進数?

よくポケモンの名前に「FFF」とか「DCC」とか付けてる方、見かけますよね。
これ、ポケモン個体値を表しています。

自分も今までは、「攻撃」「防御」「HP」「総合評価(%)」の順で、
個体値ポケモンの名前につけてメモ代わりにしていました。

重要な点は各パラメータが、15段階評価というところです。
攻撃 12 / 防御 13 / HP 12 で、総合評価 82% とかだと、
「12/13/12/82」と記載して登録できる文字数ギリギリになります。

そこで、16進数です。最大15なので [1-F] の1文字で表すことができます。
(これ気づいた人は素晴らしいですね...!)

「CDC82」だけで表すことができます。
文字数も余るので、技の種類までメモすることができます。

そもそもメモする必要あるの...?

それを言われると元も子もないですが・・・
個体値と技の種類を名前にメモすることで、どの子を手元に残しておくか、
ジムバトルやレイド戦にどこの子を使うかで大きな差がでます。多分。

余談

最近、あまり活発にトレーナー活動できてないですが、
英語表記にして微妙に変数名とかメソッド名考えるときの参考にしたりしてなかったりします。

AD

StackDriver のコンソールが反応しないとき

こんなとき

StackDriver のコンソール上から Policy を ON/OFF したいけど、いくら押しても反映されない・・・

なぜか結構発生する・・・・

f:id:omohayui:20180909183308p:plain

どうする

コンソールから操作できないなら、gcloudコマンドがあるじゃない!

▼公式ドキュメント
https://cloud.google.com/logging/docs/reference/tools/gcloud-logging

Cloud SDK のインストール

ローカルに入れてない人は入れよう。
https://cloud.google.com/sdk/docs/

SDK が古い人はアップデートしよう。

gcloud components update

※ 2018/09 時点では gcloud Alpha Commands

Project ID をセット

設定をしたい GCPプロジェクトを指定する。

gcloud config set project [PROJECT_ID]

ログイン

gcloud auth login

ブラウザが立ちあがるのでブラウザ上でログイン

Policy の ON/OFF

gcloudコマンドで実行。

# アラートのオン
gcloud alpha monitoring policies update [POLICY_ID] --enabled
# アラートのオフ
gcloud alpha monitoring policies update [POLICY_ID] --no-enabled

※ [POLICY_ID] = StackDriverのURLに含まれている数値

反映されていることを確認

f:id:omohayui:20180909183050p:plain

off になった!><

Twitterの検索タイムラインウィジェットの廃止と対応策について

Twitterの公式のお知らせ

twittercommunity.com

Deprecating widget settings

In June 2016 we announced that we would be making it much easier for developers to create embedded timelines on their sites, by no longer requiring the timelines to be registered under widget settings. We launched publish.twitter.com to make it much easier to create timeline widgets without requiring you to make changes to your account settings, and to make the embedded timelines more flexible.

廃止スケジュールについて

2018年5月25日

2018年7月27日

  • 既存のタイムラインウィジェットも機能しなくなる
  • 検索タイムラインの場合は、ツイートの検索結果のリンクが表示されるだけになる
  • 検索タイムライン以外のウィジェットは、カスタマイズしている背景色の設定などが効かなくなる

移行先について

  • publish.twitter.com でタイムラインウィジェットを作成してね
  • publish.twitter.com では検索フィルタは使えないから、よしなにユーザータイムライン、リストタイムライン、コレクションのタイムラインに置き換えてね

検索タイムラインウィジェット置き換えの問題点

Replacing Deprecated Timeline Search Widget - Twitter for Websites - Twitter Developers

Twitter Developer Community でも検索タイムラインがウィジェットの設定だけで済まなくなる問題について、
批判や対応策について議論がされていました。

検索タイムラインウィジェットの対応策

batchなどで検索で拾ってきたツイートをコレクションに突っ込んで、 作成したコレクションタイムラインを publish.twitter.com 方式でウィジェットとして表示します。

1. Twitter Search API から検索フィルタにhitする tweet ID を取得する

Standard search API — Twitter Developers

  • Queryでかなり複雑な検索条件でもツイートを引っ張ってこれる
  • リクエストの上限
    • 180 request / 15 min
    • ※ 上限を超えた場合 15分間リクエスト不可になるらしい
  • 1リクエストで取得できるツイートは100件まで
  • since ID で次に取得するツイートを指定してタイムラインを作成できる

2. Twitter Collection API で取得した tweet ID をコレクションに追加する

POST collections/entries/curate — Twitter Developers

  • 1件ずつツイートを追加するなら [POST collections/entries/add] だが、まとめて追加するなら、 [POST collections/entries/curate] を使うべき
  • 100件ずつツイートをコレクションに追加することができる
  • リクエストの上限
    • 1000 request / 15 min

3. publish.twitter.com でコレクションのタイムラインウィジェットを作成する

  • Twitter Publish のガイドの通りに Collection ID をURLに指定してフォームに追加していけばできる

最後に

Developer Community のやり取りを見ていても、保守が大変だから SearhTimelines はやめます、復活することもありません、という Twitter社さんの説明が何度か見受けられました。
メンテナンスコストが高すぎるものはクローズする、というのはビジネス的に正しい判断だと思うのですが、利用者がそこそこいると思われる機能を閉じるにあたって、
もう少し代替対策について親身に相談に乗ってくれれば良かったな・・・と個人的に思いました。
(直接問い合わせても、Developer Community に起票しても、なかなか返事なくて...涙)

※ リクエストの上限などは都度変更するそうなので、最新情報をご確認ください。

AD

GAE SDK の過去バージョンをインストールする

(2018/02/24 追記) PATHにまるっと追加した方が楽というご意見いただいたので

前置き

これはどうしても特定の古いバージョンの Google App Engine SDK for Go を入れたかった為、無理くりインストールしたときのメモなので、 決して推奨できる方法でありません・・・

インストールした環境

  • MacOS 10.12.6
  • GAE 1.9.48
  • Go 1.6.3

手順1(お手軽版)

1. 過去バージョンのSDKが配置されているGCSのディレクトリにアクセス

2. 適当なディレクトリに展開

unzip ~/Downloads/go_appengine_sdk_darwin_386-1.9.48.zip
mv go_appengine ~/tmp/go_appengine_1.9.48

3. PATHに追加

# .bashrc や .zshrc などに
export PATH=~/tmp/go_appengine_1.9.48:$PATH

6. goapp version 確認

% goapp version
go version go1.6.3 (appengine-1.9.48) darwin/amd64

手順2(既存の構成に合わせる版)

1. 過去バージョンのSDKが配置されているGCSのディレクトリにアクセス

2. 展開したディレクトリを下記に配置

/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/

3. binディレクトリを作成

mkdir /usr/local/Cellar/app-engine-go-64/1.9.48/bin/

4. bin/ 下にリンク作成

cd /usr/local/Cellar/app-engine-go-64/1.9.48/bin/
ln -s ../share/app-engine-go-64/appcfg.py appcfg.py
ln -s ../share/app-engine-go-64/bulkload_client.py bulkload_client.py
ln -s ../share/app-engine-go-64/bulkloader.py bulkloader.py
ln -s ../share/app-engine-go-64/dev_appserver.py dev_appserver.py
ln -s ../share/app-engine-go-64/download_appstats.py download_appstats.py
ln -s ../share/app-engine-go-64/goapp goapp

5. /usr/local/bin/ の参照も変える

cd /usr/local/bin
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/appcfg.py appcfg.py
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/bulkload_client.py bulkload_client.py
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/bulkloader.py bulkloader.py
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/dev_appserver.py dev_appserver.py
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/download_appstats.py download_appstats.py
ln -s /usr/local/Cellar/app-engine-go-64/1.9.48/bin/goapp goapp

6. goapp version 確認

% goapp version
go version go1.6.3 (appengine-1.9.48) darwin/amd64