authentication model

Synit authentication model

Access to the privileged entities within Synit is managed using the gatekeeper protocol.

The syndicate-server supports listening on TCP and Unix sockets with a builtin gatekeeper entity to be used as an initial entity. This is often sufficient but there are subtleties in the case of the system-bus that make direct gatekeeping on sockets undesirable.

Put most simply, mediated access to a resources should not include access to mechanisms that control mediation. A sturdyref macaroon must not allow access to a dataspace where the signing key of the macaroon is observable because that would allow attenuations on the macaroon to be circumvented. Attenuation of observation can mitigate this but is a fail-open rather than a fail-safe solution. The situation with Noise protocol tunnels is similar, a Noise tunnel cannot reasonably provide authentication if the public key provides access to the tunnel secret key.

The Synit system-bus therefore must not bind sturdyrefs or Noise tunnels at its own gatekeeper.

syn-agent

The syn-agent component is used to create ephemeral macaroon signing keys which never leave the syn-agent or persist after a restart. The syn-agent only publishes keys to a child process thru the $SYNDICATE_ROUTE environment variable. To pass keys onto authenticated users the syn-agent is combined with the pam_syndicate PAM extension.

In the case of authentication on a TTY the agetty program is run as a child of syn-agent, syn-agent is a child of the system bus, and PAM is configured to load pam_syndicate.so and invoke its session facility. When agetty begins PAM authentication an internal Syndicate actor is started that opens a tunnel along $SYNDICATE_ROUTE to the syn-agent. A fresh sturdyref is requesting by a <mint-sturdyref> assertion, and the result is attenuated by PAM to enforce a step after the sturdyef that declares PAM session information such as the authenticating user. PAM constructs a $SYNDICATE_ROUTE from this and sets it in the session environment. The PAM Syndicate actor goes idle until the session is closed at which point the sturdyref created for the session is retracted and revoked automatically. This means that while a session is open, the $SYNDICATE_ROUTE set in the environment may be delegated outside of the environment (so long as the syn-agent socket is accessible) but when the session is closed any sessions using the route are retracted.

An example of an attenuated PAM route:

<route
  [ <tcp "::1" 53695> ]
  <ref {
    caveats: [
      <rewrite
        <rec resolve [ <_> <bind <_>> ]>
        <rec resolve [
          <rec oid [
            <dict {
              RHOST: <lit "::1">
              RUSER: <lit "">
              SERVICE: <lit "sshd">
              TTY: <lit "ssh">
              USER: <lit "alice">
            }>
          ]>
          <ref 0>
        ]>
      >
    ]
    oid: 28838
    sig: #[x7XJzgraluwjrru9ejNymQ]
  }>
  #f
>

Externalising the attenuation into the sturdyref makes it larger but minimises the state that must be held within the syn-agent.

binding

The current recommendation is to provide a dedicated syndicate-server for each user with administrative rights, bind PAM steps from that user to the gatekeeper of the user syndicate-server, and perform additional binds at that server.

# Example configuration for the system-bus syndicate-server.

# Assume that greetd and sshd daemons are wrapped by
# syn-agent which presents a dataspace for controlling
# its internal gatekeeper.
#
# Publish those gatekeepers to the system-bus dataspace.
#
? <service-object <daemon greetd> ?obj> [
  $config += <pam-gatekeeper $obj>
]
? <service-object <daemon sshd> ?obj> [
  $config += <pam-gatekeeper $obj>
]

? <service-object <daemon user-bus-alice> ?userBus> [

  # Assume that the user-bus will assert its gatekeeper
  # on the dataspace that is exposed over stdio to the
  # system-bus.
  #
  $userBus ? <gatekeeper ?gkUser> [

    # Collect all syn-agent gatekeepers that converse with PAM.
    #
    $config ? <pam-gatekeeper ?gkPam> [

      # Bind into the syn-agent gatekeeper with a step
      # to the gatekeeper of the user-bus.
      #
      $gkPam += <bind <oid { USER: "alice" }> $gkUser #f>

    ]

    # Bind the system-bus into the user-bus gatekeeper.
    # The user shall have full access to the system-bus.
    #
    $gkUser += <bind <oid system-bus> $config #f>

    # Bind the user-bus into its own gatekeeper.
    #
    $gkUser += <bind <oid user-bus> $userBus #f>

    # Emulate a gatekeeper at the user-bus that
    # loops back to itself.
    #
    $userBus ? <resolve <oid user-bus> ?obs> [
      $obs += <ok $userBus>
    ]

  ]
]