Podcast - Backyard Hatena
TechTalk - Google Cloud Born Digital Summit
ぽ靴な缶
この記事は はてなエンジニア Advent Calendar 2022 2日目の記事です。 みなさんは Slack の RSS アプリ を使っていますか? /feed subscribe FEED_URL で RSS や Atom フィードをチャンネルに流すことができます。 Slack に RSS フィードを追加する | Slack これを使って各種リリースノートやニュースサイトの新着をいろんなチャンネルに流しています。Slack をお使いの皆様もきっとそうしているでしょう。 フィードによって技術の最前線をキャッチアップでき、供給された話題は参加者同士の活発な議論を産む。学習とコラボレーションが同時に促進される素晴らしい機能と言えますね。 . . . 本当か??? 例えば BigQuery のリリースノートを流すとこうなる!! 激流 これ 5 記事あるわけじゃないからな。 こんなフィードをチャンネルに流していると、いつ開いてもフィードしか見えない。 そうして人々は言葉を発しなくなる。 そうやって生まれた自動的な通知ばかりで人が話さなくなったチャンネルをロボット帝国と呼んでいます。人類は機械に支配されたのである。 展開オプション 当然知っているけど、Slack には展開オプションがあって、受け手側で展開を抑制することもできる。 でも全く展開してほしくないわけじゃないのよ、普段の会話では展開してくれるのは便利だし。 展開オプション ロボット帝国に対抗するために生まれた feed-pruning-proxy そんなチャンネルに人間性を取り戻すため pokutuna/feed-pruning-proxy を開発しました。 これはクエリパラメータに与えた URL のフィードの内容を加工して返すアプリケーションです。 いくつかの機能がある。 /p?feed={url} (デフォルト) フィード中の各エントリの本文部分を削除します。 RSS なら description, Atom なら summary と content 記事の URL やタイトルは流れるので、それだけ Slack が展開することに期待します フィードの本文と展開される URL の内容が重複するようなフィードに対して、2回も言わなくていいよという時に使う。 /p?feed={url}&diet (diet モード) フィード中の各エントリの本文部分のマークアップを削除します。 リンクの展開を抑制しつつ本文を出力したい時に使います。 Slack の展開結果が 何もない or 画像だけ のような、何か言ってよというページに対して使う。 こうして得た URL を /feed で購読することで、たかだか1つ展開されるちょうどよい出力がチャンネルに流れるようになります。 実際に記事を読んでるのか そういう気持ちになることもありませんか。それも解決します /p?feed={url}&org={str}&channel={str} とすると これで実際にフィードから記事を読みに行っているのか計測できるようになり、このフィード誰も見てないし remove しましょう、という話ができるようになる。 このログを BigQuery に流し込むと集計や可視化も簡単にできて、みんなが注目した記事とかが分かって楽しいですね。 ご利用頂けます これを GAE にデプロイしておきました。こちらからご利用いただけます。 https://feed-pruning-proxy.an.r.appspot.com/ 迷惑がかかるような使い方をされていたり、金がかかるな〜思ったら予告なく止めるかもしれません。 App Engine または Cloud Run へのデプロイ なのでぜひ自分の GCP プロジェクトにデプロイしてみてください。 App Engine へのデプロイは $ gcloud app deploy でできます。エッジキャッシュもあるし、こういうちょっとしたアプリケーションを公開するのに大変便利ですね。 blog.pokutuna.com また、Cloud Run にデプロイできるボタンを README に置いておきました。押すと Cloud Shell が開いて Cloud Run にデプロイできます。 これを使っています github.com さあロボット帝国に抗い、人間の輝きを取り戻しましょう。 はてなエンジニア Advent Calendar 2022 2日目の記事でした。 昨日は id:arthur-1 さんの Advent Calendar を Mackerel で監視する 〜新卒の暮らし方を添えて〜』 でした 明日は id:mizdra さんです。
ぽ靴な缶
Google Cloud で何かアプリケーションを動かしたい時、いつも App Engine (GAE) を第一の選択肢として挙げています。 なのにみ〜んな Cloud Run に行ってしまう。なぜなのか?? 確かに Cloud Run のほうが新しくて公式に露出が多いし、GAE はこういうランディングページからの言及も消えているので無理もない。Google Cloud 的にもあんまり使って欲しくない雰囲気が漂っている。 cloud.google.com App Engine は GCP 最初期からあるサービスで今年で 14 年目になるらしい。 Google App Engine 単体で出ていて、他のサービスが続いて Google Cloud Platform になったような気がする1。 そんな歴史あるサービスだとレガシー感が漂っていそうなものだけど、全くそんなことはない。 2019 年の 2nd gen 化から改めて使ってみたところ、圧倒的に良くなっているし、今も一線で使えるサーバレス実行環境である。 ポートフォリオサイトの https://pokutuna.com/ も GAE だし、仕事でも社内用の小さなアプリケーションから、多少トラフィックのある API サーバーまで GAE でリリースしてきた。 アプリケーション実行環境の選択肢は色々増えたものの、今でも GAE のほうが楽に安くアプリケーションを構築できる状況や要件はよくある。そんな GAE のいいところや GAE が便利な状況について書いておきたい。 静的ファイルを配れる & エッジキャッシュが使える GAE では、静的ファイルのパスを app.yaml で指定することで静的ファイルを Google のエッジサーバーでキャッシュさせつつ配れる。アプリケーションからのレスポンスでは Cache-Control: public, max-age=3600 などヘッダに含めることでキャッシュさせられる。 アプリケーションの手前にリバースプロキシを置いて静的ファイルを返す構成はよくあるが、GAE は単体でそれ相当のことができる。小規模なアプリケーションでとてもありがたい。手動のキャッシュの破棄はできないが、設定不要の CDN が付いているのに等しい。 GAE がこの機能を持つのは、静的ファイルを返すことは Web アプリケーションの通常のユースケースだからだろう。 どちらも HTTP エンドポイントを実行するサービスだけど、GAE がユーザ向けアプリケーションを公開することに重心を置いているのに対し、Cloud Run はもっと広く Pub/Sub を受けたりジョブを実行したり非同期システムのランタイムを志向しているので、Cloud Run がエッジキャッシュをサポートしていないのもまあ納得できる。 Cloud Run で静的ファイル返したい場合 手前に Cloud Load Balancing を置いて Cloud CDN を有効にする Firebase Hosting で静的ファイルを配りつつ特定のパスを Cloud Run に向ける 別に Cloud Storage に上げて公開して URL を返す 諦めて Cloud Run のアプリケーション内から返す などが考えられる。 1 つ目の、手前に Load Balancing を置いて Cloud CDN を使うのが素直な構成だと思うけど、Load Balancing を立てているだけで月数十ドルかかる。事業でサービスを公開するなら安いコストだけど、個人開発や社内向けの小さなアプリケーションだと地味に払いたくないコストである。 費用を意識するならコンポーネントは増えるがここだけ Firebase Hosting を使うのが良いと思う。 Identity-Aware Proxy (IAP) が Load Balancing 無しに使える IAP を使うと、アプリケーションに手を加えず簡単に Google Workspace ドメインや、特定の Google アカウントに対してのみアプリケーションを公開できる。管理画面や、社内用アプリケーションを作る際によく利用する。 Cloud Run や GKE で IAP を使うためには、Cloud Load Balancing が必要なのだけど、GAE だけは単体で IAP を挟むことができる。特に社内向けアプリケーションは、営業時間中にまばらにトラフィックがあるだけなのに LB 立て続けるのはもったいない。GAE すればコストがタダに近くなる。 cloud.google.com プロジェクトの初めのうちはプロトタイプを IAP かけた GAE で開発しつつ、一般公開前に Cloud Load Balancing を立ててバックエンドサービスに GAE を指定して将来の構成の変更に対応しやすくする、というのもいいでしょう(ちょうど最近やりました)。 今は App Engine にロックインされない かつては、ローカルの開発時に dev_appserver.py とかいうよくわからんスクリプトを使う必要があったり、外部に HTTP リクエストを送るのに専用の urlfetch ライブラリを使う必要があったり、ライブラリを自由に入れられないので自分でアップロードしてインポートパスを通したりする必要があった。ロックインされるし、開発体験が良くなかった。 2nd gen になってからこれらの制約は無くなった。ふつうに書いた Web アプリケーションがそのまま動く。 1st gen は独自のサンドボックスでユーザのアプリケーションを分離していたのと、ユーザ認証からデータストア、タスクキューまで付いたオールインワンのアプリケーション実行環境として提供されていたのもあって、専用ライブラリを使ってね、としていたのだと思う。 2nd gen では、それら GAE にバンドルされていたサービスは各 Google Cloud プロダクトを利用して実装する形になった2。App Engine 特有の実装も不要になり、脱出も容易、つまり、安心して使えます。 cloud.google.com ランタイム選択フローチャート かつてこういう図が公式ドキュメントにあった。 (引用) Which serverless compute platform is right for you? の図 Choosing a Serverless Option | Serverless Guide | Google Cloud (Internet Archive) これをたどると、大半のユースケースで App Engine に辿り着かない? 僕はまず GAE で動かせないか検討して、言語がサポートされていないとか、追加で何かインストールしないといけない要件(Image Magick 要るとか)がある場合に Cloud Run を検討する、という感じでやっている。 過去には、やや複雑化してきた Cloud Function を GAE に置き換えたりもした。GAE は 0 台までダウンスケールできるし起動も早いし、新しいバージョンをリリースする際に段階的にトラフィックを移したり、前のバージョンに戻したりも楽ちん。Cloud Run でもよいけど、Cloud Functions で出来ていた程度のもののイメージを管理したくないという判断もあった。Cloud Functions gen2 はガワだけで中身は Cloud Run なので、今なら Run にするかな。 繰り返しになるけど、LB もいらず IAP もかけられるので、GAE はプロトタイプの開発にも向いていると思う。 まとめ GAE の楽さや安上がりな点について紹介しました。 こんなアプリケーションに集中できるいいプロダクトなのに公式の案内から消えていきつつある!! みんなが GAE でケチりながら激安アプリケーションをホストすると Google が儲からないので隠されているのだと思う。 このエントリで GAE が選択肢に上がるとうれしいです。 App Engine の中心的な考え方であるサーバーレス、サーバー管理不要、イベントドリブン プログラミング、リソースの使用量に応じた料金などは 10 年前から一貫しており、現在も当時と同様に当を得ています。 誕生から 10 年、App Engine の歩みを振り返って | Google Cloud 公式ブログ これかっこいい、おっしゃる通りです 関連エントリ blog.pokutuna.com blog.pokutuna.com Wikipedia(en) の Google Cloud Platform ページの最初の履歴は 2014 年で、記述を見るたぶん合ってるのではないか https://en.wikipedia.org/w/index.php?title=Google_Cloud_Platform&oldid=602909799↩ Google Cloud が提供していないものもあるけど...↩
ぽ靴な缶
Google Cloud で運用しているサービスの Cloud Storage 費用が10月の料金改定から爆増していた。 Cloud Storage 費用(オレンジ部分)が増加 料金改定のタイミングで Cloud Storage のマルチリージョンからマルチリージョン内のリージョンへの転送費用が無料じゃなくなっていた。 Docker イメージの転送費用によるものであれば、Container Registry から Artifact Registry へ移行することでこの費用は無にできる。 cloud.google.com 無料条件がなくなった Google Cloud 内の下り(外向き)ネットワーク費用を見る。 Internet Archive に残っている過去の料金表(2022-05-01)には以下の記述があった。 マルチリージョンにある Cloud Storage バケットからある 1 つのリージョンにある別の Google Cloud サービスへのデータの移動で、両方のロケーションが同じ大陸にある。 無料 現行は、この無料条件がなくなっているうえに、 $0.08/GB とまずまず高めの値段設定になった。 同じ大陸内の異なるロケーション間でデータを移動する場合、転送元バケットは ASIA マルチリージョンに配置され、上記の無料ケースのいずれも適用されない。 $0.08/GB cloud.google.com Container Registry (GCR) のコンテナイメージは Cloud Storage のマルチリージョンバケットに保存され、イメージを利用する実行環境は何らかのリージョンにあるので、この条件にあたってしまう。 今まではイメージと実行環境のロケーションを合わせていれば無料で使えたが1、一通りマルチリージョンバケットからの転送に費用がかかるようになってしまった現在はもう無料で使うことはできない!! asia ほどの費用にはならないが、gcr.io から us 内への転送も $0.02/GB と、無料ではなくなっている。 Artifact Registry を使う Container Registry (GCR) より後に公開された Artifact Registry。 Maven や npm モジュールなどもホストできる。 cloud.google.com 移行するモチベーションは特になかったけど、今回の費用改定で明らかにメリットが生まれてしまった。 Artifact Registry はアーティファクトを保存するリポジトリのロケーションを選ぶことができる。実行環境と同じロケーションにイメージを置くことで、Cloud Storage のネットワーク費用を無料にすることができる!! 移行する作業は特に難しくなく、ドキュメントで移行について案内されている。 cloud.google.com アクセス権限周りに大きな変更があったが、困るようなことはなかった。 GCR 時代のアクセスコントロールは Cloud Storage の IAM ロールでやる感じで、おおざっぱだし分かりづらかったけど、Artifact Registry ではそれ用のロールが設けられプロジェクト単位でも個別のリポジトリに対しても権限を設定できる。 実際の作業としては、API を有効にし、Artifact Registry にリポジトリを作って、GCR に置いてあるイメージを Artifact Registry Registry に上げなおして、k8s manifest やデプロイコマンドなど各所の image 指定を更新する程度でした。 これでグラフの右端のように、また Cloud Storage 費用を無にできたわけです。 今回の値上げといい、ドキュメントの記述といい、かなり Artifact Registry への移行を促してる感ありますね。 Container Registry の進化形である Artifact Registry は、 https://cloud.google.com/artifact-registry?hl=ja Container Registry は引き続き使用可能で、Google Enterprise API としてサポートされていますが、新機能は Artifact Registry でのみ利用可能です。Container Registry には、重要なセキュリティ修正のみ与えられます。 https://cloud.google.com/artifact-registry/docs/transition/transition-from-gcr Google Cloud のドキュメント中の "大陸" (continent に対する訳) って独特の概念だよね、ASIA マルチリージョンの各所は海で隔てられている(台湾, 香港, 東京, ムンバイ, ...)2ものの、同じ文脈で大陸として出てくる "US" や "EU" と同じ扱いであったりもするわけで。でもある日 ASIA は大陸じゃありませーんと言われてもしょうがない気もするし。 https://blog.pokutuna.com/entry/gke-autopilot-storage-egress↩ https://cloud.google.com/storage/docs/locations#available-locations↩
ぽ靴な缶
前回の記事では --project を毎回渡せという主張を展開していたけど切り替える話。 blog.pokutuna.com gcloud コマンドには構成を管理するサブコマンド gcloud config configurations がある。管理するプロジェクトが多くない場合は、カレントプロジェクトを設定しつつ切り替える運用でもよいのではないでしょうか。 また、複数の Google アカウントを切り替える場合も configuration を作って切り替えるのがいい。カレントプロジェクトは設定しない派だけど、個人の @gmail.com と勤務先の Google Workspace のログイン状態を切り替えるのに使ってる。 ちなみに configurations を切り替えても ADC はそのままで、最後に gcloud auth application-default login した時点の認証情報から変わらないのが注意ポイント。 gcloud config configurations Cloud SDK 構成の管理 | Cloud SDK のドキュメント | Google Cloud 触ってみないと微妙に分かりづらいけど、Google アカウントやカレントプロジェクトなど一連の設定を 1 つのエントリとしてまるっと切り替えることができる。 "プロジェクトを切り替えることができる" と説明されていたりするけど、Google アカウントを含む一連の構成を切り替えると思っておかないと、 gcloud config set project でプロジェクトを切り替えたり、ログインし直したりしているとよく分からなくなる。 プロジェクトを切り替えるには、同じ Google アカウントでログインした複数の構成を作って、別々のカレントプロジェクトを設定しておいて、それらを切り替えるという感じ。 # configuration の一覧 $ gcloud config configurations list # configuration を作る & 同時にその設定名がアクティブになる $ gcloud config configurations create NAME # configuration に設定する $ gcloud init # 最初から $ gcloud auth login --project=PROJECT_ID # ログインしてプロジェクト ID 設定する $ gcloud config set project PROJECT_ID # プロジェクト ID だけ設定する $ gcloud config set compute/region REGION # region $ gcloud config set comute/zone ZONE # zone # NAME の設定に切り替える $ gcloud config configurations activate NAME 例のように、region や zone も保存しておけるので、Compute Engine などこれらの引数を要求するコマンドをよく使うなら、設定してあるとちょっと楽になる。 gcloud config に設定できるもの 先に挙げたものが config に設定できるものとしてメジャーだけど、他にもいろんな設定を保存できるし、configuration で切り替えられる。 例えば以下のように設定しておくと、Cloud Functions に新しい関数をデプロイする際に region を省略しても asia-northeast1 になる。 $ gcloud config set functions/region asia-northeast1 設定可能な項目はドキュメントにちゃんとまとまってある。 gcloud config | Google Cloud CLI Documentation あるいは json や yaml で出力してみると雰囲気が分かっておもしろい。 $ gcloud config configurations list --format=json accessibility/screen_reader を true に設定すると gcloud の出力がスクリーンリーダーフレンドリーになったり、core/log_http すると gcloud の API リクエストとレスポンスが出力されたりして面白いですね。 fzf や peco で切り替える よくあるやつ。fzf でも peco でも動くので読み替える。 gcloud-switch() { local selected=$( gcloud config configurations list --format='table[no-heading](is_active.yesno(yes="[x]",no="[_]"), name, properties.core.account, properties.core.project.yesno(no="(unset)"))' \ | fzf --select-1 --query="$1" \ | awk '{print $2}' ) if [ -n "$selected" ]; then gcloud config configurations activate $selected fi } gcloud にはグローバルな `--format=NAME[ATTRIBUTES](PROJECTION) オプションがあって、単体で出力をかなり加工できる。他のツールと組み合わせるときに使うとかわいいですね。 gcloud topic formats | Google Cloud CLI Documentation gcloud topic projections | Google Cloud CLI Documentation あるいは direnv を使っている場合は CLOUDSDK_ACTIVE_CONFIG_NAME 環境変数で切り替えることもできる。チームで configuration 名をプロジェクト名にしてリポジトリに入れたりするのもよいかもしれません。 Cloud SDK 構成の管理 | Cloud SDK のドキュメント | Google Cloud
Type of change Bugfix Description of change The Adagio adapter revert to the previous style of the element itself, rather than computed style. Details is the issue #9035. Resolves #9035 Other information
Type of issue Bug Description Since adding the Adagio adapter, I have found that some ad slots remain hidden. Adagio adapter sends adunit_position which means slot position from window.top with bid request. Adagio adapter temporarily set display: block to the slot element to compute its position, and then reverts to the previous computed style. Prebid.js/modules/adagioBidAdapter.js Lines 791 to 800 in 0acda04 const elComputedStyle = wt.getComputedStyle(domElement, null); const elComputedDisplay = elComputedStyle.display || 'block'; const mustDisplayElement = elComputedDisplay === 'none'; if (mustDisplayElement) { domElement.style = domElement.style || {}; domElement.style.display = 'block'; box = domElement.getBoundingClientRect(); domElement.style.display = elComputedDisplay; } This moves the style from the stylesheet to the elements and away from the control of the website to switch classes. This causes problems when ad slots have placed that switch between display states. For example, when a ad slot is placed in a collapsible sidebar or when content and an ad slot are switched by some condition. In this situation, the ad slot itself or the page part containing the ad slot may have display: none at bidding time and continue to retain the style by Adagio adapter. To avoid this problem, the adapter should revert to the previous style of the element itself, rather than computed style. Steps to reproduce Occurs when SafeFrame is not used and window.top is accessible. Prebid.js/modules/adagioBidAdapter.js Line 763 in 0acda04 } else if (canAccessTopWindow()) { 1. Starts with hidden ad slots <style> .is-hidden { display: none; } </style> <div id="slot1" class="is-hidden"></div> <div id="container" class="is-hidden"> <div id="slot2"></div> </div> 2. Adapter calculates slot positions <style> .is-hidden { display: none; } </style> <div id="slot1" class="is-hidden" style="display: block;"></div> <div id="container" class="is-hidden"> <div id="slot2" style="display: block;"></div> </div> 3. Adapter reverts styles to computed <style> .is-hidden { display: none; } </style> <div id="slot1" class="is-hidden" style="display: none;"></div> <div id="container" class="is-hidden"> <div id="slot2" style="display: none;"></div> </div> 4. Publisher site attempts to display by removing class <style> .is-hidden { display: none; } </style> <div id="slot1" class="" style="display: none;"></div> <div id="container" class=""> <div id="slot2" style="display: none;"></div> </div> Test page Expected results Actual results Platform details Other information When working with Google Ad Manager, gpt.js (pubads_impl_*.js) may eventually work correctly by updating the styles of elements (removing display: none for ad slot). However, problems occur when using other ad servers. It is better not to depend on the gpt.js behavior. And the fix is easy.
Fixed installation commands in README. Installation executables by go get is deprecated in 1.17. https://go.dev/doc/go1.17#go-get no longer works in 1.18 https://go.dev/doc/go1.18#go-get Installation by go install is available from 1.16 (released 2021-02-16). It seems recent, but 1.16 is no longer supported.
原文: https://github.com/OWASP/Go-SCP/blob/248f41d62b7cd17c0ea4f140546fe8888472ece1/src/input-validation/validation.md?plain=1#L138L139