Mohammed Naser | c0ba666 | 2025-01-29 16:39:41 -0500 | [diff] [blame] | 1 | ############## |
| 2 | Authentication |
| 3 | ############## |
| 4 | |
| 5 | ******************************************* |
| 6 | Using external token from identity provider |
| 7 | ******************************************* |
| 8 | |
| 9 | Since OpenStack is configured to trust Keycloak as an identity provider, you will |
| 10 | need to generate a token from Keycloak and use it to authenticate with the OpenStack |
| 11 | API. |
| 12 | |
| 13 | If you are using Keycloak with an OpenID Connect (OIDC) identity provider, you |
| 14 | may want to exchange a token generated from your identity provider for a token |
| 15 | from Keycloak, which can then be used to authenticate with the OpenStack API. |
| 16 | |
| 17 | .. mermaid:: |
| 18 | :align: center |
| 19 | :config: {"theme": "dark"} |
| 20 | |
| 21 | sequenceDiagram |
| 22 | participant Client |
| 23 | participant OIDC Provider |
| 24 | participant Keycloak |
| 25 | participant Keystone |
| 26 | participant OpenStack |
| 27 | |
| 28 | Client->>OIDC Provider: Request Token (Client Credentials) |
| 29 | OIDC Provider-->>Client: Returns OIDC Token |
| 30 | |
| 31 | Client->>Keycloak: Exchange OIDC Token |
| 32 | Keycloak-->>Client: Returns Keycloak OIDC Token |
| 33 | |
| 34 | Client->>Keystone: Authenticate with Keycloak Token |
| 35 | Keystone-->>Client: Returns Keystone Token |
| 36 | |
| 37 | Client->>OpenStack: Use Keystone Token |
| 38 | OpenStack-->>Client: OpenStack API Access Granted |
| 39 | |
| 40 | In order to get started with this process, you'll need a OpenID connect token |
| 41 | issued by an identity provider which exists in the Keycloak realm. |
| 42 | |
| 43 | 1. **Exchange the OpenID connect (OIDC) Token with Keycloak** |
| 44 | |
| 45 | Use the *OpenID connect token* from your identity provider and exchange it for |
| 46 | a *Keycloak-issued token*. The following ``curl`` command is provided as an |
| 47 | example but you can use any tool that can make HTTP requests. |
| 48 | |
| 49 | You will need to replace the following placeholders in the example code: |
| 50 | |
| 51 | - ``<KEYCLOAK_URL>``: The URL of your Keycloak instance. |
| 52 | - ``<KEYCLOAK_CLIENT_ID>``: The client ID of the Keycloak client. |
| 53 | - ``<KEYCLOAK_CLIENT_SECRET>``: The client secret of the Keycloak client. |
| 54 | |
| 55 | .. code-block:: sh |
| 56 | |
| 57 | curl -X POST "https://<KEYCLOAK_URL>/realms/atmosphere/protocol/openid-connect/token" \ |
| 58 | -H "Content-Type: application/x-www-form-urlencoded" \ |
| 59 | -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ |
| 60 | -d "client_id=<KEYCLOAK_CLIENT_ID>" \ |
| 61 | -d "client_secret=<KEYCLOAK_CLIENT_SECRET>" \ |
| 62 | -d "subject_token=<OIDC_TOKEN>" \ |
| 63 | -d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" |
| 64 | |
| 65 | The response will return a token that is issued by Keycloak which you can use |
| 66 | to authenticate with the OpenStack API. |
| 67 | |
| 68 | .. code-block:: json |
| 69 | |
| 70 | { |
| 71 | "access_token" : ".....", |
| 72 | "refresh_token" : ".....", |
| 73 | "expires_in" : "...." |
| 74 | } |
| 75 | |
| 76 | |
| 77 | 2. **Authenticate with Keystone Using the Keycloak Token** |
| 78 | |
| 79 | With the token issued by Keycloak, you can now authenticate with Keystone in order |
| 80 | to obtain a fernet token which can be used to talk to all of the OpenStack APIs. |
| 81 | |
| 82 | You will need to replace the following placeholders in the example code: |
| 83 | |
| 84 | - ``<OPENSTACK_AUTH_URL>``: The URL of your Keystone authentication endpoint. |
| 85 | - ``<KEYCLOAK_OIDC_TOKEN>``: The token issued by Keycloak. |
| 86 | |
| 87 | .. code-block:: sh |
| 88 | |
| 89 | curl "<OPENSTACK_AUTH_URL>/v3/OS-FEDERATION/identity_providers/atmosphere/protocols/openid/auth" \ |
| 90 | -H "Authorization: Bearer <KEYCLOAK_OIDC_TOKEN>" |
| 91 | |
| 92 | This response will return an unscoped Keystone token (not tied to any project) which |
| 93 | will be in the ``X-Subject-Token`` header. |
| 94 | |
| 95 | .. code-block:: http |
| 96 | |
| 97 | HTTP/1.1 201 Created |
| 98 | X-Subject-Token: <UNSCOPED_KEYSTONE_TOKEN> |
| 99 | |
| 100 | 3. **List projects using the Keystone Token** (optional, if you already know the project ID) |
| 101 | |
| 102 | At this point, you have an unscoped token issued by Keystone which is not bound |
| 103 | to any project. You will need to exchange that token for a project-scoped token |
| 104 | in order to be able to interact with the OpenStack APIs. |
| 105 | |
| 106 | You can choose to list what projects you have access to using the Keystone token |
| 107 | that you have obtained. |
| 108 | |
| 109 | You will need to replace the following placeholders in the example code: |
| 110 | |
| 111 | - ``<OPENSTACK_AUTH_URL>``: The URL of your Keystone authentication endpoint. |
| 112 | - ``<UNSCOPED_KEYSTONE_TOKEN>``: The token issued by Keystone. |
| 113 | |
| 114 | .. code-block:: sh |
| 115 | |
| 116 | curl "<OPENSTACK_AUTH_URL>/v3/projects" \ |
| 117 | -H "X-Auth-Token: <UNSCOPED_KEYSTONE_TOKEN>" |
| 118 | |
| 119 | This response will return a list of projects that you have access to. |
| 120 | |
| 121 | .. code-block:: json |
| 122 | |
| 123 | { |
| 124 | "projects": [ |
| 125 | { |
| 126 | "id": "....", |
| 127 | "name": "....", |
| 128 | "description": "...." |
| 129 | } |
| 130 | ] |
| 131 | } |
| 132 | |
| 133 | 4. **Exchange the unscoped token for a project-scoped token** |
| 134 | |
| 135 | Once you have identified the project that you want to interact with, you can |
| 136 | exchange the unscoped token for a project-scoped token. |
| 137 | |
| 138 | You will need to replace the following placeholders in the example code: |
| 139 | |
| 140 | - ``<OPENSTACK_AUTH_URL>``: The URL of your Keystone authentication endpoint. |
| 141 | - ``<UNSCOPED_KEYSTONE_TOKEN>``: The token issued by Keystone. |
| 142 | - ``<PROJECT_ID>``: The ID of the project that you want to interact with. |
| 143 | |
| 144 | .. code-block:: sh |
| 145 | |
| 146 | curl "<OPENSTACK_AUTH_URL>/v3/auth/projects" \ |
| 147 | -H "Content-Type: application/json" \ |
| 148 | -H "X-Auth-Token: <UNSCOPED_KEYSTONE_TOKEN>" \ |
| 149 | -d '{ |
| 150 | "auth": { |
| 151 | "identity": { |
| 152 | "methods": ["token"], |
| 153 | "token": { |
| 154 | "id": "<UNSCOPED_KEYSTONE_TOKEN>" |
| 155 | } |
| 156 | }, |
| 157 | "scope": { |
| 158 | "project": { |
| 159 | "id": "<PROJECT_ID>" |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | }' |
| 164 | |
| 165 | This response will return a project-scoped token which you can use to interact |
| 166 | with the OpenStack APIs which will be in the ``X-Subject-Token`` header. |
| 167 | |
| 168 | .. code-block:: http |
| 169 | |
| 170 | HTTP/1.1 201 Created |
| 171 | X-Subject-Token: <SCOPED_KEYSTONE_TOKEN> |
| 172 | |
| 173 | OpenStack Keystone will provide the token details in the response body, including |
| 174 | the full catalog of services that you have access to. |
| 175 | |
| 176 | .. code-block:: json |
| 177 | |
| 178 | { |
| 179 | "token": { |
| 180 | "methods": [ |
| 181 | "token" |
| 182 | ], |
| 183 | "expires_at": "....", |
| 184 | "issued_at": "....", |
| 185 | "user": { |
| 186 | "domain": { |
| 187 | "id": "....", |
| 188 | "name": "...." |
| 189 | }, |
| 190 | "id": "....", |
| 191 | "name": "...." |
| 192 | }, |
| 193 | "audit_ids": [ |
| 194 | "...." |
| 195 | ], |
| 196 | "catalog": [ |
| 197 | { |
| 198 | "endpoints": [ |
| 199 | { |
| 200 | "id": "....", |
| 201 | "interface": "....", |
| 202 | "region": "....", |
| 203 | "url": "...." |
| 204 | } |
| 205 | ], |
| 206 | "id": "....", |
| 207 | "name": "....", |
| 208 | "type": "...." |
| 209 | } |
| 210 | ], |
| 211 | "project": { |
| 212 | "domain": { |
| 213 | "id": "....", |
| 214 | "name": "...." |
| 215 | }, |
| 216 | "id": "....", |
| 217 | "name": "...." |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | You can then use the project-scoped token to interact with the OpenStack APIs, |
| 223 | such as creating a server, listing servers, etc. |