Configuring and managing Apicurio Registry deployment

Securing Apicurio Registry using the Keycloak Operator

The following procedure shows how to configure a Apicurio Registry REST API and web console to be protected by Keycloak.

Apicurio Registry supports the following user roles:

Table 1. Apicurio Registry user roles
Name Capabilities

sr-admin

Full access, no restrictions.

sr-developer

Create artifacts and configure artifact rules. Cannot modify global rules, perform import/export, or use /admin REST API endpoint.

sr-readonly

View and search only. Cannot modify artifacts or rules, perform import/export, or use /admin REST API endpoint.

There is a related configuration option in the ApicurioRegistry CRD that you can use to set the web console to read-only mode. However, this configuration does not affect the REST API.
Prerequisites
  • You must have already installed the Apicurio Registry Operator.

  • You must install the Keycloak Operator or have Keycloak accessible from your OpenShift cluster.

The example configuration in this procedure is intended for development and testing only. To keep the procedure simple, it does not use HTTPS and other defenses recommended for a production environment. For more details, see the Keycloak documentation.
Procedure
  1. In the OpenShift web console, click Installed Operators and Keycloak Operator, and then the Keycloak tab.

  2. Click Create Keycloak to provision a new Keycloak instance for securing a Apicurio Registry deployment. You can use the default value, for example:

    apiVersion: keycloak.org/v1alpha1
    kind: Keycloak
    metadata:
      name: example-keycloak
      labels:
        app: sso
    spec:
      instances: 1
      externalAccess:
        enabled: True
      podDisruptionBudget:
        enabled: True
  3. Wait until the instance has been created, and click Networking and then Routes to access the new route for the keycloak instance.

  4. Click the Location URL and copy the displayed URL value for later use when deploying Apicurio Registry.

  5. Click Installed Operators and Keycloak Operator, and click the Keycloak Realm tab, and then Create Keycloak Realm to create a registry example realm:

    apiVersion: keycloak.org/v1alpha1
    kind: KeycloakRealm
    metadata:
      name: registry-keycloakrealm
      labels:
        app: registry
    spec:
      instanceSelector:
        matchLabels:
          app: sso
      realm:
        displayName: Registry
        enabled: true
        id: registry
        realm: registry
        sslRequired: none
        roles:
          realm:
            - name: sr-admin
            - name: sr-developer
            - name: sr-readonly
        clients:
          - clientId: registry-client-ui
            implicitFlowEnabled: true
            redirectUris:
              - '*'
            standardFlowEnabled: true
            webOrigins:
              - '*'
            publicClient: true
          - clientId: registry-client-api
            implicitFlowEnabled: true
            redirectUris:
              - '*'
            standardFlowEnabled: true
            webOrigins:
              - '*'
            publicClient: true
        users:
          - credentials:
              - temporary: false
                type: password
                value: changeme
            enabled: true
            realmRoles:
              - sr-admin
            username: registry-admin
          - credentials:
              - temporary: false
                type: password
                value: changeme
            enabled: true
            realmRoles:
              - sr-developer
            username: registry-developer
          - credentials:
              - temporary: false
                type: password
                value: changeme
            enabled: true
            realmRoles:
              - sr-readonly
            username: registry-user
    You must customize this KeycloakRealm resource with values suitable for your environment if you are deploying to production. You can also create and manage realms using the Keycloak web console.
  6. If your cluster does not have a valid HTTPS certificate configured, you can create the following HTTP Service and Ingress resources as a temporary workaround:

    1. Click Networking and then Services, and click Create Service using the following example:

      apiVersion: v1
      kind: Service
      metadata:
        name: keycloak-http
        labels:
          app: keycloak
      spec:
        ports:
          - name: keycloak-http
            protocol: TCP
            port: 8080
            targetPort: 8080
        selector:
          app: keycloak
          component: keycloak
        type: ClusterIP
        sessionAffinity: None
      status:
        loadBalancer: {}
    2. Click Networking and then Ingresses, and click Create Ingress using the following example::

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: keycloak-http
        labels:
          app: keycloak
      spec:
        rules:
          - host: KEYCLOAK_HTTP_HOST
            http:
              paths:
                - path: /
                  pathType: ImplementationSpecific
                  backend:
                    service:
                      name: keycloak-http
                      port:
                        number: 8080

      Modify the host value to create a route accessible for the Apicurio Registry user, and use it instead of the HTTPS route created by Keycloak Operator.

  7. Click the Apicurio Registry Operator, and on the ApicurioRegistry tab, click Create ApicurioRegistry, using the following example, but replace your values in the keycloak section.

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry
    metadata:
      name: example-apicurioregistry-keycloak
    spec:
      configuration:
        security:
          keycloak:
            url: "http://keycloak-http-<namespace>.apps.<cluster host>"
            # ^ Required
            # Use an HTTP URL in development.
            realm: "registry"
            # apiClientId: "registry-client-api"
            # ^ Optional (default value)
            # uiClientId: "registry-client-ui"
            # ^ Optional (default value)

Managing Apicurio Registry environment variables

Apicurio Registry Operator manages most common Apicurio Registry configuration, but there are some options that it does not support yet. If a high-level configuration option is not available in the ApicurioRegistry CR, you can use an environment variable to adjust it. You can update these by setting an environment variable directly in the ApicurioRegistry CR, in the spec.configuration.env field. These are then forwarded to the Deployment resource of Apicurio Registry.

Procedure

You can manage Apicurio Registry environment variables by using the OpenShift web console or CLI.

OpenShift web console
  1. Select the Installed Operators tab, and then Apicurio Registry Operator.

  2. On the Apicurio Registry tab, click the ApicurioRegistry CR for your Apicurio Registry deployment.

  3. Click the YAML tab and then edit the spec.configuration.env section as needed. The following example shows how to set default global content rules:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry
    metadata:
      name: example-apicurioregistry
    spec:
      configuration:
        # ...
        env:
          - name: REGISTRY_RULES_GLOBAL_VALIDITY
            value: FULL # One of: NONE, SYNTAX_ONLY, FULL
          - name: REGISTRY_RULES_GLOBAL_COMPATIBILITY
            value: FULL # One of: NONE, BACKWARD, BACKWARD_TRANSITIVE, FORWARD, FORWARD_TRANSITIVE, FULL, FULL_TRANSITIVE
OpenShift CLI
  1. Select the project where Apicurio Registry is installed.

  2. Run oc get apicurioregistry to get the list of ApicurioRegistry CRs

  3. Run oc edit apicurioregistry on the CR representing the Apicurio Registry instance that you want to configure.

  4. Add or modify the environment variable in the spec.configuration.env section.

    The Apicurio Registry Operator might attempt to set an environment variable that is already explicitly specified in the spec.configuration.env field. If an environment variable configuration has a conflicting value, the value set by Apicurio Registry Operator takes precedence.

    You can avoid this conflict by either using the high-level configuration for the feature, or only using the explicitly specified environment variables. The following is an example of a conflicting configuration:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry
    metadata:
      name: example-apicurioregistry
    spec:
      configuration:
        # ...
        ui:
          readOnly: true
        env:
          - name: REGISTRY_UI_FEATURES_READONLY
            value: false

    This configuration results in the Apicurio Registry web console being in read-only mode.

Apicurio Registry liveness and readiness environment variables

Apicurio Registry provides readiness and liveness probes for OpenShift to ensure application health. These settings are configured to use reasonable defaults, but if you want to adjust them, this section provides details on the environment variables that you can configure.

OpenShift liveness and readiness errors are explained as follows:

  • Liveness error - the application cannot make progress, OpenShift restarts the failing pod.

  • Readiness error - the application is not ready, for example, it is overwhelmed by requests. OpenShift stops sending requests to the pod for the time the probe fails. If other pods are OK, they still receive requests.

Table 2. Apicurio Registry liveness environment variables
Name Value type Description

LIVENESS_ERROR_THRESHOLD

Positive integer

Number of liveness errors that can occur before the liveness probe fails.

LIVENESS_COUNTER_RESET

Positive integer, seconds

Period in which the threshold number of errors must occur. For example, if this value is 60 and the threshold is 1, the check fails after two errors occur in 1 minute.

LIVENESS_STATUS_RESET

Positive integer, seconds

Number of seconds that must elapse without any more errors for the liveness probe to reset to OK status. Because OpenShift restarts the pod that fails the liveness check, this value, unlike readiness, does not actually affect what happens.

LIVENESS_ERRORS_IGNORED

Comma-separated list of fully qualified exception class names.

List of errors that are ignored for liveness checking purposes.

Table 3. Apicurio Registry readiness environment variables
Name Value type Description

READINESS_ERROR_THRESHOLD

Positive integer

Number of readiness errors that can occur before the readiness probe fails.

READINESS_COUNTER_RESET

Positive integer, seconds

Period in which the threshold number of errors must occur. For example, if this value is 60 and the threshold is 1, the check fails after two errors occur in 1 minute.

READINESS_STATUS_RESET

Positive integer, seconds

Number of seconds that must elapse without any more errors for the readiness probe to reset to OK status. In practice, this value means how long the pod remains in an unready state until it returns to normal operation.

READINESS_TIMEOUT

positive integer, seconds

The readiness system tracks the timeout of two operations: how long it takes for a storage request to complete, and how long it takes for an HTTP REST API request to return a response. If the operation takes more time, it is counted as a readiness error. This value controls those timeouts.

Configuring Apicurio Registry deployment using PodTemplate

This is a Technology Preview feature only, which might evolve in future releases. Before using this feature in production, make sure to test that your deployment works as expected. Review the Release Notes in future releases for updates.

The ApicurioRegistry CRD contains the spec.deployment.podTemplateSpecPreview field, which has the same structure as the field spec.template in a Kubernetes Deployment resource (the PodTemplateSpec struct).

With some restrictions, the Apicurio Registry Operator forwards the data from this field to the corresponding field in the Apicurio Registry deployment. This provides greater configuration flexibility, without the need for the Apicurio Registry Operator to natively support each use case.

The following table contains a list of subfields that are not accepted by the Apicurio Registry Operator, and result in a configuration error:

Table 4. Restrictions on the podTemplateSpecPreview subfields
podTemplateSpecPreview subfield Status Details

metadata.annotations

alternative exists

spec.deployment.metadata.annotations

metadata.labels

alternative exists

spec.deployment.metadata.labels

spec.affinity

alternative exists

spec.deployment.affinity

spec.containers[*]

warning

To configure the Apicurio Registry container, name: registry must be used

spec.containers[name = "registry"].env

alternative exists

spec.configuration.env

spec.containers[name = "registry"].image

alternative exists

spec.deployment.image

spec.imagePullSecrets

alternative exists

spec.deployment.imagePullSecrets

spec.tolerations

alternative exists

spec.deployment.tolerations

If you set a field in podTemplateSpecPreview, its value must be valid, as if you configured it in the Apicurio Registry Deployment directly. The Apicurio Registry Operator might still modify the values you provided, but it will not fix an invalid value or make sure a default value is present.

Configuring an HTTPS connection to Apicurio Registry from inside the OpenShift cluster

The following procedure shows how to configure Apicurio Registry deployment to expose a port for HTTPS connections from inside the OpenShift cluster.

This kind of connection is not directly available outside of the cluster. Routing is based on hostname, which is encoded in the case of an HTTPS connection. Therefore, edge termination or other configuration is still needed. See Configuring an HTTPS connection to Apicurio Registry from outside the OpenShift cluster.
Prerequisites
  • You must have already installed the Apicurio Registry Operator.

Procedure
  1. Generate a keystore with a self-signed certificate. You can skip this step if you are using your own certificates.

    openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout tls.key -out tls.crt
  2. Create a new secret to hold the certificate and the private key.

    1. In the left navigation menu of the OpenShift web console, click Workloads > Secrets > Create Key/Value Secret.

    2. Use the following values:
      Name: https-cert-secret
      Key 1: tls.key
      Value 1: tls.key (uploaded file)
      Key 2: tls.crt
      Value 2: tls.crt (uploaded file)

    or create the secret using the following command:

    oc create secret generic https-cert-secret --from-file=tls.key --from-file=tls.crt
  3. Edit the spec.configuration.security.https section of the ApicurioRegistry CR for your Apicurio Registry deployment, for example:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry
    metadata:
      name: example-apicurioregistry
    spec:
      configuration:
        # ...
        security:
          https:
            secretName: https-cert-secret
  4. Verify that the connection is working:

    1. Connect into a pod on the cluster using SSH (you can use the Apicurio Registry pod):

      oc rsh example-apicurioregistry-deployment-6f788db977-2wzpw
    2. Find the cluster IP of the Apicurio Registry pod from the Service resource (see the Location column in the web console). Afterwards, execute a test request (we are using self-signed certificate, so an insecure flag is required):

      curl -k https://172.30.230.78:8443/health
In the Kubernetes secret containing the HTTPS certificate and key, the names tls.crt and tls.key must be used for the provided values. This is currently not configurable.
Disabling HTTP

If you enabled HTTPS using the procedure in this section, you can also disable the default HTTP connection by setting the spec.security.https.disableHttp to true. This removes the HTTP port 8080 from the Apicurio Registry pod container, Service, and the NetworkPolicy (if present).

Importantly, Ingress is also removed because the Apicurio Registry Operator currently does not support configuring HTTPS in Ingress. Users must create an Ingress for HTTPS connections manually.

Configuring an HTTPS connection to Apicurio Registry from outside the OpenShift cluster

The following procedure shows how to configure Apicurio Registry deployment to expose an HTTPS edge-terminated route for connections from outside the OpenShift cluster.

Prerequisites
Procedure
  1. Add a second Route in addition to the HTTP route created by the Apicurio Registry Operator. For example:

    kind: Route
    apiVersion: route.openshift.io/v1
    metadata:
      [...]
      labels:
        app: example-apicurioregistry
        [...]
    spec:
      host: example-apicurioregistry-default.apps.example.com
      to:
        kind: Service
        name: example-apicurioregistry-service-9whd7
        weight: 100
      port:
        targetPort: 8080
      tls:
        termination: edge
        insecureEdgeTerminationPolicy: Redirect
      wildcardPolicy: None
    Make sure the insecureEdgeTerminationPolicy: Redirect configuration property is set.

    If you do not specify a certificate, OpenShift will use a default. Alternatively, you can generate a custom self-signed certificate using the following commands:

    openssl genrsa 2048 > tls.key &&
    openssl req -new -x509 -nodes -sha256 -days 365 -key tls.key -out tls.crt

    Then create a route using the OpenShift CLI:

    oc create route edge \
      --service=example-apicurioregistry-service-9whd7 \
      --cert=tls.crt --key=tls.key \
      --hostname=example-apicurioregistry-default.apps.example.com \
      --insecure-policy=Redirect \
      -n default

Backing up Apicurio Registry PostgreSQL storage

When using storage in a PostgreSQL database, you must ensure that the data stored by Apicurio Registry is backed up regularly.

SQL Dump is a simple procedure that works with any PostgreSQL installation. This uses the pg_dump utility to generate a file with SQL commands that you can use to recreate the database in the same state that it was in at the time of the dump.

pg_dump is a regular PostgreSQL client application, which you can execute from any remote host that has access to the database. Like any other client, the operations that can perform are limited to the user permissions.

Procedure
  • Use the pg_dump command to redirect the output to a file:

     $ pg_dump dbname > dumpfile

    You can specify the database server that pg_dump connects to using the -h host and -p port options.

  • You can reduce large dump files using a compression tool, such as gzip, for example:

     $ pg_dump dbname | gzip > filename.gz
Additional resources

Restoring Apicurio Registry PostgreSQL storage

You can restore SQL Dump files created by pg_dump using the psql utility.

Prerequisites
Procedure
  1. Enter the following command to create the database:

     $ createdb -T template0 dbname
  2. Enter the following command to restore the SQL dump

     $ psql dbname < dumpfile
  3. Run ANALYZE on each database so the query optimizer has useful statistics.