Skip to content

Commit

Permalink
Add fake client for launcher/verifier/client interface (#234)
Browse files Browse the repository at this point in the history
Fix test with new Fake Client

Co-authored-by: Josh Krstic <jkrstic@google.com>
  • Loading branch information
JoshuaKrstic and Josh Krstic authored Aug 20, 2022
1 parent 4292990 commit fb6d253
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 226 deletions.
2 changes: 1 addition & 1 deletion launcher/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (a *agent) MeasureEvent(event cel.Content) error {

// Attest fetches the nonce and connection ID from the Attestation Service,
// creates an attestation message, and returns the resultant
// principalIDTokens are Metadata Server-generated ID tokens for the instance.
// principalIDTokens and Metadata Server-generated ID tokens for the instance.
func (a *agent) Attest(ctx context.Context) ([]byte, error) {
challenge, err := a.client.CreateChallenge(ctx)
if err != nil {
Expand Down
64 changes: 32 additions & 32 deletions launcher/agent/agent_test.go
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
package agent

import (
"bytes"
"context"
"log"
"net"
"crypto/rand"
"crypto/rsa"
"fmt"
"testing"

"github.com/golang-jwt/jwt/v4"
"github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm-tools/internal/test"
"github.com/google/go-tpm-tools/launcher/verifier/grpcclient"
"github.com/google/go-tpm-tools/launcher/verifier/grpcclient/service"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/test/bufconn"

servgrpc "github.com/google/go-tpm-tools/launcher/verifier/grpcclient/proto/attestation_verifier/v0"
"github.com/google/go-tpm-tools/launcher/verifier/fake"
)

func TestAttest(t *testing.T) {
tpm := test.GetTPM(t)
defer client.CheckedClose(t, tpm)

server := grpc.NewServer()

fakeServer := service.New()
servgrpc.RegisterAttestationVerifierServer(server, &fakeServer)

lis := bufconn.Listen(1024 * 1024)
go func() {
if err := server.Serve(lis); err != nil {
log.Fatalf("Server exited with error: %v", err)
}
}()
bufDialer := func(context.Context, string) (net.Conn, error) {
return lis.Dial()
}

conn, err := grpc.DialContext(context.Background(), "bufconn", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
fakeSigner, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("failed to connect to attestation service: %v", err)
t.Errorf("Failed to generate signing key %v", err)
}
verifierClient := grpcclient.NewClient(conn, log.Default())
// Cannot test a GCE key on the simulator.
verifierClient := fake.NewClient(fakeSigner)
agent := CreateAttestationAgent(tpm, client.AttestationKeyECC, verifierClient, placeholderFetcher)

token, err := agent.Attest(context.Background())
tokenBytes, err := agent.Attest(context.Background())
if err != nil {
t.Errorf("failed to attest to Attestation Service: %v", err)
}

if !bytes.Equal(token, service.FakeToken) {
t.Errorf("received unexpected token: %v, expected: %v", token, service.FakeToken)
registeredClaims := &jwt.RegisteredClaims{}
keyFunc := func(token *jwt.Token) (interface{}, error) { return fakeSigner.Public(), nil }
token, err := jwt.ParseWithClaims(string(tokenBytes), registeredClaims, keyFunc)
if err != nil {
t.Errorf("Failed to parse token %s", err)
}

if err = registeredClaims.Valid(); err != nil {
t.Errorf("Invalid exp, iat, or nbf: %s", err)
}

if !registeredClaims.VerifyAudience("https://sts.googleapis.com/", true) {
t.Errorf("Invalid aud")
}

if !registeredClaims.VerifyIssuer("https://confidentialcomputing.googleapis.com/", true) {
t.Errorf("Invalid iss")
}

if registeredClaims.Subject != "https://www.googleapis.com/compute/v1/projects/fakeProject/zones/fakeZone/instances/fakeInstance" {
t.Errorf("Invalid sub")
}

fmt.Printf("token.Claims: %v\n", token.Claims)
}

func placeholderFetcher(audience string) ([][]byte, error) {
Expand Down
66 changes: 66 additions & 0 deletions launcher/verifier/fake/fakeverifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Package fake is a fake implementation of the Client interface for testing.
package fake

import (
"context"
"crypto"
"encoding/binary"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/google/go-tpm-tools/launcher/verifier"
)

type fakeClient struct {
signer crypto.Signer
}

// NewClient contructs a new fake client given a crypto.Signer.
func NewClient(signer crypto.Signer) verifier.Client {
return &fakeClient{signer}
}

// CreateChallenge returns a hard coded, basic challenge.
//
// If you have found this method is insufficient for your tests, this class must be updated to
// allow for better testing.
func (fc *fakeClient) CreateChallenge(ctx context.Context) (*verifier.Challenge, error) {
bs := make([]byte, 2)
binary.LittleEndian.PutUint16(bs, 15)
return &verifier.Challenge{
Name: "projects/fakeProject/locations/fakeRegion/challenges/d882c62f-452f-4709-9335-0cccaf64eee1",
Nonce: bs,
}, nil
}

// VerifyAttestation does basic checks and returns a hard coded attestation response.
//
// If you have found this method is insufficient for your tests, this class must be updated to
// allow for better testing.
func (fc *fakeClient) VerifyAttestation(ctx context.Context, request verifier.VerifyAttestationRequest) (*verifier.VerifyAttestationResponse, error) {
// Determine signing algorithm.
signingMethod := jwt.SigningMethodRS256
now := jwt.TimeFunc()
claims := jwt.RegisteredClaims{
IssuedAt: &jwt.NumericDate{Time: now},
NotBefore: &jwt.NumericDate{Time: now},
ExpiresAt: &jwt.NumericDate{Time: now.Add(time.Hour)},
Audience: []string{"https://sts.googleapis.com/"},
Issuer: "https://confidentialcomputing.googleapis.com/",
Subject: "https://www.googleapis.com/compute/v1/projects/fakeProject/zones/fakeZone/instances/fakeInstance",
}

token := jwt.NewWithClaims(signingMethod, claims)

// Instead of a private key, provide the signer.
signed, err := token.SignedString(fc.signer)
if err != nil {
return nil, err
}

response := verifier.VerifyAttestationResponse{
ClaimsToken: []byte(signed),
}

return &response, nil
}
81 changes: 0 additions & 81 deletions launcher/verifier/grpcclient/service/fake_attestationverifier.go

This file was deleted.

111 changes: 0 additions & 111 deletions launcher/verifier/grpcclient/service/fake_attestationverifier_test.go

This file was deleted.

This file was deleted.

0 comments on commit fb6d253

Please sign in to comment.