= yaml = title: Principals and Blessings layout: tutorial wherein: Alice and her friend Bob take the stage to demonstrate inter-principal communication. prerequisites: {scenario: b} sort: 21 toc: true = yaml =
A principal in the Vanadium framework is simply a public and private key pair. It has a set of human-readable names bound to it using public-key certificate chains, called blessings. All Vanadium processes act on behalf of a principal and are authorized by other processes based on the blessing names bound to the principal.
For example a principal Alice may have the blessings alice
and bob:houseguest
bound to it. A process running on behalf of Alice may authenticate to others as either alice
or bob:houseguest
or both.
A principal and the set of blessings bound to it, are together referred to as credentials. The basics tutorial demonstrated that a client and server can talk to each other if they run with the same credentials.
To reiterate this, create two principals Alice and Bob with blessings alice
and bob
bound to them respectively:
$V_BIN/principal create --overwrite $V_TUT/cred/alice alice $V_BIN/principal create --overwrite $V_TUT/cred/bob bob
Run the server with Alice's credentials (i.e, authenticate as alice
):
kill_tut_process TUT_PID_SERVER $V_TUT/bin/server \ --v23.credentials $V_TUT/cred/alice \ --endpoint-file-name $V_TUT/server.txt & TUT_PID_SERVER=$!
then make a request as Alice:
$V_TUT/bin/client \ --v23.credentials $V_TUT/cred/alice \ --server `cat $V_TUT/server.txt`
then make a request as Bob (it should fail):
$V_TUT/bin/client \ --v23.credentials $V_TUT/cred/bob \ --server `cat $V_TUT/server.txt`
The reason the request from Alice succeeds and that from Bob fails is because of the Default Authorization Policy used by the server.
In the absence of any explicit indications by the developer, Vanadium services use the following default policy:
Servers authorize clients if the client‘s blessings are an extension of the server’s, or the server‘s blessings are an extension of the client’s.
For example, a server that presents the blessing alice:hometv
to clients will authorize only clients that present either alice
, or alice:hometv
, or alice:hometv:app
, etc. to the server.
In the sample run above, Alice the server recognizes Alice the client as herself (same principal and blessing), and therefore grants access under the default authorization policy.
Under the same policy, Alice‘s server rejects Bob’s request, as neither alice
nor bob
is an extension of the other.
Per the default authorization policy, Bob‘s request to Alice’s server would succeed if he had a blessing of the form alice:<something>
. Such a blessing can be created by Alice by blessing Bob.
A principal can bless another principal by extending a subset of its own blessings and create a blessing for the other principal. This operation can be carried out by the principal
command:
$V_BIN/principal bless \ --v23.credentials $V_TUT/cred/alice \ --for=24h $V_TUT/cred/bob friend:bob | \ $V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ set forpeer - alice
In the first invocation of principal
, Alice creates a blessing for Bob named alice:friend:bob
. A blessing can carry an expiry time (along with other restrictions, explained in subsequent tutorials) after which it is no longer valid.
The second invocation takes that blessing off the pipe and stores it for later use by Bob when talking to Alice's server.
{{# helpers.info }}
A blessing does not contain any private keys and is useful only to the one blessed, so it could be transferred via email without compromising its purpose.
Blessings are transferred via pipes in this tutorial for educational brevity. Later tutorials will show (with more coding details) how a blessing can directly accompany the request that the blessing authorizes. {{/ helpers.info }}
Because Bob has stored the new blessing with his credentials, the same request from Bob that previously failed now succeeds:
$V_TUT/bin/client \ --v23.credentials $V_TUT/cred/bob \ --server `cat $V_TUT/server.txt`
We're done with the server now.
kill_tut_process TUT_PID_SERVER
In Vanadium, a remote procedure call is a multi-step process authentication based on blessings:
The client knocks on the door with an initial, ping-like request that reveals little to the not-yet trusted server.
The server responds with one or more blessings - the server is saying who it is. A blessing is an identity.
Above, the server sends its blessing alice
. This allows the client to establish the server‘s identity before revealing any further information about the client’s intent.
Based on the received blessings, the client choses which (if any) of its blessings to reveal to the server, and sends them along with its service request.
Above, Bob's client sent back two blessings: bob
and alice:friend:bob
. The former is always sent, and the latter is sent to any server identifying itself as alice
.
If the server authorizes the request for the given blessings, it executes the service call and returns results.
Above, the blessing alice:friend:bob
(originally generated by alice and stored by bob) has authorization, so Bob gets his fortune.
Alice and Bob have been established as principals.
Alice ran a server, which Bob couldn‘t talk to. Without changing anything about the runner server, Alice blessed Bob and Bob could talk to Alice’s server.
The default authorization policy lets anyone that Alice blesses talk to her without restriction.
The principal
program reports credentials data
principal dump
summarizes credentials.principal get
drills into credential details.principal dumpblessings
reports the detailed certificate chains that comprise blessings.{{# helpers.info }}
Feel free to skim this, and refer back to it from later tutorials as the need arises.
{{/ helpers.info }}
This section reviews commands that display data from a principal's credentials. The principal
subcommands shown here are handy to use in all subsequent tutorials.
The dump
command summarizes a principal's credentials:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ dump
This results in something like:
{{# helpers.codeoutput }} Public key : 0a:e3:61:0e:3e:ec:9c:ce:ed:04:c1:c6:58:78:28:a8 ---------------- BlessingStore ---------------- Default blessings: alice Peer pattern : Blessings ... : alice ---------------- BlessingRoots ---------------- Public key : Pattern 0a:e3:61:0e:3e:ec:9c:ce:ed:04:c1:c6:58:78:28:a8 : [alice] {{/ helpers.codeoutput }}
This output and its individual components are described below.
The Public key
line shows the public half of Alice's public/private key pair. Isolate it as follows:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ get publickey --pretty
The Default blessings
line shows the blessings that the principal will use when it acts as a server responding to a client.
These blessings will be revealed to all clients of the server, regardless of the blessings presented by the client.
There can be more than one blessing; a principal can play multiple roles - phone, music player, email client, etc.
Examine them as follows:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ get default -names
Below the headings Peer pattern | Blessings
are the blessings used when the principal acts as a client, sending its credentials to a server.
This is a peer map. The client takes the blessing that came from the server, matches it to patterns on the left, and responds to the server using the blessings on the right.
Examine the map as follows:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ get peermap
The pattern ...
matches on all servers, so the name alice
(the name associated with her self-blessing) is provided to all servers.
The BlessingRoots
section displays all root public keys recognized by this principal. The blessing name patterns following a given public key are trusted if they are presented by a principal with the given key.
Report just the recognized roots with:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ get recognizedroots
There's only one key here because currently alice
only recognizes herself.
The situation for Bob is slightly different:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ dump
Example output:
{{# helpers.codeoutput }} Public key : 8e:03:13:7b:f1:57:28:11:87:f0:e8:90:3b:5c:5f:fe ---------------- BlessingStore ---------------- Default blessings: bob Peer pattern : Blessings ... : bob alice : alice:friend:bob ---------------- BlessingRoots ---------------- Public key : Pattern 0a:e3:61:0e:3e:ec:9c:ce:ed:04:c1:c6:58:78:28:a8 : [alice] 8e:03:13:7b:f1:57:28:11:87:f0:e8:90:3b:5c:5f:fe : [bob] {{/ helpers.codeoutput }}
Critically, Bob has a different public key from Alice:
keyAlice=`$V_BIN/principal \ --v23.credentials $V_TUT/cred/alice \ get publickey --pretty` keyBob=`$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get publickey --pretty` echo -e "alice $keyAlice\n bob $keyBob"
Bob will report himself to clients as bob
:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get default -names
Bob's peer map shows that he has stored a blessing alice:friend:bob
that is sent only to servers that have identified themselves as alice
.
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get peermap
Bob also sends his self-blessing bob
to everyone.
Bob, as a side effect of accepting a blessing from Alice, remembers Alice's public key and will trust a principal claiming to be alice
only if it presents that public key.
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get recognizedroots
On the other hand, Alice‘s principal at this point has no record of Bob’s public key. Her server honors Bob's request because Bob presents a blessing rooted at her own public key.
The following command extracts the blessings Bob should use with Alice and prints them in detail:
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get forpeer alice | \ $V_BIN/principal dumpblessings -
Example output:
{{# helpers.codeoutput }} Blessings : bob#alice:friend:bob PublicKey : 8e:03:13:7b:f1:57:28:11:87:f0:e8:90:3b:5c:5f:fe Certificate chains : 2 Chain #0 (1 certificates). Root certificate public key: 8e:03:13:7b:f1:57:28:11:87:f0:e8:90:3b:5c:5f:fe Certificate #0: bob with 0 caveats Chain #1 (2 certificates). Root certificate public key: 0a:e3:61:0e:3e:ec:9c:ce:ed:04:c1:c6:58:78:28:a8 Certificate #0: alice with 0 caveats Certificate #1: friend:bob with 1 caveat (0) security.unixTimeExpiryCaveat(1419279349 = 2014-12-22 12:15:49 -0800 PST) {{/ helpers.codeoutput }}
Alice's public key is at the root of a certificiate chain corresponding to the blessing alice:friend:bob
.
From the dumpblessings
output, isolate blessing names (the names presented to a server) with
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get forpeer -names alice
This shows that Bob will present bob
and alice:friend:bob
.
Examine root keys with
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get forpeer -rootkey=alice:friend:bob alice
That command answers the question
Find the blessings
bob
will present toalice
, and among them find the blessing namedalice:friend:bob
and report the public key of the principal it came from.
In this case, the output should match Alice's public key:
echo $keyAlice
Examine caveats with
$V_BIN/principal \ --v23.credentials $V_TUT/cred/bob \ get forpeer -caveats=alice:friend:bob alice
That command answers the question
Find the blessings
bob
will present toalice
, and among them find the blessing namedalice:friend:bob
and report its caveats.
This shows that Bob's blessing from Alice will expire in about 24h. That expiration was set using the --for
flag in the bless
command above.
Caveats will be discussed in more depth in the caveats tutorial.