Table of Contents
この記事は Fusic Advent Calendar 2025 の17日目の記事です。(公開を忘れるのが怖いので先に投稿)
はじめに
リモートセンシングデータのメタデータ管理において、STAC(SpatioTemporal Asset Catalog)は業界標準として広く採用されています。
公開され自由に利用できるSTACサーバも複数ありますが、実験・検証のタイミングでは好きに叩けるプライベートな環境が欲しくなります。
そこで、オープンソースのstac-serverを使用して、
- AWSへのデプロイ(最小構成)
- 自前のサンプルデータの登録
- IPアドレス制限
までを行い、検索できるようになるところまでを確認します。
基本的にはREADME.mdの手順どおりで構築が可能です。
STACとは
STAC(SpatioTemporal Asset Catalog)は、衛星画像や航空写真などのリモートセンシングデータのメタデータを標準化された形式で管理・検索するための仕様です。
主要コンポーネント:
| コンポーネント | 説明 |
|---|---|
| Catalog | コレクションやアイテムをグループ化するルートオブジェクト |
| Collection | 関連するアイテムのグループ(例: Sentinel-2データセット) |
| Item | 単一の地理空間アセットのメタデータ(例: 1シーンの衛星画像) |
| Asset | 実際のデータファイルへのリンク(GeoTIFF、COGなど) |
stac-serverの特徴
- STAC API仕様を実装したNode.jsベースのサーバー
- AWS Lambda + API Gatewayによるサーバーレス構成
- OpenSearchによる高速検索
- SNS/SQSによる非同期データ登録
- Serverless Frameworkによる簡単デプロイ
構築方針
以下の方針で構築します:
- リージョン: 東京(ap-northeast-1)
- 環境: 開発・検証用
- 構成: 最小構成(コスト優先)
- 認証: AWS IAM認証(シンプルさ優先)
環境準備
今回の実行環境
node --version # v22.15.0
npm --version # 10.9.2
npx serverless --version # 3.40.0
aws sts get-caller-identity # 認証設定済みであること
セットアップ手順
1. リポジトリのクローン
git clone https://github.com/stac-utils/stac-server.git
cd stac-server
2. serverless.ymlの設定
cp serverless.example.yml serverless.yml
以下の変更を適用します:
基本設定
provider:
region: ${opt:region, 'ap-northeast-1'} # 東京リージョン
environment:
CORS_ORIGIN: "*" # 開発環境用
認証方式の選択
stac-serverは2つの認証方式をサポートしています:
| 方式 | 概要 | 特徴 |
|---|---|---|
| Fine-grained Access Control (default) | OpenSearchの内部ユーザーデータベースを使用 | きめ細かい権限制御が可能。デプロイ後に追加設定が必要 |
| AWS IAM Authentication | AWS IAMロールで認証 | 設定がシンプル。追加のアカウント作成不要 |
今回は複雑な権限管理は必要ないため、AWS IAM認証で構築を行います。
※ API Gatewayは公開エンドポイントとなるため、後述のIPアドレス制限で対応します。
AWS IAM認証の設定
以下の変更をserverless.ymlに適用します:
1. OpenSearch認証情報環境変数をコメントアウト
environment:
# OPENSEARCH_CREDENTIALS_SECRET_ID: ...
2. Secrets Manager IAM権限をコメントアウト
iam:
role:
statements:
# - Effect: Allow
# Resource: arn:aws:secretsmanager:...
# Action: secretsmanager:GetSecretValue
3. OpenSearchのFine-grained Access Controlを無効化
OpenSearchInstance:
Properties:
AdvancedSecurityOptions:
Enabled: false
InternalUserDatabaseEnabled: false
4. アクセスポリシーをAWSアカウントに制限
AccessPolicies:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal: { "AWS": "arn:aws:iam::${aws:accountId}:root" }
Action: "es:ESHttp*"
Resource: "arn:aws:es:${aws:region}:${aws:accountId}:domain/${self:service}-${self:provider.stage}/*"
3. ビルドとデプロイ
npm install
npm run build
npm run deploy # 10〜15分程度
デプロイ完了後、エンドポイントが表示されます:
endpoints:
ANY - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
4. 動作確認
試しにエンドポイントを叩いてみて、結果が返ってくればOKです。
curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
{
"stac_version": "1.1.0",
"type": "Catalog",
"id": "stac-server",
"title": "STAC API",
"description": "A STAC API using stac-server",
...
}
5. 自動インデックス作成の無効化(オプション)
コレクションより先にアイテムが登録された場合、不適切なマッピングでインデックスが作成される可能性があるため、本番環境ではOpenSearchの自動インデックス作成を無効化することが推奨されています。
今回は開発環境のため、この工程はスキップします。
設定方法は公式READMEを参照してください。
6. インデックスの初期化
OpenSearchにSTAC用のインデックスを作成します:
aws lambda invoke \
--function-name stac-server-dev-ingest \
--cli-binary-format raw-in-base64-out \
--payload '{ "create_indices": true }' \
/tmp/response.json
ここまで実行すると以下のURLでコレクション一覧のAPIが叩けるようになります。
https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/collections
データの登録
サーバーができたので、ようやくデータ登録です。 stac-serverへのデータ登録はSNS経由で行います。 コレクション → アイテム の順序で登録が必要です。
コレクションの登録
{
"type": "Collection",
"id": "my-satellite-data",
"stac_version": "1.0.0",
"description": "サンプル衛星画像コレクション",
"license": "proprietary",
"extent": {
"spatial": { "bbox": [[139.0, 35.0, 140.0, 36.0]] },
"temporal": { "interval": [["2024-01-01T00:00:00Z", null]] }
},
"links": []
}
aws sns publish \
--topic-arn arn:aws:sns:ap-northeast-1:ACCOUNT_ID:stac-server-dev-ingest \
--message file://collection.json
アイテムの登録
{
"type": "Feature",
"stac_version": "1.0.0",
"id": "my-item-001",
"geometry": {
"type": "Polygon",
"coordinates": [[[139.0, 35.0], [140.0, 35.0], [140.0, 36.0], [139.0, 36.0], [139.0, 35.0]]]
},
"bbox": [139.0, 35.0, 140.0, 36.0],
"properties": { "datetime": "2024-01-15T10:30:00Z" },
"collection": "my-satellite-data",
"links": [],
"assets": {
"data": {
"href": "s3://my-bucket/data/image.tif",
"type": "image/tiff; application=geotiff"
}
}
}
aws sns publish \
--topic-arn arn:aws:sns:ap-northeast-1:ACCOUNT_ID:stac-server-dev-ingest \
--message file://item.json
一括登録したい場合
for item in items/*.json; do
aws sns publish --topic-arn $TOPIC_ARN --message "file://$item"
sleep 0.1
done
※ SNS publishはJSONを文字列として送信しています。サイズが大きい場合はS3 + SQS構成を検討してください。
※ 大量のアイテムを登録する場合、公式READMEのIngesting large itemsも参考になります。
検索
ここまでくると、アイテムの取得もできるようになっているはずです。
# 全アイテム
curl -s "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/search" | jq
# 件数を指定して取得
curl -s "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/search?limit=1" | jq
# コレクション一覧
curl -s "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/collections" | jq
IP制限の設定
開発環境の場合、IPアドレス制限を加えたいことがほとんどだと思います。
本番ではWAFとの組み合わせが有力ですが、今回はAPI Gatewayでシンプルに対応します。
serverless.ymlに以下を追加:
provider:
apiGateway:
resourcePolicy:
- Effect: Allow
Principal: "*"
Action: execute-api:Invoke
Resource: execute-api:/*/*/*
Condition:
IpAddress:
aws:SourceIp:
- "xxx.xxx.xxx/32"
npm run deploy
コスト概算
最小構成での月額費用(東京リージョン):
| リソース | 仕様 | 月額 |
|---|---|---|
| OpenSearch | t3.small.search × 1 | ~$26 |
| EBS | 35GB gp3 | ~$3 |
| Lambda/API Gateway/SNS/SQS | 従量課金 | ~$1-5 |
| 合計 | ~$30-35 |
Tips: cloneしたリポジトリでcommitができない場合
元リポジトリではHuskyでいろいろなチェックが動いています。
検証用のリポジトリでそこまで気にしなくてよい場合は、以下のオプションで回避できます。
HUSKY=0 git commit -m "message"
# または
git commit --no-verify -m "message"
まとめ
stac-serverを使用して、AWS上で自前のSTACカタログを検索できる環境を構築しました。
最小構成であれば月額約$30〜35程度で運用できるため、開発・検証環境として手軽に始められ便利ですね。
今回作ったカタログを使って、次はブラウザ・Viewerの構築を検証していきます。
※ 本番環境で利用する場合は、CORS制限、OpenSearchのセキュリティ設定、認証方式、WAF導入などを含めたセキュリティ設計を必ず再検討してください。
参考リンク
uchida
福岡でWebエンジニアやってます。PHP, クラウド, インフラあたりが好き。