To prevent data theft, enterprise customers with a strong demand for security want to make sure that their users can only access approved accounts.
In the past, this could be managed by only allowing their employees to connect to certain allow-listed domains and/or IP addresses. This approach works as long as you can distinguish tenant-specific traffic using domains or IP addresses. Using cloud services, this approach often fails, as tenant- or account-specific access cannot be secured on a domain or IP address level. Access to specific IBM Cloud Accounts must be limited using a different, application-level approach. IBM Cloud Identity and Access Management (IAM) is introducing a feature to limit access for tenants based on their numeric enterprise ids and account ids.
How does this feature work?
To limit which accounts a user might select, the customer must add a comma-separated list of enterprise ids and/or account ids as HTTP header called IBM-Cloud-Tenant to requests for IBM Cloud. Whenever an IBM Cloud user wants to switch to an initial or a follow-on account during a login session, IAM will check if that tenant header exists, and if it exists, that the target account is either allow-listed directly as account id or allow-listed indirectly because the account belongs to an allow-listed enterprise id.
Which requests need the HTTP header?
If an IBM Cloud customer wants to invoke an IBM Cloud API, the customer must first create an IAM Token. The typical call using an API key is as follows:
Each API key is connected to an IBM Cloud account; therefore, this call is considered as an account-selecting call.
If the user runs a client that directly calls IBM Cloud IAM from the enterprise network like the IBM Cloud CLI, or a self-written script or an application directly interacts with IBM Cloud IAM, you can add an appropriate tenant header to those requests like in the following enhanced API key token call with the mentioned HTTP header:
Executing this call will only be successful if the account that is connected to the API key is included in the IBM-Cloud-Tenant header — otherwise it will fail with an error (see later).
As a second example, if an IBM Cloud service wants to call IAM to switch the account (e.g., when working in the IBM Cloud Console), the service must execute an OAuth2 refresh-token grant request. During that request, the IBM Cloud service provides the new account id in the parameters (e.g., an account switch without the mentioned HTTP header):
To enforce the right account, if the user runs an application that directly calls IBM Cloud IAM from the enterprise network (like the IBM Cloud CLI) or a self-written script or an application directly interacts with IBM Cloud IAM, those requests need the appropriate tenant header (e.g., like this account switch with the mentioned HTTP header):
<new account> is not known in the list
<account1>,<account2> and is also not part of
<enterprise1>, the request will be refused; otherwise, it succeeds.
How do you add the HTTP header to the requests?
Typically, the enterprise wants to enforce this tenant header in each request to IBM Cloud IAM, so relying on all clients adding the tenant header to their request is dangerous. Individual applications might forget to add that header and unintentionally open security holes. Others might intentionally avoid adding the header and get access to IBM Cloud accounts which do not belong to the tenant:
Therefore, it is much more common to place a transparent HTTPS proxy into the enterprise network that will intercept HTTPS calls and add the required header to each call to IBM Cloud. This will enforce the right behavior for all applications that are directly connecting to IBM Cloud IAM:
What about web-based user interfaces?
As indicated above, the HTTP header that contains the tenant restrictions must reach IBM Cloud IAM. Requests that are originated from your local environment can easily be intercepted, and the HTTP header can be added. What about other applications — like the web-based IBM Cloud Console — that indirectly talk to IAM?:
To support tenant restrictions, the IBM Cloud Console would need to add the required header to its own IAM requests. To solve this scenario, IBM Cloud Console also has added support for the tenant HTTP header (i.e., whenever a request hits IBM Cloud Console, any existing HTTP header named IBM-Cloud-Tenant will be added to any outgoing call). This means that if the enterprise ensures (e.g., via a transparent proxy as described above) that the tenant HTTP header is added to all requests to IBM Cloud, IBM Cloud Console will use that information and also enforce this limitation:
Which URLs should the proxy intercept?
We suggest adding the tenant restriction HTTP header to all requests to cloud.ibm.com and their sub domains. This will include iam.cloud.ibm.com and all region-specific subdomains. It will also cover the IBM Cloud Console and all its dashboards, catalogs, and functionalities.
System behavior in case of a mismatch
This section discusses how an end user will be notified if an action is blocked because of a provided IBM-Cloud-Tenant header.
IBM Cloud CLI
When you log in to the IBM Cloud CLI, you always have to select an account for the subsequent commands. If you specify an API key, for example, the account is already part of the information represented by the API key. Doing a CLI login using username/password or the –sso option will present you with an account selection dialog.
In both cases, if your network is adding the IBM-Cloud-Tenant header, and the account that you selected is not allow-listed in that header, the following error message will occur as part of the authentication or account selection step:
Remote server error. Status code: 403, error code: BXNIM0523E, message: Account id or enterprise id not found in matching ibm-cloud-tenant allow list.
If you log in to the IBM Cloud Console and your network is sending the IBM-Cloud-Tenant header, some of the accounts that you are a member of might be blocked. In that case, you will observe an error dialog like this one:
Please select another account that is not blocked or click on Log out to exit from the IBM Cloud Console.
When you do API calls, you might get the following error response during token creation:
In all of these cases, if you see this error, this means that your enterprise network seems to run a transparent HTTP(S) proxy and injects an IBM-Cloud-Tenant header in which your required account id or enterprise id is missing. If you need to access that account, please contact your network administrator to update the IBM-Cloud-Tenant header to contain the account id that you are required to work with.
This section discusses how you can test the feature without installing a transparent HTTP(S) proxy in your network.
IBM Cloud CLI
To simulate the behavior of a transparent HTTP(S) proxy running on your network, you can install a proxy server on your local system that injects the IBM-Cloud-Tenant header into outgoing HTTPS requests. There are several products available.
For our tests, we have chosen to use the Burb Suite Community Edition and configured the proxy server to inject an IBM-Cloud-Tenant header with an appropriate account id into outgoing requests:
In addition to running this proxy server locally, you also have to indicate to your IBM Cloud CLI to use the proxy server for outgoing traffic. The traffic can be redirected by setting the following environment variables:
The IBM Cloud CLI respects these values and redirects traffic over those proxy endpoints.
To intercept HTTPS traffic, the Burp Suite Community Edition has to create its own certificate, which is not accepted by the IBM Cloud CLI. You can either download the Root CA from the Burp Suite Community Edition and import it into your operating system’s trust store, or simply pass the option —
--skip-ssl-validation — on each invocation of the IBM Cloud CLI. For example:
If you have installed a local HTTP(S) proxy for CLI testing, you can reuse that installation for your browser test, too. The only thing you need to do is to point your browser’s proxy endpoint to
http://127.0.0.1:8080. Potentially, you will have to accept invalid certificates for this test.
Alternatively, each browser that can be extended by plugins will likely have a browser extension that allows you to add a custom HTTP header to your web browser requests. In our tests, we decided to use the ModHeader Chrome Plugin to add arbitrary HTTP headers — we were using the IBM-Cloud-Tenant header with appropriate account ids — to outgoing calls.
In case you have already installed a proxy server like the Burp Suite Community Edition as described above, you can simply reconfigure your browser to use the proxy server at 127.0.0.1 on port 8080 to execute the requests. Again, you have to either import the Root CA from the Burp Suite Community Edition or accept insecure traffic for your test.
On the API, specify a new HTTP header IBM-Cloud-Tenant with the list of permitted account ids. If you are using the command line tool
curl, this would be done with the following parameter:
For example, if using this parameter with a valid API key in one of the specified accounts, the call execution will work as expected:
If the API key is created in an account that is not in the IBM-Cloud-Tenant list, you will get the following error message: