# Upgrading from rc.12 to rc.13

This page lists what you must change, and what behaves differently, when you move a HelixIAM install from
`v1.0.0-rc.12` to `v1.0.0-rc.13`. The source is the `v1.0.0-rc.13` release notes and upgrade notes.

!!! warning "Security release: everyone on rc.12 or earlier should upgrade"
    rc.13 fixes a SAML assertion replay, a privacy problem with the BSN (Dutch citizen service number), per-replica
    rate limits and a realm that could not be disabled. See [the security fixes](#7-security-fixes-in-this-release).
    The core is also relicensed: see [the licence change](#6-licence-change).

## Before you upgrade: checklist

| # | Do this | Applies if |
| --- | --- | --- |
| 1 | Upgrade Helm with [`--reset-then-reuse-values`](#1-helm-use-reset-then-reuse-values) (Helm 3.14 or later) | you deploy with Helm |
| 2 | Run the [query for disabled realms](#2-realms-with-enabledfalse) | always |
| 3 | Set [`DB_ENCRYPTION`](#3-db_encryption-is-required-for-the-bsn-migration-and-digid) | you use DigiD or eIDAS sign-in, or want the BSN migration to run |
| 4 | Opt relying parties that used `preferred_username` as the BSN in to the [`bsn` claim](#4-the-bsn-migration-and-changed-usernames) | such relying parties exist |
| 5 | Plan for [flows in progress](#5-flyway-v87-v88-and-v89-and-flows-in-progress) being lost | always |
| 6 | Read the [licence change](#6-licence-change) | always |

Back up the database first, as for every upgrade, and keep `DB_ENCRYPTION` with the backup. BSNs remain in older
backups and external log stores until those expire.

---

## 1. Helm: use `--reset-then-reuse-values`

**What changed.** The chart refuses to render when a values section is missing, rather than drop defaults that are on
(such as data retention).

**What you must do.** Upgrade with `--reset-then-reuse-values` (Helm 3.14 or later), not `--reuse-values`:

```bash
helm upgrade helixiam deploy/helm/helixiam --reset-then-reuse-values --set image.tag=v1.0.0-rc.13
```

It keeps the values you set and adds the defaults of the sections the new chart introduced. With `--reuse-values`
those sections are missing and the chart stops with `values section "..." is missing`.

## 2. Realms with `enabled=false`

**What changed.** Disabling a realm now takes effect. Before, a realm with `enabled=false` still signed users in. Now
it refuses the authorization endpoint, sign-in and registration pages, the SAML IdP, the account console and token
issuance. Access tokens issued before stay valid until they expire. The master realm cannot be disabled.

**What you must do.** Before upgrading, check that no realm you use has `enabled=false`. Such a realm stops signing
anyone in:

```sql
SELECT realm_id FROM realm_config WHERE NOT enabled;
```

Switch the realms the query lists back on, or accept that they stop. The admin API stays reachable, so a realm-admin
can switch a realm back on afterwards. A `PUT /admin/realms/{r}/settings` that omits `enabled` now keeps the current
state.

## 3. `DB_ENCRYPTION` is required for the BSN migration and DigiD

**What changed.** The BSN is now stored encrypted with `DB_ENCRYPTION` (AES-GCM, like the TOTP secrets), and the
federated link is keyed on an HMAC with a per-realm pepper.

**What you must do.** Set `DB_ENCRYPTION` if it is not set. Outside the dev profile, a realm whose pepper cannot be
created is skipped with an ERROR and retried at the next start, and **DigiD sign-in does not work** until the key is
set.

## 4. The BSN migration and changed usernames

**What changed.** A DigiD sign-in used to store the BSN unencrypted as the account's username and federated link key,
and so released it to every application through `preferred_username`. On the first start of rc.13, a one-off,
idempotent migration runs per realm (under a PostgreSQL advisory lock, one replica at a time, never blocking start-up):

- The BSN moves to the encrypted `user_bsn` table, per realm and user, only when the link's provider is
  BSN-authoritative (DigiD, eIDAS with a Dutch PersonIdentifier, or a provider a realm-admin marked
  `bsnAuthoritative`). Otherwise it is only scrubbed, and `BSN_MIGRATION_SKIPPED` is audited.
- **Usernames of DigiD accounts change.** A username that contained the BSN is replaced by `{alias}-{random}`. A
  BSN-shaped username that no BSN-authoritative link vouches for is replaced by `user-{random}`: such a password user
  signs in with their e-mail address or gets a new username from an administrator.
- Profile attributes that contain the BSN are deleted, and audit rows that quote it get `[bsn]`. A `BSN_MIGRATION`
  event (counts only) is audited per realm.
- Citizens keep their accounts: a sign-in that finds a link under its old raw form re-keys it.

**What you must do.** `preferred_username` never carries a BSN any more. A relying party that used it as the BSN must be
opted in to the `bsn` claim by a realm-admin, with a legal basis. The BSN is then released in the userinfo response
only (never inside a token), or as the SAML attribute `urn:nl-eid-gdi:1.0:id:BSN`:

```
PUT /admin/realms/{r}/bsn-release   {"protocol": "oidc|saml", "clientId": "...", "enabled": true, "legalBasis": "..."}
```

In the console, use **Client → Advanced** or **SAML client → NameID & attributes**. The default is never.

## 5. Flyway V87, V88 and V89, and flows in progress

**What changed.** rc.13 adds three migrations. They
are applied on start-up, and `schema.sql` has the same tables:

| Migration | Adds |
| --- | --- |
| V87 | `flow_state` and `rate_limit_bucket` (both empty; no data migration). With Redis sessions they stay empty and the state lives under the Redis keys `helix:flow:*` and `helix:rl:*` |
| V88 | `identity_provider_mapper`, `idp_mapper_role_grant` and `saml_attribute_mapper` (additive: existing providers and SAML SPs behave as before until a mapper is added) |
| V89 | `user_bsn`, `bsn_release` and `privacy_migration`, plus `federated_link.provider_instance_id` (backfilled) |

**What you must do.** Nothing for the schema. Push, QR, transaction-signing, enrolment and CIBA flows in progress
during the upgrade are lost (they were in memory); users start them again. Rate-limit budgets start fresh. A custom
`PushApprovalStore`, `QrSessionStore`, `TransactionSigningStore` or `DeviceEnrollmentTicketStore` bean must implement
the new `replace` method.

## 6. Licence change

**What changed.** The licence terms changed with this release.

**What you must do.** Read [Licensing](../licensing.md).

## 7. Security fixes in this release

Affected: `v1.0.0-rc.12` and earlier. No CVSS vector or CVE identifier has been assigned yet.

1. **SAML assertion replay** inside the clock-skew window, and across replicas. An assertion ID is now kept until
   `NotOnOrAfter` plus skew plus a margin, and the cache is shared across replicas.
2. **BSN stored in plaintext and released to applications.** Now encrypted, masked in the console and released only on
   an audited opt-in (see section 4).
3. **Impersonation borrowed the administrator's sign-in** (auth time and `acr`). An impersonation now has its own auth
   time and no `acr`.
4. **Rate limits and multi-step flows were per replica.** They are now shared across replicas.
5. **Disabling a realm had no effect.** It now refuses sign-in (see section 2).

Until you can upgrade: run a single replica, do not connect DigiD or eIDAS providers to realms whose applications must
not receive the BSN, and do not grant impersonation rights.
