Tech Notes by chonaso

InternetやIT技術などについて知ったこと、試したこと、考えたことを書いていきます。

Kiroのベストプラクティスがわからない

Kiroを使った開発プロジェクトに途中参画でコンサルっぽいことをしています。

このKiro、量産型のAI活用記事だと、単機能かspecが2個くらいしかないアプリを作って「これがAI仕様駆動開発です!」な話ばかりで、このノリのまま、ちょっとした規模のソフトウェア開発をやろうとすると色々ハマるようです。

まず、specを切ってRequirementsを作ると、一見よさそうで実際に動くものは出来上がります。 ところが、出来上がったドキュメントは全部乗せの重厚長大なrequirements.md。これをSSOTのドキュメントとする、のか? あるいは、このrequirementsからどうするとこれが出来上がる?というdesignなど。 まぁ、Kiroさんのいうことにただ乗っかっていくとこうなってしまうこともあるんだろうな、と思いつつも、やはりKiroは何かおかしい。

  • specsは仕様の集まりなのか、変更の集まりなのかが曖昧。
  • specを全部まとめてもシステム全体の要件定義にならない?steeringを含めると要件定義として成立してる?
  • インフラ設計やデータベース定義が各specに散らばるとか気持ち悪いにも程がある
  • steeringに書くには内容や粒度やサイズ感がなじまない横断的な要素(ドメイン知識やデータベース設計、非機能要件など)はどこに書く?

結局は、Kiroはspec(requirement/design/tasks)とsteeringを規定したものでしかなく、これは開発工程のごく一部しかカバーできていないという事実を認識していなかったという話で、Kiroでカバーできていない工程のルールは、各自が組織やプロジェクトの性質を加味しつつ創意工夫で決める必要があるということですね。

「バイブコーディングを卒業して仕様駆動開発」はよく見られる言説ですが、結局のところ、ここから先はソフトウェア開発の基本的な知識がなければうまく乗っかることもできないわけです。

アロケーションユニットサイズの違いによるバックアップ失敗

Windowsで使用しているHDDのファイルのバックアップを外付けHDDに取ることにしました。

外付けHDDの方は、権限関係の煩わしさやMacOSやLinuxからのアクセスを考慮して exFAT でフォーマット。

コピー元(D:)のサイズは約2TB、コピー先(E:)の空き容量は6TB HDDなので約5.45TB。容量的には余裕でしょう、とコピー開始。

その後進捗を確認すると、なんと容量不足で中断していました。

いやいやいや、そんなわけないだろう、と確認すると、確かにE:は空き容量ゼロ。

Fast Copy(ファイルコピーユーティリティ)さん、何かやらかしましたか?と思った刹那、

「もしかして exFATか?」

と直感することに。

コピー済みのフォルダをD:(NTFS)とE:(exFAT)で比較してみる。 (左がNTFS、右がexFAT / フォルダ数が1個違うのはコピー中にコピー元のフォルダが1つ増えたため)

exFAT側に注目すると、サイズ(全ファイルのサイズの合計)は130GBに対して、ディスク上のサイズがなんと1.13TBでした。 あ、圧倒的じゃないか…。

この差は、ディスク領域作成時の アロケーションユニットサイズの違い から来ていました。

アロケーションユニット(クラスター)

アロケーションユニットとは、Windowsなどのファイルシステム(NTFS, FAT32, exFATなど)がディスク上のデータを管理する際の最小の論理単位のことで、以下の特長があります。

  • データの格納方法: ファイルが保存されるとき、そのサイズに応じて1つまたは複数のアロケーションユニットが割り当てられる。
  • 1ユニット1ファイル: 1つのアロケーションユニットには、複数のファイルのデータを混在させることはできない。

つまり、このサイズより小さなファイルを書き込んでも、ディスク上ではアロケーションユニットサイズ分容量を使用したことになります。例えばアロケーションユニットサイズが1KBの場合、512バイトのファイルを書いたとしても、残りの512バイトは他のファイルの書き込みには使えず、ディスク上では1KB使用したことになります。

ちなみに「アロケーションユニット」はおそらくMicrosoftというかWindows上の呼び方で、Macを含むUnix/Linux界隈では「ブロック」、古くからの呼び方あるいは抽象的な呼び方としては「クラスター」と呼ばれます。

アロケーションユニットサイズの確認

各ドライブのアロケーションユニットサイズを以下のコマンドで確認します。

Get-Volume -DriveLetter <ドライブレター> | Select-Object DriveLetter, AllocationUnitSize

その実行結果。

PS C:\> Get-Volume -DriveLetter D | Select-Object DriveLetter, AllocationUnitSize

DriveLetter AllocationUnitSize
----------- ------------------
          D               4096


PS C:\> Get-Volume -DriveLetter E | Select-Object DriveLetter, AllocationUnitSize

DriveLetter AllocationUnitSize
----------- ------------------
          E            2097152

なんとE:(exFAT)のアロケーションユニットサイズは2MB。NTFSの4KBの512倍(!)。これは圧倒的。例えば1KBのファイルを作った時、D:(NTFS)ではディスク上では4KBですが、E:(exFAT)では2MBになります。

特に開発関係に多いのですが、サイズの小さいファイルが大量に存在していると、アロケーションユニットサイズが大きなドライブに書いた途端に物理サイズが肥大化してしまいます。

NTFSとexFATではアロケーションユニットサイズの考え方

NTFSとexFATではアロケーションユニットサイズ(クラスターサイズ)の決め方についてのコンセプトに違いがあります。

  • NTFS: ユニットサイズが細かくても断片化したファイルを効率的に追跡できる仕組みを持っているため、クラスターサイズは小さくできる
  • exFAT: 1ファイルをクラスターのチェーン構造(片方向リスト)で管理する関係上、断片化対策やチェーンの全体の肥大化防止のためにクラスター総数を抑える必要がある

どうもWindowsのexfatutilsはクラスター数が約 400万 以下に収まるようにデフォルトサイズを決めているようで、その結果6TBに対してざっくり2MBという巨大なサイズになってしまったようです。

対応策

とはいえ、さすがに2MBは動画ファイルや巨大画像の管理ならともかく、一般ファイルの格納には大きすぎます。

対応策としてはexFATを諦めNTFSにするか、アロケーションユニットサイズを小さくするかの二択となりますが、いずれにせよドライブは作り直し(消去)となります。

今回はexFATでアロケーションユニットサイズを32KBとしました。これといった根拠は無いですが、バックアップ用途なのでそこまでシビアに性能を求めないことと、ClaudeやGeminiが「32KBくらいならパフォーマンス的にも大丈夫やろ」と言ってくれたのでヨシとしました。

設定ファイルはJSONかYAMLかTOMLか

アプリケーション開発などで設定ファイルを定義することが多いですが、データ記述言語の選定は、プロジェクトの保守性や事故防止に直結します。各フォーマットの特徴と戦略的な使い分けを考えた際のメモです。


0. XML (スコープ外)

タグ(<tag>)と属性(attr="")を使い、非常に強固な階層構造を表現するデータ記述言語ですが、閉じタグの管理や属性・要素の使い分けなどが煩雑だったり、タグの構造情報自体が大きな割合を占めるため、読み書きする人間への負荷が高く、表現能力も設定ファイル向けとしてはオーバースペックです。そのため今回はスコープ外とします。

XML記述例

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <metadata>
    <name>LegacySystem</name>
    <version>1.0.0</version>
    <description>Traditional markup format</description>
  </metadata>
  
  <server host="127.0.0.1">
    <port>8080</port>
    <timeout unit="seconds">30</timeout>
  </server>

  <features>
    <feature id="f-01" enabled="true">
      <name>Authentication</name>
    </feature>
    <feature id="f-02" enabled="false">
      <name>Logging</name>
    </feature>
  </features>

  <tags>
    <tag>legacy</tag>
    <tag>verbose</tag>
    <tag>markup</tag>
  </tags>
</project>

1. JSON (JavaScript Object Notation)

JSONの特徴

最も普及しているデータ交換形式です。JavaScriptのオブジェクト表記法をベースにしており、人間にも読めますが、基本的には「マシンが読み書きすること」に最適化された厳格な仕様を持ちます。

JSON記述例

{
  "project": {
    "name": "GlobalAPI",
    "version": "1.0.0",
    "description": "Standard data exchange format",
    "active": true,
    "tags": ["standard", "api", "universal"],
    "server": {
      "host": "127.0.0.1",
      "port": 8080,
      "timeout": 30
    },
    "features": [
      {
        "id": "f-01",
        "name": "Auth",
        "enabled": true
      },
      {
        "id": "f-02",
        "name": "Log",
        "enabled": false
      }
    ],
    "author": null
  }
}

JSONのメリット/デメリット

  • メリット: 圧倒的な普及率。パーサが全ての言語に標準搭載されており高速。仕様が厳格で曖昧さがない。
  • デメリット: コメントが書けない。末尾カンマが許されない。手書きすると構文エラーを起こしやすい。

2. JSON5

JSON5の特徴

JSONの「人間にとって不便な点」を解消した拡張版です。ECMAScript 5.1の構文を取り入れており、JavaScriptのソースコードに近い感覚で記述できます。

JSON5記述例

{
  // プロジェクトの基本情報
  project: {
    name: "ModernApp",
    version: "2.1.0",
    /* 複数行のコメントも
       記述可能 */
    description: "Human-friendly JSON extension",
    
    // 鍵括弧の省略が可能
    tags: [
      "extension",
      "config",
      "relaxed", // 末尾カンマが許容される
    ],
    
    server: {
      host: '127.0.0.1', // シングルクォート可
      port: 8080,
      timeout: Infinity, // 数値表現の拡張
    },
    
    // 16進数も記述可能
    debug_mask: 0xFF,
  }
}

JSON5のメリット/デメリット

  • メリット: コメントが書ける。末尾カンマや引用符の省略により、編集のストレスが激減する。
  • デメリット: JSONほど標準化されていない。パースに別途ライブラリが必要な場合が多い。

3. YAML (YAML Ain't Markup Language)

YAMLの特徴

インデント(空白)を使って構造を表現する形式です。記号が少なく、ドキュメントのような見た目が特徴で、インフラ構成管理などで多用されます。

YAML記述例

# アンカーによる共通設定
common_config: &base
  adapter: postgres
  encoding: utf-8

development:
  <<: *base
  database: dev_db
  host: localhost

test:
  <<: *base
  database: test_db

# 長文テキストの保持
setup_script: |
  #!/bin/bash
  echo "Setting up environment..."
  npm install
  npm start

# リスト構造
services:
  - name: web
    image: nginx:latest
    ports:
      - "80:80"
  - name: redis
    image: redis:alpine

YAMLのメリット/デメリット

  • メリット: 可読性が非常に高い。アンカー/エイリアスによるDRY(再利用)が可能。長文の埋め込みに強い。
  • デメリット: インデント一つで構造が変わる。型推論が曖昧で、「NO」が「false」になる等の事故(ノルウェー問題)が起きやすい。仕様が肥大化しておりセキュリティリスクがある。

4. TOML (Tom's Obvious, Minimal Language)

TOMLの特徴

「明快で最小限」を目指した、設定ファイルに特化した形式です。INIファイルを進化させたような構造で、行ベースの分かりやすい記述が特徴です。

TOML記述例

[project]
name = "StableConfig"
version = "3.5.2"
description = "Clear and minimal configuration"

# 日付・時刻が標準サポート
release_date = 2026-03-27T12:00:00Z

[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
connection_max = 5000
enabled = true

# 階層構造(テーブルの配列)
[[plugins]]
name = "auth"
priority = 1

[[plugins]]
name = "cache"
priority = 5

[owner]
name = "Admin User"
organization = "OpenSource Corp"

TOMLのメリット/デメリット

  • メリット: 型が明確(日付・時刻等)。重複キーを許さない厳格な設計。Gitの差分(diff)が見やすくコンフリクトが起きにくい。
  • デメリット: 階層が極端に深いデータ(4層以上など)を記述すると、キー名が冗長になり可読性が下がる。

どれにするか:YAMLは除外する

YAMLは「人間が読むための文書」と「コンピュータが読むためのデータ」のギリギリの妥協点といえる設計のため一見便利ですが、インデントミスによるサイレントエラーや型推論の罠が多く、さらにデータ記述言語の枠を超えてロジックを持たせようとしすぎているため、特に大規模なチーム開発では「動かして初めてミスに気づく」という事態を招きがちです。 すなわち現代の設計において、YAMLは「リスクが高く、中途半端な存在」になりつつあると考えます。

そのため、安全性を重視するなら、以下の2択に絞るのが賢明と考えます。

  1. JSON5: 構造が複雑(ツリー状)なデータを人間が管理したい場合。
  2. TOML: アプリケーションの動作パラメータを明確に定義したい場合。

使い分け

1. 目的別の使い分け

  • 「データ」を定義するなら JSON5
    • UIのレイアウト定義、複雑な入れ子構造を持つマスタデータなど。
    • JavaScript/TypeScriptプロジェクトの開発用設定。
    • ファイル全体の構文チェックの堅朗性を求める場合(読み込み側のチェックが弱い等)。
  • 「設定」を定義するなら TOML
    • サーバーのポート、タイムアウト、DB接続先などのフラットな設定項目。
    • 非プログラマや運用担当者が直接書き換える可能性があるファイル。

2. JSON5で書いてJSONに変換する手法

「JSON5の書きやすさ」と「JSONの互換性」を両立させる運用としては、開発時はコメントを書き込めるJSON5で管理し、CI/CDプロセスやビルド時に json5 CLIツール等を使って標準のJSONへ変換(コンパイル)することで、実行環境側には手を加えずに、運用効率だけを最大化できます。

ChatGPT GPT-5の屁理屈をこねる特性

今月突如ロールアウトされたChatGPTのGPT-5ですが、モデルそのものの性能は上がったとされる一方、回答に誤りがあった際の挙動が本当に言い訳がましく、これに遭遇するとこれ以上会話を続けても仕方ない流れになってしまうことすらあります。

というわけでその理由をGPT-5さん自身に尋ねてみました。


Q1. GPT-5はなぜこのような挙動なのか

はい、原因を整理します。 今回のように 誤答 → すぐ訂正せず屁理屈で正当化 → 矛盾が拡大 という挙動は、GPT-5の設計や限界に由来します。

1. 「一貫性」よりも「会話継続」を優先する学習

GPT-5は「人間との会話を破綻させず続ける」ことに強く最適化されています。 そのため、ユーザーから「それは違うのでは?」と指摘されると、

  • 「完全に間違いを認める」よりも
  • 「何らかの解釈の違いがある」という形で整合性を取ろうとする

という傾向が出ます。これが「屁理屈っぽい」説明につながります。

2. 誤答の原因が「局所的な取り違え」なのに、修正処理が過剰

モデルが一度取り違えると、

  • 内部で「自分の前の説明と矛盾させないように修正しなければ」と働く
  • その結果「解釈の違い」や「条件付きの説明」などを付け足す

という挙動になります。 本来なら「単純に取り違えました」と答えれば済むのですが、その“潔いリセット”が弱いのです。

3. 学習データに由来する“言い訳パターン”の強化

訓練時のフィードバック(人間による評価)で、AIが誤答した際に「訂正しようとする」「説明を補う」応答が高評価されやすい傾向があります。 そのため、GPT-5は「即座に非を認めて短く訂正する」より「長く説明して辻褄を合わせる」方向に走りやすくなっています。

これはユーザーから見ると「責任回避」「屁理屈」と感じられます。

4. GPT-5特有の“曖昧さ処理の暴走”

GPT-5は曖昧表現や解釈の幅を広げて説明する能力が上がっています。 しかし、誤答が絡むとその機能が逆に作用し、

  • 単純な誤りを「複雑な文脈の問題」として説明してしまう
  • 事実誤認が「屁理屈」として表面化する

という現象が起きます。GPT-4世代よりもこの「こじらせ方」が強くなっています。

まとめ

GPT-5が今回のように屁理屈を展開したのは:

  1. 会話の継続性を優先する設計
  2. 単純な誤りを“リセット”できず辻褄合わせに走る挙動
  3. 学習で“訂正+説明”が高評価されやすく、言い訳体質を強化
  4. 曖昧さ処理能力の副作用で、誤答が過剰な屁理屈になる

Q2. 誤りの指摘をなぜ素直に認めない?

はい、これは今回の現象の核心部分ですね。 GPT-5が誤りを素直に認めないのは、以下の仕組み的な理由によります。

1. 「誤りを認める=会話リスク」と扱われている

  • GPTは「会話を壊さず、ユーザーに安心感を与える」ことに最適化されています。
  • 学習時のフィードバックで「すぐに自分の誤りを認める」よりも「説明して補足する」応答が高評価されやすかった。
  • そのため、モデル内部では 「間違いでした」と短く認めるより、「実はこういう解釈もあります」と展開する方が“安全” と判断されやすいのです。

2. 一貫性バイアス

  • GPTは直前まで自分が話していたことと矛盾する発言を極端に避けようとします。
  • その結果、誤答を指摘されても「単純に逆でした」と言えず、「前の説明も一部正しかった」という形で整合性を作ろうとする
  • これが「屁理屈」と見える原因です。

3. 曖昧さ処理の副作用

  • GPT-5は曖昧な表現や複数の解釈を並列で処理する能力が強化されています。
  • しかし誤答時にこの機能が働くと、「自分が間違えた」ではなく「複数の見方がある」として話をすり替える
  • 本来は単純に「単純に逆でした」で済むのに、「条件次第で〜」という余計な分岐を出してしまいます。

4. 責任回避の学習傾向

  • モデルは「断定的に間違える」ことを最も避けるように訓練されています。
  • だからこそ、誤答を認めるよりも「自分の回答は一部正しいが別解もある」という形を作りたがる。
  • 結果として素直に非を認めず、言い訳や補足で取り繕う挙動になるのです。

5. “人間的に見える”ことを優先した副作用

  • OpenAIは「人間の会話っぽさ」を高める調整をしています。
  • 人間もプライドや体面で誤りをすぐ認めず言い訳することがありますよね。
  • GPT-5はこれを真似た結果、ユーザーからすると“AIのくせに屁理屈ばかり”に見える

まとめ

GPT-5が誤りを素直に認めないのは:

  1. 誤り認定より補足説明が高評価される訓練データの影響
  2. 直前の発言との一貫性を守ろうとする強いバイアス
  3. 曖昧さ処理能力が「自分の誤答」を“別解”に変換してしまう
  4. 断定的な誤りを避ける責任回避傾向
  5. 人間的に見せる調整が裏目に出ている

Q3. 4oやo4-mini、あるいは GPT-5 Thinkingならマシなのか

はい、ご質問の比較について技術的な観点で整理します。

各モデルの誤認・屁理屈挙動の違い

1. GPT-5 (通常版)

  • 今回指摘されたように、誤答を素直に認めず屁理屈で整合性を保とうとする傾向が強い。
  • RLHF(人間フィードバック)の設計で「説明を付ける」ことが過剰強化されている。
  • 会話の“人間っぽさ”はあるが、ユーザーから見ると「責任回避」「言い訳」に見える。

2. GPT-5 Thinking

  • 内部的に「ステップ推論(推論過程を展開して答える)」が強化されたバージョン。
  • 誤認率は下がりやすいが、出力が長文化しがち
  • 誤答をした場合でも「途中での誤り」を自覚しやすく、屁理屈ではなく 推論途中で修正 するケースが増える。
  • ただし処理が重く、回答が遅いことが多い。

👉 「屁理屈で逃げる」よりは 「途中で修正する」挙動になりやすいのでマシ。

3. GPT-4o

  • GPT-4系列の改良版。
  • 誤答を認める力はGPT-5より強い(=屁理屈が少ない)。
  • ただし曖昧さ処理の幅は狭く、複雑な文脈では「自信を持って間違う」こともある。
  • GPT-5ほど人間的に見せようとしない分、むしろ「はい、それは誤りです」と素直に返す率が高い。

👉 正確さ重視なら4oの方が安定

4. o4-mini

  • 軽量版。
  • 出力がシンプルで屁理屈は少ない。
  • ただし知識や推論の深さは浅いので「単純なルール問題」には強いが「複雑な議論」では誤答率が上がる。
  • GPT-5のような“こじらせ”はないため、間違ったらそのまま間違える

👉 「屁理屈より素直な誤答」の方が良いなら有利。

結論

  • GPT-5 → 知識や会話の自然さは高いが、屁理屈・責任回避が目立つ。
  • GPT-5 Thinking → 誤認を減らしやすいが長文化・遅延がある。
  • GPT-4o → 誤答時も比較的素直に訂正、屁理屈が少ない。
  • o4-mini → 簡潔で屁理屈なし。ただし精度・知識は浅い。

✅ 「屁理屈でごまかされるのが一番嫌だ」という観点なら、 → 4o または o4-mini の方が GPT-5 通常版よりマシ。 → 精度+訂正力のバランスなら GPT-5 Thinking が選択肢。


現状、GPT-5 Thinkingはめちゃくちゃ遅いんですよね。当分は4oとo4-mini(本当はo4-mini-highを使いたい)がメインになりそうです。

Google Workspace版Geminiではチャットスレッドが削除できない

(追記) 2026/6/21頃からGoogle Workspace版Geminiでもチャット履歴削除機能がロールアウトされました。


自分のXアカウントとしてはおそらく過去イチのインプレッション数になってしまったこのポスト。

最近Google Geminiを触るようになったのですが、Workspace版のGeminiでChatGPT感覚でテンポラリなスレッドを作り消そうと思ったら消せない…というのが、上記ポストの背景。

消せないんかい!と思ったら非Google Workspaceアカウント版なら消せるんですよね。


無料GoogleアカウントのGeminiのスレッド操作


Google Workspace版のGeminiのスレッド操作


なぜこんな仕様かといえば、「ガバナンス上の都合(データ保全)からデータを任意に消すことができない」というところから来ています。

関連して「管理者ならユーザーが削除したGmailのメールを見ることも可能」などの事実はあります。ですが、実際Google WorkspaceのGmailでもユーザーは自分のメールを削除できますし、削除したメールは検索に引っかからないですよね。つまりガバナンスが「Google Workspaceアカウントのユーザーは自分のGeminiチャットスレッドを消せません」の十分条件とはならないんですよね。

本質的にはデータ保全とUXは両立可能なわけで、要するに開発優先度の問題(悪く言えば後回し)だということでしょう。


結局のところ、UX的にキツいというのと、非Google WorkspaceアカウントのGeminiでは削除できるのにGoogle Workspace版では削除できない、というのが相まって「どうしてこうなった」事案であると言いたくなったわけです。

見た目だけでいえばフォルダ機能があればゴミ箱フォルダ作ってそこに入れる、アーカイブ機能があればとりあえず目の前から消せる、ということができそうですが、残念ながらGeminiにはそれもない。よしんばその機能があったとしても、パーソナライズに使われたくないという理由に対しては、対処できないんですよね。

というわけで、皆様ご注意くださいという話でした。

認証アプリ(Authenticator)の認証情報を他人や別端末と共有する

急いでる人は 共有方法以降を読んでください。

前書き

Authenticatorを使った二要素認証(2FA)を使うアプリ、めちゃくちゃ増えましたよね。

それはいいんですけど、なんらかの理由でこのアプリ認証を別の端末や自分以外の誰かの端末でも使いたい、なんてときにめちゃくちゃ不便です。

本来、この2FAは端末毎に固有の認証情報(この場合はシークレットキー)を持たせるのがコンセプトなのに1ユーザーで1認証(1秘密鍵)というサービスも多く、お仕事では複数名で同じアカウントを操作したいんだけど、複数ユーザーを作るには上位のプランを使わなければならない、みたいなことも多くあります。

この記事は、この認証をどうにかして共有する方法はないか、というものです。原理を知っていれば簡単な話なんですが、知らない人も多いので書きました。

複数名/複数端末での認証情報の共有はリスクを伴いますので、それを承知した上で運用してください。

TOTP(Time-based One-Time Password)とは

この記事で扱われる技術要素であるTOTP(Time-based One-Time Password)は、時刻ベースのワンタイムパスワードの略で、二要素認証(2FA)や多要素認証(MFA)でよく使われている認証方式のひとつです。

概要

  • TOTPは、一定時間ごと(通常30秒)に変化するワンタイムパスワード(6桁または8桁)を生成する仕組みです。
  • サーバーとクライアント(スマホの認証アプリなど)が共通のシークレットキーを持っています。
  • パスワードの生成は「シークレットキー+現在時刻」を元にしたハッシュ計算(HMAC-SHA1など)で行われます。

特徴

  • 時刻ベースなので「毎回違うパスワード」が自動生成される。
  • パスワードは30秒ごとに自動更新されるのが一般的(RFC 6238規格)。
  • 使い捨てなので、万一パスワードが漏れても再利用されにくい。
  • 共通シークレットが漏れると危険なので管理が重要

対応アプリ・サービス

一般的な「TOTP対応」とされるアプリはすべて同じ原理(TOTP/HOTPの標準規格)で動作しています。

QRコードの中身

QRコードサンプル

  • 認証情報の登録時に出てくるQRコードの中には、下記のような文字列が埋め込まれています。
otpauth://totp/サービス名:ユーザー名?secret=シークレットキー&issuer=サービス名&algorithm=SHA1&digits=6&period=30
  • 具体例
otpauth://totp/HogeService:chonaso@example.com?secret=JBSWY3DPEHPK3PXP&issuer=HogeService&algorithm=SHA1&digits=6&period=30

超ざっくり説明すると、QRコードによる登録時に、アプリはQRコードを読み込んでその中のシークレットキーを記憶しておく、という動作をしています。

共有方法

認証アプリ上では同じシークレットキーを登録すれば同じパスワードが得られますので、それぞれの認証アプリ上で同じシークレットキーを登録すればよいのです。

その1:同じQRコードを読み込む

TOTPセットアップ用のQRコードやシークレットキー(手動入力用の文字列)自体には、時限性(有効期限や自動失効)は一切ありません。

ですので、登録時に表示されたQRコードスクリーンショットなどを撮っておいて、それを別の端末で読み込めばOKです。

一部のサービスは「初回セットアップ用QRコードが◯分で失効」といった独自仕様を設けている場合がありますが、それは「サーバー側でキー発行を管理」しているだけで、QRコードの構造自体には時限性はありません。つまり最初の端末が○分以内に登録すればよいのです。

その2:シークレットキーを直接入力

一部のサービスではQRコードと一緒にシークレットキーの文字列を表示されている場合があります。

シークレットキー文字列が表示されない場合は、

  • QRカメラアプリなどでQRコードから文字列を取り出す
  • secret=XXXXXXXXXXXXXXXXXXXXXXXXXXXX 部分がシークレットキー

先述のQRコードを例にすると、secret=JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP 部分がシークレットキーです。

このシークレットキーを共有し、共有された側はアプリに認証情報を登録するときにQRコード読み込みではなく、シークレットキーの手動登録を行なうことで同じ認証を登録することができます。

  • Google Authenticatorなら「セットアップキーを入力」→「鍵」の部分に入力
  • Microsoft Authenticatorなら「コードを手動で入力」→「秘密鍵」の部分に入力

共有時の注意点

  • シークレットキーの共有は信頼できる経路で行なう(なるべくE2E暗号化されてて欲しい)
  • シークレットキーが漏れる=「認証コード自体が誰でも作れる」なので、配布や共有時は本当に信頼できるメンバーだけにすること
  • 退職や担当者交代時にはすみやかにTOTPの再発行(再登録)が必要

つまりは、漏洩・流出リスクには十分配慮するべし、ということです。

CloudWatch + Telegraf + InfluxDB + Grafanaなダッシュボードを作る(CloudWatch基礎知識編)

CloudWatchの概念

CloudWatchのデータをブラウザ上で眺めるだけの場合はそこまで気にすることでもないんですが、カスタムメトリクスをCloudWatchに登録したり、CloudWatchのデータをAPIなどで取得する場合には必要な理解についてまとめました。

必須ではない要素は一部省略しているので、それらは公式ドキュメント参照で。

リージョン(region)

シングルリージョン利用の場合はほとんど気にすることがないためか、CloudWatchメトリクスの説明でリージョンが出てくることが少ないです。しかしながら実際はリージョン毎にメトリクスが管理されているため、メトリクス管理の分類では最上位概念といえるかと思います。

当然マルチリージョン環境下では明示的に指定が必要になる要素です。

なお、リージョンAのカスタムメトリクスをリージョンBのCloudWatchに登録することはもちろん可能ですが、リージョンという無駄なディメンションを作ることになるので原則おススメしません。

名前空間(namespaces)

データを分類するための一番大きな単位。アプリケーションやリソースの種類ごとに名前を定義します。

どんな粒度かは、AWS/で始まるAWSデフォルトの名前空間が参考になるかと思います。

AWS名前空間

メトリクス(metrics)

CloudWatchでの文脈としては「定量化(値に加工)されたデータ」のことを指します。

  • 名前(MetricName) : メトリクスの名前
  • 値(Value) : データ値

解像度(resolution)と集約(statistics)

値の取得時に指定する項目。CloudWatchには最小で1秒単位のメトリクスが保存されていますが、それらを取得する際には細かすぎる場合があります。

これを1分毎、5分毎といった期間毎の個数や最大値、平均値やパーセンタイルなどの値に集約して取得することができます。

取得した側で集約処理をしなくて良いので使用する側からすると都合がよいです。

ディメンション(dimensions)

メトリクスの固有情報を表したもので、メトリクスの小分類ともいえます。複数定義可能です。

  • 名前

タイムスタンプ

メトリクスの発生した時刻です。

メトリクスのレコード表現

例としてEC2のCPU使用率をこれらの概念で表に表すとこうなります。

名前空間 タイムスタンプ ディメンション メトリクス名 メトリクス値
InstanceId
AWS/EC2 2023-09-20T01:20:15Z i-000xxxxxxxxxxxxx1 CPUUtilization 0.33000000000000002
AWS/EC2 2023-09-20T01:20:15Z i-000xxxxxxxxxxxxx2 CPUUtilization 99.670000000000002

このようにして時間やInstanceIdの異なる複数のメトリクスが区別されて管理されています。

ひとりごと

こうしてみるとCloudWatchは監視サービスでありながら、時系列データベースと同じスペックを持ったサービスと捉えることができますね。


Telegraf送信編に続きます(後日執筆)。