Tines 監査ログを収集する
このドキュメントでは、Amazon S3 を使用して Tines 監査ログを Google Security Operations に取り込む方法について説明します。
始める前に
次の前提条件を満たしていることを確認してください。
- Google SecOps インスタンス。
- Tines への特権アクセス。
- AWS(S3、Identity and Access Management(IAM)、Lambda、EventBridge)への特権アクセス。
Tines の URL を取得する
- ブラウザでテナントの Tines UI を開きます。
- アドレスバーからドメインをコピーします。これは TINES_BASE_URLとして使用します。- 形式: https://<tenant-domain>(例:https://<tenant-domain>.tines.com)。
 
- 形式: 
Tines Service API キー(推奨)または Personal API キーを作成する
後の手順で使用する値:
- TINES_BASE_URL- 例:- https://<domain>.tines.com
- TINES_API_KEY- 次の手順で作成するトークン
オプション 1 - サービス API キー(推奨)
- ナビゲーション メニュー > API キーに移動します。
- [+ 新しいキー] をクリックします。
- [Service API key] を選択します。
- わかりやすい名前(例: SecOps Audit Logs)を入力します。
- [作成] をクリックします。
- 生成されたトークンをすぐにコピーして安全に保存します。このトークンは TINES_API_KEYとして使用します。
オプション 2 - 個人用 API キー(サービスキーが利用できない場合)
- ナビゲーション メニュー > API キーに移動します。
- [+ 新しいキー] をクリックします。
- [Personal API key] を選択します。
- わかりやすい名前を入力します。
- [作成] をクリックします。
- 生成されたトークンをコピーして安全に保存します。 
監査ログの読み取り権限を付与する
- テナント オーナーとしてログインします(または、テナント オーナーに依頼して操作してもらいます)。
- [Settings] > [Admin] > [User administration] に移動します。 (または、左上のメニューでチーム名をクリックして、[Users] を選択します)。
- Service API キーに関連付けられているサービス アカウント ユーザーを見つけます(API キーと同じ名前になります)。- 個人用 API キーを使用している場合は、ご自身のユーザー アカウントを探します。
 
- ユーザーをクリックしてプロフィールを開きます。
- [テナント権限] セクションで、AUDIT_LOG_READ を有効にします。
- [保存] をクリックします。
(省略可)API アクセスを確認する
- curl または任意の HTTP クライアントを使用してエンドポイントをテストします。 - curl -X GET "https://<tenant-domain>/api/v1/audit_logs?per_page=1" \ -H "Authorization: Bearer <TINES_API_KEY>" \ -H "Content-Type: application/json"
- 監査ログエントリを含む JSON レスポンスが返されます。 
- UI で [設定> モニタリング> 監査ログ] に移動して、監査ログが存在することを確認することもできます(AUDIT_LOG_READ 権限が必要です)。 
AWS S3 バケットを構成する
- バケットの作成のユーザーガイドに沿って、Amazon S3 バケットを作成します。
- 後で参照できるように、バケットの名前とリージョンを保存します(例: tines-audit-logs)。
Lambda S3 アップロードの IAM ポリシーとロールを構成する
- AWS コンソールで、[IAM] > [ポリシー] > [ポリシーの作成] > [JSON] タブ に移動します。
- 次のポリシーをコピーして貼り付けます。
- ポリシー JSON(別のバケット名を入力した場合は - tines-audit-logsを置き換えます):- { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::tines-audit-logs/*" }, { "Sid": "AllowGetStateObject", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::tines-audit-logs/tines/audit/state.json" } ] }
- [次へ] > [ポリシーを作成] をクリックします。 
- ポリシーに - TinesLambdaS3Policyという名前を付けます。
- [IAM] > [ロール] > [ロールの作成] > [AWS サービス] > [Lambda] に移動します。 
- 作成した - TinesLambdaS3Policyを添付します。
- ロールに「 - TinesAuditToS3Role」という名前を付けて、[ロールを作成] をクリックします。
Lambda 関数を作成する
- AWS コンソールで、[Lambda] > [Functions] > [Create function] に移動します。
- [Author from scratch] をクリックします。
- 次の構成情報を提供してください。 - 設定 - 値 - 名前 - tines_audit_to_s3- ランタイム - Python 3.13 - アーキテクチャ - x86_64 - 実行ロール - TinesAuditToS3Role
- 関数を作成したら、[コード] タブを開き、スタブを削除して次のコード( - tines_audit_to_s3.py)を貼り付けます。- #!/usr/bin/env python3 # Lambda: Pull Tines Audit Logs to S3 (no transform) import os, json, time, urllib.parse from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError import boto3 S3_BUCKET = os.environ["S3_BUCKET"] S3_PREFIX = os.environ.get("S3_PREFIX", "tines/audit/") STATE_KEY = os.environ.get("STATE_KEY", "tines/audit/state.json") LOOKBACK_SEC = int(os.environ.get("LOOKBACK_SECONDS", "3600")) # default 1h PAGE_SIZE = int(os.environ.get("PAGE_SIZE", "500")) # Max is 500 for Tines MAX_PAGES = int(os.environ.get("MAX_PAGES", "20")) TIMEOUT = int(os.environ.get("HTTP_TIMEOUT", "60")) HTTP_RETRIES = int(os.environ.get("HTTP_RETRIES", "3")) TINES_BASE_URL = os.environ["TINES_BASE_URL"] TINES_API_KEY = os.environ["TINES_API_KEY"] s3 = boto3.client("s3") def _iso(ts: float) -> str: return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(ts)) def _load_state() -> dict: try: obj = s3.get_object(Bucket=S3_BUCKET, Key=STATE_KEY) b = obj["Body"].read() return json.loads(b) if b else {} except Exception: return {} def _save_state(st: dict) -> None: s3.put_object( Bucket=S3_BUCKET, Key=STATE_KEY, Body=json.dumps(st, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) def _req(url: str) -> dict: attempt = 0 while True: try: req = Request(url, method="GET") req.add_header("Authorization", f"Bearer {TINES_API_KEY}") req.add_header("Accept", "application/json") req.add_header("Content-Type", "application/json") with urlopen(req, timeout=TIMEOUT) as r: data = r.read() return json.loads(data.decode("utf-8")) except HTTPError as e: if e.code in (429, 500, 502, 503, 504) and attempt < HTTP_RETRIES: retry_after = 1 + attempt try: retry_after = int(e.headers.get("Retry-After", retry_after)) except Exception: pass time.sleep(max(1, retry_after)) attempt += 1 continue raise except URLError: if attempt < HTTP_RETRIES: time.sleep(1 + attempt) attempt += 1 continue raise def _write(payload, page: int) -> str: ts = time.gmtime() key = f"{S3_PREFIX}{time.strftime('%Y/%m/%d/%H%M%S', ts)}-tines-audit-{page:05d}.json" s3.put_object( Bucket=S3_BUCKET, Key=key, Body=json.dumps(payload, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) return key def _extract_items(payload) -> list: if isinstance(payload, list): return payload if isinstance(payload, dict): audit_logs = payload.get("audit_logs") if isinstance(audit_logs, list): return audit_logs return [] def _extract_newest_ts(items: list, current: str | None) -> str | None: newest = current for it in items: # Use created_at as the timestamp field t = it.get("created_at") if isinstance(t, str) and (newest is None or t > newest): newest = t return newest def lambda_handler(event=None, context=None): st = _load_state() since = st.get("since") or _iso(time.time() - LOOKBACK_SEC) page = 1 pages = 0 total = 0 newest_ts = since while pages < MAX_PAGES: # Build URL with query parameters # Note: Tines audit logs API uses 'after' parameter for filtering base_url = f"{TINES_BASE_URL.rstrip('/')}/api/v1/audit_logs" params = { "after": since, # Filter for logs created after this timestamp "page": page, "per_page": PAGE_SIZE } url = f"{base_url}?{urllib.parse.urlencode(params)}" payload = _req(url) _write(payload, page) items = _extract_items(payload) total += len(items) newest_ts = _extract_newest_ts(items, newest_ts) pages += 1 # Check if there's a next page using meta.next_page_number meta = payload.get("meta") or {} next_page = meta.get("next_page_number") if not next_page: break page = next_page if newest_ts and newest_ts != since: st["since"] = newest_ts _save_state(st) return {"ok": True, "pages": pages, "items": total, "since": st.get("since")} if __name__ == "__main__": print(lambda_handler())
- [構成] > [環境変数] に移動します。 
- [編集>新しい環境変数を追加] をクリックします。 
- 次の表に示す環境変数を入力し、サンプル値を自分の値に置き換えます。 - 環境変数 - キー - 値の例 - S3_BUCKET- tines-audit-logs- S3_PREFIX- tines/audit/- STATE_KEY- tines/audit/state.json- TINES_BASE_URL- https://your-tenant.tines.com- TINES_API_KEY- your-tines-api-key- LOOKBACK_SECONDS- 3600- PAGE_SIZE- 500- MAX_PAGES- 20- HTTP_TIMEOUT- 60- HTTP_RETRIES- 3
- 関数が作成されたら、そのページにとどまるか、[Lambda] > [関数] > [your-function] を開きます。 
- [CONFIGURATION] タブを選択します。 
- [全般設定] パネルで、[編集] をクリックします。 
- [Timeout] を [5 minutes (300 seconds)] に変更し、[Save] をクリックします。 
EventBridge スケジュールを作成する
- [Amazon EventBridge] > [Scheduler] > [スケジュールの作成] に移動します。
- 次の構成の詳細を入力します。
- 定期的なスケジュール: レート(1 hour)。
- ターゲット: Lambda 関数 tines_audit_to_s3。
- 名前: tines-audit-1h
 
- 定期的なスケジュール: レート(
- [スケジュールを作成] をクリックします。
Google SecOps 用の読み取り専用 IAM ユーザーと鍵を作成する
- AWS コンソールで、[IAM] > [ユーザー] に移動します。
- [ユーザーを追加] をクリックします。
- 次の構成の詳細を入力します。
- ユーザー: 「secops-reader」と入力します。
- アクセスの種類: [アクセスキー - プログラムによるアクセス] を選択します。
 
- ユーザー: 「
- [ユーザーを作成] をクリックします。
- 最小限の読み取りポリシー(カスタム)を関連付ける: [ユーザー] > [secops-reader] > [権限] > [権限を追加] > [ポリシーを直接関連付ける] > [ポリシーを作成]。
- JSON: - { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::tines-audit-logs/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::tines-audit-logs" } ] }
- 名前 = - secops-reader-policy。
- [ポリシーを作成> 検索/選択> 次へ> 権限を追加] をクリックします。 
- secops-readerのアクセスキーを作成します。[セキュリティ認証情報] > [アクセスキー] に移動します。
- [アクセスキーを作成] をクリックします。 
- .CSVをダウンロードします。(これらの値はフィードに貼り付けます)。
Tines Audit Logs を取り込むように Google SecOps でフィードを構成する
- [SIEM 設定] > [フィード] に移動します。
- [+ 新しいフィードを追加] をクリックします。
- [フィード名] フィールドに、フィードの名前を入力します(例: Tines Audit Logs)。
- [ソースタイプ] として [Amazon S3 V2] を選択します。
- [ログタイプ] として [Tines] を選択します。
- [次へ] をクリックします。
- 次の入力パラメータの値を指定します。
- S3 URI: s3://tines-audit-logs/tines/audit/
- Source deletion options: 必要に応じて削除オプションを選択します。
- ファイルの最大経過日数: 指定した日数以内に変更されたファイルを含めます。デフォルトは 180 日です。
- アクセスキー ID: S3 バケットにアクセスできるユーザー アクセスキー。
- シークレット アクセスキー: S3 バケットにアクセスできるユーザーのシークレット キー。
- アセットの名前空間: アセットの名前空間。
- Ingestion labels: このフィードのイベントに適用されるラベル。
 
- S3 URI: 
- [次へ] をクリックします。
- [Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。
さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。