パラメータストアの StringList に文字列チェック機能を設定する

概要

AWS SSM パラメータストアの StringList は、カンマ区切りの文字列を格納できますが
a,b,c, のようにカンマで終わる入力値も許容してしまいます。

パラメータストアを利用しているプログラムではこれが問題になるケースもあると思いますので、
パラメータストアの文字列チェック機能(AllowedPattern)を利用して
上記のようなケースを回避できないか検討しました。

結論としては「出来なかった」のですが、検証した内容やワークアラウンド的なものを紹介します。

文字列チェック機能について

パラメータストアには AllowedPattern という設定項目があり、文字列チェック機能を追加することが可能です。
例えば以下のように、英小文字に一致する正規表現 [a-z]* を設定してみます。

$ aws ssm put-parameter \
>   --name "test-string" \
>   --type String \
>   --value "abc" \
>   --allowed-pattern "[a-z]*" \
>   --overwrite
{
    "Version": 1,
    "Tier": "Standard"
}

英小文字で構成された文字列 abcdef を書き込むことは可能ですが、

$ aws ssm put-parameter \
>   --name "test-string" \
>   --value "abcdef" \
>   --overwrite
{
    "Version": 2,
    "Tier": "Standard"
}

英大文字で構成された文字列 ABCDEF は書き込み不可となります。

$ aws ssm put-parameter \
>   --name "test-string" \
>   --value "ABCDEF" \
>   --overwrite

An error occurred (ParameterPatternMismatchException) when calling the PutParameter operation: Parameter value, cannot be validated against allowedPattern: [a-z]*

StringList の場合、カンマで区切られた各文字列がチェックの対象になります。
例えば以下のように英小文字1文字に一致する正規表現 [a-z]{1} を設定すると、

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --type StringList \
>   --value "a,b,c" \
>   --allowed-pattern "[a-z]{1}" \
>   --overwrite
{
    "Version": 1,
    "Tier": "Standard"
}

英小文字1文字のリストである a,b,c,d,e,f を書き込むことは可能ですが、

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --value "a,b,c,d,e,f" \
>   --overwrite
{
    "Version": 2,
    "Tier": "Standard"
}

3文字の文字列をリスト内に含む aaa,b,c,d,e,f は書き込めません。

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --value "aaa,b,c,d,e,f" \
>   --overwrite

An error occurred (ParameterPatternMismatchException) when calling the PutParameter operation: Parameter value, cannot be validated against allowedPattern: [a-z]{1}

StringList にいい感じの文字列チェック追加を検討

最初の話に戻ると、StringList は a,b,c, のような
カンマで終わる入力値も許容してしまうため、これを回避できないか…ということでした。

a,b,c, の場合はリストにすると [ "a", "b", "c", "" ] のようになるはずです。
StringList の場合はこのリストの各要素に対して文字列チェックをかけることになります。

そのため、以下のように「1文字以上の任意の文字列」を示す正規表現 .+ を設定してみました。
これなら、最後の要素 "" が正規表現ではじかれるはず…!

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --type StringList \
>   --value "a,b,c" \
>   --allowed-pattern ".+" \
>   --overwrite
{
    "Version": 3,
    "Tier": "Standard"
}

a,b,c,d,e,f は書き込み可能です。

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --value "a,b,c,d,e,f" \
>   --overwrite
{
    "Version": 4,
    "Tier": "Standard"
}

試しにリスト要素の c を抜いてみると、設定した正規表現によりはじかれていました。
[ "a", "b", "", "d", "e", "f" ] 内の "" が正規表現と不一致だったということですね。

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --value "a,b,,d,e,f" \
>   --overwrite

An error occurred (ParameterPatternMismatchException) when calling the PutParameter operation: Parameter value, cannot be validated against allowedPattern: .+

これなら最後がカンマになっている StringList もブロックしてくれるはず
…と思ったら正常に書き込めてしまいました。

$ aws ssm put-parameter \
>   --name "test-stringlist" \
>   --value "a,b,c,d,e," \
>   --overwrite
{
    "Version": 5,
    "Tier": "Standard"
}

この後も他の正規表現を試してみたりしたのですが、
どうも最後にカンマを加えた場合はリスト最後尾の空文字が正規表現チェックされないような感じでした。

ワークアラウンド: String を StringList みたいに使う

「カンマ区切りの文字列」を表す正規表現 ^[^,]+(?:,[^,]+)*$ を設定した
String タイプのパラメータストアの場合、想定した挙動になりました。

$ aws ssm put-parameter \
>   --name "test-string" \
>   --type String \
>   --value "a,b,c" \
>   --allowed-pattern "^[^,]+(?:,[^,]+)*$" \
>   --overwrite
{
    "Version": 6,
    "Tier": "Standard"
}

$ aws ssm put-parameter \
>   --name "test-string" \
>   --value "a,b,c,d,e,f" \
>   --overwrite
{
    "Version": 7,
    "Tier": "Standard"
}

$ aws ssm put-parameter \
>   --name "test-string" \
>   --value "a,b,,d,e,f" \
>   --overwrite

An error occurred (ParameterPatternMismatchException) when calling the PutParameter operation: Parameter value, cannot be validated against allowedPattern: ^[^,]+(?:,[^,]+)*$

$ aws ssm put-parameter \
>   --name "test-string" \
>   --value "a,b,c,d,e," \
>   --overwrite

An error occurred (ParameterPatternMismatchException) when calling the PutParameter operation: Parameter value, cannot be validated against allowedPattern: ^[^,]+(?:,[^,]+)*$

正規表現は以下を参考にさせていただきました。
カンマ区切りの文字列を正規表現で表す

まとめ

StringList にいい感じの文字列チェックを追加できないか検討したのですが、今回検証した範囲だとうまくいきませんでした。
もしかしたら他にいい正規表現があるのかも知れないですが、現状の選択肢としては以下になるかなと思います。

  • リストに空文字が含まれていても問題ないプログラムを書く
  • String タイプのパラメータに「カンマ区切りの文字列」の正規表現を設定して使う (上記参照)

共同著者: 神津