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.