blob: 73d736344005d9abe8f8ec9e98f1fe965ed51a24 [file] [log] [blame]
#!/bin/bash
# Test the principal command-line tool.
#
# This tests most operations of the principal command-line tool.
# Not the "seekblessing" command yet, since that requires
# starting a separate server.
source "$(go list -f {{.Dir}} v.io/core/shell/lib)/shell_test.sh"
readonly WORKDIR=${shell_test_WORK_DIR}
build() {
PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/principal')"
}
# rmpublickey replaces public keys (16 hex bytes, :-separated) with XX:....
# This substitution enables comparison with golden output even when keys are freshly
# minted by the "principal create" command.
rmpublickey() {
sed -e "s/\([0-9a-f]\{2\}:\)\{15\}[0-9a-f]\{2\}/XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX/g"
}
rmcaveats() {
sed -e "s/security.unixTimeExpiryCaveat([^)]*)/security.unixTimeExpiryCaveat/"
}
dumpblessings() {
"${PRINCIPAL_BIN}" dumpblessings "$1" | rmpublickey | rmcaveats
}
main() {
cd "${WORKDIR}"
build
# Prevent any VEYRON_CREDENTIALS in the environment from interfering with this test.
unset VEYRON_CREDENTIALS
# Create three principals, one called "alice" one called "bob" and one called "carol"
"${PRINCIPAL_BIN}" create --overwrite=true ./alice alice >/dev/null || shell_test::fail "line ${LINENO}: create failed"
"${PRINCIPAL_BIN}" create ./bob bob >/dev/null || shell_test::fail "line ${LINENO}: create failed"
"${PRINCIPAL_BIN}" create --overwrite=true ./bob bob >/dev/null || shell_test::fail "line ${LINENO}: create failed"
"${PRINCIPAL_BIN}" create ./carol carol >/dev/null || shell_test::fail "line ${LINENO}: create failed"
# Run dump, bless, blessself on alice
export VEYRON_CREDENTIALS=./alice
"${PRINCIPAL_BIN}" blessself alicereborn >alice.blessself || shell_test::fail "line ${LINENO}: blessself failed"
"${PRINCIPAL_BIN}" bless ./bob friend >alice.bless || shell_test::fail "line ${LINENO}: bless failed"
"${PRINCIPAL_BIN}" dump >alice.dump || shell_test::fail "line ${LINENO}: dump failed"
# Run store setdefault, store default, store set, store forpeer on bob
# This time use the --veyron.credentials flag to set the principal.
"${PRINCIPAL_BIN}" --veyron.credentials=./bob store setdefault alice.bless || shell_test::fail "line ${LINENO}: store setdefault failed"
"${PRINCIPAL_BIN}" --veyron.credentials=./bob store default >bob.store.default || shell_test::fail "line ${LINENO}: store default failed"
"${PRINCIPAL_BIN}" --veyron.credentials=./bob store set alice.bless alice/... || shell_test::fail "line ${LINENO}: store set failed"
"${PRINCIPAL_BIN}" --veyron.credentials=./bob store forpeer alice/server >bob.store.forpeer || shell_test::fail "line ${LINENO}: store forpeer failed"
# Run recvblessings on carol, and have alice send blessings over
# (blessings received must be set as default and shareable with all peers.)
"${PRINCIPAL_BIN}" --veyron.credentials=./carol --veyron.tcp.address=127.0.0.1:0 recvblessings >carol.recvblessings&
shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" carol.recvblessings "bless --remote_key" || shell_test::fail "line ${LINENO}: recvblessings did not print command for sender"
local -r PRINCIPAL_BIN_DIR=$(dirname "${PRINCIPAL_BIN}")
local SEND_BLESSINGS_CMD=$(grep "bless --remote_key" carol.recvblessings | sed -e 's|extension[0-9]*|friend/carol|')
SEND_BLESSINGS_CMD="${PRINCIPAL_BIN_DIR}/${SEND_BLESSINGS_CMD}"
$(${SEND_BLESSINGS_CMD}) || shell_test::fail "line ${LINENO}: ${SEND_BLESSINGS_CMD} failed"
grep "Received blessings: alice/friend/carol" carol.recvblessings >/dev/null || shell_test::fail "line ${LINENO}: recvblessings did not log any blessings received $(cat carol.recvblessings)"
# Run recvblessings on carol, and have alice send blessings over
# (blessings received must be set as shareable with peers matching 'alice/...'.)
"${PRINCIPAL_BIN}" --veyron.credentials=./carol --veyron.tcp.address=127.0.0.1:0 recvblessings --for_peer=alice/... --set_default=false >carol.recvblessings&
shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" carol.recvblessings "bless --remote_key" || shell_test::fail "line ${LINENO}: recvblessings did not print command for sender"
SEND_BLESSINGS_CMD=$(grep "bless --remote_key" carol.recvblessings | sed -e 's|extension[0-9]*|friend/carol/foralice|')
SEND_BLESSINGS_CMD="${PRINCIPAL_BIN_DIR}/${SEND_BLESSINGS_CMD}"
$(${SEND_BLESSINGS_CMD}) || shell_test::fail "line ${LINENO}: ${SEND_BLESSINGS_CMD} failed"
grep "Received blessings: alice/friend/carol/foralice" carol.recvblessings >/dev/null || shell_test::fail "line ${LINENO}: recvblessings did not log any blessings received $(cat carol.recvblessings)"
# Mucking around with the public key should fail
"${PRINCIPAL_BIN}" --veyron.credentials=./carol --veyron.tcp.address=127.0.0.1:0 recvblessings >carol.recvblessings&
local -r RECV_BLESSINGS_PID="$!"
shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" carol.recvblessings "bless --remote_key" || shell_test::fail "line ${LINENO}: recvblessings did not print command for sender"
SEND_BLESSINGS_CMD=$(grep "bless --remote_key" carol.recvblessings | sed -e 's|remote_key=|remote_key=BAD|')
SEND_BLESSINGS_CMD="${PRINCIPAL_BIN_DIR}/${SEND_BLESSINGS_CMD}"
$(${SEND_BLESSINGS_CMD} 2>error) && shell_test::fail "line ${LINENO}: ${SEND_BLESSINGS_CMD} should have failed"
grep "key mismatch" error >/dev/null || shell_test::fail "line ${LINENO}: key mismatch error not printed"
# Mucking around with the token should fail
SEND_BLESSINGS_CMD=$(grep "bless --remote_key" carol.recvblessings | sed -e 's|remote_token=|remote_token=BAD|')
SEND_BLESSINGS_CMD="${PRINCIPAL_BIN_DIR}/${SEND_BLESSINGS_CMD}"
$(${SEND_BLESSINGS_CMD} 2>error) && shell_test::fail "line ${LINENO}: ${SEND_BLESSINGS_CMD} should have failed"
grep "blessings received from unexpected sender" error >/dev/null || shell_test::fail "line ${LINENO}: unexpected sender error not printed"
kill -9 "${RECV_BLESSINGS_PID}"
# Dump carol out, the only blessing that survives should be from the first
# "bless" command. (alice/friend/carol).
"${PRINCIPAL_BIN}" --veyron.credentials=./carol dump >carol.dump || shell_test::fail "line ${LINENO}: dump failed"
# Run fork to setup up credentials for alice-phone that are blessed by alice under the extension "phone".
"${PRINCIPAL_BIN}" --veyron.credentials=./alice fork ./alice-phone "phone" >/dev/null || shell_test::fail "line ${LINENO}: fork failed"
# Dump alice-phone out, the only blessings it has must be from alice (alice/phone).
"${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone dump >alice-phone.dump || shell_test::fail "line ${LINENO}: dump failed"
# Run fork to setup up credentials for alice-phone-calendar that are blessed by alice-phone under the extension "calendar".
"${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone fork ./alice-phone-calendar "calendar" >/dev/null || shell_test::fail "line ${LINENO}: fork failed"
# Dump alice-phone-calendar out, the only blessings it has must be from alice-phone (alice/phone/calendar).
"${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone-calendar dump >alice-phone-calendar.dump || shell_test::fail "line ${LINENO}: dump failed"
# Any other commands to be run without VEYRON_CREDENTIALS set.
unset VEYRON_CREDENTIALS
# Validate the output of various commands (mostly using "principal dump" or "principal dumpblessings")
cat alice.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice.dump | rmpublickey failed"
cat >want <<EOF
Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
---------------- BlessingStore ----------------
Default blessings: alice
Peer pattern : Blessings
... : alice
---------------- BlessingRoots ----------------
Public key : Pattern
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
dumpblessings alice.blessself >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
cat >want <<EOF
Blessings : alicereborn
PublicKey : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate chains : 1
Chain #0 (1 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate #0: alicereborn with 0 caveats
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
dumpblessings bob.store.default >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
cat >want <<EOF
Blessings : alice/friend
PublicKey : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate chains : 1
Chain #0 (2 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate #0: alice with 0 caveats
Certificate #1: friend with 1 caveat
(0) security.unixTimeExpiryCaveat
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
dumpblessings bob.store.forpeer >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
cat >want <<EOF
Blessings : bob#alice/friend
PublicKey : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate chains : 2
Chain #0 (1 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate #0: bob with 0 caveats
Chain #1 (2 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Certificate #0: alice with 0 caveats
Certificate #1: friend with 1 caveat
(0) security.unixTimeExpiryCaveat
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
cat carol.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat carol.dump | rmpublickey failed"
cat >want <<EOF
Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
---------------- BlessingStore ----------------
Default blessings: alice/friend/carol
Peer pattern : Blessings
... : alice/friend/carol
alice/... : alice/friend/carol/foralice
---------------- BlessingRoots ----------------
Public key : Pattern
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [carol/...]
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
cat alice-phone.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice-phone.dump | rmpublickey failed"
cat >want <<EOF
Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
---------------- BlessingStore ----------------
Default blessings: alice/phone
Peer pattern : Blessings
... : alice/phone
---------------- BlessingRoots ----------------
Public key : Pattern
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
cat alice-phone-calendar.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice-phone-calendar.dump | rmpublickey failed"
cat >want <<EOF
Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
---------------- BlessingStore ----------------
Default blessings: alice/phone/calendar
Peer pattern : Blessings
... : alice/phone/calendar
---------------- BlessingRoots ----------------
Public key : Pattern
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
EOF
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
shell_test::pass
}
main "$@"