Steampipe とは
標準 SQL を使用して、対応するクラウドサービス (AWS, Azure Google Cloud, and more!) にクエリを実行できるオープンソース の CLI ツールです。マルチクラウドのガバナンスプラットフォームを提供する Turbot (Turbot HQ, Inc.) が中心となって開発しています。
類似するサービスに IaSQL などがあります。IaSQL は SQL でインフラ構成を管理する、つまりリソースの作成や維持も目的としています。
対して Steampipe は API やサービスからデータを調査、評価し、洞察を得るという参照に特化しています。また単に CLI ツールであるため、ローカルや AWS CloudShell などの環境にインストールし、認証情報を与えるだけで利用できます。ユーザー自身で別途データベースを用意する必要もありません。
実際にはローカルに Steampipe が管理する PostgreSQL が作成されます。単にデータベースとしても使用できるので、その他のクライアントツールから接続したり、データのエクスポートなども可能です。
と言ってもデータベースにクラウドサービスのデータが保存されているわけではありません。Steampipe は Postgres Foreign Data Wrapper を使用して外部サービス API からデータを取得し、テーブルとして表示します。
SaaS 版の Steampipe Cloud も提供予定とのことで現在プレビュー中です。
Steampipe のセットアップ
CLI のインストール
mac OS または各種 Linux ディストリビューションで利用できます。Linux の場合、シェルスクリプトを実行するだけです。
$ sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/turbot/steampipe/main/install.sh)"
$ steampipe -v
steampipe version 0.15.0
Plugin による連携サービスの追加
Steampipe は Plugin によって様々なサービスと連携します (2022 年 6 月時点で 78)。steampipe-plugin-sdk が公開されており、コミュニティベースでもプラグインが開発されています。
Steampipe Hub に利用可能なサービス一覧の記載があります。
デフォルトでは何もインストールされていないため、ここでは AWS プラグインをインストールしてみます。
$ steampipe plugin install steampipe aws
aws [====================================================================] Done
Installed plugin: aws@latest v0.66.0
Documentation: https://hub.steampipe.io/plugins/turbot/aws
select * from cloud;
Steampipe でクエリを実効するには steampipe query
でインタラクティブシェルを開くか、steampipe query "select vpc_id, cidr_block, state from aws_vpc"
のような形でバッチ実行することもできます。インタラクティブシェルではオートコンプリートや構文の強調表示、history などが使えるので便利です。
AWS プラグインの使用例
各プラグインは steampipe-postgres-fdw を使用し、対応サービスからデータを取得し、テーブルとして表示しています。AWS プラグインの場合、すべてのサービスや API に対応しているわけではありませんが、300 以上のテーブルが定義済みです。
select * from aws_ec2_instance;
が CLI の aws ec2 describe-instances
に対応しているというようなイメージを持ってもらうとわかりやすいかと思います。さらにドキュメントにはそれぞれのテーブルで豊富なクエリ例が記載されています。
aws_iam_user
テーブルから MFA を設定していない IAM ユーザーを確認してみます。
$ steampipe query
Welcome to Steampipe v0.15.0
For more information, type .help
> select name, user_id, mfa_enabled from aws.aws_iam_user where not mfa_enabled;
+---------------+-----------------------+-------------+
| name | user_id | mfa_enabled |
+---------------+-----------------------+-------------+
| user01 | AIDAXXXXXXXXXXXXXXXXX | false |
| test-bot | AIDAYYYYYYYYYYYYYYYYY | false |
| amplify-XXXXX | AIDZZZZZZZZZZZZZZZZZZ | false |
+---------------+-----------------------+-------------+
.inspect table_name
でテーブル定義を確認できます。
> .inspect aws_iam_user
+---------------------------+--------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| column | type | description |
+---------------------------+--------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| _ctx | jsonb | Steampipe context in JSON form, e.g. connection_name. |
| account_id | text | The AWS Account ID in which the resource is located. |
| akas | jsonb | Array of globally unique identifier strings (also known as) for the resource. |
| arn | text | The Amazon Resource Name (ARN) that identifies the user. |
| attached_policy_arns | jsonb | A list of managed policies attached to the user. |
| create_date | timestamp with time zone | The date and time, when the user was created. |
| groups | jsonb | A list of groups attached to the user. |
| inline_policies | jsonb | A list of policy documents that are embedded as inline policies for the user. |
| inline_policies_std | jsonb | Inline policies in canonical form for the user. |
| login_profile | jsonb | Contains the user name and password create date for a user. |
| mfa_devices | jsonb | A list of MFA devices attached to the user. |
| mfa_enabled | boolean | The MFA status of the user. |
| name | text | The friendly name identifying the user. |
| partition | text | The AWS partition in which the resource is located (aws, aws-cn, or aws-us-gov). |
| password_last_used | timestamp with time zone | The date and time, when the user's password was last used to sign in to an AWS website. |
| path | text | The path to the user. |
| permissions_boundary_arn | text | The ARN of the policy used to set the permissions boundary for the user. |
| permissions_boundary_type | text | The permissions boundary usage type that indicates what type of IAM resource is used as the permissions boundary for an entity. This data type can only have a value of Policy. |
| region | text | The AWS Region in which the resource is located. |
| tags | jsonb | A map of tags for the resource. |
| tags_src | jsonb | A list of tags that are attached to the user. |
| title | text | Title of the resource. |
| user_id | text | The stable and unique string identifying the user. |
+---------------------------+--------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
jsonb
というデータ型に着目してください。AWS に限らず、多くの API では JSON で構造化データが返ります。PostgreSQL は JSON をネイティブにサポートしているので SQL で操作できます。
以下の例では IAM ユーザーが所属するグループの詳細を表示しています。
select
name as user_name,
iam_group ->> 'GroupName' as group_name,
iam_group ->> 'GroupId' as group_id,
iam_group ->> 'CreateDate' as create_date
from
aws_iam_user
cross join jsonb_array_elements(groups) as iam_group;
+---------------+---------------+-----------------------+----------------------+
| user_name | group_name | group_id | create_date |
+---------------+---------------+-----------------------+----------------------+
| admin-user | Administrator | AGPABBBBBBBBBBBBBBBBB | 2021-10-01T06:52:13Z |
| amplify-XXXXX | Administrator | AGPABBBBBBBBBBBBBBBBB | 2021-03-12T01:30:56Z |
| test-bot | Bot | AGPACCCCCCCCCCCCCCCCC | 2021-10-02T00:37:38Z |
| user01 | DefaultUser | AGPADDDDDDDDDDDDDDDDD | 2021-03-12T01:30:56Z |
| user02 | DefaultUser | AGPADDDDDDDDDDDDDDDDD | 2021-10-03T04:49:24Z |
| user02 | Operator | AGPAEEEEEEEEEEEEEEEEE | 2021-10-02T00:42:02Z |
| user03 | Audit | AGPAFFFFFFFFFFFFFFFFF | 2021-03-12T01:30:56Z |
| user03 | DefaultUser | AGPADDDDDDDDDDDDDDDDD | 2021-03-18T06:14:03Z |
+---------------+---------------+-----------------------+----------------------+
JSON クエリの詳細はドキュメントを参照してください。
テーブルの結合
もちろん可能です。これが Steampipe の大きな魅力の 1 つでもあります。
以下の例では、aws_ec2_instance
テーブルと aws_vpc_subnet
テーブルから EC2 インスタンスが所属するサブネットとサブネットのアベイラビリティゾーンをクエリしています。
select
instance.instance_id,
instance.subnet_id,
subnet.availability_zone
from
aws_ec2_instance as instance
join aws_vpc_subnet as subnet on instance.subnet_id = subnet.subnet_id;
+---------------------+--------------------------+-------------------+
| instance_id | subnet_id | availability_zone |
+---------------------+--------------------------+-------------------+
| i-01111111111111111 | subnet-xxxxxxxxxxxxxxxxx | ap-northeast-1a |
| i-02222222222222222 | subnet-xxxxxxxxxxxxxxxxx | ap-northeast-1a |
| i-03333333333333333 | subnet-xxxxxxxxxxxxxxxxx | ap-northeast-1a |
| i-04444444444444444 | subnet-yyyyyyyyyyyyyyyyy | ap-northeast-1c |
| i-05555555555555555 | subnet-yyyyyyyyyyyyyyyyy | ap-northeast-1c |
| i-06666666666666666 | subnet-zzzzzzzzzzzzzzzzz | ap-northeast-1d |
+---------------------+--------------------------+-------------------+
以下の例では外部結合を使用し、存在しない EBS ボリュームのスナップショット ID を取得しています。不要スナップショットの整理が捗りそうです。
select
s.snapshot_id,
s.volume_id
from
aws_ebs_volume as v
right join aws_ebs_snapshot as s on v.volume_id = s.volume_id
where
v.volume_id is null;
+------------------------+-----------------------+
| snapshot_id | volume_id |
+------------------------+-----------------------+
| snap-01111111111111111 | vol-0abcdefghijklmnop |
| snap-02222222222222222 | vol-0abcdefghijklmnop |
| snap-03333333333333333 | vol-0qrstuvwxyzabcdef |
| snap-04444444444444444 | vol-0xxxxxxxxxxxxxxxx |
| snap-05555555555555555 | vol-0xxxxxxxxxxxxxxxx |
| snap-06666666666666666 | vol-0yyyyyyyyyyyyyyyy |
| snap-07777777777777777 | vol-0zzzzzzzzzzzzzzzz |
+------------------------+-----------------------+
クラウドサービス間のデータを結合する
テーブルの結合は特定のクラウド (プラグイン) 内のみという制限はありません。つまり複数のクラウドサービス間でデータを結合して新たな洞察を得ることができます。Steampipe の Web サイトの例では Slack と AWS 両方にアカウントが存在するユーザーをクエリする例が紹介されています。
select
aws.name aws_user_name,
slack.id as slack_user_id,
slack.display_name as slack_name
from
aws_iam_user as aws,
slack_user as slack
where
aws.name = slack.email;
+--------------------------+---------------+------------+
| aws_user_name | slack_user_id | slack_name |
+--------------------------+---------------+------------+
| dwight@dundermifflin.com | U2EMB8HLP | dwight |
| jim@dundermifflin.com | U02HE4Z7E | jim |
+--------------------------+---------------+------------+
認証情報のカスタマイズ
AWS プラグインはデフォルトでは AWS CLI と同じ認証情報 (環境変数または Default Profile) を使用し、Default Region に接続します。しかしマルチアカウントで接続したい、異なるプロファイルを使用したい、複数リージョンに接続したいといった要件を満たすことができません。
プラグインインストール時に作成される ~/.steampipe/config/aws.spc
を編集することで認証情報や接続するリージョンをカスタマイズすることができます。
Steampipe 関連の設定ファイルは HCL (Hashicorp Configuration Language) で記述します。
例えばマルチリージョン/アカウントで接続したい場合、以下のように定義します。
connection "aws_01" {
plugin = "aws"
profile = "aws_01"
regions = ["us-east-1", "us-west-2"]
}
connection "aws_02" {
plugin = "aws"
profile = "aws_02"
regions = ["*"]
}
connection "aws_all" {
type = "aggregator"
plugin = "aws"
connections = ["aws_*"]
}
-
profile
で任意の名前付きプロファイルを指定します- AWS SSO も対応していますが、認証情報の更新 (
aws sso login
) は手動で行う必要があります
- AWS SSO も対応していますが、認証情報の更新 (
-
regions
で任意のリージョンを指定できます -
aggregator
を作成すると、マルチアカウントで接続できます
Connection ごとに Steampipe 内部の Postgresデータベースに個別の名前空間が作成されるため、このためスキーマの指定を変えることで各アカウントに接続することができます。
select
title as instance_name,
instance_type,
region,
account_id
from
aws_01.aws_ec2_instance;
+-------------------------+---------------+----------------+--------------+
| instance_name | instance_type | region | account_id |
+-------------------------+---------------+----------------+--------------+
| heuristic_sammet | t3.micro | us-east-1 | 111111111111 |
| condescending_antonelli | t3.medium | us-east-1 | 111111111111 |
| xenodochial_shtern | t3.medium | us-west-2 | 111111111111 |
+-------------------------+---------------+----------------+--------------+
aggregator として作成した Connection を指定すると、合致するすべてのアカウントおよびリージョンの情報を参照します。
select
title as instance_name,
instance_type,
region,
account_id
from
aws_all.aws_ec2_instance;
+-------------------------+---------------+----------------+--------------+
| instance_name | instance_type | region | account_id |
+-------------------------+---------------+----------------+--------------+
| heuristic_sammet | t3.micro | us-east-1 | 111111111111 |
| condescending_antonelli | t3.medium | us-east-1 | 111111111111 |
| xenodochial_shtern | t3.medium | us-west-2 | 111111111111 |
| clever_wilson | t2.small | ap-northeast-1 | 222222222222 |
| sharp_jackson | t2.small | ap-northeast-1 | 222222222222 |
| zealous_ritchie | t3.medium | ap-northeast-3 | 222222222222 |
| interesting_golick | t2.micro | sa-east-1 | 222222222222 |
+-------------------------+---------------+----------------+--------------+
Steampipe Mods による Dasahboard as Code
Mod とは
Steampipe Mod は事前定義されたクエリ (Named queris) によるコンプライアンスチェックやベンチマークの実行 (Controls)、それらの実行結果の Dashboard をまとめて提供する機能です。実体は HCL による定義ファイルおよび SQL のコレクションです。
2022年6月時点で 33 の Mod が公開されています。
例えば AWS に関連する Mod では以下の様なものが提供されています
- AWS Compliance: セキュリティ周りのコンプライアンスベンチマークを実行し、結果を可視化します
- AWS Insights: 各種 AWS リソースの使用状況をレポートします
- AWS Thrifty: 未使用のリソースチェックなどコスト最適化できる要素をチェックします
AWS Compliance Mod の実行例
各 Mod は GitHub で公開されており、Steampipe の実行環境に Clone して利用します。
$ git clone https://github.com/turbot/steampipe-mod-aws-compliance.git
$ cd steampipe-mod-aws-compliance
AWS Compliance Mod は CIS Benchmark や FedRAMP、GDPR、HIPPA など各種コンプライアンスに対応したベンチマークを実行できます。
コンプライアンスチェックを実行する前に、IAM 認証情報レポートを取得しておきます。
$ aws iam generate-credential-report
{
"State": "STARTED",
"Description": "No report exists. Starting a new report generation task"
}
今回は CIS AWS Foundations Benchmark 1.4.0 への準拠状況を確認してみます。
$ steampipe check aws_compliance.benchmark.cis_v140 --export=cis_v140.html
コンソールに各項目のチェック結果と最後にサマリーが出力されます。
--export=
で html, json, csv 形式で結果を出力できます
steampipe check all
で Mod で提供されているすべてのチェックを実行することもできます
html でレポートを確認できるのは非常に便利です。
steampipe dashboard
でダッシュボードサーバーを起動すると、実行結果が可視化されたダッシュボードに接続することもできます。
$ steampipe dashboard
[ Wait ] Loading Workspace
[ Wait ] Starting Dashboard Server
[ Message ] Workspace loaded
[ Message ] Initialization complete
[ Ready ] Dashboard server started on 9194 and listening on local
[ Message ] Visit http://localhost:9194
[ Message ] Press Ctrl+C to exit
NW 経由で Dashboard に接続する
Steampipe の Dashboard や 組み込みの PostgreSQL データベースはデフォルトではローカルホストでリッスンされます。steampipe service start --dashboard
を実行し、Steampipe をサービスモードで実行すると NW 経由の接続を許可できます。
$ steampipe service start --dashboard
Steampipe service is running:
Database:
Host(s): localhost, 127.0.0.1, 172.31.47.239
Port: 9193
Database: steampipe
User: steampipe
Password: ********* [use --show-password to reveal]
Connection string: postgres://steampipe@localhost:9193/steampipe
Dashboard:
Host(s): localhost, 127.0.0.1, 172.31.47.239
Port: 9194
URL: http://localhost:9194/
Managing the Steampipe service:
# Get status of the service
steampipe service status
# View database password for connecting from another machine
steampipe service status --show-password
# Restart the service
steampipe service restart
# Stop the service
steampipe service stop
まとめ
- Steampipe は 標準 SQL を使用し、対応するクラウドサービスの API から情報を取得します
- 利用者はクラウドサービスの API 仕様を意識することなく、SQL でデータを参照、結合できます
- Steampipe Mod を使用すればユーザー自身で SQL を書かずともリソースの使用状況やセキュリティのチェックを実行し、可視化できます
- サービスモードで起動すると、Dashborad や 組み込みの PostgreSQL を外部公開し、別のツールから利用することもできます
参考
以上です。
参考になれば幸いです