AlibabaCloudのセキュリティグループをalibaba-cloud-sdk-goを使って操作してみた。


Alibaba Cloudは、中国のアリババが展開するクラウドサービス。
最近、日本向けにもサービスを開始し、AWSやGCP、Azureと並ぶ急速な勢いで伸びています。
今回は、そんなAlibaba CloudのセキュリティグループをGo言語を使って操作する方法を紹介します。
>今回Alibaba Cloudは初めて触りました。

## セキュリティグループ

セキュリティグループは、Alibaba Cloudにおいて、ファイアーウォールの役割を持つサービスです。このサービスで作成したセキュリティグループをECSインスタンス(AWSだとEC2に相当)に割り当てることで、ポートを開け閉めするような設定をインスタンスに適応させます。

## 手順
さて、作業をしていきましょう。
今回の目標はセキュリティグループの操作をGo言語から行うことです。

### 1. alibaba-cloud-sdk-go

[alibaba-cloud-sdk-go](https://github.com/aliyun/alibaba-cloud-sdk-go)は、Alibaba CloudのAPIをGo言語から便利に操作するためのパッケージです。`go get`や`dep`を使ってインストールしてください。
あ、`dep`は先にコード書かないといけませんね。

### 2. RAMユーザーを作成

API操作をするために、アクセスキーIDとアクセスキーSecret、リージョンIDが必要です。
Alibaba Cloudのルートアカウントで操作してると全てのサービスをいじれてセキュリティ的に問題があるので、権限を制限したRAMユーザーを作成し、そのアクセスキーを取得します。
>AWSだとIAMユーザーに相当

![ram.png](https://qiita-image-store.s3.amazonaws.com/0/151746/fd57bd21-86ac-9541-e7ac-b0d5ff34d980.png)


1. Alibaba CloudコンソールのResource Access Management
2. ユーザー
3. 新規ユーザー

で設定することでRAMユーザーを作成できます。作成時にアクセスキーIDとアクセスキーSecretをダウンロードします。
次に、作成後は何も権限がない状態なので、ユーザー名をクリックし、権限付与ポリシーを設定します。
今回は、`AliyunECSFullAccess`だけあればいいでしょう。

### 3. セキュリティグループを作成

APIで作成もできますが、今回はあらかじめ作成したセキュリティグループを操作することにします。
![group.png](https://qiita-image-store.s3.amazonaws.com/0/151746/9e72c72b-0f78-e967-fa3b-c72d2af5c3a2.png)

ECSの中にセキュリティグループがあります。ここでセキュリティグループを作成しておきます。
![before.png](https://qiita-image-store.s3.amazonaws.com/0/151746/138aded9-1355-1423-6a46-22f86b195a43.png)

デフォルトは定番のポートだけ空いてますね。
これで準備完了です。これをECSインスタンスに割り当てるんですが、セキュリティグループ操作を試すだけならいらないかも? 今回は割り当てています。

### 4. Go

いよいよGo言語を書いていきます。
AWSのように詳細なSDKドキュメントはないようなので、生のAPIのドキュメントを見ながら書きました。

まず、今回`import`したパッケージはこれです。

```go
import (
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
	"os"
	"strings"
)
```

これをふまえて、操作を書いていきます。

#### ecsクライアントの作成

```go
	ecsClient, err := ecs.NewClientWithAccessKey(
		"ap-northeast-1", //リージョンID
		"アクセスキーID",
		"アクセスキーSecret")
```

RAMユーザーを作成したときにダウンロードしたアクセスキーIDとアクセスキーSecretはここで使います。
`NewClientWithAccessKey()`によって、RAMユーザーが持つ権限の範囲でECSサービスを操作するためのクライアントが作成されます。リージョンIDは東京リージョンを使っているので、ap-northeast-1にしています。

#### DescribeSecurityGroups

既にあるセキュリティグループの情報を取ってきます。

```go
	request := ecs.CreateDescribeSecurityGroupsRequest()
	response, err := ecsClient.DescribeSecurityGroups(request)
	fmt.Println(response)
```

alibaba-cloud-sdk-goでサービスを操作するときは、基本、

1. `request := ecs.Create****Request()`でリクエストを作成
2. `ecsClient.****(request)` のようにリクエストをサービスの関数に渡す

というようにして操作します。

さて、テスト用のセキュリティグループ`test_group`のIDを取り出してみましょう。
以下のように返ってきたセキュリティグループの情報`response`から`groupid`を取り出します。

```go
	groupname := "test_group"
	groupid := ""
	for _, v := range response.SecurityGroups.SecurityGroup {
		if v.SecurityGroupName == groupname {
			groupid = v.SecurityGroupId
		}
	}
```

#### 	AuthorizeSecurityGroup

新たにルールを追加し、ポートを開けます。

```go
	request3 := ecs.CreateAuthorizeSecurityGroupRequest()
	reqmap := map[string]string{
		"SecurityGroupId": groupid,
		"RegionId":        region,
		"IpProtocol":      "TCP",
		"PortRange":       "23/23",
		"SourceCidrIp":    "0.0.0.0/0"}
	request3.FormParams = reqmap
	response3, err := ecsClient.AuthorizeSecurityGroup(request3)
```


ここでは、以下のことをしています。

1. CreateAuthorizeSecurityGroupRequest()でリクエストを作成
2. 追加するルールのパラメータmapを作成
3. リクエストにルールのmapを設定
4. ecsClient.AuthorizeSecurityGroup(request3)でリクエストを送信・実行

これでポート23が開放されました。
![after.png](https://qiita-image-store.s3.amazonaws.com/0/151746/01217b5a-d969-6a50-eb15-beae07a90a32.png)

#### RevokeSecurityGroup

ポートを開けたので、今度は閉じてみましょう。

```
	request4 := ecs.CreateRevokeSecurityGroupRequest()
	reqmap := map[string]string{
		"SecurityGroupId": groupid,
		"RegionId":        region,
		"IpProtocol":      "TCP", "PortRange": "23/23", "SourceCidrIp": "0.0.0.0/0"}
	request4.FormParams = reqmap
	response4, err := ecsClient.RevokeSecurityGroup(request4)
```

ここでは、以下のことをしています。

1. CreateRevokeSecurityGroupRequest()でリクエストを作成
2. 削除するルールのパラメータmapを作成
3. リクエストにルールのmapを設定
4. ecsClient.RevokeSecurityGroup(request4)でリクエストを送信・実行

これでポート23が閉じました。

## おわりに

今回はGo言語でAlibaba Cloudのセキュリティグループを操作してポートの開け閉めをしてみました。
[alibaba-cloud-sdk-go](https://github.com/aliyun/alibaba-cloud-sdk-go)を使うと、他のAPI操作も似たような書き方で書けそうです。[APIのドキュメント](https://www.alibabacloud.com/help/doc-detail/25485.htm?spm=a2c63.p38356.b99.233.3fa63bcdWI0d41)を参考に試してみてはどうでしょうか。