LoginSignup
8
1

More than 3 years have passed since last update.

Github Actions Secrets API を使って Go で Secrets を更新する

Last updated at Posted at 2020-01-31

Github Actions API が公開され、 Secrets を API 経由で更新できるようになりました

Github Actions で利用する Secrets はこれまで手作業で更新する必要がありました。
たくさんのレポジトリを管理していてそれぞれに Actions を仕込むときに更新がとても大変でした。

そんな中、 Github Actions API が公開(2020/1/27)され、 Secrets の更新が API 経由で行えるようになりました :tada:

Secrets | Github Developer Guide

Secrets API の概要

Secrets は秘密鍵、公開鍵を用いて暗号化しているのですが、 Github Actions では libsodium を使って実現しているようです。

github_secrets-100.jpg

  • 暗号化に使う公開鍵を Github Actions API を使って取得します。
  • key_id と key が取得できます。 (libsodium で Secrets を暗号化するための公開鍵です)
    • key は base64 でエンコードされているのでデコードしてバイナリに戻します。
  • 公開鍵を用いて Secrets を暗号化します。
  • Github Actions API を使って Secrets 名と暗号化された Secrets を送信します。
  • Github Actions で用いるときに秘密鍵で復号化して Secrets を利用しているものと思われます。

Go で API を叩いてみます

Go には google/go-github という Github API のライブラリが存在します。

google/go-github - Github

ただ、 2020/1/31 現在、まだこのライブラリでは Github Actions API をサポートしてない模様です。
調べてみると、既にサポート PR が出ていたので試してみました。

go.mod
replace github.com/google/go-github/v29 => github.com/martinssipenko/go-github/v29 v29.0.3-0.20200130054045-bbe3d535861d
func UpdateSecret(owner, repo, name, secret string) error {
    // Github Client を用意
    sts := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
    )
    oc := oauth2.NewClient(context.Background(), sts)
    cli := github.NewClient(oc)

    // 公開鍵を取得
    pubKey, _, err := cli.Actions.GetPublicKey(context.Background(), owner, repo)
    if err != nil {
        fmt.Println("error GetPublicKey:", err.Error())
        return err
    }
    pkBase64 := pubKey.GetKey()
    pk := make([]byte, 32)
    _, err = base64.StdEncoding.Decode(pk, []byte(pkBase64))
    if err != nil {
        fmt.Println("base64 decode error:", pkBase64, err.Error())
        return err
    }

    // sodium で暗号化を施す
    encSec := sodium.Bytes(secret).SealedBox(sodium.BoxPublicKey{Bytes: pk})
    encSecBase64 := base64.StdEncoding.EncodeToString(encSec)

    // Secret を更新
    es := &github.EncryptedSecret{
        Name:           name,
        KeyID:          *pubKey.KeyID,
        EncryptedValue: encSecBase64,
    }
    _, err = cli.Actions.CreateOrUpdateSecret(context.Background(), owner, repo, es)
    if err != nil {
        fmt.Println("failed to update secret", err.Error())
        return err
    }
    return nil
}

これで無事 Secret を API 経由で更新できました :tada:

8
1
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
8
1