mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-08-07 07:14:50 +00:00
NOISSUE - Add CLI option to download ASK and ARK (#149)
* add cli option to download ask and ark * add ARK and ASK to cert chain of the attestation report * fix spelling mistake * add explanation for aTLS testing * remove commented code
This commit is contained in:
committed by
GitHub
parent
30092c6a45
commit
7c090fd19f
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package cli
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/google/go-sev-guest/abi"
|
||||
"github.com/google/go-sev-guest/kds"
|
||||
"github.com/google/go-sev-guest/verify/trust"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
caBundleName = "ask_ark.pem"
|
||||
filePermisionKeys = 0o766
|
||||
)
|
||||
|
||||
func (cli *CLI) NewCABundleCmd(fileSavePath string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "ca-bundle",
|
||||
Short: "Fetch AMD SEV-SNPs CA Bundle (ASK and ARK)",
|
||||
Example: "ca-bundle <path_to_platform_info_json>",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
attestationConfiguration := grpc.AttestationConfiguration{}
|
||||
err := grpc.ReadManifest(args[0], &attestationConfiguration)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while reading manifest: %v", err)
|
||||
}
|
||||
|
||||
product := attestationConfiguration.RootOfTrust.Product
|
||||
|
||||
getter := trust.DefaultHTTPSGetter()
|
||||
caURL := kds.ProductCertChainURL(abi.VcekReportSigner, product)
|
||||
|
||||
bundle, err := getter.Get(caURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Error fetching ARK and ASK from AMD KDS for product: %s, error: %v", product, err)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(path.Join(fileSavePath, product), filePermisionKeys)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while creating directory for product name %s, error: %v", product, err)
|
||||
}
|
||||
|
||||
bundleFilePath := path.Join(fileSavePath, product, caBundleName)
|
||||
if err = saveToFile(bundleFilePath, bundle); err != nil {
|
||||
log.Fatalf("Error while saving ARK-ASK to file: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func saveToFile(fileSavePath string, content []byte) error {
|
||||
file, err := os.OpenFile(fileSavePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, filePermisionKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := file.Write(content); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+3
-8
@@ -8,16 +8,11 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/google/go-sev-guest/proto/check"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
|
||||
)
|
||||
|
||||
const filePermision = 0o755
|
||||
|
||||
type AttestationConfiguration struct {
|
||||
SNPPolicy *check.Policy `json:"snp_policy,omitempty"`
|
||||
RootOFTrust *check.RootOfTrust `json:"root_of_trust,omitempty"`
|
||||
}
|
||||
const filePermision = 0o644
|
||||
|
||||
func (cli *CLI) NewAddMeasurementCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
@@ -31,7 +26,7 @@ func (cli *CLI) NewAddMeasurementCmd() *cobra.Command {
|
||||
log.Fatalf("Error could not decode base64: %v", err)
|
||||
}
|
||||
|
||||
attestationConfiguration := AttestationConfiguration{}
|
||||
attestationConfiguration := grpc.AttestationConfiguration{}
|
||||
|
||||
manifest, err := os.OpenFile(args[1], os.O_RDWR, filePermision)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,8 +6,10 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/google/logger"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/ultravioletrs/cocos/cli"
|
||||
@@ -21,6 +23,8 @@ const (
|
||||
svcName = "cli"
|
||||
envPrefixAgentGRPC = "AGENT_GRPC_"
|
||||
completion = "completion"
|
||||
filePermision = 0o755
|
||||
cocosDirectory = ".cocos"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
@@ -29,10 +33,23 @@ type config struct {
|
||||
|
||||
func main() {
|
||||
var cfg config
|
||||
logger.Init("", false, false, os.Stderr)
|
||||
|
||||
if err := env.Parse(&cfg); err != nil {
|
||||
log.Fatalf("failed to load %s configuration : %s", svcName, err)
|
||||
}
|
||||
|
||||
homePath, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
log.Fatalf("Error fetching user home directory: %v", err)
|
||||
}
|
||||
|
||||
directoryCachePath := path.Join(homePath, cocosDirectory)
|
||||
|
||||
if err := os.MkdirAll(directoryCachePath, filePermision); err != nil {
|
||||
log.Fatalf("Error while creating directory %s, error: %v", directoryCachePath, err)
|
||||
}
|
||||
|
||||
logger, err := mglog.New(os.Stdout, cfg.LogLevel)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating logger: %s", err)
|
||||
@@ -92,6 +109,7 @@ func main() {
|
||||
rootCmd.AddCommand(cliSVC.NewFileHashCmd())
|
||||
rootCmd.AddCommand(cliSVC.NewAddMeasurementCmd())
|
||||
rootCmd.AddCommand(cliSVC.NewKeysCmd())
|
||||
rootCmd.AddCommand(cliSVC.NewCABundleCmd(directoryCachePath))
|
||||
|
||||
// Attestation commands
|
||||
attestaionCmd.AddCommand(cliSVC.NewGetAttestationCmd())
|
||||
|
||||
@@ -9,11 +9,13 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/google/go-sev-guest/abi"
|
||||
"github.com/google/go-sev-guest/proto/check"
|
||||
"github.com/google/go-sev-guest/proto/sevsnp"
|
||||
"github.com/google/go-sev-guest/validate"
|
||||
"github.com/google/go-sev-guest/verify"
|
||||
"github.com/google/go-sev-guest/verify/trust"
|
||||
@@ -32,6 +34,13 @@ const (
|
||||
withmTLS
|
||||
)
|
||||
|
||||
const (
|
||||
cocosDirectory = ".cocos"
|
||||
caBundleName = "ask_ark.pem"
|
||||
productNameMilan = "Milan"
|
||||
productNameGenoa = "Genoa"
|
||||
)
|
||||
|
||||
var (
|
||||
errGrpcConnect = errors.New("failed to connect to grpc server")
|
||||
errGrpcClose = errors.New("failed to close grpc connection")
|
||||
@@ -63,7 +72,7 @@ type Config struct {
|
||||
|
||||
type AttestationConfiguration struct {
|
||||
SNPPolicy *check.Policy `json:"snp_policy,omitempty"`
|
||||
RootOFTrust *check.RootOfTrust `json:"root_of_trust,omitempty"`
|
||||
RootOfTrust *check.RootOfTrust `json:"root_of_trust,omitempty"`
|
||||
}
|
||||
|
||||
type Client interface {
|
||||
@@ -132,7 +141,7 @@ func connect(cfg Config) (*grpc.ClientConn, security, error) {
|
||||
tc := insecure.NewCredentials()
|
||||
|
||||
if cfg.AttestedTLS {
|
||||
err := readManifest(cfg)
|
||||
err := ReadManifest(cfg.Manifest, &attestationConfiguration)
|
||||
if err != nil {
|
||||
return nil, secure, fmt.Errorf("failed to read Manifest %w", err)
|
||||
}
|
||||
@@ -183,16 +192,16 @@ func connect(cfg Config) (*grpc.ClientConn, security, error) {
|
||||
return conn, secure, nil
|
||||
}
|
||||
|
||||
func readManifest(cfg Config) error {
|
||||
if cfg.Manifest != "" {
|
||||
manifest, err := os.Open(cfg.Manifest)
|
||||
func ReadManifest(manifestPath string, attestationConfiguration *AttestationConfiguration) error {
|
||||
if manifestPath != "" {
|
||||
manifest, err := os.Open(manifestPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(errManifestOpen, err)
|
||||
}
|
||||
defer manifest.Close()
|
||||
|
||||
decoder := json.NewDecoder(manifest)
|
||||
err = decoder.Decode(&attestationConfiguration)
|
||||
err = decoder.Decode(attestationConfiguration)
|
||||
if err != nil {
|
||||
return errors.Wrap(errManifestDecode, err)
|
||||
}
|
||||
@@ -226,7 +235,7 @@ func verifyAttestationReportTLS(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
||||
attestationConfiguration.SNPPolicy.ReportData = expectedReportData[:]
|
||||
|
||||
// Attestation verification and validation
|
||||
sopts, err := verify.RootOfTrustToOptions(attestationConfiguration.RootOFTrust)
|
||||
sopts, err := verify.RootOfTrustToOptions(attestationConfiguration.RootOfTrust)
|
||||
if err != nil {
|
||||
return errors.Wrap(errAttVerification, err)
|
||||
}
|
||||
@@ -243,6 +252,10 @@ func verifyAttestationReportTLS(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
||||
return errors.Wrap(errAttVerification, err)
|
||||
}
|
||||
|
||||
if err := fillInAttestationLocal(attestationPB); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = verify.SnpAttestation(attestationPB, sopts); err != nil {
|
||||
return errors.Wrap(errAttVerification, err)
|
||||
}
|
||||
@@ -278,3 +291,32 @@ func checkIfCertificateSelfSigned(cert *x509.Certificate) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillInAttestationLocal(attestation *sevsnp.Attestation) error {
|
||||
product := attestationConfiguration.RootOfTrust.Product
|
||||
|
||||
chain := attestation.GetCertificateChain()
|
||||
if chain == nil {
|
||||
chain = &sevsnp.CertificateChain{}
|
||||
attestation.CertificateChain = chain
|
||||
}
|
||||
if len(chain.GetAskCert()) == 0 || len(chain.GetArkCert()) == 0 {
|
||||
homePath, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundleFilePath := path.Join(homePath, cocosDirectory, product, caBundleName)
|
||||
if _, err := os.Stat(bundleFilePath); err == nil {
|
||||
amdRootCerts := trust.AMDRootCerts{}
|
||||
if err := amdRootCerts.FromKDSCert(bundleFilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chain.ArkCert = amdRootCerts.ProductCerts.Ark.Raw
|
||||
chain.AskCert = amdRootCerts.ProductCerts.Ask.Raw
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -30,7 +30,13 @@ LINE="earlyprintk=serial console=ttyS0"
|
||||
sev-snp-measure --mode snp --vcpus 4 --vcpu-type EPYC-v4 --ovmf $OVMF_CODE --kernel $KERNEL --initrd $INITRD --append "$LINE" --output-format base64
|
||||
```
|
||||
|
||||
```sh
|
||||
To speed up the verification process of attested TLS, download the ARK and ASK certificates using the CLI tool. The CLI tool will download the certificates under your home directory in the `.cocos` directory.
|
||||
```bash
|
||||
go run cmd/cli/main.go ca-bundle <path/to/platfrom_info.json>
|
||||
```
|
||||
|
||||
In the following text, we can see an example of how the CLI tool is used.
|
||||
```bash
|
||||
export AGENT_GRPC_URL=localhost:7002
|
||||
|
||||
# For attested TLS, the CLI should also be aware of the VM measurement. To
|
||||
|
||||
Reference in New Issue
Block a user