Secure Proxy
With the Secure Proxy appliance, sensitive data can stay private to your organization via client-side encryption and customer-managed keys. You gain the privacy benefits of an on-premises installation without the cost of maintaining your own data infrastructure. It’s recommended if you’re in a regulated environment with sensitive data such as financial or healthcare and can help you meet any internal compliance requirements like HIPAA (more info on security and compliance).
For a case study, view How pVerify Deploys Moesif HIPAA-Compliant API Analytics to scale COVID testing.
How it works
The secure proxy is deployed as a Docker container in your infrastructure which handles encryption and decryption on the fly using your customer-managed keys. Because your master keys are never transmitted or stored on Moesif servers, its employees cannot access or inspect your API data.
Secure proxy is available only on enterprise plans. Reach out to our sales team for help.
Keystore
The secure proxy has connectors for popular Cloud key stores and will automatically rotates data keys as needed. Currently, AWS Key Management Service (KMS) and AWS CloudHSM are supported. If you require an alternative, reach out to our success team.
Moesif always encrypts your data at rest and in motion using Moesif-managed keys even if Secure Proxy is not deployed. Secure Proxy is an additional privacy layer enabling you to have full control over encryption keys (also called customer-managed keys).
Features supported
The majority of Moesif features will function normally even with the secure proxy deployed including the dashboards, Management API, alerts, and embedded dashboards. Moesif built a customized analytics store which works on encrypted data enabling you to still gain the reports you expect from Moesif. There are some minor limitations which we recommend reviewing before deploying secure proxy.
Access
There are two different ways to deploy secure proxy depending on whether you plan on utilizing Moesif’s embedded dashboards feature:
-
Local network only: If you don’t plan to use Moesif’s embedded dashboards feature, you can deploy the secure proxy on an internal host that’s not exposed to the internet. However, the host must be accessible by an employee’s laptop when they log into the Moesif portal such as by being on a corporate VPN.
-
Exposed to the internet: If you plan on using Moesif’s embedded dashboards feature, the secure proxy must be accessible by the internet so that your customers can also decrypt their data on the fly. The recommended way to do so is to deploy NGINX with SSL in front of Moesif secure proxy with SSL. A Docker example with NGINX and Moesif Secure Proxy is available on GitHub. Once done, you can add a CNAME or A Record to your DNS settings like
analytics.acmeinc.com
. Employees can also access the Moesif portal on the go and do not need to be on a corporate VPN.
What’s encrypted
All sensitive data such your HTTP headers, request and response body, and event metadata is encrypted. Non-sensitive fields such as request time is not encrypted for proper analytics. More info on unencrypted data.
Example
A working docker-compose.yml
is available on GitHub with moesifproxy
and NGINX configured with SSL termination using Let’s Encrypt.
How to install
1. Generate API Keys
You will need both your Collector Application Id and a Management API Key which can be found by logging into Moesif and going to API Keys from the menu. For Management API Key, ensure you generate with at least the following scopes:
create:events
read:events
create:encrypted_keys
read:encrypted_keys
read:workspaces
update:workspaces
read:virtual_eventtypes
update:virtual_eventtypes
2. Create AWS Key Management Service
Within your AWS Consle, create a new AWS Key Management Service. You can also use an existing KMS instance if preferred. Once AWS KMS is deployed, create a new symmetric encryption key within AWS KMS. Ensure the key type is set to symmetric and the use case, select Encrypt and decrypt.
Obtain your Customer Key Id from the AWS Console. This will be set in AWS_CUSTOMER_KEY_ID
in the later steps. To find your Key Id please follow the instructions here.
3. Create IAM Policy to access KMS
With AWS Console, create a new IAM policy which can access AWS KMS. Edit the policy using JSON editor and paste in the JSON below. If using Option B: AWS KMS access assuming an IAM role, you’ll also need permission to assume roles.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "kms:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
}
]
}
The above example will apply to all resources. As a best practice, you should set the “Resource” key to the ARN of the individual resources.
4. Run the Docker image
Run the moesif/moesifproxy:latest
docker image which is available in Docker Hub. In order for the secureproxy to access your AWS KMS, there are two ways to authenticate: You can either use Option A: AWS KMS access with access key or Option B: AWS KMS access assuming an IAM role.
Option A: AWS KMS access with access key
This option is the simplest which uses AWS access keys. These are passed to the secure proxy using the environment variables AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
.
- Within AWS Console, create a new IAM User. Ensure Access key - Programmatic access is checked.
- Then, associate the newly created user with the IAM policy created in the last step.
- Using the user’s credentials, set
AWS_CUSTOMER_KEY_ID
andAWS_SECRET_ACCESS_KEY
You can run the secureproxy using Docker run like below:
docker run -it -e MOESIF_MANAGEMENT_API_KEY="Your Moesif Management Key" \
-e MOESIF_APPLICATION_ID="Your moesif application Id" \
-e AWS_CUSTOMER_KEY_ID="Your customer managed key(CMK) in AWS KMS" \
-e AWS_ACCESS_KEY_ID="Your AWS access Key Id" \
-e AWS_SECRET_ACCESS_KEY="Your AWS secret access key" \
-e AWS_KMS_REGION="Your AWS KMS region such as 'us-west-2'" \
-p 9500:9500 --name moesifproxy moesif/moesifproxy
In Option A, AWS_SECURE_PROXY_ROLE_ARN
and AWS_KMS_REGION
are not defined.
Option B: AWS KMS access assuming an IAM role
This option provides additional security vs Option A as developers don’t need to store long-lived AWS credentials in environment variables. Instead, the secureproxy will use temporary AWS credentials to assume the IAM role which was created in last step to access your AWS KMS instance. In order for Secure Proxy to assume role in AWS_SECURE_PROXY_ROLE_ARN
, base credentials must already been injected by AWS or K8s service accounts to your container.
If you are using AWS EKS, follow the AWS Docs for Kubernetes Service Accounts. If you’re using EC2 directly, follow the AWS Docs for EC2.
Note that for EC2 credential injection, if you are using a single role to inject into the instance and also to assume the role in AWS_SECURE_PROXY_ROLE_ARN
, you will need to add the following trust policy to the role you are injecting into the instance in addition to a trust policy allowing the EC2 service to assume the role in AWS_SECURE_PROXY_ROLE_ARN
. This requirement is a recent change by AWS which is announced here: https://aws.amazon.com/blogs/security/announcing-an-update-to-iam-role-trust-policy-behavior/
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
}
},
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::123456789012:role/MyRole"
}
]
}
- To use Option B, create a new IAM role. Make note of the ARN of the newly created role.
- Then, associate the newly created user with the IAM policy created in the last step.
- Set the environment variable
AWS_SECURE_PROXY_ROLE_ARN
to the newly created role’s ARN. - Set
AWS_KMS_REGION
to the string representing AWS region where AWS KMS is configured.
You can run the secureproxy using Docker run like below:
docker run -it -e MOESIF_MANAGEMENT_API_KEY="Your Moesif Management Key" \
-e MOESIF_APPLICATION_ID="Your moesif application Id" \
-e AWS_CUSTOMER_KEY_ID="Your customer managed key (CMK) in AWS KMS" \
-e AWS_SECURE_PROXY_ROLE_ARN="IAM role that secure proxy should assume to access AWS KMS" \
-e AWS_KMS_REGION="Your AWS KMS region such as 'us-west-2'" \
-p 9500:9500 --name moesifproxy moesif/moesifproxy
In Option B, AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
are not defined.
Option C: Azure KeyVault
Please make sure that service principal has the following permissions:
Key Vault Crypto User
Key Vault Reader
- Only works for key vaults that use the
Azure role-based access control
permission model. - The Key algorithm should be
RSA-256
.- Key Type:
RSA
- RSA Key Size:
2048
- Key Type:
- No expiry time for key or atleast 2 years from the creation time.
- Auto Rotation should be
disabled
Important Notes: Please make sure Auto rotation
policy is disabled and key is valid for more than 2 years.
You can run the secureproxy using Docker run in two ways.
Using Managed Identity
Manage identity approach is preferred way if service is deployed in Azure Cloud
.
docker run -it -e MOESIF_MANAGEMENT_API_KEY="Your Moesif Management Key" \
-e MOESIF_APPLICATION_ID="Your moesif application Id" \
-e KMS_PROVIDER="Azure" \
-e AZURE_VAULT_URL="The URL of your Azure Key Vault (e.g., https://your-vault-name.vault.azure.net/)" \
-e AZURE_KEY_NAME="The name of the key in Azure Key Vault to be used for encryption/decryption" \
-p 9500:9500 --name moesifproxy moesif/moesifproxy
Using Environment Variables
Same as above but needs three extra environment variables:
AZURE_TENANT_ID
: The Azure Active Directory tenant (directory) IDAZURE_CLIENT_ID
: The application (client) ID registered in Azure Active DirectoryAZURE_CLIENT_SECRET
: The client secret for the application registered in Azure AD
docker run -it -e MOESIF_MANAGEMENT_API_KEY="Your Moesif Management Key" \
-e MOESIF_APPLICATION_ID="Your moesif application Id" \
-e KMS_PROVIDER="Azure" \
-e AZURE_VAULT_URL="The URL of your Azure Key Vault (e.g., https://your-vault-name.vault.azure.net/)" \
-e AZURE_KEY_NAME="The name of the key in Azure Key Vault to be used for encryption/decryption" \
-e AZURE_TENANT_ID="The Azure Active Directory tenant (directory) ID" \
-e AZURE_CLIENT_ID="The application (client) ID registered in Azure Active Directory " \
-e AZURE_CLIENT_SECRET="The client secret for the application registered in Azure AD" \
-p 9500:9500 --name moesifproxy moesif/moesifproxy
5. Update your server integration
You must update your server integrations to send data to the collector proxy located at http://localhost:9500/collector
of your secure proxy (assuming it’s running at localhost:9500). This ensures data is properly encrypted before sending to Moesif.
To do so, update the Base URI of your server integration to http://localhost:9500/collector
.
Refer to the options section of your respective server integration docs or reach out to support if you need help.
An example for moesif-nodejs is below:
const moesifMiddleware = moesif({
applicationId: process.env.MOESIF_APPLICATION_ID,
baseUri: 'http://localhost:9500/collector',
});
6. Let Moesif know
Once both the secure proxy and your server integration is set up, email Moesif support with your the hostname for secure proxy. Moesif will make an update to your account to finalize installation.
Accessing the Moesif Collector API
To send data to the Moesif collector API, you must use the proxy located at http://localhost:9500/collector
. This ensures data is properly encrypted before sending to Moesif. Any previous references to https://api.moesif.net
should be replaced with http://localhost:9500/collector
.
For example, to save users to Moesif, perform the following API call:
curl -X POST http://localhost:9500/collector/v1/users -H 'Content-Type: application/json' -H 'X-Moesif-Application-Id: YOUR_MOESIF_APPLICATION_ID' -d '{"user_id":"12345","company_id":"67890","metadata":{"email":"john@acmeinc.com","first_name":"John","last_name":"Doe","title":"Software Engineer"}}'
Accessing the Moesif Management API
To access your data using the management API, you must use the proxy located at http://localhost:9500/api
. Any previous references to https://api.moesif.com/v1
should be replaced with http://localhost:9500/api
. This ensures data is properly decrypted before consumption by any integrations you have.
Do not include the /v1
path segment when accessing management API. The secure proxy adds this automatically.
For example to query using the events endpoint, replace https://api.moesif.com/v1/search/~/search/events
with http://localhost:9500/api/search/~/search/events
like bellow:
curl -X POST -H 'Authorization: Bearer YOUR_MANAGEMENT_API_KEY' -H 'Content-Type: application/json' -d '{"size":50,"sort":[{"request.time":{"order":"desc","unmapped_type":"string"}}]}' -i 'http://localhost:9500/api/search/~/search/events?from=-7d&to=now&time_zone=America%2FLos_Angeles&week_starts_on=5'
Scaling Moesif proxy
For light load, you may be fine with a single Docker container running. If you expect a high volume of data collected or want to ensure high availability, you can run a pool of Secure Proxy instances behind a load balancer such as NGINX or HaProxy. Because secure proxy doesn’t maintain any persistent state, scaling Secure Proxy is simplified.
Different Secure Proxy setups
Each application in Moesif can be configured with a different secure proxy hostname. This can be helpful if you want different encryption keys for different environments. For example, you might want different encryption keys for your staging and your production environments. In this case, you would run two different Secure Proxy setups, one for each application.
Configuration options
MOESIF_APPLICATION_ID
Required Your Moesif Collector Application Id which can be found by logging into Moesif and going to API Keys from the top-right menu.
MOESIF_MANAGEMENT_API_KEY
Required Your Moesif Management API key. You can generate a new one by logging into Moesif and going to API Keys from the top-right menu. Ensure your API key is generated with at least the following scopes:
create:events
read:events
create:encrypted_keys
read:encrypted_keys
read:workspaces
update:workspaces
read:virtual_eventtypes
update:virtual_eventtypes
If you’re using additional functionality from the Moesif Management API, you may need additional scopes.
ENABLE_DEBUG_LOGS
Set to true to print debug logs. This is helpful to debug internal issues with secure proxy.
AWS options
The below options are used to configure AWS KMS.
AWS_CUSTOMER_KEY_ID
AWS_CUSTOMER_KEY_ID is the Customer managed key (CMK) in AWS KMS, To find KeyId follow the instructions here
AWS_KMS_REGION
AWS_KMS_REGION is a string representing aws region where AWS KMS is configured. Defaults to ‘us-west-2’
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
These are access keys needed to access AWS KMS via API. More information about access keys here. Make sure that IAM user/role associated with the access keys has permissions to access AWS KMS.
AWS_SECURE_PROXY_ROLE_ARN
This is the ROLE ARN that secure proxy should assume to access AWS KMS
Azure KeyVault options
The below options are used to configure Azure Key Vault.
KMS_PROVIDER
KMS_PROVIDER should be set to ‘Azure’ to use Azure Key Vault as the Key Management Service provider.
AZURE_TENANT_ID
AZURE_TENANT_ID is the Azure Active Directory tenant (directory) ID. This is a unique identifier for your Azure AD instance. You can find this in the Azure portal under Azure Active Directory > Properties
AZURE_CLIENT_ID
AZURE_CLIENT_ID is the application (client) ID registered in Azure Active Directory. This is used to authenticate your application with Azure. You can create a new application registration in Azure AD to get this ID
AZURE_CLIENT_SECRET
AZURE_CLIENT_SECRET is the client secret for the application registered in Azure AD. This acts as the application’s password for authentication. You can generate a new client secret in your application’s settings in Azure AD
AZURE_VAULT_URL
AZURE_VAULT_URL is the full URL of your Azure Key Vault instance (e.g., “https://your-vault-name.vault.azure.net/”). This is where your encryption keys are stored
AZURE_KEY_NAME
AZURE_KEY_NAME is the specific name of the key within your Azure Key Vault that you want to use for encryption and decryption operations
Encryption options
These options below control what data is encrypted. This can be useful if you require numeric math or date math. See Limitations of client-side encryption.
MOESIF_ENCRYPTION_ENABLED
Set to false to disable client-side encryption. This can be useful if you don’t need client-side encryption features but would like to leverage this service as a buffer.
MOESIF_ENCRYPT_NUMERICS
Set to false if numbers does not contain sensitive data and don’t require encryption. This enables numeric math in Moesif.
MOESIF_ENCRYPT_DATES
Set to false if dates (RFC 3339 formatted strings) does not contain sensitive data and don’t require encryption. This enables date math in Moesif.
MOESIF_ENCRYPT_REQUEST_HEADERS
Set to false if request headers does not contain sensitive data and don’t require encryption.
MOESIF_ENCRYPT_RESPONSE_HEADERS
Set to false if response headers does not contain sensitive data and don’t require encryption.
MOESIF_ENCRYPT_METADATA
Set to false if event metadata does not contain sensitive data and don’t require encryption.
MOESIF_ENCRYPT_REQUEST_HEADERS_BLACKLIST
Set to a comma separated string of blacklist of fields that will bypass request headers encryption. For example, if MOESIF_ENCRYPT_REQUEST_HEADERS_BLACKLIST=Host
is set, then Moesif will skip encrypting the host
request header. Please note that this configuration option is case insensitive.
MOESIF_ENCRYPT_RESPONSE_HEADERS_BLACKLIST
Set to a comma separated string of blacklist of fields that will bypass request headers encryption. For example, if MOESIF_ENCRYPT_REQUEST_HEADERS_BLACKLIST=Last-Modified
is set, then Moesif will skip encrypting the Last-Modified
response header. Please note that this configuration option is case insensitive.
MOESIF_ENCRYPT_REQUEST_BODY_BLACKLIST
Set to a comma separated string of blacklist of fields that will bypass request body encryption. For example, if MOESIF_ENCRYPT_REQUEST_BODY_BLACKLIST=dev,digit,test
is set, then Moesif will skip encrypting dev
, digit
and test
at any level while creating an event. Please note that this configuration option is case insensitive.
MOESIF_ENCRYPT_RESPONSE_BODY_BLACKLIST
Set to a comma separated string of blacklist of fields that will bypass response body encryption. For example, if MOESIF_ENCRYPT_RESPONSE_BODY_BLACKLIST=uuid,message
is set, then Moesif will skip encrypting uuid
and message
at any level while creating an event. Please note that this configuration option is case insensitive.
MOESIF_ENCRYPT_METADATA_BLACKLIST
Set to a comma separated string of blacklist of fields that will bypass metadata encryption. For example, if MOESIF_ENCRYPT_METADATA_BLACKLIST=datacenter,sf
is set, then Moesif will skip encrypting datacenter
and sf
at any level while creating an event. Please note that this configuration option is case insensitive.
MOESIF_ENCRYPT_GRAPHQL_QUERY
Set to true if the GraphQL query string is sensitive and requires encryption (uncommon). Moesif will encrypt the GraphQL query in request body. When encrypted, GraphQL analytics will have limited functionality. Default to false, where Moesif will encrypt all the fields in the request body except query
field.
MOESIF_ENCRYPTION_ROTATION_MONTHS
Set to an integer as the duration in calendar months for encryption key rotation. Default = 12, e.g. 12 months for annual key rotation happening on 01-01 00:00 UTC each year. Customers who require a specific key rotation interval can set MOESIF_ENCRYPTION_ROTATION_MONTHS to the schedule of calendar months at which they would like their encryption keys to change. Key rotation always happens on the first of a calendar month. Moesif recommends the default value of 12.
How to build
Moesif Proxy uses the revel webframework. To learn more about revel https://revel.github.io/
To build Docker image
docker build -t moesif/moesifproxy:latest
To push to Docker repo
docker login
docker push moesif/moesifproxy:latest
Troubleshooting
Debug logs
If you experience issues with secure proxy, restart your instance after setting the environment variable ENABLE_DEBUG_LOGS
to true. This will print helpful debug logs which can be shared with Moesif support.
Verify access
If you experience errors related to AWS Credentials like NoCredentialProviders
, it’s likely the secure proxy cannot access your keystore in AWS. Check that you correctly injected the right role and that the associated policy has access AWS KMS. See create a role to access KMS.
If you’re using AWS KMS access assuming an IAM role, also ensure the role is correctly attached to your EC2 VM or k8s pod and the role has permissions to assume a role.
Limitations
- If enabled for a pre-existing app, filtering and aggregations will not work on old data. We recommend creating a new app in Moesif for enabling secure proxy.
- Numeric fields will behave like strings (i.e. no math supported) unless MOESIF_ENCRYPT_NUMERICS is set to
false
. - Date fields will behave like strings (i.e. no date math supported) unless MOESIF_ENCRYPT_DATES is set to
false
. - If using embedded templates (for customer-facing portal), the secure proxy must be accessible from the internet.
- We recommend a subdomain like
analytics.acmeinc.com
that points to NGINX with SSL (See Docker example). - Alert rules with a group by will not have decrypted values in any notifications. A feature is on our roadmap for Q1 2024 to fix this.
Unencrypted data
There are certain parts of your API data that bypass client-side encryption for proper analytics, including:
- Request and response time (latency)
- Route and verb
- Response status code
- user_id and company_id
- Binary and non-JSON payloads such as Protobuf or Thrift
- The names of fields used within your API
Like most web analytics tools, the secure proxy does not encrypt data from client integrations like moesif-browser-js as tracking custom actions like “Signed In” or “Viewed Page” typically do not typically contain sensitive data.
Other use cases
Besides client-side encryption and decryption, the secure proxy enables a variety of other use cases:
- Reduce the number of outbound connections to Moesif’s APIs.
- Relay requests from servers that don’t have direct access to the internet.
- White label the Moesif Collector or Management API like
analytics.acmeinc.com/api
.