TR-069 Per-Device Unique Credentials — Software Design Document

Table of Contents

1. Overview

1.1. Purpose

This document describes the design and implementation of the per-device unique credentials feature (DEV-1194) for TR-069 devices managed by the Friendly Technologies ACS.

This feature applies exclusively to TR-069 (CWMP) devices. Other device management protocols (MQTT, USP, LWM2M) are not affected.

1.2. Problem Statement

In TR-069, the ACS communicates with CPE devices using two sets of credentials:

  • Management Server (MS) credentials — username/password used by the TR-069 device to authenticate its HTTP Inform requests to the ACS. Configured in the cpe_login table and shared across all devices in the same login group.

  • Connection Request (CR) credentials — username/password used by the ACS to authenticate a Connection Request push to the TR-069 device. Configured in the device profile and shared across all devices in the same profile.

Because these credentials are shared within a group or profile, any device that obtains them can impersonate another device during HTTP authentication, and any party with knowledge of the CR credentials can initiate unauthorized connection requests to any device in the same group or profile.

For TR-069 deployments that require stronger device identity isolation, the shared credential model is insufficient.

1.3. Solution Summary

The system can now generate a unique username/password pair for each individual TR-069 device for:

  • Management Server authentication — used by the TR-069 device when it sends Inform requests to the ACS over HTTP

  • Connection Request authentication — used by the ACS when it initiates a TR-069 Connection Request push to the device

The feature is opt-in, configured per cpe_login group. Credentials are generated on first TR-069 contact, sent to the device via SetParameterValues, and considered active only after the device confirms receipt via SetParameterValuesResponse. Until confirmation, the shared credentials from cpe_login (MS) and profile (CR) remain valid as fallback.

2. Architecture

2.1. Component Overview

This feature is implemented entirely within the TR-069 stack. All credential generation, confirmation, and enforcement logic is specific to the TR-069 (CWMP) protocol.

cpe-credentials-components

2.2. Key Classes

cpe-credentials-classes

3. Data Model

3.1. Database Schema

cpe-credentials-schema

3.2. Table Descriptions

3.2.1. cpe_login (modified)

Two boolean columns were added:

Column Default Description

generate_management_server_credentials

false

When true, unique MS username/password are generated and provisioned to every device using this login group.

generate_connection_request_credentials

false

When true, unique CR username/password are generated and used by ACS when initiating Connection Requests to devices in this login group.

3.2.2. cpe_credentials

One record per device (identified by serial + group_id). Created on first device Inform after the feature is enabled.

Column Nullable Description

id

No

Primary key.

serial

No

Device serial number.

group_id

No

Login group ID from cpe_login. Together with serial forms the unique key.

cpe_id

Yes

Foreign key to cpe table. Set at record creation time from the device’s ID. Becomes NULL when the device is deleted from ACS (at the same time cpe_deleted_at is populated). Returns to a non-NULL value if the deleted device re-registers — a new cpe record is created and cpe_id is updated accordingly.

isp_id

No

ISP identifier. Used by the retention policy cleanup job.

original_login

No

The cpe_login.login value at the time the record was created. Used as a stable reference to the owning cpe_login entry on every subsequent device interaction. On each Inform and on each SetParameterValuesResponse, the system loads the CpeLogin entity via original_login and reads the current values of generate_management_server_credentials and generate_connection_request_credentials to decide whether to confirm, reset, or delete the credentials. This ensures that any change an administrator makes to those flags is detected and acted upon correctly.

management_server_username / management_server_password

Yes

Unique encrypted MS credentials. Both either set or NULL. Set to non-NULL on Inform, if generate_management_server_credentials = true.

connection_request_username / connection_request_password

Yes

Unique encrypted CR credentials. Both either set or NULL. Set to non-NULL on Inform, if generate_connection_request_credentials = true.

ms_confirmed

No

Becomes true after the device confirms receipt of MS credentials via SetParameterValuesResponse. Until then, fallback credentials from cpe_login are used for authentication. Not reset when the device is deleted from ACS — the confirmed state is preserved so the device can authenticate with its unique credentials if it re-registers without a factory reset.

cr_confirmed

No

Becomes true after the device confirms receipt of CR credentials via SetParameterValuesResponse. Until then, fallback credentials from the profile/provision are used for push. Not reset when the device is deleted from ACS — the confirmed state is preserved so unique CR credentials remain active if the device re-registers without a factory reset.

cpe_deleted_at

Yes

Populated when the associated CPE device is deleted. Used by the retention policy cleanup job to determine when the credential record itself can be removed. Becomes NULL on device re-registration.

3.2.3. cpe_credentials_retention_policy

Defines how long credential records are kept after the associated device is deleted.

Column Default Description

isp_id

ISP identifier.

value

30

Retention period in days. After this period, credential records for deleted devices are purged by the cleanup job.

Default row (isp_id=0, value=30) is inserted during migration and serves as a global fallback.

4. Configuration

4.1. Feature Toggle per Login Group (cpe_login)

The feature is enabled/disabled at the cpe_login level via two independent flags:

Flag Effect when enabled (true)

generate_management_server_credentials

ACS generates unique MS username/password for each device in this login group and sends them via SPV. Authentication switches to unique credentials once ms_confirmed = true.

generate_connection_request_credentials

ACS generates unique CR username/password for each device in this login group and sends them via SPV. Connection Request push switches to unique credentials once cr_confirmed = true.

Both flags are independent: you can enable/disable MS-only, CR-only, or both.

Settings on UI: Settings → Protocols → TR-069 → selected Login.

An example:

image1
When generate_management_server_credentials is enabled for a login group, the ACS configuration parameter useCpeSerialAsLogin is ignored for devices in that group. useCpeSerialAsLogin requires each device to present its serial number as the HTTP authentication username, but unique MS credentials use a generated username in the format {OUI}-{RANDOM}-{SERIAL} — not the serial alone. Since the two mechanisms are mutually exclusive, useCpeSerialAsLogin takes no effect while generate_management_server_credentials is active.

4.2. Credential Length Parameters (DMConfigurationParameter)

The length of the randomly generated part of the credential value is configurable (Settings → System Settings → ACS Settings page):

Parameter Default Allowed Range Description

credentialMinLength

7

7 to credentialMaxLength - 1

Minimum length of the random part. If the configured value is out of range, the default (7) is used.

credentialMaxLength

180

credentialMinLength + 1 to 180

Maximum length of the random part. If the configured value is out of range, the default (180) is used.

The actual random part length is chosen uniformly at random in the range [credentialMinLength, credentialMaxLength] on each credential generation.

If these parameters have invalid values, default ones will be used.

4.3. Credential Format

The full credential value follows this pattern:

{OUI}-{RANDOM_PART}-{SERIAL}

Where:

  • {OUI} — device OUI identifier

  • {RANDOM_PART} — random string of length between credentialMinLength and credentialMaxLength, drawn from:

    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#%^*()-_=+[]{}|;.?/~
    The $ character is intentionally excluded from the charset due to a known limitation in the TR-069 device emulator.
  • {SERIAL} — device serial number

Credentials are DES-encrypted before being stored in the database.

4.4. Retention Policy

The cleanup job (FTCpeCredentialsDeleteTaskJob) runs on a Quartz schedule and deletes credential records for already-deleted CPE devices. Domain-specific setting set on Settings → System Settings → Interface page:

image2

The resolution order for the retention period is:

  1. ISP-specific entry in cpe_credentials_retention_policy table for the device’s isp_id

  2. Parent ISP entry (traversing the ISP hierarchy using dot-notation)

  3. Global default entry (isp_id = 0, value = 30 days)

5. Business Logic

5.1. Credential Provisioning Flow

Triggered on every device Inform via CpeCredentialsAop → CpeCredentialsService.provisionCredentials().

cpe-credentials-provisioning

5.2. Profile Task Credential Parameter Exclusion

When a profile SetParameterValues task is being built for a device, ProfileParameterProcessor.processTaskCreating() filters credential parameters (MS username/password, CR username/password) out of the profile parameter list under two conditions:

  1. Device already has unique credentials — a cpe_credentials record exists with a non-null managementServerUsername (for MS params) or connectionRequestUsername (for CR params). The profile parameter for that credential type is excluded, preventing the profile from overwriting the unique value already stored for the device.

  2. Device does not yet have unique credentials, but its CpeLogin is configured to generate them — the cpe_login.generate_management_server_credentials or generate_connection_request_credentials flag is enabled. The corresponding credential parameters are excluded even though no cpe_credentials record exists yet, because unique credentials will be generated and sent to the device on first contact.

handleSetParameterValuesProfileResponse() (see Profile SPV Response (handleSetParameterValuesProfileResponse())) continues to run after every profile SetParameterValuesResponse as a safety net: if credential parameters reach the device despite the exclusion due to some issue, the unique credentials are immediately re-sent upon device confirmation.

5.3. Credential Confirmation Flow

CpeCredentialsAop.afterSPVResponse() intercepts every SetParameterValuesResponse and routes it based on task type:

  • Provision SPV (SetParameterValuesProvision) → confirmCredentialsSent() — confirms or clears unique credentials depending on current flag state.

  • Profile SPV (SetParameterValuesProfile) → handleSetParameterValuesProfileResponse() — re-sends unique credentials if the profile overwrote them.

  • All other SPV task types are ignored by CpeCredentialsAop.

5.3.1. Provision SPV Response (confirmCredentialsSent())

Triggered when a device acknowledges a provision SetParameterValues that carried unique MS/CR credentials.

cpe-credentials-confirmation
Confirmation is performed on SetParameterValuesResponse, not on the first authentication with new credentials. This eliminates the timing window that would exist if confirmation happened on authentication, which could occur during a push initiated with old credentials.

5.3.2. Profile SPV Response (handleSetParameterValuesProfileResponse())

Triggered when a device acknowledges a profile SetParameterValues. Under normal conditions, credential parameters are excluded from profile tasks before they are sent (see Profile Task Credential Parameter Exclusion), so this method will typically find no credential parameters in the task and return early. It acts as a safety net: if credential parameters do reach the device despite the exclusion, ACS detects this on SetParameterValuesResponse and immediately re-sends the unique credentials to restore them, resetting the confirmed flags until the device re-confirms.

cpe-credentials-profile-response
Profile and provision are treated differently by design. Profile changes are automatically "healed" — ACS detects that the profile overwrote unique credentials and immediately re-sends them. Provision changes are intentional and adopted as the new unique values (handled in confirmCredentialsSent(), see Scenario B in Interaction with cpe_provision and Profile CR Credentials).

5.4. Authentication Flow (Management Server)

When a device sends 0 BOOTSTRAP (factory reset), ACS always falls back to shared cpe_login credentials regardless of whether unique MS credentials exist and are confirmed. This ensures the device can authenticate immediately after a reset, before the ACS has a chance to re-send and the device re-confirm the unique credentials.

For all other events in Inform, ACS looks up cpe_credentials by device identity (serial, manufacturer, product class, protocol). This lookup works regardless of whether the device currently exists in ACS — a deleted device with cpe_id = NULL is found by the same query. If ms_confirmed = true, ACS validates the request against the unique MS credentials stored in that record. If no such record exists, or if the credentials have not yet been confirmed, authentication falls back to the shared cpe_login credentials.

cpe-credentials-auth

5.5. Connection Request Push Flow

When initiating a Connection Request push to a device, ACS resolves the CR credentials to use as follows:

  • If a cpe_credentials record exists for the device and cr_confirmed = true, ACS uses the unique CR credentials stored in that record.

  • Otherwise — if no record exists, or the credentials have not yet been confirmed — ACS falls back to the default CR credentials from the device profile or provision.

cpe-credentials-push

5.6. Credential Cleanup Flow

When a device is deleted from ACS, its cpe_credentials record is not removed immediately — instead, cpe_deleted_at is set to the deletion timestamp and the record is retained for a configurable period. This allows the device to re-register without losing its credentials if it comes back online within the retention window.

A scheduled Quartz job (FTCpeCredentialsDeleteTaskJob) periodically removes records for deleted devices that have exceeded the retention period. The job runs on the schedule defined by the autoDeleteCron ACS configuration parameter (default: 0 0 2 * * ? — every day at 02:00). The retention period is resolved per ISP: the job first checks for an ISP-specific entry in cpe_credentials_retention_policy, then traverses the ISP hierarchy, and finally falls back to the global default of 30 days. If the resolved retention period is 0, cleanup is disabled for that ISP and its credential records are never automatically removed.

cpe-credentials-cleanup

5.7. Bootstrap Behavior

When a device sends 0 BOOTSTRAP (factory reset), the confirmed flags are reset to false:

  • ms_confirmedfalse

  • cr_confirmedfalse

The credential values themselves are not regenerated — the same unique credentials are sent to the device again via SetParameterValues. This means the device will reauthenticate with cpe_login credentials until the ACS resends and the device re-confirms the unique credentials.

If a device with an existing cpe_credentials record send Inform with 0 BOOTSTRAP through an ACS endpoint that does not require HTTP authentication, the record is permanently deleted.

5.8. Device Re-registration After Deletion

When a device is deleted from ACS, cpe_id is set to NULL and cpe_deleted_at is populated, but ms_confirmed and cr_confirmed are intentionally preserved. This allows the device to re-register and authenticate using its unique credentials without going through a factory reset.

If the deleted device re-registers without 0 BOOTSTRAP (e.g., Periodic Inform):

  • ACS looks up cpe_credentials by device identity (serial, manufacturer, product class, protocol). The record is found even though cpe_id = NULL.

  • If ms_confirmed = true, ACS authenticates the request using the stored unique MS credentials. If the device sends cpe_login credentials in this case, its authenitcation will fail.

  • cpe_id is updated from NULL to the new device ID; cpe_deleted_at is cleared.

  • Credentials are not re-sent — the device already holds them and has previously confirmed receipt.

If the deleted device re-registers with 0 BOOTSTRAP (factory reset), normal Bootstrap handling applies: ms_confirmed and cr_confirmed are reset to false, and the unique credentials are re-sent via SetParameterValues. See Bootstrap Behavior for details.

5.9. Interaction with cpe_provision and Profile CR Credentials

The behavior of unique CR credentials when other CR credential sources exist depends on the order of operations.

5.9.1. Priority Rules Summary

CR Credential Source Condition Result

Unique (cpe_credentials)

crConfirmed = true, no cpe_provision CR change after

Used for push. Profile values will be overwritten.

cpe_provision

Added before unique credentials were enabled

Unique credentials are generated later and sent to the device. Once confirmed, they take precedence.

cpe_provision

Added after unique credentials are already confirmed

Provision values are sent to the device and, upon confirmation, stored in cpe_credentials — they become the new unique credentials.

Profile

Profile is applied and unique credentials are managed for the device — either a cpe_credentials record exists with a non-null username, or the device’s cpe_login has the corresponding generation flag enabled

Credential parameters are excluded from the profile task before it is created. The device never receives them as part of the profile. handleSetParameterValuesProfileResponse() acts as a safety net in edge cases.

5.9.2. Scenario A: cpe_provision was configured before unique credentials were enabled

  1. Device has CR credentials in cpe_provision.

  2. Administrator enables generate_connection_request_credentials = true on the login group.

  3. On the next device Inform, CpeCredentialsService.provisionCredentials() generates new unique CR credentials and schedules a SetParameterValues task.

  4. The device receives and confirms the unique credentials via SetParameterValuesResponse.

  5. Result: cpe_credentials.connectionRequestUsername/Password holds the unique values; cr_confirmed = true. The cpe_provision CR values are no longer used for Connection Request push.

5.9.3. Scenario B: cpe_provision CR credentials are added after unique credentials are already confirmed

  1. Device already has confirmed unique CR credentials (cr_confirmed = true).

  2. A new cpe_provision entry is added (or updated) with CR username/password values for this device.

  3. ACS sends a SetParameterValues with the provision CR parameters to the device.

  4. Device acknowledges the SPV with SetParameterValuesResponse.

  5. CpeCredentialsService.confirmCredentialsSent() detects CR parameters in the task and reads their values from cpe_provision.

  6. The provision values are decrypted and re-encrypted into cpe_credentials.connectionRequestUsername/Password.

  7. Result: the provision CR values are now stored in cpe_credentials and become the active unique credentials; cr_confirmed = true.

In Scenario B the provision values "win" because they arrive after the unique credentials and the device confirms them. The cpe_credentials record is updated to reflect the current state of the device — whatever CR credentials the device last confirmed are always stored in cpe_credentials.

5.9.4. Scenario C: Profile is applied while unique credentials are managed for the device

ProfileParameterProcessor excludes credential parameters from the profile task in two situations.

Sub-scenario C1: Unique credentials already exist

  1. Device already has a cpe_credentials record (MS and/or CR credentials generated).

  2. ACS is about to send a profile SetParameterValues that includes credential parameters.

  3. ProfileParameterProcessor.processTaskCreating() loads the cpe_credentials record; isUniqueCredentialParameter() detects that the corresponding username is non-null and excludes the parameter from the task.

  4. Device confirms the profile SPV. CpeCredentialsService.handleSetParameterValuesProfileResponse() is triggered but finds no credential parameters in the task and returns early.

  5. Result: the profile is applied on the device without touching the unique credentials. cr_confirmed remains true.

Sub-scenario C2: Unique credentials not yet created, but CpeLogin has generation enabled

  1. Device’s cpe_login has generate_management_server_credentials=true and/or generate_connection_request_credentials=true, but the device has not yet connected — no cpe_credentials record exists.

  2. ACS builds a profile SetParameterValues task for the device.

  3. ProfileParameterProcessor.processTaskCreating() finds no cpe_credentials record, but resolves the CpeLogin via the active device session store; isUniqueCredentialParameter() detects the generation flags are enabled and excludes the corresponding parameters.

  4. When the device eventually connects, provisionCredentials() generates and sends the unique credentials.

  5. Result: the profile does not pre-configure credential parameters that will be auto-generated..

If credential parameters reach the device despite the exclusion due to some issue, handleSetParameterValuesProfileResponse() detects them on SetParameterValuesResponse, resets the confirmed flag(s), and immediately re-sends the unique credentials to restore them.
Profile and cpe_provision are treated differently. Profile credential parameters are proactively excluded when unique credentials are managed; cpe_provision changes are intentional and adopted as the new unique values.

5.10. Disabling the Feature After Activation

5.10.1. Both flags false from the start

If both generate_management_server_credentials and generate_connection_request_credentials are false on a cpe_login, the feature is entirely inactive for that login group:

  • CpeCredentialsService.provisionCredentials() is called on every Inform, but the generateMS=true OR generateCR=true condition is not met — no credentials are generated, no cpe_credentials record is created, and no SetParameterValues task is scheduled.

  • All devices in the group authenticate with shared cpe_login credentials and receive Connection Request pushes using profile CR credentials, exactly as before the feature existed.

5.10.2. Flag disabled after credentials were generated but before confirmation

If a flag is disabled after a cpe_credentials record has been created (credentials generated and a SetParameterValues task scheduled) but before the device responds with SetParameterValuesResponse:

  • The cpe_credentials record remains in the database with ms_confirmed=false (and/or cr_confirmed=false).

  • On the next Inform, provisionCredentials() sees the flag is now false and does not schedule a new SPV — the pending credentials are left as-is.

  • When the device eventually responds with SetParameterValuesResponse, confirmCredentialsSent() reads the current flag value, detects it is false, and clears the corresponding credential columns (NULL) and resets the confirmed flag.

  • If both MS and CR become NULL as a result, the entire cpe_credentials record is deleted.

  • Until that cleanup happens, the record sits in the database with ms_confirmed=false; this has no functional impact because ACS only switches to unique credentials once the confirmed flag is true.

5.10.3. Flag disabled after credentials were confirmed

If an administrator disables the generate_management_server_credentials or generate_connection_request_credentials flag on a cpe_login after credentials have already been provisioned and confirmed:

  • On the next SetParameterValuesResponse for that device, CpeCredentialsService.confirmCredentialsSent() detects the flag is now disabled.

  • The corresponding credential columns are cleared (NULL) and the confirmed flag is reset.

  • If both MS and CR credentials are now NULL, the entire cpe_credentials record is deleted.

  • The device falls back to shared cpe_login credentials.

There is a window between disabling the flag and the next SetParameterValuesResponse during which the cpe_credentials record still exists with ms_confirmed / cr_confirmed = true. During this window, ACS continues to use the unique credentials — MS authentication validates against them and Connection Request pushes use them — exactly as if the flag were still enabled. The credentials are cleared only after the next SetParameterValuesResponse triggers confirmCredentialsSent() and detects the flag is now disabled.

When the device sends a 0 BOOTSTRAP the corresponding credentials are cleared (see the bootstrap handling in Credential Provisioning Flow for details).

6. Support Guide

6.1. How to Enable Unique Credentials for a Device Group

  1. In the ACS management UI, navigate to the login group configuration (cpe_login).

  2. Enable Generate Management Server Credentials and/or Generate Connection Request Credentials.

  3. On the next Inform from a device in this group, unique credentials will be generated and sent to the device.

The transition is seamless — devices continue to authenticate with shared credentials until they confirm the new unique ones.

6.2. Understanding the Confirmation Window

Between the moment unique credentials are sent and the device confirms them:

  • The device is still using the old shared credentials from cpe_login.

  • ACS accepts both: if ms_confirmed = false, it falls back to cpe_login credentials automatically.

  • Once the device ACKs SetParameterValues (SPV response), ms_confirmed is set to true and only the unique credentials are accepted.

6.3. What Happens on Factory Reset

When a device is factory-reset:

  1. Device sends Inform with event code 0 BOOTSTRAP.

  2. ACS resets ms_confirmed = false and cr_confirmed = false for that device.

  3. ACS sends the same unique credentials again via SetParameterValues.

  4. Device authenticates with shared cpe_login credentials until it re-confirms the unique ones.

The device goes through the same confirmation cycle as on first enrollment.

If the device sends 0 BOOTSTRAP through an ACS endpoint that does not require HTTP authentication, its unique credentials are permanently deleted.
If a deleted device reconnects with a regular Periodic Inform (no factory reset), it is authenticated using its still-confirmed unique credentials, cpe_id is restored, and the credentials are not re-sent. See Device Re-registration After Deletion for the full re-registration flow.

6.4. Credential Storage Security

Credential values in cpe_credentials are DES-encrypted. They are never stored in plain text in the database. Decryption happens in memory only during authentication or push operations.

6.5. Retention Policy After Device Deletion

6.5.1. Main logic

When a device is deleted from ACS:

  1. Its cpe_credentials record is not immediately removed.

  2. The cpe_deleted_at column is set to the deletion timestamp.

  3. A scheduled Quartz job runs periodically and removes credential records older than the configured retention period.

  4. The default retention is 30 days (configurable per ISP in cpe_credentials_retention_policy).

This retention window ensures that if a deleted device unexpectedly comes back online, its credentials are still available for a reasonable period.

6.5.2. ISP Synchronization on Deletion

Before the credential record is soft-deleted, cpe_credentials.isp_id is updated to match the location_id of the device at the moment of deletion. This step is necessary when ispMode=1 (Multi-Domain mode) and the operator has manually moved the device to a different domain after the credential record was first created. In that case cpe_credentials.isp_id may still hold the old domain value, so the update ensures the retention policy is resolved against the domain the device actually belonged to when it was deleted — not the domain it was originally enrolled in.

Without this synchronization, the scheduled job would apply the wrong domain’s retention period (or fall back to the default), potentially deleting credentials too early or too late relative to the operator’s intent.

7. Database Migration Reference

Migration file: changelog-6.5.1.DEV-1194.xml

Change Set Description

v6.5.1.DEV-1194-1

Adds generate_management_server_credentials and generate_connection_request_credentials columns to cpe_login (both TINYINT(1), default 0).

v6.5.1.DEV-1194-2

Creates the cpe_credentials table with unique constraint (serial, group_id).

v6.5.1.DEV-1194-3

Oracle only: creates sequence CPE_CREDENTIALS_0.

v6.5.1.DEV-1194-4

Creates cpe_credentials_retention_policy table with default row (isp_id=0, value=30).

v6.5.1.DEV-1194-5

Oracle only: creates sequence CPE_CREDENTIALS_RETENTION_POLICY_0.

v6.5.1.DEV-1194-6

Adds performance indexes: idx_cpe_credentials_cpe_id and idx_cpe_credentials_isp_id_deleted_at.