Protocol Documentation======================The protocol is a simple transport for other APIs. It's a simple wrapper oversome other protocols, like DBus, REST, and so on. At the present time thisis unstable, but will need to become stable in the near future.Channels--------Each message is part of a channel, which has a id. This channel ididentifies the type of data in the message payload, the host where it isheaded to/from and things like the service or user credentials.An empty/missing channel id represents a special channel called the controlchannel. It contains command messages. These are described below. Initiallyonly the control channel exists. Additional channels are opened and closedvia command messages.Channels operate across all participants, and they help a forwarding layerlike cockpit-ws to know where to send messages.Framing-------The channel id is a UTF-8 valid string. The channel id string comes firstin the message, then a new line, then payload.For example if you had a payload of the string 'abc', and it was beingsent through the channel 'a5', that might look like:a5\nabcWhen a message is sent over a stream transport that does not have distinctmessages (such as SSH or stdio), the message is also prefixed with a base 10integer and new line, which represents the length of the following message.The length must be a positive number in canonical form (ie: strictly greaterthan zero, with no leading zeros).An example. When going over a stream transport with a payload of the 3 bytestring 'abc', and a channel of 'a5', would have a message length of 6: 3 bytes ofpayload, 2 bytes for the channel number, 1 for the new line. It would look likethis in a stream:6\na5\nabcControl Messages----------------Control messages let the various components such as cockpit-web, cockpit-ws andcockpit-bridge communicate about what's going on.Control messages are always sent in the control channel. They always have anempty channel. The payload of a control message is always a jsonobject. There is always a "command" field:```{"command": <command>,"channel": <channel>,...}```If a control message pertains to a specific channel it has a "channel" fieldcontaining the id of the channel. It is invalid to have a present but empty"channel" field.Unknown control messages are ignored. Control messages that have a channel areforwarded to the correct endpoint. Control messages without a channel are notforwarded, but only travel a single hop.Command: init-------------The "init" command is the first message sent over a new transport. It isan error if any other message is received first. The transport is not consideredopen until the "init" message has been received.The following fields are defined:* "version": The version of the protocol. Currently 1, and stable.* "capabilities": Optional array of strings advertizing capabilities.* "channel-seed": A seed to be used when generating new channel ids.* "host": The host being communicated with.* "problem": A problem occurred during init.* "csrf-token": The web service will send a csrf-token for external channels.* "os-release": The bridge sends fields from /etc/os-release which identify the system.* "packages": The bridge sends a list of package names on the system.* "superuser": Instructs a bridge about whether and how to start a superuser bridge.If a problem occurs that requires shutdown of a transport, then the "problem"field can be set to indicate why the shutdown will be shortly occurring.The "init" command message may be sent multiple times across an already opentransport, if certain parameters need to be renegotiated.Command: open-------------The "open" command opens a new channel for payload.The following fields are defined:* "binary": If present set to "raw"* "channel": A uniquely chosen channel id* "payload": A payload type, see below* "host": The destination host for the channel, defaults to "localhost"* "user": Optional alternate user for authenticating with host* "superuser": Optional. Use "require" to run as root, or "try" to attempt to run as root.* "group": An optional channel group* "capabilities": Optional, array of capability strings required from the bridge* "session": Optional, set to "private" or "shared". Defaults to "shared"* "flow-control": Optional boolean whether the channel should throttle itself via flow control.* "send-acks": Set to "bytes" to send "ack" messages after processing each data frameIf "binary" is set to "raw" then this channel transfers binary messages.After the command is sent, then the channel is assumed to be open. No responseis sent. If for some reason the channel shouldn't or cannot be opened, thenthe recipient will respond with a "close" message.The channel id must not already be in use by another channel.An example of an open:```json{"command": "open","channel": "a4","payload": "stream","host": "localhost"}```This message is sent to the cockpit-bridge.The caller can control whether to open a new bridge session or not by settingthe "session" field to "private" or "shared". A "private" session will alwaysstart another bridge just for this channel. If this option is not specifiedthen typically the channel will share an already existing session. There arecertain heuristics for compatibility, where it defaults to private.The open fields are also used with external channels. External channels arechannels that have their payload sent via a separate HTTP request or anotherWebSocket. In this case the "channel" field must not be present, and an"external" field may be present with the following arguments:* "content-disposition": a Content-Disposition header for GET responses* "content-type": a Content-Type header for GET responses* "protocols": an array of possible protocols for a WebSocketChannel "group" fields can be used to group channels into groups. You shouldprefix your groups with a reverse domain name so they don't conflict withother or Cockpit's group names. Group names without any punctuation arereserved.One such special group name is "default", which contains all channels whichwere opened without specifying a group.The "flow-control" option controls whether a channel should attempt to throttleitself via flow control when sending or receiving large amounts of data. Thecurrent default (when this option is not provided) is to not do flow control.However, this default will likely change in the future. This only impacts datasent by the bridge to the browser.If "send-acks" is set to "bytes" then the bridge will send acknowledgementmessages detailing the number of payload bytes that it has received andprocessed. This mechanism is provided for senders (ie: in the browser) whowish to throttle the data that they're sending to the bridge.**Host values**Because the host parameter is how cockpit maps url requests to the correct bridge,cockpit may need to additional information to route the message correctly.For example you want to connect to a container `my-container` runningon "my.host".To allow this the host parameter can encode a key/value pair that willbe expanded in the open command json. The format is host+key+value. For example```json{"command": "open","channel": "a4","payload": "stream","host": "my.host+container+my-container"}```will be expanded to```json{"command": "open","channel": "a4","payload": "stream","host": "my.host","host-container": "my-container","host": "my.host"}```Command: close--------------The "close" command closes a channel.The following fields are defined:* "channel": The id of the channel to close* "problem": A short problem code for closure, or not present for a normal closeThe channel id must be set. An example of a close:```json{"command": "close","channel" : "5x","problem": "access-denied"}```Any protocol participant can send this message. The cockpit-bridge and cockpit-wsbackends will send this message when a channel closes whether because of anerror or a normal closure. The frontend cockpit-web will send this when itwants to close a channel normally. Once either end has sent this message thechannel is considered closed.See below for a list of problem codes.When a channel closing is the result of a ssh transport closing cockpit-wsreports on the authentication methods used while attempting to authenticateby adding a "auth-method-results" object to the close object. This is mainlyuseful to provide helpful error messages and suggestions to users.The "auth-method-results" object contains a key for each method that cockpit-wsis able to attempt authentication with as well as the result of the attempt.For example:```json{"password": "denied"}```This possible "result" values are:* "no-server-support": The target server does not support this method.* "not-provided": cockpit-ws doesn't have a credential to try so this method was skipped.* "succeeded": Authentication with this method was successful.* "denied": Authentication with this method was denied.* "partial": The server wants more authentication.* "error": Unexpected error occurred when using this method.* "not-tried": This methods was not tried, usually due to an earlier method succeeding.Other fields may be present in a close message.Command: ready--------------The "ready" command indicates that the channel implementation (usuallythe bridge) is in a ready and settled state. It is not normally necessary tolisten to this control message, since it is possible to start sending payloadover a channel immediately after the open message has been sent.The following fields are defined:* "channel": The id of the channelOther fields may be present in a ready message.Command: done-------------The "done" command indicates that no more messages will be sent on the channelin the same direction as the "done" was sent.The following fields are defined:* "channel": The id of the channelEither or both endpoints of a channel can send this message. It may only besent once.After it is sent no more messages may be sent in that direction. It is an errorto send further messages, or send another "done" message.Command: options----------------The "options" command sends further channel options on the fly. The contents ofthe message depends on the channel payload.The following fields are defined:* "channel": The id of the channelCommand: ping-------------The "ping" command is simply a keep alive.No additional fields are defined, but any are allowed. If a "channel"is set this "ping" will be forwarded. Otherwise it be limited to a single hop.An example of a ping:```json{"command": "ping"}```Any protocol participant can send a "ping". It is responded to by sendinga "pong" with identical options as a reply. If a "ping" is sent with a"channel" field set to a channel that is not currently open, the "ping"will be ignored as expected, and no "pong" will be sent.Command: authorize------------------The "authorize" command is for communication of authentication andauthorization challenges and responses between cockpit-bridge andcockpit-ws. Despite the name this is also used for authentication.For challenge/response authentication, the following fields are defined:* "cookie": a unique string sent with a challenge that must bepresent in the corresponding response.* "challenge": a challenge string present in messages from a bridgeto cockpit-ws* "response": a response string present in messages from cockpit-wsto a bridgeExample authorize challenge and response messages:```json{"command": "authorize","cookie": "555","challenge": "Basic c2NydWZmeTp6ZXJvZw=="}``````json{"command": "authorize","cookie": "555","challenge": "Basic c2NydWZmeTp6ZXJvZw=="}```Authorize messages are used during authentication by authenticationcommands like `cockpit-session` to obtain the users credentialsfrom cockpit-ws. An authentication command can send a authorize messagewith a response but no cookie. For example```json{"command": "authorize","response": "Basic ..."}```In that case cockpit-ws will store the response and use it in a replyto a subsequent challenge.For credential cache authorization, the following fields are defined:* "credential": Empty or "password"When set to "password" then a "password" field should also be presentwhich represents a new password to cache, which replaces any currentpasswords. If no password field is present then the passwords are cleared.Command: kill-------------The "kill" command terminates a whole set of channels. It is sent by the frontendand processed by cockpit-ws.The following fields are defined:* "host": optional string kills channels with the given host* "group": optional string to select only channels opened with the given "group"If no fields are specified then all channels are terminated.Command: logout---------------The "logout" command is sent by the shell to cockpit-ws. Itdisconnects the user.In older versions, the "logout" command was broadcast to all bridgesand used to terminate privileged ones. Privileged bridges are nowterminated by closing their transport.Command: hint-------------The "hint" command provides hints to other components about the state of thingsor what's going to happen next. The remainder of the fields are extensible.Payload: null-------------A channel opened with this payload type will never send data, and willignore all data it receives.Payload: echo-------------A channel opened with this payload type will send back all data thatit receives. It sends an "done" when it receives one.Payload: dbus-json3-------------------DBus messages are encoded in JSON payloads by cockpit-web, and decoded incockpit-bridge. The 'dbus-json1' and 'dbus-json2' protocols are nolonger supported.Additional "open" command options are needed to open a channel of thistype:* "bus": The DBus bus to connect to either "session", "system" or "none".Defaults to "system" if not present. If set to "none" you must alsoprovide the address parameter.* "name": A service name of the DBus service to communicate with by default.Always omit this field if "bus" is "none". If omitted and "bus" is not"none" then a "name" field must be specified explicitly on other messages.* "address": A dbus supported address to connect to. This option is onlyused when bus is set to "none". Accepts any valid DBus address or"internal" to communicate with the internal bridge DBus connection.The DBus bus name is started on the bus if it is not already running. If itcould not be started the channel is closed with a "not-found". If the DBusconnection closes, the channel closes with "disconnected".DBus messages are encoded as JSON objects. If an unrecognized JSON objectis received, then the channel is closed with a "protocol-error".Method calls are a JSON object with a "call" field, whose value is an array,with parameters in this order: path, interface, method, in arguments.```json{"call": [ "/path", "org.Interface", "Method", [ "arg0", 1, "arg2" ] ],"id": "cookie"}```All the various parameters must be valid for their use. arguments may benull if no DBus method call body is expected. If a "type" field is specifiedthen it is expected to be the DBus method type signature (no tuple). If a"flags" field is a string, then this includes message flags. The default flagsoption has the "i" flag set:* "i": Allow interactive authentication.If no "name" field was specified in the "open" call, indicating which DBusservice to talk to, then one must be specified here along with the "call".If a DBus method call fails an "error" message will be sent back. An errorwill also be sent back in parameters or arguments in the "call" message areinvalid.An optional "id" field indicates that a response is desired, which will besent back in a "reply" or "error" message with the same "id" field.If an interface has been exported, then the bridge will send "call" messagesin its direction for calls received for on that interface.Method reply messages are JSON objects with a "reply" field whose value isan array, the array contains another array of out arguments, or null ifthe DBus reply had no body.```json{"reply": [ [ "arg0", 1, 2 ] ],"id": "cookie"}```If the call had a "type" field, then the reply will have one too containingthe DBus type signature of the arguments. If a "flags" field was present onthe call, then "flags" will also be present on the reply. Valid out flagsare:* `>`: Big endian message* `<`: Little endian messageAn error message is JSON object with an "error" field whose value is anarray. The array contains: error name, error arguments```json{"error": [ "org.Error", [ "Usually a message" ] ],"id": "cookie"}```To receive signals you must subscribe to them. This is done by sending a"add-match" message. It contains various fields to match on. If a fieldis missing then it is treated as a wildcard."path" limits the signals to those sent by that DBus object path, it mustbe a valid object path according to the specification. "path_namespace"limits signals to the subtree of DBus object paths. It must be a validobject path according to the specification, and may not be specifiedtogether with "path"."interface" limits the signals to those sent on the given DBus interface,and must be a valid interface name. "member" limits the signal to thoseof that signal name. "arg0" limits the signals to those that have thegiven string as their first argument. If any of the values are notvalid according to the dbus specification, the channel will close witha "protocol-error".```json{"add-match": {"name": "org.the.Name","path": "/the/path","interface": "org.Interface","member": "SignalName","arg0": "first argument"}}```If the "name" field is omitted, it will be populated from the "open" message.If no "name" was specified in the "open" message, then DBus messages from anybus name will be matched.To unsubscribe from DBus signals, use the "remove-match" message. If amatch was added more than once, it must be removed the same number oftimes before the signals are actually unsubscribed.The form of "remove-match" is identical to "add-match".```json{"remove-match": {"name": "org.the.Name","path": "/the/path","interface": "org.Interface","member": "SignalName","arg0": "first argument"}}```Signals are sent in JSON objects that have a "signal" field, which is anarray of parameters: path, interface, signal name, and arguments. argumentsmay be null if the DBus signal had no body.```json{"signal": [ "/the/path", "org.Interface", "SignalName", [ "arg0", 1, 2 ] ]}```If a signal message is sent to the bridge, the signal will be emitted.In addition a "destination" field may be present to indicate whetherthe signal should be broadcast or not.```json{"signal": [ "/the/path", "org.Interface", "SignalName", [ "arg0", 1, 2 ] ]}```If the bus name of the sender of the signal does not match the "name" field ofthe "open" message, then a "name" field will be included with the "signal" message.Properties can be watched with the "watch" request. Either a "path" or"path_namespace" can be watched. Property changes are listened for withDBus PropertiesChanged signals. If a "path_namespace" is watched andpath is a DBus ObjectManager, then it is used to watch for new DBusinterfaces, otherwise DBus introspection is used. The "id" field isoptional, if present a "reply" will be sent with this same "id" whenthe watch has sent "notify" messages about the things being watched.```json{"watch": {"name": "org.the.Name","path": "/the/path/to/watch","interface": "org.Interface"},"id": 5}```To remove a watch, pass the identical parameters with an "unwatch"request.```json{"unwatch": {"path": "/the/path/to/watch"}}```If the "name" field is omitted, it will be populated from the "open" message.Either a "name" field must be specified here or in the "open" message.Property changes will be sent using a "notify" message. This includesaddition of interfaces without properties, which will be an emptyinterface object, or interfaces removed, which will be null. Only thechanges since the last "notify" message will be sent.```json{"notify": {"/a/path": {"org.Interface1": {"Prop1": "x","Prop2": 1},"org.Interface2": { }},"/another/path": {"org.Removed": null}}}```If the bus name of the sender of the signal does not match the "name" field ofthe "open" message, then a "name" field will be included with the "notify" message.Interface introspection data is sent using "meta" message. Before thefirst time an interface is sent using a "notify" message, a "meta"will be sent with that interface introspection info. Additional fieldswill be defined here, but this is it for now.```json{"meta": {"org.Interface": {"methods": {"Method1": { },"Method2": { }},"properties": {"Prop1": { "flags": "rw" },"Prop2": { "flags": "r" }}}}}```If the bus name of the sender of the signal does not match the "name" field ofthe "open" message, then a "name" field will be included with the "meta" message.Such meta information can also be sent to the bridge, in order to populate thecache of introspection data for the channel.When the owner of the DBus "name" (specified in the open message) changes an "owner"message is sent. The owner value will be the id of the owner or null if the nameis unowned.```json{"owner": "1:"}```A "publish" message can be used to export DBus interfaces on the bus. The bridgewill then send "call" messages back to the frontend for each method invocationon the published interface and object path. The interface must first be describedwith DBus meta information. If a cookie is specified then a reply will be sentwhen the interface is published. If the interface is already published at the givenpath, it will be replaced.```json{"publish": [ "/a/path", "org.Interface" ],"id": "cookie"}```An "unpublish" message will unexport a DBus interface on the bus. It is not anerror if no such interface has been published.```json{"unpublish": [ "/a/path", "org.Interface" ]}```DBus types are encoded in various places in these messages, such as thearguments. These types are encoded as follows:* byte, int16, uint16, int32, uint32, int64, uint64, double: encodedas a JSON number* boolean: encoded as a JSON boolean* string, object-path, signature: encoded as JSON strings* array of bytes: encoded as a base64 string* other arrays, struct/tuple: encoded as JSON arrays* dict: encoded as a JSON object, if the dict has string keys then thoseare used as property names directly, otherwise the keys are JSON encoded andthe resulting string is used as a property name.* variant: encoded as a JSON object with a "v" field containing a valueand a "t" field containing a DBus type signature.```json{"v": "value","t": "s"}```Payload: http-stream2---------------------This channel represents a single HTTP request and response. The requestHTTP headers are sent in the "open" message, and response headers arereturned in a "response" control message.The remaining messages make up the HTTP request and response bodies.When the channel is in text mode, the response body is automaticallycoerced to UTF-8.The following HTTP methods are not permitted:* 'CONNECT'The following headers are not permitted on requests, some of theseare added automatically as appropriate, and others are stripped fromthe response, in particular 'Content-Length':* 'Accept-Charset'* 'Accept-Ranges'* 'Connection'* 'Content-Length'* 'Content-MD5'* 'Content-Range'* 'Range'* 'TE'* 'Trailer'* 'Transfer-Encoding'* 'Upgrade'The following are not accepted on non-binary channels:* 'Accept-Encoding'* 'Content-Encoding'Additional "open" command options are needed to open a channel of thispayload type:* "unix": Open a channel with the given unix socket.* "port": Open a channel with the given TCP port on localhost.* "address": Open a channel that communicates with the givenaddress instead of localhost. This can be an IP address or a validhost name. To use this option you must also specify a port.This option should be used to communicate with externalapis and not as a synonym for the host parameter.* "method": "GET", "POST", or other valid HTTP methodYou may also specify these options:* "headers": JSON object with additional request headers* "tls": Set to a object to use an https connection.The TLS object can have the following options:* "authority": Certificate authority(s) to expect as signers of peer.* "validate": Validate the peer's certificate.The "authority" is an object with either of the following fields:* "file": String with a file name* "data": String with PEM encoded dataAny data to be sent should be sent via the channel, and then the channelshould be closed without a problem.Payload: websocket-stream1--------------------------This channel payload implements a WebSocket client. The data in thechannel is the message frames.Most of same options for http-stream2 apply here.The response headers are send back in a "response" control message.Payload: stream---------------Raw data is sent back and forth to a socket. See cockpitstream.c. Theboundaries of the messages are arbitrary, and depend on how the kerneland socket buffer things.If the channel is not binary, then non-UTF-8 data is forced into UTF-8with a replacement character.Additional "open" command options should be specified with a channel ofthis payload type:* "unix": Open a channel with the given unix socket.* "port": Open a channel with the given TCP port on localhost.* "address": Open a channel that communicates with the givenaddress instead of localhost. This can be an IP address or a validhost name. To use this option you must also specify a port.* "batch": Batches data coming from the stream in blocks of at least thissize. This is not a guarantee. After a short timeout the data will besent even if the data doesn't match the batch size. Defaults to zero.* "latency": The timeout for flushing any cached data in milliseconds.* "spawn": Spawn a process and connect standard input and standard outputto the channel. Should be an array of strings which is the processfile path and arguments.You can't specify both "unix" and "spawn" together. When "spawn" is set thefollowing options can be specified:* "directory": The directory to spawn the process in.* "err": If "spawn" is set, and "err" is set to "out", then stderris included in the payload data. If "err" is set to "ignore" then, thestderr output will be discarded. If "err" is set to "message" then it willbe included in the close message. If "pty" is set then stderr is alwaysincluded.* "environ": This is a list of additional environment variables for the newspawned process. The variables are in the form of "NAME=VALUE". The defaultenvironment is inherited from cockpit-bridge.* "pty": Execute the command as a terminal pty.* "window": An object containing "rows" and "cols" properties, which set thesize of the terminal window. Values must be integers between 0 and 0xffff.This option is only valid if "pty" is true.For type "spawn", the `ready` message contains a "pid" field with the spawnedprocess ID.If an "done" is sent to the bridge on this channel, then the socket and/or pipeinput is shutdown. The channel will send an "done" when the output of the socketor pipe is done.If "spawn" is set and the channel is closed with a "problem" code, then theprocess will be sent a SIGTERM signal.Additionally, a "options" control message may be sent in this channelto change the "batch", "latency", and "window" options.Payload: packet---------------Raw data is sent back and forth to as messages to a socket. The messageboundaries correspond exactly to the messages sent over the socket.If the channel is not binary, then non-UTF-8 data is forced into UTF-8with a replacement character.Additional "open" command options should be specified with a channel ofthis payload type:* "unix": Open a channel with the given unix socket.* "max-size": The maximum possible size of a message. Default is 64KSupports up to 128K. Messages larger than this will be truncated.If an "done" is sent to the bridge on this channel, then the socketinput is shutdown. The channel will send an "done" when the output of the socketor pipe is done.Additionally, a "options" control message may be sent in this channelto change the "max-size" options.Payload: fsinfo----------------This channel is used to report information about a given path, and the file ora directory which may reside there, including the possibility of updates. Inthe case of directories, information can also be reported about the (directly)contained entries.Additional "open" command options should be specified with a channel ofthis payload type:* `path` (mandatory): a string, an absolute path name. If this ends with `/`then the path must refer to a directory.* `attrs` (mandatory): a list of strings, the requested attributes to bereported for the file at `path`, and (optionally) its sub-items. See belowfor the possibilities.* `fnmatch`: (optional, default ''): if non-empty, this is a [`fnmatch`-stylepattern](https://docs.python.org/3/library/fnmatch.html). In case `path`refers to a readable directory, an `entries` attribute will be reported(described below). Use `*` to report all files. Can also be used toimplement search (`searc*`) or hide temporary files (`[!.]*`).* `watch` (optional, default: false): if the channel should watch for changes* `follow` (default: true): if the trailing component of `path` is a symboliclink, whether we should follow it. `follow: false` mode is not supportedfor `watch` (but is also mostly unnecessary).A channel is created with an associated absolute pathname (`path`). A path isa string that you pass to the `open()` syscall. The object returned by thatcall is described by the (JSON Document) value of the channel.Strictly speaking, the path is specified to the channel as a unicode string,but paths on the filesystem are binary strings. This mapping is handled usingthe usual Python convention: filenames are stored in utf8 and encoded anddecoded with `errors='surrogateescape'`, which allows for handling of filenameswhich are not utf8.Conceptually, the channel represents the value of a JSON object describing whatis found at the path, or the reason for an error. Each message on the channelis a JSON Merge Patch ([RFC7396](https://datatracker.ietf.org/doc/html/rfc7396)) which updates or replacesthis object.The top-level keys in the object are:- `info`: the info about the reported path (described below)- `error`: an object with information about why `info` can't be reported.This is currently basically an errno formatted in several possible ways:- `problem`: a Cockpit "problem" code type of string like `not-found` or`not-directory`- `message`: the result of strerror(). Currently English, hopefullytranslated at some point- `errno`: the symbolic `errno` name like `ENOENT` or `ENOTDIR`- `partial`: `true` if the data is in a "partial" state. This is used whensending updates in multiple pieces.The value of the `info` attribute is a JSON object describing the attributes ofthe file. Any attribute which cannot be read (eg: due to permissions problems)is simply not reported.* `type`: a string: `reg`, `dir`, `lnk`, `chr`, `blk`, `fifo`, or `sock`* `mode`: an integer representing the "file permission" bits(`S_IMODE(st_mode)`). As per JSON, this is transmitted as a decimal value,but it is meant to be interpreted in octal, in the usual way.* `uid`: an integer, the uid of the file owner (`st_uid`)* `user`: a string, or an integer if the lookup failed* `gid`: an integer, the gid of the file group (`st_gid`)* `group`: a string, or an integer if the lookup failed* `size`: an integer, the (apparent) size of the file (`st_size`)* `mtime`: a float, the mtime of the file (`st_mtim`)* `tag`: a value type: the current 'transaction tag' of the file, with thesame meaning as elsewhere in this document. Ideally: this changes if thecontent of the file changes. This is the same as the tag used in `fsread1`and `fsreplace1`.* `entries`: for directories: the contents of the directory (see below)* `target`: for symbolic links: the target of the link (a string)* `targets`: for directories: extra information about symlink targets forsymlinks found in the directory (see below)* `r-ok`: boolean, whether reading is allowed. (note: checking access is expensive)* `w-ok`: boolean, whether writing is allowed. (note: checking access is expensive)* `x-ok`: boolean, whether executing is allowed. (note: checking access is expensive)The `entries` attribute is reported iff `fnmatch` is non-empty, and `path`refers to a readable directory. It is an object where each key is the name ofa file in the directory, and each value is an object describing that file,using the same attributes as above. `entries` is not reported on entries (ie:no recursive listing). Listing `entries` in `attrs` is equivalent to`fnmatch='*'`.The `targets` attribute is reported iff `targets` is listed in `attrs`. Itcontains information that was true at some point in time about the targets ofsymbolic links that were found in the current directory. An entry is addedhere only in case the entry wouldn't be found in the main `entries` dictionary.For example, if `path` is `/usr/lib` and `fnmatch` is `*.so` and the directorycontains the links `a.so → a-impl.so`, `b.so → b.so.0` and `c.so -> ../x/c.so`then the `targets` dictionary would include `b.so.0` (which isn't reported inentries because it doesn't match `fnmatch`) and `../x/c.so` (which isn'treported because it's in a different directory). Monitoring these entries forchanges would be expensive, so it's simply not done. Clients are expected touse this information to flesh out details about directory entries, answeringquestions like "`/bin` links to `usr/bin`, but what type of file is that?".`targets` is incompatible with `follow: false`.If the provided `path` is a symbolic link, it is followed, unless`follow: false` is specified. If symbolic links are present in the directory,they are always reported directly (ie: not followed). `follow: false` is notsupported in combination with `watch: true` but you probably don't need it:watch mode doesn't only watch the final path component, but all componentsleading up to it, including any symlink that have been followed. That meansthat you can watch `/etc/localtime` and find out about if the link changed, orif the contents of the file itself changed, or was deleted or replaced, or alsoif `/usr`, `/etc`, or any other directories or intermediate links were changed,deleted, or moved out of the way.The life-cycle of the channel works like this:- When opening the channel, `ready` is always immediately sent.- One or more patches are sent to modify the initial value of the channel(`null`). The "initial state" is reached when the value is a objectwhich does not have the `partial` attribute set on it.- If `watch` mode is false then `done` is sent immediately, and the channel isclosed.- Otherwise (`watch: true`), the channel remains open. When any changes aredetected, they are sent as updates to the value of the channel. This mayinvolve transitions between reporting `info` and reporting `problem`.- The channel will stay open until the client closes it.Payload: fsread1----------------Returns the contents of a file and its current 'transaction tag'.The following options can be specified in the "open" control message:* "path": The path name of the file to read.* "max_read_size": option to limit the amount of data that is read. If thefile is larger than the given number of bytes, no data is read and thechannel is closed with problem code "too-large". The default limit is 16MiB. The limit can be completely removed by setting it to -1.The ready message contains a "size-hint" when the channel is openedwith the "binary" option set to "raw".The channel will return the content of the file in one or moremessages. As with "stream", the boundaries of the messages arearbitrary.If the file is modified while you are reading it, the channel isclosed with a "change-conflict" problem code. If the file isatomically replaced as with 'rename' when you are reading it, this isnot considered an error and you will get the old content with acorrect tag.When all content has been sent or an error has occurred, the channelwill be closed. In addition to the usual "problem" field, the "close"control message sent by the server might have the following additionalfields:* "message": A string in the current locale describing the error.* "tag": The transaction tag for the returned file content. The tagfor a non-existing file is "-".It is not permitted to send data in an fsread1 channel. This channelsends a "done" when all file data was sent.Payload: fsreplace1-----------------Replace the content of a file.The following options can be specified in the "open" control message:* "path": The path name of the file to replace.* "size": The expected size of the file content. If set, the file isallocated immediately, and the channel "open" request will fail ifinsufficient space is available. If this option is set, it is notpossible to delete the file (ie: sending immediate EOF will result ina 0 byte file) This option should always be provided if possible, toavoid fragmentation, but is particularly important for large files.* "tag": The expected transaction tag of the file. When the actualtransaction tag of the file is different, the write will fail. Ifyou don't set this field, the actual tag will not be checked. Toexpress that you expect the file to not exist, use "-" as the tag.* "attrs": a JSON object containing optional file attributes to set:- `user`: a string, or an integer, the uid of the file owner (`st_uid`).If set `group` also has to be set.- `group`: a string, or an integer, the gid of the file group (`st_gid`)If set `user` also has to be set.- `mode`: an integer, usually expressed in octal, but in json it is theequivalent value in decimal.You should write the new content to the channel as one or moremessages. To indicate the end of the content, send a "done" message.If you don't send any content messages before sending "done", and no"size" was given, the file will be removed. To create an empty file,send at least one content message of length zero, or set the "size" to0.If "size" is given, and less data is actually sent, then the file willbe truncated down to the size of the data that was actually sent. Ifmore data is sent, the file will grow (subject to additionalfragmentation and potential ENOSPC errors).When the file does not have the expected tag, the channel will beclosed with a "change-conflict" problem code.The new content will be written to a temporary file and the oldcontent will be replaced with a "rename" syscall when the channel isclosed without problem code. If the channel is closed with a problemcode (by either client or server), the file will be left untouched.If `tag` is given and no equivalent `attrs`, file owner, mode and SELinuxcontext are preserved (copied from the original file). Other attributes (likeACLs) are never copied.In addition to the usual "problem" field, the "close" control messagesent by the server might have the following additional fields:* "message": A string in the current locale describing the error.* "tag": The transaction tag of the new content.No payload messages will be sent by this channel.Payload: metrics1-----------------With this payload type, you can monitor a large number of metrics,such as all of the metrics exposed by PCP, the Performance Copilot.In addition to monitoring live values of the metrics, you can alsoaccess archives of previously recorded values.You specify which metrics to monitor in the options of the "open"command for a new channel.One of the options is the "source" of the metrics. Many details ofhow to specify metrics and how the channel will work in detail dependon the type of the source, and are explained in specific sectionsbelow.The channel guarantees that each sample returned by it contains valuesfor all requested metrics.The general open options are:* "source" (string): The source of the metrics:* "direct": PCP metrics from plugins that are loaded into theCockpit bridge directly. Use this when in doubt.* "pmcd": PCP metrics from the local PCP daemon.* A string starting with "/": PCP metrics from one or morearchives.The string is either the name of an archive, or the name of adirectory. When it refers to a directory, the bridge will findall archives in that directory and merge them. The archives mustnot overlap in time.* "pcp-archive": PCP metrics from the default pmlogger archive.This is the same as using the name of the default pmloggerarchive directory directly, but you don't have to know where itis.* "metrics" (array): Descriptions of the metrics to use. See below.* "instances" (array of strings, optional): When specified, only thelisted instances are included in the reported samples.* "omit-instances" (array of strings, optional): When specified, thelisted instances are omitted from the reported samples. Only oneof "instances" and "omit-instances" can be specified.* "interval" (number, optional): The sample interval in milliseconds.Defaults to 1000.* "timestamp" (number, optional): The desired time of the firstsample. This is only used when accessing archives of samples.This is either the number of milliseconds since the epoch, or (whennegative) the number of milliseconds in the past.The first sample will be from a time not earlier than thistimestamp, but it might be from a much later time.* "limit" (number, optional): The number of samples to return. Thisis only used when accessing an archive.When no "limit" is specified, all samples until the end of thearchive are delivered.You specify the desired metrics as an array of objects, where eachobject describes one metric. For example:```json[{"name": "kernel.all.cpu.user","units": "millisec","derive": "rate"},...]```A metric description can contain the following fields:* "name" (string): The name of the metric. Available metrics dependon the source.* "units" (string, optional): The units that values for this metricshould be delivered in. If the given metric can not be convertedinto these units, the channel is closed. The format of the stringdepends on the source.* "derive" (string, optional): Optional computation. Possible valuesare "delta" and "rate". For "delta", the channel delivers thedifference between the current and the previous value for a metric.For "rate", the channel delivers the change per millisecond of themetric.For both "delta" and "rate", the value for a metric will be "false"if there is no previous value to do the computation with.Once the channel is open, it will send messages encoded as JSON. Itwill send two types of message: 'meta' messages that describe themetrics, and 'data' messages with the actual samples.A 'meta' message applies to all following 'data' messages until thenext 'meta' message. The first message in a channel will always be a'meta' message.The 'meta' messages are JSON objects; the 'data' messages are JSONarrays.The 'meta' messages have at least the following fields:* "metrics" (array): This field provides information about therequested metrics. The array has one object for each metric, inthe same order as the "metrics" option used when opening thechannel.For each metric, the corresponding object contains at least thefollowing field:* "instances" (array of strings, optional): This field lists theinstances for instanced metrics. This field is not present fornon-instanced metrics.* "units" (string): The units of the values for this metric.* "derive" (string): The post-processing mode, as specified in the"open" message.* "timestamp" (number): The point in time of the next 'data' message,in milliseconds since the epoch.* "interval" (number): The time interval between subsequent points intime in the 'data' messages, in milliseconds.Depending on the source, more fields might be present in a 'meta'message, and more fields might be present in the objects of the"metrics" field.The 'data' messages are nested arrays in this shape:```[ // first point in time[// first metric (instanced, with two instances)[// first instance1234,// second instance5678],// second metric (not instanced)789,// third metric543],// next point in time[// same shape again as for the first point in time]]```Thus, a 'data' message contains data for one or more points in timewhere samples have been taken. A point in time is always one`interval` later than the previous point in time, even when they arereported in the same 'data' message.For real time monitoring, you will generally only receive one point intime per 'data' message, but when accessing archived data, the channelmight report multiple points in time in one message, to improveefficiency.For each point in time, there is an array with samples for eachmetric, in the same order as the `metrics` option used when openingthe channel.For non-instanced metrics, the array contains the value of the metric.For instanced metrics, the array contains another array with samplesfor each instance, in the same order as reported in the `instances`field of the most recent 'meta' message.In order to gain efficiency, 'data' messages are usually compressed.This is done by only transmitting the differences from one point intime to the next.If a value for a metric or a instance is the same as at the previouspoint in time, the channel transmits a `null` value instead.Additionally, `null` values at the end of an array are suppressed bytransmitting a shorter array.For example, say the samples for three points in time are1: [ 21354, [ 5, 5, 5 ], 100 ]2: [ 21354, [ 5, 15, 5 ], 100 ]3: [ 21354, [ 5, 15, 5 ], 100 ]then the channel will send these array instead:1: [ 21354, [ 5, 5, 5 ], 100 ]2: [ null, [ null, 15 ] ]3: [ null, [ ] ]This compression only happens when the last and current value belongto the same instance of the same metric. Thus, the client does notneed to track layout changes when decompressing data messages.Instead of a number of `null`, a data message can also contain`false`. This indicates an error of some kind, or an unavailablevalue.**PCP metric source**Cou can use "pminfo -L" to get a list of available PCP metric namesfor a "direct" source, for example. If no metric of this name exists,the channel is closed without delivering any message.The format of the "units" member is the same as the one used by"pminfo -d".The metric information objects in the 'meta' messages for PCP sourcesalso contain these fields:* `semantics` (string): The semantics of this metric, one of`counter`, `instant`, or `discrete`.Only numeric metrics are currently supported. Non-numeric metricshave all their samples set to `false`.Payload: session-control------------------------Control aspects of the current session. Currently this is limited tothe session idle timeout.When opening a channel with payload "session-control", the bridge thathandles this channel switches on its idle timeout handling. Afteropening such a channel, you are then responsible for sending messagesto the bridge that inform it of user activity. If no such message isreceived (while the channel is open) for the duration of theconfigured session idle timeout, the bridge will exit.If you close the channel, the bridge will stop its idle timeouthandling.This might change in the future such that the idle timeout handling inthe bridge is always active and cannot be switched off.The bridge is made responsible for implementing the session idletimeout to make sure it happens even when JavaScript stops executingor is severely throttled, maybe due to being stopped by the Browser,the user, or because it has crashed to such a degree that it won'thandle the session timeout anymore.JavaScript still has to explicitly switch on the session idle timeouthandling in the bridge however (by opening a "session-control"channel). This might change in the future and the bridge might startthe session idle timeout unconditionally.The following channel control messages will be send by the bridge:```json{ "command": "ready", "timeout": N }```The first message will be "ready" and it will contain the configuredsession idle timeout in seconds. A timeout value of zero means thatno timeout has been configured.```json{ "command": "countdown", "counter": N }```The bridge will countdown the last 30 seconds of the session and willsend these messages to announce that. You should show the countdown tothe user somewhere.```json{ "command": "logout" }```After the countdown, the bridge will tell you to logout with thismessage. You should do a clean logout. If such a logout doesn'thappen, the bridge will forcefully exit 10 seconds later.You can send these message to the bridge:```json{ "command": "active" }```This indicates that the user was active. The bridge will reset itsidle timer.Problem codes-------------These are problem codes for errors that cockpit-web responds to. They shouldbe self explanatory. It's totally not interesting to arbitrarily invent newcodes. Instead the web needs to be ready to react to these problems. When indoubt use `internal-error`.* `internal-error`* `no-cockpit`* `unsupported-shell`* `no-session`* `access-denied`* `authentication-failed`* `not-found`* `terminated`* `timeout`* `unknown-hostkey`* `no-forwarding`