1
1

More than 3 years have passed since last update.

AWS SSM Parameter StoreにあるNameのリストをフィルターして取得する

Last updated at Posted at 2021-08-19

この記事でできるようになること

どうも、IoTエンジニアのDangoと言います。AWSを用いたIoTシステムを構築していることが多いです。

今回はPythonでAWS SSM Parameter StoreにあるNameをフィルターして取得し、List化します。

前提

AWS SSM Parameter Storeの詳しい仕様については割愛します。
Python3 + boto3で操作する前提です(AWS CLIなどでもやることは大体同じですが)。
IAMの設定も済んでいる前提です。

基本操作

まずはboto3でssmを操作する方法を簡単に。
最初に、ssmのclientを作ります。

import boto3
REGION = "ap-northeast-1"
ssm = boto3.client("ssm",region_name=REGION)

そして、次のように操作します。

戻り値 = ssm.メソッド(引数)

やりたいこと

AWS SSM Parameter Storeから読み出すとき、
Name(=パラメーター名)が決まっていれば、ssm.get_parametersにその値を入れて終わりなのですが、

「Nameの一部だけを知っている」場合に、同じ部分を持ったNameをListで取得できると、
ssm.get_parametersで一気にValue(=パラメーターの値)を取得できて便利です。

※ssm.get_parametersの使い方については、以下をご覧ください。
https://dev.classmethod.jp/articles/get-data-from-system-manager-parameter-store-using-boto3-ja/

Nameの一部だけを知っている例

例えば、次のようなNameのparameterがあったとします。

hoge-sub
hoge-main
fuga-main
fuga-sub

これを、

  • 「"hoge-"から始まる」
  • 「"fuga-"から始まる」
  • 「"main"を含む」
  • 「"sub"を含む」

といった条件で検索できたら、該当するNameの中身を一度に読めて便利です。

どうすれば実現できるでしょうか。

実現方法

ssm.describe_parametersを使用します。

※補足
Nameが"-"などではなく"/"区切りになっている場合、ssm.get_parameter_by_pathで済む話なのですが、命名規則に"/"が採用されていない場合でも、前方一致(BeginWith)や部分一致(Contains)で調べられます。

以下は、公式ドキュメントのdescribe_parametersの項目を解釈した内容です。
より詳しい情報は公式ドキュメントをご覧ください。
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.describe_parameters

describe_parametersの基本

Nameが"hoge"で始まる。と検索する場合、次のように書きます。

ret = ssm.describe_parameters(
    ParameterFilters=[
        {
            "Key":"Name",
            "Option":"BeginsWith",
            "Values":["hoge"]
        }
    ]
)

Nameに"main"を含む。という場合、次のように書きます。

ret = ssm.describe_parameters(
    ParameterFilters=[
        {
            "Key":"Name",
            "Option":"Contains",
            "Values":["main"]
        }
    ]
)

Valuesの部分は、Listですので、複数検索語句を含めれば「or」で検索可能です。

戻り値

次のような構造の辞書が返ってきます(公式ドキュメントより)。

{
    'Parameters': [
        {
            'Name': 'string',
            'Type': 'String'|'StringList'|'SecureString',
            'KeyId': 'string',
            'LastModifiedDate': datetime(2015, 1, 1),
            'LastModifiedUser': 'string',
            'Description': 'string',
            'AllowedPattern': 'string',
            'Version': 123,
            'Tier': 'Standard'|'Advanced'|'Intelligent-Tiering',
            'Policies': [
                {
                    'PolicyText': 'string',
                    'PolicyType': 'string',
                    'PolicyStatus': 'string'
                },
            ],
            'DataType': 'string'
        },
    ],
    'NextToken': 'string'
}

今はNameが欲しいので、こんな感じでListとして取り出しましょう。

name_list=[]
for parameter in ret["Parameters"]:
    name_list.append(parameter["Name"])

NextToken

しかし、話はこれで終わりではありません。
条件に一致するParameterが多い場合(確かデフォルトでは10より多い場合)、一回のdescribe_parametersではパラメーターを全て読み出すことはできません。
一度に読み出せるパラメーター数がキーワード引数MaxResultsによって決まっているからです。
以下のようにして変更できますが、最大でも50までです。

ret = ssm.describe_parameters(
    ParameterFilters = [
        {
            "Key":"Name",
            "Option":"Contains",
            "Values":["main"]
        }
    ],
    MaxResults = 50 # 1~50 
)

51以上parameterの数が超える可能性がある場合、どうやって条件に当てはまるパラメータを全て取得するのでしょうか。
ここでNextTokenが登場します。
これは返り値の中に含まれています。

next_token = ret['NextToken']

これは、いわば本の「しおり」のようなもので、
parameterのうち何件まで読み出したかをハッシュ値で返してくれています。
50件まで読み込んだのなら、51件以降はこのNextTokenを使って「続きから」読めます。

使い方は、次のような感じでdescribe_parametersの引数に指定します。

ret = ssm.describe_parameters(
    ParameterFilters = [
        {
            "Key":"Name",
            "Option":"Contains",
            "Values":["main"]
        }
    ],
    MaxResults = 50, # 1~50 
    NextToken = next_token  # 追加
)

※補足
NextTokenやMaxResultsの機能は、もともとパラメーターの一覧をページネーションで切り替えられるようにした機能のようです。1ページ〇〇件と指定して、「次へ」を押すとNextTokenで次の〇〇件を取得する、という機能です。

全体像

あとは、next_tokenが返って来なくなるまでdescribe_parametersし続ければ、全件読み出し完了、というわけです。
whileループで読み出しましょう。

import boto3
REGION = "ap-northeast-1"
ssm = boto3.client("ssm",region_name=REGION)

names = [] # target

desc_args={
    "ParameterFilters":[
        {
            "Key":"Name",
            "Option":"BeginsWith",
            "Values":["hoge"]
        }
    ]
}

# NextTokenが空になるまでループを回す
while (True):
    ret = ssm.describe_parameters(**desc_args)  #キーワード引数の展開

    for parameter in ret["Parameters"]:
        names.append(parameter["Name"])

    if(not "NextToken" in ret):
        break
    else:
        desc_args["NextToken"]=ret["NextToken"]

なお、一回目のdescribeと二回目以降のdescribeでは、NextTokenに値を入れるかどうかで引数の使い方が異なるため、普通に書くとssm.describe_parametersを二回書くことになります。
**を使ってキーワード引数をアンパックすることにより、キーワード引数の数に関係なく一回のssm.describe_parametersで簡潔に記述できます。

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