Consider accepting credentials from the environment or CLI

Today, my automated deployment failed. Not having changed anything on the CI, I verified that the (old) recommended solution (to deploy a snapcraft.cfg with a macaroon in it) was still in place and the file had the right contents. Not really knowing what to do, I messaged @popey and he confirmed my hunch that macaroons expire.

Now, I did not particularly like having to deploy a config file at build time to begin with, I think this is rather clunky - but it worked. However, the fact that the credentials expire makes this more than a difference in taste.

I’d like to propose accepting credentials either via the command line or the environment. I understand that macaroon tokens are used for increased security in certain situations, but in our case (completely closed CI & environment that we control) they make our jobs way more difficult than it needs to be.

Most other tools that require authentication are able to read it from the environment or the command line (in fact, I would be hard pressed to name one that we use and doesn’t). I wonder what led to the decision not do the same with snapcraft and if there is any chance to change this?

2 Likes

I suspect there wasn’t any active decision to deny usage of the command line or environment. More likely it just didn’t cross the minds of the developers/designers when creating the app so it didn’t get implemented by oversight rather than malice :-).

I definitely wasn’t thinking malice :slight_smile: only that there might have been a deliberate decision on this front. But you raise a good point, maybe just no one thought of it. I hope some of the active developers can chime in.

1 Like

I knew we wrote documentation for this somewhere, it turns out it was on the Travis CI docs.

The gist of it is:

# export credentials to stdout (-) for <snap-name> allowiing releases to edge.
snapcraft export-login --snap <snap-name> --channels edge -

Put that in an envvar and then:

echo "$SNAPCRAFT_SECRET" | snacraft login --with -

@degville I am certain this lives in our docs somewhere, may it be that it is not indexed?

@sergiusens unfortunately that also exports a macaroon token (which will also expire, if I’m not mistaken).

or wait, that actually assumes that I’m logged in or otherwise able to interactively enter the credentials. Not the case during a CI build.

I think @sergiusens meant for you to run snapcraft export-login from your desktop. The idea is you login locally, then run export-login and save that value into a secret in your CI system. Once you have the secret saved you run in your CI builds echo "$SECRET_VARIABLE_NAME" | snapcraft login --with - or maybe snapcraft login --with "$SECRET_VARIABLE_NAME"… however, this exported credential will still expire after a year from saving IIRC.

I see. Yeah, that will still expire.

FWIW, I tried to use expect to enter the credentials, but that doesn’t seem to work due to snapcraft using the getpass module (I assume). But there is a pexpect module which does the job. For anyone finding this in the future (if there is still no good way to provide the credentials):

import pexpect

token_filename = "login.token"
if os.path.exists(token_filename):
  os.remove(token_filename) # it fails if this exists already

with pexpect.spawn(f"snapcraft export-login {token_filename}") as snapcraft:
  snapcraft.expect("Email:")
  snapcraft.sendline(username)
  snapcraft.expect("Password:")
  snapcraft.sendline(password)
  snapcraft.wait()

After this, there is login.token that I can use and discard. No more expiry.