github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/website/source/docs/acl/acl-migrate-tokens.html.md (about) 1 --- 2 layout: "docs" 3 page_title: "ACL Token Migration" 4 sidebar_current: "docs-acl-migrate-tokens" 5 description: |- 6 Consul 1.4.0 introduces a new ACL system with improvements for the security and 7 management of ACL tokens and policies. This guide documents how to upgrade 8 existing (now called "legacy") tokens after upgrading to 1.4.0. 9 --- 10 11 # ACL Token Migration 12 13 Consul 1.4.0 introduces a new ACL system with improvements for the security and 14 management of ACL tokens and policies. This guide documents how to upgrade 15 existing (now called "legacy") tokens after upgrading to 1.4.0. 16 17 Since the policy syntax changed to be more precise and flexible to manage, it's 18 necessary to manually translate old tokens into new ones to take advantage of 19 the new ACL system features. Tooling is provided to help automate this and this 20 guide describes the overall process. 21 22 ~> **Note**: Before starting the token migration process all Consul agents, servers 23 and clients, must be running at least version 1.4.0. Additionally, you 24 must ensure the cluster is in a healthy state including a functioning leader. Once 25 the leader has determined that all servers in the cluster are capable of using the 26 new ACL system, the leader will transition itself. Then, the other servers will 27 transition themselves to the new system, followed by the client agents. You can 28 use `consul info` to investigate the cluster health. 29 30 Consul 1.4.0 retains full support for "legacy" ACL tokens so upgrades 31 from Consul 1.3.0 are safe. Existing tokens will continue to work in the same 32 way for at least two "major" releases (1.5.x, 1.6.x, etc; note HashiCorp does 33 not use SemVer for our products). 34 35 This document will briefly describes the [high-level migration process](#migration-process) and provides some [specific examples](#migration-examples) of migration strategies. 36 37 ## Migration Process 38 39 While "legacy" tokens will continue to work for several major releases, it's 40 advisable to plan on migrating existing tokens as soon as is convenient. 41 Migrating also enables using the new policy management improvements, stricter 42 policy syntax rules and other features of the new system without 43 re-issuing all the secrets in use. 44 45 The high-level process for migrating a legacy token is as follows: 46 47 1. Create a new policy or policies that grant the required access 48 2. Update the existing token to use those policies 49 50 ### Prerequisites 51 52 This process assumes that the 1.4.0 upgrade is complete including all legacy 53 ACLs having their accessor IDs populated. This might take up to several minutes 54 after the servers upgrade in the primary datacenter. You can tell if this is the 55 case by using `consul acl token list` and checking that no tokens exist with a 56 blank `AccessorID`. 57 58 In addition, it is assumed that all clients that might _create_ ACL tokens (e.g. 59 Vault's Consul secrets engine) have been updated to use the [new ACL 60 APIs](/docs/guides/acl-migrate-tokens.html#api-separation). 61 62 Specifically if you are using Vault's Consul secrets engine you need to be 63 running Vault 1.0.0 or higher, _and_ you must update all roles defined in Vault 64 to specify a list of policy names rather than an inline policy (which causes 65 Vault to use the legacy API). 66 67 ~> **Note:** if you have systems still creating "legacy" tokens with the old 68 APIs, the migration steps below will still work, however you'll have to keep 69 re-running them until nothing is creating legacy tokens to ensure all tokens are 70 migrated. 71 72 ### Creating Policies 73 74 There are a range of different strategies for creating new policies from existing 75 tokens. Two high-level strategies are described here although others or a 76 mixture of these may be most appropriate depending on the ACL tokens you already 77 have. 78 79 #### Strategy 1: Simple Policy Mapping 80 81 The simplest and most automatic strategy is to create one new policy for every 82 existing token. This is easy to automate, but may result in a lot of policies 83 with exactly the same rules and with non-human-readable names which will make 84 managing policies harder. This approach can be accomplished using the [`consul 85 acl policy create`](/docs/commands/acl/acl-policy.html#create) command with 86 `-from-token` option. 87 88 | Pros | Cons | 89 | ---- | ---- | 90 | ✅ Simple | ❌ May leave many duplicated policies | 91 | ✅ Easy to automate | ❌ Policy names not human-readable | 92 93 A detailed example of using this approach is [given 94 below](#simple-policy-mapping). 95 96 #### Strategy 2: Combining Policies 97 98 This strategy takes a more manual approach to create a more manageable set of 99 policies. There are a spectrum of options for how to do this which tradeoff 100 increasing human involvement for increasing clarity and re-usability of the 101 resulting policies. 102 103 For example you could use hashes of the policy rules to de-duplicate identical 104 token policies automatically, however naming them something meaningful for 105 humans would likely still need manual intervention. 106 107 Toward the other end of the spectrum it might be beneficial for security to 108 translate prefix matches into exact matches. This however requires the operator 109 knowing that clients using the token really doesn't rely on the prefix matching 110 semantics of the old ACL system. 111 112 To assist with this approach, there is a CLI tool and corresponding API that can 113 translate a legacy ACL token's rules into a new ACL policy that is exactly 114 equivalent. See [`consul acl 115 translate-rules`](/docs/commands/acl/acl-translate-rules.html). 116 117 | Pros | Cons | 118 | ---- | ---- | 119 | ✅ Clearer, more manageable policies | ❌ Requires more manual effort | 120 | ✅ Policies can be re-used by new ACL tokens | ❌ May take longer for large or complex existing policy sets | 121 122 A detailed example of using this approach is [given below](#combining-policies). 123 124 ### Updating Existing Tokens 125 126 Once you have created one or more policies that adequately express the rules 127 needed for a legacy token, you can update the token via the CLI or API to use 128 those policies. 129 130 After updating, the token is no longer considered "legacy" and will have all the 131 properties of a new token, however it keeps it's `SecretID` (the secret part of 132 the token used in API calls) so clients already using that token will continue 133 to work. It is assumed that the policies you attach continue to grant the 134 necessary access for existing clients; this is up to the operator to ensure. 135 136 #### Update via API 137 138 Use the [`PUT /v1/acl/token/:AccessorID`](/api/acl/tokens.html#update-a-token) 139 endpoint. Specifically, ensure that the `Rules` field is omitted or empty. Empty 140 `Rules` indicates that this is now treated as a new token. 141 142 #### Update via CLI 143 144 Use the [`consul acl token update`](/docs/commands/acl/acl-token.html#update) 145 command to update the token. Specifically you need to use `-upgrade-legacy` 146 which will ensure that legacy rules are removed as well as the new policies 147 added. 148 149 ## Migration Examples 150 151 Below are two detailed examples of the two high-level strategies for creating 152 polices discussed above. It should be noted these are intended to clarify the 153 concrete steps you might take. **We don't recommend you perform production 154 migrations with ad-hoc terminal commands**. Combining these or something similar 155 into a script might be appropriate. 156 157 ### Simple Policy Mapping 158 159 This strategy uses the CLI to create a new policy for every existing legacy 160 token with exactly equivalent rules. It's easy to automate and clients will see 161 no change in behavior for their tokens, but it does leave you with a lot of 162 potentially identical policies to manage or clean up later. 163 164 #### Create Policies 165 166 You can get the AccessorID of every legacy token from the API. For example, 167 using `curl` and `jq` in bash: 168 169 ```sh 170 $ LEGACY_IDS=$(curl -sH "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ 171 'localhost:8500/v1/acl/tokens' | jq -r '.[] | select (.Legacy) | .AccessorID') 172 $ echo "$LEGACY_IDS" 173 621cbd12-dde7-de06-9be0-e28d067b5b7f 174 65cecc86-eb5b-ced5-92dc-f861cf7636fe 175 ba464aa8-d857-3d26-472c-4d49c3bdae72 176 ``` 177 178 To create a policy for each one we can use something like: 179 180 ```sh 181 for id in $LEGACY_IDS; do \ 182 consul acl policy create -name "migrated-$id" -from-token $id \ 183 -description "Migrated from legacy ACL token"; \ 184 done 185 ``` 186 187 Each policy now has an identical set of rules to the original token. You can 188 inspect these: 189 190 ```sh 191 $ consul acl policy read -name migrated-621cbd12-dde7-de06-9be0-e28d067b5b7f 192 ID: 573d84bd-8b08-3061-e391-d2602e1b4947 193 Name: migrated-621cbd12-dde7-de06-9be0-e28d067b5b7f 194 Description: Migrated from legacy ACL token 195 Datacenters: 196 Rules: 197 service_prefix "" { 198 policy = "write" 199 } 200 ``` 201 202 Notice how the policy here is `service_prefix` and not `service` since the old 203 ACL syntax was an implicit prefix match. This ensures any clients relying on 204 prefix matching behavior will still work. 205 206 #### Update Tokens 207 208 With the policies created as above, we can automatically upgrade all legacy 209 tokens. 210 211 ```sh 212 for id in $LEGACY_IDS; do \ 213 consul acl token update -id $id -policy-name "migrated-$id" -upgrade-legacy; \ 214 done 215 ``` 216 217 The update is now complete, all legacy tokens are now new tokens with identical 218 secrets and enforcement rules. 219 220 ### Combining Policies 221 222 This strategy has more manual elements but results in a cleaner and more 223 manageable set of policies than the fully automatic solutions. Note that this is 224 **just an example** to illustrate a few ways you may choose to merge or 225 manipulate policies. 226 227 #### Find All Unique Policies 228 229 You can get the AccessorID of every legacy token from the API. For example, 230 using `curl` and `jq` in bash: 231 232 ```sh 233 $ LEGACY_IDS=$(curl -sH "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ 234 'localhost:8500/v1/acl/tokens' | jq -r '.[] | select (.Legacy) | .AccessorID') 235 $ echo "$LEGACY_IDS" 236 8b65fdf9-303e-0894-9f87-e71b3273600c 237 d9deb39b-1b30-e100-b9c5-04aba3f593a1 238 f2bce42e-cdcc-848d-28ca-cfd0556a22e3 239 ``` 240 241 Now we want to read the actual policy for each legacy token and de-duplicate 242 them. We can use the `translate-rules` helper sub-command which will read the 243 token's policy and return a new ACL policy that is exactly equivalent. 244 245 ```sh 246 $ for id in $LEGACY_IDS; do \ 247 echo "Policy for $id:" 248 consul acl translate-rules -token-accessor "$id"; \ 249 done 250 Policy for 8b65fdf9-303e-0894-9f87-e71b3273600c: 251 service_prefix "bar" { 252 policy = "write" 253 } 254 Policy for d9deb39b-1b30-e100-b9c5-04aba3f593a1: 255 service_prefix "foo" { 256 policy = "write" 257 } 258 Policy for f2bce42e-cdcc-848d-28ca-cfd0556a22e3: 259 service_prefix "bar" { 260 policy = "write" 261 } 262 ``` 263 264 Notice that two policies are the same and one different. 265 266 We can change the loop above to take a hash of this policy definition to 267 de-duplicate the policies into a set of files locally. This example uses command 268 available on macOS but equivalents for other platforms should be easy to find. 269 270 ```sh 271 $ mkdir policies 272 $ for id in $LEGACY_IDS; do \ 273 # Fetch the equivalent new policy rules based on the legacy token rules 274 NEW_POLICY=$(consul acl translate-rules -token-accessor "$id"); \ 275 # Sha1 hash the rules 276 HASH=$(echo -n "$NEW_POLICY" | shasum | awk '{ print $1 }'); \ 277 # Write rules to a policy file named with the hash to de-duplicated 278 echo "$NEW_POLICY" > policies/$HASH.hcl; \ 279 done 280 $ tree policies 281 policies 282 ├── 024ce11f26f59436c518fb31f0999d1400485c17.hcl 283 └── 501b787c9444fbd62f346ab257eeb27197be2444.hcl 284 ``` 285 286 #### Cleaning Up Policies 287 288 You can now manually inspect and potentially edit these policies. For example we 289 could rename them according to their intended use. In this case we maintain the 290 hash as it will allow us to match tokens to policies later. 291 292 ```sh 293 $ cat policies/024ce11f26f59436c518fb31f0999d1400485c17.hcl 294 service_prefix "bar" { 295 policy = "write" 296 } 297 $ # Add human-readable suffix to the file name so policies end up clearly named 298 $ mv policies/024ce11f26f59436c518fb31f0999d1400485c17.hcl \ 299 policies/024ce11f26f59436c518fb31f0999d1400485c17-bar-service.hcl 300 ``` 301 302 You might also choose to tighten up the rules, for example if you know you never 303 rely on prefix-matching the service name `foo` you might choose to modify the 304 policy to use exact match. 305 306 ```sh 307 $ cat policies/501b787c9444fbd62f346ab257eeb27197be2444.hcl 308 service_prefix "foo" { 309 policy = "write" 310 } 311 $ echo 'service "foo" { policy = "write" }' > policies/501b787c9444fbd62f346ab257eeb27197be2444.hcl 312 $ # Add human-readable suffix to the file name so policies end up clearly named 313 $ mv policies/501b787c9444fbd62f346ab257eeb27197be2444.hcl \ 314 policies/501b787c9444fbd62f346ab257eeb27197be2444-foo-service.hcl 315 ``` 316 317 #### Creating Policies 318 319 We now have a minimal set of policies to create, with human-readable names. We 320 can create each one with something like the following. 321 322 ```sh 323 $ for p in $(ls policies | grep ".hcl"); do \ 324 # Extract the hash part of the file name 325 HASH=$(echo "$p" | cut -d - -f 1); \ 326 # Extract the name suffix without .hcl 327 NAME=$(echo "$p" | cut -d - -f 2- | cut -d . -f 1); \ 328 # Create new policy based on the rules in the file and the name we gave 329 consul acl policy create -name $NAME \ 330 -rules "@policies/$p" \ 331 -description "Migrated from legacy token"; \ 332 done 333 ID: da2a9f9b-4e44-13f8-e308-76ce7a8dcb21 334 Name: bar-service 335 Description: Migrated from legacy token 336 Datacenters: 337 Rules: 338 service_prefix "bar" { 339 policy = "write" 340 } 341 342 ID: 9fbded86-9140-efe4-b661-c8bd07b6c584 343 Name: foo-service 344 Description: Migrated from legacy token 345 Datacenters: 346 Rules: 347 service "foo" { policy = "write" } 348 349 ``` 350 351 #### Upgrading Tokens 352 353 Finally we can map our existing tokens to those policies using the hash in the 354 policy file names. The `-upgrade-legacy` flag removes the token's legacy 355 embedded rules at the same time as associating them with the new policies 356 created from those rules. 357 358 ```sh 359 $ for id in $LEGACY_IDS; do \ 360 NEW_POLICY=$(consul acl translate-rules -token-accessor "$id"); \ 361 HASH=$(echo -n "$NEW_POLICY" | shasum | awk '{ print $1 }'); \ 362 # Lookup the hash->new policy mapping from the policy file names 363 POLICY_FILE=$(ls policies | grep "^$HASH"); \ 364 POLICY_NAME=$(echo "$POLICY_FILE" | cut -d - -f 2- | cut -d . -f 1); \ 365 echo "==> Mapping token $id to policy $POLICY_NAME"; \ 366 consul acl token update -id $id -policy-name $POLICY_NAME -upgrade-legacy; \ 367 done 368 ==> Mapping token 8b65fdf9-303e-0894-9f87-e71b3273600c to policy bar-service 369 Token updated successfully. 370 AccessorID: 8b65fdf9-303e-0894-9f87-e71b3273600c 371 SecretID: 3dbb3981-7654-733a-3475-5ce20fc5a7b9 372 Description: 373 Local: false 374 Create Time: 0001-01-01 00:00:00 +0000 UTC 375 Policies: 376 da2a9f9b-4e44-13f8-e308-76ce7a8dcb21 - bar-service 377 ==> Mapping token d9deb39b-1b30-e100-b9c5-04aba3f593a1 to policy foo-service 378 Token updated successfully. 379 AccessorID: d9deb39b-1b30-e100-b9c5-04aba3f593a1 380 SecretID: 5f54733b-4c76-eb74-8781-3550c20f4969 381 Description: 382 Local: false 383 Create Time: 0001-01-01 00:00:00 +0000 UTC 384 Policies: 385 9fbded86-9140-efe4-b661-c8bd07b6c584 - foo-service 386 ==> Mapping token f2bce42e-cdcc-848d-28ca-cfd0556a22e3 to policy bar-service 387 Token updated successfully. 388 AccessorID: f2bce42e-cdcc-848d-28ca-cfd0556a22e3 389 SecretID: f3aaa3e2-2c6f-cf3c-1e86-454de728e8ab 390 Description: 391 Local: false 392 Create Time: 0001-01-01 00:00:00 +0000 UTC 393 Policies: 394 da2a9f9b-4e44-13f8-e308-76ce7a8dcb21 - bar-service 395 ``` 396 397 At this point all tokens are upgraded and can use new ACL features while 398 retaining the same secret clients are already using.