GolangでAWSのセキュリティグループを編集するCLIツールを作成したお話


インフラエンジニアの寺岡です。

今回はGolangでCLIツールを作成したお話です。
名前は「goacl」といいますが、どのようなものかご紹介したいと思います。

1.goaclとは

goaclはGolangで記述されたCLIツールです。

AWSのセキュリティグループの一覧を表示したり
特定のグループに対してルールの追加を行ったりすることが出来ます。

現在は一覧表示とルールの追加のみですが
不要なルールの削除も行えるように機能追加する予定です。

2.作成した理由

社内的/個人的で2つの理由があります。

社内的理由

一言で言うと「将来的にオフィスの固定IPアドレスが変更になるから」が理由です。

弊社内のネットワークの品質をより良いものにするために
回線そのものを変更することが決定したのですが
新しいIPアドレスからのアクセス許可はどうしようとなったわけです。

弊社はMSPを業務の主軸としているため
おかげ様で多数のお客様のAWSアカウントをお預かりしております。
IPアドレスが変更になれば都度全てのアカウントの許可設定を見直す必要があり
手動で許可設定を追加するにはどうしても限界があります。
ここで利用するのが「goacl」です。

個人的理由

以前からGolangを書けるようになりたいと思っていて
業務を効率化すると共に個人的な勉強にもなると考えました。

GolangはTerraformなどのHashiCorpの製品や
kubernetesにも利用されている言語なので
インフラエンジニアでも習得するメリットは充分にあると思います。

3.goaclの使い方とロジック

CLIツールなのでコマンドラインから実行する形になります。

Usage

単純にgoaclと入力するとUsageを確認することができます。

$ goacl
goacl is a CLI tool for listing AWS security groups and adding / deleting rules.

Usage:
  goacl [command]

Available Commands:
  add         Add SecurityGroup rule
  help        Help about any command
  list        List SecurityGroup info

Flags:
      --config string   config file (default is $HOME/.goacl.yaml)
  -h, --help            help for goacl
  -t, --toggle          Help message for toggle

Use "goacl [command] --help" for more information about a command.

list

セキュリティグループの一覧を確認することが出来ます。
「list」というサブコマンドを以下のように利用します。

$ goacl list --region us-west-1 --profile default
+-------------+-----------+----------+----------------+--------------+
|   GROUPID   | GROUPNAME | FROMPORT | CIDRIP/GROUPID |    VPCID     |
+-------------+-----------+----------+----------------+--------------+
| sg-XXXXXXXX | default   |       -1 | sg-XXXXXXXX    | vpc-XXXXXXXX |
+-------------+-----------+----------+----------------+--------------+

ブログなのでIDの部分はマスクしていますが
goacl内部でaws-sdk-goを利用してセキュリティグループの情報を取得し
実行結果はテーブルに成形されて出力されます。

コマンドのオプションとして
一覧表示するリージョンと利用するプロファイルの指定が可能です。
何も指定しない場合はデフォルト値が参照されて
リージョンが「ap-northeast-1」、プロファイルが「default」になります。

サブコマンドとオプションの実装はcobraを利用しています。
kubernetesのソースコードでも利用されているので割と有名ではないでしょうか。

add

特定のセキュリティグループにルールを追加することが出来ます。
addコマンドを実行する場合はyamlで記述された設定ファイルが必要になります。

rules:
  - 
    groupid: sg-XXXXXXXX
    fromport: 80
    toport: 80
    ipprotocol: tcp
    ipranges:
      - 0.0.0.0/0
  - 
    groupid: sg-XXXXXXXX
    fromport: 443
    toport: 443
    ipprotocol: tcp
    ipranges:
      - 0.0.0.0/0

80/443ポートを解放する場合は上記のようになります。
iprangesが許可するIPアドレスになりますが
この項目は複数個記述が可能です。
実際に実行してみましょう。

$ goacl add --region us-west-1 --profile default --config config.yaml
$ goacl list --region us-west-1 --profile default
+-------------+-----------+----------+----------------+--------------+
|   GROUPID   | GROUPNAME | FROMPORT | CIDRIP/GROUPID |    VPCID     |
+-------------+-----------+----------+----------------+--------------+
| sg-XXXXXXXX | default   |       80 | 0.0.0.0/0      | vpc-XXXXXXXX |
+             +           +----------+----------------+              +
|             |           |       -1 | sg-XXXXXXXX    |              |
+             +           +----------+----------------+              +
|             |           |      443 | 0.0.0.0/0      |              |
+-------------+-----------+----------+----------------+--------------+

「–config」オプションで設定ファイルの指定が可能です。
後のオプションはlistコマンドと同様です。
addコマンド実行後にlistコマンドを実行すると追加されていることが確認できますね。

ロジックとしては設定ファイルの読み込みにviperを利用しています。
Goのコードの中にyamlの構造と同じ構造体を定義しておき
設定ファイルを読み込んでviper.Unmarshalすることで
構造体にyamlに記述された値を格納しています。

type Config struct {
	Rules []Rules `yaml:rules`
}

type Rules struct {
	GroupID    string   `yaml:groupid`
	FromPort   int64    `yaml:fromport`
	ToPort     int64    `yaml:toport`
	IpProtocol string   `yaml:ipprotocol`
	IpRanges   []string `yaml:ipranges`
}

構造体という考えを実は全く理解していなかったので割と苦戦しましたが
何とか正常に動作してくれるようになりました(もう少し勉強します)

4.まとめ

ひとまず社内で利用してバグの洗い出しをしてからになると思いますが
将来的にOSSとして公開できればと思っています。
まだルールの削除ができないのでそこは引き続き実装してまたブログにまとめます!


この記事をかいた人

About the author

寺岡佑樹

2016年新卒入社、現在4年目。
SREとして、社内の運用業務の仕組みの検討・実装をしつつ
社外で技術的な登壇を行うエバンジェリスト的な側面も持つ。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn