Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions server/proto/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")

package(default_visibility = ["//visibility:public"])

proto_library(
name = "config_proto",
srcs = ["config.proto"],
import_prefix = "github.com/openconfig/bootz",
deps = [
"//proto:bootz_proto",
"@openconfig_attestz//proto:tpm_enrollz_proto",
"@openconfig_gnsi//authz:authz_proto",
"@openconfig_gnsi//pathz:pathz_proto",
],
)

##############################################################################
# Go
##############################################################################

go_proto_library(
name = "config_go_proto",
importpath = "github.com/openconfig/bootz/server/proto/config",
proto = ":config_proto",
deps = [
"//proto:bootz",
"@openconfig_attestz//proto:tpm_enrollz_go",
"@openconfig_gnsi//authz",
"@openconfig_gnsi//pathz",
],
)

go_library(
name = "config",
embed = [":config_go_proto"],
importpath = "github.com/openconfig/bootz/server/proto/config",
)
87 changes: 87 additions & 0 deletions server/proto/config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package config;
Comment thread
Chounoki marked this conversation as resolved.

import "github.com/openconfig/attestz/proto/tpm_enrollz.proto";
import "github.com/openconfig/bootz/proto/bootz.proto";
import "github.com/openconfig/gnsi/authz/authz.proto";
import "github.com/openconfig/gnsi/pathz/pathz.proto";

option go_package = "github.com/openconfig/bootz/server/proto/config";

// A binding configuration for Bootz server.
message Config {
// Bootz server address (IP:port).
string server_address = 1;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will we know the server address of the Bootz server ahead of time? Some runtime environments (e.g. Google's) don't let you reserve a specific IP when bringing up SUT components. We will need another way to learn about the Bootz server address.

Copy link
Copy Markdown
Contributor Author

@Chounoki Chounoki May 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is my understanding:

With Monax, each SUT will run in a container, which by default is assigned to a private network by Docker runtime. This private network is bridged (NAT'ed) by the host machine. (I.e. the host machine acts as the gateway of the SUT's private network).

https://docs.docker.com/engine/network/

This private network address doesn't really matter, because any external switch will only see the real IP address of the host machine on which the containers run. In other words, the host machine does port mapping from container private network to host public network.

The DHCP entries must use the real host IP address as Bootz server address. Similarly the image URI created by Bootz must also use the real host IP address, because to any external switches, only the real IP address of the host machine is visible (All IP addresses inside the private network of the containners are not visible externally).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Monax isn't necessarily going to run on Docker containers. Some vendors may run these SUT components on bare-metal machines, and as I said above, it definitely wouldn't work in Borg. This is why we should find a solution that can be applied to any runtime/deployment environment.

Copy link
Copy Markdown
Contributor Author

@Chounoki Chounoki May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the vendors are going to directly run the Monax test we provide to them, then each SUT will be inside a container just like the math example provided by Monax, you can see each SUT has its own Dockerfile and kubernetes.txtpb file.

If the vendors don't plan to run the Monax, but to use each service on bare machine without Monax, then they already know the IP of the machine which can be manually written into the textproto of this file by the vendors, and then Bootz server will be initialized from this textproto.

In either case, personally I think it is better and safer to ask the vendors to manually fill in the IP address of the machine on which they plan to run the test (regardless of Bootz server inside a container or not), since the machine can have multiple network interfaces and multiple IP addresses.

While Bootz calls net.Listen() function without specifying an IP, it will create a listener on each of those network interfaces and their IP addresses (https://pkg.go.dev/net#Listen), which means if we try to retrieve a single server IP address dynamically from Bootz runtime, we would get multiple IP addresses instead, and it would be a mess because we can only put one single Bootz IP into DHCP.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my main point still stands: How will we run this Monax test on Borg if you have to know the IP address ahead of time? We need to think about all future cases, not just the immediate ones.

Monax at its core is a SUT manager. It's purpose is to automatically bring up, manage and provide access to SUT components without having to know the implementation/addressing details about them. It is responsible for figuring out the IP addresses of the SUT components it brings up, and then initiating the gRPC/HTTP/whatever connections to them. By introducing external fields that override this, you are potentially breaking that binding.

Regarding net.Listen() listening on all available IP addresses, I don't see that as a huge problem. Sure, the server will need to pick one address to provide in the DHCP lease but the beauty of Monax is that each vendor can customize that logic as much as they want. This is why I've put in a GetBootzURL() RPC to the Bootz controller: Each test implementation has full control over how the Bootz server determines what its correct address is.

// Bootz server trust anchor cert key pair.
CertKeyPair trust_anchor = 2;
// Owner certificate key pair.
CertKeyPair owner_certificate = 3;
// Based64 encoding of ASN.1 DER vendor CA certificates.
repeated string vendor_ca_certs = 4;
// Chassis owned by the organization.
repeated Chassis chassis = 5;
}

message CertKeyPair {
// Base64 encoding of ASN.1 DER certificate.
string cert = 1;
// Base64 encoding of PKCS#8 DER private key.
string key = 2;
Comment thread
Chounoki marked this conversation as resolved.
}

message Chassis {
// Chassis manufacturer.
string manufacturer = 1;
// For fixed form factor chassis, populate only 1 control card to represent
// the chassis itself. For modular form factor chassis, populate 2 control
// cards.
repeated ControlCard control_cards = 2;
// The intended hostname of the chassis.
string hostname = 3;
// Boot mode defines the boot mode that can be secure or insecure.
bootz.BootMode boot_mode = 4;
// Whether Streaming Bootz is supported or not.
bool streaming_supported = 5;
// Software image to be loaded on the chassis.
bootz.SoftwareImage intended_image = 6;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Bootz SoftwareImage contains a download URL. How will we know that URL ahead of time? This URL should be generated by the ImageService SUT dynamically.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the image URI must also use the real IP address of the host machine, which is known by the user doing the test beforehand.

In the worst case, Bootz can still override this IP if required (i.e. we can provide a function for Monax to call).

// Bootloader password.
string boot_password_hash = 7;
// Boot config to be loaded on the chassis.
bootz.BootConfig boot_config = 8;
// Credentials.
bootz.Credentials credentials = 9;
// Pathz.
gnsi.pathz.v1.UploadRequest pathz = 10;
// Authz.
gnsi.authz.v1.UploadRequest authz = 11;
// Certz profiles.
bootz.CertzProfiles certz_profiles = 12;
}

message ControlCard {
// Serial number of the control card.
string serial_number = 1;
// Base64 encoding of ownership voucher.
string ownership_voucher = 2;
// Base64 encoding of PKIX DER EK/PPK public key.
// This field is not populated for control cards having IDevID.
string public_key = 3;
Comment thread
Chounoki marked this conversation as resolved.
// Public key type: EK or PPK.
// This field is not populated for control cards having IDevID.
openconfig.attestz.Key public_key_type = 4;
}
Loading
Loading