intenal: add logging to attestation issuer (#1264)

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-02-28 16:34:18 +01:00 committed by GitHub
parent af8c6e70ad
commit b3486fc32b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 63 additions and 28 deletions

View File

@ -82,7 +82,7 @@ func main() {
log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs") log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs")
} }
issuer = aws.NewIssuer() issuer = aws.NewIssuer(log)
metadata, err := awscloud.New(ctx) metadata, err := awscloud.New(ctx)
if err != nil { if err != nil {
@ -108,7 +108,7 @@ func main() {
log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs") log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs")
} }
issuer = gcp.NewIssuer() issuer = gcp.NewIssuer(log)
metadata, err := gcpcloud.New(ctx) metadata, err := gcpcloud.New(ctx)
if err != nil { if err != nil {
@ -137,10 +137,10 @@ func main() {
} }
if _, err := snp.GetIDKeyDigest(vtpm.OpenVTPM); err == nil { if _, err := snp.GetIDKeyDigest(vtpm.OpenVTPM); err == nil {
issuer = snp.NewIssuer() issuer = snp.NewIssuer(log)
} else { } else {
// assume we are running in a trusted-launch VM // assume we are running in a trusted-launch VM
issuer = trustedlaunch.NewIssuer() issuer = trustedlaunch.NewIssuer(log)
} }
metadata, err := azurecloud.New(ctx) metadata, err := azurecloud.New(ctx)
@ -166,7 +166,7 @@ func main() {
log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs") log.With(zap.Error(err)).Fatalf("Failed to get selected PCRs")
} }
issuer = qemu.NewIssuer() issuer = qemu.NewIssuer(log)
cloudLogger = qemucloud.NewLogger() cloudLogger = qemucloud.NewLogger()
metadata := qemucloud.New() metadata := qemucloud.New()

View File

@ -79,7 +79,7 @@ func main() {
log.With(zap.Error(err)).Fatalf("Failed to set up AWS metadata API") log.With(zap.Error(err)).Fatalf("Failed to set up AWS metadata API")
} }
issuer = aws.NewIssuer() issuer = aws.NewIssuer(log)
case cloudprovider.Azure: case cloudprovider.Azure:
diskPath, err = filepath.EvalSymlinks(azureStateDiskPath) diskPath, err = filepath.EvalSymlinks(azureStateDiskPath)
@ -92,7 +92,7 @@ func main() {
log.With(zap.Error).Fatalf("Failed to set up Azure metadata API") log.With(zap.Error).Fatalf("Failed to set up Azure metadata API")
} }
issuer = azure.NewIssuer() issuer = azure.NewIssuer(log)
case cloudprovider.GCP: case cloudprovider.GCP:
diskPath, err = filepath.EvalSymlinks(gcpStateDiskPath) diskPath, err = filepath.EvalSymlinks(gcpStateDiskPath)
@ -100,7 +100,7 @@ func main() {
_ = exportPCRs() _ = exportPCRs()
log.With(zap.Error(err)).Fatalf("Unable to resolve GCP state disk path") log.With(zap.Error(err)).Fatalf("Unable to resolve GCP state disk path")
} }
issuer = gcp.NewIssuer() issuer = gcp.NewIssuer(log)
gcpMeta, err := gcpcloud.New(context.Background()) gcpMeta, err := gcpcloud.New(context.Background())
if err != nil { if err != nil {
log.With(zap.Error).Fatalf("Failed to create GCP client") log.With(zap.Error).Fatalf("Failed to create GCP client")
@ -116,7 +116,7 @@ func main() {
case cloudprovider.QEMU: case cloudprovider.QEMU:
diskPath = qemuStateDiskPath diskPath = qemuStateDiskPath
issuer = qemu.NewIssuer() issuer = qemu.NewIssuer(log)
metadataAPI = qemucloud.New() metadataAPI = qemucloud.New()
_ = exportPCRs() _ = exportPCRs()

View File

@ -28,12 +28,13 @@ type Issuer struct {
} }
// NewIssuer creates a new OpenVTPM based issuer for AWS. // NewIssuer creates a new OpenVTPM based issuer for AWS.
func NewIssuer() *Issuer { func NewIssuer(log vtpm.AttestationLogger) *Issuer {
return &Issuer{ return &Issuer{
Issuer: vtpm.NewIssuer( Issuer: vtpm.NewIssuer(
vtpm.OpenVTPM, vtpm.OpenVTPM,
getAttestationKey, getAttestationKey,
getInstanceInfo(imds.New(imds.Options{})), getInstanceInfo(imds.New(imds.Options{})),
log,
), ),
} }
} }

View File

@ -28,9 +28,9 @@ import (
// NewIssuer returns an SNP issuer if it can successfully read the idkeydigest from the TPM. // NewIssuer returns an SNP issuer if it can successfully read the idkeydigest from the TPM.
// Otherwise returns a Trusted Launch issuer. // Otherwise returns a Trusted Launch issuer.
func NewIssuer() atls.Issuer { func NewIssuer(log vtpm.AttestationLogger) atls.Issuer {
if _, err := snp.GetIDKeyDigest(vtpm.OpenVTPM); err == nil { if _, err := snp.GetIDKeyDigest(vtpm.OpenVTPM); err == nil {
return snp.NewIssuer() return snp.NewIssuer(log)
} }
return trustedlaunch.NewIssuer() return trustedlaunch.NewIssuer(log)
} }

View File

@ -56,7 +56,7 @@ type Issuer struct {
} }
// NewIssuer initializes a new Azure Issuer. // NewIssuer initializes a new Azure Issuer.
func NewIssuer() *Issuer { func NewIssuer(log vtpm.AttestationLogger) *Issuer {
imdsAPI := imdsClient{ imdsAPI := imdsClient{
client: &http.Client{Transport: &http.Transport{Proxy: nil}}, client: &http.Client{Transport: &http.Transport{Proxy: nil}},
} }
@ -66,6 +66,7 @@ func NewIssuer() *Issuer {
vtpm.OpenVTPM, vtpm.OpenVTPM,
getAttestationKey, getAttestationKey,
getInstanceInfo(&tpmReport{}, imdsAPI), getInstanceInfo(&tpmReport{}, imdsAPI),
log,
), ),
} }
} }

View File

@ -35,7 +35,7 @@ type Issuer struct {
} }
// NewIssuer initializes a new Azure Issuer. // NewIssuer initializes a new Azure Issuer.
func NewIssuer() *Issuer { func NewIssuer(log vtpm.AttestationLogger) *Issuer {
i := &Issuer{ i := &Issuer{
hClient: &http.Client{}, hClient: &http.Client{},
} }
@ -43,6 +43,7 @@ func NewIssuer() *Issuer {
vtpm.OpenVTPM, vtpm.OpenVTPM,
getAttestationKey, getAttestationKey,
i.getAttestationCert, i.getAttestationCert,
log,
) )
return i return i
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/simulator" "github.com/edgelesssys/constellation/v2/internal/attestation/simulator"
"github.com/edgelesssys/constellation/v2/internal/crypto" "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/logger"
tpmclient "github.com/google/go-tpm-tools/client" tpmclient "github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm/tpm2" "github.com/google/go-tpm/tpm2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -179,7 +180,7 @@ func TestGetAttestationCert(t *testing.T) {
)) ))
require.NoError(tpm2.NVWrite(tpm, tpm2.HandleOwner, tpmAkCertIdx, "", akCert, 0)) require.NoError(tpm2.NVWrite(tpm, tpm2.HandleOwner, tpmAkCertIdx, "", akCert, 0))
issuer := NewIssuer() issuer := NewIssuer(logger.NewTest(t))
issuer.hClient = newTestClient(tc.crlServer) issuer.hClient = newTestClient(tc.crlServer)
certs, err := issuer.getAttestationCert(tpm) certs, err := issuer.getAttestationCert(tpm)

View File

@ -25,12 +25,13 @@ type Issuer struct {
} }
// NewIssuer initializes a new GCP Issuer. // NewIssuer initializes a new GCP Issuer.
func NewIssuer() *Issuer { func NewIssuer(log vtpm.AttestationLogger) *Issuer {
return &Issuer{ return &Issuer{
Issuer: vtpm.NewIssuer( Issuer: vtpm.NewIssuer(
vtpm.OpenVTPM, vtpm.OpenVTPM,
tpmclient.GceAttestationKeyRSA, tpmclient.GceAttestationKeyRSA,
getGCEInstanceInfo(metadataClient{}), getGCEInstanceInfo(metadataClient{}),
log,
), ),
} }
} }

View File

@ -21,12 +21,13 @@ type Issuer struct {
} }
// NewIssuer initializes a new QEMU Issuer. // NewIssuer initializes a new QEMU Issuer.
func NewIssuer() *Issuer { func NewIssuer(log vtpm.AttestationLogger) *Issuer {
return &Issuer{ return &Issuer{
Issuer: vtpm.NewIssuer( Issuer: vtpm.NewIssuer(
vtpm.OpenVTPM, vtpm.OpenVTPM,
tpmclient.AttestationKeyRSA, tpmclient.AttestationKeyRSA,
func(tpm io.ReadWriteCloser) ([]byte, error) { return nil, nil }, func(tpm io.ReadWriteCloser) ([]byte, error) { return nil, nil },
log,
), ),
} }
} }

View File

@ -85,19 +85,34 @@ type Issuer struct {
openTPM TPMOpenFunc openTPM TPMOpenFunc
getAttestationKey GetTPMAttestationKey getAttestationKey GetTPMAttestationKey
getInstanceInfo GetInstanceInfo getInstanceInfo GetInstanceInfo
log AttestationLogger
} }
// NewIssuer returns a new Issuer. // NewIssuer returns a new Issuer.
func NewIssuer(openTPM TPMOpenFunc, getAttestationKey GetTPMAttestationKey, getInstanceInfo GetInstanceInfo) *Issuer { func NewIssuer(
openTPM TPMOpenFunc, getAttestationKey GetTPMAttestationKey,
getInstanceInfo GetInstanceInfo, log AttestationLogger,
) *Issuer {
if log == nil {
log = &nopAttestationLogger{}
}
return &Issuer{ return &Issuer{
openTPM: openTPM, openTPM: openTPM,
getAttestationKey: getAttestationKey, getAttestationKey: getAttestationKey,
getInstanceInfo: getInstanceInfo, getInstanceInfo: getInstanceInfo,
log: log,
} }
} }
// Issue generates an attestation document using a TPM. // Issue generates an attestation document using a TPM.
func (i *Issuer) Issue(userData []byte, nonce []byte) ([]byte, error) { func (i *Issuer) Issue(userData []byte, nonce []byte) (res []byte, err error) {
i.log.Infof("Issuing attestation statement")
defer func() {
if err != nil {
i.log.Warnf("Failed to issue attestation statement: %s", err)
}
}()
tpm, err := i.openTPM() tpm, err := i.openTPM()
if err != nil { if err != nil {
return nil, fmt.Errorf("opening TPM: %w", err) return nil, fmt.Errorf("opening TPM: %w", err)
@ -113,7 +128,7 @@ func (i *Issuer) Issue(userData []byte, nonce []byte) ([]byte, error) {
// Create an attestation using the loaded key // Create an attestation using the loaded key
extraData := makeExtraData(userData, nonce) extraData := makeExtraData(userData, nonce)
attestation, err := aK.Attest(tpmClient.AttestOpts{Nonce: extraData}) tpmAttestation, err := aK.Attest(tpmClient.AttestOpts{Nonce: extraData})
if err != nil { if err != nil {
return nil, fmt.Errorf("creating attestation: %w", err) return nil, fmt.Errorf("creating attestation: %w", err)
} }
@ -125,11 +140,18 @@ func (i *Issuer) Issue(userData []byte, nonce []byte) ([]byte, error) {
} }
attDoc := AttestationDocument{ attDoc := AttestationDocument{
Attestation: attestation, Attestation: tpmAttestation,
InstanceInfo: instanceInfo, InstanceInfo: instanceInfo,
UserData: userData, UserData: userData,
} }
return json.Marshal(attDoc)
rawAttDoc, err := json.Marshal(attDoc)
if err != nil {
return nil, fmt.Errorf("marshaling attestation document: %w", err)
}
i.log.Infof("Successfully issued attestation statement")
return rawAttDoc, nil
} }
// Validator handles validation of TPM based attestation. // Validator handles validation of TPM based attestation.

View File

@ -16,6 +16,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
tpmsim "github.com/edgelesssys/constellation/v2/internal/attestation/simulator" tpmsim "github.com/edgelesssys/constellation/v2/internal/attestation/simulator"
"github.com/edgelesssys/constellation/v2/internal/logger"
tpmclient "github.com/google/go-tpm-tools/client" tpmclient "github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm-tools/proto/tpm" "github.com/google/go-tpm-tools/proto/tpm"
@ -75,7 +76,7 @@ func TestValidate(t *testing.T) {
tpmOpen, tpmCloser := tpmsim.NewSimulatedTPMOpenFunc() tpmOpen, tpmCloser := tpmsim.NewSimulatedTPMOpenFunc()
defer tpmCloser.Close() defer tpmCloser.Close()
issuer := NewIssuer(tpmOpen, tpmclient.AttestationKeyRSA, fakeGetInstanceInfo) issuer := NewIssuer(tpmOpen, tpmclient.AttestationKeyRSA, fakeGetInstanceInfo, logger.NewTest(t))
validator := NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, nil) validator := NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, nil)
nonce := []byte{1, 2, 3, 4} nonce := []byte{1, 2, 3, 4}
@ -266,6 +267,7 @@ func TestFailIssuer(t *testing.T) {
}, },
tpmclient.AttestationKeyRSA, tpmclient.AttestationKeyRSA,
fakeGetInstanceInfo, fakeGetInstanceInfo,
nil,
), ),
userData: []byte("Constellation"), userData: []byte("Constellation"),
nonce: []byte{1, 2, 3, 4}, nonce: []byte{1, 2, 3, 4},
@ -277,6 +279,7 @@ func TestFailIssuer(t *testing.T) {
return nil, errors.New("failure") return nil, errors.New("failure")
}, },
fakeGetInstanceInfo, fakeGetInstanceInfo,
nil,
), ),
userData: []byte("Constellation"), userData: []byte("Constellation"),
nonce: []byte{1, 2, 3, 4}, nonce: []byte{1, 2, 3, 4},
@ -288,6 +291,7 @@ func TestFailIssuer(t *testing.T) {
return &tpmclient.Key{}, nil return &tpmclient.Key{}, nil
}, },
fakeGetInstanceInfo, fakeGetInstanceInfo,
nil,
), ),
userData: []byte("Constellation"), userData: []byte("Constellation"),
nonce: []byte{1, 2, 3, 4}, nonce: []byte{1, 2, 3, 4},
@ -297,6 +301,7 @@ func TestFailIssuer(t *testing.T) {
newSimTPMWithEventLog, newSimTPMWithEventLog,
tpmclient.AttestationKeyRSA, tpmclient.AttestationKeyRSA,
func(io.ReadWriteCloser) ([]byte, error) { return nil, errors.New("failure") }, func(io.ReadWriteCloser) ([]byte, error) { return nil, errors.New("failure") },
nil,
), ),
userData: []byte("Constellation"), userData: []byte("Constellation"),
nonce: []byte{1, 2, 3, 4}, nonce: []byte{1, 2, 3, 4},
@ -307,6 +312,8 @@ func TestFailIssuer(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
tc.issuer.log = logger.NewTest(t)
_, err := tc.issuer.Issue(tc.userData, tc.nonce) _, err := tc.issuer.Issue(tc.userData, tc.nonce)
assert.Error(err) assert.Error(err)
}) })

View File

@ -35,13 +35,13 @@ func main() {
var issuer server.AttestationIssuer var issuer server.AttestationIssuer
switch cloudprovider.FromString(*provider) { switch cloudprovider.FromString(*provider) {
case cloudprovider.AWS: case cloudprovider.AWS:
issuer = aws.NewIssuer() issuer = aws.NewIssuer(log)
case cloudprovider.GCP: case cloudprovider.GCP:
issuer = gcp.NewIssuer() issuer = gcp.NewIssuer(log)
case cloudprovider.Azure: case cloudprovider.Azure:
issuer = azure.NewIssuer() issuer = azure.NewIssuer(log)
case cloudprovider.QEMU: case cloudprovider.QEMU:
issuer = qemu.NewIssuer() issuer = qemu.NewIssuer(log)
default: default:
log.With(zap.String("cloudProvider", *provider)).Fatalf("Unknown cloud provider") log.With(zap.String("cloudProvider", *provider)).Fatalf("Unknown cloud provider")
} }