> ## Documentation Index
> Fetch the complete documentation index at: https://docs.safeonlineexam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SEB Config Certificate: Generation, Rotation, and Trust

> Generate the X.509 identity that encrypts Safe Online Exam .seb files, deploy it to clients, rotate it safely, and review the trust model and fallback.

Safe Online Exam encrypts generated `.seb` configuration files to a configured public X.509 certificate by default. The service holds only the public certificate; the matching private identity is installed exclusively on approved client devices. This page covers the trust model, generating the identity, configuring the service, deploying the private identity to clients, pre-assessment validation, and the full rotation procedure. It also describes the `SEB_CONFIG_ENCRYPTION_ENABLED=false` compatibility mode and its security trade-offs.

This identity is not the service's HTTPS certificate and is not the LTI JWK. It exists only to let approved SEB clients decrypt generated configuration files and is completely separate from Config Key proof, which protects access-code release after SEB opens the configuration.

## Trust Model

Each component holds different material and has strict boundaries on what it must never hold:

| Component                                   | Holds                                                            | Must not hold                                                          |
| ------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Application runtime                         | Public X.509 certificate or permitted local public-key fallback  | Private key, `.p12`, client identity passphrase                        |
| Secret Manager runtime secret               | Public certificate PEM                                           | Private key or `.p12`                                                  |
| Device-management system / restricted vault | Private identity and its protection material                     | Broad user, instructor, or runtime access                              |
| Approved SEB client                         | Non-extractable, SEB-restricted private identity where supported | An exportable identity available to a student account or unrelated app |

Encryption prevents an unapproved device from opening the configuration. Config Key proof prevents an access code from being released when the running configuration does not match current server settings. Use both controls whenever the instance needs device-restricted configurations.

## Generate an Identity

The repository generator writes private artifacts under the `.local/` directory, which is excluded from version control. Create a protected passphrase file rather than putting the passphrase in a command argument or environment variable:

```bash theme={null}
umask 077
mkdir -p .local
openssl rand -base64 48 > .local/seb-cert-p12-password

SEB_CERT_NAME=seb-config-encryption \
SEB_CERT_SUBJECT="/CN=Safe Online Exam Configuration Encryption/O=Organization" \
bash scripts/generate-seb-config-cert.sh \
  .local/seb-certs \
  .local/seb-cert-p12-password
```

### Output Files

The generator produces four files in the `.local/seb-certs/` directory:

| File                            | Purpose                                                 | Where it goes                                                      |
| ------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------ |
| `seb-config-encryption.crt.pem` | Public certificate in PEM format                        | Upload to Secret Manager or mount as a file secret for the service |
| `seb-config-encryption.cer`     | Public certificate in DER format                        | Optional reference copy for verification                           |
| `seb-config-encryption.key.pem` | Private key — restricted bootstrap artifact             | Move immediately to restricted vault; never upload to the service  |
| `seb-config-encryption.p12`     | Private client identity — restricted bootstrap artifact | Move to MDM/vault; deploy to approved devices only                 |

<Warning>
  Immediately move the private PEM, `.p12`, and passphrase file into approved restricted storage after generation. Remove temporary workstation copies after vault upload and client deployment are verified. Never commit, log, email, attach, or pass these artifacts through command arguments, management-policy parameters, tickets, or chat.
</Warning>

## Configure the Service

<Tabs>
  <Tab title="Google Cloud Run">
    Store the public certificate PEM in Secret Manager and inject it as the `SEB_CONFIG_ENCRYPTION_CERT_PEM` secret. The Cloud Run installer handles this automatically during `./setup.sh`. For manual management, create a new secret version containing the PEM content and update the service revision to reference the new version.

    ```bash theme={null}
    # Create a new numbered secret version from the PEM file
    gcloud secrets versions add safe_online_exam_seb_config_cert_pem \
      --data-file=.local/seb-certs/seb-config-encryption.crt.pem
    ```

    The service reads the certificate at startup and validates it before accepting traffic. Update the secret version reference in the Cloud Run service configuration and deploy a new revision to pick up a rotated certificate.
  </Tab>

  <Tab title="Docker Compose">
    Provide the public certificate as a protected runtime file and reference it through `SEB_CONFIG_ENCRYPTION_CERT_PATH` in the environment. Copy the PEM to the secrets directory with restricted permissions:

    ```bash theme={null}
    cp .local/seb-certs/seb-config-encryption.crt.pem \
      /srv/safe-online-exam/secrets/seb_config_encryption_cert.pem
    chmod 600 /srv/safe-online-exam/secrets/seb_config_encryption_cert.pem
    ```

    In the environment file:

    ```text theme={null}
    SEB_CONFIG_ENCRYPTION_ENABLED=true
    SEB_CONFIG_ENCRYPTION_CERT_PATH=/run/secrets/seb_config_encryption_cert.pem
    ```

    The bundle's Compose topology mounts the secrets directory into the container at `/run/secrets/`. Recreate the application container after updating the certificate file.
  </Tab>
</Tabs>

### Certificate Validation Requirements

<Note>
  When `SEB_CONFIG_ENCRYPTION_ENABLED` is unset or `true`, the service validates the X.509 certificate at startup in hardened runtimes and again when it creates each configuration download. The certificate must satisfy all of the following:

  * A currently valid end-entity certificate (not expired, not a CA certificate).
  * An RSA public key.
  * Key Usage that permits key encipherment or data encipherment.
  * A complete PEM encoding with correct line breaks preserved.

  A public-key-only input is a local-development compatibility path and is not accepted as the production trust identity.
</Note>

The configured public certificate is also available for external verification at:

```text theme={null}
${TOOL_URL}/seb/config-encryption-certificate.pem
${TOOL_URL}/seb/config-encryption-certificate.cer
```

These endpoints never serve private material. Their `x-seb-public-key-hash` response header can be compared with the client identity during rollout checks.

## Deploy the Private Identity to Clients

Use your device-management platform's certificate or profile mechanism. A well-formed client deployment:

1. Installs the PKCS#12 identity into the intended device or user scope.
2. Marks the private key non-extractable where the platform supports it.
3. Restricts private-key use to the approved SEB application identity rather than all applications.
4. Prevents profile removal by an ordinary student account when platform policy supports it.
5. Scopes the profile to a test group first, then to approved assessment devices after validation.

<AccordionGroup>
  <Accordion title="Any MDM: Staged-file installer">
    For an MDM-neutral fallback, releases include `install-seb-config-identity-user-keychain.sh`. Use it only when the MDM can stage the P12 and passphrase in root-owned, mode-0600 files, then run the script as root after the intended user has logged in:

    ```bash theme={null}
    sudo bash ./install-seb-config-identity-user-keychain.sh \
      --p12 /root-only/path/seb-config-encryption.p12 \
      --password-file /root-only/path/seb-config-encryption-password \
      --fingerprint SHA256_HEX
    ```

    The installer validates the P12 fingerprint and private-key match, validates the approved SEB bundle and Team ID, and performs `security import` in the active user's GUI security session. Exit code 75 means a user session, login keychain, SEB installation, or keychain interaction is not ready; retry after that prerequisite is available.

    Do not pass private material, passphrases, or login-keychain passwords as MDM parameters.
  </Accordion>

  <Accordion title="Jamf School: Signed package fallback">
    If Jamf School cannot deliver a PKCS#12 payload to the required user keychain, build a signed package fallback on a secured administrator workstation:

    ```bash theme={null}
    sudo bash ./build-jamf-seb-identity-package.sh \
      --p12 /secure/path/seb-config-encryption.p12 \
      --password-file /secure/path/seb-p12-password \
      --output /secure/path/safe-online-exam-seb-identity.pkg \
      --sign "Developer ID Installer: Organization (TEAMID)"
    ```

    Upload the resulting package as an in-house macOS package. Install Safe Exam Browser first, then scope the identity package to a test device group before broader rollout.
  </Accordion>

  <Accordion title="Jamf School: Inline script fallback">
    If Jamf School policy requires a direct Bash script instead of a package, generate a one-off script locally and upload that generated file only to the restricted Jamf School Scripts area:

    ```bash theme={null}
    node ./generate-jamf-seb-identity-inline-script.mjs \
      /secure/path/seb-config-encryption.p12 \
      /secure/path/seb-p12-password \
      /secure/path/jamf-school-install-seb-identity.sh
    ```

    The generated script embeds the P12 and passphrase. Never commit it, attach it to a ticket, or give it to a student. This is a lower-assurance fallback; Jamf School role access to the script itself is equivalent to access to the identity.
  </Accordion>
</AccordionGroup>

## Pre-Assessment Validation

Before each rollout window, confirm:

1. The active application revision has encryption enabled and the expected public-certificate secret version or mounted file.
2. The public certificate endpoint responds and the `x-seb-public-key-hash` header matches the deployed identity.
3. The client profile reports installed on every intended test device.
4. On an approved test device, run the application's setup check and open the encrypted setup configuration.
5. Config Key proof succeeds after SEB starts.
6. A device without the client identity cannot open the encrypted configuration.
7. An unrelated application and an ordinary student account cannot export or use the private key.
8. The certificate remains valid through the assessment and recovery window.

## Compatibility Mode

Set `SEB_CONFIG_ENCRYPTION_ENABLED=false` only for an instance that cannot distribute the private identity to student devices. In this mode the service does not load or use certificate material, and the certificate download endpoints return `404`.

<Warning>
  `SEB_CONFIG_ENCRYPTION_ENABLED=false` is a compatibility decision, not an equivalent security posture. The downloaded configuration is no longer restricted to devices holding the client identity. A teacher-set start password still adds SEB password (`pswd`) wrapping, and Config Key proof remains required and enforced. Use this mode only when managed-client certificate distribution is genuinely not possible for the institution.
</Warning>

When both controls are configured (encryption enabled and a start password set), the service applies inner `pswd` start-password protection and then the outer certificate-encrypted `pkhs` envelope. Config Key proof is independent and remains required after SEB opens the file.

## When to Rotate

Perform routine rotation outside active assessment windows. Rotate the certificate when any of the following apply:

* The certificate is approaching its expiry date.
* The private identity is suspected compromised (pause affected assessments immediately).
* The device-management profile needs to be reissued for operational reasons.
* Institution policy requires periodic rotation.

Any change to SEB settings invalidates old configuration files. Tell students to download a fresh `.seb` file after certificate rotation or any protected policy changes.

## Rotation Procedure

<Steps>
  <Step title="Generate and secure a replacement identity">
    Run the generator script again with a new name or the same name (in a clean directory) to produce a new certificate and private identity. Secure the private artifacts immediately.
  </Step>

  <Step title="Create and test the client profile">
    Create the matching non-extractable, SEB-restricted client profile using your MDM. Deploy it to a test group and complete the full setup check before broad rollout.
  </Step>

  <Step title="Deploy the new profile to all intended clients">
    Allow an explicitly planned overlap period so devices receive the new profile before the service switches certificates. Both the old and new certificates are valid during the overlap.
  </Step>

  <Step title="Update the service with the new public certificate">
    Add the replacement public certificate to the service:

    * **Cloud Run**: create a new numbered Secret Manager version for `SEB_CONFIG_ENCRYPTION_CERT_PEM` and deploy a new revision referencing that version.
    * **Docker Compose**: replace the certificate file at `SEB_CONFIG_ENCRYPTION_CERT_PATH` and recreate the application container.

    Verify the active public-key hash at `${TOOL_URL}/seb/config-encryption-certificate.pem` and confirm it matches the new identity.
  </Step>

  <Step title="Download and verify fresh configurations">
    After the service switches to the new certificate, require fresh `.seb` configuration downloads. Verify that an approved device with the new profile can open the new configuration and that Config Key proof succeeds.
  </Step>

  <Step title="Remove the old profile and revoke the old identity">
    After the overlap and recovery window closes, remove the old client profile from all devices and revoke or delete the old private material from the vault. Do not retain the old private identity longer than necessary.
  </Step>
</Steps>

## Troubleshooting

| Symptom                                                 | Check                                                                                                                                                           |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SEB cannot open a downloaded configuration              | Confirm it is a fresh download, the profile is installed in the correct scope, and the public-key hash matches the active service certificate.                  |
| A previously working device fails after rotation        | Confirm the new client profile arrived on the device before the service switched certificates, then download a fresh configuration.                             |
| The service fails startup or download creation          | Confirm encryption is enabled, the configured certificate is a currently valid X.509 certificate, and the secret or file value retains correct PEM line breaks. |
| A private key is exportable or usable by unrelated apps | Stop the rollout and correct the device-management profile. Do not weaken application restrictions as a workaround.                                             |

## Next Steps

With the certificate deployed to clients and the service configured, complete the full Canvas and SEB acceptance sequence described in the [Testing](/operations/testing) guide, including a Config Key proof verification on an approved managed device.
