Secrets Management for iOS Apps

Muddsar Iqbal
Tumiya
Published in
5 min readApr 23, 2020
Photo by Samantha Lam on Unsplash

Secrets management is a key challenge in mobile app development. Almost every app uses third party SDKs and APIs, which has explicit keys and secrets to uniquely identify apps. These secrets are considered gatekeepers to your app and if compromised, it can have harmful impact on not only your application, but your overall business. We explored existing solutions to manage the iOS apps secrets and tried to find one that could possibly address all of our requirements. Here are some great strategies shared by some awesome iOS developers

Unfortunately we were unable to find one suitable for our need, so we ended up designing our own strategy using some existing and custom tools. Before we jump to the actual strategy, we need to list down some key requirements which we aim to accomplish.

  • Keep secrets out of Git repository
  • No plain text secret in compiled app
  • Unified strategy for automated pipelines and local development environments
  • Support or scale to N environments (Ideally in automated fashion)
  • Audit logs for all access queries to secrets store
  • Rotation of keys/secrets have no impact on pipelines & local environments
  • Secrets Management for growing cross-functional teams

Strategy

We will be taking a high level peek of the solution to get some good understanding of end-to-end approach. In order to meet the above requirements we were looking for some existing tools which can be used as part of our strategy. We ended up using following tools as part of our solution

  • Cocoapods-Keys
  • HashiCorp Vault
  • In-house custom tool/scripts

Cocoapods-Keys

Cocoapods-keys is a key-value store for iOS secrets. Cocoapods-keys is designed to store keys and tokens securely in each developer’s keychain, and not in the application source code. On build time, Cocoapods-Keys scrambles the secrets then injects them into the application source code. Incase some modifications are required in existing keys, changes are made directly to Podfile in the source code. These changes get reflected on next pod install or update.

HashiCorp Vault

Vault is a cross-platform secrets management engine built and maintained by Hashicorp. Vault can be configured to run in High Availability (HA), and it is backed by a variety of storage engines from Consul to Google Cloud Storage (GCS), many of which can also be configured to run in HA. Our use case of Vault involves the Key/Value (KV) Secrets Engine, Policies, and Tokens. Vault also has audit devices, which are powerful features that enable auditing of all secrets.

Policies : Policies in Vault describe what a user can access. For example defining policy to grant read-only access to devs on certain lower environments and write access to dev lead. Similarly giving production environment access to service accounts & product owners. We use policies to restrict paths for which a user has access. It can span from one project environment to multiple projects and their environments.

KV Secret Engines: Vault has multiple built-in secret engines. Our use case involves the Key/Value (KV) Secrets Engine. The KV Secrets engine works similar to paths and it maps secrets to identifier strings.

Tokens : Users are authenticated by Vault using their unique and individual tokens. Vault tokens are bound to policies. The build machines for each project can also have their own build tokens.

In-house custom tool/scripts

Both tools mentioned above (Vault and Cocoapod-keys) are great but in order to make them compatible with our specific requirements we have to come up with several internal automation tools. These scripts involved steps like authorizing user with cloud service & vault, pulling secrets for environments, passing/updating information to Cocoapods-Keys, triggering pipelines and much more. We used bash to write most of our scripts.

Architecture

Below is the high level diagram of our approach. It gives sneak peek into both pipeline and development environment workflows for secret management.

Diagram by William Yang

We will briefly explain the terminologies in diagram

GCP — Vault : Vault service hosted on google cloud platform

VCB : Custom tool which serve as bridge between vault services and CI/Development environments.

First we will try to understand the workflow for CI Pipeline.

Diagram by William Yang

Steps

  1. CI build machine runs ./vcb with environments secrets & ./vcb fetches vault access token from token issuing service.
  2. ./vcb authenticates with given vault endpoint.
  3. ./vcb reads and retrieves all secrets the CI build token can access.
  4. ./vcb calls Cocoapods-keys.
  5. Cocoapods-keys stores retrieved secrets in macOS system keychain.
  6. Xcode project builds.
  7. Cocoapods-keys retrieves secrets from Keychain.
  8. Cocoapods-Keys make secrets available to Xcode project via Keys framework in scrambled version.

If at any stage the step fails, ./vcb will log an error.

In development environment, As part of step 1, developer is granted access token to specific lower environment for specific project. This token enabled them to run VCB on their machine and complete the whole flow.

VCB

VCB is the core component in this whole architecture which takes care of multiple responsibilities. When a new pipeline is triggered in our internal CI system, it immediately calls our VCB scripts which handles following responsibilities

  1. VCB make a request to our token issuing service which returns a vault access token for current session for current project and vault environment.
  2. VCB connects to the required vault environment (for example Develop, SIT, or UAT) using access token and fetches all secrets from that specific environment.
  3. VCB encrypts those secrets and passes them to the designated pipeline.
  4. In our case we were using Bitrise as external CI/CD service, new pipeline is started in Bitrise and it is passed the encrypted secrets as environment secret variable.
  5. VCB script is triggered before xcodebuild which decrypts the secrets & set them using bundle exec pod keys set KEY VALUE
  6. From this point onward, Cocoapods-Keys take care of the secrets & make sure they are injected in scrambled form as part of build time process. You can check Cocoapods-Keys official documentation to get exact flow how it handles secrets in secure manner.

That was high level overview of our strategy to meet all of our requirements. Availability of good lower environments structure was key for this customized approach, this system assume you have production like lower environments available which can facilitate testing & debugging of iOS builds.

We are still working on some proof of concepts for more advanced usage of this solution and will be sharing the updates in future.

Thanks to Avery Roswell and William Yang who had significant role in design and implementation of this solution.

--

--