What are some ways to prevent someone from accidentally destroying an app?

This is possible with org/deploy tokens, but it’s a bit complicated. Quick overview:

  • Org tokens are limited to managing a single org and its resources
  • Deploy tokens are limited to managing a single app and its resources

From the sounds of it, an org token most suits your needs, but just letting you know it’s possible to do a similar thing with a deploy token if needs be.

First, create an org token. You have to do this interactively at the moment, there’s no way to pass the organization as a flag.

fly tokens create org

Now we’re going to attenuate the token using fly tokens attenuate. This command takes a token to attenuate and a list of caveats to append. If the terminology here is confusing, and you’re curious, have a read of some of the links I’ve left at the bottom.

Take a look at the output of fly tokens debug -t ORG_TOKEN using the org token you’ve just generated. In my case, I see:

[
  {
    "location": "https://api.fly.io/v1",
    "caveats": [
      {
        "type": "Organization",
        "body": {
          "id": 341243,
          "mask": "rwcdC"
        }
      },
      ...
    ]
  },
  ...
]

The relevant part here is the Organization caveat, which has the mask rwcdC corresponding to: read, write, create, delete, control. For a full description of what these mean see this stuff.

The important point here is that this org token has d in the mask, so the owner of this token can destroy resources associated with the org. So we want to add an Organization caveat with the mask rwcC, so that we can still do all the stuff other than deleting.

There was a bit of reading of source code in the macaroon repo to figure out how to create a valid payload for the fly tokens attenuate command, but the result is understandable:

[
  {
    "type": "Organization",
    "body": {
      "id": 341243,
      "mask": "rwcC"
    }
  }
]

The id I’ve just taken from the output of fly tokens debug above. The payload is a list, because the command expects a list of caveats.

So now we can attenuate. FYI: -f is the file to read caveats from. I’m just using bash redirection <() to directly pass a string.

fly tokens attenuate -t "$ORG_TOKEN" -f <(echo '[{"type": "Organization", "body": {"id": 341243, "mask": "rwcC"}}]')

Now if I try to destroy an app:

FLY_API_TOKEN="$ATTENUATED_TOKEN" fly apps destroy APP_WITHIN_THAT_ORG
Destroying an app is not reversible.
? Destroy app APP_WITHIN_THAT_ORG? Yes
Error: Not authorized to destroy this app.

So I guess the idea would be to mint tokens like this for each of your developers and then require that they use them in this way. They could export FLY_API_TOKEN in their .bashrc if they want to avoid always having to type it out as above.

Useful resources for understanding macaroons:

edit: I’ve just added a --org flag to fly tokens create org, so this can be done non-interactively now.

2 Likes