0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

QuickSight Asset Bundle APIでダッシュボードをエクスポート/インポートしてみた

0
Last updated at Posted at 2026-06-07

背景・目的

前回の記事ではDefinition APIを使ってダッシュボードを作成・更新しました。

本記事では、QuickSight Asset Bundle APIを使ってアセットのエクスポート/インポートを試します。

Asset Bundleは、ダッシュボードとその依存関係(データセット・データソース)をまとめてエクスポートし、別環境にインポートできる機能です。

本記事では以下を試します。

  1. 既存ダッシュボードをAsset Bundleとしてエクスポート
  2. エクスポートされたファイルの中身を確認
  3. CloudFormation形式でもエクスポートして比較
  4. 別IDでインポートして環境移行を模擬

まとめ

項目 内容
Asset Bundleとは アセット(ダッシュボード+依存リソース)の定義をまとめてエクスポート/インポートする機能。実データや認証情報は含まれない
エクスポート形式 QUICKSIGHT_JSON(.qs zip、リソースごとに分割)と CLOUDFORMATION_JSON(1ファイルのCFnテンプレート)
include-all-dependencies 指定したアセットが依存するリソース(データセット・データソース・VPC接続)を自動的に含める
PrefixForAllResources 同一アカウント内で複製する場合、全リソースIDにプレフィックスを付けて新規作成する
ダウンロードURL 署名付きURL(5分有効)。期限切れたらdescribeで再取得可能
Body指定 fileb:// は使えない。Base64エンコードして渡す
権限 エクスポート時に --include-permissions を付けないとインポート先で権限なし。別途付与が必要
Definition APIとの違い Definition APIは「作る・直す」、Asset Bundleは「運ぶ・管理する」

概要

Asset Bundleとは

下記を基に整理します。

QuickSightのアセット(ダッシュボード・データセット・データソース等)をまとめてエクスポート/インポートする機能です。

  • エクスポートされるのはアセットの定義(設定情報)のみで、実データや認証情報は含まれません
  • 用途として下記のようなものが考えられます
    • dev環境で作ったダッシュボードをprod環境に持っていく
    • アカウント間のアセット移行
    • バックアップ
    • CloudFormationテンプレートとしてIaC化

Definition APIとAsset Bundleの違い

前回、利用したDefinition APIとの違いを簡単にまとめます。

Definition API Asset Bundle
やること ダッシュボード1個の中身を編集 複数アセットをまとめて移動
ユースケース 開発・修正(ビジュアル追加、計算式変更) デプロイ・移行・管理(dev→prod、バックアップ)
対象 単一アセット 複数アセット+依存関係
形式 JSON(直接指定) .qs zip or CloudFormation

エクスポートされるファイルの中身

.qsファイル(zip)
├── ダッシュボードの定義
├── データセットの定義(どのテーブルのどの列を使うか)
├── データソースの定義(接続先情報)
├── 権限情報(オプション)
└── タグ情報(オプション)

APIの流れ

エクスポート

StartAssetBundleExportJob(非同期開始)
↓
DescribeAssetBundleExportJob(ポーリング)
↓
成功 → ダウンロードURL取得 → .qs zipダウンロード

インポート

StartAssetBundleImportJob(.qsファイル指定)
↓
DescribeAssetBundleImportJob(ポーリング)
↓
成功 → アセットが作成/更新される

実践

前提

  • AWS CLIを使用
  • QuickSight Enterprise Editionを利用
  • リージョン: ap-northeast-1
  • 前回作成したダッシュボード(api-test-dashboard-001)をエクスポート対象とする

シナリオ1: QUICKSIGHT_JSON形式でエクスポート

エクスポート

1. start-asset-bundle-export-job によりエクスポートジョブを開始します

aws quicksight start-asset-bundle-export-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-export-job-id export-001 \
    --resource-arns '["arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:dashboard/api-test-dashboard-001"]' \
    --include-all-dependencies \
    --export-format QUICKSIGHT_JSON \
    --region ap-northeast-1

---

json
{
    "Status": 202,
    "Arn": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:asset-bundle-export-job/export-001",
    "AssetBundleExportJobId": "export-001"
}
  • asset-bundle-export-job-id: 任意のIDを付けられる
  • include-all-dependencies: 指定したアセットが依存するリソースを自動的に一緒にエクスポートするオプション
    • データセットやデータソースも含めて抽出します
  • export-format:出力の形式
    • QUICKSIGHT_JSON:.qs zip(QS独自のJSON)
    • CLOUDFORMATION_JSON:CFnテンプレート(JSON)

2. ステータスを確認します。SUCCESSFULになっていました

aws quicksight describe-asset-bundle-export-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-export-job-id export-001 \
    --region ap-northeast-1
---

{
    "Status": 200,
    "JobStatus": "SUCCESSFUL",
    "DownloadUrl": "https://quicksight-asset-bundle-export-job-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/...",
    "AssetBundleExportJobId": "export-001",
    "ResourceArns": [
        "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:dashboard/api-test-dashboard-001"
    ],
    "IncludeAllDependencies": true,
    "ExportFormat": "QUICKSIGHT_JSON",
    "IncludePermissions": false,
    "IncludeTags": false
}

  • asset-bundle-export-job-id:要求時に指定したID
  • レスポンス
    • DownloadUrl:AWS管理しているS3のURLが返される(presigned URL)。有効期限は300秒のようです
    • IncludePermissions:false。権限情報無しでエクスポートしています。そのためインポートする場合は別途付与する必要があります

3. ダウンロードURLから .qs ファイルを取得します

curl -o export-001.qs 'https://quicksight-asset-bundle-export-job-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/・・・'

4. ダウンロードできました

ls -la /XXXXX/export-001.qs

-rw-r--r--@ 1 XXXXX  XXXXX  2271 Jun  7 21:10 /XXXXXX/export-001.qs

エクスポートされたファイルの中身を確認

1. 展開して確認します

unzip export-001.qs -d export-001-extracted

2. 下記のような構成になっていました

export-001-extracted/
├── dashboard/api-test-dashboard-001.json
├── dataset/monthly-sales-summary.json
├── datasource/redshift-dev.json
└── vpcConnection/qs-redshift-vpc-conn.json

dashboard/api-test-dashboard-001.json

1. ビジュアル・レイアウトの定義が確認できました

{
    "resourceType": "dashboard",
    "dashboardId": "api-test-dashboard-001",
    "name": "API Test Dashboard",
    "definition": {
        "dataSetIdentifierDeclarations": [
            {"identifier": "my_dataset", "dataSetArn": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:dataset/monthly-sales-summary"}
        ],
        "sheets": [{
            "sheetId": "sheet-1",
            "name": "Sheet 1",
            "visuals": [{
                "tableVisual": {
                    "visualId": "table-visual-1",
                    "title": {"visibility": "VISIBLE", "formatText": {"plainText": "Monthly Sales Summary"}},
                    "chartConfiguration": {
                        "fieldWells": {
                            "tableUnaggregatedFieldWells": {
                                "values": [
                                    {"fieldId": "sales_month", "column": {"dataSetIdentifier": "my_dataset", "columnName": "sales_month"}},
                                    {"fieldId": "category", "column": {"dataSetIdentifier": "my_dataset", "columnName": "category"}},
                                    {"fieldId": "region", "column": {"dataSetIdentifier": "my_dataset", "columnName": "region"}},
                                    {"fieldId": "quantity", "column": {"dataSetIdentifier": "my_dataset", "columnName": "quantity"}},
                                    {"fieldId": "revenue", "column": {"dataSetIdentifier": "my_dataset", "columnName": "revenue"}}
                                ]
                            }
                        }
                    }
                }
            }],
            "layouts": [{"configuration": {"gridLayout": {"elements": [{"elementId": "table-visual-1", "elementType": "VISUAL", "columnSpan": 36, "rowSpan": 12}]}}}]
        }]
    },
    "validationStrategy": {"mode": "LENIENT"}
}

dataset/monthly-sales-summary.json

1. テーブル・列情報、インポートモードが確認できました

{
    "resourceType": "dataset",
    "dataSetId": "monthly-sales-summary",
    "name": "Monthly Sales Summary",
    "physicalTableMap": {
        "salesTable": {
            "relationalTable": {
                "dataSourceArn": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:datasource/redshift-dev",
                "schema": "dm",
                "name": "monthly_sales_summary",
                "inputColumns": [
                    {"name": "sales_month", "type": "INTEGER"},
                    {"name": "category", "type": "STRING"},
                    {"name": "region", "type": "STRING"},
                    {"name": "quantity", "type": "INTEGER"},
                    {"name": "revenue", "type": "DECIMAL", "subType": "FIXED"}
                ]
            }
        }
    },
    "importMode": "SPICE"
}

datasource/redshift-dev.json

1. 接続先ホスト・ポート・DB名、認証のSecret ARNが確認できました

{
    "resourceType": "datasource",
    "dataSourceId": "redshift-dev",
    "name": "Redshift Dev",
    "type": "REDSHIFT",
    "dataSourceParameters": {
        "redshiftParameters": {
            "host": "${REDSHIFT_ENDPOINT}",
            "port": XXXX,
            "database": "${REDSHIFT_DB}"
        }
    },
    "vpcConnectionProperties": {
        "vpcConnectionArn": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:vpcConnection/qs-redshift-vpc-conn"
    },
    "credentials": {
        "secretArn": "arn:aws:secretsmanager:ap-northeast-1:${AWS_ACCOUNT_ID}:secret:${SECRET_NAME}"
    }
}

vpcConnection/qs-redshift-vpc-conn.json

1. サブネット、SG、IAMロールが確認できました

{
    "resourceType": "vpcConnection",
    "vpcConnectionId": "qs-redshift-vpc-conn",
    "name": "QS to Redshift VPC Connection",
    "subnetIds": ["subnet-xxx", "subnet-yyy", "subnet-zzz"],
    "securityGroupIds": ["sg-xxx"],
    "roleArn": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/service-role/aws-quicksight-service-role-v0"
}

シナリオ2: CLOUDFORMATION_JSON形式でエクスポートして比較

エクスポート

  1. CloudFormation形式でエクスポートします
aws quicksight start-asset-bundle-export-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-export-job-id export-cfn-001 \
    --resource-arns '["arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:dashboard/api-test-dashboard-001"]' \
    --include-all-dependencies \
    --export-format CLOUDFORMATION_JSON \
    --region ap-northeast-1
---
{
    "Status": 202,
    "Arn": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:asset-bundle-export-job/export-cfn-001",
    "AssetBundleExportJobId": "export-cfn-001"
}
  • export-format:CLOUDFORMATION_JSON。CFnのフォーマットを指定します

2. ステータスを確認します。SUCCESSFUL になりました

aws quicksight describe-asset-bundle-export-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-export-job-id export-cfn-001 \
    --region ap-northeast-1
---
{
    "Status": 200,
    "JobStatus": "SUCCESSFUL",
    "DownloadUrl": "https://quicksight-asset-bundle-export-job-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/...",
    "ExportFormat": "CLOUDFORMATION_JSON"
}

3. ダウンロードします。今回はzipではなく単一のJSONファイル(9,252 bytes)になります

curl -o export-cfn-001.json '<DownloadUrl>'

エクスポートされたファイルの中身を確認

エクスポート結果の確認(CloudFormation形式)

1. QUICKSIGHT_JSON形式とは異なり、1つのCloudFormationテンプレートとして出力されます。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "qsredshiftvpcconnSecurityGroupId0": {
      "Default": "sg-xxx",
      "Description": "SecurityGroupId0 for vpcConnection:qs-redshift-vpc-conn",
      "Type": "String"
    },
    "qsredshiftvpcconnSubnetId0": {
      "Default": "subnet-xxx",
      "Type": "String"
    },
    "redshiftdevSecretArn": {
      "Default": "arn:aws:secretsmanager:ap-northeast-1:${AWS_ACCOUNT_ID}:secret:${SECRET_NAME}",
      "Type": "String"
    }
  },
  "Resources": {
    "apitestdashboard001": {
      "Type": "AWS::QuickSight::Dashboard",
      "Properties": {
        "AwsAccountId": {"Fn::Sub": "${AWS::AccountId}"},
        "DashboardId": "api-test-dashboard-001",
        "Name": "API Test Dashboard",
        "Definition": {
          "DataSetIdentifierDeclarations": [{
            "DataSetArn": {"Fn::GetAtt": ["monthlysalessummary", "Arn"]},
            "Identifier": "my_dataset"
          }],
          "Sheets": [{"..."}]
        }
      }
    },
    "monthlysalessummary": {
      "Type": "AWS::QuickSight::DataSet",
      "Properties": {
        "AwsAccountId": {"Fn::Sub": "${AWS::AccountId}"},
        "DataSetId": "monthly-sales-summary",
        "Name": "Monthly Sales Summary",
        "ImportMode": "SPICE",
        "PhysicalTableMap": {
          "salesTable": {
            "RelationalTable": {
              "DataSourceArn": {"Fn::GetAtt": ["redshiftdev", "Arn"]},
              "Schema": "dm",
              "Name": "monthly_sales_summary",
              "InputColumns": [
                {"Name": "sales_month", "Type": "INTEGER"},
                {"Name": "category", "Type": "STRING"},
                {"Name": "region", "Type": "STRING"},
                {"Name": "quantity", "Type": "INTEGER"},
                {"Name": "revenue", "Type": "DECIMAL", "SubType": "FIXED"}
              ]
            }
          }
        }
      }
    },
    "redshiftdev": {
      "Type": "AWS::QuickSight::DataSource",
      "Properties": {
        "AwsAccountId": {"Fn::Sub": "${AWS::AccountId}"},
        "DataSourceId": "redshift-dev",
        "Name": "Redshift Dev",
        "Type": "REDSHIFT",
        "DataSourceParameters": {
          "RedshiftParameters": {
            "Host": "${REDSHIFT_ENDPOINT}",
            "Port": XXXX,
            "Database": "${REDSHIFT_DB}"
          }
        },
        "Credentials": {
          "SecretArn": {"Fn::Sub": "${redshiftdevSecretArn}"}
        },
        "VpcConnectionProperties": {
          "VpcConnectionArn": {"Fn::GetAtt": ["qsredshiftvpcconn", "Arn"]}
        }
      }
    },
    "qsredshiftvpcconn": {
      "Type": "AWS::QuickSight::VPCConnection",
      "Properties": {
        "AwsAccountId": {"Fn::Sub": "${AWS::AccountId}"},
        "Name": "QS to Redshift VPC Connection",
        "VPCConnectionId": "qs-redshift-vpc-conn",
        "RoleArn": {"Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/aws-quicksight-service-role-v0"},
        "SecurityGroupIds": [{"Fn::Sub": "${qsredshiftvpcconnSecurityGroupId0}"}],
        "SubnetIds": [{"Fn::Sub": "${qsredshiftvpcconnSubnetId0}"}, "..."]
      }
    }
  }
}

形式の比較

シナリオ1と2でエクスポートにより抽出したJSON形式について、比較します

QUICKSIGHT_JSON CLOUDFORMATION_JSON
ファイル形式 .qs zip(リソースごとに分割JSON) 1つのCFnテンプレート(JSON)
サイズ 2,271 bytes 9,252 bytes
リソース参照 ARN直書き Fn::GetAtt でリソース間を参照
環境差分 インポート時にOverrideParametersで上書き CFn Parametersで上書き
アカウントID ハードコード ${AWS::AccountId} で自動解決
デプロイ方法 start-asset-bundle-import-job aws cloudformation deploy

シナリオ3:別IDでインポートして環境移行を模擬

先ほどエクスポートした .qs ファイルを別のダッシュボードIDでインポートしてみます。

インポート

1. Base64エンコードしてBodyに渡してインポートします

BODY_B64=$(base64 -i export-001.qs)

aws quicksight start-asset-bundle-import-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-import-job-id import-005 \
    --asset-bundle-import-source "{\"Body\":\"$BODY_B64\"}" \
    --override-parameters '{"ResourceIdOverrideConfiguration":{"PrefixForAllResources":"copy-"}}' \
    --region ap-northeast-1
---
{
    "Status": 202,
    "AssetBundleImportJobId": "import-005"
}

2. ステータスを確認します。 SUCCESSFUL になりました

aws quicksight describe-asset-bundle-import-job \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --asset-bundle-import-job-id import-005 \
    --region ap-northeast-1
---
{
    "JobStatus": "SUCCESSFUL",
    "OverrideParameters": {
        "ResourceIdOverrideConfiguration": {
            "PrefixForAllResources": "copy-"
        }
    }
}

3. 権限を付与して確認します。copy-api-test-dashboard-001 として作成されていました

aws quicksight update-dashboard-permissions \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --dashboard-id copy-api-test-dashboard-001 \
    --grant-permissions '[{
        "Principal": "arn:aws:quicksight:ap-northeast-1:${AWS_ACCOUNT_ID}:user/default/${QS_USER_NAME}",
        "Actions": ["quicksight:DescribeDashboard","quicksight:QueryDashboard","quicksight:ListDashboardVersions"]
    }]' \
    --region ap-northeast-1
---
{
    "Status": 200,
    "DashboardId": "copy-api-test-dashboard-001"
}

4. list-dashboards で確認します。copy-api-test-dashboard-001 が作成されています

aws quicksight list-dashboards \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --region ap-northeast-1
---
{
    "DashboardSummaryList": [
        {
            "DashboardId": "api-test-dashboard-001",
            "Name": "API Test Dashboard",
            "PublishedVersionNumber": 2,
            "CreatedTime": "2026-06-07T15:16:22+09:00"
        },
        {
            "DashboardId": "copy-api-test-dashboard-001",
            "Name": "API Test Dashboard",
            "PublishedVersionNumber": 1,
            "CreatedTime": "2026-06-07T22:34:22+09:00"
        }
    ]
}

マネージメントコンソールで確認

1. AWSで確認します
2. ダッシュボードが2つありました。所有者はその他になっています
image.png

3. 同じ内容が出てきました
image.png

4. URLを見ると、dashboards/copy-api-test-dashboard-001となっていました

考察

  • Asset Bundle APIを使えば、ダッシュボードとその依存リソースをまとめてエクスポート/インポートできることを確認した
  • CLOUDFORMATION_JSON形式でエクスポートすると、Fn::GetAtt によるリソース間参照や Parameters による環境差分の外出しが自動生成されるため、手書きなしでIaC化できる
  • 同一アカウント内で複製する場合、OverrideParametersの DashboardId ではIDを変更できない。PrefixForAllResources を使う必要がある点はドキュメントから読み取りにくく、ハマりやすい
  • インポート後に権限が付与されない問題は、Definition API の create-dashboard と同じ。QS CLIの共通のハマりポイントとして認識しておくべき
  • Body パラメータで fileb:// が使えず、Base64エンコードが必要だった

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?