Exoscale offers multiple ways to interact with the platform in a programmatic way, from either a command line, your favorite programming language, or some of our integrations to 3rd party tools.

To do so you have first to create a Role and then generate one or more API keys and secrets to be used in such tools.

This is a quick start guide. For more in-depth knowledge of IAM, please refer to the API Keys, Roles and Policies article

First time setup

The goal is to have the necessary resources to use IAM outside of the portal too.

  1. Navigate to IAM, then ROLES, and add a new Role.
  2. In the Role creation form: name your new Role example-api-role and leave other settings as default - make sure “Default service strategy” is ALLOW and “Service Classes” is empty. This will create a role with no restrictions.
  3. Navigate to IAM, then KEYS, and add a new API Key.
  4. In the Key creation form: name your key example-api-key and select the Role from the previous step (example-api-role).
  5. Once created, the API key id API Key and secret API Secret are displayed. The secret is displayed only once. We will need both for the next step.
  6. This documentation shows you how to configure the CLI with the API key you just created. If you haven’t installed the CLI yet, you can refer to the Installation section

Creating Roles and generating API keys

You can create a Role and API keys from the Portal or the CLI.

Every role defines a policy in charge of authorization. API keys are attached to a role, they are responsible for authentication.

Creating a new API key

exo iam api-key create second-api-key example-api-role

Because we specified the same role from the first time setup, this will create another key with unrestricted use of all API operations - identical to the one we created previously.

For most use cases however, we recommend that you create a restricted Role that can only be used for certain operations.

Creating a new Role

cat policy.json | exo iam role create example-restricted-role --editable --policy -

policy.json defines the role’s policy.

For example, here’s a policy that allows IAM operations, allows DNS operations, but denies anything else:

{
  "default-service-strategy": "deny",
  "services": {
    "dns": {
      "type": "allow"
    },
    "iam": {
      "type": "allow"
    }
  }
}

"default-service-strategy": "deny" rejects any request that doesn’t satisfy the conditions under "services".

"services" are high level classification of operations used to split the authorization flow. Possible keys inside "services" are: compute, iam, dns, dbaas, sos, block-storage, and compute-legacy.

You can find more information about which operations/endpoint belong to which service with the help of this reference.

Role management

To fetch a role with the CLI

exo iam role show my-role
┼─────────────┼──────────────────────────────────────┼
│ ID          │ f37adf2f-1c95-4866-8d73-baadeb3e18a0 │
│ Name        │ my-role                              │
│ Description │                                      │
│ Editable    │ true                                 │
│ Labels      │ n/a                                  │
│ Permissions │ n/a                                  │
┼─────────────┼──────────────────────────────────────┼

To see it’s policy, add the --policy flag

exo iam role show my-role --policy
┼─────────┼────────────────────────────────┼─────────────┼────────────────────────────────────────────────┼
│ SERVICE │ TYPE (DEFAULT STRATEGY "DENY") │ RULE ACTION │                RULE EXPRESSION                 │
┼─────────┼────────────────────────────────┼─────────────┼────────────────────────────────────────────────┼
│ compute │ rules                          │ deny        │ resources.sks_cluster.name == 'my-sks-cluster' │
│         │                                │ allow       │ true                                           │
│ dns     │ allow                          │             │                                                │
┼─────────┼────────────────────────────────┼─────────────┼────────────────────────────────────────────────┼

To see the policy in JSON format, add the --output-format json flag

exo iam role my-role --policy --output-format json | jq .
{
  "default-service-strategy": "deny",
  "services": {
    "compute": {
      "type": "rules",
      "rules": [
        {
          "action": "deny",
          "expression": "resources.sks_cluster.name == 'my-sks-cluster'"
        },
        {
          "action": "allow",
          "expression": "true"
        }
      ]
    },
    "dns": {
      "type": "allow"
    }
  }
}

Reusing an existing Role

If you want to copy or slightly modify an existing policy for a new role, you can get the policy directly:

exo iam role show --policy --output-format json example-restricted-role > role-policy.json

Then

cat role-policy.json | exo iam role create example-restricted-role-copy --policy -

Updating a role

exo iam role update example-role --description "hello world"

Note

The Role policy can only be updated if the role is Editable (default true). This parameter can’t be updated.

cat role-policy-v2.json | exo iam role update example-restricted-role --policy -

Deleting a role

exo iam role delete example-role

API Key management

API Keys can’t be updated or reassigned to another role. One can only create/list/delete them.

exo iam delete api-key EXO1234567890

Note that you should rather use the key’s ID EXO… instead of its name when deleting.

Migrating Legacy Access Keys to Role + API Key

If you have been using our services for a while, you might have noticed old keys being labeled Legacy on the platform, known as Access Keys.

It is currently not possible to migrate Access Keys, but you can reproduce an existing Access Key’s behavior by creating a Role with a specific policy.

Unrestricted Access Keys

This is the simple scenario: create a Role with default settings and API Keys to go along with it.

Restricted Access Keys

Start by getting the Access Key’s Operations.

exo iam access-key show EXO...
┼────────────────┼──────────────────────────────────────────────────┼
│ IAM ACCESS KEY │                                                  │
┼────────────────┼──────────────────────────────────────────────────┼
│ Name           │ my-legacy-access-key                             │
│ Type           │ restricted                                       │
│ API Key        │ EXOXXXXXXXXXXXXXXXXXXXXXXXX                      │
│ API Secret     │ *******************************************      │
│ Operations     │ create-load-balancer                             │
│                │ delete-load-balancer                             │
|                | list-dns-domain-records                          |
┼────────────────┼──────────────────────────────────────────────────┼

Create an initial "default-service-strategy": "deny" policy

{
  "default-service-strategy": "deny",
  "services": {

  }
}

Classify operations by their service class by referring to this document. Eg. create-load-balancer belongs to compute, and list-dns-domain-records belongs to dns.

For each service class, create a key in the policy under "services", then populate it as such:

{
  "default-service-strategy": "deny",
  "services": {
    "compute": {"type": "rules",
                "rules": [{"action": "allow"
                            "expression": "operation in ['create-load-balancer', 'delete-load-balancer']"}]},
    "dns":     {"type": "rules",
                "rules": [{"action": "allow"
                            "expression": "operation in ['list-dns-domain-records']"}]}
  }
}

Pass the finished policy to the CLI through STDIN.

cat policy.json | exo iam role create migrated-access-key-role --policy -

Finally, create an API Key referencing the role

exo iam api-key create migrated-my-legacy-access-key migrated-access-key-role