Custom Authorizer

Wherein you craft a custom authorizer for Alice that lets family in at any time, but constrains friends to a time window. This is an advanced tutorial.

Prerequisites:
All tutorials require Vanadium installation, and must run in a bash shell.
Further, please download this script then source it:

source ~/Downloads/scenario-d-setup.sh

This command wipes tutorial files and defines shell environment variables. If you start a new terminal, and just want to re-establish the environment, see instructions here.

If you would like to generate files from this tutorial without the copy/paste steps, download and source this script. Files will be created in the $V_TUT directory.

Introduction

The goal of this tutorial is to make a custom authorizer and test it using some existing principals.

This command

ls $V_TUT/cred

should list (at least) alice and bob and carol.

The prerequisite script should have arranged for Bob to have the blessing alice:friend:bob and Carol to have the blessing alice:family:sister.

Custom authorization policy

If the Permissions authorizer and/or caveats (caveats are discussed later) aren't sufficient for some purpose, Vanadium applications can create their own arbitrarily complex policy by implementing the security.Authorizer interface.

For example, this policy:

Alice's family can access the service at any time, but friends can access only during a particular time window.

is implemented by this code:

 cat - <<EOF >$V_TUT/src/fortune/server/util/authorizer.go
package util

import (
  "flag"
  "fmt"
  "time"
  "v.io/v23/context"
  "v.io/v23/security"
)

var (
  openStart  = flag.Int(
    "start", 12, "Hour when friends may start access.")
  openLength = flag.Int(
    "length", 1, "Number of hours the window stays open.")
)

type policy struct{}

func (policy) Authorize(ctx *context.T, call security.Call) error {
  var (
    client, _  = security.RemoteBlessingNames(ctx, call)
    hour, _, _ = time.Now().Clock()
    friendsOk  = hour >= *openStart &&
                 hour < (*openStart + *openLength)

    // Patterns on the blessings of authorized folks.
    friends = security.BlessingPattern("alice:friend")
    family  = security.BlessingPattern("alice:family")
  )
  // The client may present multiple blessings, check if any
  // of them satisfy the policy.
  if family.MatchedBy(client...) {
      // family is always okay, so this request is authorized.
      return nil
  }
  if friends.MatchedBy(client...) {
    // Friends only allowed in a given time window.
    if friendsOk {
      return nil
    }
    return fmt.Errorf(
        "friends like %v not authorized at this hour (%d)",
        client, hour)
  }
  // Nobody else is authorized
  return fmt.Errorf("not friend nor family, not authorized")
}

func MakeAuthorizer() security.Authorizer {
  return policy{}
}
EOF
go install fortune/server

Kill the running server (if any) and restart it so that it picks up this new authorization policy:

kill_tut_process TUT_PID_SERVER
$V_TUT/bin/server \
    --v23.credentials $V_TUT/cred/alice \
    --endpoint-file-name $V_TUT/server.txt \
    --start `date +%k` &
TUT_PID_SERVER=$!

Bob has the blessing alice:friend:bob, so RPCs will succeed - but only in the given time window.

The following should work since --start is set to the current hour:

$V_TUT/bin/client \
    --v23.credentials $V_TUT/cred/bob \
    --server `cat $V_TUT/server.txt`

Bob's request to the server succeeds because it is during business hours

Restart the server with a value of --start a few hours in the future so that Bob's requests are rejected:

kill_tut_process TUT_PID_SERVER
$V_TUT/bin/server \
    --v23.credentials $V_TUT/cred/alice \
    --endpoint-file-name $V_TUT/server.txt \
    --start `expr \`date +%k\` + 3` &
TUT_PID_SERVER=$!

Bob is now rejected:

$V_TUT/bin/client \
    --v23.credentials $V_TUT/cred/bob \
    --server `cat $V_TUT/server.txt`

Bob's request to the server fails because it is outside of business hours

Carol, on the other hand, has the blessing alice:family:sister.

Bob may be locked out, but Carol's requests work regardless of the time:

$V_TUT/bin/client \
    --v23.credentials $V_TUT/cred/carol \
    --server `cat $V_TUT/server.txt`

Feel free to review Carol's status with the principal dump command.

Carol's request to the server succeeds

We're done with the server for now.

kill_tut_process TUT_PID_SERVER

Summary