Skip to content

feat(ocpp-wamp): enforce the security profile expected for each charging station #156

Open

Description

@juherr

Context

#152 (#154) adds ConnectionAuthorizer, a low-level callback deciding from a ConnectionRequest whether a charging
station may connect, before the WebSocket handshake. Every CSMS still has to implement the rules of the security
profiles on top of it, as the hand-written Basic authentication example of the README does.

Problem

Those rules are the same for every CSMS, depend on the OCPP version of the station, and are easy to get wrong:

  • Basic authentication (profiles 1 and 2). The password is a UTF-8 passwordString in OCPP 2.0.1, but a binary
    AuthorizationKey represented in hexadecimal in OCPP 1.6 (A00.FR.205 in both). The 1.6 whitepaper does not say
    whether a station sends the bytes or their hexadecimal form, and the 2.0.1 specification warns that the encoding
    differs. The username is the station identity (A00.FR.204).
  • Client certificate (profile 3). The CSMS verifies the certification path (A00.FR.403), that the O of the subject
    holds the name of the CSO (A00.FR.404), and that its CN holds the serial number of the station (A00.FR.405), which
    is not necessarily its OCPP id. It terminates the connection otherwise (A00.FR.407) and should log a security event
    (A00.FR.408).
  • TLS version. An OCPP 1.6 charge point MAY use TLS 1.0 or 1.1, OCPP 2.0.1 never (A00.FR.416).
  • No downgrade. Once a station has connected with a higher profile, the CSMS SHALL NOT let it connect with a lower
    one anymore (1.6 A05.FR.09, 2.0.1 A05.FR.07).

Proposed solution

A security profile policy provided by the toolkit and built on ConnectionAuthorizer:

  • a callback giving the security expected for each station, for instance (ocppId) -> StationSecurity?, null for
    an unknown station;
  • implementations such as Basic(passwords) and ClientCertificate(serialNumber, organizationName, trustAnchors),
    the toolkit applying the rules of the OCPP version of the station (password encoding, TLS versions);
  • an enforcement mode: BLOCK by default, REPORT to admit the station but notify the failure (for instance while
    migrating a fleet to a higher profile), OFF;
  • a security event notified to a listener on each failure, never carrying the credentials.

To settle:

  • how the version is known at admission: the subprotocols offered in Sec-WebSocket-Protocol, before the handshake
    negotiates one, or a version given by the application in StationSecurity;
  • the listener of the security events: EventsListeners or a dedicated one;
  • where the highest profile reached by a station is kept: by the application, or by the toolkit through a callback;
  • whether both forms of an OCPP 1.6 AuthorizationKey are accepted by default.

Acceptance criteria

  • A CSMS declares the security expected for each station and the toolkit enforces it, without parsing the
    Authorization header nor the certificate itself.
  • Basic authentication works for OCPP 1.6 stations (bytes or hexadecimal form of the key) and OCPP 2.0.1 stations.
  • A station connecting below the profile expected for it is refused in BLOCK mode.
  • REPORT admits the station and notifies the failure, OFF does neither.
  • Tests cover each profile, both OCPP versions and each mode.
  • The README replaces the hand-written Basic authentication example.

Dependencies and out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions