GitHub の Personal Access Token を使って Python の独自パッケージを Greengrass V2 コアデバイスにインストールしてみた

Greengrass デバイスにプライベートな Python パッケージを Github からインストールします。
2022.03.24

今回の要件

前回の記事では、SSH の秘密鍵を使って GitHub のプライベートリポジトリにあるパッケージを作業 PC(Mac)にインストールしていました。

今回はインストール先を Greengrass (V2) コアデバイスにしたいと思います。しかし要件として、前回とは異なり秘密鍵をデバイスで保持せずにインストールする方法を試したいと思います。

GitHub ではなく AWS CodeArtifact を使う場合については、下記で紹介していますので合わせてご覧いただければと思います。

要件を実現する方法

上記の要件にあるように、今回は(デバイス証明書と秘密鍵以外で追加の)永続的なクレデンシャル情報をデバイス側に持たずに、GitHub から独自パッケージをインストールしてみたいと思います。
今回この要件を実現する為に試す方法は次のとおりです。

  • GitHub の Personal Access Token を発行
  • 発行したトークンを AWS Secrets Manager に保存
  • コンポーネントデプロイ時に AWS Secrets Manager からトークンを取得
  • 取得したトークンを使って GitHub に接続してパッケージインストール

全体を図にすると以下のようなイメージです。

00-pac-sercrets-mng

注意点は記事の下部に記載していますので、そちらも合わせてご確認下さい。
なお、プライベートリポジトリの作成と Python のパッケージ作成は前回の記事の環境をそのまま使います。

それでは作業を行っていきます。

Personal Access Token の設定

GitHub アカウントをクリックして settings を開きます。

03-account-settings

次の画面でメニューから Developer settings をクリックします。

04-developers-settings

Personal access tokens の画面を開いて Generate new token をクリックします。

05-generate-new-token

作成するトークンの設定を行います。有効期限( Expiration は 7 日間としました。)と Note を入力します。
また、権限の範囲は repo にチェックを入れてプライベートリポジトリに対するフル権限を付与しました。(必要に応じて適宜設定してください)

06-setting-new-token

最後に Generate token をクリックしてトークンを作成します。

07-generate-token

これで下記の通り Personal access token が作成できました。
作成したトークンは後から再び確認することができないので、作成できたらどこかに一時的に控えておきましょう。

08-copy-token

Personal Access Token を AWS Secrets Manager に保存

作成したトークンを AWS Secrets Manager に保存するので 「新しいシークレットを保存する」をクリックします。

09-new-secrets

シークレットのタイプは、「その他のシークレットのタイプ」を選択して「キー/値」のペアを下記の通り設定します。

  • キー:mypat (分かりやすいもので構いません)
  • 値:控えておいた Personal Access Token の値を入力

暗号化キーは適当なものを選択して下さい。

10-save-secrets

次の画面でシークレット名、説明を記入します。

11-named-secrets

「自動ローテーション」は無効に設定します。

12-no-rotation

最後に「保存」をクリックして終了です。

13-save-secrets

正常にシークレットが保存されていることを確認します。

14-list-secrets

Greengrass コンポーネントの作成

下記の記事と同様に Greengrass コンポーネントを「GDK CLI」(Greengrass Development Kit CLI)を使って作成します。

コンポーネント名と同じ作業ディレクトリを作成します。

$ mkdir GithubCustomPack
$ cd GithubCustomPack
$ gdk component init -l python -t HelloWorld

gdk-config.json は下記の内容で作成します。

gdk-config.json

{
  "component": {
    "com.example.GithubCustomPack": {
      "author": "CM-ICHIDA",
      "version": "NEXT_PATCH",
      "build": {
        "build_system": "zip"
      },
      "publish": {
        "bucket": "gdk-build",
        "region": "ap-northeast-1"
      }
    }
  },
  "gdk_version": "1.0.0"
}

レシピは下記の内容で作成します。
Script に記載している通り、AWS CLI で Secrets Manager にあるシークレット(トークン)を取得するので、Greengrass デバイス にはあらかじめ AWS CLI をインストールしておいて下さい。
最後に、取得したシークレット(トークン)を使って pip install しています。

recipe.yaml

---
RecipeFormatVersion: "2020-01-25"
ComponentName: "{COMPONENT_NAME}"
ComponentVersion: "{COMPONENT_VERSION}"
ComponentDescription: "This is GDK Test component written in Python."
ComponentPublisher: "{COMPONENT_AUTHOR}"
Manifests:
  - Platform:
      os: all
    Artifacts:
      - URI: "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/GithubCustomPack.zip"
        Unarchive: ZIP
    Lifecycle:
      Install:
        Script: |
          GIT_TOKEN=`aws secretsmanager get-secret-value --secret-id GithubPersonalAccessToekn --query "SecretString" --output text |jq -r '.[]'`
          pip3 install git+https://${GIT_TOKEN}@github.com/cm-ichida/myawsname.git
      Run: "python3 -u {artifacts:decompressedPath}/GithubCustomPack/main.py"

コンポーネントのコード(main.py)は下記になります。
コンポーネントがデプロイされたら 1回だけ s3: Amazon S3 と出力して終了する想定です。

main.py

import myawsname
import json

s3_name_data = json.loads(myawsname.s3())
s3_name = s3_name_data['ServiceName']
print("s3: " + str(s3_name))

準備ができたら、GDK CLI でコンポーネントを作成します。

$ gdk component build
$ gdk component publish

Greengrass コアデバイスのロールエイリアスの修正

Greengrass コンポーネントデプロイ時に AWS Secrets Manager にアクセスできるように権限を追加します。対象の Greengrass コアデバイスのロールエイリアスが参照している IAM Role に権限を追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "*"
        }
    ]
}

Greengrass コンポーネントのデプロイ

GDK CLI により正常にコンポーネントが作成できていれば、下記のように Greengrass のコンソールに作成したコンポーネントが登録されています。
リンクをクリックしてコンポーネントの詳細画面を開きます。

15-select-component

コンポーネント画面で「デプロイ」をクリックします。

16-deploy-component

後は、デプロイするターゲットを選択してデプロイします。デプロイが正常に終了するとコンポーネントログ(今回は、/greengrass/v2/logs/com.example.GithubCustomPack.log)に下記のようなログが出力されます。

下記は分かりやすいように抜粋・編集したものですが、GitHub のリポジトリからパッケージをダウンロードしていることが分かります。
また最後の 4 行目でコンポーネントが実行されて s3: Amazon S3 と出力していることも確認できました。

/greengrass/v2/logs/com.example.GithubCustomPack.log

2022-03-23T10:53:17.726Z [INFO] com.example.GithubCustomPack: stdout. Collecting git+https://****@github.com/cm-ichida
/myawsname.git.
2022-03-23T10:53:17.729Z [INFO] com.example.GithubCustomPack: stdout. Cloning https://****@github.com/cm-ichida/myawsn
ame.git to /tmp/pip-req-build-xxx 
2022-03-23T10:53:24.876Z [INFO] com.example.GithubCustomPack: shell-runner-start. currentState=STARTING, command=["python3 -u /greengrass/v2/packages/artifacts-unarchived/com.example.GithubCust..."]}
2022-03-23T10:53:24.973Z [INFO] com.example.GithubCustomPack: stdout. s3: Amazon S3.

デプロイ後 ggc_usermyawsname パッケージがインストールされていることも確認できました。

$ whoami
ggc_user

$ pip3 show myawsname
Name: myawsname
Version: 0.0.1
Summary: You can receive AWS Service Name.
Home-page: https://github.com/cm-ichida/mypypi
Author: cm-taro
Author-email: cmtaro@example.com
License: MIT
Location: /home/ggc_user/.local/lib/python3.7/site-packages
Requires:
Required-by:

注意点

今回は GitHb から Personal Access Token を使って独自パッケージをインストールしましたが、 Personal Access Token はユーザーに紐づくためユーザーの削除等があるとトークン自体も消えてしまいます。

また、トークンの有効期限が切れた場合は、新たに作成しなおして Secrets Manager のシークレットも更新する必要があります。(トークンの有効期限は「なし」にすることもできますが…)

このように、Personal Access Token を使う場合は注意が必要になります。

最後に

今回はデバイス側に永続的なクレデンシャルを持ちたくない、という条件のもとで Personal Access Token を試してみましたが「注意点」に記載した課題が残る形となりました。

次回はより柔軟な権限設定やトークンの利用時間を指定できる「GitHub App」を使った方法を試してみたいと思います。