diff --git a/common/owner_certificate/BUILD.bazel b/common/owner_certificate/BUILD.bazel index f4930d9d..aec9605d 100644 --- a/common/owner_certificate/BUILD.bazel +++ b/common/owner_certificate/BUILD.bazel @@ -12,5 +12,4 @@ go_test( name = "owner_certificate_test", srcs = ["owner_certificate_test.go"], embed = [":owner_certificate"], - deps = ["//testdata:testdata_lib"], ) diff --git a/common/owner_certificate/owner_certificate.go b/common/owner_certificate/owner_certificate.go index a7e414f5..b7d57531 100644 --- a/common/owner_certificate/owner_certificate.go +++ b/common/owner_certificate/owner_certificate.go @@ -17,40 +17,43 @@ package ownercertificate import ( "crypto" + "crypto/rand" + "crypto/rsa" "crypto/x509" + "crypto/x509/pkix" "fmt" + "time" "go.mozilla.org/pkcs7" ) -// Verify checks that the provided CMS value is signed by a signer in the provided -// certPool and returns the Ownership Certificate. +// Verify checks that the provided CMS message is signed by a signer in the provided certPool and returns the signer certificate. func Verify(in []byte, certPool *x509.CertPool) (*x509.Certificate, error) { if len(in) == 0 { - return nil, fmt.Errorf("owner certificate is empty") + return nil, fmt.Errorf("input CMS message is empty") } p7, err := pkcs7.Parse(in) if err != nil { return nil, fmt.Errorf("unable to parse into pkcs7 format: %v", err) } - if err = p7.VerifyWithChain(certPool); err != nil { - return nil, fmt.Errorf("failed to verify OC: %v", err) - } if len(p7.Certificates) == 0 { return nil, fmt.Errorf("no certificates found in pkcs7 message") } + if err = p7.VerifyWithChain(certPool); err != nil { + return nil, fmt.Errorf("failed to verify the chain of trust: %v", err) + } return p7.Certificates[0], nil } -// GenerateCMS takes an Ownership Certificate keypair and converts it to a CMS structure. -// The CMS structure contains the Ownership Certificate in its list of certificates. +// GenerateCMS takes an owner certificate keypair and converts it to a CMS message. +// The CMS message contains the owner certificate in its list of certificates. func GenerateCMS(cert *x509.Certificate, priv crypto.PrivateKey) ([]byte, error) { signedMessage, err := pkcs7.NewSignedData(nil) if err != nil { return nil, err } + // Override the default SHA1 digest with SHA256. signedMessage.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSHA256) - signedMessage.SetEncryptionAlgorithm(pkcs7.OIDEncryptionAlgorithmRSA) signedMessage.AddCertificate(cert) err = signedMessage.AddSigner(cert, priv, pkcs7.SignerInfoConfig{}) @@ -60,3 +63,43 @@ func GenerateCMS(cert *x509.Certificate, priv crypto.PrivateKey) ([]byte, error) return signedMessage.Finish() } + +// NewRSACertificate creates a new RSA certificate and its private key, signed by the given certificate authority. +// If certificate authority is not provided, this new certificate will be created as a certificate authority instead. +func NewRSACertificate(commonName, deviceSerial string, caCert *x509.Certificate, caKey crypto.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) { + isCA := false + if caCert == nil || caKey == nil { + isCA = true + } + template := &x509.Certificate{ + Subject: pkix.Name{ + CommonName: commonName, + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(999, 0, 0), + IsCA: isCA, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + if deviceSerial != "" { + template.Subject.SerialNumber = deviceSerial + } + key, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, nil, err + } + if isCA { + caCert = template + caKey = key + } + der, err := x509.CreateCertificate(rand.Reader, template, caCert, &key.PublicKey, caKey) + if err != nil { + return nil, nil, err + } + cert, err := x509.ParseCertificate(der) + if err != nil { + return nil, nil, err + } + return cert, key, nil +} diff --git a/common/owner_certificate/owner_certificate_test.go b/common/owner_certificate/owner_certificate_test.go index faf92e9f..7be197ba 100644 --- a/common/owner_certificate/owner_certificate_test.go +++ b/common/owner_certificate/owner_certificate_test.go @@ -17,30 +17,26 @@ package ownercertificate import ( "crypto/x509" "testing" - - _ "embed" - - artifacts "github.com/openconfig/bootz/testdata" ) // Tests that the CMS structure can be created and that it can be verified with a PDC. func TestGenerateAndVerify(t *testing.T) { - pdc, pdcPrivateKey, err := artifacts.NewCertificateAuthority("Pinned Domain Cert", "Google", "localhost") + pdc, pdcPrivateKey, err := NewRSACertificate("Pinned Domain Cert", "", nil, nil) if err != nil { - t.Fatalf("NewCertificateAuthority(): %v", err) + t.Fatalf("failed to create PDC: %v", err) } - oc, ocPrivateKey, err := artifacts.NewSignedCertificate("Owner Certificate", "Google", "localhost", pdc, pdcPrivateKey) + oc, ocPrivateKey, err := NewRSACertificate("Owner Certificate", "", pdc, pdcPrivateKey) if err != nil { - t.Fatalf("NewSignedCertificate(): %v", err) + t.Fatalf("failed to create owner certificate: %v", err) } cms, err := GenerateCMS(oc, ocPrivateKey) if err != nil { - t.Fatalf("GenerateCMS(): %v", err) + t.Fatalf("failed to create CMS: %v", err) } pdcPool := x509.NewCertPool() pdcPool.AddCert(pdc) _, err = Verify(cms, pdcPool) if err != nil { - t.Fatalf("Verify(): %v", err) + t.Fatalf("failed to verify owner certificate: %v", err) } } diff --git a/common/ownership_voucher/BUILD.bazel b/common/ownership_voucher/BUILD.bazel index 0a99ad9a..375bc045 100644 --- a/common/ownership_voucher/BUILD.bazel +++ b/common/ownership_voucher/BUILD.bazel @@ -5,15 +5,12 @@ go_library( srcs = ["ownership_voucher.go"], importpath = "github.com/openconfig/bootz/common/ownership_voucher", visibility = ["//visibility:public"], - deps = [ - "//testdata:testdata_lib", - "@org_mozilla_go_pkcs7//:pkcs7", - ], + deps = ["@org_mozilla_go_pkcs7//:pkcs7"], ) go_test( name = "ownership_voucher_test", srcs = ["ownership_voucher_test.go"], embed = [":ownership_voucher"], - deps = ["//testdata:testdata_lib"], + deps = ["//common/owner_certificate"], ) diff --git a/common/ownership_voucher/ownership_voucher.go b/common/ownership_voucher/ownership_voucher.go index bb46c366..4976524a 100644 --- a/common/ownership_voucher/ownership_voucher.go +++ b/common/ownership_voucher/ownership_voucher.go @@ -16,19 +16,34 @@ package ownershipvoucher import ( + "crypto" "crypto/x509" "encoding/json" "encoding/xml" "fmt" + "time" "go.mozilla.org/pkcs7" - - artifacts "github.com/openconfig/bootz/testdata" ) -// Unmarshal unmarshals the contents of an Ownership Voucher. If a certPool is provided, -// it is used to verify the contents. -func Unmarshal(in []byte, certPool *x509.CertPool) (*artifacts.OwnershipVoucher, error) { +// OwnershipVoucher defines the ownership voucher. See https://www.rfc-editor.org/rfc/rfc8366.html. +type OwnershipVoucher struct { + OV OVInner `json:"ietf-voucher:voucher"` +} + +// OVInner defines the ownership voucher inner structure. +type OVInner struct { + XMLName xml.Name `xml:"voucher"` + CreatedOn string `json:"created-on" xml:"created-on"` + ExpiresOn string `json:"expires-on" xml:"expires-on"` + SerialNumber string `json:"serial-number" xml:"serial-number"` + Assertion string `json:"assertion" xml:"assertion"` + PinnedDomainCert []byte `json:"pinned-domain-cert" xml:"pinned-domain-cert"` + DomainCertRevocationChecks bool `json:"domain-cert-revocation-checks" xml:"domain-cert-revocation-checks"` +} + +// Unmarshal unmarshals the contents of an ownership voucher. If a certPool is provided, it is used to verify the contents. +func Unmarshal(in []byte, certPool *x509.CertPool) (*OwnershipVoucher, error) { if len(in) == 0 { return nil, fmt.Errorf("ownership voucher is empty") } @@ -36,8 +51,8 @@ func Unmarshal(in []byte, certPool *x509.CertPool) (*artifacts.OwnershipVoucher, if err != nil { return nil, fmt.Errorf("unable to parse into pkcs7 format: %v", err) } - ov := artifacts.OwnershipVoucher{} - jsonErr := json.Unmarshal(p7.Content, &ov) + ov := &OwnershipVoucher{} + jsonErr := json.Unmarshal(p7.Content, ov) if jsonErr != nil { xmlErr := xml.Unmarshal(p7.Content, &ov.OV) if xmlErr != nil { @@ -46,8 +61,44 @@ func Unmarshal(in []byte, certPool *x509.CertPool) (*artifacts.OwnershipVoucher, } if certPool != nil { if err = p7.VerifyWithChain(certPool); err != nil { - return nil, fmt.Errorf("failed to verify OV: %v", err) + return nil, fmt.Errorf("failed to verify ownership voucher: %v", err) + } + } + return ov, nil +} + +// NewOwnershipVoucher generates an ownership voucher signed by the vendor certificate. +func NewOwnershipVoucher(encoding string, deviceSerial string, pdc, vendorCert *x509.Certificate, vendorKey crypto.PrivateKey) ([]byte, error) { + ov := &OwnershipVoucher{ + OV: OVInner{ + CreatedOn: time.Now().Format(time.RFC3339), + ExpiresOn: time.Now().AddDate(999, 0, 0).Format(time.RFC3339), + SerialNumber: deviceSerial, + PinnedDomainCert: pdc.Raw, + }, + } + var ovBytes []byte + var err error + switch encoding { + case "json": + if ovBytes, err = json.Marshal(ov); err != nil { + return nil, err + } + case "xml": + if ovBytes, err = xml.Marshal(ov.OV); err != nil { + return nil, err } + default: + return nil, fmt.Errorf("unsupported encoding: %v", encoding) + } + signedMessage, err := pkcs7.NewSignedData(ovBytes) + if err != nil { + return nil, err + } + // Override the default SHA1 digest with SHA256. + signedMessage.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSHA256) + if err = signedMessage.AddSigner(vendorCert, vendorKey, pkcs7.SignerInfoConfig{}); err != nil { + return nil, err } - return &ov, nil + return signedMessage.Finish() } diff --git a/common/ownership_voucher/ownership_voucher_test.go b/common/ownership_voucher/ownership_voucher_test.go index c06ade5f..d56867d3 100644 --- a/common/ownership_voucher/ownership_voucher_test.go +++ b/common/ownership_voucher/ownership_voucher_test.go @@ -19,7 +19,7 @@ import ( "crypto/x509" "testing" - artifacts "github.com/openconfig/bootz/testdata" + ownercertificate "github.com/openconfig/bootz/common/owner_certificate" ) var ( @@ -28,18 +28,18 @@ var ( // Tests that a new OV can be created and it can be unpacked and verified. func TestEndToEndJSON(t *testing.T) { - pdc, _, err := artifacts.NewCertificateAuthority("Pinned Domain Cert", "Google", "localhost") + pdc, _, err := ownercertificate.NewRSACertificate("Pinned Domain Cert", "", nil, nil) if err != nil { t.Fatalf("unable to generate PDC: %v", err) } - vendorca, vendorcaPrivateKey, err := artifacts.NewCertificateAuthority("Cisco Certificate Authority", "Cisco", "localhost") + vendorca, vendorcaPrivateKey, err := ownercertificate.NewRSACertificate("Vendor Certificate Authority", "", nil, nil) if err != nil { t.Fatalf("unable to generate Vendor CA: %v", err) } - ov, err := artifacts.NewOwnershipVoucher("json", wantSerial, pdc, vendorca, vendorcaPrivateKey) + ov, err := NewOwnershipVoucher("json", wantSerial, pdc, vendorca, vendorcaPrivateKey) if err != nil { - t.Errorf("New err = %v, want nil", err) + t.Errorf("unable to generate ownership voucher: err = %v, want nil", err) } vendorCAPool := x509.NewCertPool() @@ -59,18 +59,18 @@ func TestEndToEndJSON(t *testing.T) { } func TestEndToEndXML(t *testing.T) { - pdc, _, err := artifacts.NewCertificateAuthority("Pinned Domain Cert", "Google", "localhost") + pdc, _, err := ownercertificate.NewRSACertificate("Pinned Domain Cert", "", nil, nil) if err != nil { t.Fatalf("unable to generate PDC: %v", err) } - vendorca, vendorcaPrivateKey, err := artifacts.NewCertificateAuthority("Cisco Certificate Authority", "Cisco", "localhost") + vendorca, vendorcaPrivateKey, err := ownercertificate.NewRSACertificate("Vendor Certificate Authority", "", nil, nil) if err != nil { t.Fatalf("unable to generate Vendor CA: %v", err) } - ov, err := artifacts.NewOwnershipVoucher("xml", wantSerial, pdc, vendorca, vendorcaPrivateKey) + ov, err := NewOwnershipVoucher("xml", wantSerial, pdc, vendorca, vendorcaPrivateKey) if err != nil { - t.Errorf("New err = %v, want nil", err) + t.Errorf("unable to generate ownership voucher: err = %v, want nil", err) } vendorCAPool := x509.NewCertPool() diff --git a/common/signature/BUILD.bazel b/common/signature/BUILD.bazel index 55217bc7..e7348dc5 100644 --- a/common/signature/BUILD.bazel +++ b/common/signature/BUILD.bazel @@ -11,5 +11,4 @@ go_test( name = "signature_test", srcs = ["signature_test.go"], embed = [":signature"], - deps = ["//testdata:testdata_lib"], ) diff --git a/common/tls/BUILD.bazel b/common/tls/BUILD.bazel index c3bae7b9..bdc48156 100644 --- a/common/tls/BUILD.bazel +++ b/common/tls/BUILD.bazel @@ -7,7 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "@com_github_golang_glog//:glog", - ] + ], ) go_test( diff --git a/common/tls/tls.go b/common/tls/tls.go index dd0f979e..73864809 100644 --- a/common/tls/tls.go +++ b/common/tls/tls.go @@ -5,12 +5,10 @@ import ( "crypto" "crypto/rand" "crypto/rsa" - "crypto/sha256" "crypto/tls" "crypto/x509" "crypto/x509/pkix" "fmt" - "math/big" "net" "time" @@ -69,26 +67,19 @@ func TLSConfiguration(opts *Opts) (*tls.Config, error) { if opts.ServerCertSubject == nil { return nil, fmt.Errorf("ServerCertSubject is nil") } - // 1. Generate a private key for the server. + // Generate a private key for the server. privateKey, err := rsa.GenerateKey(rand.Reader, 4096) if err != nil { return nil, fmt.Errorf("unable to generate private key: %v", err) } - // 2. Calculate SubjectKeyId - pubKeyBytes := x509.MarshalPKCS1PublicKey(&privateKey.PublicKey) - keyHash := sha256.Sum256(pubKeyBytes) - - // 3. Create the template and cert. + // Create the template and cert. template := x509.Certificate{ - SerialNumber: big.NewInt(int64(time.Now().Year())), - Subject: *opts.ServerCertSubject, - IPAddresses: []net.IP{opts.IPAddress}, - NotBefore: time.Now().AddDate(0, 0, -1), // One day before server start-up. - NotAfter: time.Now().AddDate(11, 0, 0), // 11 years after server start-up. - SubjectKeyId: keyHash[:], - AuthorityKeyId: opts.CACert.SubjectKeyId, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - KeyUsage: x509.KeyUsageDigitalSignature, + Subject: *opts.ServerCertSubject, + IPAddresses: []net.IP{opts.IPAddress}, + NotBefore: time.Now().AddDate(0, 0, -1), // One day before server start-up. + NotAfter: time.Now().AddDate(11, 0, 0), // 11 years after server start-up. + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature, } cert, err := x509.CreateCertificate( @@ -107,11 +98,11 @@ func TLSConfiguration(opts *Opts) (*tls.Config, error) { Certificate: [][]byte{cert}, } - // 4. Create the Root CAs trust bundle. + // Create the Root CAs trust bundle. rootCAs := x509.NewCertPool() rootCAs.AddCert(opts.CACert) - // 5. Create the final TLS server config. + // Create the final TLS server config. return &tls.Config{ Certificates: []tls.Certificate{*tlsCert}, RootCAs: rootCAs, diff --git a/server/artifactmanager/BUILD.bazel b/server/artifactmanager/BUILD.bazel new file mode 100644 index 00000000..960da618 --- /dev/null +++ b/server/artifactmanager/BUILD.bazel @@ -0,0 +1,26 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "artifactmanager", + srcs = ["artifactmanager.go"], + importpath = "github.com/openconfig/bootz/server/artifactmanager", + visibility = ["//visibility:public"], + deps = [ + "//server/proto:config", + "@openconfig_attestz//proto:tpm_enrollz_go", + ], +) diff --git a/server/artifactmanager/artifactmanager.go b/server/artifactmanager/artifactmanager.go new file mode 100644 index 00000000..3f630936 --- /dev/null +++ b/server/artifactmanager/artifactmanager.go @@ -0,0 +1,143 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package artifactmanager is an artifact manager that manages artifacts like certificates and keys. +// The implementation here is an in-memory implementation primarily used for testing and qualification. +// For production usecase, you should replace this implementation with your own one. +package artifactmanager + +import ( + "context" + "crypto" + "crypto/x509" + "encoding/base64" + "fmt" + + epb "github.com/openconfig/attestz/proto/tpm_enrollz" + cpb "github.com/openconfig/bootz/server/proto/config" +) + +// InMemoryArtifactManager provides a simple in memory handler for artifacts. +type InMemoryArtifactManager struct { + trustAnchorCert *x509.Certificate + trustAnchorKey crypto.PrivateKey + ownerCert *x509.Certificate + ownerKey crypto.PrivateKey + vendorCAPool *x509.CertPool + controlCards []*cpb.ControlCard +} + +// BootzServerTrustAnchorKeyPair returns the Bootz server trust anchor. This is the keypair that will generate the server's TLS certificate. +func (m *InMemoryArtifactManager) BootzServerTrustAnchorKeyPair() (*x509.Certificate, crypto.PrivateKey) { + return m.trustAnchorCert, m.trustAnchorKey +} + +// OwnerCertificateKeypair returns the owner certificate keypair for signing the bootstrap response. +func (m *InMemoryArtifactManager) OwnerCertificateKeyPair() (*x509.Certificate, crypto.PrivateKey) { + return m.ownerCert, m.ownerKey +} + +// OwnershipVoucher returns the ownership voucher for the given serial number and vendor. +func (m *InMemoryArtifactManager) OwnershipVoucher(ctx context.Context, serial string, vendor string) ([]byte, error) { + // For simplicity, we assume the serial numbers are unique among vendors. + // For production usecase, you should use both vendor and serial number to look up chassis in case of serial number collision. + for _, v := range m.controlCards { + if v.SerialNumber == serial { + ov, err := base64.StdEncoding.DecodeString(v.GetOwnershipVoucher()) + if err != nil { + return nil, fmt.Errorf("failed to decode ownership_voucher: %v", err) + } + return ov, nil + } + } + return nil, fmt.Errorf("ownership voucher not found for serial number: %v", serial) +} + +// PublicKey retrieves the EK or PPK public key of the chassis for use in the BootstrapStream challenge. +func (m *InMemoryArtifactManager) PublicKey(ctx context.Context, serial string, vendor string) (crypto.PublicKey, epb.Key, error) { + // For simplicity, we assume the serial numbers are unique among vendors. + // For production usecase, you should use both vendor and serial number to look up chassis in case of serial number collision. + for _, v := range m.controlCards { + if v.SerialNumber == serial { + pubBytes, err := base64.StdEncoding.DecodeString(v.GetPublicKey()) + if err != nil { + return nil, epb.Key_KEY_UNSPECIFIED, fmt.Errorf("failed to decode public key: %v", err) + } + pub, err := x509.ParsePKIXPublicKey(pubBytes) + if err != nil { + return nil, epb.Key_KEY_UNSPECIFIED, fmt.Errorf("failed to parse public key: %v", err) + } + return pub, v.GetPublicKeyType(), nil + } + } + return nil, epb.Key_KEY_UNSPECIFIED, fmt.Errorf("public key not found for serial number: %v", serial) +} + +// VendorCABundle returns the pool of certificates that the server should use to validate the provided IDevID certificates. +func (m *InMemoryArtifactManager) VendorCABundle() *x509.CertPool { + return m.vendorCAPool +} + +func parseCertKeyPair(pair *cpb.CertKeyPair) (*x509.Certificate, crypto.PrivateKey, error) { + if pair == nil { + return nil, nil, fmt.Errorf("certificate key pair is nil") + } + certBytes, err := base64.StdEncoding.DecodeString(pair.GetCert()) + if err != nil { + return nil, nil, fmt.Errorf("failed to decode certificate: %v", err) + } + keyBytes, err := base64.StdEncoding.DecodeString(pair.GetKey()) + if err != nil { + return nil, nil, fmt.Errorf("failed to decode private key: %v", err) + } + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse certificate: %v", err) + } + key, err := x509.ParsePKCS8PrivateKey(keyBytes) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse private key: %v", err) + } + return cert, key, nil +} + +// New returns a new in-memory artifact manager. +func New(config *cpb.Config) (*InMemoryArtifactManager, error) { + var err error + am := &InMemoryArtifactManager{} + am.trustAnchorCert, am.trustAnchorKey, err = parseCertKeyPair(config.GetTrustAnchor()) + if err != nil { + return nil, fmt.Errorf("trust anchor error: %v", err) + } + am.ownerCert, am.ownerKey, err = parseCertKeyPair(config.GetOwnerCertificate()) + if err != nil { + return nil, fmt.Errorf("owner certificate error: %v", err) + } + am.vendorCAPool = x509.NewCertPool() + for _, v := range config.GetVendorCaCerts() { + certBytes, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return nil, fmt.Errorf("failed to decode vendor CA certificate: %v", err) + } + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return nil, fmt.Errorf("failed to parse vendor CA certificate: %v", err) + } + am.vendorCAPool.AddCert(cert) + } + for _, v := range config.GetChassisInventories() { + am.controlCards = append(am.controlCards, v.GetControlCards()...) + } + return am, nil +} diff --git a/server/chassismanager/BUILD.bazel b/server/chassismanager/BUILD.bazel new file mode 100644 index 00000000..81a73892 --- /dev/null +++ b/server/chassismanager/BUILD.bazel @@ -0,0 +1,28 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "chassismanager", + srcs = ["chassismanager.go"], + importpath = "github.com/openconfig/bootz/server/chassismanager", + visibility = ["//visibility:public"], + deps = [ + "//common/types", + "//proto:bootz", + "//server/proto:config", + "@com_github_golang_glog//:glog", + ], +) diff --git a/server/chassismanager/chassismanager.go b/server/chassismanager/chassismanager.go new file mode 100644 index 00000000..0ec80c31 --- /dev/null +++ b/server/chassismanager/chassismanager.go @@ -0,0 +1,102 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package chassismanager is a chassis manager that manages chassis. +// The implementation here is an in-memory implementation primarily used for testing and qualification. +// For production usecase, you should replace this implementation with your own one. +package chassismanager + +import ( + "context" + "fmt" + + log "github.com/golang/glog" + "github.com/openconfig/bootz/common/types" + + bpb "github.com/openconfig/bootz/proto/bootz" + cpb "github.com/openconfig/bootz/server/proto/config" +) + +// InMemoryChassisManager provides a simple in memory handler for chassis. +type InMemoryChassisManager struct { + inventories []*cpb.ChassisInventory +} + +// ResolveChassis fills the chassis information based on the matched inventory. +func (m *InMemoryChassisManager) ResolveChassis(ctx context.Context, chassis *types.Chassis) error { + if chassis == nil { + return fmt.Errorf("chassis cannot be nil") + } + inventory, err := m.lookupChassis(chassis.ActiveSerial) + if err != nil { + return err + } + chassis.Hostname = inventory.GetHostname() + chassis.BootMode = inventory.GetBootMode() + chassis.StreamingSupported = inventory.GetStreamingSupported() + chassis.Manufacturer = inventory.GetManufacturer() + return nil +} + +// GenerateBootstrapData generates the bootstrap data response for the provided serial number. +func (m *InMemoryChassisManager) GenerateBootstrapData(ctx context.Context, _ *types.Chassis, serial string) (*bpb.BootstrapDataResponse, error) { + inventory, err := m.lookupChassis(serial) + if err != nil { + return nil, err + } + return &bpb.BootstrapDataResponse{ + SerialNum: serial, + IntendedImage: inventory.GetIntendedImage(), + BootPasswordHash: inventory.GetBootPasswordHash(), + BootConfig: inventory.GetBootConfig(), + Credentials: inventory.GetCredentials(), + Pathz: inventory.GetPathz(), + Authz: inventory.GetAuthz(), + CertzProfiles: inventory.GetCertzProfiles(), + }, nil +} + +// UpdateStatus updates the status for each control card on the chassis. +func (m *InMemoryChassisManager) UpdateStatus(ctx context.Context, req *bpb.ReportStatusRequest) error { + if len(req.GetStates()) == 0 { + return fmt.Errorf("no control card or fixed chassis states provided") + } + // We only do the logging. + log.Infof("Bootstrap Status: %v: Status message: %v", req.GetStatus(), req.GetStatusMessage()) + for _, v := range req.GetStates() { + log.Infof("Control card %v changed status to %v", v.GetSerialNumber(), v.GetStatus()) + } + return nil +} + +func (m *InMemoryChassisManager) lookupChassis(serial string) (*cpb.ChassisInventory, error) { + if serial == "" { + return nil, fmt.Errorf("lookup serial number cannot be empty") + } + // For simplicity, we assume the serial numbers are unique among vendors. + // For production usecase, you should use other info besides serial number to look up chassis in case of serial number collision. + for _, chassis := range m.inventories { + for _, card := range chassis.GetControlCards() { + if card.GetSerialNumber() == serial { + return chassis, nil + } + } + } + return nil, fmt.Errorf("could not find chassis of serial %q", serial) +} + +// New returns a new in-memory chassis manager. +func New(config *cpb.Config) *InMemoryChassisManager { + return &InMemoryChassisManager{inventories: config.GetChassisInventories()} +} diff --git a/server/proto/BUILD.bazel b/server/proto/BUILD.bazel new file mode 100644 index 00000000..6a211214 --- /dev/null +++ b/server/proto/BUILD.bazel @@ -0,0 +1,53 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "config_proto", + srcs = ["config.proto"], + import_prefix = "github.com/openconfig/bootz", + deps = [ + "//proto:bootz_proto", + "@openconfig_attestz//proto:tpm_enrollz_proto", + "@openconfig_gnsi//authz:authz_proto", + "@openconfig_gnsi//pathz:pathz_proto", + ], +) + +############################################################################## +# Go +############################################################################## + +go_proto_library( + name = "config_go_proto", + importpath = "github.com/openconfig/bootz/server/proto", + proto = ":config_proto", + deps = [ + "//proto:bootz", + "@openconfig_attestz//proto:tpm_enrollz_go", + "@openconfig_gnsi//authz", + "@openconfig_gnsi//pathz", + ], +) + +go_library( + name = "config", + embed = [":config_go_proto"], + importpath = "github.com/openconfig/bootz/server/proto/config", +) diff --git a/server/proto/config.proto b/server/proto/config.proto new file mode 100644 index 00000000..43149101 --- /dev/null +++ b/server/proto/config.proto @@ -0,0 +1,85 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package config; + +import "github.com/openconfig/attestz/proto/tpm_enrollz.proto"; +import "github.com/openconfig/bootz/proto/bootz.proto"; +import "github.com/openconfig/gnsi/authz/authz.proto"; +import "github.com/openconfig/gnsi/pathz/pathz.proto"; + +// A binding configuration for Bootz server. +message Config { + // Bootz server address (IP:port). + string server_address = 1; + // Bootz server trust anchor cert key pair. + CertKeyPair trust_anchor = 2; + // Owner certificate key pair. + CertKeyPair owner_certificate = 3; + // Based64 encoding of ASN.1 DER vendor CA certificates. + repeated string vendor_ca_certs = 4; + // Chassis owned by the orgization. + repeated ChassisInventory chassis_inventories = 5; +} + +message CertKeyPair { + // Base64 encoding of ASN.1 DER certificate. + string cert = 1; + // Base64 encoding of PKCS#8 DER private key. + string key = 2; +} + +message ChassisInventory { + // Chassis manufacturer. + string manufacturer = 1; + // For fixed form factor chassis, populate only 1 control card to represent + // the chassis itself. For modular form factor chassis, populate 2 control + // cards. + repeated ControlCard control_cards = 2; + // The intended hostname of the chassis. + string hostname = 3; + // Boot mode defines the boot mode that can be secure or insecure. + bootz.BootMode boot_mode = 4; + // Whether Streaming Bootz is supported or not. + bool streaming_supported = 5; + // Software image to be loaded on the chassis. + bootz.SoftwareImage intended_image = 6; + // Bootloader password. + string boot_password_hash = 7; + // Boot config to be loaded on the chassis. + bootz.BootConfig boot_config = 8; + // Credentials. + bootz.Credentials credentials = 9; + // Pathz. + gnsi.pathz.v1.UploadRequest pathz = 10; + // Authz. + gnsi.authz.v1.UploadRequest authz = 11; + // Certz profiles. + bootz.CertzProfiles certz_profiles = 12; +} + +message ControlCard { + // Serial number of the control card. + string serial_number = 1; + // Base64 encoding of ownership voucher. + string ownership_voucher = 2; + // Base64 encoding of PKIX DER EK/PPK public key. + // This field is not populated for control cards having IDevID. + string public_key = 3; + // Public key type: EK or PPK. + // This field is not populated for control cards having IDevID. + openconfig.attestz.Key public_key_type = 4; +} diff --git a/server/proto/config/config.pb.go b/server/proto/config/config.pb.go new file mode 100755 index 00000000..6240fdf0 --- /dev/null +++ b/server/proto/config/config.pb.go @@ -0,0 +1,461 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: github.com/openconfig/bootz/server/proto/config.proto + +package proto + +import ( + tpm_enrollz "github.com/openconfig/attestz/proto/tpm_enrollz" + bootz "github.com/openconfig/bootz/proto/bootz" + authz "github.com/openconfig/gnsi/authz" + pathz "github.com/openconfig/gnsi/pathz" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Config struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServerAddress string `protobuf:"bytes,1,opt,name=server_address,json=serverAddress,proto3" json:"server_address,omitempty"` + TrustAnchor *CertKeyPair `protobuf:"bytes,2,opt,name=trust_anchor,json=trustAnchor,proto3" json:"trust_anchor,omitempty"` + OwnerCertificate *CertKeyPair `protobuf:"bytes,3,opt,name=owner_certificate,json=ownerCertificate,proto3" json:"owner_certificate,omitempty"` + VendorCaCerts []string `protobuf:"bytes,4,rep,name=vendor_ca_certs,json=vendorCaCerts,proto3" json:"vendor_ca_certs,omitempty"` + ChassisInventories []*ChassisInventory `protobuf:"bytes,5,rep,name=chassis_inventories,json=chassisInventories,proto3" json:"chassis_inventories,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Config) Reset() { + *x = Config{} + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_server_proto_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Config) GetServerAddress() string { + if x != nil { + return x.ServerAddress + } + return "" +} + +func (x *Config) GetTrustAnchor() *CertKeyPair { + if x != nil { + return x.TrustAnchor + } + return nil +} + +func (x *Config) GetOwnerCertificate() *CertKeyPair { + if x != nil { + return x.OwnerCertificate + } + return nil +} + +func (x *Config) GetVendorCaCerts() []string { + if x != nil { + return x.VendorCaCerts + } + return nil +} + +func (x *Config) GetChassisInventories() []*ChassisInventory { + if x != nil { + return x.ChassisInventories + } + return nil +} + +type CertKeyPair struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cert string `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CertKeyPair) Reset() { + *x = CertKeyPair{} + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CertKeyPair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertKeyPair) ProtoMessage() {} + +func (x *CertKeyPair) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CertKeyPair.ProtoReflect.Descriptor instead. +func (*CertKeyPair) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_server_proto_config_proto_rawDescGZIP(), []int{1} +} + +func (x *CertKeyPair) GetCert() string { + if x != nil { + return x.Cert + } + return "" +} + +func (x *CertKeyPair) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +type ChassisInventory struct { + state protoimpl.MessageState `protogen:"open.v1"` + Manufacturer string `protobuf:"bytes,1,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + ControlCards []*ControlCard `protobuf:"bytes,2,rep,name=control_cards,json=controlCards,proto3" json:"control_cards,omitempty"` + Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"` + BootMode bootz.BootMode `protobuf:"varint,4,opt,name=boot_mode,json=bootMode,proto3,enum=bootz.BootMode" json:"boot_mode,omitempty"` + StreamingSupported bool `protobuf:"varint,5,opt,name=streaming_supported,json=streamingSupported,proto3" json:"streaming_supported,omitempty"` + IntendedImage *bootz.SoftwareImage `protobuf:"bytes,6,opt,name=intended_image,json=intendedImage,proto3" json:"intended_image,omitempty"` + BootPasswordHash string `protobuf:"bytes,7,opt,name=boot_password_hash,json=bootPasswordHash,proto3" json:"boot_password_hash,omitempty"` + BootConfig *bootz.BootConfig `protobuf:"bytes,8,opt,name=boot_config,json=bootConfig,proto3" json:"boot_config,omitempty"` + Credentials *bootz.Credentials `protobuf:"bytes,9,opt,name=credentials,proto3" json:"credentials,omitempty"` + Pathz *pathz.UploadRequest `protobuf:"bytes,10,opt,name=pathz,proto3" json:"pathz,omitempty"` + Authz *authz.UploadRequest `protobuf:"bytes,11,opt,name=authz,proto3" json:"authz,omitempty"` + CertzProfiles *bootz.CertzProfiles `protobuf:"bytes,12,opt,name=certz_profiles,json=certzProfiles,proto3" json:"certz_profiles,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ChassisInventory) Reset() { + *x = ChassisInventory{} + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ChassisInventory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChassisInventory) ProtoMessage() {} + +func (x *ChassisInventory) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChassisInventory.ProtoReflect.Descriptor instead. +func (*ChassisInventory) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_server_proto_config_proto_rawDescGZIP(), []int{2} +} + +func (x *ChassisInventory) GetManufacturer() string { + if x != nil { + return x.Manufacturer + } + return "" +} + +func (x *ChassisInventory) GetControlCards() []*ControlCard { + if x != nil { + return x.ControlCards + } + return nil +} + +func (x *ChassisInventory) GetHostname() string { + if x != nil { + return x.Hostname + } + return "" +} + +func (x *ChassisInventory) GetBootMode() bootz.BootMode { + if x != nil { + return x.BootMode + } + return bootz.BootMode(0) +} + +func (x *ChassisInventory) GetStreamingSupported() bool { + if x != nil { + return x.StreamingSupported + } + return false +} + +func (x *ChassisInventory) GetIntendedImage() *bootz.SoftwareImage { + if x != nil { + return x.IntendedImage + } + return nil +} + +func (x *ChassisInventory) GetBootPasswordHash() string { + if x != nil { + return x.BootPasswordHash + } + return "" +} + +func (x *ChassisInventory) GetBootConfig() *bootz.BootConfig { + if x != nil { + return x.BootConfig + } + return nil +} + +func (x *ChassisInventory) GetCredentials() *bootz.Credentials { + if x != nil { + return x.Credentials + } + return nil +} + +func (x *ChassisInventory) GetPathz() *pathz.UploadRequest { + if x != nil { + return x.Pathz + } + return nil +} + +func (x *ChassisInventory) GetAuthz() *authz.UploadRequest { + if x != nil { + return x.Authz + } + return nil +} + +func (x *ChassisInventory) GetCertzProfiles() *bootz.CertzProfiles { + if x != nil { + return x.CertzProfiles + } + return nil +} + +type ControlCard struct { + state protoimpl.MessageState `protogen:"open.v1"` + SerialNumber string `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + OwnershipVoucher string `protobuf:"bytes,2,opt,name=ownership_voucher,json=ownershipVoucher,proto3" json:"ownership_voucher,omitempty"` + PublicKey string `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + PublicKeyType tpm_enrollz.Key `protobuf:"varint,4,opt,name=public_key_type,json=publicKeyType,proto3,enum=openconfig.attestz.Key" json:"public_key_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ControlCard) Reset() { + *x = ControlCard{} + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ControlCard) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ControlCard) ProtoMessage() {} + +func (x *ControlCard) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ControlCard.ProtoReflect.Descriptor instead. +func (*ControlCard) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_server_proto_config_proto_rawDescGZIP(), []int{3} +} + +func (x *ControlCard) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *ControlCard) GetOwnershipVoucher() string { + if x != nil { + return x.OwnershipVoucher + } + return "" +} + +func (x *ControlCard) GetPublicKey() string { + if x != nil { + return x.PublicKey + } + return "" +} + +func (x *ControlCard) GetPublicKeyType() tpm_enrollz.Key { + if x != nil { + return x.PublicKeyType + } + return tpm_enrollz.Key(0) +} + +var File_github_com_openconfig_bootz_server_proto_config_proto protoreflect.FileDescriptor + +const file_github_com_openconfig_bootz_server_proto_config_proto_rawDesc = "" + + "\n" + + "5github.com/openconfig/bootz/server/proto/config.proto\x12\x06config\x1a5github.com/openconfig/attestz/proto/tpm_enrollz.proto\x1a-github.com/openconfig/bootz/proto/bootz.proto\x1a,github.com/openconfig/gnsi/authz/authz.proto\x1a,github.com/openconfig/gnsi/pathz/pathz.proto\"\x9c\x02\n" + + "\x06Config\x12%\n" + + "\x0eserver_address\x18\x01 \x01(\tR\rserverAddress\x126\n" + + "\ftrust_anchor\x18\x02 \x01(\v2\x13.config.CertKeyPairR\vtrustAnchor\x12@\n" + + "\x11owner_certificate\x18\x03 \x01(\v2\x13.config.CertKeyPairR\x10ownerCertificate\x12&\n" + + "\x0fvendor_ca_certs\x18\x04 \x03(\tR\rvendorCaCerts\x12I\n" + + "\x13chassis_inventories\x18\x05 \x03(\v2\x18.config.ChassisInventoryR\x12chassisInventories\"3\n" + + "\vCertKeyPair\x12\x12\n" + + "\x04cert\x18\x01 \x01(\tR\x04cert\x12\x10\n" + + "\x03key\x18\x02 \x01(\tR\x03key\"\xe5\x04\n" + + "\x10ChassisInventory\x12\"\n" + + "\fmanufacturer\x18\x01 \x01(\tR\fmanufacturer\x128\n" + + "\rcontrol_cards\x18\x02 \x03(\v2\x13.config.ControlCardR\fcontrolCards\x12\x1a\n" + + "\bhostname\x18\x03 \x01(\tR\bhostname\x12,\n" + + "\tboot_mode\x18\x04 \x01(\x0e2\x0f.bootz.BootModeR\bbootMode\x12/\n" + + "\x13streaming_supported\x18\x05 \x01(\bR\x12streamingSupported\x12;\n" + + "\x0eintended_image\x18\x06 \x01(\v2\x14.bootz.SoftwareImageR\rintendedImage\x12,\n" + + "\x12boot_password_hash\x18\a \x01(\tR\x10bootPasswordHash\x122\n" + + "\vboot_config\x18\b \x01(\v2\x11.bootz.BootConfigR\n" + + "bootConfig\x124\n" + + "\vcredentials\x18\t \x01(\v2\x12.bootz.CredentialsR\vcredentials\x122\n" + + "\x05pathz\x18\n" + + " \x01(\v2\x1c.gnsi.pathz.v1.UploadRequestR\x05pathz\x122\n" + + "\x05authz\x18\v \x01(\v2\x1c.gnsi.authz.v1.UploadRequestR\x05authz\x12;\n" + + "\x0ecertz_profiles\x18\f \x01(\v2\x14.bootz.CertzProfilesR\rcertzProfiles\"\xbf\x01\n" + + "\vControlCard\x12#\n" + + "\rserial_number\x18\x01 \x01(\tR\fserialNumber\x12+\n" + + "\x11ownership_voucher\x18\x02 \x01(\tR\x10ownershipVoucher\x12\x1d\n" + + "\n" + + "public_key\x18\x03 \x01(\tR\tpublicKey\x12?\n" + + "\x0fpublic_key_type\x18\x04 \x01(\x0e2\x17.openconfig.attestz.KeyR\rpublicKeyTypeb\x06proto3" + +var ( + file_github_com_openconfig_bootz_server_proto_config_proto_rawDescOnce sync.Once + file_github_com_openconfig_bootz_server_proto_config_proto_rawDescData []byte +) + +func file_github_com_openconfig_bootz_server_proto_config_proto_rawDescGZIP() []byte { + file_github_com_openconfig_bootz_server_proto_config_proto_rawDescOnce.Do(func() { + file_github_com_openconfig_bootz_server_proto_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_bootz_server_proto_config_proto_rawDesc), len(file_github_com_openconfig_bootz_server_proto_config_proto_rawDesc))) + }) + return file_github_com_openconfig_bootz_server_proto_config_proto_rawDescData +} + +var file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_github_com_openconfig_bootz_server_proto_config_proto_goTypes = []any{ + (*Config)(nil), // 0: config.Config + (*CertKeyPair)(nil), // 1: config.CertKeyPair + (*ChassisInventory)(nil), // 2: config.ChassisInventory + (*ControlCard)(nil), // 3: config.ControlCard + (bootz.BootMode)(0), // 4: bootz.BootMode + (*bootz.SoftwareImage)(nil), // 5: bootz.SoftwareImage + (*bootz.BootConfig)(nil), // 6: bootz.BootConfig + (*bootz.Credentials)(nil), // 7: bootz.Credentials + (*pathz.UploadRequest)(nil), // 8: gnsi.pathz.v1.UploadRequest + (*authz.UploadRequest)(nil), // 9: gnsi.authz.v1.UploadRequest + (*bootz.CertzProfiles)(nil), // 10: bootz.CertzProfiles + (tpm_enrollz.Key)(0), // 11: openconfig.attestz.Key +} +var file_github_com_openconfig_bootz_server_proto_config_proto_depIdxs = []int32{ + 1, // 0: config.Config.trust_anchor:type_name -> config.CertKeyPair + 1, // 1: config.Config.owner_certificate:type_name -> config.CertKeyPair + 2, // 2: config.Config.chassis_inventories:type_name -> config.ChassisInventory + 3, // 3: config.ChassisInventory.control_cards:type_name -> config.ControlCard + 4, // 4: config.ChassisInventory.boot_mode:type_name -> bootz.BootMode + 5, // 5: config.ChassisInventory.intended_image:type_name -> bootz.SoftwareImage + 6, // 6: config.ChassisInventory.boot_config:type_name -> bootz.BootConfig + 7, // 7: config.ChassisInventory.credentials:type_name -> bootz.Credentials + 8, // 8: config.ChassisInventory.pathz:type_name -> gnsi.pathz.v1.UploadRequest + 9, // 9: config.ChassisInventory.authz:type_name -> gnsi.authz.v1.UploadRequest + 10, // 10: config.ChassisInventory.certz_profiles:type_name -> bootz.CertzProfiles + 11, // 11: config.ControlCard.public_key_type:type_name -> openconfig.attestz.Key + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name +} + +func init() { file_github_com_openconfig_bootz_server_proto_config_proto_init() } +func file_github_com_openconfig_bootz_server_proto_config_proto_init() { + if File_github_com_openconfig_bootz_server_proto_config_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_bootz_server_proto_config_proto_rawDesc), len(file_github_com_openconfig_bootz_server_proto_config_proto_rawDesc)), + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_github_com_openconfig_bootz_server_proto_config_proto_goTypes, + DependencyIndexes: file_github_com_openconfig_bootz_server_proto_config_proto_depIdxs, + MessageInfos: file_github_com_openconfig_bootz_server_proto_config_proto_msgTypes, + }.Build() + File_github_com_openconfig_bootz_server_proto_config_proto = out.File + file_github_com_openconfig_bootz_server_proto_config_proto_goTypes = nil + file_github_com_openconfig_bootz_server_proto_config_proto_depIdxs = nil +}