WL#12376: X Protocol session connect attributes

Affects: Server-8.0   —   Status: Complete

Motivation

MySQL X Clients connection the server may differ in:

  • application version,
  • MySQL library version,
  • OS,
  • CPU,
  • CPU endianess,
  • programming language

While the xprotocol ensures that all data is transferred in an architecture agnostic way, the server may want know more about the client.

Having more information about clients/statistics is going to help server administrators with finding faulty clients, targeting potential issues and allow better optimizing.

User Stories

  1. As a DevOp I want to know the application name to route a client connection to the right cluster.
  2. As a DBA I want to know the client's library version to diagnose which version is causing problems with the server.
  3. As a ApplicationDev I want to utilize a connection pool that's shared between multiple applications in the same process to not open a new TCP connection for each new SQL session.
  4. As a ApplicationDev I want to send attributes that are application dependent and can be read from a stored procedure.

Goal

  • allow clients to send more information about it before session establishment

Security Considerations

As session-connect-attributes are sent pre-authentication, their amount MUST be limited to reduce the attack surface.

Design Requirements

DR1
client MUST be able to send attributes before authentication
DR2
client MUST be able to send new attributes before re-authentication after session-close
DR3
amount of data before Authentication MUST be limited.
DR4
keys and values of attributes MUST NOT limited to predefined values.
DR5
keys MAY be duplicate.

Functional Requirements

FR1
session-connect-attributes MUST only apply to the next opened session.
FR2
session-connect-attributes MUST be able to readable from performance_schema.session_connect_attrs
FR3
server MUST send an error if session-connect-attributes data is too large.
FR4
session-reset(reset for session data, introduced by WL#12375) MUST NOT change the session-connect-attributes.
FR5
after session-reset(full/reauthentication), server MUST accept capabilities with session-connect-attributes.
FR6
after session-reset(full/reauthentication), server MUST NOT accept capabilities other than session-connect-attributes.

General

This feature is a wrapper on connection-attributes present in classic protocol. Classic client is able to send an array of key-value pairs to server, which are presented by it in "session_connect_attrs" table. Server validates the data according following constraints:

  • array of key-value pairs:
    • keys name must not exceed 32 characters,
    • value must not exceed 1024 characters,
  • cumulative size of all key-value pairs must not exceed 1MB (limited by PFS API)
  • cumulative size of all key-value pairs must not exceed 64KB (limited by classic protocol)

Server doesn't put any requirements on concrete values that must be supplied in those key-value pairs. User/client library may define a template they would like to follow.

Protocol

X Protocol has already a functionality that may be used to assign some per connection data, its capability exchange in connection-negotiation-phase. X Protocol has three session-establishment phases, relation between them is visible on following state diagram:

state NegotiationOngoing
state AuthenticationOngoing
state SessionOngoing

[*] --> NegotiationOngoing
NegotiationOngoing --> NegotiationOngoing: Connection.CapabilitySet
NegotiationOngoing --> AuthenticationOngoing: Session.AuthenticationStart
AuthenticationOngoing --> SessionOngoing: Session.AuthenticationOk
SessionOngoing --> AuthenticationOngoing: Session.Reset(full-reset)

The feature requires that each 'session-connection-attributs' are assigned per session, still current design (look at previous state diagram) doesn't all setting capabilities after handling 'Session.Reset(full-reset)'.

To handle it properly, session-establishment must work according following:

state AuthenticationOngoing
state SessionOngoing
state NegotiationOngoing {
  state NegotiationOnlyAttribs
  state NegotiationAll

  [*] --> NegotiationAll
  NegotiationAll --> AuthenticationOngoing : Session.AuthenticationStart
  NegotiationOnlyAttribs-->AuthenticationOngoing:Session.AuthenticationStart
}

[*] --> NegotiationOngoing
AuthenticationOngoing --> SessionOngoing: Session.AuthenticationOk
SessionOngoing -up-> NegotiationOnlyAttribs: Session.Reset(full-reset)

The difference is in transition triggered by 'Session.Reset', it moves the connection to negotiation state, still the state is divided at two sub-states:

  • handle setting all capabilities,
  • handle only connection-session-attributes,

we move to the second sub-state. Doing so we do not allow user to change TLS settings or other future capabilities that are specific for communication channel.

In case when client is going to reset-session-data, then session-connect-attributes are preserved because no new session is established.

There are no changes to protocol (proto files). 'CapabilitySet' defines value as 'Any' type, which means that implementation must only validate the capability name and its value under following message:

message Capability {
  required string name = 1;
  required Mysqlx.Datatypes.Any value = 2;
}

X Plugin must allow following capability which is going to set the 'connection-session-attributes':

  • name: session_connect_attrs
  • value: X Protocol object (list of key-value pairs)

    • keys MUST be strings
    • values MUST be strings

Like:

client->server: Connection::CapabilitySet({name=session_connect_attrs, value={fld{key:"k1", value:"v1"}, fld{key:"k2", value:"v2"}...}}
client<-server: Ok

Errors

Failure in setting X Protocol capabilities, is communicated to user by error message with identifier: ER_X_CAPABILITIES_PREPARE_FAILED. Still there are a lot of different reasons why the setting connection-session-attributes may fail. Mostly those errors are consequence of key-value limitation inside the server (general-section). Thus user must be able to identify the failing cause, thus X Plugin must return unique error ID for each of those cases:

  • Connection-session-attribute contains string value that length exceeds 1024 character limit
Property Value
Name ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_VALUE_LENGTH
Error code 5004
Error text Value is too long for '%s' attribute, currently limited to
%i
  • Connection-session-attribute contains string key that length exceeds 32 character limit
Property Value
Name ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_KEY_LENGTH
Error code 5005
Error text Key name beginning with '%s0-32'... is too log, currently
limited to %i
  • Connection-session-attribute contains an empty string key
Property Value
Name ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_EMPTY_KEY
Error code 5006
Error text Empty key name given
  • X Plugin must check the capability length after decoding and if the size exceeds 64k bytes then following error must be returned:
Property Value
Name ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_LENGTH
Error code 5007
Error text There are too many bytes in connection-session-attributes
the capability is limited to %i

PFS API limits the length of 'session-connection-attributes' to 1MB, thus it affect X Plugin anyway the decision was to limit it on X Protocol layer to 64 KB.

There must be an generic mechanism limiting number of bytes received by X Plugin before client successful authentication, which should be not confused with this limit.

  • Connection-session-attribute contains an entry which value or key is not a string:
Property Value
Name ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_TYPE
Error code 5008
Error text Key and values support only string values

* After session reset user can change only one capability, which is 'session_connect_attr':

Property Value
Name ER_X_CAPABILITY_SET_NOT_ALLOWED
Error code 5009
Error text Only session_connect_attr capability is allowed after
Session.Reset

* User specified same capability twice in single CapabilitySet message:

Property Value
Name ER_X_DUPLICATED_CAPABILITIES
Error code 5010
Error text Duplicated capability: '%s'

Neither of those errors is fatal, this means that user can retry setting those attributes:

client->server: Mysqlx.Connection.CapabilitySet(session_connect_attrs...)
client<-server: Mysqlx.Error(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_...)
client->server: Mysqlx.Connection.CapabilitySet(session_connect_attrs...)
client<-server: Mysqlx.Error(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_...)

Performance schema

Client needs to take into consideration that except the limitations on X Protocol there are limitations on performance schema. MySQL Server is going to truncate attributes when cumulative length per thread is longer than value defined under 'performance_schema_session_connect_attrs_size' system variable.

Examples

Mysqlx.Connection.CapabilitiesSet {
  capabilities {
    capabilities {
      name: "session_connect_attrs"
      value {
        type: OBJECT
        object {
         fld {
           key: "_OS"
           value {
             type: SCALAR
             scalar {
               type: V_STRING
               v_string { value: "LINUX" }
             }
           }
         }
       }
     }
   }
 }
}