0
Help us understand the problem. What are the problem?

posted at

Node.js でマルチアカウントの AWS リソース情報をファイル出力してみた

使用している AWS リソース情報を一覧で確認したいことってありますよね。
単一アカウントであれば、以下の方法があります。

今回は、上記の方法のうち 2 つ目の記事を参考に、マルチアカウントの AWS リソース情報を json ファイルとして出力する Node.js プログラムを作成してみました。

前提

・AWS マルチアカウント構成である
・各アカウントにはスイッチロールすることができる
・スイッチロールの権限は AdministratorAccess
AWS CLI でスイッチロールができる状態である
・CLI からの呼び出しで MFA は使用していない

なお、今回はマルチリージョンでの出力は行っていませんのでご注意ください。

コード

Node.js でのスイッチロールは以下の記事のコードを流用しています。

sample.js
const fs = require("fs");
const AWS = require("aws-sdk");
AWS.config.update({ region: "ap-northeast-1" });
AWS.config.apiVersions = {
  sts: "2011-06-15",
  resourcegroupstaggingapi: "2017-01-26",
};
const sts = new AWS.STS();

const main = async () => {
  const ops = {
    flag: "a",
  };
  const profiles = ["profile-name-1 ", "profile-name-2"];
  const roles = [
    "アカウント A の スイッチ用 IAM ロール ARN",
    "アカウント B の スイッチ用 IAM ロール ARN",
  ];
  const roleSessionNames = ["test1", "test2"];

  for (let i = 0; i < profiles.length; i++) {
    const credentials = new AWS.SharedIniFileCredentials({
      profile: profiles[i],
    });
    AWS.config.credentials = credentials;

    try {
      const credentials = await assumeRole(roles[i], roleSessionNames[i]);
      const options = {
        accessKeyId: credentials.AccessKeyId,
        secretAccessKey: credentials.SecretAccessKey,
        sessionToken: credentials.SessionToken,
      };
      const resourcegroupstaggingapi = new AWS.ResourceGroupsTaggingAPI(
        options
      );
      const result = await resourcegroupstaggingapi.getResources().promise();
      const str = JSON.stringify(result);

      fs.writeFile("resources.json", str, ops, (err) => {
        if (err) {
          console.log(err);
        }
      });
    } catch (error) {
      console.log(error);
    }
  }
};
main();

async function assumeRole(RoleArn, RoleSessionName) {
  const params = {
    RoleArn,
    RoleSessionName,
  };

  try {
    const result = await sts.assumeRole(params).promise();
    return result.Credentials;
  } catch (error) {
    console.log(error);
  }
}

コード内容

Node.js でのスイッチロール部分に関しては、先述の記事で説明しているので割愛します。

GetResources API

今回はリソース情報を取得するために、GetResources という API を使用しています。

GetResourcesResourceGroupsTaggingAPI というサービス API に含まれるので、以下の部分で STS とともに API バージョンを指定しています。

AWS.config.apiVersions = {
  sts: "2011-06-15",
  resourcegroupstaggingapi: "2017-01-26",
};

設定値のロード

以下の部分で config ファイルに記載されているスイッチロール用の各種 profile 情報をロードします。
(ロードではなくハードコーディングですが…)

const profiles = ["profile-name-1 ", "profile-name-2"];
const roles = [
"アカウント A の スイッチ用 IAM ロール ARN",
"アカウント B の スイッチ用 IAM ロール ARN",
];
const roleSessionNames = ["test1", "test2"];

本来はハードコーディングせずに config ファイルから直接ロードしたかったのですが、ロード方法がわからなかったので、ハードコーディングになりました。
config ファイルからロードする方法があればそちらの方が良いと思います。

ループでスイッチロール

各アカウントへのスイッチロール用の profile 分ループさせて、スイッチロールごとに GetResources を呼び出しています。
取得した結果を文字列に変換してから、ファイルに追記モードで書き込んでいます。

for (let i = 0; i < profiles.length; i++) {
    const credentials = new AWS.SharedIniFileCredentials({
      profile: profiles[i],
    });
    AWS.config.credentials = credentials;

    try {
      const credentials = await assumeRole(roles[i], roleSessionNames[i]);
      const options = {
        accessKeyId: credentials.AccessKeyId,
        secretAccessKey: credentials.SecretAccessKey,
        sessionToken: credentials.SessionToken,
      };
      const resourcegroupstaggingapi = new AWS.ResourceGroupsTaggingAPI(
        options
      );
      const result = await resourcegroupstaggingapi.getResources().promise();
      const str = JSON.stringify(result);

      fs.writeFile("resources.json", str, ops, (err) => {
        if (err) {
          console.log(err);
        }
      });
    } catch (error) {
      console.log(error);
    }
  }

追記モードに関しては、ループの中で毎回指定する必要はなかったので、処理の冒頭で以下のように指定しています。

const ops = {
    flag: "a",
  };

実行方法

aws-sdk をインストールする必要があるので、以下のコマンドを実行します。

npm i aws-sdk

aws-sdk をインストール後、以下のコマンドでプログラムを実行します。

node sample.js

実行後に resources.json というファイルが生成され、各アカウントの東京リージョンのリソース情報が記載されているはずです。

整形

プログラム実行語に生成された json ファイルは不正な形式なので、フォーマットがうまくいかないと思います。
そのため、アカウントごとの切れ目を見つけて、別々の json ファイルにする必要があるのですが、切れ目の見つけ方は簡単です。

文字列検索で、PaginationToken という単語がヒットするので、この直前の { がアカウントの切れ目です。
なので、PaginationToken 直前の { から始まる 1 ブロックごとに別々の json ファイルに分けると、うまく整形できるはずです。

そもそもプログラム側で書き込む時に、 1 つの json ファイルではなく、別々の json ファイルに分けるという方法もあると思いますので、適宜変更して下さい。

その他

マルチリージョンのリソース情報を取得する場合は、リージョン分ループかつアカウント分ループの 2 重ループでできるのではないかと思っています。
そのうち試してみようと思います。

また、シェルスクリプトでもできる気はしますが、僕はスクリプトよくわからないマンなので、きっと誰かが作ってくれるのではないかと願っています。

まとめ

今回はマルチアカウントの AWS リソース情報を json ファイルとして出力する Node.js プログラムを作成してみました。
改良の余地はありますが、参考になれば幸いです。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?