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:

curl --data-urlencode 'grant_type=urn:ibm:params:oauth:grant-type:apikey' \
     --data-urlencode 'apikey=<...>' \
     'https://iam.cloud.ibm.com/identity/token' 

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:

curl -H 'IBM-Cloud-Tenant: <account1>,<account2>,<enterprise1>'
     --data-urlencode 'grant_type=urn:ibm:params:oauth:grant-type:apikey' \
     --data-urlencode 'apikey=<...>' \
     'https://iam.cloud.ibm.com/identity/token' 

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):

curl -u '<clientid>:<clientsecret>' \
     --data-urlencode 'grant_type=refresh_token' \
     --data-urlencode 'refresh_token=<...>' \
     --data-urlencode 'account=<new account>' \
     'https://iam.cloud.ibm.com/identity/token' 

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):

curl -u '<clientid>:<clientsecret>' \
     -H 'IBM-Cloud-Tenant: <account1>,<account2>,<enterprise1>' \
     --data-urlencode 'grant_type=refresh_token' \
     --data-urlencode 'refresh_token=<...>' \
     --data-urlencode 'account=<new account>' \
     'https://iam.cloud.ibm.com/identity/token' 

If <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.

Console

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.

API

When you do API calls, you might get the following error response during token creation:

403 Forbidden
{
  "errorCode": "BXNIM0523E",
  "errorMessage": "Account id or enterprise id not found in matching ibm-cloud-tenant allow list.",
  "context": {
    ...
}

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.

Testing

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:

http_proxy=http://127.0.0.1:8080
https_proxy=http://127.0.0.1:8080

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:

ibmcloud login --sso --skip-ssl-validation

Console

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.

API

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: 

-H "IBM-Cloud-Tenant: <comma separated list of accountids>"

For example, if using this parameter with a valid API key in one of the specified accounts, the call execution will work as expected:

curl --data-urlencode "grant_type=urn:ibm:params:oauth:grant-type:apikey" \
     --data-urlencode "apikey=${APIKEY}" \
     -H "IBM-Cloud-Tenant: ${ACCOUNTID}" \
     https://iam.cloud.ibm.com/identity/token

200 OK
{
  "access_token": "...",
  "refresh_token": "not_supported",
  "ims_user_id": ...,
  "token_type": "Bearer",
  "expires_in": 3600,
  "expiration": 1651825368,
  "scope": "ibm openid"
}

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:

curl --data-urlencode "grant_type=urn:ibm:params:oauth:grant-type:apikey" \
     --data-urlencode "apikey=${APIKEY}" \
     -H "IBM-Cloud-Tenant: ${ACCOUNTID}" \
     https://iam.cloud.ibm.com/identity/token

403 Forbidden
{
  "errorCode": "BXNIM0523E",
  "errorMessage": "Account id or enterprise id not found in matching ibm-cloud-tenant allow list.",
  "context": {
    ...
}

Learn more

Categories

More from Cloud

IBM Tech Now: October 2, 2023

< 1 min read - ​Welcome IBM Tech Now, our video web series featuring the latest and greatest news and announcements in the world of technology. Make sure you subscribe to our YouTube channel to be notified every time a new IBM Tech Now video is published. IBM Tech Now: Episode 86 On this episode, we're covering the following topics: AI on IBM Z IBM Maximo Application Suite 8.11 IBM NS1 Connect Stay plugged in You can check out the IBM Blog Announcements for a…

IBM Cloud inactive identities: Ideas for automated processing

4 min read - Regular cleanup is part of all account administration and security best practices, not just for cloud environments. In our blog post on identifying inactive identities, we looked at the APIs offered by IBM Cloud Identity and Access Management (IAM) and how to utilize them to obtain details on IAM identities and API keys. Some readers provided feedback and asked on how to proceed and act on identified inactive identities. In response, we are going lay out possible steps to take.…

IBM Cloud VMware as a Service introduces multitenant as a new, cost-efficient consumption model

4 min read - Businesses often struggle with ongoing operational needs like monitoring, patching and maintenance of their VMware infrastructure or the added concerns over capacity management. At the same time, cost efficiency and control are very important. Not all workloads have identical needs and different business applications have variable requirements. For example, production applications and regulated workloads may require strong isolation, but development/testing, training environments, disaster recovery sites or other applications may have lower availability requirements or they can be ephemeral in nature,…

IBM accelerates enterprise AI for clients with new capabilities on IBM Z

5 min read - Today, we are excited to unveil a new suite of AI offerings for IBM Z that are designed to help clients improve business outcomes by speeding the implementation of enterprise AI on IBM Z across a wide variety of use cases and industries. We are bringing artificial intelligence (AI) to emerging use cases that our clients (like Swiss insurance provider La Mobilière) have begun exploring, such as enhancing the accuracy of insurance policy recommendations, increasing the accuracy and timeliness of…