Search Unity

Managing credentials at Unity

February 3, 2020 in Technology | 5 min. read
Share

Is this article helpful for you?

Thank you for your feedback!

As part of our Secure Software Development Life Cycle (SSDLC) at Unity, we’d like to share our credential management strategy. Managing tokens, keys, and credentials in code, otherwise known as secrets, can be a daunting process. By sharing these details, we hope others will benefit and learn from our journey.

A couple of years ago, the Unity Security team, along with our partners in the infrastructure teams, set their sights on tackling the problem of managing credentials. In a large, diverse environment such as Unity, projects can be written in one of many programming languages, developed in several different environments, and deployed through a number of continuous integration toolchains. This makes managing credentials an even more challenging task. In this blog post, we’re sharing our journey as well as open-sourcing our solution so others may follow suit.

What are credentials, anyway?

So, we need to manage credentials. But what are they? A credential, also known as a secret, is any piece of information required by your service to perform a privileged operation on a resource or another service. This can be a token for an API, a password to log in to some service, an SSH private key for connecting to an external server, a set of credentials for writing to a storage bucket, or an RSA key for signing binaries. Regardless of its type, the information needs to be carefully guarded and known only to the parties involved in the transaction that uses it. Ideally, not even the developers working on the service should know it, or at the very least, they should not have constant access to this information.

The two goals of any solid credential management strategy are to ensure that credentials don’t fall into the hands of malicious actors, and deal with credentials in a way that doesn’t create unnecessary complications for developers. However, that’s easier said than done.

Problems with credential management

When establishing a credential management strategy, the team should anticipate a few common problems:

  • Credentials in code: The most straightforward and, unfortunately, the most common method for storing and handling credentials is to write the credential directly into the code file as a variable to be used where it’s needed. A good credential management solution needs to offer an alternative to the convenience of writing credential in code.
  • Credential rotation: Credentials expire, get accidentally deactivated, or need to be rotated for any number of reasons. A good credential management solution should allow for the easy rotation of credentials.
  • Diverse development environments: Since we’re dealing with many different programming languages, a credential management solution shouldn’t be tied to a specific programming language or a development environment. It needs to support the largest possible number of developers and projects.
  • Access control: People leave and join teams, new projects begin, and credentials are always being added. A proper solution must tightly control access to the credentials while also coping with the fluidity of the development environment.
  • Human error: A solution should be designed to minimize human error, both on the user side and the administrator side. For example, the configuration syntax should be expressive and explicit, and destructive commands should introduce a minor level of friction to minimize the likelihood of unintended changes.
  • The Matryoshka doll (Russian nesting doll) problem: This is perhaps the most crucial point. To securely store a credential, it should be locked securely – only the service requiring the credential should have access to the key that unlocks it. Now the question is: How do we ensure that this key is safe? Well, we treat it as a credential and lock it securely. And now, how do we protect that key? You can probably see where this is going – a Russian doll of credentials protecting credentials.

Vault

After careful deliberation, we’ve opted to use HashiCorp’s Vault. This credential management solution allowed us to address most of the problems we had in our sights. What’s more, a version of it is available as an open source solution.

Vault provided us with a solution for securely storing the credentials, tightly controlling access to them, and allowing users to retrieve them. Unfortunately, developers still had to manually integrate the Vault libraries into their projects in order to retrieve and use the credentials. Crucially, Vault still doesn’t address the nesting Russian doll problem. Yes, now we have a safe, secure place for storing the credentials, but accessing them still requires a token. This puts us in a much better position, but it pushes the problem one more level nonetheless.

Enter Vault Secret Fetcher

To address the remaining issues, we looked into a few existing tools, but they didn’t match all of our requirements, especially when it came to user-friendliness. This is why we created Vault Secret Fetcher (VSF). VSF works by arranging the authentication through GKE/Kubernetes or Google Compute Engine to push the nesting Russian doll problem one level further away from the code while leaving the initial authentication to the orchestration or underlying infrastructure platform. This behavior can be easily modified to support any other infrastructure since Vault supports a wide array of authentication mechanisms.

All the developer has to do is to write the secret to Vault.

vault write secret/<YOUR PATH> token="..."

And then assign the path placeholder in their service’s environment.

TOKEN = ‘VAULTSECRET::{"path":"secret/sre/dev/TEST", "key":"token"}’

The credential-fetching flow looks like this:

  1. The service boots up by first calling VSF.
  2. VSF authenticates through the authentication provider (e.g. Kubernetes).
  3. VSF reads the configured paths, acquires the credentials from Vault, and populates its own environment with the credential values.
  4. VSF calls the service’s entrypoint and replaces its own memory space with the service, thereby giving the service access to the credentials.

Find more detailed information about the process in the project’s README.

Next steps

Since we’re releasing Vault Secret Fetcher as an open source project, we’re inviting you to check it out and consider how it could help you with your projects. We also welcome your contributions.

In the future, we’ll be looking for ways to make Vault Secret Fetcher even more portable and allow it to support more platforms and use cases.

February 3, 2020 in Technology | 5 min. read

Is this article helpful for you?

Thank you for your feedback!