Product Leaders AI 2026に参加!AI時代のプロダクトリーダーに求められることを、あらためて考えた1日

こんにちは!ニーリーでPdMをしている阿部です。

この1年で、AIによって自分自身の働き方は大きく変わった感覚があります。特にデータ分析等の情報収集は、以前とは比べものにならないくらいラクになっており、同じような感覚の方も多いのではないでしょうか。
そんな中で、他のプロダクトリーダーはどう変わってきているのか。そもそも、どう変わるべきなのか。この部分を自分の目で確かめるべく、9月4日開催の「Product Leaders AI 2026」に参加してきました。

Product Leaders AI 2026とは

日本CPO協会が主催する、プロダクトマネージャーやCPO、VP of Productといったプロダクトリーダー層に向けたカンファレンスです。
テーマは「AI時代のプロダクトリーダーシップ ―― 組織・戦略・人間の役割」。ニーリーからはプロダクト開発部門の4名で参加しました。

product-leaders-ai.org

海外の登壇者のセッションは同時通訳の字幕つきで、日本語セッションと交互に進む構成でした。この記事では、特に印象に残ったセッションについて書いていきます。

Session 1:5年で0から2 Billionへ ― 信頼を築くAIプロダクト

リーガルAIを手がけるEvenUpのCPO兼CLO、Saam Mashhadさんのセッション(モデレーターはVeeva JapanのKen Wakamatsuさん)。

顧客の要望を集めて、優先順位を決める。平均的なプロダクトマネージャーがやっているそのベースラインは、自動化できる。

まず印象に残っているのがこちら。実際、自分の体感とも合っています。ニーリーでも、要望や問い合わせの集計、期待効果の見積もり、リリース後の効果分析といったあたりはAIを前提に進めるのが当たり前になってきています。とはいえ、あらためて言い切られると背筋が伸びました...!

もうひとつ面白かったのが、EvenUpの事業の組み立て方です。顧客の代わりに実際の業務を遂行していて、その運用チームを外部に出さず自社で持っている。そして成功指標を顧客と同じにする(社内のオペレーターが顧客と同じノーススターメトリックを持っている)。そうすると自分たちの運用の達成度がそのまま目標になり、うまくいけばワークフローの獲得が進み、市場シェアも取れる。

こういった設計を行うのはまさにプロダクトリーダーの仕事だと感じました。

ほかにも、プロダクトリーダーへのアドバイスとして「ICとして実装や実験まで一貫して関与し、LLMにできること・できないことの直感を養う」(IC=Individual Contributor、マネジメントではなく個人として手を動かす立ち位置)という話もありました。
自分で触って技術の勘所を持っておくことが、事業に踏み込むときの土台にもなるなと感じました。

ニーリーの場合は、エンジニアが事業に染み出す動きが強く、PdMはさらに事業の奥まで踏み込んでいく、という形になっています。出発点は逆ですが、境界を越えて手を動かすという意味では通じるものがあります。自分はどこまで越えられているかな、と考えながら聞いていました。

Session 2:AIがAIを監督する時代へ

WayfoundのCEO、Tatyana MamutさんとHomageのAzusa Hanaiさんのセッション。エージェントがエージェントを監視するという世界観が、純粋に面白かったです。

なるほどと思ったのが監視のタイミングで、問題が起きてから検知するのではなく、役割・目標・従うべきガイドラインをあらかじめ与えておいて事前に評価する。AIに任せる範囲を広げるほど、事後の検知だけでは間に合わないよなと思いました。

キャリアの話も出ていて、マネジメントからICになり、またチームを率いて、またICに戻る、と。エージェントの監督という文脈で聞くと、この行き来の意味が少し違って聞こえました。管理する対象が人間だけではなくなるなら、より手を動かしていないと勘は働かない。この指摘はかなり腹落ちしました。

Session 3:プロダクトの差は、AIの外で生まれる ― 磨き込める人の条件

GOの黒澤さん、カウシェの佐藤さん、クライス&カンパニーの山本さんによるパネル(モデレーターはLINEヤフーの二木さん)。ここは日本語セッションだったので、とっても聞きやすい気持ちになってました...。笑

冒頭の問いがとても印象的でした。

この1年で、AIによってプロダクトは良くなったか?

各社の文脈があるので個別の回答は書きませんが、働き方は明らかに変わった、ただそのぶんプロダクトが圧倒的に良くなったかというと必ずしもそうではない。そんな温度感でした。

また、インサイト収集などのデータ分析はラクになった一方で、特にtoCサービスでは議事録に残らない非言語情報を取れることが価値になる、という話も。つまり自分でヒアリングに足を運ぶ価値そのものだよね、と。AIのカンファレンスで「会いに行け」が出てくるのが、妙に納得感がありました。

もうひとつは、生産性の改善はもう誰でもできる前提になってきているので、より求められるのはトップラインを伸ばす開発ができることという話。昔から言われていることではありますが、AI時代になっても変わらないんだなというのが率直な感想でした。

名刺交換したらデモが始まった

そして、懇親会での会話も面白かったです。
目の前でいきなりプロダクトのデモが始まり(見せていただいて本当にありがとうございました!!)、その後はどれだけ自分のプロダクトに身銭を切っているかという話になり、次はエンジニアが開発にどこまで足を踏み入れるかという話になり……という具合で、プロダクトの話を色々とできて非常に楽しかったです。

最後に

求められる動きの水準が上がっている。1日を通して、そう感じました。
要望を集めて優先順位をつけるような平均的な動きは自動化されていくので、差がつくのはその先。それを高い水準でやり切れるかが、改めて問われているんだろうなと思いましたし、私自身も事業の奥まで踏み込むことを実践していきたいと思います。

登壇者のみなさん、運営のみなさん、現地で話してくださったみなさん、ありがとうございました!

「広島行こ」から始まった PyCon JP 2026 参加レポート — セッションから3日目のスプリントまで

ニーリーでSET(Software Engineer in Test)を担当しています、宮内(@miyakun)です。 日頃は自動E2Eテストの開発・運用やテスト環境の整備、テストデータの自動生成などに取り組んでいます。
最近ではDjangoを使ってテストデータ作成APIを開発するなど、Pythonを書く機会もあります。
(ニーリーらしくPdEに染み出していくべく、キャッチアップの日々です!)

さて、今回はPyCon JP 2026参加のレポートをお届けします!

「広島行こ」から始まった

ある日、マネージャーの野呂(@ev_yug)から突然DMが届きました。

(赤魔道士は気にしないでください)

今回が自分にとって初めてのPyCon JPへの参加です。それどころか、プログラミング言語のカンファレンスに参加すること自体が初めて。
これまで参加する機会はなかったものの、以前からプログラミング言語のカンファレンスには一度行ってみたいと思っていたので、二つ返事で参加を決めました。
なお、ニーリーはPyCon JP 2026にSilverスポンサーとして協賛していました。協賛に至った背景や、ニーリーとPythonの関わりについては事前の記事で紹介していますので、こちらもぜひご覧ください。

nealle-dev.hatenablog.com

ちなみに自分自身は広島へ行くのも、仕事で出張するのも今回が初めて。さらには新幹線のチケットを自分で取ることも初めてでした!
新幹線の予約から何から妻に助けてもらいながら、なんとか準備完了。
ありがとう、マイ・ディア・ワイフ。


さて、ここからは、3日間で参加したセッションやスプリントについて振り返っていきます。

会場の広島国際会議場
弊社のロゴも確認できました

初めてのPyConで気になったセッション

今回が初めてのPyCon参加というだけでなく、自分自身Pythonについてはまだまだ発展途上です。

そのため、初級者向けかつ日本語で聞けるセッションを中心に、その中でも自分の経験や普段の仕事と重なるテーマを選んで参加しました。

ここからは、その中からいくつかのセッションを振り返ります。

Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた(佐藤樹さん)

speakerdeck.com

以前から勉強の一環で「ブラウザを自作してみたい」と思っていたこともあり、参加しました。

Webページの取得やHTML・CSSの解釈といったブラウザの振る舞いは、IETFやWHATWG、W3Cなどが公開している仕様として文書化されています。「ブラウザの作り方は、全部文書になっている」という話を聞き、こうした仕様に沿って進めていけば、自分でも安心してブラウザの実装に挑戦できそうだと感じました。

普段、自動E2Eテストで当たり前のようにブラウザを操作している自分にとって、そのブラウザ自体がどう作られているのかを知れたのも面白かったです。
そして最後にここまでスライドを映していたブラウザが、実は今回の自作ブラウザだったと明かされたのが、あまりに素敵すぎました。

自分自身もこのセッションを踏まえて、ブラウザ自作に挑戦してみようと思います。

AI 時代に学ぶ好きなルール・嫌いなルール Linter 編(根本翔多さん)

speakerdeck.com

普段の開発でもLinterを使っていますが、「なぜこのルールがあるのか」まで深く考える機会はあまりありませんでした。
しかし、AIによって大量のコードが生成されるようになった今だからこそ、Linterによるチェックがより重要になっているという話は、確かにそうだなと納得できるものがありました。

また、「嫌いなルール」として紹介されていた、コードの長さや個数を数える系のルールも印象に残りました。AIがコードを書く機会が増えている今、単純に行数や個数を制限するルールは、以前ほど必要ではないのかもしれないという話は興味深かったです。

普段開発しているプロダクトで、どんなルールを設定しているのか改めて確認しつつ、最適解を模索してみたいと思います。

まじでpythonなんもわからん!を救う会(harukiさん)

www.docswell.com

タイトルを見た瞬間に「これは聞いておきたい」と思ったセッションでした。

「Pythonはプログラミング言語です」というところから始まり、標準ライブラリでできることや、初心者が難しく感じやすいポイントなどが紹介されていました。

初心者に寄り添った内容で、普段は仕事でAPIを書くために使うことが多いPythonを、もっと気軽に仕事とは違う分野でも使ってみたいと思えるセッションでした。

異なる設計思想のフレームワークを経験して得た学び(Laravel開発からDjango開発へ)(天久秀樹さん)

speakerdeck.com

自分は以前PHPエンジニアとして2〜3年ほどLaravelを使っており、最近になって初めてDjangoを使ったAPI開発に取り組みました。

まさに自分のキャリアと重なるタイトルだったので、こちらもぜひ聞きたい!と思い参加しました。

セッションでは、LaravelとDjangoで一般的に見られるディレクトリ構成の違いなどを例に、それぞれのフレームワークが持つ設計思想について紹介されていました。

自分がDjangoを初めて触ったときに違和感があったのがViewという名前です。LaravelのControllerと比較しながら理解していたため、「これをViewと呼ぶんだ」と戸惑った記憶があります。

セッション後に登壇者の方へ「最初にDjangoを触ったとき、Viewという名前に違和感はありませんでしたか?」と聞いてみたところ、「ありました!」とのこと。

自分が感じていた違和感を共有でき、非常に嬉しかったです。

セッションを聞いて、Djangoを触ったときに感じていたLaravelとの違いも、単なる書き方の違いではなく、それぞれのフレームワークが持つ設計思想の違いとして捉えると面白いなと思いました。

せっかくLaravelを使ってきた経験があるので、「Laravelではどうだったか」「なぜDjangoではこうなっているのか」と考えながら、Djangoについてもっと深掘りしてみたいと思います。

3日目はスプリントへ — 悪意あるPythonパッケージを調査する

PyCon 3日目は、特定のプロジェクトやテーマに興味を持つ参加者が集まり、開発や調査などに取り組むスプリントに参加しました。

セッションを聞くだけでなく、実際に手を動かして参加できる機会だったので、自分も何かやってみたいと思っていました。

そこで参加したのが、「DIVE into Evil — 悪意あるPythonパッケージを解剖する」です。

悪意あるパッケージは、どうやって紛れ込む?

自分は、有名なパッケージとよく似た名前を公開し、利用者のタイプミスなどを狙う「タイポスクワッティング」に注目して調査しました。

AIにも候補を聞きながらPyPIを検索し、有名なパッケージと似た名前のものがないかを探していきます。同じグループでは、1文字ずつ名前を変えたように見えるパッケージが連続して公開されている例も見つかりました。

もちろん、それだけで悪意あるパッケージだと判断することはできません。今回は実際にパッケージを動かすところまでは踏み込まず、PyPI上で似た名前のパッケージを探すことを中心に調査しました。

普段は何気なくパッケージをインストールしていますが、「そのパッケージは本当に自分が使おうとしているものなのか」という視点でPyPIを眺めてみるのは面白かったです。

「やはりコード書きますか!」残り2時間からのスプリント

午後、野呂が合流。

悪意あるパッケージについて理解できてきた一方で、自分はPyPIで似た名前のパッケージを探し続けている状態。
「このままだとタイポ探すマンで終わってしまいそうですね……」
そんな話をしていると、
「じゃあ、新しくスプリント立てましょうか!」
と、まさかの新しいスプリントを立ち上げることに。

別のチームで「雑Instagram」(最低限の機能だけで作るSNS)を作っていたことから、テーマは「雑Twitter」に決まりました。

野呂が参加者へ呼びかけると、学生の皆さんが3人も集まってくれました。
展開が早い。
こうして残り約2時間、5人での「雑Twitter」開発が始まりました。

残り2時間、とにかく雑に作る

バックエンドにはFastAPIを使い、APIはログイン・新規投稿・投稿一覧取得の3つだけ。

残り時間も少なかったため、DBは使わずJSONファイルにデータを保存するシンプルな構成にしました。ログインではユーザーIDとパスワードを確認し、認証したユーザーが投稿できるようにするなど、短時間でも一連の流れが動くように仕様を決めました。

フロントエンドには、前日のクロージング基調講演で紹介されていたPyxelを採用。レトロな見た目のTwitterを目指します。

自分はAPI設計と新規投稿APIを担当し、学生の皆さんにはログインAPI、投稿一覧取得API、Pyxelを使ったフロントエンドをそれぞれ担当してもらいました。

Pyxelで作成した雑Twitterのログイン画面

初めて会ったメンバーで残り2時間。「ここはどうします?」「APIはこうしましょう!」と相談しながら、とにかく手を動かしていきました。

時間切れ、夏が終わった

自分が担当した新規投稿APIはSwagger UIでの動作確認を終え、PRを出すところまで進めることができました。フロントエンドも形になってきましたが、ここでタイムアップ。
完成には届かず、成果発表もできませんでした。
それでも、初めて会った学生の皆さんと、その場で役割を決めて一気にコードを書く時間はとにかく濃かったです。

終わった瞬間に思ったのは、
「夏が終わった……」
でした。

最後には一緒に開発した学生の皆さんとSNSも交換し、残り2時間から始まった「雑Twitter」スプリントは終了しました。

3日間参加してみて

今回が初めてのPyCon、そして初めてのプログラミング言語のカンファレンスへの参加でした。

参加前は「Pythonに詳しい人ばかりで、少しハードルが高いのでは」と思っていましたが、実際には初心者向けのセッションも多く、3日間フルで楽しむことができました。

パーティーやスプリントでは、普段からPythonを使っている方々や学生、運営の方々など、いろいろな方とお話しすることができました。皆さん本当にPythonやPyConが好きなんだなと感じる場面も多く、そんな方々と直接話せたことが貴重な機会でした。
業務への持ち帰りとしては、まず普段開発しているプロダクトのLinterの設定を見直して、「なぜこのルールが設定されているのか」というところまでしっかり確認してみようと思います。


滞在中のホテルでムカデに遭遇したり、帰りには広島駅へ向かっているつもりで乗った電車が、実は広島駅へ向かっていなかったりと、最後までハプニングもありました。

そのときは、たまたま同じ電車に乗っていたPyCon運営の方が声をかけてくださり、広島駅へ向かっていないことを教えていただきました。あのまま乗り続けていたら、果たしてどこへ向かっていたのか……。

そんなハプニングも含めて、無事に3日間のPyConを終えることができました。

そして、自分たちのPyConはもう少しだけ続きます

9月9日には、PyCon JP 2026にプロポーザルを提出したものの惜しくも採択されなかった企業が集まって発表する「非公式リジェクトコン」を、Sansan様、RevComm様と共同開催します!

一緒に行ったマネージャーの野呂が登壇します!

sansan.connpass.com

また、今回のスプリントでは学生の皆さんと一緒に開発する機会にも恵まれました。
弊社では現在、プロダクトエンジニアやプロダクト開発リードを募集しているほか、学生向けのインターン募集も始まっています。
この記事を通して「こんな人たちと一緒に働いてみたいかも」と少しでも思っていただけた方がいれば、ぜひ覗いてみてください。

▼ プロダクトエンジニアの募集はこちら herp.careers

▼ プロダクト開発リードの募集はこちら herp.careers

▼ 学生向けインターンの募集はこちら nealle-dev.hatenablog.com

最後になりますが、PyCon JP 2026の開催に関わってくださった運営の皆さま、登壇者の皆さま、そして現地でお話しした皆さま、ありがとうございました!

自撮り棒で頑張って撮った写真

Google Cloudのセキュリティ強化を爆速で! - Google Cloud minimum viable secure platformのススメ

はじめに

みなさん、こんにちは! ニーリーでSREをしています、宇田川(X: @Ryoheiengineer)です!

今回は、Google Cloud minimum viable secure platform(GCMVSP)を使って、Google Cloudのセキュリティ強化を約1ヶ月で実施した取り組みについてご紹介します。

「Google Cloudを使い始めたけれど、セキュリティ対策は何から手をつければいいの?」「Google CloudのBigQueryなど一部は使ってるけど、本格的に使っているわけではないのでセキュリティ対策全然やれていない」と悩んでいるSRE・ソフトウェアエンジニアの方に向けて、私たちの判断プロセスと実際にやったことを話していきたいと思います!

背景: Google Cloudの利用拡大

ニーリーではAWSをメインに利用しており、Google Cloudは一部サービスだけ、限定的な利用の仕方をしていました。 そのため、Google Cloudに対するセキュリティ監視・対策は最低限の範囲にとどまっている状況でした。

しかし、Google Maps APIやVertex AI、BigQueryなど、Google Cloudがビジネスクリティカルな機能を担う場面が徐々に増え始めました。 また、SREチーム以外のチームもすでにGoogle Cloudを利用しており、今後さらに利用が増えていく見込みがあったため、優先度を上げてさらなるセキュリティ強化に取り組むことにしました。

何から始める? - 「Google Cloud minimum viable secure platform」という選択

セキュリティ強化と一口に言っても、やれることは無限にあります。 最初に悩んだのは「何を、どこまでやるか」でした。

当初は、世の中のベストプラクティス集を読み込んで自前でTODOリストを作る案も検討しました。 しかし、この方法は調査だけで大きな工数がかかってしまいます。 そこで採用したのが、Google Cloud公式の「Google Cloud minimum viable secure platform(GCMVSP)」です。

GCMVSPはGoogleが提供している、セキュアなプラットフォームを構築するために必要な項目を優先度付きのチェックリストとしてまとめたガイドラインです。 「何をやるべきか」と「どれから着手すべきか」が示されているため、自前でTODO化する工数を丸ごと削減できます。

GCMVSPの特徴は大きく3つあります。

1つ目は、レベルで分けられていることです。 規模やユースケースを問わずすべての組織におすすめされる「基本(ベーシック)」を起点に、「中級」「高度」と段階的にレベルが定義されており、自分たちの状況に合わせてどこまでやるかを選べます。今回はまず、このベーシックレベルを実施することにしました。

2つ目は、カテゴリ分けされていることです。 「認証と認可」「組織」「インフラストラクチャ」「データの保護」「ネットワーク セキュリティ」「モニタリング、ロギング、アラート」の6つのカテゴリに整理されており、カテゴリごとに対応すべき項目が示されています。

3つ目は、対応方法だけでなく、予防的な制御まで示されていることです。 個々の項目を直して終わりではなく、組織ポリシーによって「今後もルールが破られない」状態を作れるようになっています。 既存の是正と将来のガードレールをセットで進められるのが、GCMVSPに沿うことの大きなメリットだと感じています。

Google Cloud minimum viable secure platformの例: https://docs.cloud.google.com/docs/security/gcmvsp/authentication-authorization?hl=ja

このガイドラインを踏まえて実施したことは大きく分けて下記の2つです。

  1. ベーシックレベルの対応項目の実施
  2. 組織ポリシーのTerraform管理(IaC化)

順番に紹介していきます。

やったこと①: ベーシックレベルの対応項目を実施

GCMVSPのカテゴリに沿って、ベーシックレベルの対応項目を実施していきました。 本記事では「インフラストラクチャ」「データの保護」「ネットワーク」「モニタリング」の4カテゴリの取り組みを紹介します。

インフラストラクチャ: 組織ポリシーで攻撃面を事前に塞ぐ

Compute Engine関連では、VMシリアルポートアクセスの無効化(compute.disableSerialPortAccess)と外部IPv6の無効化(compute.disableVpcExternalIpv6)を組織ポリシーで適用しました。 組織レベルで適用しているため、将来新しいプロジェクトでVMを使い始めたときにも、最低限のセキュリティが自動で担保されます。

データの保護: バケットのアクセス制御をIAMへ一元化

Cloud Storageについては、全プロジェクトのバケットのACL設定を調査し、個別ACLが残っていたバケットを均一なバケットレベルアクセスへ移行、アクセス制御をIAMに一元化しました。 また、Cloud SQLのパブリックIP制限(sql.managed.restrictPublicIp)についても、将来の予防策として組織ポリシーによる制限を実施しています。 ネットワーク: 未使用のdefault VPCを削除 サブネットも調査し、自動作成されたまま使われていないdefault VPCを整理しました。VPCに接続しているリソースがないこと(Cloud RunやCloud FunctionsもVPCコネクタ未使用)を確認したうえで、未使用のdefault VPCをまるごと削除しています。 使っていないネットワークは、消してしまえば攻撃面そのものがなくなります。

モニタリング: 通知先を「人」ではなく「グループ」に

重要な連絡先(Essential Contacts)として、支払い・法的事項・プロダクト更新・セキュリティ・サスペンション・技術的問題の6カテゴリの通知先を組織レベルで設定しました。ポイントは、個人ではなくメーリングリストを登録したことです。担当者の異動や退職で重要な通知が誰にも届かなくなる、という事故を防げます。

また、請求異常についても費用異常の管理通知と予算アラートを設定しました。 予算はプロジェクト単位ではなく組織単位で作成しています。 プロジェクト単位の管理は運用コストが大きいため、まずは組織単位で異常に気づける状態をゴールにしました。

なお、本記事でご紹介したのは取り組みの一部です。ベーシックレベルにはほかにも対応項目があり、書ききれなかったものも複数対応しています。

やったこと②: 組織ポリシーのTerraform管理(IaC化)

最後の仕上げがTerraformによるIaC化です。 組織ポリシーをTerraformでコード管理し、設定変更が必ずPRレビューを通る状態にしています。

組織ポリシーのなかでもマネージド制約やカスタム制約といったタイプのポリシーは、ドライランモードで適用できます。 ドライランでは違反してもオペレーションはブロックされず、違反内容が監査ログに記録されるため、既存のリソースにどんな影響があるかを事前に把握したうえで本適用に進めます。

Google Cloudの組織ポリシーの画面

Terraformでは google_org_policy_policy リソースの dry_run_spec でドライランを表現できるため、私たちはドライランで検証してから本適用する、という構成にしました。 以下は、サービスアカウントキーの新規作成をブロックするマネージド制約の例です。

まずはドライランで影響を観察(ステップ①)し、問題がなければ本適用する(ステップ②)という手順を踏めるようmoduleを整備し、既存リソースを壊す心配なく安全にガードレールを敷いています。

ステップ①

locals {
  # === dry run検証用ポリシー ===
  org_policies_for_dry_run = {
    "iam.managed.disableServiceAccountKeyCreation" = true
  }

  # === 本番適用ポリシー ===
  # dry run検証完了後、ここに移行
  org_policies = {
  }
}

# dry run検証用
module "org_policies_dry_run" {
  source   = "../modules/org_policy_dryrun"
  for_each = local.org_policies_for_dry_run

  organization_id = local.organization_id
  constraint      = each.key
  enforce         = each.value
}

# 本番適用
module "org_policies" {
  source   = "../modules/org_policy"
  for_each = local.org_policies

  organization_id = local.organization_id
  constraint      = each.key
  enforce         = each.value
}

ステップ②

locals {
  # === dry run検証用ポリシー ===
  org_policies_for_dry_run = {
    }

  # === 本番適用ポリシー ===
  # dry run検証完了後、ここに移行
  org_policies = {
    "iam.managed.disableServiceAccountKeyCreation" = true
  }
}
# 以下、ステップ①と同様

最後に

今回は、Google Cloud minimum viable secure platform(GCMVSP)のベーシックレベルに沿ったセキュリティ強化の取り組みについてご紹介しました。 ベーシックな項目に対応すると同時にTerraformによるIaCを進めたことで、セキュリティレベルを上げながら今後の開発効率を上げる仕込みもできました。

セキュリティ強化はやれることが無限にあるように見えますが、GCMVSPはレベルやカテゴリを分けて対応項目が記載されているので、自分たちがやるべきことを迷わずに実施することができます。

「Google Cloudのセキュリティ、何から始めればいいかわからない」という方は、ぜひGCMVSPのベーシックレベルから始めてみることをおすすめします。

ニーリーでは、こうした仕組み化・セキュリティ強化を一緒に進めてくれるエンジニアを募集しています。本記事を読んで少しでもご興味を持っていただけた方は、ぜひお気軽にご連絡ください!

プロダクト開発の採用サイトはこちらから!

jobs.nealle.com

実践就業型!28卒向け長期エンジニアインターン募集を開始します!!!

こんにちは。DevHRの榎本(@motumotuo)です。

ニーリーは、月極駐車場のオンライン契約サービス「Park Direct」を中心に、マルチプロダクトを展開しているスタートアップです。駐車場という、まだほとんどデータになっていない領域を扱いながら社会のインフラ(Mobility OS)を作るべく、日々開発を進めています。

そして私たちはこの度、長期インターン(プロダクトエンジニア、SRE)の募集を開始します!
9月から順次スタート予定です!(フルリモート可/週2〜3日から/時給2,000円〜)

28卒の方を中心に考えていますが、学年は問いません
「実務経験を積んでみたい」「ちゃんと開発できるところで働きたい」、そういった思いを持っている方にぜひ読んでいただきたいと思います。

長期インターンをする上での推しポイント

1. 実際にユーザーに使われているプロダクトの開発ができます

ニーリーでは、最初から実際のプロダクトの課題解決を受け持ってもらいます。「サンプルアプリを作って発表して終わり」と言うことはありません。
なぜこの設計になっているのかを考えつつ価値提供のポイントを見極め、レビューを通じてコードをブラッシュアップする。このプロセスを通じて技術力を磨いていくことができます。

しかも相手にしているのは、駐車場契約というリアルなドメインです。明確な正解がない場合も、チームで答えを出していくことになるため、事業にしっかりと向き合う経験ができます。

2. 「フルリモート」も「隣で教えてほしい」も歓迎です

地方に住まわれている方のフルリモートでの参画も大歓迎です。オンボーディングもレビューもリモート前提で回せる体制があります!

一方で「ちゃんとオフィスに行って、隣で教えてもらえる方がありがたい」という気持ちも、とてもよくわかります。

なのでニーリーでは、進め方を選べるようにしています。

  • 完全リモートで、テキストとオンラインMTG中心に進める
  • 週に何日か、自分で決めた頻度でオフィスに出社して、対面で相談しながら進める
  • 最初の1ヶ月だけ出社多めにして、慣れたらリモートに移行する

このあたりは、やりやすい形に合わせて相談させてください。オフィスは東京都中央区日本橋にあります(出社の場合は交通費支給)。

3. 「OJTで終わり」にしない、サポート体制

配属チームでのOJTはもちろん行います。が、ニーリーにはもうひとつ、DevHR(Developer's HR)という役割があります。

これは開発組織専任のHRで、所属しているVPoEの菊地と私(榎本)はエンジニア経験があります。インターンの期間中は、この2人が現場とは別の立場から全面的にサポートします。

たとえば、こんなことを相談してもらえます。

  • 仕事で詰まっている部分へのアドバイスがほしい
  • 就活、どう動けばいいのか分からない。キャリア的な相談に乗ってほしい。

現場とは別に、斜めからサポートするメンバーがいるというのは、想像以上に効くと思うので、ぜひぜひ安心して飛び込んできてください。

実際にどんなことをやるのか?

ニーリーはマルチプロダクト展開をしているので、興味の持ちどころがたくさんあります。具体的にどんなことをやるかはぜひお会いして相談させてほしいですが、例えばこんなことをお願いするかもしれません!

  • ソフトウェア開発
    • AIを業務に組み込んだ新規プロダクトの開発
    • エンタープライズの非定型データを使い倒せる「資産」へ変換するプロダクト開発
  • SRE業務
    • クラウドインフラアーキテクチャの設計・構築
    • リリースエンジニアリングのアップデート

なお、ニーリーで使われている主な技術スタックは下記の通りです。

  • バックエンド:Python + Djangoもしくは共通基盤であれば Kotlin
  • フロントエンド:AngularまたはNext.js(TypeScript)
    ※プロダクトの性質に合わせて使い分けています。
  • インフラ:AWS(TerraformによるIaC化済み)

実際に、こんな人が働いていました

「長期インターンって、結局どこまでやらせてもらえるの?」というのも、気になるところだと思います。過去にニーリーで働いていた学生が、自分で振り返りを書いてくれているので、そちらを紹介させてください!

ひとりは、プログラミング歴3年弱の状態でジョインして、およそ1年半、下記を担当していました。

  • Amazon Connectを使ったコンタクトセンターの開発・運用
  • ビジネス側が使う社内ツールの開発
  • コーポレートサイトの内製化プロジェクト

いずれの業務も社内外のステークホルダーと常に会話しながら実際の事業グロースに貢献していただきました!

モビリティSaaSの会社って何?ニーリーで1年半長期インターン生として働いてみて

もうひとりは、AWSをほとんど触ったことがない状態から入って、Park DirectのフロントエンドのCD構築、バックエンドのコンテナビルドなどを担当していました。最終的にはAWS Developer Associateも取得しています。

インフラ業務,はじめました

これらは少し前の記事ではあるのですが、本番に入るものを任されていくという進み方は同じです!
記事を通じて文化や、進め方などを感じ取ってもらえると嬉しいです。

募集要項

こんな人に来てほしい

  • 知的好奇心旺盛な方
  • 巨大な未整備領域に、面白さを感じられる方
  • 動くものを作るだけでなく、良いものを作ることに興味がある方

これがあるとなお嬉しい

  • 何かを最後まで作り切ったことがある(規模は問いません)
  • 他社インターンなどでのシステム開発経験
  • ハッカソンやチーム開発の経験
  • 技術ブログやOSSなど、何らかのアウトプット

逆に応募時点で必要ないもの

  • DjangoやNext.js、Angularの実装経験 → 入ってから覚えれば十分です!
  • 完璧なポートフォリオ → 作りかけでも、何を考えて作ったかを話せれば大丈夫です!

詳細

対象 28卒中心ですが学年不問です!
期間 3ヶ月〜(1年以上の長期も歓迎です)
稼働 週2日以上/1日4時間〜相談可。試験期間・研究の繁忙期は中断などの調整が可能です。
それ以外の事情でも、稼働時間を調整できるのでご相談ください!
給与 時給2,000円〜
勤務地 東京都中央区日本橋堀留町1丁目9-8(またはリモート勤務)
交通費 全額支給
雇用形態 アルバイト雇用契約

選考フロー

  1. こちらのフォームから応募をお願いします。
  2. カジュアル面談(オンライン)
    選考ではないので、まずは「話を聞いてみたい!」くらいの温度感で来ていただければ大丈夫です!
  3. 面接1回〜
  4. 合否連絡

最後に

ここまで読んでいただいてありがとうございます。インターンに参加したからといって、ニーリーに入社しなければいけないということはありません!

なお、ニーリーがなぜこのタイミングで新卒・インターン採用に踏み切ったのかについては、別の記事で改めて書きます。そちらもよかったら読んでください。

お会いできるのを楽しみにしています!!

まずはカジュアル面談から!
応募フォーム

XのDMでは質問も受け付けています!
VPoE 菊地(@_tinoji)
DevHR 榎本(@motumotuo)

PyCon JP 2026 にSilverスポンサーとして協賛いたします

ニーリーは、2026年8月21日(金)から開催される「PyCon JP 2026」に Silver スポンサーとして協賛いたします。

PyCon JP 2026 の概要

  • 日程: 2026年8月21日(金)- 22日(土)(スプリントは23日開催 @広島大学 東千田キャンパス)
  • 会場: 広島国際会議場
  • 公式サイト: 2026.pycon.jp

「PyCon JP」は、プログラミング言語 Python に関する日本最大級の国際カンファレンスです。 Python ユーザーが集まり、Python や Python を使ったソフトウェアについてのセッション、情報交換・交流をします。 Python にまつわる様々な分野の知識や情報を交換することで、新たな友達やコミュニティとのつながり、ビジネスチャンスを増やせる場所となっています。

協賛の背景

ニーリーは、2019年にローンチした月極駐車場オンライン契約サービス「Park Direct」をメインプロダクトとして事業成長してきました。
2021年には法人向けサービスとして「Park Direct for Business」を、そして昨年2025年には1日単位で駐車場予約ができるサービス「ワンデイパーク」の提供を開始しています。
さらにこれらにとどまらずモビリティを通じた社会のインフラ(OS)となるべく、下記のようなモビリティプラットフォーム構想を進めており、プロダクト全体としてもまた一段と大きな変化を遂げようとしています。

モビリティプラットフォーム構想

これらを実現する上でバックエンドのメインを支えている技術がPythonです!
1つ目のプロダクト「Park Direct」の開発初期から主要技術スタックとしてPython/Djangoを利用し、プロダクトのスケール・事業拡大を実現してきました。
ここまで事業を拡大できたのはPythonそしてそれを支える技術コミュニティのおかげであり、今回のスポンサーを通じて、当社の事業拡大を支えてきたPython・技術コミュニティへ還元していければと考えています!

ニーリーのアーキテクチャ概観

またニーリーではPythonを主力言語として、事業価値を創出するプロダクトエンジニアを絶賛募集中です。
ぜひぜひ下記リンクもご覧ください!!

herp.careers

herp.careers

おわりに

開催期間中は、当社のエンジニアからは、野呂宮内の2名が現地参加予定です! 2人の取り組みもぜひご覧ください!

nealle-dev.hatenablog.com

note.nealle.com

お見かけいただいた際はぜひ声かけてください〜〜〜!!!

ベースマキナのアクションをコード管理に移行した話

はじめに

こんにちは、SREチームのkuboです。

今回は、社内で利用している管理画面ツール「ベースマキナ」のアクションを、Web UIでの手作業管理からGitHub上でのコード管理に移行した話を書きます。やったことを洗い出して記事として書いてみたら、ベースマキナの機能の紹介というより「一度設定したら戻せない」仕様にどう向き合いながら他チームと合意をとるか、みたいな進め方の話が中心になりました。

同じような移行を検討している方の参考になれば嬉しいです。

きっかけ

ベースマキナには、SQLやAPI呼び出しを「アクション」として登録しておくと、画面上から誰でも安全に実行できるようになる機能があります。ニーリーではこのアクションを使って、本番データベースに対する定型的な操作など、繰り返し発生するオペレーションを省力化してきました。

ただ、活用が進んでアクションが増えるにつれて、運用上の困りごとも見えてきていました。アクションはWeb UIで誰でもすぐSQLを書いて保存できる反面、作成や変更にレビューが挟まらず、差分も残りません。 作った本人しか中身を把握していないアクションが増えていき、データベースのスキーマ変更にSQLが追従できているかどうかの確認も難しくなっていました。

そんな折、あるアクションのSQLがテーブルのスキーマ変更に追従できるかをベースマキナの担当者に相談したところ、「コード管理」という新機能がリリースされていたことを教えてもらいました。アクションをWeb UIで直接編集するのではなく、GitHub上でTypeScriptのコードとして管理し、PRレビューを経てから反映できるという機能です。

これなら、スキーマ変更の追従だけでなく、抱えていた課題もまとめて解決できるのではないかと感じ、アクションをコード管理に移行することにしました。

「一度指定したら戻せない」ことに気づく

コード管理を有効にするには、まず「開発環境」をプロジェクトに指定する必要があります。ここでいうプロジェクトとはベースマキナ側の管理単位のことで、その中には開発用・本番用といった複数の「環境」があります。ニーリーでは1つのプロジェクトの中に複数のチームのアクションが同居してきました。

公式ドキュメントを読み込んでいくと、この開発環境の指定にはかなり重い制約があることが分かりました。

  1. 開発環境の指定はプロジェクト単位で行われ、一部のアクションだけを対象にすることはできない
  2. 一度指定すると、未指定の状態には戻せない
  3. 指定後はアクションの編集やバージョン管理が、開発環境に集約され、他の環境では実行しかできなくなる

開発環境指定の説明図

つまり、Park Directのプロジェクトにこの設定を入れた瞬間、そこに同居している他のチームのアクションの運用フローまで、後戻りできない形で変わってしまいます。 本格的な導入の前に試験的にやりたかったことは、特定のオペレーションをコード化されたアクションで作成することによる動作確認でしたが、そのためだけにプロジェクト全体を不可逆に移行するのは割に合わないと判断しました。

そこで、次の二段階のアプローチを取ることにしました。

  1. 検証用の別プロジェクトを用意し、そこでコード管理の挙動を一通り確認
  2. 運用のイメージが固まった段階で、実際にアクションを作っている各チームと合意形成した上で、本番のプロジェクトに適用する

検証用プロジェクトで確かめたこと

検証用のプロジェクトでは、想定より多くのことを確認できました。

個人的に一番大きかったのは、データソースの仕様の把握です。 ベースマキナ側の設計では、データソースの「定義」は全環境で共有し、実際の接続先だけを環境ごとに設定する形になっています。 ところが、我々がこれまで利用していたPark Directプロジェクトでは、開発・ステージング・本番それぞれに別々のデータソースを並べて登録するという、公式の想定とは異なる構成になっていました。 この構成の違いは、後の本番移行の設計にそのまま響いてきます。

各チームへのヒアリングと方針決定

検証と並行して、実際にベースマキナでアクションを作っている各チームに現状のヒアリングを行いました。聞いたのは主に3点で、どこでアクションを作っているか、どのくらいの頻度で使っているか、そしてコード管理への移行に応じられそうかという内容です。

出てきた懸念は、大きく2つありました。

1つ目は、レビューのコストに対する懸念です。
開発メンバーがレビュアーになる場合、レビューのためにベースマキナにおける設定ファイルの書き方まで覚える必要があるなら割に合わないのではないか、という指摘でした。これについては、人によるレビューは、SQLの中身や意図の妥当性を見ることに集中してもらうべきという前提の元、 CIに型チェックを組み込めば参照ミスや型の不一致といった機械的に検出できる誤りはそこで弾ける、という整理で合意しました。

ベースマキナのコード管理が型安全になっていることが前提だったからこそ、できたのだと思います。
また、型チェックだけではなく、ベースマキナ社自身が提供している「Agent Skill」というAIエージェント向けのスキルが、設定ファイルの作成という観点ではかなり役立ちました。(詳しくは「コード管理によるメリット」で後述します!)

2つ目の懸念は、PRマージ前に動作を確認したいという要望でした。
通常の開発であれば、動作確認をして、問題がなければPRマージという順番になるはずです。しかしベースマキナのアクションは手元では動作確認などできず、実際のデータソースに接続されたベースマキナの環境上で動かす必要があります。 そのため、コードが環境に反映されるためにはPRマージが必須であると、マージして動作確認した後にNGだった場合に、再度PRを作り直す手戻りが発生してしまいます。

これは、開発環境であればコード管理下でもこれまで通りWeb UI上でアクションを作成して動作確認でき、新規アクションであればbm pullというコマンドでその内容をコードに取り込めると分かったことで解消しました。
最終的には、アクションの作成・編集はエンジニア側に寄せ、ビジネス側のメンバーは実行のみを行うという運用で、関係する開発チームの意見が一致しました。目立った課題もなく、合意形成は思ったよりスムーズに進みました。

本番移行と、トラブル対応

ヒアリングと検証を経て、本番のPark Directプロジェクトに開発環境を指定しました。 ここが不可逆な一線を越える瞬間で、既存のアクション全てをまとめてコードとして取り込み、リポジトリでの管理に切り替えました。ブランチはdevelop(開発環境向け)とmain(本番環境向け)の2段階とし、それぞれのブランチへのpushをトリガーに、GitHub Actionsから公式CLIのbm syncコマンドを実行して、ベースマキナ側に同期する仕組みを組みました。

運用フローの説明図

そうして臨んだ移行の直後には、やはりというべきかトラブルも発生しました。

ベースマキナをコード管理するためのリポジトリにおけるPRのCIで、bm sync --dryが毎回サーバーエラーで失敗してしまったのです。 最初はそのPRに含まれていたSQLの修正を疑い、同じ処理を別の書き方に置き換えてみましたが、それでもエラーは再現しました。 さらに、以前は問題なく通っていたはずの別のPRを再実行しても失敗するようになっていたことから、原因はPRの中身ではなく環境側の状態にあるのではないかと考えました。

調べた結果、開発環境上であるアクションをWeb UIで編集した際に、SQLテンプレート内のパラメータ名と実際に定義されているパラメータの名前がずれてしまっていたことが原因でした。 bm sync --dry は同期の前に環境の現在の状態を解析する処理を行っており、その解析対象のアクションにこの不整合があったために、無関係な別のPRのCIまで巻き添えで失敗したことも判明しました。 これについてはおそらく自分たちだけではではなく、ベースマキナ社のサポートの方と協力してエラーの解析などを一緒に行なって頂くことで、半日程度でスムーズに解決できました。

移行後のデータソースの整理統合

本番移行が一段落してから、検証段階で見えていた、データソースにおける「差分(※)」の解消に着手しました。
※元々は環境ごとにデータソースを作成して使っていたのに対して、本来公式が想定しているのは接続先を環境ごとに設定するだけというもの。

アクションから参照されていた23個のデータソースを棚卸しして、公式の想定通りの環境切替式の構成へ統合していきました。 全アクションの参照変更を伴うため、影響範囲を区切りながらPRを分割して段階的に進めました。

コード管理によるメリット

移行を終えてしばらく経ってから、当初は想定していなかった副産物に気づきました。アクションがTypeScriptのファイルとしてリポジトリに存在するようになったことで、Claude Codeのようなコーディングエージェントとの相性が非常に良くなりました。

自分たちは普段の開発でClaude Codeをメインで使っていますが、アクションがコード化されたことで、Claude Codeにこのリポジトリを読み込ませつつ、バックエンドのリポジトリも合わせて参照させられるようになりました。バックエンド側のテーブル定義やスキーマの構造をClaude Codeに理解してもらった上でSQLアクションの叩き台を提案してもらうと、SQLとしての整合性が保たれやすく、テーブル構造が変わったときにも追従しやすくなります。

さらにこの移行と同時に、過去の本番作業の実施記録からアクションを自動生成するClaude Code Skillも作りました。 作業記録ドキュメントへの記載、関連チケットを入力すると、確認用・実行用のアクション定義とレビュー用のPRまで一気通貫で作ってくれるというものです。 加えて、ベースマキナ社自身がGitHubの basemachina/skills リポジトリで提供している「Agent Skill」を使うと、アクション作成に必要な設定ファイルの雛形はスキル側が自動生成してくれます。この雛形の生成とバックエンドリポジトリを理解したClaude Codeの提案を組み合わせることで、SQLやベースマキナの設定に詳しくない担当者でも「やりたいこと」を起点にアクションを作成できるようになってきています。

コード管理に移行するというと、一見エンジニアの負担を増やす方向の変更に見えるかもしれません。しかし実際には、コード化したことでAIエージェントを介在させやすくなり、むしろ「誰でも安全にアクションを作れる」というツール本来の狙いに、別の観点からから近づけた気がしています。

おわりに

ノーコード/ローコードツールは、手軽に使える一方で、使い続けるほどガバナンスをどう効かせるかという課題に直面しやすいです。 ベースマキナのコード管理機能は、その課題に対する一つの解決策でしたが、実際に導入するプロセスでは、機能の仕様を読み解くこと以上に、「不可逆な設定変更をどう扱うか」「複数チームが同居する環境をどう合意形成しながら動かすか」という、技術以外の判断も数多く必要でした。

さらに既存データソースの整理・統合のように、移行するにあたって初めて見えてきた地道な作業も多かったです。 それでも、型チェックとレビューで不整合が可視化されるようになり、コーディングエージェントとも組み合わせやすくなったので、トイルを減らしていく土台としては十分に元が取れたと感じています。実際、月に数件発生するような定型的なトイルも、この基盤の上でアクション化する動きが横展開し始めています。

もちろんすべてが綺麗に片付いたわけではありませんが、一度検証用の環境で小さく確かめてから、関係者と合意形成した上で本番に広げるという進め方は、今回のベースマキナに限らず、他のSaaSやツールの不可逆な設定変更に直面したときにも、そのまま適用できる考え方だと思いました。
ぜひ参考にしてみて下さい!

GitHub Organization Rulesetsで、新規リポジトリを含む組織全体のCIポリシーを強制する

はじめに

@2357gi です。
みなさんの組織ではGitHub ActionsのコミットSHAでの固定を行なっていますか?
サプライチェーン攻撃のリスクが高まる昨今、リポジトリの棚卸しを行い、全ての箇所で固定を行い、新規workflowにおいても継続的にガバナンスを効かせる為CIでチェックまで一通りセットアップを行うことが推奨されています。
一方で、新規リポジトリに対しての一律した強制は適用できておらず、逐次新規リポジトリにそれらのCI workflowを追加されている方もいると思います。 それらのガバナンス制御を、新規リポジトリ作成時に逐次対応することなく、継続的にOrganization全体へ適用する方法について解説したいと思います。

リポジトリ単位のCIだけでは新規リポジトリを守れない

通常のCIは、各リポジトリの.github/workflowsにWorkflowファイルを配置して動かします。 そのため、新しいリポジトリが作成されたときに、

  • 必要なWorkflowがまだ配置されていない
  • Required Status Checksが設定されていない
  • セキュリティチェックを通さずにマージできる

という状態が発生する可能性があります。 Repository Templateや自動セットアップによってある程度は防げますが、設定漏れやテンプレートを使わずに作られたリポジトリまでは保証できません。 組織全体でポリシーを強制したい場合は、「各リポジトリにCIを置いてもらう」だけでなく、「組織側の設定によってCIを必須実行する」仕組みが必要です。

Organization Rulesetsを使う

GitHubには、複数のリポジトリに対して共通のルールを適用できるOrganization Rulesetsがあります。 Organization Rulesetsは、GitHub TeamまたはGitHub Enterpriseプランで利用できます。 Organization Ownerは、組織内の複数リポジトリを対象として、ブランチやタグに次のようなルールを適用できます。

  • Pull Requestを経由しない変更を禁止する
  • Required Status Checksを必須にする
  • Force Pushを禁止する
  • 署名済みコミットを要求する
  • 指定したWorkflowの成功をマージ条件にする

中央リポジトリのWorkflowを組織全体で必須化する

repository ruleset と同様に、Organization RulesetのルールとしてもRequire workflows to pass before mergingを設定できます。 このルールでは、Organization設定から次の2つを指定します。

  • Workflowを保管するソースリポジトリ
  • 必須実行するWorkflowファイル

例えば、次のような構成にします。

    example-org/
    ├── organization-ci-repo/
    │   └── .github/
    │       └── workflows/
    │           └── supply-chain-policy.yml
    ├── service-a-repo/
    ├── service-b-repo/
    └── service-c-repo/

organization-ci-repoリポジトリに組織共通のチェックを定義し、そのWorkflowをOrganization Rulesetから指定します。 これにより、service-a-repoやservice-b-repo側に同じWorkflowファイルをコピーしなくても、対象リポジトリのPull Requestで中央管理されたWorkflowを実行し、その成功をマージ条件にできます。 新しく作成されたリポジトリがRulesetの対象条件に一致すれば、そのリポジトリにもルールが適用されます。 各リポジトリの開発者が中央Workflowを配置したり、内容を維持したりする必要はありません。 また、任意でソースリポジトリ側のコミットハッシュを固定することも可能です。

Workflowの配置場所

Workflowファイルは、通常のGitHub Actions Workflowと同じく、ソースリポジトリの次のディレクトリ直下に配置します。

    .github/workflows/

例えば、次の配置は有効です。

    .github/workflows/supply-chain-policy.yml

一方、Reusable Workflowに用いられる次のようなサブディレクトリ配置はサポートされません。

    .github/workflows/security/supply-chain-policy.yml

Workflowは.github/workflowsの直下に配置する必要があります💪

Rulesetの対象リポジトリを柔軟に指定する

Organization Rulesetは、Organization内の全リポジトリに一律適用するだけではありません。 対象リポジトリは、次のような方法で指定できます。

  • Organization内のすべてのリポジトリ
  • 手動で選択した特定のリポジトリ
  • リポジトリ名のパターン
  • Public、Private、InternalなどのVisibility
  • リポジトリの主要言語
  • Organizationで定義したCustom Properties
  • デプロイ済み、またはデプロイ可能と判定されたリポジトリ

例えば、フィルターでは次のような条件を指定できます。

    visibility:private props.team:infra -language:java

これにより、

  • Privateリポジトリのみ
  • teamというCustom Propertyがinfraのもの
  • Javaリポジトリは除外

といった動的な対象指定ができます。 リポジトリ名については、fnmatch形式のInclude・Excludeパターンを指定できます。 例えば、

    service-*

に一致するリポジトリを対象にしつつ、Sandboxリポジトリを除外する、といった運用が可能です。 新しいリポジトリについても、Rulesetの動的な対象条件に一致すれば適用対象になります。

ブランチの対象指定にも注意する

Ruleset Workflowは、Pull RequestまたはMerge Queueの一部として動作します。 そのため、すべてのブランチを無条件に対象にする設定には向きません。 GitHub公式ドキュメントでも、Ruleset Workflowを設定したルールをすべてのブランチに適用するとDirect Pushがブロックされるため、すべての変更をPull Request経由で行うブランチに限定するよう案内されています。 一般的には、次のようなブランチを対象にします。

  • Default Branch
  • main
  • release/*

例えば、mainへの変更を必ずPull Request経由にした上で、Ruleset Workflowの成功を必須にします。

GitHub Organization Rulesetのユースケース紹介

GitHub Organization Rulesetのユースケースとして、一部ではありますが弊社で実施しているものをご紹介します🙌

GitHub ActionsのSHA Pinningを検査する

本記事冒頭で説明した通り、GitHub ActionsがコミットSHAで固定されているかをCIにより検知することができます。
自前でscriptを書くこともできますが、ローカルActionや Docker Actionなどを区別する必要もあるので、弊社ではsuzuki-shunsuke/pinact-action を用いてCIを行っています。 また、SHA固定は参照先の改変リスクを下げますが、古い脆弱なバージョンを固定し続ける可能性があります。 そのため、DependabotなどによるAction更新と組み合わせることが重要です。

CIでnpm ciを使用しているか検査する

Node.jsリポジトリに対しては、CIやデプロイWorkflowでnpm installではなくnpm ciを使っているかを検査しています。 ただし、「リポジトリ内にnpm installという文字列が存在したら失敗」といった単純なチェックは意図しないFailedを招くので、ホワイトリストの仕組みを用意してあげるなどの工夫が必要です。

Takumi guard がCI上でセットアップされているか検査する

弊社ではパッケージレジストリのセキュリティプロキシとしてTakumi Guard(https://shisho.dev/docs/ja/t/)を使用しています。
CI上でも同様にTakumi Guardを用いているのですが、それらも任意で設定をすることができる内容のため、repository rulesetによって検査を行っています。

その他のTips

イベントフィルターは無視される

Ruleset Workflowでは、次のようなイベントフィルターを指定しても無視されます。

  • branches
  • branches-ignore
  • paths
  • paths-ignore
  • types

例えば、次のように書いても、Rulesetによる実行時にはpaths条件による絞り込みは行われません。

    on:
      pull_request:
        paths:
          - "package.json"

対象リポジトリや対象ブランチを絞りたい場合は、Workflow内のイベントフィルターではなく、Ruleset側のTarget設定を使うのが基本です。

権限とセキュリティ上の注意

中央Workflowは、多数のリポジトリで自動実行されます。 そのため、Workflowに与える権限は最小限にします。 検査だけであれば、基本的には次のような設定から始められます。

    permissions:
      contents: read

Pull Requestへコメントを書く場合などは、必要な権限のみを追加します。 また、信頼できないPull Requestのコードを扱うWorkflowでpull_request_targetを利用する場合は注意が必要です。 pull_request_targetはBase Branch側のコンテキストで動き、Secretsや書き込み権限を扱える場合があります。 攻撃者が変更したコードをCheckoutしてそのまま実行すると、Secretsの窃取やリポジトリへの書き込みにつながる可能性があります。 単純な静的検査であれば、まずpull_requestと読み取り専用権限を使う設計を検討するべきです。

ソースリポジトリのVisibilityに注意する

Ruleset Workflowを保管するリポジトリのVisibilityには制約があります。 GitHub公式ドキュメントでは、次のように定義されています。

  • PublicリポジトリのWorkflowは、組織内のPublic、Internal、Privateリポジトリで実行可能
  • InternalリポジトリのWorkflowは、InternalおよびPrivateリポジトリで実行可能
  • PrivateリポジトリのWorkflowは、Privateリポジトリでのみ実行可能

また、InternalまたはPrivateリポジトリに中央Workflowを置く場合は、他のリポジトリからそのWorkflowにアクセスできるよう、Actionsのアクセス設定を有効にする必要があります。 中央WorkflowをPrivateリポジトリに置く場合は、ソースリポジトリの次の設定を確認します。

    Settings
      └── Actions
          └── General
              └── Access

ここで、同一Organization内の他のリポジトリから利用できるように設定します。 ただし、PrivateリポジトリのWorkflowを共有すると、呼び出し先リポジトリのOutside CollaboratorがWorkflow実行ログを通じて一部の情報を間接的に確認できる可能性があります。中央Workflowには機密情報を直接埋め込まない設計が必要です。

まとめ

リポジトリ単位でCIを配置するだけでは、新規リポジトリへの設定漏れを完全には防げません。 Organization RulesetsとRequire workflows to pass before mergingを利用すると、中央リポジトリに定義したWorkflowを、対象となる複数リポジトリのPull Requestで必須実行できます。 この仕組みにより、次のようなポリシーをOrganizationレベルで強制できます。

  • GitHub ActionsのコミットSHA固定
  • CIでのnpm ci利用
  • Dependency Review
  • ライブラリやライセンスのチェック

セキュリティルールを「各チームに守ってもらう」のではなく、「チェックを通過しなければマージできない」仕組みに変えられることが、Organization Rulesetsの大きな価値です。 それではこれで以上になります、皆さんもよきGitHubライフを 🙌