Guidance on classic vs auto-connect for Terraform

Hi

I’m going to be maintaining the Terraform snap going forward.

My initial thoughts were that this should be a classic snap - this snap is really simple and just fetches the upstream binaries from the relevant Github release (see snapcraft.yaml). Making this a classic snap would allow users to run the Terraform command from anywhere on their filesystem - by default Terraform creates a hidden directory in the working directory where it stores state, etc.

This feels like a similar use-case to kubectl to me, which is also a classic snap. I’d be happy to make it strict, but would probably need some auto-connected interfaces to give Terraform access to the filesystem to make the experience good.

What’s the best route here?

Thank you!

Jon

If the snap is fetching content from the internet at run/install time, that could be a potential compromise vector, in which case I’d feel safer if it were a confined snap.

“by default Terraform creates a hidden directory in the working directory where it stores state, etc.” - restricting this to either a snap-owned directory or e.g. home (using the home interface) would mitigate the risk, though it might end up feeling alien and constraining to people used to plain Terraform. One thing that could be done is provide a terraform wrapper that warns the user to move their terraform-ed directories to a specific location, explaining the security benefits of doing so.

Bundling a specific version of Terraform in the snap at build time would allow better control and auditing of what’s being shipped in the snap, so it could be an alternative - but since we’re just downloading/packaging an upstream artifact, the compromise vector I mentioned earlier would still be a potential issue. It might be worth looking at existing snaps that use this "just bundle the .jar" pattern to see if they’re typically classic or confined.

These are just some thoughts though, I’m not opposed to anything at this point.

  • Daniel

I would recommend going for a strictly confined snap if possible. This will give better consistency, better forward upgrade path, and reduce any risks of incompatible libraries at runtime.

Access to a hidden directory can be done with a personal-files or system-files interface.

As for loading random binaries either fetched from the web or local filesystem, they would still need to be compatible with the particular version of terraform, which isn’t solved with the classic snap, and conversely, can be done with a strictly confined snap. The terraform snap could also include (if needed) compilation tools to builds its module/plugins inside the snap environment.

The problem is somewhat similar to R, Octave and alike, but there the biggest issue with snapping is that precompiled modules/libs expect hardcoded paths (might be solvable with layouts), and refactoring the existing archive of thousands of mathematical modules to be distributable as snaps.

If you don’t have that restriction, or you’re willing to work around, strict confinement should do the job.

One thing we could think going forward is perhaps a stub “classic” interface, which would allow access to all or most system paths but while still having the snaps confined and all its libs/modules aligned to the base inside the snap (to ensure runtime consistency).

Okay, I’ve had a bit more a play with this (you can see some sketching on Github).

I don’t think there is a nice way to make this play as a strict snap. I initially thought I was on to something by having a plug per hidden directory, and essentially per-provider in Terraform speak - this would have enabled users to very granularly grant permission to different cloud credentials.

However: the problem is that it isn’t actually the terraform binary that reads the credentials in most cases. When the user runs terraform init, what actually happens is that terraform goes out and downloads either specified or the latest version of that provider, which is in fact a binary – it is that binary that tries to read the credentials, but obviously cannot due to the confinement.

The only real route here would be to have a really “fat” snap that contained all of the providers, but that would be very large indeed, and out of date by the time the CI pipeline finished building it! Unless I’m missing something, there is no way to allow access to those things as they are downloaded.

Additionally, there is an almost uncountable number of providers, meaning the list of plugs, and the maintenance burden will become really high. I think therefore that this has really changed into a request for a classic snap!

(I can’t update the title here, but perhaps @sergiusens and/or @alexmurray might be able to have some input here?)

Do credentials need to live outside the snap? You could have these saved inside the snap writable area, but then they would/might differ from the host. You could also potentially use layouts if the providers hard code to paths like /etc.

What you could have is similar to what kde do: slim app snaps and a big kde content snap that has all the common shared stuff. You could have a small terraform snap, plus a content snap with providers, and potentially have a slot/plug mechanism, which would allow people to write their own provider snaps and be able to connect them with terraform.

In theory no, in practice probably. Most of the providers rely upon credentials being put in place by a third party app like the Azure CLI or AWS CLI for example. The providers themselves don’t often include the login/authentication logic.

This is a very big hill to climb, according to the website there are 2033 providers, and that’s just the ones listed on Hashicorp’s site! It feels like it’d end up quite brittle. To make things more complicated, you’d actually probably need to have all the versions of the providers, as individual Terraform setups can pin to a provider version.

I think we will hit this problem over and over with anything that acts as a download/package manager, so we might want to consider a transparent classic-like interface. It would allow “most” of the access to the system and on the fly (arbitrary) execution, but while still allowing some level of confinement.

As for 2033 providers, those are rookie numbers, we need to pump those numbers up!

Yes, I think you’re almost certainly right. I think the way to move this one forward for now is to go classic and I’ll gladly be the crash-test dummy for any such interface? :wink:

Something to discuss in the coming weeks for sure!

So from my basic reading I would assume terraform would fit under the existing category of " kubernetes tools requiring arbitrary authentication agents" from Process for reviewing classic confinement snaps and as such would be a candidate for being granted classic confinement.

Thanks @alexmurray - so are you able to +1 that request here, and is there anyone else needed before I poke the store team? :slight_smile:

I am part of that team :slight_smile: - as such the requirements for classic confinement are understood - I have vetted the publisher and granted classic confinement for terraform, this is now live.

1 Like

Note existing snap users will not be automatically refreshed to the version with classic confinement as this would be a potential unexpected loss of security. As such you will need to notify / prompt existing users to manually upgrade.

Thank you! :rocket: :sunglasses: