
This add-on is operated by Mixable, Inc.
Encrypt, decrypt and audit access to your application secrets and sensitive data
ICE
Last updated 04 January 2018
The ICE add-on is currently in beta.
Table of Contents
ICE is an add-on for managing application secrets and sensitive data with encryption.
You can use ICE to encrypt app environment variables like API keys and database URLs. You can also use it to encrypt data like credit card numbers, customer records or personal videos. Encrypting and decrypting the data is fast, easy and secure, and every operation is logged for an audit trail.
Encrypting data is a security best practice. If you are storing financial or health data, it is a requirement that you encrypt data at rest to minimize the chance of exposing secrets. Any sensitive data can benefit from encryption to prevent visibility to an unauthorized party or an attacker.
When you add ICE, your application gains access to a Hardware Security Module (HSM) and its implementation of the Advanced Encryption Standard (AES) encryption algorithms. It is backed by the AWS Key Management Service (KMS), which is proven to meet the toughest security, compliance and auditing needs.
ICE leverages the AWS KMS API, which has supported client libraries for Java, .NET, NodeJS, PHP, Python, Ruby and Go.
Cryptography service basics
“Plaintext” is data in its unencrypted form. An “encryption algorithm” is set of mathematical steps that uses an unguessable “key” to transform plaintext into a “ciphertext”.
This ciphertext can be shared freely, as the data is meaningless until the secret encryption key is used again to decrypt it.
A “Hardware Security Module” (HSM) is tamper-proof hardware that stores a key and executes an encryption algorithm. With an HSM the secret key is never revealed to any other part of the system. A plaintext is sent into the HSM and it returns the ciphertext, or a ciphertext is sent and it returns the plaintext. There is no way to decrypt data without talking to the HSM.
With AWS Key Management Service (KMS) every encrypt and decrypt API call is audited. The request time, access key, IP address and operation is recorded in log files. This provides a way to verify that no unauthorized party accessed encrypted data.
Provisioning the add-on
ICE can be attached to a Heroku application via the CLI:
A list of all plans available can be found here.
$ heroku addons:create ice
-----> Adding ICE to sharp-mountain-4005... done, v18 ($5/mo)
Once ICE has been added, the ICE_AWS_ACCESS_KEY_ID
, ICE_SECRET_ACCESS_KEY
and ICE_KEY_ID
config vars will be available in the app configuration. You can then use any AWS KMS client to send data to the key service for encryption or decryption.
Local setup
AWS CLI setup
After provisioning the add-on, it’s useful to save the access key so your development environment can encrypt and decrypt data with the service.
First, install the AWS Command Line Interface and configure a profile with the ICE access key:
$ heroku config:get
=== sharp-mountain-4005 Config Vars
ICE_AWS_ACCESS_KEY_ID: AKIAI5BEGAWFYN3E7J6A
ICE_AWS_SECRET_ACCESS_KEY: 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
ICE_KEY_ID: arn:aws:kms:us-east-1:178540880712:key/e7eb068d-9b14-4b77-97c5-8cb38e71e210
$ brew install awscli
$ aws configure --profile ice
AWS Access Key ID [None]: <ICE_AWS_ACCESS_KEY_ID>
AWS Secret Access Key [None]: <ICE_AWS_SECRET_ACCESS_KEY>
Default region name [None]: us-east-1
Default output format [None]:
Now you can use the aws
command to encrypt a secret, in this case a pass phrase neuromancer
.
$ export AWS_DEFAULT_PROFILE=ice
$ aws kms encrypt \
--plaintext neuromancer \
--key-id arn:aws:kms:us-east-1:178540880712:key/e7eb068d-9b14-4b77-97c5-8cb38e71e210
{
"KeyId": "arn:aws:kms:us-east-1:178540880712:key/e7eb068d-9b14-4b77-97c5-8cb38e71e210",
"CiphertextBlob": "AQECAHhUH3SgfMwR3l/3GhIC4MjA43IDifWWdSXIVR0nbqnHkwAAAGQwYgYJKoZIhvcNAQcGoFUwUwIBADBOBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDCBdsKBHiXVGpruZnQIBEIAhNgAQ/8M+jpsQTdmq1OsAyKj7Bq/aM0H8MNuDMEVQ4toD"
}
Now you can save the encrypted secret in your Heroku app config. Heroku will never see the plaintext of this secret.
$ heroku config:add CIPHERTEXT_PASSWORD="AQECAHhUH3SgfMwR3l/3GhIC4MjA43IDifWWdSXIVR0nbqnHkwAAAGQwYgYJKoZIhvcNAQcGoFUwUwIBADBOBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDCBdsKBHiXVGpruZnQIBEIAhNgAQ/8M+jpsQTdmq1OsAyKj7Bq/aM0H8MNuDMEVQ4toD"
Setting CIPHERTEXT_PASSWORD and restarting ⬢ sharp-mountain-4005... done, v19
App setup
It’s also useful to save the config vars so your app development environment can operate against the service.
Use the Heroku Local command-line tool to configure, run and manage process types specified in your app’s Procfile. Heroku Local reads configuration variables from a .env
file. To view all of your app’s config vars, type heroku config
. Use the following command for each value that you want to add to your .env
file.
$ heroku config:get -s ICE_AWS_ACCESS_KEY_ID >> .env
$ heroku config:get -s ICE_AWS_SECRET_ACCESS_KEY >> .env
$ heroku config:get -s ICE_KEY >> .env
$ heroku config:get -s CIPHERTEXT_PASSWORD >> .env
Credentials and other sensitive configuration values should not be committed to source-control. In Git, exclude the .env
file with: echo .env >> .gitignore
.
For more information, see the Heroku Local article.
Using with Rails
Ruby on Rails applications will need to add the following entry into their Gemfile
.
gem 'aws-sdk'
Update application dependencies with bundler.
$ bundle install
Then use the AWS SDK to decrypt the ciphertext.
require 'aws-sdk'
kms = Aws::KMS::Client.new(
region: 'us-east-1',
access_key_id: ENV['ICE_AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['ICE_AWS_SECRET_ACCESS_KEY'],
)
resp = kms.decrypt(
ciphertext_blob: Base64.decode64(ENV['CIPHERTEXT_PASSWORD'])
)
ENV["PLAINTEXT_PASSWORD"] = resp.plaintext # neuromancer
Using with Python/Django
Python/Django applications will need to add the following entry into their requirements.txt
.
boto3
Update application dependencies with pip.
$ pip install -r requirements.txt
Then use the Boto library to decrypt the ciphertext.
import base64, boto3, os
client = boto3.client(
'kms',
aws_access_key_id=os.environ['ICE_AWS_ACCESS_KEY_ID'],
aws_secret_access_key=os.environ['ICE_AWS_SECRET_ACCESS_KEY'],
)
response = client.decrypt(
CiphertextBlob=base64.b64decode(os.environ['CIPHERTEXT_PASSWORD'])
)
os.environ['PLAINTEXT_PASSWORD'] = resp.plaintext # neuromancer
Migrating between plans
$ heroku addons:upgrade ice:production
-----> Upgrading ice:production to sharp-mountain-4005... done, v20 ($25/mo)
Your plan has been updated to: ice:production
Removing the add-on
ICE can be removed via the CLI.
This will disable your key and schedule it for deletion. This could result in encrypted data that can no longer be decrypted.
$ heroku addons:destroy ice
-----> Removing ice from sharp-mountain-4005... done, v21 ($25/mo)
Support
All ICE support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome via email.