One of the unique problems you encounter when building a framework to manage internal access is that your framework itself needs sensitive permissions to be able to automate access to things.
Let’s say that we want to automate permissions in GitHub. Using the framework, a user might want to temporarily elevate their access to a repository, so that they can set up some secrets in GitHub Actions.
That’s great (and good on your users for keeping secrets out of their source code) — but it means the framework itself needs permissions which allow roles to be created.
This problem is something we’ve been thinking a lot about as we build Common Fate Cloud. Sure, self-hosting everything is certainly an option, but we think that having a third party (like us) keeping your internal access workflows running helps avoid nasty cascading issues if you have an outage you need to deal with. We want to provide a managed permissions orchestration service with an SLA to boot, but we don’t want to force you to hand over the keys to your kingdom.
We’ve built something that helps to solve this problem, and we call it the Access Provider framework.
Anatomy of an Access Provider
First and foremost, an Access Provider’s main job is to hold the credentials required to automate permissions. Sometimes, these credentials are static secrets like API keys. In the case of access to cloud providers like AWS, GCP, or Azure though, the credentials might also be short-lived session tokens attached to a certain role.
(Also, if you’re interested, we’ve written about how we mitigate secrets being logged in Go)
As I mentioned in the GitHub access example above, we need to have these credentials somewhere in order to automate role assignments, so we’ll give them to the Access Provider.
An Access Provider’s second job is to keep these credentials safe, and not give them to anyone — not even Common Fate. To achieve this, we designed a restrictive API around the Access Provider which has four permitted actions:
When your tireless developer requests access to the GitHub repository, Common Fate uses the
Revoke actions to trigger the Access Provider. The Access Provider then calls GitHub’s API with its credentials to create and remove the role.
Load action is used to determine who has access to which resources, and
Describe runs a health-check on the Access Provider.
This approach means we can treat the internals of an Access Provider as totally opaque — heck, we don’t care if the Access Provider is dialing @ashtom’s mobile phone to provision access — as long as it is successfully provisioned when we ask. Treating the internals as opaque gives us the nice property we’re looking for, in that Common Fate has no knowledge or direct access to sensitive credentials.
The last piece of Access Providers is how they are hosted. Access Providers are packaged as serverless functions and run in your own cloud environment (not Common Fate’s). At the moment, we support running Access Providers in AWS Lambda, but we’re working on support for Azure Functions and Google Cloud Functions too. Using serverless functions for this has frankly been great, as it allows us to use cloud-native IAM permissions to ensure that only Common Fate can trigger the Grant/Revoke/Load/Describe actions. We’ll write more about this soon.
You can take a look at our AWS Lambda Access Provider implementation here.
Access Providers Released
We’ve been working towards having Access Providers since the initial release of Common Fate. Our latest release v0.15 contains the full implementation of the Access Provider framework. From this release onwards, Access Providers will be developed and released independently of our core framework.
If you’d like to learn more about how to set up Access Providers you can get started in our docs.