This is a guide on how to deploy Immuta on OpenShift.
Prerequisites
The following managed services must be provisioned and running before proceeding. For further assistance consult the recommendations table for your respective cloud provider.
Feature availability
If deployed without Elasticsearch/OpenSearch, several core services and features will be unavailable. See the deployment requirements for details.
PostgreSQL
(Optional) Elasticsearch/OpenSearch
Checklist
This checklist outlines the necessary prerequisites for successfully deploying Immuta.
Creating a dedicated namespace ensures a logically isolated environment for your Immuta deployment, preventing resource conflicts with other applications.
Create project
Create an OpenShift project named immuta.
oc new-project immuta
Get the UID range allocated to the project. Each running container's UID must fall within this range. This value will be referenced later on.
oc get project immuta --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
Get the GID range allocated to the project. Each running container's GID must fall within this range. This value will be referenced later on.
oc get project immuta --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
Switch to project immuta.
oc project immuta
Create registry secret
Create a container registry pull secret. Your credentials to authenticate with ocir.immuta.com can be viewed in your user profile at support.immuta.com.
There are numerous ways to connect to a PostgreSQL database. This step demonstrates how to connect with psql by creating an ephemeral Kubernetes pod.
Connect to the database
Connect to the database as an admin (e.g., postgres) by creating an ephemeral container inside the Kubernetes cluster. A shell prompt will not be displayed after executing the kubectl run command outlined below. Wait 5 seconds, and then proceed by entering a password.
Temporal's upgrade mechanism utilizes SQL command CREATE EXTENSION when managing database schema changes. However, in cloud-managed PostgreSQL offerings, this command is typically restricted to roles with elevated privileges to protect the database and maintain the stability of the cloud environment.
To ensure Temporal can successfully manage its schema, a pre-defined administrator role must be granted. The role name varies depending on the cloud-managed service:
Amazon RDS: rds_superuser
Azure Database: azure_pg_admin
Google Cloud SQL: cloudsqlsuperuser
Create the immuta role.
CREATE ROLE immuta with LOGIN ENCRYPTED PASSWORD '<postgres-password>';
ALTER ROLE immuta SET search_path TO immuta,public;
Grant administrator privileges to the immuta role. Upon successfully completing this installation guide, you can optionally revoke this role grant.
Grant role immuta additional privileges. Refer to the PostgreSQL documentation for further details on database roles and privileges.
GRANT ALL ON DATABASE immuta TO immuta;
GRANT ALL ON DATABASE temporal TO immuta;
GRANT ALL ON DATABASE temporal_visibility TO immuta;
Configure the immuta database.
\c immuta
CREATE EXTENSION pgcrypto;
Configure the temporal database.
\c temporal
GRANT CREATE ON SCHEMA public TO immuta;
Configure the temporal_visibility database.
\c temporal_visibility
GRANT CREATE ON SCHEMA public TO immuta;
CREATE EXTENSION btree_gin;
Exit the interactive prompt. Type \q, and then press Enter.
Install Immuta
This section demonstrates how to deploy Immuta using the Immuta Enterprise Helm chart once the prerequisite cloud-managed services are configured.
Why disable Ingress?
In OpenShift, Ingress resources are managed by OpenShift Routes. These routes provide a more integrated and streamlined way to handle external access to your applications. To avoid conflicts and ensure proper functionality, it's necessary to disable the pre-defined Ingress resource in the Helm chart.
Feature availability
If deployed without Elasticsearch/OpenSearch, several core services and features will be unavailable. See the deployment requirements for details.
immuta-values.yaml
global:
imageRegistry: ocir.immuta.com
imagePullSecrets:
- name: immuta-oci-registry
postgresql:
host: <postgres-fqdn>
port: 5432
username: immuta
password: <postgres-password>
audit:
config:
elasticsearchEndpoint: http://es-db-elasticsearch.immuta.svc.cluster.local:9200
elasticsearchUsername: <elasticsearch-username>
elasticsearchPassword: <elasticsearch-password>
postgresql:
database: immuta
deployment:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
worker:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
discover:
deployment:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
secure:
ingress:
enabled: false
postgresql:
database: immuta
ssl: false
web:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
backgroundWorker:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
temporal:
enabled: true
schema:
createDatabase:
enabled: false
server:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
config:
persistence:
default:
sql:
database: temporal
tls:
enabled: true
visibility:
sql:
database: temporal_visibility
tls:
enabled: true
frontend:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
history:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
matching:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
worker:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
schema:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
proxy:
deployment:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
immuta-values.yaml
global:
imageRegistry: ocir.immuta.com
imagePullSecrets:
- name: immuta-oci-registry
featureFlags:
AuditService: false
detect: false
auditLegacyViewHide: false
postgresql:
host: <postgres-fqdn>
port: 5432
username: immuta
password: <postgres-password>
audit:
enabled: false
discover:
deployment:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
secure:
ingress:
enabled: false
postgresql:
database: immuta
ssl: true
web:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
backgroundWorker:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
temporal:
enabled: true
schema:
createDatabase:
enabled: false
server:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
config:
persistence:
default:
sql:
database: temporal
tls:
enabled: true
visibility:
sql:
database: temporal_visibility
tls:
enabled: true
frontend:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
history:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
matching:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
worker:
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
schema:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
proxy:
deployment:
podSecurityContext:
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
runAsUser: <user-id>
# A number that is within the project range:
# oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
runAsGroup: <group-id>
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
Create a file named immuta-values.yaml with the above content, making sure to update all placeholder values.
This section helps you validate your Immuta installation by temporarily accessing the application locally. However, this access is limited to your own computer. To enable access for other devices, you must proceed with configuring Ingress outlined in the Next steps section.
Determine the name of the Secure service.
oc get service --selector "app.kubernetes.io/component=secure" --output name
Listen on local port 8080, forwarding TCP traffic to the Secure service's port named http.
oc port-forward <service-name> 8080:http
In a web browser, navigate to localhost:8080, to ensure the Immuta application loads.