Skip to main content

Installing Securosys KACLS

This page describes how to set up a Google Workspace with client-side encryption (CSE), with encryption keys protected in a Securosys HSM. The HSM is accessed through the Securosys Key Access Client List Service (KACLS).

The installation happens in two main steps: the deployment of the Securosys Key Service followed by the configuration of the Google Workspace.

Prerequisites​

To follow this guide, you need:

  • A Primus HSM or CloudHSM
    • Your Partition needs to have the JCE API enabled
  • A Google Workspace tenant, and administrator privileges to it
  • A server with Docker and Docker Compose installed, to deploy the Securosys Key Service on

Wrapping Key​

There are two ways to have a wrapping key in your Primus HSM:

  • Use an existing key that is already available on your Partition,
  • Let the Key Service create one for you during the initialization of the service.

In either case, when configuring the application.yml file, define the key name, algorithm and tag length you want. That key will be used for wrapping and unwrapping going forward.

Key Service Configuration​

Download the Securosys Key Service configuration files. The ZIP file contains the application.yml configuration file that you need to update. Importantly, you need to configure:

  • Which HSM and Partition to connect to: hsm.host, hsm.user, hsm.setupPassword
  • Which wrapping key to use: hsm.keyName, hsm.cipherAlgorithm, hsm.tagLength
  • Your workspace domain and e-mail addresses

Below is the full template.yml file with the most important Key Service configuration details highlighted.

Expand to view the full template file
# Full Securosys Google Workspace CSE KACLS configuration template.
# Copy required settings to application.yml and replace every replace-me value.

server:
port: 443 # HTTPS listener; omit :443 from the Google Admin KACLS URL.
address: 0.0.0.0 # Listen on every container interface.
domain: 'replace-me-kacls.example.com' # Public DNS name; no scheme or path.
https: true # Builds/validates the KACLS URL in JWT claims.
ssl:
enabled: true # Required by Google.
bundle: cse-tls

# Google requires TLS 1.2+ and a valid X.509 certificate covering server.domain.
spring.ssl.bundle.pem.cse-tls:
options:
enabled-protocols: [TLSv1.3, TLSv1.2]
reload-on-update: false # Restart after certificate rotation.
keystore:
certificate: file:/etc/app/config/tls/server.crt # Leaf followed by intermediates.
private-key: file:/etc/app/config/tls/server.key # Unencrypted PKCS#8 PEM.

logging:
config: /etc/app/config/log/logback.xml

cors:
# Required Google CSE browser origin. Never use a wildcard in production.
allowedOrigins:
- 'https://client-side-encryption.google.com'
allowedMethods: [GET, POST, OPTIONS]
allowedHeaders: [Origin, Content-Type, Accept, Authorization]
maxAge: 3600 # Preflight cache lifetime in seconds.
order: 100 # Servlet filter order.
# urlPatterns: ['/*'] # Omitted means every endpoint.

trusted:
# Perimeter allowlists. Empty email and domain lists trust no identities.
# A user is accepted when either the full address or the domain matches.
emails:
- 'replace-me-user@replace-me-workspace-domain.example'
domains:
- 'replace-me-workspace-domain.example'

# Applied to google-visitor and customer-idp authorization email types.
visitorEmails:
- 'replace-me-visitor@replace-me-workspace-domain.example'
visitorDomains:
- 'replace-me-workspace-domain.example'

# Reserved PKI-provider allowlist. Empty currently allows all providers.
pkiProviders: []

# Accepted authorization and authentication token issuers.
iss:
- 'gsuitecse-tokenissuer-drive@system.gserviceaccount.com'
- 'gsuitecse-tokenissuer-meet@system.gserviceaccount.com'
- 'gsuitecse-tokenissuer-calendar@system.gserviceaccount.com'
- 'gsuitecse-tokenissuer-gmail@system.gserviceaccount.com'
- 'apps-security-cse-kaclscommunication@system.gserviceaccount.com'
- 'https://replace-me-idp.example'

# Google authorization, customer IdP, and KACLS migration audiences.
aud:
- 'cse-authorization'
- 'replace-me-idp-audience-or-client-id'
- 'kacls-migration'

# Official Google CSE JWKS endpoints plus one explicit customer IdP endpoint.
# The five Google mappings are also resolved automatically by the service.
# Quote [issuer] so Spring preserves @, : and / in the exact JWT iss map key.
jwtJwksUrls:
'[gsuitecse-tokenissuer-drive@system.gserviceaccount.com]': 'https://www.googleapis.com/service_accounts/v1/jwk/gsuitecse-tokenissuer-drive@system.gserviceaccount.com'
'[gsuitecse-tokenissuer-meet@system.gserviceaccount.com]': 'https://www.googleapis.com/service_accounts/v1/jwk/gsuitecse-tokenissuer-meet@system.gserviceaccount.com'
'[gsuitecse-tokenissuer-calendar@system.gserviceaccount.com]': 'https://www.googleapis.com/service_accounts/v1/jwk/gsuitecse-tokenissuer-calendar@system.gserviceaccount.com'
'[gsuitecse-tokenissuer-gmail@system.gserviceaccount.com]': 'https://www.googleapis.com/service_accounts/v1/jwk/gsuitecse-tokenissuer-gmail@system.gserviceaccount.com'
'[apps-security-cse-kaclscommunication@system.gserviceaccount.com]': 'https://www.googleapis.com/service_accounts/v1/jwk/apps-security-cse-kaclscommunication@system.gserviceaccount.com'
'[https://replace-me-idp.example]': 'https://replace-me-idp.example/.well-known/jwks.json'

# HS256 is for explicitly enabled local/test issuers only.
jwtSharedSecrets: {}

# Must match a delegated token's optional kacls_owner_domain claim.
kaclsOwnerDomain: 'replace-me-workspace-domain.example'

# Empty disables /wrapprivatekey and IdP-authorized privileged APIs.
wrapPrivateKeyAdminEmails:
- 'replace-me-cse-admin@replace-me-workspace-domain.example'

hsm:
# Permit outbound TCP access. Host/port combinations are tried in sequence.
host:
- 'replace-me-primary-api.cloudshsm.com'
- 'replace-me-secondary-api.cloudshsm.com'
port:
- '2300'
user: 'replace-me-hsm-user'

# First-login OTP used to create the blinded secret file.
# Remove the value after successful setup and retain config-files/.secret securely.
setupPassword: 'replace-me-hsm-setup-password'
secretPath: '${SECRET_PATH:/etc/app/config/.secret}'

# Optional CloudsHSM proxy credentials; empty means a direct HSM connection.
proxyUser: ''
proxyPassword: ''

attestationKeyName: 'attestation-key' # Created automatically if missing.

# Created as a persistent AES-256 key on first startup if absent.
# Existing keys are reused without changing their attributes.
# Keep the label stable.
# Generated attributes: sensitive, non-extractable, modifiable, indestructible.
keyName: 'cse-wrapping-key'
wrappingKeyIndestructible: true # Set false only for disposable environments.
cipherAlgorithm: 'AES_GCM' # CipherAlgorithm enum name.
tagLength: 128 # AES-GCM tag length in bits.

# Created as a persistent RSA signing key on first startup if absent.
# Existing keys are reused and must have a persisted RSA public-key object.
jwtSigningKeyName: 'cse-jwt-signing-key'
jwtSigningKeySize: 3072 # Guidance; minimum supported is 2048.

springdoc:
api-docs:
enabled: false # Enable only on a protected admin network.
path: /v3/api-docs
swagger-ui:
enabled: false
path: /swagger-ui.html
disable-swagger-default-url: true

Afterwards, start the Docker container:

docker compose up --detach

API Reference​

The Key Service API uses the standard list of endpoints, as defined by Google.

Add Key Service to Google Workspace​

The administrator of your Google Workspace has to enable and configure CSE.

Firstly, in the Admin Console, navigate to Data > Compliance > Client-Side Encryption and select Add external key service.

Add CSE via external Key Service

In the next menu, enter the following details:

  • Name: Some descriptive name for your key service
  • URL: The HTTPS URL of your server.domain

External Key Service Details

Navigate back to the CSE page where you now see multiple new options.

Next, assign a default external key service. Select Assign and then in the Assignment section, select Assign again. In the dropdown menu, select which key service should be used by default.

Assign a default Key Service

Connect Your IdP​

Connect your IdP to your Google Workspace by following Google's documentation. You have two options:

  • Option 1: Connect to your IdP using a .well-known file
  • Option 2: Connect to your IdP using the Admin console

For convenience, the below section describes how to do it via the Admin Console.

Add the IdP configuration details via the IdP fallback button.

Add IdP details

In this example, Microsoft Entra ID is used a the IdP, but similar details can be generated in any IdP that supports the OIDC standard.

Define Entra as an IdP

Enable CSE for Apps​

You can now select for which Google Workspace apps CSE should be enabled. By default, all apps are marked as "OFF for everyone".

Default App configurations

Navigate to each app for which you want to enable client-side encryption and switch it to "ON":

Screenshot showing the ON/OFF toggle for Drive and Docs

Next Steps​

CSE is now ready to be used in your Google Workspace tenant. Your users can encrypt content by following the steps in this tutorial.

Further Reading​

Get started withCloudHSM for free.
Other questions?Ask Sales.
Feedback
Need help?