Account Security
Users & Roles
You can allow other people in your organization to access to your Soracom account by using Soracom Access Management (SAM) to create and manage different users. Each user can be created with different roles or access privileges.
For example, your technical department may have full access to the User Console, while your accounting department may have read-only access to billing and payment information.
In addition, users can be created in order to allow cloud services to programmatically access and manage your account.
Access management to your Soracom account is performed using Soracom Access Management (SAM) Users and Roles.
Adding and removing users is simple, and allows you to manage access to your Soracom account without having to share your Soracom root account login information.
SAM Users and Roles are managed from the Security screen. Login to the User Console. Click your account menu, then select Security.
By default, SAM Users and Roles can be managed by logging in to your Soracom root account (email address and password). To manage SAM Users and Roles while logging in as a SAM user, ensure that the User:*
and Role:*
API permissions are enabled for your SAM user account.
Creating a SAM User
-
From the Security screen, click the Users tab. Then click the Create a user button.
-
Enter a unique Name for the SAM user. This username will be used to login to the User Console or access the Soracom API. You can also add a Description to help identify this user.
Then click the Create button.
The user will be listed in the Users screen.
Authentication Methods
By default, when a SAM user account is created, the account will not contain any authentication credentials. SAM Users support two types of authentication methods:
- Password - This will enable password-based authentication, and allow an authorized user to log in to the User Console using your Operator ID, the SAM username, and password.
- AuthKeys - This will generate a AuthKey ID and AuthKey Secret key pair, which can be used to authenticate Soracom API and Soracom CLI access.
Each authentication method is optional. For example, if you create a SAM User with AuthKeys authentication in order to integrate the Soracom API or Soracom CLI in your application, you do not need to enable Password authentication. This allows you to use SAM Users to separate your authorized users from your application integrations.
Password authentication can be combined with Multi-Factor Authentication to improve account security. For more information, refer to the Multi-Factor Authentication documentation.
When generating AuthKeys, each SAM User account is limited to a maximum of two AuthKeys. For more information, refer to the AuthKeys documentation.
To enable an authentication method:
-
Click the name of the SAM User you want to manage.
-
From the SAM User settings page, click the Authentication tab.
Enabling Password Authentication
- From the Console login password panel, click the Create password button. Then follow the prompt to create a password for the SAM User.
Once a password has been created, an authorized user can login to the User Console using the Operator ID, SAM User account username, and the specified password. For convenience, a login URL will be displayed once a password has been created.
Enabling AuthKeys Authentication
- From the AuthKeys panel, click the Generate an AuthKey button. An AuthKey ID and AuthKey Secret key pair will be automatically generated.
When generating a new AuthKey, the AuthKey Secret will only be shown once. Ensure that you save the secret key in a secure location. If you lose the secret key, you will need to generate a new AuthKey.
Access Levels
Once a SAM User authentication method has been enabled, an authorized user or application integration will be able to access the Soracom User Console, Soracom API, or Soracom CLI. However, by default, the SAM User account will not include any permissions to perform actions.
You can add permissions to SAM Users in order to allow (or deny) access to different parts of the User Console, API, or CLI.
Access levels allow you to create permissions for one or more SAM Users at a time, and are structured as follows:
- Default SAM User Permissions - Permissions defined in this access level apply to all SAM Users in your account.
- Roles - Permissions defined in this access level apply to all SAM Users that are attached to the role.
- Inline Permissions - Permissions defined in this access level apply only to the specific SAM User account.
Regardless of access level, permissions are defined by using a Permission Statement. Refer to the Permission Statements section below for information on syntax and custom permission types.
When multiple permissions are defined, a deny
permission will always take precedence over any allow
permission based on which API matches the permissions. For example:
Default SAM User Permissions | Inline Permissions | Effect |
---|---|---|
Access to Sim:listSims is set to deny |
Access to Sim:listSims is set to allow |
The SAM User is not allowed to access the Sim:listSims API |
Access to Sim:listSims is set to allow |
Access to Sim:listSims is set to deny |
The SAM User is not allowed to access the Sim:listSims API |
Access to * is set to allow |
Access to Billing:* is set to deny |
The SAM User is not allowed to access any Billing:* APIs, however they can access all other APIs |
Creating Default Permissions
In order to modify Default SAM User Permissions, you must be logged in to your Soracom root account using your email and password credentials.
-
From the Security screen, click the Default SAM User Permission Configuration tab.
- Enter the Permissions using the Permission Statement format, then click the Save button.
Once the default permissions have been modified, they will apply to all SAM Users in your account. No further configuration is required.
Creating a Role
Roles may be managed using your Soracom root account, or by a SAM User with access to the Role:*
API permission.
-
From the Security screen, click the Roles tab. Then click the Create a role button.
-
Enter a Name for the role, and optionally a Description to identify the role. Then enter the Permissions using the Permission Statement format, and click the Create button.
Once a role has been created, it can be attached to a SAM User:
-
From the Security screen, click the Users tab. Then click the name of the SAM User you want to manage.
-
From the SAM User settings page, click the Permissions tab.
-
From the Attached roles panel, click the Attach roles button. Select the roles you want to attach to the SAM User, then click the Attach button.
-
Select the roles to attach to the user, then click Attach.
Once a role has been attached, its permissions will apply to the SAM User.
The maximum number of SAM Roles that you may configure is 20. Please contact Soracom Support if you need an increase in this number.
Creating Inline Permissions
Inline permissions may be managed using your Soracom root account, or by a SAM User with access to the User:*
API permission. Some User
APIs include the username, and their corresponding permission statement can be configured so that a SAM User can only access the APIs pertaining to their own username, and not the usernames of other SAM User accounts.
-
From the Security screen, click the Users tab. Then click the name of the SAM User you want to manage.
-
From the SAM User settings page, click the Permissions tab.
- In the Inline permissions panel, enter the Permissions using the Permission Statement format, and click the Save button.
Permission Statements
Permission statements are defined using JSON format, and looks like this:
{
"statements": [
{
"effect": "allow",
"api": ["Subscriber:list*", "Group:*"],
"condition": "currentDate >= date(2016, 02, 01) and ipAddress('10.0.0.1/24')"
}
]
}
The permission statement includes the following parameters:
- statements (array, required) - An array of individual permissions, each of which contain the following:
- effect (string, required) - Define whether this permission should
allow
ordeny
access to the specified API. - api (string or array of strings, required) - The API(s) which should be included in this permission. The asterisk
*
symbol can be used as a wildcard to match multiple APIs. - condition (string, optional) - An expression to be evaluated in order to determine if a requested API matches the permission.
- effect (string, required) - Define whether this permission should
API Parameter and Wildcards
Each permission must include one or more API paths, with each path specified using the following format: Service:Operation
.
The Service and Operation names are defined according to the Soracom API. You can find all available service and operation names using the API Reference.
To specify a single operation, simply use the full service and operation name in the API path parameter. For example:
"api": "Subscriber:listSubscribers",
You can use the *
wildcard in order to match multiple paths. For example,
"api": "Subscriber:list*",
will match both the Subscriber:listSubscribers
and Subscriber:listSessionEvents
APIs.
You can also use the *
wildcard to match all operation names. Setting:
"api": "Subscriber:*",
will match all API operations underneath Subscriber
.
Similarly,
"api": "*",
will match all APIs.
Even if a SAM User has been given permission to access all APIs, root account level operations, such as changing the root account email or password, cannot be performed.
The api parameter can also be defined using an array of strings, with each string following the same Service:Operation
format. This can be used to simplify the permission statement for multiple APIs. For example:
"api": ["Subscriber:list*", "Group:*"],
will match both Subscriber:listSubscribers
and Subscriber:listSessionEvents
, as well as all operations within Group
.
Conditional Permissions
In some cases, it is useful to allow (or deny) access to a particular API on a conditional basis, for example based on the IP address of the API client, the IMSI of the subscriber, or even the username of the SAM User.
By setting the condition parameter of a permission statement, an expression will be evaluated in order to determine if the requested API matches the statement, and if so, apply the effect to the request.
Each condition expression may contain a variable, function, placeholder, or static value, and evaluated using comparison or arithmetic operators. Multiple expressions may be combined using logical operators.
Operators
- Comparison operators
eq
or==
- Values must be equal.ne
or!=
- Values must not be equal.lt
or<
- The first value must be less than the second value.le
or<=
- The first value must be less than or equal to the second value.gt
or>
- The first value must be greater than the second value.ge
or>=
- The first value must be greater than or equal to the second value.matches
- The first value must match a regular expression defined in the second value.
- Logical operators
and
- Two expressions must be trueor
- At least one expression must be truenot
or!
- An expression must not be true
- Arithmetic operators
+
- Addition-
- Subtraction*
- Multiplicationdiv
or/
- Divisionmod
or%
- Modulus
Variables
When an API request is made, the details of the API request itself can be used to determine whether a permission should be applied.
- currentDate - The UTC date of the API request, in
yyyyMMdd
format. Use with the date() function."condition": "currentDate >= date(2016,01,27)"
- currentDateTime - The UTC date and time of the API request, in
yyyyMMddHHmmss
format. Use with the dateTime() function."condition": "currentDateTime >= dateTime(2016,01,27,15,00,00)"
- sourceIp - The source IP address of the API request. Can be used with a static string:
"condition": "sourceIp == '10.0.0.1'"
Or with a regular expression using
matches
:"condition": "sourceIp matches '10\.0\.0.*'"
When using the ipAddress() function, sourceIp does not need to be specified in the expression.
- httpMethod - The HTTP method (
GET
,POST
,PUT
, orDELETE
) of the API request. Use with a static string:"condition": "httpMethod == 'GET'"
When using the httpMethod() function, httpMethod does not need to be specified in the expression.
- samUserName - The username of the SAM User used to call the API. Can be used with a static string:
"condition": "samUserName == 'my-user'"
Or combined with a placeholder:
"condition": "samUserName == pathVariable('user_name')"
Functions
In order to simplify common or repetitive conditions, several helper functions are available in order to reduce condition complexity or verbosity. Note that some functions will return a boolean value, while others will return a string value that should be combined with a comparison operator.
- date(yyyy, MM, dd) - Creates a date object that can be used to evaluate against the currentDate variable.
- dateTime(yyyy, MM, dd, HH, mm, ss) - Creates a datetime object that can be used to evaluate against the currentDateTime variable.
- ipAddress(CIDR range, ...) - Returns true if the API client source IP address falls within one of the specified CIDR ranges. Each CIDR should be specified as a string in CIDR notation, such as:
"condition": "ipAddress('10.0.0.1/24')"
Multiple CIDR ranges can be specified using additional parameters, and will return true as long as the API client source IP address falls within at least one of the specified CIDR ranges:
"condition": "ipAddress('10.0.0.1/24', '10.0.0.2/24')"
- httpMethod(method, ...) - Returns true if the HTTP method used for the API request matches one of the specified methods. Each method should be specified as a string, such as:
"condition": "httpMethod('GET')"
Multiple methods can be specified using additional parameters, and will return true as long as the HTTP method used for the API request matches one of the specified methods:
"condition": "httpMethod('GET', 'POST')"
- pathVariable(placeholder) - Returns a string of the API request path specified by the placeholder, which can then be used to evaluate a comparison against a variable or a static string. Refer to the Placeholders section below.
Placeholders
In some cases, you may want to evaluate a conditional expression based on the API path rather than the request itself. As API paths are dynamic and vary based on the target resource (such as the IMSI of a SIM card, or the username of a SAM User), the pathVariable() function can be used to extract a part of the API path in order to evaluate a conditional expression.
Many Soracom APIs will include one or more path variables, with each variable identified by a placeholder name. You can find path variables and placeholder names using the API Reference.
By passing the placeholder name as a string into the pathVariable() function, the string value of that portion of the API request path will be returned to the conditional expression.
For example, the Subscriber:updateSpeedClass API has an API path of /subscribers/{imsi}/update_speed_class
. If a SAM User accesses this API for a SIM card with IMSI 295000012345678
, the API path of the request will be /subscribers/295000012345678/update_speed_class
.
We can use the imsi
placeholder name in order to retrieve the value from the API path:
"condition": "pathVariable('imsi') == '295000012345678'"
The pathVariable() function will extract the imsi
from the API path, and then we can compare it against a static string to determine whether a permission should be applied.
In this example, if a SAM User does not have other permissions, the following inline permission statement:
{
"statements": [
{
"effect": "allow",
"api": "Subscriber:updateSpeedClass",
"condition": "pathVariable('imsi') == '295000012345678'"
}
]
}
will allow the SAM User to update the speed class for the specified SIM card, but not for other SIMs.
In some cases, you may want to evaluate a variable in the API path against a variable in the API request.
For example, the User:updateUserPassword API has an API path of /operators/{operator_id}/users/{user_name}/password
. If a SAM User accesses this API for a SAM User with username my-user
, the API path of the request will be /operators/OP0012345678/users/my-user/password
.
If we want to limit the user's ability to change SAM User passwords to their own account (and deny access to changing other SAM User account passwords), we can check that the user_name
placeholder matches a particular value:
"condition": "pathVariable('user_name') == 'my-user'"
However, the static string 'my-user'
will need to change for every user, and when managing a large number of SAM User accounts, setting a custom permission for each account is tedious.
Instead, we can evaluate against the samUserName variable:
"condition": "pathVariable('user_name') == samUserName"
This will ensure that the SAM User account used to create the API request and the SAM User account that will be modified according to the request match, regardless of the actual username.
We can then simply add the following permission statement:
{
"statements": [
{
"effect": "allow",
"api": "User:updateUserPassword",
"condition": "pathVariable('user_name') == samUserName"
}
]
}
to the Default SAM User Permission configuration, which will then be applied to all SAM User accounts.