Skip to main content
Skip table of contents

Deploy EJBCA as RA with automation

ENTERPRISE

This outlines how to deploy a Registration Authority (RA) using the EJBCA Enterprise configuration export/import tool EJBCA ConfigDump.

EJBCA-RA-Container-Diagram.png

Prerequisites

Before you begin, you should be familiar with how to deploy EJBCA CA in Kubernetes.

  • Enroll server TLS certificates.

  • Configure Ingress and internal services with TLS.

  • Prepare database and other credentials.

EJBCA installation with ConfigDump import does not support replication during the installation stage. Instead, use helm install with ConfigDump and replicaCount: 1. After installation, perform a helm upgrade to the desired replicaCount.

Step 1 - Deploy EJBCA RA

Prepare configuration dump for the RA installation

The following attributes are created using the EJBCA ConfigDump configuration file in the examples provided:

  • Certification Authorities (CAs): Import the existing CAs as external CAs in the RA instance. You need to configure the CA certificate and subjectDN for this example. Note that these are truncated in the following ConfigMap example.

  • Roles and Role Members: Roles used for certificate authentication with CN (common name) SuperAdmin and AutomationAdmin.

  • Protocols: Configuration that enables REST, ACME and other protocols.

Prepare the configuration dump file as a Kubernetes ConfigMap.

Example filename: ejbca-ra-init-configmap.yaml

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: ejbca-ra-init-configmap
data:
  configdump.json: |
    {
      "certification-authorities": {
        "ManagementCA": {
          "Object Type": "Certification Authority",
          "Version": 2,
          "Name": "ManagementCA",
          "Type of CA": "X.509",
          "Description": "CA created by certificate import.",
          "Serial Number Octet Size": 20,
          "Pre-produce OCSP Responses": false,
          "Microsoft CA Compatible Mode Used": false,
          "Store responses on-demand": false,
          "Pre-produce OCSP Responses Upon certificate issuance/revocation": false,
          "Certificate Profile": "ROOTCA",
          "Default Certificate Profile": "Not used",
          "Use Append-Only Table": false,
          "Certificate Chain": [
            "MIIDLTC....truncated.....GHKxovrA=="
           ],
          "Enforce Unique Public Keys": true,
          "Enforce key renewal": false,
          "Enforce Unique DN": true,
          "User Storage": true,
          "Certificate Storage": true,
          "Accept Revocations for Non-Existing Entries": false,
          "Subject DN": "CN=ManagementCA,OU=SomeOrg",
          "Signed By": "Self Signed",
          "Validity": "0d",
          "Subject Alternative Name": null,
          "Use UTF-8 in Policy Notice Text": true,
          "LDAP DN Order": true,
          "Authority Key Id Used": true,
          "CRL Number Used": true,
          "Partitioned CRL Used": false,
          "CRL Expiration Period": "1d",
          "CRL Issue Interval": "0m",
          "CRL Overlap Time": "10m",
          "Delta CRL Period": "0m",
          "Generate CRL Upon Revocation": false,
          "Allow Changing Revocation Reason": false,
          "Finish User": true,
          "CA Healthcheck Enabled": true,
          "Request Processor": null
        },
        "RootCA": {
          "Object Type": "Certification Authority",
          "Version": 2,
          "Name": "RootCA",
          "Type of CA": "X.509",
          "Description": "CA created by certificate import.",
          "Serial Number Octet Size": 20,
          "Pre-produce OCSP Responses": false,
          "Microsoft CA Compatible Mode Used": false,
          "Store responses on-demand": false,
          "Pre-produce OCSP Responses Upon certificate issuance/revocation": false,
          "Certificate Profile": "ROOTCA",
          "Default Certificate Profile": "Not used",
          "Use Append-Only Table": false,
          "Certificate Chain": [
            "MIIDLTC....truncated.....GHKxovrA=="
          ],
          "Enforce Unique Public Keys": true,
          "Enforce key renewal": false,
          "Enforce Unique DN": true,
          "User Storage": true,
          "Certificate Storage": true,
          "Accept Revocations for Non-Existing Entries": false,
          "Subject DN": "CN=RootCA,C=SE",
          "Signed By": "Self Signed",
          "Validity": "0d",
          "Subject Alternative Name": null,
          "Use UTF-8 in Policy Notice Text": true,
          "LDAP DN Order": true,
          "Authority Key Id Used": true,
          "CRL Number Used": true,
          "Partitioned CRL Used": false,
          "CRL Expiration Period": "1d",
          "CRL Issue Interval": "0m",
          "CRL Overlap Time": "10m",
          "Delta CRL Period": "0m",
          "Generate CRL Upon Revocation": false,
          "Allow Changing Revocation Reason": false,
          "Finish User": true,
          "CA Healthcheck Enabled": true,
          "Request Processor": null
        }
      },
      "available-protocols": {
        "available-protocol-configuration": {
          "Object Type": "Available Protocols",
          "Version": 1,
          "Name": "available-protocol-configuration",
          "ACME": true,
          "Certstore": true,
          "CMP": true,
          "CRLstore": true,
          "EST": true,
          "MSAE": true,
          "OCSP": false,
          "SCEP": true,
          "RA Web": true,
          "REST CA Management": false,
          "REST Certificate Management": false,
          "REST Coap Management": false,
          "REST Crypto Token Management": false,
          "REST End Entity Management": true,
          "REST End Entity Management V2": true,
          "REST Configdump": true,
          "REST Certificate Management V2": true,
          "REST SSH V1": true,
          "REST System V1": false,
          "Webdist": true,
          "Web Service": true,
          "ITS Certificate Management": false,
          "Custom header name for REST calls from browser": "X-Keyfactor-Requested-With"
        }
      },
      "peer-connectors": {
        "global-peer-configuration": {
          "Object Type": "Peer Global Configuration",
          "Version": 1,
          "Allow incoming connections": true,
          "Allow outgoing connections": false
        }
      },
      "admin-roles": {
        "Super Administrator Role": {
          "Object Type": "Role",
          "Version": 1,
          "Name": "Super Administrator Role",
          "Role Members": [
            {
              "Token Type": "CertificateAuthenticationToken",
              "Issuer": "ManagementCA",
              "Match With": "WITH_COMMONNAME",
              "Match Value": "AutomationAdmin"
            },
            {
              "Token Type": "CertificateAuthenticationToken",
              "Issuer": "ManagementCA",
              "Match With": "WITH_COMMONNAME",
              "Match Value": "SuperAdmin"
            },
            {
              "Token Type": "CliAuthenticationToken",
              "Issuer": null,
              "Match With": "USERNAME",
              "Match Value": "ejbca"
            }
          ],
          "Namespace": "",
          "RA Style Id": 0,
          "Access Rules": {
            "/": "Allow"
          }
        },
        "raIncomingCaPeer": {
          "Object Type": "Role",
          "Version": 1,
          "Name": "raIncomingCaPeer",
          "Role Members": [
            {
              "Token Type": "CertificateAuthenticationToken",
              "Issuer": "ManagementCA",
              "Match With": "WITH_COMMONNAME",
              "Match Value": "peer-key"
            }
          ],
          "Namespace": "",
          "RA Style Id": 0,
          "Access Rules": {
            "/ca/RootCA/": "Allow",
            "/ca/ManagementCA/": "Allow",
            "/peerincoming/": "Allow",
            "/ra_slave/manage/": "Allow"
          }
        }
      }
    }

Create the ConfigMap:

BASH
kubectl apply -f ejbca-ra-init-configmap.yaml

Deployment customization with values.yaml

YAML
image:
  variant: ra
  
#imagePullSecrets:
#  - name: keyfactor-registry  

ejbca:
  configdumpImport:
    enabled: true
    initialize: true
    configMapName: ejbca-ra-init-configmap
    configMapKey: configdump.json
  env:
    DATABASE_JDBC_URL: "jdbc:mariadb://ra-database-service:3306/ejbca?characterEncoding=utf8"
    DATABASE_USER: ejbca
  envRaw:
    - name: DATABASE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mariadb-passwords
          key: mariadb-password          
nginx:
  enabled: true
  host: "ejbca-ra-internal-host"
  mountInternalNginxCert: true
  secretInternalNginxCert: "internal-nginx-credential-secret-ra1"
ingress:
  enabled: true
  className: "nginx"
  annotations:
    nginx.ingress.kubernetes.io/auth-tls-verify-client: "optional"
    nginx.ingress.kubernetes.io/auth-tls-secret: "default/ejbca-ingress-trust-secret"
    nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
    nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
  hosts:
    - host: "ejbcara.example.com"
      paths:
        - path: /
          pathType: Prefix
  tls:
    - hosts:
        - "ejbcara.example.com"
      secretName: ingress-credential-secret-ra1

Step 2 - Configure Peer Connection

To configure the Peer setup in the CA instance with ConfigDump, you need to make a ConfigDump REST POST call to the CA instance with a SuperAdmin token with initialize set to true.

You can use the following script where SuperAdmin.p12 or ADMINP12 is the SuperAdmin token enrolled after the CA installation:

BASH
#!/bin/bash
# usage
# ./configdump-rest.sh ejbcaca1.example.com add_ra_in_ca_configdump SuperAdmin.p12 foo123

SERVER_HOST="$1"
CONFIGDUMP_JSON="$2"
ADMINP12="$3"
ADMINP12PASS="$4"
curl -k -X POST \
    "https://$SERVER_HOST/ejbca/ejbca-rest-api/v1/configdump?ignoreerrors=false&initialize=true&continue=false&overwrite=yes&resolve=abort" \
    --cert-type P12 --cert "$ADMINP12:$ADMINP12PASS" -H  "Content-Type: application/json" \
    -d "@$CONFIGDUMP_JSON" -v

Ensure peer-connectors.{peer-name}.URL is configured according to the service name attached to the NGINX sidecar of the peer. Typically, this is {peer-chart-release-name}.{peer-namespace}.

Additionally, the common name(CN) of the server TLS certificate must match the Match Value in admin-roles.Role Members, such as ejbcara.example.com in the following example.

JSON
{
  "peer-connectors": {
    "ejbca-ra1": {
      "Object Type": "Peer Connector",
      "Version": 1,
      "Name": "ejbca-ra1",
      "Peer Enabled": true,
      "URL": "https://ejbcara-deployment-nginx/ejbca/peer/v1",
      "Long Hanging Connections Enabled": true,
      "Min Long Hanging Connections": 10,
      "Max Long Hanging Connections": 20,
      "Authentication Key Binding": "peer-key"
    }
  },
  "internal-key-bindings": {
    "peer-key": {
      "Object Type": "Internal Key Binding",
      "Version": 1,
      "Name": "peer-key",
      "Type": "AuthenticationKeyBinding",
      "Status": "ACTIVE",
      "Crypto Token": "PeerToken",
      "Key Pair Alias": "peerkey",
      "Next Key Pair Alias": null,
      "Signature Algorithm": "SHA256WithRSA",
      "Enrollment info: Key Binding SubjectDN": "CN=peer-key",
      "Enrollment info: Signing CA SubjectDN": "CN=ManagementCA,OU=SomeOrg",
      "Enrollment info: Certificate profile": "ENDUSER",
      "Enrollment info: End entity profile": "EMPTY",
      "Enrollment info: Key spec or curve": "RSA2048",
      "Trusted certificates": {},
      "Signed on behalf of CAs": {},
      "Properties": {
        "Protocol and Cipher Suite": "TLSv1.2;TLS_RSA_WITH_AES_256_CBC_SHA256"
      }
    }
  },
  "admin-roles": {
    "RA-Peer-Connection": {
      "Object Type": "Role",
      "Version": 1,
      "Name": "RA-Peer-Connection",
      "Role Members": [
        {
          "Token Type": "CertificateAuthenticationToken",
          "Issuer": "ManagementCA",
          "Match With": "WITH_COMMONNAME",
          "Match Value": "ejbcara.example.com"
        }
      ],
      "Namespace": "",
      "RA Style Id": 0,
      "Access Rules": {
        "/administrator/": "Allow",
        "/ca/": "Allow",
        "/ca_functionality/create_certificate/": "Allow",
        "/ca_functionality/use_approval_request_id/": "Allow",
        "/ca_functionality/use_username/": "Allow",
        "/ca_functionality/view_ca/": "Allow",
        "/ca_functionality/view_certificate/": "Allow",
        "/endentityprofilesrules/": "Allow",
        "/endentityprofilesrules/EMPTY/": "Deny",
        "/protocol/acme/": "Allow",
        "/protocol/cmp/": "Allow",
        "/protocol/est/": "Allow",
        "/protocol/rest/": "Allow",
        "/protocol/scep/": "Allow",
        "/protocol/web_services/": "Allow",
        "/ra_functionality/approve_end_entity/": "Allow",
        "/ra_functionality/create_end_entity/": "Allow",
        "/ra_functionality/delete_end_entity/": "Allow",
        "/ra_functionality/edit_end_entity/": "Allow",
        "/ra_functionality/revoke_end_entity/": "Allow",
        "/ra_functionality/view_approvals/": "Allow",
        "/ra_functionality/view_end_entity/": "Allow",
        "/ra_functionality/view_end_entity_history/": "Allow",
        "/ra_functionality/view_end_entity_profiles/": "Allow",
        "/ra_master/invoke_api/": "Allow"
      }
    }
  }
}

Step 3 - Verify the setup

To verify the EJBCA RA setup, refer to instructions in Deploy RA and VA in Kubernetes.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.