Next.jsのprocess.envとDatadog RUMの環境変数の扱い方
概要
Next.jsのprocess.envはどう解決サれているのか?
実行環境に準じる。Next.jsではセキュリティ上の理由から、NEXT_PUBLIC_プレフィックスが付いた環境変数のみがクライアント側(ブラウザー)で参照可能。それ以外の環境変数はサーバー側でのみ利用できる。
next.config.jsのenvに定義した値はWebpackのDefinePluginを使ってビルド時に置換されるため、Webpackを通さない外部ライブラリからは参照できない。その場合はprocess.envオブジェクトにも値を入れる必要がある。
遭遇した事象
Datadog RUMのApplicationIdとClientTokenをなるべくコード上で持ちたくないと考えた。(間違いの始まり)
GiHub ActionsでビルドをしてデプロイをしているのでGitHub ActionsのsecretsにApplicationIdとClientTokenを登録しビルド時に値を埋め込む事を考えた。しかし、このやり方ではデプロイ後のコードではApplicationIdとClientTokenはundefindになる。
実際のコード
app.tsx
import { datadogRum } from '@datadog/browser-rum';
datadogRum.init({
applicationId: '<DATADOG_APPLICATION_ID>',
clientToken: '<DATADOG_CLIENT_TOKEN>',
site: '<DATADOG_SITE>',
sessionSampleRate: 100,
sessionReplaySampleRate: 100,
defaultPrivacyLevel: 'mask'
});
GiHub Actions
jobs:
build:
runs-on: ubuntu-latest
env:
APPLICATION_ID: ${{ secrets.APPLICATION_ID }}
steps:
- uses: actions/checkout@v3
- run: |
echo "ApplicationId: $APPLICATION_ID"
# ビルドやデプロイの処理でシークレットを使う
ApplicationIdとClientTokenがundefindになる原因
このやり方が間違っている点は2つある。
- Datadog RUMのApplicationIdとClientTokenをなるべくコード上で持ちたくない
- GiHub ActionsでビルドをしてデプロイをしているのでGitHub ActionsのsecretsにApplicationIdとClientTokenを登録しビルド時に値を埋め込む
1の間違っている点は認識の問題である。なぜコード上で持ちたくないのかというと秘匿するべき情報なのではないかという認識をしていたから。
Datadog RUMのApplicationIdとClientTokenは最終的にビルドされ_app.tsxもしくはlayout.tsxに記述される。完全にApplicationIdとClientTokenを隠蔽することは難しくminifyして難読化するのが限界だ。
Datadogの公式ドキュメントを読むとわかるのだが、このApplicationIdとClientTokenからDatadogに侵入されたり攻撃サれることはないとされている。
2の間違いはprocess.envがどう解決されるのかへの理解不足である。
process.envは実行環境のenvファイルに記載された宣言を読み出している。つまり最終的にNextjsはブラウザで実行されるためあらかじめenvファイルに記載をしてコード側で持っている情報歯科読み出せない。
正確にはGitHub AcrionsでビルドされたときにはApplicationIdとClientTokenには期待した値が入るがそれはビルドをしたDockerマシンの中での話でブラウザで実行されたときにはこの値はブラウザがにないのでundefindになる。
どうするのが正解か?
env.prod.jsonにApplicationIdとClientTokenを記載して実行するのが正解だろう。
それか、いっそハードコードしてしまっても問題ない。本番のみDatadogを適用するならハードコードで十分なきがする。
学び
- 公式ドキュメントはちゃんと読もう
- 秘匿するべき情報は組織で明記して管理しよう
- envの扱いには注意しよう
Discussion