12
6

More than 3 years have passed since last update.

GitHub ActionsでSrc IP制限のかかったサービス(AWS RDS)につなぐ

Posted at

はじめに

GitHub Actionsは、GitHub上のコードに対して、PushやPullRequestをフックして、処理を実行できる処理基盤です。

このGitHub Actionsを使って自動テストや自動デプロイをするのですが、GitHub ActionsのワーカーのグローバルIPアドレスは毎回変わるため、Src IP制限のかかったサービスを使おうとするとうまくいきません。

そこで、この記事では、GitHub ActionsからSrc IP制限のかかったサービスを使う方法を、AWSのRDSを例に上げて説明します。

概要

処理の概要は以下のとおりです

  1. GitHub ActionsのワーカーのグローバルIPを、haythem/public-ip@v1.2 を使って取得する
  2. RDSのSecurity Groupに対して、取得したグローバルIPからの通信を一時的に許可する
  3. サービスにつないでやりたいことをやる
  4. RDSのSecurity Groupに対して、取得したグローバルIPからの通信を一時的に遮断する

作り方

1. RDSのセキュリティグループを開け締めするプログラムを作る

まず、Security Groupを操作するためのプログラムをGo言語で作ります。

sgutil.go

package main

import (
    "fmt"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ec2"
    "github.com/aws/aws-sdk-go/service/rds"
    "os"
    "syscall"
)

const RDS_ID = "myrds" // RDSのID
const RDS_PORT = 5432 // RDSのポート

// cidrからの通信を許可するようにRDSのセキュリティグループを変更する。
// @param : ipAddr :通信を許可したいIPアドレス。
// @param : op : 操作。op=openで開ける。 op=closeで閉じる。
func securityGroupIngressControl(ipAddr string, op string) {
    sess, err := session.NewSession(&aws.Config{Region: aws.String("ap-northeast-1")})
    if err != nil {panic(err)}
    rdsService := rds.New(sess)

    // RDSのセキュリティグループの取得
    input := &rds.DescribeDBClustersInput{DBClusterIdentifier: aws.String(RDS_ID)}
    result, err := rdsService.DescribeDBClusters(input)
    if err != nil {panic(err)}
    securityGroupId := *(result.DBClusters[0].VpcSecurityGroups[0].VpcSecurityGroupId)

    // security groupの操作
    ec2Service := ec2.New(sess)
    ipPermissions := []*ec2.IpPermission{
        {
            FromPort:   aws.Int64(int64(RDS_PORT)),
            ToPort:     aws.Int64(int64(RDS_PORT)),
            IpProtocol: aws.String("tcp"),
            IpRanges:   []*ec2.IpRange{{CidrIp: aws.String(ipAddr + "/32")}},
        },
    }
    if op == "open" {
        // security groupを開ける
        input := &ec2.AuthorizeSecurityGroupIngressInput{
            GroupId:       aws.String(securityGroupId),
            IpPermissions: ipPermissions,
        }
        _, err := ec2Service.AuthorizeSecurityGroupIngress(input)
        if err != nil {panic(err)}
    } else if op == "close" {
        // security groupを閉じる
        input := &ec2.RevokeSecurityGroupIngressInput{
            GroupId:       aws.String(securityGroupId),
            IpPermissions: ipPermissions,
        }
        _, err := ec2Service.RevokeSecurityGroupIngress(input)
        if err != nil {panic(err)}
    } else {
        panic("invalid op")
    }
}

func printUsage() {
    fmt.Printf("Argument ERROR. \n\nUsage: go run %s [open|close] IpAddress \n", os.Args[0])
}

func main() {
    if len(os.Args) != 3 {
        printUsage()
        syscall.Exit(1)
    }
    op := os.Args[1] // 操作 [open|close]
    ipAddr := os.Args[2]
    securityGroupIngressControl(ipAddr, op)
}

※Go言語を用いなくても、bashとaws cliを駆使して実現することも可能ですが、少し複雑なプログラムのため、プログラミング言語で作りました。

2. GitHubのsecretsにAWSのクレデンシャル情報を追加する

今回は、AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY という名前に、それぞれAWSのシークレットを登録します。

3. Github Actionsのワークフローを作る

./github/workflows/my_action.yml


name: MyAction

on:
  push:
    # developブランチにpushされたら動き出す。
    branches: [ develop ]

jobs:
  my_action:
    name: MyJob
    runs-on: ubuntu-latest
    steps:

      # AWSのクレデンシャルをセット
      - name: Create AWS credential Environment Variables
        uses: aws-actions/configure-aws-credentials@v1
        with:
          # GitHubのSecretsに登録しておくと、secrets.XXXXで参照できる
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      # GitHub ActionsのワーカーのGlobalIPアドレスを取得するためのステップ
      - name: Install Public IP Lib
        id: ip
        uses: haythem/public-ip@v1.2

      # Go言語のセットアップ
      - name: Setup Go
        uses: actions/setup-go@v2
        with:
          go-version:  1.15

      # コードのチェックアウト
      - name: checkout
        uses: actions/checkout@v2

      # RDSのセキュリティグループに対して、GitHub Actionsのワーカーからの通信を許可する
      - name: Open RDS security group ingress from this IP
        run: go run sgctl.go open ${{ steps.ip.outputs.ipv4 }} # steps.ip.outputs.ipv4でIPを参照できる

      # DBに接続していろいろする
      - name: Run DB Ops
        run: xxxxxxxxx

      # RDSのセキュリティグループに対して、GitHub Actionsのワーカーからの通信を閉じる
      - name: Close RDS security group ingress from this IP
        if: always() # alwaysをつけることにより、アクションが失敗しても必ず実行されるようにする
        run: go run sgctl.go close ${{ steps.ip.outputs.ipv4 }}


12
6
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
12
6