blob: 5337a27d4566205984e747a0c41b92b34a026f1e [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main_test
import (
"crypto/tls"
"encoding/base64"
_ "encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"strings"
"testing"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/security"
"v.io/v23/services/stats"
"v.io/v23/vom"
"v.io/x/ref/test/testutil"
"v.io/x/ref/test/v23test"
)
const urlRE = "^(https://.*)$"
func httpGet(t *testing.T, url string) string {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
jar, err := cookiejar.New(&cookiejar.Options{})
if err != nil {
t.Fatalf("failed to create a cookie jar: %v", err)
}
client := &http.Client{
Jar: jar,
Transport: transport,
}
resp, err := client.Get(url)
if err != nil {
t.Fatalf("Get(%q) failed: %v", url, err)
}
output, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
t.Fatalf("ReadAll() failed: %v", err)
}
return string(output)
}
func seekBlessings(t *testing.T, sh *v23test.Shell, principal, httpAddr string) {
args := []string{
"seekblessings",
"--browser=false",
fmt.Sprintf("--from=%s/auth/google", httpAddr),
"-v=3",
}
cmd := sh.Cmd(principal, args...)
cmd.Start()
line := cmd.S.ExpectSetEventuallyRE(urlRE)[0][1]
// Scan the output of "principal seekblessings", looking for the
// URL that can be used to retrieve the blessings.
output := httpGet(t, line)
if want := "Received blessings: <tt>root:u:testemail@example.com:test-extension"; !strings.Contains(output, want) {
t.Fatalf("failed to seek blessings: %v", string(output))
}
}
func testOauthHandler(t *testing.T, addr string) {
p := testutil.NewPrincipal("foo")
keyBytes, err := p.PublicKey().MarshalBinary()
if err != nil {
t.Fatal(err)
}
url := addr + "/auth/google/bless?token=tok&output_format=base64vom&public_key=" + base64.URLEncoding.EncodeToString(keyBytes)
output := httpGet(t, url)
var blessings security.Blessings
if raw, err := base64.URLEncoding.DecodeString(output); err != nil {
t.Fatal(err)
} else if err = vom.Decode(raw, &blessings); err != nil {
t.Fatal(err)
}
expected := "root:o:test-client-id:testemail@example.com"
if !blessings.CouldHaveNames([]string{expected}) {
t.Fatalf("Wanted blessing root:o:clientid:email, got %v", blessings)
}
}
func readCounter(t *testing.T, ctx *context.T, addr, stat string) (int64, error) {
v, err := stats.StatsClient(naming.Join(addr, stat)).Value(ctx)
if err != nil {
return 0, err
}
var c int64
err = v.ToValue(&c)
return c, err
}
func TestV23IdentityServer(t *testing.T) {
v23test.SkipUnlessRunningIntegrationTests(t)
sh := v23test.NewShell(t, nil)
defer sh.Cleanup()
sh.StartRootMountTable()
// Start identityd:
//
// identityd must have credentials that recognize the root mounttable.
// In production, the two share a common root certificate and thus
// recognize each other. The same is done here: sh.Credentials.Principal
// wields the root key.
identityd := v23test.BuildGoPkg(sh, "v.io/x/ref/services/identity/internal/identityd_test")
creds := sh.ForkCredentials("u")
oauthCreds := sh.ForkCredentials("o")
cmd := sh.Cmd(identityd,
"-v23.tcp.address=127.0.0.1:0",
"-http-addr=127.0.0.1:0",
"-oauth-agent-path="+oauthCreds.Handle).WithCredentials(creds)
cmd.Start()
httpAddr := cmd.S.ExpectVar("HTTP_ADDR")
v23Addr := cmd.S.ExpectVar("NAME")
// Use the principal tool to seekblessings.
// This tool will not run with any credentials: Its whole purpose is to "seek" them!
principal := v23test.BuildGoPkg(sh, "v.io/x/ref/cmd/principal")
// Test an initial seekblessings call.
seekBlessings(t, sh, principal, httpAddr)
// Test that a subsequent call succeeds with the same
// credentials. This means that the blessings and principal from the
// first call works correctly.
// TODO(ashankar): Does anyone recall what was the intent here? Running
// the tool twice doesn't seem to help?
seekBlessings(t, sh, principal, httpAddr)
// Check stats: Since not blessings were issued over HTTP right now, the value should be 0.
if got, _ := readCounter(t, sh.ForkContext("u"), v23Addr, "__debug/stats/http/blessings/root:o"); got != 0 {
t.Errorf("Got %d, want 0 for the count of blessings issued over HTTP", got)
}
testOauthHandler(t, httpAddr)
if got, err := readCounter(t, sh.ForkContext("u"), v23Addr, "__debug/stats/http/blessings/root:o"); got != 1 || err != nil {
t.Errorf("Got (%d, %v), want (1, <nil>) for the count of blessings issued over HTTP", got, err)
}
}
func TestMain(m *testing.M) {
v23test.TestMain(m)
}