SAM ユーザーに権限を設定するときの書式のことを「パーミッション構文」と呼びます。
例: Sim:listSims API
および Group:* API
のすべてが、2021 年 2 月 1 日以降、IP アドレスレンジ 10.0.0.0/24
のクライアントから利用可能になる設定
{
"statements": [
{
"effect": "allow",
"api": [
"Sim:listSims",
"Group:*"
],
"condition": "currentDate >= date(2021, 02, 01) and ipAddress('10.0.0.0/24')"
}
]
}
パーミッション構文は、JSON フォーマットに従っています。ここでは、各プロパティの意味や、設定する内容を説明します。
SAM で実現できないアクセス制御について
以下のようなアクセス制御は実現できません。
- SIM グループ、LoRaWAN グループ、Sigfox グループごとに、閲覧の可否を制御することはできません。
- 一部の IoT SIM のみ SIM 管理画面に表示するかどうかを制御することはできません。
一方、パスに {sim_id}
や {device_id}
のようなプレースホルダーが含まれる API は pathVariable(placeholder)
を使用して、利用を許可したり、禁止したりできます。
例:
このほかにもプレースホルダーが含まれる API は数多くあります。詳しくは、SORACOM API リファレンス を参照してください。
ステートメントブロックが有効になることと API の呼び出しが許可されることは別の概念です
condition
で指定した条件を満たしたときに有効になるのは「ステートメントブロック」です。
つまり effect
が allow
の場合は、condition
で指定した条件を満たしたときに限り、API の実行が許可 (allow
) されます。
一方で effect
が deny
の場合は、condition
で指定した条件を満たしたときに、API の実行が禁止 (deny
) されます。
JSON を入力する画面について
パーミッション構文に従った JSON は、以下のいずれかの画面で入力します。
パーミッション構文 (JSON) の例
そのほかの例は、FAQ: SAM のパーミッション構文のサンプルはありますか? を参照してください。
API を指定する
ひとつの api
プロパティの中に、複数の API を指定できます。
例:
"api": [
"Sim:listSims",
"Group:*"
]
:
の前の部分を「サービス名」、:
の後の部分を「オペレーション名」と呼びます。
「サービス名」および「オペレーション名」は、SORAOCM API リファレンス で確認できます。
SORACOM プラットフォームの機能と SORACOM API の対応については、SORACOM プラットフォームの機能と API の対応 を参照してください。
特定の API を指定する
特定の API を指定する場合は、api
にサービス名とオペレーション名を配列で指定します。
例: Sim:listSims API
および Sim:getSim API
を対象とする
"api": [
"Sim:listSims",
"Sim:getSim"
]
ワイルドカード (*) で複数の API をまとめて指定する
api
に指定するサービス名とオペレーション名には、ワイルドカード (*) を指定できます。サービス単位などでまとめて API を指定したり、似たような機能を持つ API をまとめて指定するときに便利です。
例 1: サービス名が
Sim:* API
の API のうち、オペレーション名がlist
で始まる下記の API をすべて対象にする"api": [ "Sim:list*" ]
例 2: サービス名が
Subscriber:* API
の API のうち、オペレーション名がSubscriberTransferToken
で終わる下記の API をすべて対象にするSubscriber:deleteSubscriberTransferToken API
Subscriber:issueSubscriberTransferToken API
Subscriber:verifySubscriberTransferToken API
"api": [ "Subscriber:*SubscriberTransferToken" ]
例 3: すべての API を対象にする
"api": [ "*" ]
すべての API を対象にした場合でも、SAM ユーザーからルートユーザーのパスワードやメールアドレスを変更することはできません。
api
プロパティに、1 件だけ指定する場合は、String でも指定できます。
"api": "*"
条件を指定する
condition
には、IPv4 アドレスや API を呼び出した時刻などを使用して、ステートメントブロックが有効になる条件を指定できます。
演算子、変数、関数の 3 つを組み合わせて、条件を指定できます。
項目 | 説明 |
---|---|
演算子 | 比較演算子、論理演算子を利用できます。 |
変数 | currentDate 、currentDateTime などを利用できます。 |
関数 | currentDate や currentDateTime と比較するための date(yyyy,MM,dd) や dateTime(yyyy,MM,dd,HH,mm,ss) などを利用できます。 |
例 1: 2021 年 1 月 27 日 15:00:00 以降に、ステートメントブロックを有効にする
"condition": "currentDate >= dateTime(2021, 01, 27, 15, 00, 00);"
例 2: クライアントの IPv4 アドレスが「10.0.0.0/24」に一致する場合に、ステートメントブロックを有効にする
"condition": "ipAddress('10.0.0.0/24')"
例 3: HTTP メソッドが
GET
の場合に、ステートメントブロックを有効にする"condition": "httpMethod('GET')"
したがって、以下のように指定すると、HTTP メソッドが
GET
のすべての API が許可されます。{ "statements": [ { "effect": "allow", "api": [ "*" ], "condition": "httpMethod('GET')" } ] }
演算子
比較演算子、論理演算子を利用できます。
かっこ () を使って評価の優先順位を指定できます
以下のように記載すると、かっこの中が先に評価されます。
"condition": "not (samUserName eq 'example-user-name')"
比較演算子
文字列や数値を比較できます。
例:
"condition": "samUserName eq 'example-user-name'"
演算子 | 説明 |
---|---|
eq / == | 等しい
|
ne / != | 等しくない
|
lt / < | より小さい (*1)
|
le / <= | より小さいか等しい (*1)
|
gt / > | より大きい (*1)
|
ge / >= | より大きいか等しい (*1)
|
matches | 文字列が正規表現と一致する
変数が |
- (*1) 文字列の比較には利用しないでください。
論理演算子
and
、or
、not
を利用すると、複雑な条件を指定できます。
例:
"condition": "(samUserName eq 'example-user-name') and (currentDate eq date(2021,11,11))"
演算子 | 説明 |
---|---|
and | 演算子の前後の条件の、両方を満たす
|
or | 演算子の前後の条件の、両方もしくは一方を満たす
|
not / ! | 演算子の後の条件を満たさない
|
変数
ステートメントブロックを有効にする条件として、以下の変数を利用できます。
変数 | 説明 |
---|---|
currentDate | 現在の日付 (UTC) を表すオブジェクト。date(yyyy, MM, dd) で取得したオブジェクトと比較します。 |
currentDateTime | 現在の日時 (UTC) を表すオブジェクト。dateTime(yyyy, MM, dd, HH, mm, ss) で取得したオブジェクトと比較します。 |
sourceIp | クライアントの IPv4 アドレスを表す文字列。例: 10.0.0.1 、198.51.100.1 。より柔軟に指定する場合は、この sourceIp ではなく ipAddress(CIDR...) を使用してください。 |
httpMethod | HTTP メソッドを表す文字列。例: GET POST PUT DELETE 。より柔軟に指定する場合は、この httpMethod ではなく httpMethod(method...) を使用してください。 |
samUserName | API キーと API トークンを発行した SAM ユーザー名。SORACOM ユーザーコンソールの場合は、ログインした SAM ユーザー名です。pathVariable() と組み合わせても便利です。 |
変数が currentDate
または currentDateTime
の場合は、演算子 matches
は利用できません。
変数と関数の使用例については、使用例 を参照してください。
関数
ステートメントブロックを有効にする条件として、以下の関数を利用できます。
変数と関数の使用例については、使用例 を参照してください。
date(yyyy, MM, dd)
日付 (UTC) を表すオブジェクトを取得します。
引数:
引数 | 型 | 説明 |
---|---|---|
yyyy | Integer | 年 |
MM | Integer | 月 (*1) |
dd | Integer | 日 (*1) |
- (*1) 数字が 1 桁の場合は、先頭の
0
は省略できます。
戻り値:
日付 (UTC) を表すオブジェクトを返します。
例:
date(2021, 01, 27)
dateTime(yyyy, MM, dd, HH, mm, ss)
日時 (UTC) を表すオブジェクトを取得します。
引数:
引数 | 型 | 説明 |
---|---|---|
yyyy | Integer | 年 |
MM | Integer | 月 (*1) |
dd | Integer | 日 (*1) |
HH | Integer | 時 (*1) |
mm | Integer | 分 (*1) |
ss | Integer | 秒 (*1) |
- (*1) 数字が 1 桁の場合は、先頭の
0
は省略できます。
戻り値:
日時 (UTC) を表すオブジェクトを返します。
例:
dateTime(2021, 01, 27, 15, 00, 00)
date(2021, 01, 27)
と dateTime(2021, 01, 27, 00, 00, 00)
は、同じ値です。
ipAddress(CIDR...)
API クライアントの IPv4 アドレスが、CIDR に指定した範囲に含まれているかどうかを判定します。
引数:
引数 | 型 | 説明 |
---|---|---|
CIDR | String (*1) | API クライアントの IPv4 アドレスの範囲。CIDR 表記で指定します。 |
- (*1) 複数指定できます。
戻り値:
以下のいずれかの値を返します。
true
: API クライアントの IPv4 アドレスが、CIDR に指定した範囲のいずれかに含まれています。false
: API クライアントの IPv4 アドレスが、CIDR に指定したどの範囲にも含まれていません。
例:
API クライアントの IPv4 アドレスが 10.0.1.0
~ 10.0.1.255
の範囲に含まれる場合に、true
を返します。
ipAddress("10.0.1.0/24")
API クライアントの IPv4 アドレスが 10.0.1.0
~ 10.0.1.255
または 10.0.2.0
~ 10.0.2.255
の範囲に含まれる場合に、true
を返します。
ipAddress("10.0.1.0/24", "10.0.2.0/24");
httpMethod(method...)
API の HTTP メソッドが、methods に指定した HTTP メソッドと一致するかどうかを判定します。
引数:
引数 | 型 | 説明 |
---|---|---|
method | String (*1) | HTTP メソッド。大文字で指定します。 |
- (*1) 複数指定できます。
戻り値:
以下のいずれかの値を返します。
true
: API の HTTP メソッドが、methods に指定した HTTP メソッドのいずれかと一致します。false
: API の HTTP メソッドが、methods に指定したどの HTTP メソッドとも一致しません。
例:
httpMethod('GET', 'POST');
すべての API のうち GET メソッドおよび POST メソッドを使用する API のみを許可する場合の JSON は以下のとおりです。
{
"statements": [
{
"effect": "allow",
"api": "*",
"condition": "httpMethod('GET', 'POST')"
}
]
}
論理演算子 not と組み合わせないことをおすすめします
httpMethod(method...) と 論理演算子 not
を組み合わせて、以下のように設定することもできます。
{
"statements": [
{
"effect": "allow",
"api": "*",
"condition": "not httpMethod('DELETE')"
},
{
"effect": "allow",
"api": "*",
"condition": "httpMethod('GET', 'POST', 'PUT')"
}
]
}
1 個目のステートメントブロックと、2 個目のステートメントブロックは、同じ効果があるように見えますが、これは同じではありません。
- 1 個目のステートメントブロックのように指定すると、HEAD メソッドを使用する
FileEntry:getFileMetadata API
を呼び出せます。 - 2 個目のステートメントブロックでは、この API は呼び出せません。
このように、not
を組み合わせて許可 (allow
) すると、今後、SORACOM API に、ほかの HTTP メソッド (例: PATCH メソッド) を使用した API が増えたときに、予期しない形で権限を許可することになります。そのようなことがないように、not
と組み合わせない指定方法をおすすめします。
pathVariable(placeholder)
API のパス中のプレースホルダーに指定した値を取得します。
たとえば、User:hasUserPassword API
のように、パス中にプレースホルダー ({operator_id}
、{user_name}
などのこと) が含まれる API を呼び出したとき、プレースホルダー ({operator_id}
や {user_name}
) に指定した値を取得できます。
同じステートメントブロックで指定できる API に制限があります
pathVariable(placeholder)
を指定する場合、placeholder
には、そのステートメントブロックに含まれるすべての API に共通のプレースホルダーしか指定できません。
たとえば、以下のように {user_name}
が存在する User:hasUserPassword API
と、{user_name}
が存在しない Billing:getBilling API
を 1 つのステートメントブロックで指定して、condition
に pathVariable('user_name')
を指定することはできません。
{
"statements": [
{
"effect": "allow",
"api": [
"User:hasUserPassword",
"Billing:getBilling"
],
"condition": "pathVariable('user_name') == 'EXAMPLE-USER'"
}
]
}
これは、Billing:getBilling
を呼び出した際、評価対象のプレースホルダー {user_name}
が存在しないために、pathVariable('user_name')
が null
を返すことによる制限です。
これを回避するためには、ステートメントブロックを以下のように分けて指定してください。
{
"statements": [
{
"effect": "allow",
"api": [
"User:hasUserPassword"
],
"condition": "pathVariable('user_name') == 'EXAMPLE-USER'"
},
{
"effect": "allow",
"api": [
"Billing:getBilling"
]
}
]
}
pathVariable('path') の評価について
- pathVariable('path') を評価する際は、ファイルパスの先頭と末尾の
/
(正規表現で示すと/+
) が削除されたうえで、完全一致したファイルパスが評価対象です。ルートパス (
/
) を評価するときは、pathVariable('path') == null
を指定します。{ "statements": [ { "effect": "allow", "api": "FileEntry:listFiles", "condition": "pathVariable('path') == null" } ] }
logs
という名前のファイルまたはフォルダを評価するときは、pathVariable('path') == 'logs'
を指定します。{ "statements": [ { "effect": "allow", "api": "FileEntry:listFiles", "condition": "pathVariable('path') == 'logs'" } ] }
あるフォルダ (
/folder_name/
) 以下のすべてのファイルやフォルダを評価するときは、pathVariable('path') matches 'folder_name(/.+)*'
を指定します。{ "statements": [ { "effect": "allow", "api": "FileEntry:listFiles", "condition": "pathVariable('path') == null or pathVariable('path') matches 'folder_name(/.+)*'" } ] }
(*)
FileEntry:listFiles API
の条件に pathVariable('path') を指定するときは、以下のいずれかを先頭に指定してください。これは、ルートパスで pathVariable('path') が null になることによる制限です。- ルートパスを含む場合:
pathVariable('path') == null or
- ルートパスを含まない場合:
pathVariable('path') != null and
- ルートパスを含む場合:
- pathVariable('path') の評価対象の先頭と末尾に
/
を入力しないでください。先頭と末尾の/
が削除されてから評価されるため、すべてのファイルおよびフォルダが一致しなくなります。たとえば、ルートフォルダのlogs.txt
の読み書きを許可する場合は、pathVariable('path') == 'logs.txt'
と入力します。pathVariable('path') == '/logs.txt'
と入力しないでください。
引数:
引数 | 型 | 説明 |
---|---|---|
placeholder | String | プレースホルダー名。プレースホルダー名については、SORACOM API リファレンス を参照してください。 |
戻り値:
指定したプレースホルダーの値が String 型で返されます。
パスにプレースホルダーが含まれなかった場合は、'null' が返されます。
例:
SAM ユーザー EXAMPLE-USER
のパスワードの更新 (User:updateUserPassword API
の呼び出し) を許可する場合の JSON は以下のとおりです。
{
"statements": [
{
"effect": "allow",
"api": "User:updateUserPassword",
"condition": "pathVariable('user_name') == 'EXAMPLE-USER'"
}
]
}
これを samUserName
と組み合わせると、SAM ユーザーが自分自身のパスワードのみを変更することを許可できます。このとき、他の SAM ユーザーのパスワードは変更できません。
{
"statements": [
{
"effect": "allow",
"api": "User:updateUserPassword",
"condition": "pathVariable('user_name') == samUserName"
}
]
}
使用例
condition
に変数と関数を組み合わせた場合の使用例は以下のとおりです。
例 1: 2021 年 1 月 27 日以降に、ステートメントブロックを有効にする
"condition": "currentDate >= date(2021, 01, 27)"
数字が 1 桁の場合は、以下のように先頭の
0
は省略できます。"condition": "currentDate >= date(2021, 1, 27)"
例 2: 2021 年 1 月 27 日 15:00:00 以降に、ステートメントブロックを有効にする
"condition": "currentDateTime >= dateTime(2021,01,27,15,00,00)"
例 3: 特定の IPv4 アドレス (
10.0.0.1
) からアクセスされた場合に、ステートメントブロックを有効にする"condition": "sourceIp == '10.0.0.1'"
"condition": "sourceIp matches '10\.0\.0\.1'"
例 4: GET メソッドの API を呼び出す場合に、ステートメントブロックを有効にする
"condition": "httpMethod == 'GET'"
例 5: 特定のユーザーが発行した API キーと API トークンを利用して API を呼び出す場合に、ステートメントブロックを有効にする
"condition": "samUserName == 'EXAMPLE-USER'"
例 6: 特定のユーザーの情報に対する API 呼び出しの場合 (API パスにプレースホルダー
{user_name}
を含み、その値が特定のユーザーの場合) に、ステートメントブロックを有効にする"condition": "pathVariable('user_name') == 'EXAMPLE-USER'"