config: dynamic attestation configuration through S3 backed API (#1808)

This commit is contained in:
Adrian Stobbe 2023-05-25 17:43:44 +01:00 committed by GitHub
parent 25211dc154
commit 0a6e5ec02e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 1020 additions and 302 deletions

View file

@ -13,11 +13,11 @@ RUN go mod download
COPY . . COPY . .
# Build # Build
WORKDIR /workspace/internal/versionsapi/cli WORKDIR /workspace/internal/api/versionsapi/cli
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o versionsapi . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o versionsapi .
FROM scratch as release FROM scratch as release
COPY --from=builder /workspace/internal/versionsapi/cli/versionsapi . COPY --from=builder /workspace/internal/api/versionsapi/cli/versionsapi .
CMD ["/notIntendedToBeExecuted"] CMD ["/notIntendedToBeExecuted"]

View file

@ -6,7 +6,7 @@ on:
branches: branches:
- main - main
paths: paths:
- "internal/versionsapi/**" - "internal/api/versionsapi/**"
- ".github/workflows/build-versionsapi-ci-image.yml" - ".github/workflows/build-versionsapi-ci-image.yml"
- ".github/actions/versionsapi/**" - ".github/actions/versionsapi/**"

View file

@ -36,7 +36,7 @@
/internal/retry @katexochen /internal/retry @katexochen
/internal/sigstore @malt3 /internal/sigstore @malt3
/internal/versions @katexochen /internal/versions @katexochen
/internal/versionsapi @katexochen /internal/api/versionsapi @katexochen
/joinservice @daniel-weisse /joinservice @daniel-weisse
/keyservice @daniel-weisse /keyservice @daniel-weisse
/operators @malt3 /operators @malt3

View file

@ -46,6 +46,8 @@ go_library(
"//cli/internal/terraform", "//cli/internal/terraform",
"//cli/internal/upgrade", "//cli/internal/upgrade",
"//disk-mapper/recoverproto", "//disk-mapper/recoverproto",
"//internal/api/fetcher",
"//internal/api/versionsapi",
"//internal/atls", "//internal/atls",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/azureshared", "//internal/cloud/azureshared",
@ -71,8 +73,6 @@ go_library(
"//internal/sigstore", "//internal/sigstore",
"//internal/variant", "//internal/variant",
"//internal/versions", "//internal/versions",
"//internal/versionsapi",
"//internal/versionsapi/fetcher",
"//operators/constellation-node-operator/api/v1alpha1", "//operators/constellation-node-operator/api/v1alpha1",
"//verify/verifyproto", "//verify/verifyproto",
"@com_github_mattn_go_isatty//:go-isatty", "@com_github_mattn_go_isatty//:go-isatty",
@ -126,6 +126,7 @@ go_test(
"//cli/internal/terraform", "//cli/internal/terraform",
"//cli/internal/upgrade", "//cli/internal/upgrade",
"//disk-mapper/recoverproto", "//disk-mapper/recoverproto",
"//internal/api/versionsapi",
"//internal/atls", "//internal/atls",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
@ -142,7 +143,6 @@ go_test(
"//internal/logger", "//internal/logger",
"//internal/variant", "//internal/variant",
"//internal/versions", "//internal/versions",
"//internal/versionsapi",
"//operators/constellation-node-operator/api/v1alpha1", "//operators/constellation-node-operator/api/v1alpha1",
"//verify/verifyproto", "//verify/verifyproto",
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",

View file

@ -14,12 +14,12 @@ import (
"net/url" "net/url"
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -77,7 +77,7 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
cfm.log.Debugf("Using flags %v", flags) cfm.log.Debugf("Using flags %v", flags)
cfm.log.Debugf("Loading configuration file from %q", flags.configPath) cfm.log.Debugf("Loading configuration file from %q", flags.configPath)
conf, err := config.New(fileHandler, flags.configPath, flags.force) conf, err := config.NewWithClient(fileHandler, flags.configPath, client, flags.force)
var configValidationErr *config.ValidationError var configValidationErr *config.ValidationError
if errors.As(err, &configValidationErr) { if errors.As(err, &configValidationErr) {
cmd.PrintErrln(configValidationErr.LongMessage()) cmd.PrintErrln(configValidationErr.LongMessage())

View file

@ -15,12 +15,12 @@ import (
"net/url" "net/url"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

View file

@ -17,6 +17,8 @@ import (
"github.com/edgelesssys/constellation/v2/cli/internal/helm" "github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes" "github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/compatibility"
@ -28,8 +30,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/versionsapi/fetcher"
"github.com/siderolabs/talos/pkg/machinery/config/encoder" "github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -67,7 +67,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
if err != nil { if err != nil {
return err return err
} }
versionListFetcher := fetcher.NewFetcher() versionListFetcher := fetcher.NewVersionAPIFetcher()
rekor, err := sigstore.NewRekor() rekor, err := sigstore.NewRekor()
if err != nil { if err != nil {
return fmt.Errorf("constructing Rekor client: %w", err) return fmt.Errorf("constructing Rekor client: %w", err)
@ -83,7 +83,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
flags: flags, flags: flags,
cliVersion: compatibility.EnsurePrefixV(constants.VersionInfo()), cliVersion: compatibility.EnsurePrefixV(constants.VersionInfo()),
log: log, log: log,
versionsapi: fetcher.NewFetcher(), versionsapi: fetcher.NewVersionAPIFetcher(),
}, },
log: log, log: log,
} }

View file

@ -15,6 +15,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
@ -22,7 +23,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

View file

@ -14,6 +14,7 @@ go_library(
"//cli/internal/helm", "//cli/internal/helm",
"//cli/internal/terraform", "//cli/internal/terraform",
"//cli/internal/upgrade", "//cli/internal/upgrade",
"//internal/api/versionsapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/compatibility", "//internal/compatibility",
@ -26,7 +27,6 @@ go_library(
"//internal/variant", "//internal/variant",
"//internal/versions", "//internal/versions",
"//internal/versions/components", "//internal/versions/components",
"//internal/versionsapi",
"//operators/constellation-node-operator/api/v1alpha1", "//operators/constellation-node-operator/api/v1alpha1",
"@io_k8s_api//core/v1:core", "@io_k8s_api//core/v1:core",
"@io_k8s_apimachinery//pkg/api/errors", "@io_k8s_apimachinery//pkg/api/errors",

View file

@ -18,6 +18,7 @@ import (
"github.com/edgelesssys/constellation/v2/cli/internal/helm" "github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform" "github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/upgrade" "github.com/edgelesssys/constellation/v2/cli/internal/upgrade"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/compatibility"
@ -30,7 +31,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/edgelesssys/constellation/v2/internal/versions/components" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors"

View file

@ -22,7 +22,7 @@ With `cdbg` and `yq` installed in your path:
1. Run `constellation config generate` to create a new default configuration 1. Run `constellation config generate` to create a new default configuration
2. Locate the latest debugd images by running `(cd internal/versionsapi/cli && go build -o versionsapi . && ./versionsapi latest --ref main --stream debug)` 2. Locate the latest debugd images by running `(cd internal/api/versionsapi/cli && go build -o versionsapi . && ./versionsapi latest --ref main --stream debug)`
3. Modify the `constellation-conf.yaml` to use an image with the debugd already included and add required firewall rules: 3. Modify the `constellation-conf.yaml` to use an image with the debugd already included and add required firewall rules:

View file

@ -11,13 +11,13 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/e2e/internal/upgrade", importpath = "github.com/edgelesssys/constellation/v2/e2e/internal/upgrade",
visibility = ["//e2e:__subpackages__"], visibility = ["//e2e:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/constants", "//internal/constants",
"//internal/imagefetcher", "//internal/imagefetcher",
"//internal/logger", "//internal/logger",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"@sh_helm_helm_v3//pkg/action", "@sh_helm_helm_v3//pkg/action",
"@sh_helm_helm_v3//pkg/cli", "@sh_helm_helm_v3//pkg/cli",
], ],

View file

@ -12,11 +12,11 @@ import (
"context" "context"
"net/http" "net/http"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/imagefetcher" "github.com/edgelesssys/constellation/v2/internal/imagefetcher"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
type upgradeInfo struct { type upgradeInfo struct {

View file

@ -6,10 +6,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/hack/cli-k8s-compatibility", importpath = "github.com/edgelesssys/constellation/v2/hack/cli-k8s-compatibility",
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/api/versionsapi/client",
"//internal/logger", "//internal/logger",
"//internal/versions", "//internal/versions",
"//internal/versionsapi",
"//internal/versionsapi/client",
"@org_uber_go_zap//zapcore", "@org_uber_go_zap//zapcore",
], ],
) )

View file

@ -11,10 +11,10 @@ import (
"context" "context"
"flag" "flag"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/versionsapi/client"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )

View file

@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "configapi_lib",
srcs = ["main.go"],
importpath = "github.com/edgelesssys/constellation/v2/hack/configapi",
visibility = ["//visibility:private"],
deps = [
"//internal/api/configapi",
"//internal/kms/uri",
"@com_github_spf13_cobra//:cobra",
],
)
go_binary(
name = "upload",
embed = [":configapi_lib"],
visibility = ["//visibility:public"],
)

91
hack/configapi/main.go Normal file
View file

@ -0,0 +1,91 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package main
import (
"context"
"fmt"
"time"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/spf13/cobra"
)
const (
awsRegion = "eu-central-1"
awsBucket = "cdn-constellation-backend"
invalidDefault = 0
)
var (
// AWS S3 credentials.
awsAccessKeyID string
awsAccessKey string
// Azure SEV-SNP version numbers.
bootloaderVersion uint8
teeVersion uint8
snpVersion uint8
microcodeVersion uint8
)
func handleError(err error) {
if err != nil {
panic(err)
}
}
func main() {
myCmd := &cobra.Command{
Use: "upload a set of versions specific to the azure-sev-snp attestation variant to the config api",
Short: "upload a set of versions specific to the azure-sev-snp attestation variant to the config api",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
cfg := uri.AWSS3Config{
Bucket: awsBucket,
AccessKeyID: awsAccessKeyID,
AccessKey: awsAccessKey,
Region: awsRegion,
}
sut, err := configapi.NewAttestationVersionRepo(ctx, cfg)
if err != nil {
panic(err)
}
versions := configapi.AzureSEVSNPVersion{
Bootloader: bootloaderVersion,
TEE: teeVersion,
SNP: snpVersion,
Microcode: microcodeVersion,
}
if err := sut.UploadAzureSEVSNP(ctx, versions, time.Now()); err != nil {
panic(err)
} else {
fmt.Println("Successfully uploaded version numbers", versions)
}
},
}
myCmd.PersistentFlags().Uint8VarP(&bootloaderVersion, "bootloader-version", "b", invalidDefault, "Bootloader version number")
handleError(myCmd.MarkPersistentFlagRequired("bootloader-version"))
myCmd.PersistentFlags().Uint8VarP(&teeVersion, "tee-version", "t", invalidDefault, "TEE version number")
handleError(myCmd.MarkPersistentFlagRequired("tee-version"))
myCmd.PersistentFlags().Uint8VarP(&snpVersion, "snp-version", "s", invalidDefault, "SNP version number")
handleError(myCmd.MarkPersistentFlagRequired("snp-version"))
myCmd.PersistentFlags().Uint8VarP(&microcodeVersion, "microcode-version", "m", invalidDefault, "Microcode version number")
handleError(myCmd.MarkPersistentFlagRequired("microcode-version"))
myCmd.PersistentFlags().StringVar(&awsAccessKeyID, "key-id", "", "ID of the Access key to use for AWS tests. Required for AWS KMS and storage test.")
handleError(myCmd.MarkPersistentFlagRequired("key-id"))
myCmd.PersistentFlags().StringVar(&awsAccessKey, "key", "", "Access key to use for AWS tests. Required for AWS KMS and storage test.")
handleError(myCmd.MarkPersistentFlagRequired("key"))
handleError(myCmd.Execute())
}

View file

@ -24,6 +24,7 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/image/upload/internal/cmd", importpath = "github.com/edgelesssys/constellation/v2/image/upload/internal/cmd",
visibility = ["//image/upload:__subpackages__"], visibility = ["//image/upload:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/logger", "//internal/logger",
@ -36,7 +37,6 @@ go_library(
"//internal/osimage/measurementsuploader", "//internal/osimage/measurementsuploader",
"//internal/osimage/nop", "//internal/osimage/nop",
"//internal/osimage/secureboot", "//internal/osimage/secureboot",
"//internal/versionsapi",
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",
"@com_github_spf13_cobra//:cobra", "@com_github_spf13_cobra//:cobra",
"@org_uber_go_zap//zapcore", "@org_uber_go_zap//zapcore",

View file

@ -10,8 +10,8 @@ import (
"context" "context"
"io" "io"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
type archivist interface { type archivist interface {

View file

@ -12,8 +12,8 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )

View file

@ -11,9 +11,9 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
infoupload "github.com/edgelesssys/constellation/v2/internal/osimage/imageinfo" infoupload "github.com/edgelesssys/constellation/v2/internal/osimage/imageinfo"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -13,8 +13,8 @@ import (
"io" "io"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
func uploadImage(ctx context.Context, archiveC archivist, uploadC uploader, req *osimage.UploadRequest, out io.Writer) error { func uploadImage(ctx context.Context, archiveC archivist, uploadC uploader, req *osimage.UploadRequest, out io.Writer) error {

View file

@ -0,0 +1,36 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "configapi",
srcs = [
"attestation.go",
"attestationversion.go",
"configapi.go",
"repo.go",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/api/configapi",
visibility = ["//:__subpackages__"],
deps = [
"//internal/constants",
"//internal/kms/storage",
"//internal/kms/storage/awss3",
"//internal/kms/uri",
"//internal/variant",
],
)
go_test(
name = "configapi_test",
srcs = [
"attestationversion_test.go",
"repo_test.go",
],
embed = [":configapi"],
deps = [
"//internal/kms/uri",
"//internal/variant",
"@com_github_stretchr_testify//require",
"@in_gopkg_yaml_v3//:yaml_v3",
],
)

View file

@ -0,0 +1,99 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package configapi
import (
"fmt"
"net/url"
"path"
"strings"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/variant"
)
// attestationURLPath is the URL path to the attestation versions.
const attestationURLPath = "constellation/v1/attestation"
// AzureSEVSNPVersionType is the type of the version to be requested.
type AzureSEVSNPVersionType string
// AzureSEVSNPVersion tracks the latest version of each component of the Azure SEVSNP.
type AzureSEVSNPVersion struct {
// Bootloader is the latest version of the Azure SEVSNP bootloader.
Bootloader uint8 `json:"bootloader"`
// TEE is the latest version of the Azure SEVSNP TEE.
TEE uint8 `json:"tee"`
// SNP is the latest version of the Azure SEVSNP SNP.
SNP uint8 `json:"snp"`
// Microcode is the latest version of the Azure SEVSNP microcode.
Microcode uint8 `json:"microcode"`
}
// AzureSEVSNPVersionGet is the request to get the version information of the specific version in the config api.
type AzureSEVSNPVersionGet struct {
Version string `json:"-"`
AzureSEVSNPVersion
}
// URL returns the URL for the request to the config api.
func (i AzureSEVSNPVersionGet) URL() (string, error) {
url, err := url.Parse(constants.CDNRepositoryURL)
if err != nil {
return "", fmt.Errorf("parsing CDN URL: %w", err)
}
url.Path = i.JSONPath()
return url.String(), nil
}
// JSONPath returns the path to the JSON file for the request to the config api.
func (i AzureSEVSNPVersionGet) JSONPath() string {
return path.Join(attestationURLPath, variant.AzureSEVSNP{}.String(), i.Version)
}
// ValidateRequest validates the request.
func (i AzureSEVSNPVersionGet) ValidateRequest() error {
if !strings.HasSuffix(i.Version, ".json") {
return fmt.Errorf("version has no .json suffix")
}
return nil
}
// Validate is a No-Op at the moment.
func (i AzureSEVSNPVersionGet) Validate() error {
return nil
}
// AzureSEVSNPVersionList is the request to list all versions in the config api.
type AzureSEVSNPVersionList []string
// URL returns the URL for the request to the config api.
func (i AzureSEVSNPVersionList) URL() (string, error) {
url, err := url.Parse(constants.CDNRepositoryURL)
if err != nil {
return "", fmt.Errorf("parsing CDN URL: %w", err)
}
url.Path = i.JSONPath()
return url.String(), nil
}
// JSONPath returns the path to the JSON file for the request to the config api.
func (i AzureSEVSNPVersionList) JSONPath() string {
return path.Join(attestationURLPath, variant.AzureSEVSNP{}.String(), "list")
}
// ValidateRequest is a NoOp as there is no input.
func (i AzureSEVSNPVersionList) ValidateRequest() error {
return nil
}
// Validate validates the response.
func (i AzureSEVSNPVersionList) Validate() error {
if len(i) < 1 {
return fmt.Errorf("no versions found in /list")
}
return nil
}

View file

@ -0,0 +1,81 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package configapi
import (
"encoding/json"
"fmt"
"strings"
)
const placeholderVersionValue = 0
// NewLatestPlaceholderVersion returns the latest version with a placeholder version value.
func NewLatestPlaceholderVersion() AttestationVersion {
return AttestationVersion{
Value: placeholderVersionValue,
IsLatest: true,
}
}
// AttestationVersion is a type that represents a version of a SNP.
type AttestationVersion struct {
Value uint8
IsLatest bool
}
// MarshalYAML implements a custom marshaller to resolve "latest" values.
func (v AttestationVersion) MarshalYAML() (any, error) {
if v.IsLatest {
return "latest", nil
}
return v.Value, nil
}
// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values.
func (v *AttestationVersion) UnmarshalYAML(unmarshal func(any) error) error {
var rawUnmarshal any
if err := unmarshal(&rawUnmarshal); err != nil {
return fmt.Errorf("raw unmarshal: %w", err)
}
return v.parseRawUnmarshal(rawUnmarshal)
}
// MarshalJSON implements a custom marshaller to resolve "latest" values.
func (v AttestationVersion) MarshalJSON() ([]byte, error) {
if v.IsLatest {
return json.Marshal("latest")
}
return json.Marshal(v.Value)
}
// UnmarshalJSON implements a custom unmarshaller to resolve "latest" values.
func (v *AttestationVersion) UnmarshalJSON(data []byte) (err error) {
var rawUnmarshal any
if err := json.Unmarshal(data, &rawUnmarshal); err != nil {
return fmt.Errorf("raw unmarshal: %w", err)
}
return v.parseRawUnmarshal(rawUnmarshal)
}
func (v *AttestationVersion) parseRawUnmarshal(rawUnmarshal any) error {
switch s := rawUnmarshal.(type) {
case string:
if strings.ToLower(s) == "latest" {
v.IsLatest = true
v.Value = placeholderVersionValue
} else {
return fmt.Errorf("invalid version value: %s", s)
}
case int:
v.Value = uint8(s)
default:
return fmt.Errorf("invalid version value type: %s", s)
}
return nil
}

View file

@ -0,0 +1,46 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package configapi
import (
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
func TestVersionMarshalYAML(t *testing.T) {
tests := []struct {
name string
sut AttestationVersion
want string
}{
{
name: "isLatest resolves to latest",
sut: AttestationVersion{
Value: 1,
IsLatest: true,
},
want: "latest\n",
},
{
name: "value 5 resolves to 5",
sut: AttestationVersion{
Value: 5,
IsLatest: false,
},
want: "5\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bt, err := yaml.Marshal(tt.sut)
require.NoError(t, err)
require.Equal(t, tt.want, string(bt))
})
}
}

View file

@ -0,0 +1,20 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
# Config API
The Config API provides information about versions of Constellation components.
This package defines API types that represents objects of the config API.
The types provide helper methods for validation and commonly used operations on the
information contained in the objects. Especially the paths used for the API are defined
in these helper methods.
The package also provides helper functions that can be used in context of the config API,
e.g. to validate versions.
*/
package configapi

View file

@ -0,0 +1,96 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package configapi
import (
"context"
"encoding/json"
"errors"
"fmt"
"path"
"sort"
"time"
"github.com/edgelesssys/constellation/v2/internal/kms/storage"
"github.com/edgelesssys/constellation/v2/internal/kms/storage/awss3"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/edgelesssys/constellation/v2/internal/variant"
)
// AttestationVersionRepo manages (modifies) the version information for the attestation variants.
type AttestationVersionRepo struct {
*awss3.Storage
}
// NewAttestationVersionRepo returns a new AttestationVersionRepo.
func NewAttestationVersionRepo(ctx context.Context, cfg uri.AWSS3Config) (*AttestationVersionRepo, error) {
s3, err := awss3.New(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("failed to create s3 storage: %w", err)
}
return &AttestationVersionRepo{s3}, nil
}
// UploadAzureSEVSNP uploads the latest version numbers of the Azure SEVSNP.
func (a AttestationVersionRepo) UploadAzureSEVSNP(ctx context.Context, versions AzureSEVSNPVersion, date time.Time) error {
bt, err := json.Marshal(versions)
if err != nil {
return err
}
variant := variant.AzureSEVSNP{}
fname := date.Format("2006-01-02-15-04") + ".json"
err = a.Put(ctx, fmt.Sprintf("%s/%s/%s", attestationURLPath, variant.String(), fname), bt)
if err != nil {
return err
}
return a.addVersionToList(ctx, variant, fname)
}
// List returns the list of versions for the given attestation type.
func (a AttestationVersionRepo) List(ctx context.Context, attestation variant.Variant) ([]string, error) {
key := path.Join(attestationURLPath, attestation.String(), "list")
bt, err := a.Get(ctx, key)
if err != nil {
return nil, err
}
var versions []string
if err := json.Unmarshal(bt, &versions); err != nil {
return nil, err
}
return versions, nil
}
// DeleteList empties the list of versions for the given attestation type.
func (a AttestationVersionRepo) DeleteList(ctx context.Context, attestation variant.Variant) error {
versions := []string{}
bt, err := json.Marshal(&versions)
if err != nil {
return err
}
return a.Put(ctx, path.Join(attestationURLPath, attestation.String(), "list"), bt)
}
func (a AttestationVersionRepo) addVersionToList(ctx context.Context, attestation variant.Variant, fname string) error {
versions := []string{}
key := path.Join(attestationURLPath, attestation.String(), "list")
bt, err := a.Get(ctx, key)
if err == nil {
if err := json.Unmarshal(bt, &versions); err != nil {
return err
}
} else if !errors.Is(err, storage.ErrDEKUnset) {
return err
}
versions = append(versions, fname)
versions = variant.RemoveDuplicate(versions)
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
json, err := json.Marshal(versions)
if err != nil {
return err
}
return a.Put(ctx, key, json)
}

View file

@ -0,0 +1,85 @@
//go:build e2e
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package configapi_test
import (
"context"
"flag"
"fmt"
"os"
"testing"
"time"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/stretchr/testify/require"
)
var (
awsRegion = flag.String("aws-region", "us-east-1", "Region to use for AWS tests. Required for AWS KMS test.")
awsAccessKeyID = flag.String("aws-access-key-id", "", "ID of the Access key to use for AWS tests. Required for AWS KMS and storage test.")
awsAccessKey = flag.String("aws-access-key", "", "Access key to use for AWS tests. Required for AWS KMS and storage test.")
awsBucket = flag.String("aws-bucket", "", "Name of the S3 bucket to use for AWS storage test. Required for AWS storage test.")
)
func TestMain(m *testing.M) {
flag.Parse()
if *awsAccessKey == "" || *awsAccessKeyID == "" || *awsBucket == "" || *awsRegion == "" {
flag.Usage()
fmt.Println("Required flags not set: --aws-access-key, --aws-access-key-id, --aws-bucket, --aws-region. Skipping tests.")
os.Exit(0)
}
os.Exit(m.Run())
}
var cfg = uri.AWSS3Config{
Bucket: *awsBucket,
AccessKeyID: *awsAccessKeyID,
AccessKey: *awsAccessKey,
Region: *awsRegion,
}
var versionValues = configapi.AzureSEVSNPVersion{
Bootloader: 2,
TEE: 0,
SNP: 6,
Microcode: 93,
}
func TestUploadAzureSEVSNPVersions(t *testing.T) {
ctx := context.Background()
sut, err := configapi.NewAttestationVersionRepo(ctx, cfg)
require.NoError(t, err)
d := time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC)
require.NoError(t, sut.UploadAzureSEVSNP(ctx, versionValues, d))
}
func TestListVersions(t *testing.T) {
ctx := context.Background()
sut, err := configapi.NewAttestationVersionRepo(ctx, cfg)
require.NoError(t, err)
err = sut.DeleteList(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
res, err := sut.List(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
require.Equal(t, []string{}, res)
d := time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC)
err = sut.UploadAzureSEVSNP(ctx, versionValues, d)
require.NoError(t, err)
res, err = sut.List(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
require.Equal(t, []string{"2021-01-01-01-01.json"}, res)
err = sut.DeleteList(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
}

View file

@ -3,18 +3,29 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library( go_library(
name = "fetcher", name = "fetcher",
srcs = ["fetcher.go"], srcs = [
importpath = "github.com/edgelesssys/constellation/v2/internal/versionsapi/fetcher", "configapi.go",
"fetcher.go",
"versionapi.go",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/api/fetcher",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = ["//internal/versionsapi"], deps = [
"//internal/api/configapi",
"//internal/api/versionsapi",
],
) )
go_test( go_test(
name = "fetcher_test", name = "fetcher_test",
srcs = ["fetcher_test.go"], srcs = [
"configapi_test.go",
"versionapi_test.go",
],
embed = [":fetcher"], embed = [":fetcher"],
deps = [ deps = [
"//internal/versionsapi", "//internal/api/configapi",
"//internal/api/versionsapi",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",
"@org_uber_go_goleak//:goleak", "@org_uber_go_goleak//:goleak",

View file

@ -0,0 +1,55 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package fetcher
import (
"context"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
)
// ConfigAPIFetcher fetches config API resources without authentication.
type ConfigAPIFetcher struct {
*fetcher
}
// NewConfigAPIFetcher returns a new Fetcher.
func NewConfigAPIFetcher() *ConfigAPIFetcher {
return &ConfigAPIFetcher{newFetcher()}
}
// NewConfigAPIFetcherWithClient returns a new Fetcher with custom http client.
func NewConfigAPIFetcherWithClient(client HTTPClient) *ConfigAPIFetcher {
return &ConfigAPIFetcher{newFetcherWith(client)}
}
// FetchAzureSEVSNPVersionList fetches the version list information from the config API.
func (f *ConfigAPIFetcher) FetchAzureSEVSNPVersionList(ctx context.Context, attestation configapi.AzureSEVSNPVersionList) (configapi.AzureSEVSNPVersionList, error) {
return fetch(ctx, f.httpc, attestation)
}
// FetchAzureSEVSNPVersion fetches the version information from the config API.
func (f *ConfigAPIFetcher) FetchAzureSEVSNPVersion(ctx context.Context, attestation configapi.AzureSEVSNPVersionGet) (configapi.AzureSEVSNPVersionGet, error) {
// TODO(elchead): follow-up PR for AB#3045 to check signature (sigstore.VerifySignature)
return fetch(ctx, f.httpc, attestation)
}
// FetchLatestAzureSEVSNPVersion returns the latest versions of the given type.
func (f *ConfigAPIFetcher) FetchLatestAzureSEVSNPVersion(ctx context.Context) (res configapi.AzureSEVSNPVersion, err error) {
var versions configapi.AzureSEVSNPVersionList
versions, err = f.FetchAzureSEVSNPVersionList(ctx, versions)
if err != nil {
return res, fmt.Errorf("fetching versions list: %w", err)
}
get := configapi.AzureSEVSNPVersionGet{Version: versions[0]} // get latest version (as sorted reversely alphanumerically)
get, err = f.FetchAzureSEVSNPVersion(ctx, get)
if err != nil {
return res, fmt.Errorf("failed fetching version: %w", err)
}
return get.AzureSEVSNPVersion, nil
}

View file

@ -0,0 +1,65 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package fetcher
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"testing"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetVersion(t *testing.T) {
client := &http.Client{
Transport: &fakeConfigAPIHandler{},
}
fetcher := NewConfigAPIFetcherWithClient(client)
res, err := fetcher.FetchLatestAzureSEVSNPVersion(context.Background())
require.NoError(t, err)
assert.Equal(t, uint8(2), res.Bootloader)
}
type fakeConfigAPIHandler struct{}
// RoundTrip resolves the request and returns a dummy response.
func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) {
if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/list" {
res := &http.Response{}
data := []string{"2021-01-01-01-01.json"}
bt, err := json.Marshal(data)
if err != nil {
return nil, err
}
res.Body = io.NopCloser(bytes.NewReader(bt))
res.Header = http.Header{}
res.Header.Set("Content-Type", "application/json")
res.StatusCode = http.StatusOK
return res, nil
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json" {
res := &http.Response{}
bt, err := json.Marshal(configapi.AzureSEVSNPVersion{
Microcode: 93,
TEE: 0,
SNP: 6,
Bootloader: 2,
})
if err != nil {
return nil, err
}
res.Body = io.NopCloser(bytes.NewReader(bt))
res.StatusCode = http.StatusOK
return res, nil
}
return nil, errors.New("no endpoint found")
}

View file

@ -18,40 +18,26 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Fetcher fetches versions API resources without authentication. // fetcher fetches versions API resources without authentication.
type Fetcher struct { type fetcher struct {
httpc httpc httpc HTTPClient
} }
// NewFetcher returns a new Fetcher. // NewHTTPClient returns a new http client.
func NewFetcher() *Fetcher { func NewHTTPClient() HTTPClient {
return &Fetcher{ return &http.Client{Transport: &http.Transport{DisableKeepAlives: true}} // DisableKeepAlives fixes concurrency issue see https://stackoverflow.com/a/75816347
httpc: http.DefaultClient, }
func newFetcherWith(client HTTPClient) *fetcher {
return &fetcher{
httpc: client,
} }
} }
// FetchVersionList fetches the given version list from the versions API. func newFetcher() *fetcher {
func (f *Fetcher) FetchVersionList(ctx context.Context, list versionsapi.List) (versionsapi.List, error) { return newFetcherWith(NewHTTPClient()) // DisableKeepAlives fixes concurrency issue see https://stackoverflow.com/a/75816347
return fetch(ctx, f.httpc, list)
}
// FetchVersionLatest fetches the latest version from the versions API.
func (f *Fetcher) FetchVersionLatest(ctx context.Context, latest versionsapi.Latest) (versionsapi.Latest, error) {
return fetch(ctx, f.httpc, latest)
}
// FetchImageInfo fetches the given image info from the versions API.
func (f *Fetcher) FetchImageInfo(ctx context.Context, imageInfo versionsapi.ImageInfo) (versionsapi.ImageInfo, error) {
return fetch(ctx, f.httpc, imageInfo)
}
// FetchCLIInfo fetches the given cli info from the versions API.
func (f *Fetcher) FetchCLIInfo(ctx context.Context, cliInfo versionsapi.CLIInfo) (versionsapi.CLIInfo, error) {
return fetch(ctx, f.httpc, cliInfo)
} }
type apiObject interface { type apiObject interface {
@ -60,7 +46,7 @@ type apiObject interface {
URL() (string, error) URL() (string, error)
} }
func fetch[T apiObject](ctx context.Context, c httpc, obj T) (T, error) { func fetch[T apiObject](ctx context.Context, c HTTPClient, obj T) (T, error) {
if err := obj.ValidateRequest(); err != nil { if err := obj.ValidateRequest(); err != nil {
return *new(T), fmt.Errorf("validating request for %T: %w", obj, err) return *new(T), fmt.Errorf("validating request for %T: %w", obj, err)
} }
@ -113,6 +99,7 @@ func (e *NotFoundError) Unwrap() error {
return e.err return e.err
} }
type httpc interface { // HTTPClient is an interface for http clients.
type HTTPClient interface {
Do(req *http.Request) (*http.Response, error) Do(req *http.Request) (*http.Response, error)
} }

View file

@ -0,0 +1,43 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package fetcher
import (
"context"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
)
// VersionAPIFetcher fetches version API resources without authentication.
type VersionAPIFetcher struct {
*fetcher
}
// NewVersionAPIFetcher returns a new Fetcher.
func NewVersionAPIFetcher() *VersionAPIFetcher {
return &VersionAPIFetcher{newFetcher()}
}
// FetchVersionList fetches the given version list from the versions API.
func (f *VersionAPIFetcher) FetchVersionList(ctx context.Context, list versionsapi.List) (versionsapi.List, error) {
return fetch(ctx, f.httpc, list)
}
// FetchVersionLatest fetches the latest version from the versions API.
func (f *VersionAPIFetcher) FetchVersionLatest(ctx context.Context, latest versionsapi.Latest) (versionsapi.Latest, error) {
return fetch(ctx, f.httpc, latest)
}
// FetchImageInfo fetches the given image info from the versions API.
func (f *VersionAPIFetcher) FetchImageInfo(ctx context.Context, imageInfo versionsapi.ImageInfo) (versionsapi.ImageInfo, error) {
return fetch(ctx, f.httpc, imageInfo)
}
// FetchCLIInfo fetches the given cli info from the versions API.
func (f *VersionAPIFetcher) FetchCLIInfo(ctx context.Context, cliInfo versionsapi.CLIInfo) (versionsapi.CLIInfo, error) {
return fetch(ctx, f.httpc, cliInfo)
}

View file

@ -14,7 +14,7 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/versionsapi" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.uber.org/goleak" "go.uber.org/goleak"
@ -190,7 +190,7 @@ func TestFetchVersionList(t *testing.T) {
return tc.serverResp return tc.serverResp
}) })
fetcher := &Fetcher{httpc: client} fetcher := VersionAPIFetcher{&fetcher{httpc: client}}
list, err := fetcher.FetchVersionList(context.Background(), tc.list) list, err := fetcher.FetchVersionList(context.Background(), tc.list)

View file

@ -12,7 +12,7 @@ go_library(
"version.go", "version.go",
"versionsapi.go", "versionsapi.go",
], ],
importpath = "github.com/edgelesssys/constellation/v2/internal/versionsapi", importpath = "github.com/edgelesssys/constellation/v2/internal/api/versionsapi",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/constants", "//internal/constants",

View file

@ -9,12 +9,12 @@ go_library(
"main.go", "main.go",
"rm.go", "rm.go",
], ],
importpath = "github.com/edgelesssys/constellation/v2/internal/versionsapi/cli", importpath = "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/cli",
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/api/versionsapi/client",
"//internal/logger", "//internal/logger",
"//internal/versionsapi",
"//internal/versionsapi/client",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2",
"@com_github_aws_smithy_go//:smithy-go", "@com_github_aws_smithy_go//:smithy-go",

View file

@ -11,9 +11,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/versionsapi/client"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"

View file

@ -10,9 +10,9 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/versionsapi/client"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )

View file

@ -16,9 +16,9 @@ import (
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/versionsapi/client"
) )
func newListCmd() *cobra.Command { func newListCmd() *cobra.Command {

View file

@ -24,9 +24,9 @@ import (
awsconfig "github.com/aws/aws-sdk-go-v2/config" awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/smithy-go" "github.com/aws/smithy-go"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
verclient "github.com/edgelesssys/constellation/v2/internal/versionsapi/client"
gaxv2 "github.com/googleapis/gax-go/v2" gaxv2 "github.com/googleapis/gax-go/v2"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"

View file

@ -3,12 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "client", name = "client",
srcs = ["client.go"], srcs = ["client.go"],
importpath = "github.com/edgelesssys/constellation/v2/internal/versionsapi/client", importpath = "github.com/edgelesssys/constellation/v2/internal/api/versionsapi/client",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/constants", "//internal/constants",
"//internal/logger", "//internal/logger",
"//internal/versionsapi",
"@com_github_aws_aws_sdk_go_v2//aws", "@com_github_aws_aws_sdk_go_v2//aws",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager", "@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",

View file

@ -42,9 +42,9 @@ import (
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Client is the client for the versions API. // Client is the client for the versions API.

View file

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
/* /*
# Versions API # Versions API
The Versions API is a provides information about versions of Constellation components. The Versions API provides information about versions of Constellation components.
This package defines API types that represents objects of the versions API. This package defines API types that represents objects of the versions API.
The types provide helper methods for validation and commonly used operations on the The types provide helper methods for validation and commonly used operations on the

View file

@ -148,7 +148,7 @@ func (v *Validator) validateSNPReport(
return errDebugEnabled return errDebugEnabled
} }
if !report.CommittedTCB.isVersion(v.config.BootloaderVersion, v.config.TEEVersion, v.config.SNPVersion, v.config.MicrocodeVersion) { if !report.CommittedTCB.isVersion(v.config.BootloaderVersion.Value, v.config.TEEVersion.Value, v.config.SNPVersion.Value, v.config.MicrocodeVersion.Value) {
return &versionError{"COMMITTED_TCB", report.CommittedTCB} return &versionError{"COMMITTED_TCB", report.CommittedTCB}
} }
if report.LaunchTCB != report.CommittedTCB { if report.LaunchTCB != report.CommittedTCB {

View file

@ -348,7 +348,7 @@ func TestNewSNPReportFromBytes(t *testing.T) {
wantErr: true, wantErr: true,
}, },
} }
cfg := config.DefaultForAzureSEVSNP()
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
@ -363,8 +363,7 @@ func TestNewSNPReportFromBytes(t *testing.T) {
assert.NotNil(report) assert.NotNil(report)
assert.Equal(hex.EncodeToString(report.IDKeyDigest[:]), "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1") assert.Equal(hex.EncodeToString(report.IDKeyDigest[:]), "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1")
// This is a canary for us: If this fails in the future we possibly downgraded a SVN. // This is a canary for us: If this fails in the future we possibly downgraded a SVN.
cfg := config.DefaultForAzureSEVSNP() assert.True(report.LaunchTCB.isVersion(cfg.BootloaderVersion.Value, cfg.TEEVersion.Value, cfg.SNPVersion.Value, cfg.MicrocodeVersion.Value))
assert.True(report.LaunchTCB.isVersion(cfg.BootloaderVersion, cfg.TEEVersion, cfg.SNPVersion, cfg.MicrocodeVersion))
} }
}) })
} }

View file

@ -13,10 +13,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/measurements", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/measurements",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/sigstore", "//internal/sigstore",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"@com_github_google_go_tpm//tpmutil", "@com_github_google_go_tpm//tpmutil",
"@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@com_github_siderolabs_talos_pkg_machinery//config/encoder",
"@in_gopkg_yaml_v3//:yaml_v3", "@in_gopkg_yaml_v3//:yaml_v3",
@ -28,9 +28,9 @@ go_test(
srcs = ["measurements_test.go"], srcs = ["measurements_test.go"],
embed = [":measurements"], embed = [":measurements"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@com_github_siderolabs_talos_pkg_machinery//config/encoder",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",

View file

@ -7,13 +7,13 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/measurements/measurement-generator", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/measurements/measurement-generator",
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/config", "//internal/config",
"//internal/constants", "//internal/constants",
"//internal/sigstore", "//internal/sigstore",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"@org_golang_x_tools//go/ast/astutil", "@org_golang_x_tools//go/ast/astutil",
], ],
) )

View file

@ -23,13 +23,13 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
) )

View file

@ -32,10 +32,10 @@ import (
"github.com/siderolabs/talos/pkg/machinery/config/encoder" "github.com/siderolabs/talos/pkg/machinery/config/encoder"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/edgelesssys/constellation/v2/internal/sigstore"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
const ( const (

View file

@ -20,9 +20,9 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
func TestMarshal(t *testing.T) { func TestMarshal(t *testing.T) {

View file

@ -18,18 +18,19 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/config", importpath = "github.com/edgelesssys/constellation/v2/internal/config",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/configapi",
"//internal/api/fetcher",
"//internal/api/versionsapi",
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/compatibility", "//internal/compatibility",
"//internal/config/imageversion", "//internal/config/imageversion",
"//internal/config/instancetypes", "//internal/config/instancetypes",
"//internal/config/snpversion",
"//internal/constants", "//internal/constants",
"//internal/file", "//internal/file",
"//internal/variant", "//internal/variant",
"//internal/versions", "//internal/versions",
"//internal/versionsapi",
"@com_github_go_playground_locales//en", "@com_github_go_playground_locales//en",
"@com_github_go_playground_universal_translator//:universal-translator", "@com_github_go_playground_universal_translator//:universal-translator",
"@com_github_go_playground_validator_v10//:validator", "@com_github_go_playground_validator_v10//:validator",
@ -49,6 +50,7 @@ go_test(
data = glob(["testdata/**"]), data = glob(["testdata/**"]),
embed = [":config"], embed = [":config"],
deps = [ deps = [
"//internal/api/configapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/config/instancetypes", "//internal/config/instancetypes",

View file

@ -8,14 +8,14 @@ package config
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"strconv"
"strings"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config/snpversion"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
) )
@ -26,16 +26,16 @@ type AzureSEVSNP struct {
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
// description: | // description: |
// Lowest acceptable bootloader version. // Lowest acceptable bootloader version.
BootloaderVersion uint8 `json:"bootloaderVersion" yaml:"bootloaderVersion"` BootloaderVersion configapi.AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"`
// description: | // description: |
// Lowest acceptable TEE version. // Lowest acceptable TEE version.
TEEVersion uint8 `json:"teeVersion" yaml:"teeVersion"` TEEVersion configapi.AttestationVersion `json:"teeVersion" yaml:"teeVersion"`
// description: | // description: |
// Lowest acceptable SEV-SNP version. // Lowest acceptable SEV-SNP version.
SNPVersion uint8 `json:"snpVersion" yaml:"snpVersion"` SNPVersion configapi.AttestationVersion `json:"snpVersion" yaml:"snpVersion"`
// description: | // description: |
// Lowest acceptable microcode version. // Lowest acceptable microcode version.
MicrocodeVersion uint8 `json:"microcodeVersion" yaml:"microcodeVersion"` MicrocodeVersion configapi.AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"`
// description: | // description: |
// Configuration for validating the firmware signature. // Configuration for validating the firmware signature.
FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"` FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"`
@ -45,14 +45,14 @@ type AzureSEVSNP struct {
} }
// DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation. // DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation.
// Version numbers are hard coded and should be updated with each new release. // Version numbers have placeholder values and the latest available values can be fetched using [AzureSEVSNP.FetchAndSetLatestVersionNumbers].
func DefaultForAzureSEVSNP() *AzureSEVSNP { func DefaultForAzureSEVSNP() *AzureSEVSNP {
return &AzureSEVSNP{ return &AzureSEVSNP{
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}), Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
BootloaderVersion: snpversion.GetLatest(snpversion.Bootloader), BootloaderVersion: configapi.NewLatestPlaceholderVersion(),
TEEVersion: snpversion.GetLatest(snpversion.TEE), TEEVersion: configapi.NewLatestPlaceholderVersion(),
SNPVersion: snpversion.GetLatest(snpversion.SNP), SNPVersion: configapi.NewLatestPlaceholderVersion(),
MicrocodeVersion: snpversion.GetLatest(snpversion.Microcode), MicrocodeVersion: configapi.NewLatestPlaceholderVersion(),
FirmwareSignerConfig: SNPFirmwareSignerConfig{ FirmwareSignerConfig: SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.DefaultList(), AcceptedKeyDigests: idkeydigest.DefaultList(),
EnforcementPolicy: idkeydigest.MAAFallback, EnforcementPolicy: idkeydigest.MAAFallback,
@ -95,26 +95,25 @@ func (c AzureSEVSNP) EqualTo(old AttestationCfg) (bool, error) {
return firmwareSignerCfgEqual && measurementsEqual && bootloaderEqual && teeEqual && snpEqual && microcodeEqual && rootKeyEqual, nil return firmwareSignerCfgEqual && measurementsEqual && bootloaderEqual && teeEqual && snpEqual && microcodeEqual && rootKeyEqual, nil
} }
// UnmarshalYAML implements a custom unmarshaler to support setting "latest" as version. // FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
func (c *AzureSEVSNP) UnmarshalYAML(unmarshal func(any) error) error { func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(client fetcher.HTTPClient) error {
aux := &fusedAzureSEVSNP{ fetcher := fetcher.NewConfigAPIFetcherWithClient(client)
auxAzureSEVSNP: (*auxAzureSEVSNP)(c), versions, err := fetcher.FetchLatestAzureSEVSNPVersion(context.Background())
} if err != nil {
if err := unmarshal(aux); err != nil { return err
return fmt.Errorf("unmarshal AzureSEVSNP: %w", err)
}
c = (*AzureSEVSNP)(aux.auxAzureSEVSNP)
for _, versionType := range []snpversion.Type{snpversion.Bootloader, snpversion.TEE, snpversion.SNP, snpversion.Microcode} {
if !convertLatestToNumber(c, versionType, aux) {
if err := convertStringToUint(c, versionType, aux); err != nil {
return fmt.Errorf("convert %s version to number: %w", versionType, err)
}
}
} }
// set number and keep isLatest flag
c.mergeVersionNumbers(versions)
return nil return nil
} }
func (c *AzureSEVSNP) mergeVersionNumbers(versions configapi.AzureSEVSNPVersion) {
c.BootloaderVersion.Value = versions.Bootloader
c.TEEVersion.Value = versions.TEE
c.SNPVersion.Value = versions.SNP
c.MicrocodeVersion.Value = versions.Microcode
}
// AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation. // AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation.
type AzureTrustedLaunch struct { type AzureTrustedLaunch struct {
// description: | // description: |
@ -145,84 +144,3 @@ func (c AzureTrustedLaunch) EqualTo(other AttestationCfg) (bool, error) {
} }
return c.Measurements.EqualTo(otherCfg.Measurements), nil return c.Measurements.EqualTo(otherCfg.Measurements), nil
} }
// auxAzureSEVSNP is a helper struct for unmarshaling the config from YAML for handling the version parsing.
// The version fields are kept to make it convertable to the native AzureSEVSNP struct.
type auxAzureSEVSNP struct {
// description: |
// Expected TPM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
// description: |
// Lowest acceptable bootloader version.
BootloaderVersion uint8 `yaml:"-"`
// description: |
// Lowest acceptable TEE version.
TEEVersion uint8 `json:"teeVersion" yaml:"-"`
// description: |
// Lowest acceptable SEV-SNP version.
SNPVersion uint8 `json:"snpVersion" yaml:"-"`
// description: |
// Lowest acceptable microcode version.
MicrocodeVersion uint8 `json:"microcodeVersion" yaml:"-"`
// description: |
// Configuration for validating the firmware signature.
FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"`
// description: |
// AMD Root Key certificate used to verify the SEV-SNP certificate chain.
AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"`
}
// fusedAzureSEVSNP is a helper struct for unmarshaling the config from YAML for handling the version parsing.
type fusedAzureSEVSNP struct {
*auxAzureSEVSNP `yaml:",inline"`
// description: |
// Lowest acceptable bootloader version.
BootloaderVersion string `yaml:"bootloaderVersion"`
// description: |
// Lowest acceptable bootloader version.
TEEVersion string `yaml:"teeVersion"`
// description: |
// Lowest acceptable bootloader version.
SNPVersion string `yaml:"snpVersion"`
// description: |
// Lowest acceptable bootloader version.
MicrocodeVersion string `yaml:"microcodeVersion"`
}
func convertStringToUint(c *AzureSEVSNP, versionType snpversion.Type, aux *fusedAzureSEVSNP) error {
v, stringV := getUintAndStringPtrToVersion(c, versionType, aux)
bvInt, err := strconv.ParseInt(*stringV, 10, 8)
if err != nil {
return err
}
*v = uint8(bvInt)
return nil
}
func convertLatestToNumber(c *AzureSEVSNP, versionType snpversion.Type, aux *fusedAzureSEVSNP) bool {
v, stringV := getUintAndStringPtrToVersion(c, versionType, aux)
if strings.ToLower(*stringV) == "latest" {
*v = snpversion.GetLatest(versionType)
return true
}
return false
}
func getUintAndStringPtrToVersion(c *AzureSEVSNP, versionType snpversion.Type, aux *fusedAzureSEVSNP) (versionUint *uint8, versionString *string) {
switch versionType {
case snpversion.Bootloader:
versionUint = &c.BootloaderVersion
versionString = &aux.BootloaderVersion
case snpversion.TEE:
versionUint = &c.TEEVersion
versionString = &aux.TEEVersion
case snpversion.SNP:
versionUint = &c.SNPVersion
versionString = &aux.SNPVersion
case snpversion.Microcode:
versionUint = &c.MicrocodeVersion
versionString = &aux.MicrocodeVersion
}
return
}

View file

@ -31,6 +31,7 @@ import (
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en" en_translations "github.com/go-playground/validator/v10/translations/en"
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
@ -381,14 +382,25 @@ func fromFile(fileHandler file.Handler, name string) (*Config, error) {
// New creates a new config by: // New creates a new config by:
// 1. Reading config file via provided fileHandler from file with name. // 1. Reading config file via provided fileHandler from file with name.
// 2. Read secrets from environment variables. // 2. For "latest" version values of the attestation variants fetch the version numbers.
// 3. Validate config. If `--force` is set the version validation will be disabled and any version combination is allowed. // 3. Read secrets from environment variables.
// 4. Validate config. If `--force` is set the version validation will be disabled and any version combination is allowed.
func New(fileHandler file.Handler, name string, force bool) (*Config, error) { func New(fileHandler file.Handler, name string, force bool) (*Config, error) {
return NewWithClient(fileHandler, name, fetcher.NewHTTPClient(), force)
}
// NewWithClient is New with a custom HTTP client.
func NewWithClient(fileHandler file.Handler, name string, client fetcher.HTTPClient, force bool) (*Config, error) {
// Read config file // Read config file
c, err := fromFile(fileHandler, name) c, err := fromFile(fileHandler, name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if azure := c.Attestation.AzureSEVSNP; azure != nil {
if err := azure.FetchAndSetLatestVersionNumbers(client); err != nil {
return c, err
}
}
// Read secrets from env-vars. // Read secrets from env-vars.
clientSecretValue := os.Getenv(constants.EnvVarAzureClientSecretValue) clientSecretValue := os.Getenv(constants.EnvVarAzureClientSecretValue)

View file

@ -7,7 +7,11 @@ SPDX-License-Identifier: AGPL-3.0-only
package config package config
import ( import (
"bytes"
"encoding/json"
"errors" "errors"
"io"
"net/http"
"reflect" "reflect"
"testing" "testing"
@ -20,6 +24,7 @@ import (
"go.uber.org/goleak" "go.uber.org/goleak"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/edgelesssys/constellation/v2/internal/api/configapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes" "github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
@ -37,37 +42,57 @@ func TestDefaultConfig(t *testing.T) {
assert.NotNil(def) assert.NotNil(def)
} }
func TestSettingLatestAsVersion(t *testing.T) { func TestDefaultConfigWritesLatestVersion(t *testing.T) {
conf := Default()
bt, err := yaml.Marshal(conf)
require := require.New(t)
require.NoError(err)
var mp configMap
require.NoError(yaml.Unmarshal(bt, &mp))
assert := assert.New(t)
assert.Equal("latest", mp.getAzureSEVSNPVersion("microcodeVersion"))
assert.Equal("latest", mp.getAzureSEVSNPVersion("teeVersion"))
assert.Equal("latest", mp.getAzureSEVSNPVersion("snpVersion"))
assert.Equal("latest", mp.getAzureSEVSNPVersion("bootloaderVersion"))
}
func TestReadConfigFile(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
config map[string]interface{} config configMap
configName string configName string
wantResult *Config wantResult *Config
wantErr bool wantErr bool
}{ }{
"mix of latest and uint as version value": { "mix of Latest and uint as version value": {
config: func() map[string]interface{} { config: func() configMap {
conf := Default() conf := Default()
// modify versions as string
m := getConfigAsMap(conf, t) m := getConfigAsMap(conf, t)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "latest" m.setAzureSEVSNPVersion("microcodeVersion", "Latest") // check uppercase also works
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["teeVersion"] = "latest" m.setAzureSEVSNPVersion("teeVersion", 2)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["snpVersion"] = "latest" m.setAzureSEVSNPVersion("bootloaderVersion", 1)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["bootloaderVersion"] = 1
return m return m
}(), }(),
configName: constants.ConfigFilename, configName: constants.ConfigFilename,
wantResult: func() *Config { wantResult: func() *Config {
conf := Default() conf := Default()
conf.Attestation.AzureSEVSNP.BootloaderVersion = 1 conf.Attestation.AzureSEVSNP.BootloaderVersion = configapi.AttestationVersion{
Value: 1,
IsLatest: false,
}
conf.Attestation.AzureSEVSNP.TEEVersion = configapi.AttestationVersion{
Value: 2,
IsLatest: false,
}
return conf return conf
}(), }(),
}, },
"refuse invalid version value": { "refuse invalid version value": {
config: func() map[string]interface{} { config: func() configMap {
conf := Default() conf := Default()
m := getConfigAsMap(conf, t) m := getConfigAsMap(conf, t)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "1a" m.setAzureSEVSNPVersion("microcodeVersion", "1a")
return m return m
}(), }(),
configName: constants.ConfigFilename, configName: constants.ConfigFilename,
@ -84,29 +109,16 @@ func TestSettingLatestAsVersion(t *testing.T) {
require.NoError(fileHandler.WriteYAML(tc.configName, tc.config, file.OptNone)) require.NoError(fileHandler.WriteYAML(tc.configName, tc.config, file.OptNone))
} }
result, err := fromFile(fileHandler, tc.configName) result, err := fromFile(fileHandler, tc.configName)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)
} else { } else {
require.NoError(err) assert.NoError(err)
assert.Equal(tc.wantResult, result) assert.Equal(tc.wantResult, result)
} }
}) })
} }
} }
// getConfigAsMap returns a map of the config.
func getConfigAsMap(conf *Config, t *testing.T) (res map[string]interface{}) {
bytes, err := yaml.Marshal(&conf)
if err != nil {
t.Fatal(err)
}
if err := yaml.Unmarshal(bytes, &res); err != nil {
t.Fatal(err)
}
return
}
func TestFromFile(t *testing.T) { func TestFromFile(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
config *Config config *Config
@ -233,7 +245,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
wantClientSecretValue: "some-secret", wantClientSecretValue: "some-secret",
}, },
} }
client := newTestClient(&fakeConfigAPIHandler{})
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
@ -248,8 +260,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
} }
// Test // Test
c, err := New(fileHandler, constants.ConfigFilename, false) c, err := NewWithClient(fileHandler, constants.ConfigFilename, client, false)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)
return return
@ -846,3 +857,68 @@ func TestConfigVersionCompatibility(t *testing.T) {
}) })
} }
} }
// configMap is used to un-/marshal the config as an unstructured map.
type configMap map[string]interface{}
func (c configMap) setAzureSEVSNPVersion(versionType string, value interface{}) {
c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType] = value
}
func (c configMap) getAzureSEVSNPVersion(versionType string) interface{} {
return c["attestation"].(configMap)["azureSEVSNP"].(configMap)[versionType]
}
// getConfigAsMap returns a map of the config.
func getConfigAsMap(conf *Config, t *testing.T) (res configMap) {
bytes, err := yaml.Marshal(&conf)
if err != nil {
t.Fatal(err)
}
if err := yaml.Unmarshal(bytes, &res); err != nil {
t.Fatal(err)
}
return
}
type fakeConfigAPIHandler struct{}
// RoundTrip resolves the request and returns a dummy response.
func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) {
if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/list" {
res := &http.Response{}
data := []string{"2021-01-01-01-01.json"}
bt, err := json.Marshal(data)
if err != nil {
return nil, err
}
res.Body = io.NopCloser(bytes.NewReader(bt))
res.Header = http.Header{}
res.Header.Set("Content-Type", "application/json")
res.StatusCode = http.StatusOK
return res, nil
} else if req.URL.Path == "/constellation/v1/attestation/azure-sev-snp/2021-01-01-01-01.json" {
res := &http.Response{}
bt, err := json.Marshal(configapi.AzureSEVSNPVersion{
Microcode: 93,
TEE: 0,
SNP: 6,
Bootloader: 2,
})
if err != nil {
return nil, err
}
res.Body = io.NopCloser(bytes.NewReader(bt))
res.StatusCode = http.StatusOK
return res, nil
}
return nil, errors.New("no endpoint found")
}
// newTestClient returns *http.Client with Transport replaced to avoid making real calls.
func newTestClient(fn *fakeConfigAPIHandler) *http.Client {
return &http.Client{
Transport: fn,
}
}

View file

@ -1,8 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "snpversion",
srcs = ["snpversion.go"],
importpath = "github.com/edgelesssys/constellation/v2/internal/config/snpversion",
visibility = ["//:__subpackages__"],
)

View file

@ -1,33 +0,0 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package snpversion
const (
Bootloader Type = "bootloader" // Bootloader is the version of the Azure SEVSNP bootloader.
TEE Type = "tee" // TEE is the version of the Azure SEVSNP TEE.
SNP Type = "snp" // SNP is the version of the Azure SEVSNP SNP.
Microcode Type = "microcode" // Microcode is the version of the Azure SEVSNP microcode.
)
// Type is the type of the version to be requested.
type Type string
// GetLatest returns the version of the given type.
func GetLatest(t Type) uint8 {
switch t {
case Bootloader:
return 2
case TEE:
return 0
case SNP:
return 6
case Microcode:
return 93
default:
panic("invalid version type")
}
}

View file

@ -19,6 +19,7 @@ import (
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/compatibility"
@ -26,7 +27,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// ValidationError occurs when the validation of a config fails. // ValidationError occurs when the validation of a config fails.

View file

@ -10,10 +10,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/imagefetcher", importpath = "github.com/edgelesssys/constellation/v2/internal/imagefetcher",
visibility = ["//cli:__subpackages__"], visibility = ["//cli:__subpackages__"],
deps = [ deps = [
"//internal/api/fetcher",
"//internal/api/versionsapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"//internal/versionsapi/fetcher",
"@com_github_schollz_progressbar_v3//:progressbar", "@com_github_schollz_progressbar_v3//:progressbar",
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",
], ],
@ -27,10 +27,10 @@ go_test(
], ],
embed = [":imagefetcher"], embed = [":imagefetcher"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/file", "//internal/file",
"//internal/variant", "//internal/variant",
"//internal/versionsapi",
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",

View file

@ -19,10 +19,10 @@ import (
"io/fs" "io/fs"
"regexp" "regexp"
"github.com/edgelesssys/constellation/v2/internal/api/fetcher"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/versionsapi/fetcher"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -35,7 +35,7 @@ type Fetcher struct {
// New returns a new image fetcher. // New returns a new image fetcher.
func New() *Fetcher { func New() *Fetcher {
return &Fetcher{ return &Fetcher{
fetcher: fetcher.NewFetcher(), fetcher: fetcher.NewVersionAPIFetcher(),
fs: &afero.Afero{Fs: afero.NewOsFs()}, fs: &afero.Afero{Fs: afero.NewOsFs()},
} }
} }

View file

@ -13,10 +13,10 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

View file

@ -27,6 +27,7 @@ type awsS3ClientAPI interface {
GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error) GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error)
CreateBucket(ctx context.Context, params *s3.CreateBucketInput, optFns ...func(*s3.Options)) (*s3.CreateBucketOutput, error) CreateBucket(ctx context.Context, params *s3.CreateBucketInput, optFns ...func(*s3.Options)) (*s3.CreateBucketOutput, error)
DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error)
} }
// Storage is an implementation of the Storage interface, storing keys in AWS S3 buckets. // Storage is an implementation of the Storage interface, storing keys in AWS S3 buckets.
@ -76,6 +77,18 @@ func (s *Storage) Get(ctx context.Context, keyID string) ([]byte, error) {
return io.ReadAll(output.Body) return io.ReadAll(output.Body)
} }
// Delete removes a DEK from AWS S3 Storage by key ID.
func (s *Storage) Delete(ctx context.Context, keyID string) error {
deleteObjectInput := &s3.DeleteObjectInput{
Bucket: &s.bucketID,
Key: &keyID,
}
if _, err := s.client.DeleteObject(ctx, deleteObjectInput); err != nil {
return fmt.Errorf("deleting DEK from storage: %w", err)
}
return nil
}
// Put saves a DEK to AWS S3 Storage by key ID. // Put saves a DEK to AWS S3 Storage by key ID.
func (s *Storage) Put(ctx context.Context, keyID string, data []byte) error { func (s *Storage) Put(ctx context.Context, keyID string, data []byte) error {
putObjectInput := &s3.PutObjectInput{ putObjectInput := &s3.PutObjectInput{

View file

@ -43,6 +43,10 @@ func (s *stubAWSS3StorageClient) PutObject(_ context.Context, params *s3.PutObje
return &s3.PutObjectOutput{}, s.putObjectErr return &s3.PutObjectOutput{}, s.putObjectErr
} }
func (s *stubAWSS3StorageClient) DeleteObject(_ context.Context, _ *s3.DeleteObjectInput, _ ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) {
return &s3.DeleteObjectOutput{}, nil
}
func (s *stubAWSS3StorageClient) CreateBucket(_ context.Context, _ *s3.CreateBucketInput, _ ...func(*s3.Options)) (*s3.CreateBucketOutput, error) { func (s *stubAWSS3StorageClient) CreateBucket(_ context.Context, _ *s3.CreateBucketInput, _ ...func(*s3.Options)) (*s3.CreateBucketOutput, error) {
s.createBucketCalled = true s.createBucketCalled = true
return &s3.CreateBucketOutput{}, s.createBucketErr return &s3.CreateBucketOutput{}, s.createBucketErr

View file

@ -6,8 +6,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/osimage/secureboot", "//internal/osimage/secureboot",
"//internal/versionsapi",
], ],
) )

View file

@ -6,9 +6,9 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/archive", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/archive",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/constants", "//internal/constants",
"//internal/logger", "//internal/logger",
"//internal/versionsapi",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager", "@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3", "@com_github_aws_aws_sdk_go_v2_service_s3//:s3",

View file

@ -16,9 +16,9 @@ import (
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager" s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3"
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Archivist uploads OS images to S3. // Archivist uploads OS images to S3.

View file

@ -6,10 +6,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/aws", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/aws",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/logger", "//internal/logger",
"//internal/osimage", "//internal/osimage",
"//internal/osimage/secureboot", "//internal/osimage/secureboot",
"//internal/versionsapi",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager", "@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
"@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2",

View file

@ -23,10 +23,10 @@ import (
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/smithy-go" "github.com/aws/smithy-go"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/osimage/secureboot" "github.com/edgelesssys/constellation/v2/internal/osimage/secureboot"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Uploader can upload and remove os images on GCP. // Uploader can upload and remove os images on GCP.

View file

@ -9,9 +9,9 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/azure", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/azure",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/logger", "//internal/logger",
"//internal/osimage", "//internal/osimage",
"//internal/versionsapi",
"@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime",
"@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity", "@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity",
"@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v4//:armcompute", "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v4//:armcompute",

View file

@ -21,9 +21,9 @@ import (
armcomputev4 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" armcomputev4 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Uploader can upload and remove os images on Azure. // Uploader can upload and remove os images on Azure.

View file

@ -6,10 +6,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/gcp", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/gcp",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/logger", "//internal/logger",
"//internal/osimage", "//internal/osimage",
"//internal/osimage/secureboot", "//internal/osimage/secureboot",
"//internal/versionsapi",
"@com_github_googleapis_gax_go_v2//:gax-go", "@com_github_googleapis_gax_go_v2//:gax-go",
"@com_google_cloud_go_compute//apiv1", "@com_google_cloud_go_compute//apiv1",
"@com_google_cloud_go_compute//apiv1/computepb", "@com_google_cloud_go_compute//apiv1/computepb",

View file

@ -19,10 +19,10 @@ import (
compute "cloud.google.com/go/compute/apiv1" compute "cloud.google.com/go/compute/apiv1"
"cloud.google.com/go/compute/apiv1/computepb" "cloud.google.com/go/compute/apiv1/computepb"
"cloud.google.com/go/storage" "cloud.google.com/go/storage"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/osimage/secureboot" "github.com/edgelesssys/constellation/v2/internal/osimage/secureboot"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
gaxv2 "github.com/googleapis/gax-go/v2" gaxv2 "github.com/googleapis/gax-go/v2"
) )

View file

@ -6,9 +6,9 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/imageinfo", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/imageinfo",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/constants", "//internal/constants",
"//internal/logger", "//internal/logger",
"//internal/versionsapi",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager", "@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3", "@com_github_aws_aws_sdk_go_v2_service_s3//:s3",

View file

@ -17,9 +17,9 @@ import (
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager" s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3"
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Uploader uploads image info to S3. // Uploader uploads image info to S3.

View file

@ -6,10 +6,10 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/measurementsuploader", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/measurementsuploader",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/constants", "//internal/constants",
"//internal/logger", "//internal/logger",
"//internal/versionsapi",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager", "@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3", "@com_github_aws_aws_sdk_go_v2_service_s3//:s3",

View file

@ -18,10 +18,10 @@ import (
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager" s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3"
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Uploader uploads image info to S3. // Uploader uploads image info to S3.

View file

@ -6,8 +6,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/nop", importpath = "github.com/edgelesssys/constellation/v2/internal/osimage/nop",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/api/versionsapi",
"//internal/logger", "//internal/logger",
"//internal/osimage", "//internal/osimage",
"//internal/versionsapi",
], ],
) )

View file

@ -10,9 +10,9 @@ package nop
import ( import (
"context" "context"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/osimage" "github.com/edgelesssys/constellation/v2/internal/osimage"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// Uploader is a no-op uploader. // Uploader is a no-op uploader.

View file

@ -11,9 +11,9 @@ import (
"io" "io"
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/osimage/secureboot" "github.com/edgelesssys/constellation/v2/internal/osimage/secureboot"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// UploadRequest is a request to upload an os image. // UploadRequest is a request to upload an os image.

View file

@ -82,7 +82,7 @@ func GetAvailableAttestationTypes() []Variant {
for _, k := range keys { for _, k := range keys {
res = append(res, providerAttestationMapping[k]...) res = append(res, providerAttestationMapping[k]...)
} }
return removeDuplicate(res) return RemoveDuplicate(res)
} }
// Getter returns an ASN.1 Object Identifier. // Getter returns an ASN.1 Object Identifier.
@ -259,9 +259,10 @@ func (QEMUTDX) Equal(other Getter) bool {
return other.OID().Equal(QEMUTDX{}.OID()) return other.OID().Equal(QEMUTDX{}.OID())
} }
func removeDuplicate(sliceList []Variant) []Variant { // RemoveDuplicate removes duplicate elements from a slice.
allKeys := make(map[Variant]bool) func RemoveDuplicate[T comparable](sliceList []T) []T {
list := []Variant{} allKeys := make(map[T]bool)
list := []T{}
for _, item := range sliceList { for _, item := range sliceList {
if _, value := allKeys[item]; !value { if _, value := allKeys[item]; !value {
allKeys[item] = true allKeys[item] = true