As developers, we often need to use third-party APIs and services in our applications. These usually require an API key for authentication and access control. The security of these API keys is critical – if they are exposed, attackers can gain access to our APIs and cause a lot of damage. So where and how should we store API keys securely?
What are API keys?
API keys are unique identifiers that are issued by service providers to grant access to their APIs. They are similar to usernames and passwords but are typically longer cryptographic strings. Some common examples include:
- AWS Access Keys
- Google Maps API Keys
- Facebook API Keys
- Stripe API Keys
These keys authenticate us and authorize our application to interact with the respective service APIs. They allow the API provider to identify the application, track usage, enforce quotas, etc. API keys carry the same privileges as the user they are issued to. If compromised, they can be used to impersonate valid users and carry out privileged actions.
Why is API key security important?
Some reasons why API key security is crucial include:
- API keys grant privileged access to sensitive data and functionality.
- Exposed API keys can lead to exfiltration and abuse of data.
- Compromised API keys allow attackers to impersonate legitimate users.
- Stolen API keys can result in significant costs through usage charges.
- Poor API key hygiene damages reputation and breaks compliance.
If our API keys fall into the wrong hands, attackers can essentially do everything we can do with those keys. They can access private user data, invoke costly actions, corrupt or delete information, and seriously impact our business. Hence it’s critical that we store and handle API keys securely.
Common API key risks
Some common risks around API keys include:
- Embedding keys in code/configs: Hardcoding keys in source code or configs makes them easy to discover.
- Checking-in secrets: Accidentally committing API keys into source code repositories.
- Exposing keys in logs: Logging API keys that get captured in logs available to many people.
- Transmitting unsafely: Sending keys over insecure channels like email.
- Shared access: Giving collective access to a single API key.
- Lack of rotation: Not rotating keys periodically to reduce exposure.
- Weak access controls: Permissive access to API keys stored in centralized stores.
Developers often unintentionally include API keys in public code and configs. Version control systems like GitHub further amplify exposure. Operational practices like logging exacerbate risks. It’s important to audit our code, systems and processes to identify and eliminate such API key risks.
Best practices for managing API keys
Here are some best practices we should follow to securely manage our API keys:
Tightly control access
Limit access to API keys to only those who absolutely need it. For example, instead of shared production credentials, each engineer could be issued personal keys. Access should be tied to mechanisms like single sign-on to ease revocation.
Apply the principle of least privilege
Issue API keys with minimum required privileges. Many providers allow scoping keys to specific resources or actions. Use service accounts where possible to attach strict permissions.
Encrypt keys at rest
Wherever keys are stored – credential stores, config files, databases – they must be encrypted at rest. Use hardware security modules (HSMs) if available. Decrypt keys only at runtime in memory.
Transmit keys securely
Any transmission of keys over networks should use secure encrypted channels like TLS. Avoid passing keys over email, chat or other plain protocols.
Rotate keys periodically
API keys should be rotated periodically to reduce the impact of any leaks. Some providers allow automatic key rotation. Most have recommended rotation periods (90 days for AWS).
Revoke compromised keys immediately
Have monitoring to detect key misuse and processes to quickly revoke any compromised keys. Most providers provide access to key usage logs and allow rapid revocation.
Use API keys appropriately
Keys should only be used as directed by the API provider. For example, AWS recommends not embedding IAM keys in code.
Analyze access logs
Review API access logs regularly to detect anomalous usage that could indicate compromised keys. Many providers offer alerting on suspicious activity.
Where to store API keys
Now that we’ve looked at risks and best practices, let’s discuss some good places to store API keys securely:
Secret management systems
Dedicated secret management solutions like HashiCorp Vault, AWS Secrets Manager and Azure Key Vault are purpose-built to securely store secrets like API keys.
They provide:
- Encryption at rest and in transit
- Fine-grained access controls
- Audit trails for access
- Rotation and automatic expiry of secrets
- Revocation of compromised secrets
- Integrations with identity providers and KMS
Secrets are accessed at runtime via SDKs or environment variables and never persisted.
Environment variables
Environment variables allow injecting keys into processes only at runtime. Setting them requires privileged access. Don’t check them into source code repos. Be careful with persistent shells that may leak values in bash history.
Configuration files
Keys can be stored in config files that are encrypted at rest. Decrypt them using a KMS at runtime. Minimize access to prevent retrievals. Use short-lived access tokens where feasible.
Credential managers
Tools like AWS Credential Manager, Git Credential Manager allow securely storing keys encrypted on disk and accessing them from associated applications.
Hardware security modules (HSMs)
HSMs are hardware appliances that safeguard and manage digital keys. They provide tamper-resistant storage and secure cryptographic operations. HSMs are expensive but highly secure.
What not to do
Here are some unsafe practices to avoid when handling API keys:
- Committing keys in source code repositories
- Bundling keys within application binaries or Docker images
- Storing keys in plain-text files accessible to many people
- Embedding keys directly in environment variables
- Logging API keys in files that can be accessed
- Transmitting keys over unencrypted connections
- Using shared API keys across multiple services
Tools to help find and remove exposed keys
It’s easy for keys to mistakenly end up in public repositories and binaries. Some tools that can help find and remove exposed keys include:
Tool | Description |
---|---|
GitLeaks | Scans git repos for exposed keys based on regex patterns |
TruffleHog | Checks git history and branches for commit messages and files with secrets |
git-secrets | Prevents committing secrets by scanning for blacklisted patterns |
Gitrob | Searches public GitHub repos for sensitive files and keys |
Dockle | Scans Docker images for exposed secrets |
It’s worth setting up scans with these tools as part of CI/CD pipelines to avoid accidentally leaking any secrets.
Managing API keys in code
For server-side applications storing keys in environment variables is a good option. Frontend JavaScript apps need a different approach since the source code is exposed.
For JavaScript apps, avoid embedding keys directly in code. Instead, use mechanisms like:
- Environment variables – Set keys via process.env at runtime.
- HTTP headers – Pass keys through headers only in server requests.
- External config – Place keys in separate config files loaded at runtime.
You can also proxy API requests through your servers to avoid exposing keys publicly.
Governance considerations
Here are some governance aspects to consider around API keys:
- Have an inventory of all keys across services mapped to owners.
- Classify keys based on sensitivity – eg. test vs production.
- Define a key management policy assigning responsibilities.
- Limit creation of production keys to designated administrators.
- Use access request tickets for issuance and rotation.
- Enforce 2FA for any key access.
- Collect access logs centrally and monitor for anomalies.
- Integrate secret rotation with credential managers.
- Review permissions and prune stale keys periodically.
Formalizing API key management ensures the right controls, visibility and auditing across the organization.
Monitoring for exposed keys
Actively monitor for any keys that may get exposed accidentally.
- Monitor public code repos, container registries, S3 buckets etc. for blacklisted patterns
- Set up alerts for anomalies in API usage metrics
- Integrate secret scanning tools into CI/CD pipelines
- Log and audit all key access centrally
- Subscribe to compromise monitoring services for exposed credentials
Detecting exposed keys quickly limits the damage from any leaks.
What to do if you expose a key
In case a key does get exposed, act swiftly to contain the impact:
- Revoke the compromised key immediately to prevent further abuse.
- Issue a new key as a replacement for broken integrations.
- Identify how the key was exposed – public repo, log files etc.
- Remediate the root cause to prevent repeat incidents.
- Scan usages of the key for any malicious activity.
- Change other keys as a precaution if it was high-privilege.
- Report the incident to your security team.
Responsible disclosure is important if the exposure impacts external services. Most providers have security contact or support channels to report compromised keys.
Conclusion
API keys enable valuable capabilities but also carry substantial risks if mishandled. Some key takeaways around API key security are:
- Minimize access to keys and securely transmit/store them.
- Follow the principle of least privilege when provisioning.
- Rotate keys frequently to limit exposure.
- Revoke compromised keys immediately and remediate root causes.
- Actively monitor, audit and analyze access to keys.
- Formalize governance processes for managing keys.
Applying standards like FIPS 140-3 and frameworks like NIST CSF also provides structure around effectively securing API keys.
Robust API key hygiene is essential for building secure, resilient applications. Investing in their proper management significantly reduces risks and prevents disastrous breaches.