diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml new file mode 100644 index 0000000..e9ec8be --- /dev/null +++ b/.github/linters/.yaml-lint.yml @@ -0,0 +1,59 @@ +--- +########################################### +# These are the rules used for # +# linting all the yaml files in the stack # +# NOTE: # +# You can disable line with: # +# # yamllint disable-line # +########################################### +rules: + braces: + level: warning + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: 1 + max-spaces-inside-empty: 5 + brackets: + level: warning + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: 1 + max-spaces-inside-empty: 5 + colons: + level: warning + max-spaces-before: 0 + max-spaces-after: 1 + commas: + level: warning + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + comments: disable + comments-indentation: disable + document-end: disable + document-start: + level: warning + present: true + empty-lines: + level: warning + max: 2 + max-start: 0 + max-end: 0 + hyphens: + level: warning + max-spaces-after: 1 + indentation: + level: warning + spaces: consistent + indent-sequences: true + check-multi-line-strings: false + key-duplicates: enable + line-length: + level: warning + max: 120 + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + new-line-at-end-of-file: disable + new-lines: + type: unix + trailing-spaces: disable diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000..8971322 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,43 @@ +# Copyright 2022 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 +# +# http://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. +--- +name: Lint Code Base + +on: + push: + branches: [main] + # Remove the line above to run when pushing to master + pull_request: + branches: [main] + +jobs: + build: + name: Lint Code Base + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Lint Code Base + uses: github/super-linter/slim@v5 + env: + VALIDATE_ALL_CODEBASE: false + VALIDATE_HTML: false + VALIDATE_JSCPD: false + VALIDATE_GO: false + IGNORE_GENERATED_FILES: true + DEFAULT_BRANCH: main + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3b735ec..0b03845 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,6 @@ # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib +.vscode/ +bazel-* -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..3753754 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,5 @@ +load("@bazel_gazelle//:def.bzl", "gazelle") + +# gazelle:prefix github.com/openconfig/gnsi +gazelle(name = "gazelle") + diff --git a/README.md b/README.md index aa948ee..5fc83bf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,263 @@ -# bootz -bootz defines structured data for network devices and bootstrap services which move a device from a factory default state to a fully production supportable state. +# Bootz protocol v2 (sZTP++ or gZTP) + +[TOC] + +## Objective + +Define a structured data format for exchanging as much data with the network device as possible, to take the device from a factory state to a fully production supportable state. + +Additionally, define both a dialout and dialin RPC service which can perform the boot workflow. + +The overall design of bootz is meant to allow operators of equipment to provide a data-only bootstrap request and allow vendors the freedom to implement the intent based on their own internal APIs. + +## Bootstrap/Configuration Management End State + +When thinking about what data is needed to transition a "factory-reset" device from that state into a production-managed state, we can divide the configuration into multiple units, which differ in how they are managed and interacted with. This is counter to the current model of vendor network devices which have a monolithic single configuration that stores all parameters[^1]. + +For the use cases in our or service provider networks, we consider the following units: + +* **Boot Config** - Static “bootstrap” configuration required to get a device into a manageable state within the network. This configuration includes parameters such as the gRPC services that are to run, and the management connectivity configuration. +* **Security Config** - Policies related to provide device access - such as authentication and authorization + configurations. This configuration explicitly controls access to who can write the configuration, read parameters + from the device via telemetry, and interact with operational RPCs. This configuration can be considered to be + separate from the base device configuration, since it is owned by a separate entity within the service provider + management plane. It also should not be something that can be modified by an entity that is given read access to + the configuration. +* **Dynamic config** - configuration of the device which is generated according to the topology, and services that + are running on the device. + +It is desirable for each of these elements of configuration to each have a single owner, who is able to + declaratively replace the running configuration on the device without needing to consider contents of the other + elements of the system (i.e., the dynamic configuration manager may be unaware of the bootstrap configuration, or + the authentication configuration). + +### Design Options + +To support such a concept, there are multiple potential solutions that we can consider: + +#### Path based authorization for configuration + +* This concept still has a single root configuration on the device. Clients “own” part of the namespace of this configuration (e.g., `/system/aaa` in OpenConfig), controlled by `gnsi.Pathz` configuration. +* The positive of this approach is that it aligns with existing device operational models, with a single configuration (other than `Pathz` exists on the device). +* The major downside of this approach is fragility - the “dynamic” configuration described above is the catch-all + configuration for the device, and would ideally replace `/`, however, it can no longer do this, fsince there exists + data under the bootstrap configuration (for example, `/interfaces` entries that store the management interfaces) + and the security configuration that must not be replaced. The “dynamic” configuration then must cherry-pick trees + that are to be replaced, potentially at relatively deep levels in the hierarchy. Bugs or issues with which trees + are replaced can render the device unmanageable, or can reflect a security problem (whereby a client that is not + authorized to change security policies is able to do so). +* Equally, authentication policies become more complex in this scenario - we imply the existence of a new namespace (`Pathz`), and create this new concept of multiple configurations solely to enforce the restrictions on the single configuration that we were trying to maintain. + +##### Path based implementation details + +* `gnsi.Pathz` policy would limit specific OpenConfig paths from general writability +* The response to the gNMI `SetRequest` that contains the OC configuration change (update, set, delete) is expected + to indicate that the request failed if those paths are not writable by the caller +* The full config replace would be responsible for only "replacing" specific paths rather than a root level replace + * /system/<subpaths> but excluding /system/aaa or /interfaces/interfac + [name=\*] but exclude /interfaces[name=mgmt0|1], this introduces fragility + and complexity in how the /interfaces/interface list, or /system paths are + managed since they now have multiple writers. + +#### Multiple namespaces for the configuration + +* This is the approach that has been pursued with gNSI - whereby certain subsets of the configuration are moved into + a separate namespace (origin in oc naming), which is not manipulated via gNMI’s `Set` RPC. To support the + bootstrap configuration, an additional ‘boot’ configuration namespace would be introduced. +* A disadvantage of this approach is the change that it makes to existing device configurations, introducing the concept of multiple potentially overlapping configurations. +* An advantage of the approach is that there is clean separation according to the operational use case described + above - a gNSI namespace exists for policies on the device; the ‘boot’ namespace would exist for configuration that + is immutable after device boot; and the existing configuration becomes the dynamic configuration of the device. + Each namespace can have its own policies for permissions, and client service. Client services need not know about + each other’s configuration since replacing a configuration replaces only the namespace of that client. + +##### Multiple namespace implementation details + +* Data supplied by gNSI is considered as a separate namespace/configuration store that is treated independently of configuration interacted with via gNMI. All system AAA paths, certificates, keys, accounts and other gNSI covered data is contained in this namespace. +* If gNSI is enabled on the device all of the content covered via gNSI is interacted with solely within this namespace. To interact with this content, gNSI is used. gNSI SetRequests are ACL'ed via gnsi.Pathz. Additionally, gNSI endpoints would continue to provide set operations as well for those configuration elements. +* OpenConfig and vendor configuration would not be allowed to configure those leaves. + +#### Explicit exclusion of configuration based on a specification in `gNMI.Set` + +* In this approach, rather than having separate namespaces be defined, a client that was performing a `gNMI.Set` request would include some additional information (likely defined through having a new extension message) that specified a set of paths that explicitly should not be modified through the contents of the `SetRequest`. Specifically, this would ensure that: + * Should the payload of the `SetRequest` specify a path that was in the “paths that are not to be modified list” an error would be returned. + * `Replace` operations that give the declarative set of end contents for a + particular path would exclude these being replaced (e.g., a `replace` + operation that impacted `/system`, along with a payload that specified that + `/system/aaa` is not to be modified) would have the semantics of replacing + the contents of `/system` with that specified, yet leaving `/system/aaa` in + place. +* This approach allows for a flexible means by which a scope can be declared + by a client that knows that there are specific areas of the configuration + that it is not intending to modify. Since this scope would be declared by + the client, clearly it is not a security mechanism, and hence `gNSI.Pathz` + is still required to define the authorisation policy as to which client can + write to specific parts of the configuration. +* The downside of this approach is the complexity introduced into the + implementation of the `Set` handler – and at the client. A client that is + managing the dynamic configuration must have a definition as to what areas + of the configuration it does not expect to overwrite, and the target + implementation must add additional validation code to ensure that the + transaction had not changed these values. + +##### Explicit exclusion implementation details + +* A gNMI `SetRequest` would require the inclusion of a message to indicate that a specific set of "exclude paths" are to be honored. +* These paths would be excluded from the merge / replace operations. +* Currently, for some implementations this behavior can be achieved via a proprietary switch within the vendor-configuration that excludes specific paths from being settable from gNMI. + * In this implementation any attempts to "set an excluded" path is ignored. + * This is not advisable as it makes it very opaque during a set as to why a set is having a specific output. + +### Proposed Solution + +We propose to follow the “multiple namespaces for configuration” approach described above, whereby separate configuration stores, per the diagram and process below. + +Figure 1: Proposed configuration namespaces and clients. + +The proposed operational model for devices is shown in Figure 1 above. + +* Security credentials (authorization, accounting, authentication) are + considered part of security/auth namespace. gNSI manages this configuration + store completely. It is considered a “precedence 0” store, whereby it is the + authoritative source of configuration in the case of any overlap with other + namespace. Explicitly, this means that gNSI owns this configuration, and + calls must be made to gNSI to mutate this store. +* Boot configuration (discussed in more detail in this document) is + considered part of a bootstrap namespace. gNOI.Bootz manages this + configuration store completely (proposed and described in this document). + Boot configuration is considered a “precedence 10” store, with it being the + authoritative source of configuration in the case of overlaps. + * Boot configuration is expressly defined to be immutable, and provided + only at the time of device boot. If the boot configuration is required to + be modified, it would be changed through calling a `Set` RPC through the + `Bootz` service. + * When changing this configuration the device must "reapply" configuration + just as would be expected through a controller doing a gnmi.Set union-merge. +* Dynamic configuration reflects the current, widely-understood concept of configuration on a network device. It is managed via gNMI. Each origin within gNMI is assigned an explicit precedence. The precedence for origins is defined in the relevant document - but the value suggested is >= 100,i.e., for overlaps with other namespaces it is explicitly ignored. + * It is expected that this is needed in the case that: + * `/system/aaa` is populated on the device running gNSI. In such a case, gNSI (in the auth namespace) is the source of truth. + * Management interfaces, or running gRPC daemons are specified in the Boot namespace, also in the `/system` or `/interfaces` hierarchies within the dynamic configuration. + +To support this approach, this document proposes a `Bootz` service, which is the mechanism by which the “boot” namespace is interacted with. **`Bootz` is proposed to replace the existing zero-touch-provisioning implementations.** + +### Background + +Currently, the industry standard[^2] is to use the base sZTP protocol + for bootstrapping devices. Current sZTP implementations require vendor + specific definitions for providing the bootstrapping of a device, because + there is no agreed upon vendor neutral data set of “boot configuration” + defined. `Bootz` provides a specification that enumerates the data elements + which can be used in a mainly vendor agnostic way, along with the operations + that are required at turn-up time that become part of the “boot” process. + Specifically, we are suggesting that TPM-related enrollment and attestation + should be required during the boot process to ensure the authenticity and + integrity of the device **before** providing it with potentially sensitive + artifacts such as certificates, key and device configuration. + +### Reference Documentation + +* External + * RFC: [RFC8572](https://datatracker.ietf.org/doc/html/rfc8572) + * Attestation: [Charra Draft](https://datatracker.ietf.org/doc/pdf/draft-ietf-rats-yang-tpm-charra-21#page=5) + +### Bootz Operation + +Devices are expected to perform a standard DHCP boot. The DHCP server passes + a boot option to the device for an endpoint (URL) from which the boot + package can be retrieved. The package returned by the endpoint consists of a + binary encoded protocol buffer containing all data for being able to + complete the boot process. In this context, “complete the boot process” + implies the device reaching a fully manageable state - with the relevant + gRPC services running, security operations(enrollment, attestation, + production credentials installed) are completed. + +Upon receiving the bootz protocol buffer, the device is responsible for +unmarshalling the bootz message and distributing to the relevant system +components for these artifacts to be acted upon. For example, configuration +to a configuration manager component, keys and credentials to the relevant +security components, etc. + + The bootz payload will be encrypted via the TLS session underlying the gRPC service. + +After loading all the provided data on first boot the device is still not in + a trusted state, however it should have enough g\* services initialized to a + state where the device can be interrogated from a trusted system to enroll + the TPM and validate specific TPM values to attest the device. Once + attested, the systems can install production configuration and certificates + into the device. + +## Detailed Design + +### Boot Procedure + +#### **API flow** + +1. DHCP Discovery of Bootstrap Server + 1. Device sends DHCP messages, containing the mac-address of the active control card. The DHCP server has been configured with all possible mac-addresses of the device, and responds with the static IP address of the bootstrap server. + 2. DHCP server also assigns an IP address and a gateway to the device. + 3. The DHCP response option code should be OPTION_V4_SZTP_REDIRECT(136) + or OPTION_V6_SZTP_REDIRECT(143). + 4. The format of the DHCP message (other than response option code) follows [RFC](https://www.rfc-editor.org/rfc/rfc8572#page-56). + 1. The URI will be in the format of bootz://<host or ip>:<port> +2. Bootstrapping Service + 1. Device initiates a gRPC connection to the bootz-server whose address was obtained from the DHCP server. + 2. The TLS connection **MUST** be secured on the client-side with the IDevId of the active control card. + 3. The responses from the bootz-server are signed by ownership-certificate. The device validates the ownership-voucher, which authenticates the ownership-certificate. The device verifies the signature of the message body before accepting the message. + 4. If the signature could not be verified, the bootstrap process starts from Step 1. +3. Ownership Voucher and Ownership Certificate + 1. These artifacts have the same meaning as the original sZTP [RFC](https://www.rfc-editor.org/rfc/rfc8572#section-3.2). This document uses OC and PDC interchangeably for convenience. However, we should keep in mind that OV authenticates a PDC (Pinned Domain Cert), and OC might be a distinct certificate with a chain of trust to the PDC. + 2. The contents of the GetBootstrappingDataResponse has an inner message body. The outer message contains the Ownership Voucher, the Ownership Certificate and a signature over the inner message body. The signature is generated using the OC and the nonce. +4. GetBootstrappingData + 1. The bootz workflow is initiated by the device sending a GetBootstrappingData RPC to the bootz-server. + 2. The device describes itself, by listing out all available control cards, and their states. + 3. For a full device install, the state of all control cards is NOT\_INITIALIZED. + 4. For installing hot-swapped modules (RMA), the primary control card sets its state to INITIALIZED, and that of the swapped module to NOT\_INITIALIZED. +5. GetBootstrappingDataResponse + 1. The server responds with the intent for the device's baseline state. This includes the OS version and boot password hash, and an initial device configuration. + 2. The proto allows us to return multiple sets of configurations, one per control card. However, in practice, we will apply the same configuration to both cards. + 3. For RMA, the server will return only one state - for the RMA'd module. + 4. The device/modules should download the OS image, verify its hash and install the OS. + 1. A reboot may be performed, if required. + 5. The device will then apply the configuration + 1. A reboot may be performed, if required. + 6. The GetIntendedState RPC can be performed as many times as required (i.e. it is idempotent). +6. ReportProgress + 1. This RPC method is used by the device to inform the bootz server that the bootstrapping process is complete. Success or failure is indicated using an enum. + 2. In case of failure, the device should retry this process from Step 1. + 3. When making this RPC, the device should verify the identity of the server using the "`server_trust_cert`" certificate obtained from GetBootstrappingDataResponse. + 4. "`server_trust_cert`" plays the same role as "trust-anchor" in the sZTP RFC (i.e. allows the device to verify the identity of the server). +7. At this point, the device has a minimal set of configuration, enabling it to receive grpc calls. Depending on the operator's security policies, an attestation-verification or an enrollment step may be performed. + 1. At Google, we plan to always require enrollment and attestation-verification. +8. TpmEnrollment + 1. The enrollment API doc is the authoritative reference for this API. The API is reproduced here for convenience. + 2. This step allows the owner organization to install an owner IAK certificate on the device(s). This may be desirable if the owner requires periodic rotation of certificates and a revocation policy that is independent of the device vendor. + 3. The TpmEnrollment API is secured with the IDevID certificate. + 4. During enrollment, the server **MUST** verify that the serial number on the Attestation Key certificate matches the serial number on the DevID certificate, and validate both certificates with the appropriate trust bundle. +9. Attestation + 1. The attestation API doc is the authoritative reference for this API. The API is reproduced here for convenience. + 2. This step allows the owner to obtain cryptographic evidence for the integrity of the software components on the control-cards. + 3. The attestation API should be secured with DevID for the first attestation, and mtls for subsequent attestations. + 1. On first attestation, the server **MUST** verify that the serial number on the Attestation Key certificate matches the serial number on the DevID certificate, and validate both certificates with the appropriate trust bundle. + 4. On modular devices, the active control card obtains attestation evidence from the standby, and relays it to the bootz server. The active card must verify the identity of the standby during this process. The standby card's ability to communicate with the active card is not sufficient evidence of identity. + 1. This specification does not prescribe how to verify the identity of the standby, as the communication between the control cards takes place over vendor-proprietary protocols. However, at a minimum, the active supervisor must check that the standby's TPM-backed IDevID. For example, it may request the IDevID cert, then issue a decrypt challenge to the standby card. +10. Final state: + 1. At this point, the device an initial configuration, user accounts, and we have validated the identity and integrity of the device and its software components. It is ready to serve traffic. + +### A Note on Modular Devices + +Many commercial modular form-factor devices start copying data from the active control card to a hot-swapped standby immediately on plug-in. This includes sensitive data such as credentials and certificates. From a security standpoint, this is undesirable. + +We recommend that the active card copy system software only (includes firmware, bootloader, boot password and OS image), then restart the hot-swapped card. It should verify the standby card's identity (using DevID verified against the vendor root of trust) and attestation evidence (which should match the active card's PCR values) before copying the operator-provided operational configuration. + +Alternatively, the active card can perform the bootstrapping, enrollment and attestation workflow on behalf of the standby before copying operational configuration. + +### Open Questions + +1. Should TpmEnrollment and Attest methods be signed with owner's certificate? +2. Do we intend to use TpmEnrollment to rotate oIAK (and oDevID) also? + +### Protobuf Payload for Bootstrap + +The following protocol buffer is provided from the bootserver to the device to provide the bundle of artifacts needed for the device to reach a manageable state. + +See [PR](https://github.com/openconfig/bootz/pull/1) diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..8d8bffe --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,99 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +### Bazel rules for many languages to compile PROTO into gRPC libraries +# Note: any version of this which is less than 4.3.0 requires bazel version 5.4.0 (set in .bazelversion file) +http_archive( + name = "rules_proto_grpc", + sha256 = "fb7fc7a3c19a92b2f15ed7c4ffb2983e956625c1436f57a3430b897ba9864059", + strip_prefix = "rules_proto_grpc-4.3.0", + urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/4.3.0.tar.gz"], +) + +# googleapis has not had a release since 2016 - take the master version as of 4-jan-23 +http_archive( + name = "com_google_googleapis", + sha256 = "9fc03150d86501d7da35eefa989d5553bdd77a95cfe4373cdafe8eee92f6bfb1", + strip_prefix = "googleapis-870a5ed7e141b4faf70e2a0858854e9b5bb18612", + urls = ["https://github.com/googleapis/googleapis/archive/870a5ed7e141b4faf70e2a0858854e9b5bb18612.tar.gz"], +) + +load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") +switched_rules_by_language( + name = "com_google_googleapis_imports", + cc = True, + go = True, +) + +load( + "@rules_proto_grpc//:repositories.bzl", + "bazel_gazelle", + "io_bazel_rules_go", + "rules_proto_grpc_repos", + "rules_proto_grpc_toolchains", +) + +rules_proto_grpc_toolchains() + +rules_proto_grpc_repos() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() + +### Golang +io_bazel_rules_go() + +load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") + +go_rules_dependencies() + +go_register_toolchains(go_version = "1.18") + +# gazelle:repo bazel_gazelle +bazel_gazelle() + +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") + +go_repository( + name = "com_github_openconfig_gnoi", + build_directives = [ + "gazelle:proto_import_prefix github.com/openconfig/gnoi", + ], + build_file_generation = "on", + importpath = "github.com/openconfig/gnoi", + sum = "h1:7Odq6UyieHuXW3PYfDBj/dUWgFrL9KVMm0iooQoFLdw=", + version = "v0.1.0", +) + +go_repository( + name = "com_github_openconfig_gnmi", + build_directives = [ + "gazelle:proto_import_prefix github.com/openconfig/gnmi", + ], + build_file_generation = "on", + importpath = "github.com/openconfig/gnmi", + sum = "h1:hVOdLTaRjdy68oCGJbkf2vrmnUoQ5xbINqBOAMix4xM=", + version = "v0.9.1", +) + +go_repository( + name = "com_github_openconfig_gnsi", + importpath = "github.com/openconfig/gnsi", + sum = "h1:CfJsd2V3ElPPtp3eAEExsShKy86Ar20hPL0rhlTp0l0=", + version = "v0.2.1", +) + +load("@rules_proto_grpc//go:repositories.bzl", rules_proto_grpc_go_repos = "go_repos") + +rules_proto_grpc_go_repos() + +# Load gazelle_dependencies last, so that the newer version of org_golang_google_grpc is used. +# see https://github.com/rules-proto-grpc/rules_proto_grpc/issues/160 +gazelle_dependencies() + + +load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") + +grpc_deps() diff --git a/common.bzl b/common.bzl new file mode 100644 index 0000000..a340c13 --- /dev/null +++ b/common.bzl @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//proto:compiler.bzl", "go_proto_compiler") +load("@io_bazel_rules_go//proto/wkt:well_known_types.bzl", "PROTO_RUNTIME_DEPS", "WELL_KNOWN_TYPES_APIV2") + +def use_new_compilers(): + go_proto_compiler( + name = "go_protoc_gen_go", + options = [ + "paths=source_relative", + ], + plugin = "@org_golang_google_protobuf//cmd/protoc-gen-go", + suffix = ".pb.go", + visibility = ["//visibility:public"], + deps = PROTO_RUNTIME_DEPS + WELL_KNOWN_TYPES_APIV2, + ) + go_proto_compiler( + name = "go_protoc_gen_go_grpc", + options = [ + "paths=source_relative", + ], + plugin = "@org_golang_google_grpc_cmd_protoc_gen_go_grpc//:protoc-gen-go-grpc", + suffix = "_grpc.pb.go", + visibility = ["//visibility:public"], + deps = PROTO_RUNTIME_DEPS + [ + "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//codes:go_default_library", + "@org_golang_google_grpc//status:go_default_library", + ], + ) \ No newline at end of file diff --git a/proto/BUILD.bazel b/proto/BUILD.bazel new file mode 100644 index 0000000..69298e3 --- /dev/null +++ b/proto/BUILD.bazel @@ -0,0 +1,47 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") +load("//:common.bzl", "use_new_compilers") + +package(default_visibility = ["//visibility:public"]) + +use_new_compilers() + +proto_library( + name = "bootz_proto", + srcs = ["bootz.proto"], + import_prefix = "github.com/openconfig/bootz", + deps = [ + "@com_google_protobuf//:struct_proto", + "@com_github_openconfig_gnsi//authz:authz_proto", + "@com_github_openconfig_gnsi//certz:certz_proto", + "@com_github_openconfig_gnsi//credentialz:credentialz_proto", + "@com_github_openconfig_gnsi//pathz:pathz_proto", + ], +) + +############################################################################## +# Go +############################################################################## + +go_proto_library( + name = "bootz_go_proto", + compilers = [ + "go_protoc_gen_go", + "go_protoc_gen_go_grpc", + ], + importpath = "github.com/openconfig/bootz/proto/bootz", + proto = ":bootz_proto", + deps = [ + "@com_github_openconfig_gnsi//authz:authz_go_proto", + "@com_github_openconfig_gnsi//certz:certz_go_proto", + "@com_github_openconfig_gnsi//credentialz:credentialz_go_proto", + "@com_github_openconfig_gnsi//pathz:pathz_go_proto", + ], +) + +go_library( + name = "bootz", + embed = [":bootz_go_proto"], + importpath = "github.com/openconfig/bootz/proto/bootz", +) \ No newline at end of file diff --git a/proto/bootz.proto b/proto/bootz.proto new file mode 100644 index 0000000..a12d38f --- /dev/null +++ b/proto/bootz.proto @@ -0,0 +1,191 @@ +// +// Copyright 2023 Google Inc. All Rights Reserved. +// +// 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 +// +// http://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"; + +import "google/protobuf/struct.proto"; + +import "github.com/openconfig/gnsi/authz/authz.proto"; +import "github.com/openconfig/gnsi/certz/certz.proto"; +import "github.com/openconfig/gnsi/credentialz/credentialz.proto"; +import "github.com/openconfig/gnsi/pathz/pathz.proto"; + + +option go_package = "github.com/openconfig/bootz/proto/bootz"; + + +// The Bootz service definition. +// Bootz service is hosted by the bootz-server, and the device is the +// client (as opposed to most g*i services, which are hosted by the device). +service Bootstrap { + // This RPC returns the data required to put the device in a known state + // (i.e. OS, bootloader password, etc) and applies an initial device + // configuration. + rpc GetBootstrapData(GetBootstrapDataRequest) returns + (GetBootstrapDataResponse) {} + + // This RPC is used by the device to indicate successful application of + // BootstrappingData. The Bootz system will proceed to the next step if + // a SUCCESS is reported, otherwise it will retry or put the device in an + // out-of-service state. The device should validate the server's identity + // against the server_trust_cert it obtained in GetBootstrappingDataResponse. + rpc ReportStatus(ReportStatusRequest) returns (EmptyResponse) {} +} + +// Initial request from device to the bootz-server. Contains a detailed +// description of the chassis and its constituent control cards. +message GetBootstrapDataRequest { + ChassisDescriptor chassis_descriptor = 1; + ControlCardState control_card_state = 2; + // A nonce that the bootstrap server should use when signing the response. + string nonce = 1001; +} + +// Structured message containing the chassis details, and listing its component +// control-card modules. +message ChassisDescriptor { + string manufacturer = 1; + string part_number = 2; + // This field is populated for fixed form-factor chassis, and empty for + // modular chassis. + string serial_number = 3; + // For modular chassis this field will be used to list the control cards + // to be bootstrapped. + repeated ControlCard control_cards = 4; +} + +// Details of the control card, including serial-number and the location +// of the card on the chassis. +message ControlCard { + string part_number = 1; + string serial_number = 2; + int32 slot = 3; +} + +// ControlCardState indicates if the bootstrap process has +// successfully completed. +// +// At the beginning of the bootstrap process (i.e. before a +// ReportStatus has completed with BOOTSTRAP_STATUS_SUCCESS), +// all control cards (1 or 2) are in NOT_INITIALIZED state. +// If bootstrap successfully completes for a control-card, the +// ControlCardStatus changes to INITIALIZED. +// +// Once a control-card is in INITIALIZED state, it may remain in that +// state indefinitely, even if removed and reinstalled in a chassis. +// +// When there are 2 control-cards present and INITIALIZED and 1 is +// removed, the remaining control card remains in INITIALIZED state. +// If a new control-card is inserted which has never completed the +// bootstrap process, it will start with NOT_INITIALIZED state. +message ControlCardState { + + enum ControlCardStatus { + // the bootstrap process status is not reported. + CONTROL_CARD_STATUS_UNSPECIFIED = 0; + // the bootstrap process has not successfully completed. + CONTROL_CARD_STATUS_NOT_INITIALIZED = 1; + // the bootstrap process has successfully completed. + CONTROL_CARD_STATUS_INITIALIZED = 2; + } + + string serial_number = 1; + ControlCardStatus status = 2; +} + +message GetBootstrapDataResponse { + + message BootstrapDataResponse { + // The serial number of the control card to which this state should + // be applied. + string serial_num = 1; + // The device should download and install this image (or skip if the + // device is already running it). + SoftwareImage intended_image = 2; + // The device should set this hash as its Bootloader password. + string boot_password_hash = 3; + // This certificate should be used to validate the server when reporting + // progress. + string server_trust_cert = 4; + // Boot configuration is specified as structured data. + BootConfig boot_config = 5; + Credentials credentials = 6; + gnsi.pathz.v1.UploadRequest pathz = 7; + gnsi.authz.v1.UploadRequest authz = 8; + gnsi.certz.v1.UploadRequest certificates = 9; + } + + // Container message that is signed by server. + // the nonce is added to verify the contents from the client. + message BootstrapDataSigned { + repeated BootstrapDataResponse responses = 1; + string nonce = 2; + } + + BootstrapDataSigned signed_response = 1; + bytes ownership_voucher = 101; + bytes ownership_certificate = 102; + // This is a signature generated over the bytes of the signed_response field, + // using the ownership_certificate. + string response_signature = 103; +} + +message SoftwareImage { + string name = 1; + string version = 2; + // An HTTP location from where the OS file can be downloaded. + string url = 3; + // Hash of the OS image. The device must verify that the hash of the + // downloaded OS image matches this. + string os_image_hash = 4; + string hash_algorithm = 5; +} + +message Credentials { + repeated gnsi.credentialz.v1.AuthorizedKeysRequest credentials = 1; + repeated gnsi.credentialz.v1.AuthorizedUsersRequest users = 2; + repeated gnsi.credentialz.v1.PasswordRequest passwords = 3; +} + +message BootConfig { + // Proprietary key-value parameters that are required as part of boot + // configuration (e.g., feature flags, or vendor-specific hardware knobs). + google.protobuf.Struct metadata = 1; + // Native format vendor configuration. + bytes vendor_config = 2; + // JSON rendered OC configuration. + bytes oc_config = 3; + // Bootloader key-value parameters that are required as part of boot + // configuration. + google.protobuf.Struct bootloader_config = 4; +} + +// The device reports the status of applying Bootstrap data using this service. +// The status_message is a human-readable message indicating the nature of +// failure, if any. +message ReportStatusRequest { + enum BootstrapStatus { + BOOTSTRAP_STATUS_UNSPECIFIED = 0; + BOOTSTRAP_STATUS_SUCCESS = 1; + BOOTSTRAP_STATUS_FAILURE = 2; + BOOTSTRAP_STATUS_INITIATED = 3; + } + BootstrapStatus status = 1; + string status_message = 2; +} + +// Used in RPC methods that are not expected to return a response. +message EmptyResponse { +} diff --git a/proto/bootz/bootz.pb.go b/proto/bootz/bootz.pb.go new file mode 100755 index 0000000..b1ceb41 --- /dev/null +++ b/proto/bootz/bootz.pb.go @@ -0,0 +1,1348 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.10 +// source: github.com/openconfig/bootz/proto/bootz.proto + +package bootz + +import ( + authz "github.com/openconfig/gnsi/authz" + certz "github.com/openconfig/gnsi/certz" + credentialz "github.com/openconfig/gnsi/credentialz" + pathz "github.com/openconfig/gnsi/pathz" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" + reflect "reflect" + sync "sync" +) + +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 ControlCardStatus int32 + +const ( + ControlCardStatus_CONTROL_CARD_STATUS_UNSPECIFIED ControlCardStatus = 0 + ControlCardStatus_CONTROL_CARD_STATUS_NOT_INSTALLED ControlCardStatus = 1 + ControlCardStatus_CONTROL_CARD_STATUS_INSTALLED ControlCardStatus = 2 +) + +// Enum value maps for ControlCardStatus. +var ( + ControlCardStatus_name = map[int32]string{ + 0: "CONTROL_CARD_STATUS_UNSPECIFIED", + 1: "CONTROL_CARD_STATUS_NOT_INSTALLED", + 2: "CONTROL_CARD_STATUS_INSTALLED", + } + ControlCardStatus_value = map[string]int32{ + "CONTROL_CARD_STATUS_UNSPECIFIED": 0, + "CONTROL_CARD_STATUS_NOT_INSTALLED": 1, + "CONTROL_CARD_STATUS_INSTALLED": 2, + } +) + +func (x ControlCardStatus) Enum() *ControlCardStatus { + p := new(ControlCardStatus) + *p = x + return p +} + +func (x ControlCardStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ControlCardStatus) Descriptor() protoreflect.EnumDescriptor { + return file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes[0].Descriptor() +} + +func (ControlCardStatus) Type() protoreflect.EnumType { + return &file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes[0] +} + +func (x ControlCardStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ControlCardStatus.Descriptor instead. +func (ControlCardStatus) EnumDescriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{0} +} + +type ReportStatusRequest_BootstrapStatus int32 + +const ( + ReportStatusRequest_BOOTSTRAP_STATUS_UNSPECIFIED ReportStatusRequest_BootstrapStatus = 0 + ReportStatusRequest_BOOTSTRAP_STATUS_SUCCESS ReportStatusRequest_BootstrapStatus = 1 + ReportStatusRequest_BOOTSTRAP_STATUS_FAILURE ReportStatusRequest_BootstrapStatus = 2 + ReportStatusRequest_BOOTSTRAP_STATUS_INITIATED ReportStatusRequest_BootstrapStatus = 3 +) + +// Enum value maps for ReportStatusRequest_BootstrapStatus. +var ( + ReportStatusRequest_BootstrapStatus_name = map[int32]string{ + 0: "BOOTSTRAP_STATUS_UNSPECIFIED", + 1: "BOOTSTRAP_STATUS_SUCCESS", + 2: "BOOTSTRAP_STATUS_FAILURE", + 3: "BOOTSTRAP_STATUS_INITIATED", + } + ReportStatusRequest_BootstrapStatus_value = map[string]int32{ + "BOOTSTRAP_STATUS_UNSPECIFIED": 0, + "BOOTSTRAP_STATUS_SUCCESS": 1, + "BOOTSTRAP_STATUS_FAILURE": 2, + "BOOTSTRAP_STATUS_INITIATED": 3, + } +) + +func (x ReportStatusRequest_BootstrapStatus) Enum() *ReportStatusRequest_BootstrapStatus { + p := new(ReportStatusRequest_BootstrapStatus) + *p = x + return p +} + +func (x ReportStatusRequest_BootstrapStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ReportStatusRequest_BootstrapStatus) Descriptor() protoreflect.EnumDescriptor { + return file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes[1].Descriptor() +} + +func (ReportStatusRequest_BootstrapStatus) Type() protoreflect.EnumType { + return &file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes[1] +} + +func (x ReportStatusRequest_BootstrapStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ReportStatusRequest_BootstrapStatus.Descriptor instead. +func (ReportStatusRequest_BootstrapStatus) EnumDescriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{8, 0} +} + +type GetBootstrapDataRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChassisDescriptor *ChassisDescriptor `protobuf:"bytes,1,opt,name=chassis_descriptor,json=chassisDescriptor,proto3" json:"chassis_descriptor,omitempty"` + ControlCardState *ControlCardState `protobuf:"bytes,2,opt,name=control_card_state,json=controlCardState,proto3" json:"control_card_state,omitempty"` + Nonce string `protobuf:"bytes,1001,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (x *GetBootstrapDataRequest) Reset() { + *x = GetBootstrapDataRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBootstrapDataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBootstrapDataRequest) ProtoMessage() {} + +func (x *GetBootstrapDataRequest) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBootstrapDataRequest.ProtoReflect.Descriptor instead. +func (*GetBootstrapDataRequest) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{0} +} + +func (x *GetBootstrapDataRequest) GetChassisDescriptor() *ChassisDescriptor { + if x != nil { + return x.ChassisDescriptor + } + return nil +} + +func (x *GetBootstrapDataRequest) GetControlCardState() *ControlCardState { + if x != nil { + return x.ControlCardState + } + return nil +} + +func (x *GetBootstrapDataRequest) GetNonce() string { + if x != nil { + return x.Nonce + } + return "" +} + +type ChassisDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Manufacturer string `protobuf:"bytes,1,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + PartNumber string `protobuf:"bytes,2,opt,name=part_number,json=partNumber,proto3" json:"part_number,omitempty"` + SerialNumber string `protobuf:"bytes,3,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + ControlCards []*ControlCard `protobuf:"bytes,4,rep,name=control_cards,json=controlCards,proto3" json:"control_cards,omitempty"` +} + +func (x *ChassisDescriptor) Reset() { + *x = ChassisDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChassisDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChassisDescriptor) ProtoMessage() {} + +func (x *ChassisDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChassisDescriptor.ProtoReflect.Descriptor instead. +func (*ChassisDescriptor) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{1} +} + +func (x *ChassisDescriptor) GetManufacturer() string { + if x != nil { + return x.Manufacturer + } + return "" +} + +func (x *ChassisDescriptor) GetPartNumber() string { + if x != nil { + return x.PartNumber + } + return "" +} + +func (x *ChassisDescriptor) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *ChassisDescriptor) GetControlCards() []*ControlCard { + if x != nil { + return x.ControlCards + } + return nil +} + +type ControlCard struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PartNumber string `protobuf:"bytes,1,opt,name=part_number,json=partNumber,proto3" json:"part_number,omitempty"` + SerialNumber string `protobuf:"bytes,2,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + Slot int32 `protobuf:"varint,3,opt,name=slot,proto3" json:"slot,omitempty"` +} + +func (x *ControlCard) Reset() { + *x = ControlCard{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[2] + 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_proto_bootz_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && 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_proto_bootz_proto_rawDescGZIP(), []int{2} +} + +func (x *ControlCard) GetPartNumber() string { + if x != nil { + return x.PartNumber + } + return "" +} + +func (x *ControlCard) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *ControlCard) GetSlot() int32 { + if x != nil { + return x.Slot + } + return 0 +} + +type ControlCardState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SerialNumber string `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"` + Status ControlCardStatus `protobuf:"varint,2,opt,name=status,proto3,enum=ControlCardStatus" json:"status,omitempty"` +} + +func (x *ControlCardState) Reset() { + *x = ControlCardState{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ControlCardState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ControlCardState) ProtoMessage() {} + +func (x *ControlCardState) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ControlCardState.ProtoReflect.Descriptor instead. +func (*ControlCardState) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{3} +} + +func (x *ControlCardState) GetSerialNumber() string { + if x != nil { + return x.SerialNumber + } + return "" +} + +func (x *ControlCardState) GetStatus() ControlCardStatus { + if x != nil { + return x.Status + } + return ControlCardStatus_CONTROL_CARD_STATUS_UNSPECIFIED +} + +type GetBootstrapDataResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SignedResponse *GetBootstrapDataResponse_BootstrapDataSigned `protobuf:"bytes,1,opt,name=signed_response,json=signedResponse,proto3" json:"signed_response,omitempty"` + OwnershipVoucher []byte `protobuf:"bytes,101,opt,name=ownership_voucher,json=ownershipVoucher,proto3" json:"ownership_voucher,omitempty"` + OwnershipCertificate []byte `protobuf:"bytes,102,opt,name=ownership_certificate,json=ownershipCertificate,proto3" json:"ownership_certificate,omitempty"` + ResponseSignature string `protobuf:"bytes,103,opt,name=response_signature,json=responseSignature,proto3" json:"response_signature,omitempty"` +} + +func (x *GetBootstrapDataResponse) Reset() { + *x = GetBootstrapDataResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBootstrapDataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBootstrapDataResponse) ProtoMessage() {} + +func (x *GetBootstrapDataResponse) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBootstrapDataResponse.ProtoReflect.Descriptor instead. +func (*GetBootstrapDataResponse) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{4} +} + +func (x *GetBootstrapDataResponse) GetSignedResponse() *GetBootstrapDataResponse_BootstrapDataSigned { + if x != nil { + return x.SignedResponse + } + return nil +} + +func (x *GetBootstrapDataResponse) GetOwnershipVoucher() []byte { + if x != nil { + return x.OwnershipVoucher + } + return nil +} + +func (x *GetBootstrapDataResponse) GetOwnershipCertificate() []byte { + if x != nil { + return x.OwnershipCertificate + } + return nil +} + +func (x *GetBootstrapDataResponse) GetResponseSignature() string { + if x != nil { + return x.ResponseSignature + } + return "" +} + +type SoftwareImage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"` + OsImageHash string `protobuf:"bytes,4,opt,name=os_image_hash,json=osImageHash,proto3" json:"os_image_hash,omitempty"` + HashAlgorithm string `protobuf:"bytes,5,opt,name=hash_algorithm,json=hashAlgorithm,proto3" json:"hash_algorithm,omitempty"` +} + +func (x *SoftwareImage) Reset() { + *x = SoftwareImage{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SoftwareImage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SoftwareImage) ProtoMessage() {} + +func (x *SoftwareImage) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SoftwareImage.ProtoReflect.Descriptor instead. +func (*SoftwareImage) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{5} +} + +func (x *SoftwareImage) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *SoftwareImage) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *SoftwareImage) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *SoftwareImage) GetOsImageHash() string { + if x != nil { + return x.OsImageHash + } + return "" +} + +func (x *SoftwareImage) GetHashAlgorithm() string { + if x != nil { + return x.HashAlgorithm + } + return "" +} + +type Credentials struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Credentials []*credentialz.AuthorizedKeysRequest `protobuf:"bytes,1,rep,name=credentials,proto3" json:"credentials,omitempty"` + Users []*credentialz.AuthorizedUsersRequest `protobuf:"bytes,2,rep,name=users,proto3" json:"users,omitempty"` + Passwords []*credentialz.PasswordRequest `protobuf:"bytes,3,rep,name=passwords,proto3" json:"passwords,omitempty"` +} + +func (x *Credentials) Reset() { + *x = Credentials{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Credentials) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Credentials) ProtoMessage() {} + +func (x *Credentials) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Credentials.ProtoReflect.Descriptor instead. +func (*Credentials) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{6} +} + +func (x *Credentials) GetCredentials() []*credentialz.AuthorizedKeysRequest { + if x != nil { + return x.Credentials + } + return nil +} + +func (x *Credentials) GetUsers() []*credentialz.AuthorizedUsersRequest { + if x != nil { + return x.Users + } + return nil +} + +func (x *Credentials) GetPasswords() []*credentialz.PasswordRequest { + if x != nil { + return x.Passwords + } + return nil +} + +type BootConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Metadata *structpb.Struct `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + VendorConfig []byte `protobuf:"bytes,2,opt,name=vendor_config,json=vendorConfig,proto3" json:"vendor_config,omitempty"` + OcConfig []byte `protobuf:"bytes,3,opt,name=oc_config,json=ocConfig,proto3" json:"oc_config,omitempty"` + BootloaderConfig *structpb.Struct `protobuf:"bytes,4,opt,name=bootloader_config,json=bootloaderConfig,proto3" json:"bootloader_config,omitempty"` +} + +func (x *BootConfig) Reset() { + *x = BootConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BootConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BootConfig) ProtoMessage() {} + +func (x *BootConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BootConfig.ProtoReflect.Descriptor instead. +func (*BootConfig) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{7} +} + +func (x *BootConfig) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *BootConfig) GetVendorConfig() []byte { + if x != nil { + return x.VendorConfig + } + return nil +} + +func (x *BootConfig) GetOcConfig() []byte { + if x != nil { + return x.OcConfig + } + return nil +} + +func (x *BootConfig) GetBootloaderConfig() *structpb.Struct { + if x != nil { + return x.BootloaderConfig + } + return nil +} + +type ReportStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status ReportStatusRequest_BootstrapStatus `protobuf:"varint,1,opt,name=status,proto3,enum=ReportStatusRequest_BootstrapStatus" json:"status,omitempty"` + StatusMessage string `protobuf:"bytes,2,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"` +} + +func (x *ReportStatusRequest) Reset() { + *x = ReportStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportStatusRequest) ProtoMessage() {} + +func (x *ReportStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportStatusRequest.ProtoReflect.Descriptor instead. +func (*ReportStatusRequest) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{8} +} + +func (x *ReportStatusRequest) GetStatus() ReportStatusRequest_BootstrapStatus { + if x != nil { + return x.Status + } + return ReportStatusRequest_BOOTSTRAP_STATUS_UNSPECIFIED +} + +func (x *ReportStatusRequest) GetStatusMessage() string { + if x != nil { + return x.StatusMessage + } + return "" +} + +type EmptyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EmptyResponse) Reset() { + *x = EmptyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmptyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyResponse) ProtoMessage() {} + +func (x *EmptyResponse) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EmptyResponse.ProtoReflect.Descriptor instead. +func (*EmptyResponse) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{9} +} + +type GetBootstrapDataResponse_BootstrapDataResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SerialNum string `protobuf:"bytes,1,opt,name=serial_num,json=serialNum,proto3" json:"serial_num,omitempty"` + IntendedImage *SoftwareImage `protobuf:"bytes,2,opt,name=intended_image,json=intendedImage,proto3" json:"intended_image,omitempty"` + BootPasswordHash string `protobuf:"bytes,3,opt,name=boot_password_hash,json=bootPasswordHash,proto3" json:"boot_password_hash,omitempty"` + ServerTrustCert string `protobuf:"bytes,4,opt,name=server_trust_cert,json=serverTrustCert,proto3" json:"server_trust_cert,omitempty"` + BootConfig *BootConfig `protobuf:"bytes,5,opt,name=boot_config,json=bootConfig,proto3" json:"boot_config,omitempty"` + Credentials *Credentials `protobuf:"bytes,6,opt,name=credentials,proto3" json:"credentials,omitempty"` + Pathz *pathz.UploadRequest `protobuf:"bytes,7,opt,name=pathz,proto3" json:"pathz,omitempty"` + Authz *authz.UploadRequest `protobuf:"bytes,8,opt,name=authz,proto3" json:"authz,omitempty"` + Certificates *certz.UploadRequest `protobuf:"bytes,9,opt,name=certificates,proto3" json:"certificates,omitempty"` +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) Reset() { + *x = GetBootstrapDataResponse_BootstrapDataResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBootstrapDataResponse_BootstrapDataResponse) ProtoMessage() {} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBootstrapDataResponse_BootstrapDataResponse.ProtoReflect.Descriptor instead. +func (*GetBootstrapDataResponse_BootstrapDataResponse) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetSerialNum() string { + if x != nil { + return x.SerialNum + } + return "" +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetIntendedImage() *SoftwareImage { + if x != nil { + return x.IntendedImage + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetBootPasswordHash() string { + if x != nil { + return x.BootPasswordHash + } + return "" +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetServerTrustCert() string { + if x != nil { + return x.ServerTrustCert + } + return "" +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetBootConfig() *BootConfig { + if x != nil { + return x.BootConfig + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetCredentials() *Credentials { + if x != nil { + return x.Credentials + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetPathz() *pathz.UploadRequest { + if x != nil { + return x.Pathz + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetAuthz() *authz.UploadRequest { + if x != nil { + return x.Authz + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataResponse) GetCertificates() *certz.UploadRequest { + if x != nil { + return x.Certificates + } + return nil +} + +type GetBootstrapDataResponse_BootstrapDataSigned struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Responses []*GetBootstrapDataResponse_BootstrapDataResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"` + Nonce string `protobuf:"bytes,2,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (x *GetBootstrapDataResponse_BootstrapDataSigned) Reset() { + *x = GetBootstrapDataResponse_BootstrapDataSigned{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBootstrapDataResponse_BootstrapDataSigned) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBootstrapDataResponse_BootstrapDataSigned) ProtoMessage() {} + +func (x *GetBootstrapDataResponse_BootstrapDataSigned) ProtoReflect() protoreflect.Message { + mi := &file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBootstrapDataResponse_BootstrapDataSigned.ProtoReflect.Descriptor instead. +func (*GetBootstrapDataResponse_BootstrapDataSigned) Descriptor() ([]byte, []int) { + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *GetBootstrapDataResponse_BootstrapDataSigned) GetResponses() []*GetBootstrapDataResponse_BootstrapDataResponse { + if x != nil { + return x.Responses + } + return nil +} + +func (x *GetBootstrapDataResponse_BootstrapDataSigned) GetNonce() string { + if x != nil { + return x.Nonce + } + return "" +} + +var File_github_com_openconfig_bootz_proto_bootz_proto protoreflect.FileDescriptor + +var file_github_com_openconfig_bootz_proto_bootz_proto_rawDesc = []byte{ + 0x0a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x7a, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x73, 0x69, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x2f, + 0x61, 0x75, 0x74, 0x68, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x73, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x7a, 0x2f, 0x63, 0x65, + 0x72, 0x74, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2f, 0x67, 0x6e, 0x73, 0x69, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x7a, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x7a, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x73, 0x69, 0x2f, + 0x70, 0x61, 0x74, 0x68, 0x7a, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0xb4, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, + 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, + 0x12, 0x63, 0x68, 0x61, 0x73, 0x73, 0x69, 0x73, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x43, 0x68, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x11, 0x63, + 0x68, 0x61, 0x73, 0x73, 0x69, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, + 0x12, 0x3f, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x15, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x61, + 0x73, 0x73, 0x69, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x22, + 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, + 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x0c, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x73, 0x22, 0x67, 0x0a, 0x0b, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, + 0x72, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x61, 0x72, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x73, 0x6c, 0x6f, 0x74, 0x22, 0x63, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, + 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2a, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xd1, 0x06, 0x0a, 0x18, 0x47, 0x65, + 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, + 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, + 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x0e, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, + 0x0a, 0x11, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x76, 0x6f, 0x75, 0x63, + 0x68, 0x65, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x15, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x18, 0x66, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x67, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0xcf, 0x03, 0x0a, 0x15, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, + 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x12, 0x35, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x2c, 0x0a, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x6f, 0x6f, + 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, + 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x63, 0x65, + 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x0b, 0x62, 0x6f, 0x6f, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, + 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x62, 0x6f, 0x6f, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x43, + 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x7a, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6e, 0x73, 0x69, 0x2e, 0x70, 0x61, + 0x74, 0x68, 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x7a, 0x12, 0x32, 0x0a, 0x05, 0x61, + 0x75, 0x74, 0x68, 0x7a, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6e, 0x73, + 0x69, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x12, + 0x40, 0x0a, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6e, 0x73, 0x69, 0x2e, 0x63, 0x65, 0x72, + 0x74, 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x1a, 0x7a, 0x0a, 0x13, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x12, 0x4d, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x47, 0x65, + 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x9a, 0x01, + 0x0a, 0x0d, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, + 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6c, 0x67, 0x6f, + 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68, 0x61, 0x73, + 0x68, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, 0xe2, 0x01, 0x0a, 0x0b, 0x43, + 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x4c, 0x0a, 0x0b, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2a, 0x2e, 0x67, 0x6e, 0x73, 0x69, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0b, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6e, 0x73, 0x69, 0x2e, 0x63, + 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x67, 0x6e, 0x73, 0x69, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x7a, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x09, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x22, + 0xc9, 0x01, 0x0a, 0x0a, 0x42, 0x6f, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x6e, 0x64, + 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x63, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6f, 0x63, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x11, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, + 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x6c, + 0x6f, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x8c, 0x02, 0x0a, 0x13, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, + 0x72, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x0f, 0x42, 0x6f, 0x6f, + 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, + 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, + 0x0a, 0x18, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, + 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x42, 0x4f, + 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, + 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x0f, 0x0a, 0x0d, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x11, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x4f, 0x4c, 0x5f, 0x43, 0x41, 0x52, + 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x4f, + 0x4c, 0x5f, 0x43, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4e, 0x4f, + 0x54, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x21, 0x0a, + 0x1d, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x4f, 0x4c, 0x5f, 0x43, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x02, + 0x32, 0x8e, 0x01, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, 0x49, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x18, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, + 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x47, + 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0c, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x2e, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x0e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x7a, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x7a, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_github_com_openconfig_bootz_proto_bootz_proto_rawDescOnce sync.Once + file_github_com_openconfig_bootz_proto_bootz_proto_rawDescData = file_github_com_openconfig_bootz_proto_bootz_proto_rawDesc +) + +func file_github_com_openconfig_bootz_proto_bootz_proto_rawDescGZIP() []byte { + file_github_com_openconfig_bootz_proto_bootz_proto_rawDescOnce.Do(func() { + file_github_com_openconfig_bootz_proto_bootz_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_bootz_proto_bootz_proto_rawDescData) + }) + return file_github_com_openconfig_bootz_proto_bootz_proto_rawDescData +} + +var file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_github_com_openconfig_bootz_proto_bootz_proto_goTypes = []interface{}{ + (ControlCardStatus)(0), // 0: ControlCardStatus + (ReportStatusRequest_BootstrapStatus)(0), // 1: ReportStatusRequest.BootstrapStatus + (*GetBootstrapDataRequest)(nil), // 2: GetBootstrapDataRequest + (*ChassisDescriptor)(nil), // 3: ChassisDescriptor + (*ControlCard)(nil), // 4: ControlCard + (*ControlCardState)(nil), // 5: ControlCardState + (*GetBootstrapDataResponse)(nil), // 6: GetBootstrapDataResponse + (*SoftwareImage)(nil), // 7: SoftwareImage + (*Credentials)(nil), // 8: Credentials + (*BootConfig)(nil), // 9: BootConfig + (*ReportStatusRequest)(nil), // 10: ReportStatusRequest + (*EmptyResponse)(nil), // 11: EmptyResponse + (*GetBootstrapDataResponse_BootstrapDataResponse)(nil), // 12: GetBootstrapDataResponse.BootstrapDataResponse + (*GetBootstrapDataResponse_BootstrapDataSigned)(nil), // 13: GetBootstrapDataResponse.BootstrapDataSigned + (*credentialz.AuthorizedKeysRequest)(nil), // 14: gnsi.credentialz.v1.AuthorizedKeysRequest + (*credentialz.AuthorizedUsersRequest)(nil), // 15: gnsi.credentialz.v1.AuthorizedUsersRequest + (*credentialz.PasswordRequest)(nil), // 16: gnsi.credentialz.v1.PasswordRequest + (*structpb.Struct)(nil), // 17: google.protobuf.Struct + (*pathz.UploadRequest)(nil), // 18: gnsi.pathz.v1.UploadRequest + (*authz.UploadRequest)(nil), // 19: gnsi.authz.v1.UploadRequest + (*certz.UploadRequest)(nil), // 20: gnsi.certz.v1.UploadRequest +} +var file_github_com_openconfig_bootz_proto_bootz_proto_depIdxs = []int32{ + 3, // 0: GetBootstrapDataRequest.chassis_descriptor:type_name -> ChassisDescriptor + 5, // 1: GetBootstrapDataRequest.control_card_state:type_name -> ControlCardState + 4, // 2: ChassisDescriptor.control_cards:type_name -> ControlCard + 0, // 3: ControlCardState.status:type_name -> ControlCardStatus + 13, // 4: GetBootstrapDataResponse.signed_response:type_name -> GetBootstrapDataResponse.BootstrapDataSigned + 14, // 5: Credentials.credentials:type_name -> gnsi.credentialz.v1.AuthorizedKeysRequest + 15, // 6: Credentials.users:type_name -> gnsi.credentialz.v1.AuthorizedUsersRequest + 16, // 7: Credentials.passwords:type_name -> gnsi.credentialz.v1.PasswordRequest + 17, // 8: BootConfig.metadata:type_name -> google.protobuf.Struct + 17, // 9: BootConfig.bootloader_config:type_name -> google.protobuf.Struct + 1, // 10: ReportStatusRequest.status:type_name -> ReportStatusRequest.BootstrapStatus + 7, // 11: GetBootstrapDataResponse.BootstrapDataResponse.intended_image:type_name -> SoftwareImage + 9, // 12: GetBootstrapDataResponse.BootstrapDataResponse.boot_config:type_name -> BootConfig + 8, // 13: GetBootstrapDataResponse.BootstrapDataResponse.credentials:type_name -> Credentials + 18, // 14: GetBootstrapDataResponse.BootstrapDataResponse.pathz:type_name -> gnsi.pathz.v1.UploadRequest + 19, // 15: GetBootstrapDataResponse.BootstrapDataResponse.authz:type_name -> gnsi.authz.v1.UploadRequest + 20, // 16: GetBootstrapDataResponse.BootstrapDataResponse.certificates:type_name -> gnsi.certz.v1.UploadRequest + 12, // 17: GetBootstrapDataResponse.BootstrapDataSigned.responses:type_name -> GetBootstrapDataResponse.BootstrapDataResponse + 2, // 18: Bootstrap.GetBootstrapData:input_type -> GetBootstrapDataRequest + 10, // 19: Bootstrap.ReportStatus:input_type -> ReportStatusRequest + 6, // 20: Bootstrap.GetBootstrapData:output_type -> GetBootstrapDataResponse + 11, // 21: Bootstrap.ReportStatus:output_type -> EmptyResponse + 20, // [20:22] is the sub-list for method output_type + 18, // [18:20] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name +} + +func init() { file_github_com_openconfig_bootz_proto_bootz_proto_init() } +func file_github_com_openconfig_bootz_proto_bootz_proto_init() { + if File_github_com_openconfig_bootz_proto_bootz_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBootstrapDataRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChassisDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ControlCard); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ControlCardState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBootstrapDataResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SoftwareImage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Credentials); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BootConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportStatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmptyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBootstrapDataResponse_BootstrapDataResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBootstrapDataResponse_BootstrapDataSigned); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_github_com_openconfig_bootz_proto_bootz_proto_rawDesc, + NumEnums: 2, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_github_com_openconfig_bootz_proto_bootz_proto_goTypes, + DependencyIndexes: file_github_com_openconfig_bootz_proto_bootz_proto_depIdxs, + EnumInfos: file_github_com_openconfig_bootz_proto_bootz_proto_enumTypes, + MessageInfos: file_github_com_openconfig_bootz_proto_bootz_proto_msgTypes, + }.Build() + File_github_com_openconfig_bootz_proto_bootz_proto = out.File + file_github_com_openconfig_bootz_proto_bootz_proto_rawDesc = nil + file_github_com_openconfig_bootz_proto_bootz_proto_goTypes = nil + file_github_com_openconfig_bootz_proto_bootz_proto_depIdxs = nil +} diff --git a/proto/bootz/bootz_grpc.pb.go b/proto/bootz/bootz_grpc.pb.go new file mode 100755 index 0000000..33dbeb6 --- /dev/null +++ b/proto/bootz/bootz_grpc.pb.go @@ -0,0 +1,141 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.10 +// source: github.com/openconfig/bootz/proto/bootz.proto + +package bootz + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// BootstrapClient is the client API for Bootstrap service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type BootstrapClient interface { + GetBootstrapData(ctx context.Context, in *GetBootstrapDataRequest, opts ...grpc.CallOption) (*GetBootstrapDataResponse, error) + ReportStatus(ctx context.Context, in *ReportStatusRequest, opts ...grpc.CallOption) (*EmptyResponse, error) +} + +type bootstrapClient struct { + cc grpc.ClientConnInterface +} + +func NewBootstrapClient(cc grpc.ClientConnInterface) BootstrapClient { + return &bootstrapClient{cc} +} + +func (c *bootstrapClient) GetBootstrapData(ctx context.Context, in *GetBootstrapDataRequest, opts ...grpc.CallOption) (*GetBootstrapDataResponse, error) { + out := new(GetBootstrapDataResponse) + err := c.cc.Invoke(ctx, "/Bootstrap/GetBootstrapData", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *bootstrapClient) ReportStatus(ctx context.Context, in *ReportStatusRequest, opts ...grpc.CallOption) (*EmptyResponse, error) { + out := new(EmptyResponse) + err := c.cc.Invoke(ctx, "/Bootstrap/ReportStatus", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// BootstrapServer is the server API for Bootstrap service. +// All implementations must embed UnimplementedBootstrapServer +// for forward compatibility +type BootstrapServer interface { + GetBootstrapData(context.Context, *GetBootstrapDataRequest) (*GetBootstrapDataResponse, error) + ReportStatus(context.Context, *ReportStatusRequest) (*EmptyResponse, error) + mustEmbedUnimplementedBootstrapServer() +} + +// UnimplementedBootstrapServer must be embedded to have forward compatible implementations. +type UnimplementedBootstrapServer struct { +} + +func (UnimplementedBootstrapServer) GetBootstrapData(context.Context, *GetBootstrapDataRequest) (*GetBootstrapDataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBootstrapData not implemented") +} +func (UnimplementedBootstrapServer) ReportStatus(context.Context, *ReportStatusRequest) (*EmptyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ReportStatus not implemented") +} +func (UnimplementedBootstrapServer) mustEmbedUnimplementedBootstrapServer() {} + +// UnsafeBootstrapServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to BootstrapServer will +// result in compilation errors. +type UnsafeBootstrapServer interface { + mustEmbedUnimplementedBootstrapServer() +} + +func RegisterBootstrapServer(s grpc.ServiceRegistrar, srv BootstrapServer) { + s.RegisterService(&Bootstrap_ServiceDesc, srv) +} + +func _Bootstrap_GetBootstrapData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBootstrapDataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BootstrapServer).GetBootstrapData(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/Bootstrap/GetBootstrapData", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BootstrapServer).GetBootstrapData(ctx, req.(*GetBootstrapDataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Bootstrap_ReportStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReportStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BootstrapServer).ReportStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/Bootstrap/ReportStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BootstrapServer).ReportStatus(ctx, req.(*ReportStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Bootstrap_ServiceDesc is the grpc.ServiceDesc for Bootstrap service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Bootstrap_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Bootstrap", + HandlerType: (*BootstrapServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetBootstrapData", + Handler: _Bootstrap_GetBootstrapData_Handler, + }, + { + MethodName: "ReportStatus", + Handler: _Bootstrap_ReportStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "github.com/openconfig/bootz/proto/bootz.proto", +} diff --git a/regenerate-files.sh b/regenerate-files.sh new file mode 100755 index 0000000..b84a2d2 --- /dev/null +++ b/regenerate-files.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -euo pipefail + +BASE=$(bazel info bazel-genfiles) +BOOTZ_NS='github.com/openconfig/bootz/proto' + +copy_generated() { + pkg="$1" + # Default to using package name for proto if $2 is unset + proto="$1" && [ "${2++}" ] && proto="$2" + # Bazel go_rules will create empty files containing "// +build ignore\n\npackage ignore" + # in the case where the protoc compiler doesn't generate any output. See: + # https://github.com/bazelbuild/rules_go/blob/03a8b8e90eebe699d7/go/tools/builders/protoc.go#L190 + for file in "${BASE}"/proto/"${proto}"_go_proto_/"${BOOTZ_NS}"/"${pkg}"/*.pb.go; do + [[ $(head -n 1 "${file}") == "// +build ignore" ]] || cp -f "${file}" "proto/${pkg}/" + done +} + +bazel build //proto:all +copy_generated "bootz"