Skip to content

Commit

Permalink
attestationconfigapi: add GCP to uploading
Browse files Browse the repository at this point in the history
  • Loading branch information
msanft committed Apr 15, 2024
1 parent 5768288 commit 52dac84
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 51 deletions.
2 changes: 1 addition & 1 deletion .github/actions/e2e_verify/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ runs:
aws-region: eu-central-1

- name: Upload extracted TCBs
if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'aws-sev-snp')
if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'aws-sev-snp' || inputs.attestationVariant == 'gcp-sev-snp')
shell: bash
env:
COSIGN_PASSWORD: ${{ inputs.cosignPassword }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-attestationconfigapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fail-fast: false
max-parallel: 1
matrix:
csp: ["azure", "aws"]
csp: ["azure", "aws", "gcp"]
runs-on: ubuntu-22.04
permissions:
id-token: write
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/e2e-test-weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ jobs:
attestationVariant: "gcp-sev-es"
kubernetes-version: "v1.28"
clusterCreation: "cli"
- test: "verify"
refStream: "ref/release/stream/stable/?"
attestationVariant: "gcp-sev-snp"
kubernetes-version: "v1.28"
clusterCreation: "cli"
- test: "verify"
refStream: "ref/release/stream/stable/?"
attestationVariant: "azure-sev-snp"
Expand Down
2 changes: 1 addition & 1 deletion internal/api/attestationconfigapi/attestationconfigapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ information contained in the objects. Especially the paths used for the API are
in these helper methods.
Regarding the decision to implement new types over using the existing types from internal/config:
AttesationCfg objects for AttestationCfg API need to hold some version information (for sorting, recognizing latest).
AttestationCfg objects for AttestationCfg API need to hold some version information (for sorting, recognizing latest).
Thus, existing config types (AWSNitroTPM, AzureSEVSNP, ...) can not be extended to implement apiObject interface.
Instead, we need a separate type that wraps _all_ attestation types. In the codebase this is done using the AttestationCfg interface.
The new type AttestationCfgGet needs to be located inside internal/config in order to implement UnmarshalJSON.
Expand Down
12 changes: 7 additions & 5 deletions internal/api/attestationconfigapi/cli/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

func newUploadCmd() *cobra.Command {
uploadCmd := &cobra.Command{
Use: "upload {azure|aws} {snp-report|guest-firmware} <path>",
Use: "upload {aws|azure|gcp} {snp-report|guest-firmware} <path>",
Short: "Upload an object to the attestationconfig API",

Long: fmt.Sprintf("Upload a new object to the attestationconfig API. For snp-reports the new object is added to a cache folder first."+
Expand Down Expand Up @@ -92,17 +92,19 @@ func runUpload(cmd *cobra.Command, args []string) (retErr error) {
return fmt.Errorf("creating client: %w", err)
}

var attesation variant.Variant
var attestation variant.Variant
switch uploadCfg.provider {
case cloudprovider.AWS:
attesation = variant.AWSSEVSNP{}
attestation = variant.AWSSEVSNP{}
case cloudprovider.Azure:
attesation = variant.AzureSEVSNP{}
attestation = variant.AzureSEVSNP{}
case cloudprovider.GCP:
attestation = variant.GCPSEVSNP{}
default:
return fmt.Errorf("unsupported cloud provider: %s", uploadCfg.provider)
}

return uploadReport(ctx, attesation, client, uploadCfg, file.NewHandler(afero.NewOsFs()), log)
return uploadReport(ctx, attestation, client, uploadCfg, file.NewHandler(afero.NewOsFs()), log)
}

func uploadReport(ctx context.Context,
Expand Down
2 changes: 1 addition & 1 deletion internal/api/attestationconfigapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateK
return repo, clientClose, nil
}

// uploadSEVSNPVersion uploads the latest version numbers of the Azure SEVSNP. Then version name is the UTC timestamp of the date. The /list entry stores the version name + .json suffix.
// uploadSEVSNPVersion uploads the latest version numbers of the SEVSNP. Then version name is the UTC timestamp of the date. The /list entry stores the version name + .json suffix.
func (a Client) uploadSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error {
versions, err := a.List(ctx, attestation)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions internal/api/attestationconfigapi/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
*/

/*
The reporter contains the logic to determine a latest version for Azure SEVSNP based on cached version values observed on CVM instances.
The reporter contains the logic to determine a latest version for SEVSNP based on cached version values observed on CVM instances.
Some code in this file (e.g. listing cached files) does not rely on dedicated API objects and instead uses the AWS SDK directly,
for no other reason than original development speed.
*/
Expand Down Expand Up @@ -79,11 +79,11 @@ func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation varia
if err := c.uploadSEVSNPVersion(ctx, attestation, minVersion, t); err != nil {
return fmt.Errorf("uploading version: %w", err)
}
c.s3Client.Logger.Info(fmt.Sprintf("Successfully uploaded new Azure SEV-SNP version: %+v", minVersion))
c.s3Client.Logger.Info(fmt.Sprintf("Successfully uploaded new SEV-SNP version: %+v", minVersion))
return nil
}

// cacheSEVSNPVersion uploads the latest observed version numbers of the Azure SEVSNP. This version is used to later report the latest version numbers to the API.
// cacheSEVSNPVersion uploads the latest observed version numbers of the SEVSNP. This version is used to later report the latest version numbers to the API.
func (c Client) cacheSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error {
dateStr := date.Format(VersionFormat) + ".json"
res := putCmd{
Expand Down
10 changes: 5 additions & 5 deletions internal/api/attestationconfigapi/snp.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ import (
// AttestationURLPath is the URL path to the attestation versions.
const AttestationURLPath = "constellation/v1/attestation"

// SEVSNPVersion tracks the latest version of each component of the Azure SEVSNP.
// SEVSNPVersion tracks the latest version of each component of the SEVSNP.
type SEVSNPVersion struct {
// Bootloader is the latest version of the Azure SEVSNP bootloader.
// Bootloader is the latest version of the SEVSNP bootloader.
Bootloader uint8 `json:"bootloader"`
// TEE is the latest version of the Azure SEVSNP TEE.
// TEE is the latest version of the SEVSNP TEE.
TEE uint8 `json:"tee"`
// SNP is the latest version of the Azure SEVSNP SNP.
// SNP is the latest version of the SEVSNP SNP.
SNP uint8 `json:"snp"`
// Microcode is the latest version of the Azure SEVSNP microcode.
// Microcode is the latest version of the SEVSNP microcode.
Microcode uint8 `json:"microcode"`
}

Expand Down
6 changes: 3 additions & 3 deletions internal/attestation/gcp/snp/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ func getInstanceInfo(_ context.Context, _ io.ReadWriteCloser, extraData []byte)
if len(extraData) > 64 {
return nil, fmt.Errorf("extra data too long: %d, should be 64 bytes at most", len(extraData))
}
truncatedExtraData := make([]byte, 64)
copy(truncatedExtraData, extraData)
extraData64 := make([]byte, 64)
copy(extraData64, extraData)

device, err := sevclient.OpenDevice()
if err != nil {
return nil, fmt.Errorf("opening sev device: %w", err)
}
defer device.Close()

report, certs, err := sevclient.GetRawExtendedReportAtVmpl(device, [64]byte(truncatedExtraData), 0)
report, certs, err := sevclient.GetRawExtendedReportAtVmpl(device, [64]byte(extraData64), 0)
if err != nil {
return nil, fmt.Errorf("getting extended report: %w", err)
}
Expand Down
58 changes: 27 additions & 31 deletions internal/config/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,35 @@ func (c *GCPSEVSNP) getToMarshallLatestWithResolvedVersions() AttestationCfg {
}

// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
func (c *GCPSEVSNP) FetchAndSetLatestVersionNumbers(_ context.Context, _ attestationconfigapi.Fetcher) error {
panic("not implemented")

// TODO(msanft): Implement with https://dev.azure.com/Edgeless/Edgeless/_workitems/edit/4024

// // Only talk to the API if at least one version number is set to latest.
// if !(c.BootloaderVersion.WantLatest || c.TEEVersion.WantLatest || c.SNPVersion.WantLatest || c.MicrocodeVersion.WantLatest) {
// return nil
// }

// versions, err := fetcher.FetchSEVSNPVersionLatest(ctx, variant.GCPSEVSNP{})
// if err != nil {
// return fmt.Errorf("fetching latest TCB versions from configapi: %w", err)
// }
// // set number and keep isLatest flag
// c.mergeWithLatestVersion(versions.SEVSNPVersion)
// return nil
func (c *GCPSEVSNP) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher attestationconfigapi.Fetcher) error {
// Only talk to the API if at least one version number is set to latest.
if !(c.BootloaderVersion.WantLatest || c.TEEVersion.WantLatest || c.SNPVersion.WantLatest || c.MicrocodeVersion.WantLatest) {
return nil
}

versions, err := fetcher.FetchSEVSNPVersionLatest(ctx, variant.GCPSEVSNP{})
if err != nil {
return fmt.Errorf("fetching latest TCB versions from configapi: %w", err)
}
// set number and keep isLatest flag
c.mergeWithLatestVersion(versions.SEVSNPVersion)
return nil
}

// func (c *GCPSEVSNP) mergeWithLatestVersion(latest attestationconfigapi.SEVSNPVersion) {
// if c.BootloaderVersion.WantLatest {
// c.BootloaderVersion.Value = latest.Bootloader
// }
// if c.TEEVersion.WantLatest {
// c.TEEVersion.Value = latest.TEE
// }
// if c.SNPVersion.WantLatest {
// c.SNPVersion.Value = latest.SNP
// }
// if c.MicrocodeVersion.WantLatest {
// c.MicrocodeVersion.Value = latest.Microcode
// }
// }
func (c *GCPSEVSNP) mergeWithLatestVersion(latest attestationconfigapi.SEVSNPVersion) {
if c.BootloaderVersion.WantLatest {
c.BootloaderVersion.Value = latest.Bootloader
}
if c.TEEVersion.WantLatest {
c.TEEVersion.Value = latest.TEE
}
if c.SNPVersion.WantLatest {
c.SNPVersion.Value = latest.SNP
}
if c.MicrocodeVersion.WantLatest {
c.MicrocodeVersion.Value = latest.Microcode
}
}

// GetVariant returns gcp-sev-es as the variant.
func (GCPSEVES) GetVariant() variant.Variant {
Expand Down

0 comments on commit 52dac84

Please sign in to comment.