<commit_before>= yaml =
title: The Agent
layout: tutorial
wherein: you use a security agent to maintain your secrets and facilitate your secure use of Vanadium.
prerequisites: {scenario: d}
sort: 25
toc: true
= yaml =

# Motivation

In the [principals tutorial] you used the `principal create` command
to create the _principals_ Alice, Bob, etc.  The operation made
collections of files in the specified target directories, e.g.:

<!-- @lsCredAlice @test -->
```
ls $V_TUT/cred/alice $V_TUT/cred/bob
```

Stored among these files are the private keys associated with Alice
and Bob.  The keys could be encrypted (there are ways to do that), but
at the moment, they aren't.  At no point during earlier tutorials did
you - the tutee - get prompted for a passphrase, despite frequent use
of the `--v23.credentials {directory}` flag.

Encrypting the file on disk, and requiring a password with each
invocation of a command specifying `--v23.credentials {directory}`
will solve the immediate problem of a clear text key on disk, but is
onerous.

In addition to the nuisance of having to provide a decryption
passphrase each time the credentials are used, having each program
load the private key into process memory as part of its runtime
initialization exposes the key to the risk of compromise.

This would be OK for the tutorials, which had the goal of _teaching_
security concepts rather than _being_ secure.  You were running only
official Vanadium apps or programs that you wrote, in your own
authenticated session, on a machine under your control.

But easy access to the private key is not OK under normal
circumstances. A private key should be private.

Furthermore, if several program were to access the same credentials
directory simulataneously, they would risk corrupting the data during
mutations.  There is a need for coordinating concurrent access to
credentials.

# An agent holds the key

Part of the solution to these problems is `v23agentd`, a Vanadium
utility analogous to [`ssh-agent`].  It loads credentials into its
memory, and serves key management requests from other client
processes.

A client process, needing to check the validity of blessings coming in
with a request, can pass said blessings (implicitly via the runtime's
use of a POSIX [file descriptor]) up to `v23agentd`, which then does
the necessary crypto with the keys it holds, passing the result back
to the client.

Launching an agent to serve credentials in a given directory (by
invoking `v23agentd {directory}`) sets up a socket file in the
directory, which the client connects to when using `--v23.credentials
{directory}`.  This happens in the Vanadium runtime - no new client
code required.

Typically, launching an agent explicitly is not necessary --
as long as `v23agentd` is in its `PATH`, a program run with
`--v23.credentials {directory}` will automatically launch an agent to
serve the credentials.  Other programs using `--v23.credentials
{directory}` will connect to the same agent and safely share the
credentials.  The agent will stay up for as long as there are client
connected to it.  In fact, this is what happened in all previous
tutorials, like the [hello world][hello world] tutorial, enabling the
same credentials to be shared between client and server.

Occasionally, launching the agent explicitly is needed, such as when
we do not trust the program to access the credentials and launch
`v23agentd`.

To illustrate, rerun the _existing_ client code against the _existing_
server code using two explicit instances of the agent - one becomes
Alice, the other becomes Bob.

The only difference between the following command sequence and
[previous usage][previous-usage] is that `v23agentd` gets launched
before we run the client and server.

<!-- @twoAgents @test -->
```
# Clean up from previous attempt, if any.
kill_tut_process TUT_PID_SERVER
/bin/rm -f $V_TUT/server.txt

# Run an agent for server credentials.
$V_BIN/v23agentd $V_TUT/cred/alice
$V_TUT/bin/server \
    --v23.credentials $V_TUT/cred/alice \
    --endpoint-file-name $V_TUT/server.txt \
    --perms '{"R": {"In": ["alice:family",
                           "alice:friend"]},
              "W": {"In": ["alice:family"]}}' &
TUT_PID_SERVER=$!

# Wait for startup.
sleep 2s

# Run an agent for client credentials.
$V_BIN/v23agentd $V_TUT/cred/bob
$V_TUT/bin/client \
    --v23.credentials $V_TUT/cred/bob \
    --server `cat $V_TUT/server.txt`

# All done, kill the server and agents
kill_tut_process TUT_PID_SERVER
$V_BIN/v23agentd --stop $V_TUT/cred/alice
$V_BIN/v23agentd --stop $V_TUT/cred/bob
```

The above should run without errors, i.e. the client should report a
fortune.

The crucial new behavior here is that _neither the server nor client
binary had access to private keys_.  The runtime off-loaded all crypto
checks to the agent in a different process.

In the normal course of events, where you run code whose source code
you've not written or may not have access to, this is a critical
capability.  The program runs with clear identity, but cannot secretly
send the private keys to that identity elsewhere.

# Become Alice

Set the environment variable `V23_CREDENTIALS={directory}` to run a
script as a given identity.  Here, the script just runs `principal
dump` commands, introspecting its own identity:

<!-- @becomeAlice @test --><commit_msg>services/agent/v23agentd: break into subcommands<commit_after>= yaml =
title: The Agent
layout: tutorial
wherein: you use a security agent to maintain your secrets and facilitate your secure use of Vanadium.
prerequisites: {scenario: d}
sort: 25
toc: true
= yaml =

# Motivation

In the [principals tutorial] you used the `principal create` command
to create the _principals_ Alice, Bob, etc.  The operation made
collections of files in the specified target directories, e.g.:

<!-- @lsCredAlice @test -->
```
ls $V_TUT/cred/alice $V_TUT/cred/bob
```

Stored among these files are the private keys associated with Alice
and Bob.  The keys could be encrypted (there are ways to do that), but
at the moment, they aren't.  At no point during earlier tutorials did
you - the tutee - get prompted for a passphrase, despite frequent use
of the `--v23.credentials {directory}` flag.

Encrypting the file on disk, and requiring a password with each
invocation of a command specifying `--v23.credentials {directory}`
will solve the immediate problem of a clear text key on disk, but is
onerous.

In addition to the nuisance of having to provide a decryption
passphrase each time the credentials are used, having each program
load the private key into process memory as part of its runtime
initialization exposes the key to the risk of compromise.

This would be OK for the tutorials, which had the goal of _teaching_
security concepts rather than _being_ secure.  You were running only
official Vanadium apps or programs that you wrote, in your own
authenticated session, on a machine under your control.

But easy access to the private key is not OK under normal
circumstances. A private key should be private.

Furthermore, if several program were to access the same credentials
directory simulataneously, they would risk corrupting the data during
mutations.  There is a need for coordinating concurrent access to
credentials.

# An agent holds the key

Part of the solution to these problems is `v23agentd`, a Vanadium
utility analogous to [`ssh-agent`].  It loads credentials into its
memory, and serves key management requests from other client
processes.

A client process, needing to check the validity of blessings coming in
with a request, can pass said blessings (implicitly via the runtime's
use of a POSIX [file descriptor]) up to `v23agentd`, which then does
the necessary crypto with the keys it holds, passing the result back
to the client.

Launching an agent to serve credentials in a given directory (by
invoking `v23agentd --credentials={directory}`) sets up a socket file in the
directory, which the client connects to when using `--v23.credentials
{directory}`.  This happens in the Vanadium runtime - no new client
code required.

Typically, launching an agent explicitly is not necessary --
as long as `v23agentd` is in its `PATH`, a program run with
`--v23.credentials {directory}` will automatically launch an agent to
serve the credentials.  Other programs using `--v23.credentials
{directory}` will connect to the same agent and safely share the
credentials.  The agent will stay up for as long as there are client
connected to it.  In fact, this is what happened in all previous
tutorials, like the [hello world][hello world] tutorial, enabling the
same credentials to be shared between client and server.

Occasionally, launching the agent explicitly is needed, such as when
we do not trust the program to access the credentials and launch
`v23agentd`.

To illustrate, rerun the _existing_ client code against the _existing_
server code using two explicit instances of the agent - one becomes
Alice, the other becomes Bob.

The only difference between the following command sequence and
[previous usage][previous-usage] is that `v23agentd` gets launched
before we run the client and server.

<!-- @twoAgents @test -->
```
# Clean up from previous attempt, if any.
kill_tut_process TUT_PID_SERVER
/bin/rm -f $V_TUT/server.txt

# Run an agent for server credentials.
$V_BIN/v23agentd --credentials=$V_TUT/cred/alice
$V_TUT/bin/server \
    --v23.credentials $V_TUT/cred/alice \
    --endpoint-file-name $V_TUT/server.txt \
    --perms '{"R": {"In": ["alice:family",
                           "alice:friend"]},
              "W": {"In": ["alice:family"]}}' &
TUT_PID_SERVER=$!

# Wait for startup.
sleep 2s

# Run an agent for client credentials.
$V_BIN/v23agentd --credentials=$V_TUT/cred/bob
$V_TUT/bin/client \
    --v23.credentials $V_TUT/cred/bob \
    --server `cat $V_TUT/server.txt`

# All done, kill the server and agents
kill_tut_process TUT_PID_SERVER
$V_BIN/v23agentd stop --credentials=$V_TUT/cred/alice
$V_BIN/v23agentd stop --credentials=$V_TUT/cred/bob
```

The above should run without errors, i.e. the client should report a
fortune.

The crucial new behavior here is that _neither the server nor client
binary had access to private keys_.  The runtime off-loaded all crypto
checks to the agent in a different process.

In the normal course of events, where you run code whose source code
you've not written or may not have access to, this is a critical
capability.  The program runs with clear identity, but cannot secretly
send the private keys to that identity elsewhere.

# Become Alice

Set the environment variable `V23_CREDENTIALS={directory}` to run a
script as a given identity.  Here, the script just runs `principal
dump` commands, introspecting its own identity:

<!-- @becomeAlice @test -->
{'fraction_non_alphanumeric': 0.06623991093793487, 'fraction_numerical': 0.007421838760552927, 'mean_word_length': 4.227934044616877, 'pattern_counts': {'":': 8, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '110013', 'n_tokens_mistral': 3109, 'n_tokens_neox': 2957, 'n_words': 1527}