From e9ad71518bdf545a00402da696de213477ff895f Mon Sep 17 00:00:00 2001 From: Stanley Liu Date: Thu, 2 Jul 2026 17:30:32 -0400 Subject: [PATCH 1/3] =?UTF-8?q?Add=20Message=20Attestation=20prototype=20?= =?UTF-8?q?=E2=80=94=20Client=20+=20Server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the Message Attestation feature from opamp-spec PR #333. Every ServerToAgent is wrapped in a SignedServerToAgent envelope carrying a detached X.509 signature. Agents that opt in can verify that responses originate from an authorised distribution server and have not been tampered with in transit. The feature is fully opt-in and backward-compatible: agents and servers that do not configure attestation continue to use the existing wire format unchanged. New signing/ package — pluggable interfaces (Signer, Verifier, TrustAnchorProvider, TOFUStore) with in-process and remote-delegation implementations. RemoteSigner supports out-of-process policy servers as recommended in supplementary-guidelines.md. Server: Settings.PayloadSigner enables signing. The server auto-advertises OffersPayloadTrustVerification and wraps outbound messages after capability negotiation with the agent. Client: StartSettings.PayloadVerifier / PayloadTOFUStore enable verification. Chain validation (RFC 5280), SAN check, and per-message signature verification are enforced by attestationState. TOFU enrollment bootstraps the verifier from the first TrustChainResponse and persists it via TOFUStore. --- client/httpclient.go | 2 + client/internal/attestation.go | 268 +++ client/internal/clientcommon.go | 47 + client/internal/httpsender.go | 169 +- client/internal/wsreceiver.go | 69 +- client/types/startsettings.go | 39 + client/wsclient.go | 41 +- internal/wsmessage.go | 34 +- protobufs/anyvalue.pb.go | 256 ++- protobufs/opamp.pb.go | 2807 ++++++++++++------------------- server/attestation.go | 126 ++ server/server.go | 15 + server/serverimpl.go | 73 +- server/wsconnection.go | 84 +- signing/algorithm.go | 187 ++ signing/certs.go | 187 ++ signing/chain.go | 92 + signing/doc.go | 30 + signing/loader.go | 147 ++ signing/local_signer.go | 130 ++ signing/local_verifier.go | 67 + signing/remote_signer.go | 138 ++ signing/tofu.go | 76 + signing/types.go | 116 ++ 24 files changed, 3186 insertions(+), 2014 deletions(-) create mode 100644 client/internal/attestation.go create mode 100644 server/attestation.go create mode 100644 signing/algorithm.go create mode 100644 signing/certs.go create mode 100644 signing/chain.go create mode 100644 signing/doc.go create mode 100644 signing/loader.go create mode 100644 signing/local_signer.go create mode 100644 signing/local_verifier.go create mode 100644 signing/remote_signer.go create mode 100644 signing/tofu.go create mode 100644 signing/types.go diff --git a/client/httpclient.go b/client/httpclient.go index aff87319..62dffc6f 100644 --- a/client/httpclient.go +++ b/client/httpclient.go @@ -163,6 +163,8 @@ func (c *httpClient) runUntilStopped(ctx context.Context) { c.common.PackagesStateProvider, &c.common.PackageSyncMutex, c.common.DownloadReporterInterval, + c.common.PayloadVerifier, + c.common.PayloadTOFUStore, ) } diff --git a/client/internal/attestation.go b/client/internal/attestation.go new file mode 100644 index 00000000..52986998 --- /dev/null +++ b/client/internal/attestation.go @@ -0,0 +1,268 @@ +package internal + +import ( + "context" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "sync" + "time" + + "google.golang.org/protobuf/proto" + + "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" +) + +// Sentinel errors returned by attestationState. Callers can use +// errors.Is to distinguish failure modes when terminating the +// connection. +var ( + // ErrMissingTrustChain is returned when the first + // SignedServerToAgent received on a connection does not carry a + // trust_chain_response field. Per the spec this is a fatal + // handshake error. + ErrMissingTrustChain = errors.New("client: first SignedServerToAgent missing trust_chain_response") + + // ErrTrustChainErrorReported is returned when the Server populates + // trust_chain_response.error_message, signalling that it cannot + // satisfy the handshake. + ErrTrustChainErrorReported = errors.New("client: server reported trust chain error") + + // ErrSANMismatch is returned when the leaf certificate's Subject + // Alternative Name entries do not contain a dNSName or iPAddress + // that matches the OpAMP server the Agent is connected to. Per the + // spec this is a fatal handshake error. + ErrSANMismatch = errors.New("client: leaf certificate SAN does not match server hostname") + + // ErrTOFUAnchorMissing is returned during TOFU enrollment when the + // Server's TrustChainResponse does not include the expected + // tofu_trust_anchor field. + ErrTOFUAnchorMissing = errors.New("client: TOFU enrollment requested but TrustChainResponse.tofu_trust_anchor is absent") + + // ErrMissingSignature is returned when a SignedServerToAgent is + // missing its signature field. Every message MUST be signed, + // including the first. + ErrMissingSignature = errors.New("client: SignedServerToAgent missing signature") + + // ErrMissingPayload is returned when SignedServerToAgent.payload + // is empty. The payload carries the inner ServerToAgent; an empty + // payload would unmarshal into an empty ServerToAgent and is + // rejected eagerly. + ErrMissingPayload = errors.New("client: SignedServerToAgent missing payload") + + // ErrEmptyInnerServerToAgent is returned when the inner payload + // decodes to a ServerToAgent with all default values. Defends + // against the proto3 field-1 wire-type collision: a malicious + // server that downgrades by responding with a plain ServerToAgent + // has its InstanceUid bytes misinterpreted as + // SignedServerToAgent.payload; the inner decode of those random + // UUID bytes either errors or produces a default-valued message. + // Legitimate server responses always carry at least InstanceUid + // because handleWSConnection auto-fills it (see + // server/serverimpl.go). + ErrEmptyInnerServerToAgent = errors.New("client: inner ServerToAgent decoded to all default values; likely downgrade attempt") +) + +// attestationState holds per-connection state for payload trust +// verification on the Agent (client) side. Construct one per OpAMP +// connection via newAttestationState and call ProcessEnvelope on each +// inbound SignedServerToAgent. +// +// When Verifier is nil (the operator did not opt in), the OpAMP wire +// format is byte-identical to upstream and no attestationState is +// created at all; payload trust is simply not negotiated. +type attestationState struct { + verifier signing.Verifier + serverName string // hostname for SAN verification + tofuStore signing.TOFUStore // non-nil when in TOFU enrollment mode + + mu sync.Mutex + firstSeen bool + leaf *x509.Certificate +} + +// newAttestationState constructs a per-connection attestation state. +// verifier is nil in TOFU enrollment mode (tofuStore non-nil); in that case +// the verifier is bootstrapped from the first TrustChainResponse. +// serverName is the hostname (without port) of the OpAMP server. +func newAttestationState(verifier signing.Verifier, serverName string, tofuStore signing.TOFUStore) *attestationState { + return &attestationState{verifier: verifier, serverName: serverName, tofuStore: tofuStore} +} + +// Reset clears the per-connection handshake state. After Reset, the +// next call to ProcessEnvelope is treated as if it were the first +// message on the connection — requiring trust_chain_response and +// performing a fresh chain validation. +// +// Used by transports that lack a persistent connection (the HTTP +// polling transport) to recover from server-side key rotation or +// other mid-stream handshake faults. WebSocket callers do not need +// to call Reset because a failure terminates the connection and the +// next reconnect attempt constructs a new attestationState. +func (s *attestationState) Reset() { + s.mu.Lock() + defer s.mu.Unlock() + s.firstSeen = false + s.leaf = nil +} + +// isAttestationFailure reports whether err originated from a payload +// trust verification problem (envelope malformed, chain validation +// failed, signature missing or invalid, etc.). Used by the WebSocket +// receive loop to distinguish attestation failures — which require +// explicit connection termination per the spec — from generic +// transport-level errors. +func isAttestationFailure(err error) bool { + if err == nil { + return false + } + return errors.Is(err, ErrMissingTrustChain) || + errors.Is(err, ErrTrustChainErrorReported) || + errors.Is(err, ErrSANMismatch) || + errors.Is(err, ErrTOFUAnchorMissing) || + errors.Is(err, ErrMissingSignature) || + errors.Is(err, ErrMissingPayload) || + errors.Is(err, ErrEmptyInnerServerToAgent) || + errors.Is(err, signing.ErrChainValidation) || + errors.Is(err, signing.ErrSignatureMismatch) || + errors.Is(err, signing.ErrEmptyChain) || + errors.Is(err, signing.ErrParseCertificate) || + errors.Is(err, signing.ErrUnsupportedAlgorithm) +} + +// ProcessEnvelope handles an incoming SignedServerToAgent received on +// this connection. On the first call, the envelope's certificate +// chain is validated against the verifier's pre-configured trust +// anchor pool and the resulting leaf is cached on the state. On +// subsequent calls, the envelope's signature is verified against the +// cached leaf. +// +// On success it returns the inner ServerToAgent payload bytes, which +// the caller unmarshals into a *protobufs.ServerToAgent for normal +// dispatch. +// +// On any failure — missing trust chain, chain validation failure, +// missing/invalid signature — it returns a non-nil error. Per the +// spec the caller MUST then terminate the OpAMP connection. +func (s *attestationState) ProcessEnvelope(ctx context.Context, envelope *protobufs.SignedServerToAgent) ([]byte, error) { + if envelope == nil { + return nil, errors.New("client: nil SignedServerToAgent envelope") + } + if len(envelope.Payload) == 0 { + return nil, ErrMissingPayload + } + + s.mu.Lock() + defer s.mu.Unlock() + + if !s.firstSeen { + chainResp := envelope.TrustChainResponse + if chainResp == nil { + return nil, ErrMissingTrustChain + } + if chainResp.ErrorMessage != "" { + return nil, fmt.Errorf("%w: %s", ErrTrustChainErrorReported, chainResp.ErrorMessage) + } + chainDER, err := parsePEMChain(chainResp.CertificateChain) + if err != nil { + return nil, fmt.Errorf("client: parse trust chain PEM: %w", err) + } + + // TOFU enrollment: bootstrap the verifier from the root CA the + // Server included in tofu_trust_anchor, then persist it. + if s.tofuStore != nil { + if len(chainResp.TofuTrustAnchor) == 0 { + return nil, ErrTOFUAnchorMissing + } + v, err := signing.VerifierFromPEM(chainResp.TofuTrustAnchor) + if err != nil { + return nil, fmt.Errorf("client: TOFU: parse trust anchor: %w", err) + } + if err := s.tofuStore.Save(chainResp.TofuTrustAnchor); err != nil { + return nil, fmt.Errorf("client: TOFU: persist trust anchor: %w", err) + } + s.verifier = v + s.tofuStore = nil // enrolled; store no longer needed this session + } + + leaf, err := s.verifier.ValidateChain(ctx, chainDER, time.Now()) + if err != nil { + return nil, fmt.Errorf("client: validate trust chain: %w", err) + } + if s.serverName != "" { + if err := leaf.VerifyHostname(s.serverName); err != nil { + return nil, fmt.Errorf("%w: %v", ErrSANMismatch, err) + } + } + s.leaf = leaf + s.firstSeen = true + } + + // Every message — including the first — MUST carry a signature. + if len(envelope.Signature) == 0 { + return nil, ErrMissingSignature + } + if err := s.verifier.Verify(ctx, envelope.Payload, envelope.Signature, s.leaf); err != nil { + return nil, fmt.Errorf("client: verify signature: %w", err) + } + return envelope.Payload, nil +} + +// parsePEMChain decodes a concatenated PEM blob into individual DER byte +// slices ordered intermediates-first, leaf-last — the form expected by +// signing.Verifier.ValidateChain. +func parsePEMChain(pemBytes []byte) ([][]byte, error) { + var chain [][]byte + rest := pemBytes + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + continue + } + chain = append(chain, block.Bytes) + } + if len(chain) == 0 { + return nil, errors.New("no CERTIFICATE blocks found in PEM") + } + return chain, nil +} + +// unwrapServerToAgent is a convenience that combines ProcessEnvelope +// with proto.Unmarshal of the resulting payload bytes into msg. If +// state is nil, the input bytes are unmarshalled directly as a +// ServerToAgent (the standard non-attestation path). +// +// rawProto is the protobuf bytes after any transport-level framing +// has been stripped (for WebSocket, after the wsMsgHeader varint). +func unwrapServerToAgent(ctx context.Context, state *attestationState, rawProto []byte, msg *protobufs.ServerToAgent) error { + if state == nil { + return proto.Unmarshal(rawProto, msg) + } + var envelope protobufs.SignedServerToAgent + if err := proto.Unmarshal(rawProto, &envelope); err != nil { + return fmt.Errorf("client: decode SignedServerToAgent envelope: %w", err) + } + payload, err := state.ProcessEnvelope(ctx, &envelope) + if err != nil { + return err + } + if err := proto.Unmarshal(payload, msg); err != nil { + return fmt.Errorf("client: decode inner ServerToAgent: %w", err) + } + // Defense in depth against proto3 field-1 wire-type collision. + // ProcessEnvelope's chain/signature checks already terminate the + // connection on the downgrade path that produces this state, but + // this check pins the contract: every legitimate ServerToAgent + // the agent processes has at least one non-default field + // (typically InstanceUid). + if proto.Equal(msg, &protobufs.ServerToAgent{}) { + return ErrEmptyInnerServerToAgent + } + return nil +} diff --git a/client/internal/clientcommon.go b/client/internal/clientcommon.go index 50afa587..7105e15c 100644 --- a/client/internal/clientcommon.go +++ b/client/internal/clientcommon.go @@ -11,6 +11,7 @@ import ( "github.com/open-telemetry/opamp-go/client/types" "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" ) var ( @@ -24,6 +25,9 @@ var ( ErrAcceptsPackagesNotSet = errors.New("AcceptsPackages and ReportsPackageStatuses must be set") ErrAvailableComponentsMissing = errors.New("AvailableComponents is nil") ErrReportsConnectionSettingsStatusNotSet = errors.New("ReportsConnectionSettingsStatus capability is not set") + ErrPayloadVerifierMissing = errors.New("PayloadVerifier must be set when RequiresPayloadTrustVerification capability is enabled") + ErrPayloadVerifierWithoutCapability = errors.New("PayloadVerifier set but RequiresPayloadTrustVerification capability is not enabled") + ErrTOFULoadFailed = errors.New("PayloadTOFUStore.Load failed at startup") errAlreadyStarted = errors.New("already started") errCannotStopNotStarted = errors.New("cannot stop because not started") @@ -46,6 +50,21 @@ type ClientCommon struct { // PackageSyncMutex makes sure only one package syncing operation happens at a time. PackageSyncMutex sync.Mutex + // PayloadVerifier validates the trust chain delivered in + // SignedServerToAgent.trust_chain_response on the first message of + // a connection, and verifies the per-message signature on every + // subsequent ServerToAgent. nil when the Agent has not opted in to + // payload trust verification (the standard OpAMP wire path stays + // active). MUST be non-nil when + // AgentCapabilities_RequiresPayloadTrustVerification is in the + // declared capability set. + PayloadVerifier signing.Verifier + + // PayloadTOFUStore, when non-nil, backs TOFU enrollment. Set from + // StartSettings.PayloadTOFUStore. Nil after the trust anchor has been + // loaded from the store and promoted to PayloadVerifier. + PayloadTOFUStore signing.TOFUStore + // The transport-specific sender. sender Sender @@ -94,6 +113,13 @@ func (c *ClientCommon) validateCapabilities(capabilities protobufs.AgentCapabili return ErrPackagesStateProviderNotSet } } + requiresAttestation := capabilities&protobufs.AgentCapabilities_AgentCapabilities_RequiresPayloadTrustVerification != 0 + switch { + case requiresAttestation && c.PayloadVerifier == nil && c.PayloadTOFUStore == nil: + return ErrPayloadVerifierMissing + case !requiresAttestation && c.PayloadVerifier != nil: + return ErrPayloadVerifierWithoutCapability + } return nil } @@ -132,6 +158,27 @@ func (c *ClientCommon) PrepareStart( // Prepare package statuses. c.PackagesStateProvider = settings.PackagesStateProvider + // Wire up payload trust verification. PayloadVerifier takes precedence; + // if only PayloadTOFUStore is set, try to load a previously-persisted + // anchor. If found, promote it to PayloadVerifier (normal path). If + // not found, keep PayloadTOFUStore set so the transport-level code + // enters TOFU enrollment mode on connection. + c.PayloadVerifier = settings.PayloadVerifier + if c.PayloadVerifier == nil && settings.PayloadTOFUStore != nil { + anchorPEM, err := settings.PayloadTOFUStore.Load() + if err != nil { + return fmt.Errorf("%w: %v", ErrTOFULoadFailed, err) + } + if len(anchorPEM) > 0 { + v, err := signing.VerifierFromPEM(anchorPEM) + if err != nil { + return fmt.Errorf("%w: persisted anchor is invalid: %v", ErrTOFULoadFailed, err) + } + c.PayloadVerifier = v + } else { + c.PayloadTOFUStore = settings.PayloadTOFUStore + } + } if err := c.validateCapabilities(c.ClientSyncedState.Capabilities()); err != nil { return err } diff --git a/client/internal/httpsender.go b/client/internal/httpsender.go index 715d1fbc..cc25a388 100644 --- a/client/internal/httpsender.go +++ b/client/internal/httpsender.go @@ -21,6 +21,7 @@ import ( "github.com/open-telemetry/opamp-go/client/types" "github.com/open-telemetry/opamp-go/internal" "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" ) const ( @@ -70,6 +71,12 @@ type HTTPSender struct { // Processor to handle received messages. receiveProcessor receivedProcessor + + // attestation, when non-nil, decodes inbound responses as + // SignedServerToAgent envelopes — validates the trust chain on the + // first response and verifies the signature on every subsequent + // one. Set by Run when the StartSettings supplied a PayloadVerifier. + attestation *attestationState } // NewHTTPSender creates a new Sender that uses HTTP to send messages @@ -92,6 +99,12 @@ func (h *HTTPSender) SetHTTPClient(client *http.Client) { h.client = client } +// SetMaxMessageSize sets the maximum message size in bytes. Messages +// larger than this limit are rejected before sending. +func (h *HTTPSender) SetMaxMessageSize(maxMessageSize int64) { + h.maxMessageSize = internal.ResolveMaxMessageSize(maxMessageSize) +} + // SetProxy will force each request to use passed proxy and use the passed headers when making a CONNECT request to the proxy. // If the proxy has no schema http is used. // This method is not thread safe and must be called before h.client is used. @@ -129,16 +142,25 @@ func (h *HTTPSender) SetProxy(proxy string, headers http.Header) error { // Run continues until ctx is cancelled. func (h *HTTPSender) Run( ctx context.Context, - url string, + serverURL string, callbacks types.Callbacks, clientSyncedState *ClientSyncedState, packagesStateProvider types.PackagesStateProvider, packageSyncMutex *sync.Mutex, reporterInterval time.Duration, + payloadVerifier signing.Verifier, + tofuStore signing.TOFUStore, ) { - h.url = url + h.url = serverURL h.callbacks = callbacks h.receiveProcessor = newReceivedProcessor(h.logger, callbacks, h, clientSyncedState, packagesStateProvider, packageSyncMutex, reporterInterval) + if payloadVerifier != nil || tofuStore != nil { + var serverName string + if parsed, err := url.Parse(h.url); err == nil { + serverName = parsed.Hostname() + } + h.attestation = newAttestationState(payloadVerifier, serverName, tofuStore) + } // we need to detect if the redirect was ever set, if not, we want default behaviour if callbacks.CheckRedirect != nil { @@ -148,13 +170,36 @@ func (h *HTTPSender) Run( } } + // attestBackoff mirrors the pattern used by the WebSocket client's + // runUntilStopped: attestation failures at the application level + // are distinct from transport errors (the TCP connection is fine, + // the server just failed verification). Without a separate backoff + // the agent would retry at the full polling rate — up to 1 req/s + // for aggressive heartbeat intervals — against a potentially + // compromised server. Exponential backoff with no max elapsed time + // matches the WS client's behaviour. + attestBackoff := backoff.NewExponentialBackOff() + attestBackoff.MaxElapsedTime = 0 + for { pollingTimer := time.NewTimer(time.Millisecond * time.Duration(h.pollingIntervalMs.Load())) select { case <-h.hasPendingMessage: // Have something to send. Stop the polling timer and send what we have. pollingTimer.Stop() - h.makeOneRequestRoundtrip(ctx) + if attestationFailed := h.makeOneRequestRoundtrip(ctx); attestationFailed { + interval := attestBackoff.NextBackOff() + h.logger.Errorf(ctx, "Payload trust verification failed, will retry in %v.", interval) + timer := time.NewTimer(interval) + select { + case <-timer.C: + case <-ctx.Done(): + timer.Stop() + return + } + } else { + attestBackoff.Reset() + } case <-pollingTimer.C: // Polling interval has passed. Force a status update. @@ -195,18 +240,19 @@ func (h *HTTPSender) SetRequestHeader(baseHeaders http.Header, headerFunc func(h // makeOneRequestRoundtrip sends a request and receives a response. // It will retry the request if the server responds with too many -// requests or unavailable status. -func (h *HTTPSender) makeOneRequestRoundtrip(ctx context.Context) { +// requests or unavailable status. It returns true if the response +// failed attestation verification so the caller can apply backoff. +func (h *HTTPSender) makeOneRequestRoundtrip(ctx context.Context) bool { resp, err := h.sendRequestWithRetries(ctx) if err != nil { h.logger.Errorf(ctx, "%v", err) - return + return false } if resp == nil { // No request was sent and nothing to receive. - return + return false } - h.receiveResponse(ctx, resp) + return h.receiveResponse(ctx, resp) } // requestResult represents the outcome of a single HTTP request attempt. @@ -378,62 +424,75 @@ func (h *HTTPSender) prepareRequest(ctx context.Context) (*requestWrapper, error return &req, nil } -func (h *HTTPSender) responseBodyReader(resp *http.Response) (io.Reader, func(), error) { - closeBody := func() { - _ = resp.Body.Close() - } - if resp.Header.Get(headerContentEncoding) != encodingTypeGZip { - return resp.Body, closeBody, nil - } - - gzipReader, err := gzip.NewReader(resp.Body) +// receiveResponse decodes and processes a server response. It returns +// true when the response failed payload trust verification so the +// caller can apply attestation-specific backoff before retrying. +func (h *HTTPSender) receiveResponse(ctx context.Context, resp *http.Response) bool { + msgBytes, err := h.readResponseBody(resp) if err != nil { - closeBody() - return nil, func() {}, err + h.logger.Errorf(ctx, "cannot read response body: %v", err) + return false } - return gzipReader, func() { - _ = gzipReader.Close() - _ = resp.Body.Close() - }, nil -} -func (h *HTTPSender) readResponseBody(resp *http.Response) ([]byte, error) { - body, closeBody, err := h.responseBodyReader(resp) - if err != nil { - return nil, err + var response protobufs.ServerToAgent + if err := unwrapServerToAgent(ctx, h.attestation, msgBytes, &response); err != nil { + // When payload trust verification is enabled, a failure here + // means the response cannot be trusted; the spec says the + // connection MUST be terminated. For HTTP polling the agent + // has no persistent connection to drop, so we skip processing + // this response and Reset the per-connection attestation + // state. The next poll will re-attempt the trust-chain + // handshake, allowing the Agent to recover from mid-stream + // faults such as server-side key rotation. Without the Reset, + // the cached firstSeen flag would keep us in the "verify + // signature" branch and the Agent could be stuck rejecting + // every subsequent response. + // + // Use the same sentinel string the WebSocket receive path + // emits ("Payload trust verification failed") so operators + // can grep for one canonical phrase across both transports. + if h.attestation != nil && isAttestationFailure(err) { + h.logger.Errorf(ctx, "Payload trust verification failed; resetting attestation state: %v", err) + h.attestation.Reset() + return true + } + h.logger.Errorf(ctx, "cannot unmarshal response: %v", err) + return false } - defer closeBody() - // Do not drain oversized responses after the limit is hit. Reading to EOF - // would preserve HTTP/1 keep-alive, but would also let a peer force - // unbounded network and decompression work after MaxMessageSize is exceeded. - return internal.ReadAllLimited(body, h.maxMessageSize, "response body") + h.receiveProcessor.ProcessReceivedMessage(ctx, &response) + return false } -func (h *HTTPSender) discardResponseBody(resp *http.Response) error { - body, closeBody, err := h.responseBodyReader(resp) - if err != nil { - return err +// readResponseBody reads the response body, decompressing gzip if indicated +// by Content-Encoding, and enforces maxMessageSize. +func (h *HTTPSender) readResponseBody(resp *http.Response) ([]byte, error) { + defer resp.Body.Close() + if resp.Header.Get(headerContentEncoding) == encodingTypeGZip { + gr, err := gzip.NewReader(resp.Body) + if err != nil { + return nil, err + } + defer gr.Close() + return internal.ReadAllLimited(gr, h.maxMessageSize, "response body") } - defer closeBody() - - return internal.CopyDiscardLimited(body, h.maxMessageSize, "response body") + return internal.ReadAllLimited(resp.Body, h.maxMessageSize, "response body") } -func (h *HTTPSender) receiveResponse(ctx context.Context, resp *http.Response) { - msgBytes, err := h.readResponseBody(resp) - if err != nil { - h.logger.Errorf(ctx, "cannot read response body: %v", err) - return - } - - var response protobufs.ServerToAgent - if err := proto.Unmarshal(msgBytes, &response); err != nil { - h.logger.Errorf(ctx, "cannot unmarshal response: %v", err) - return +// discardResponseBody drains and closes the response body, decompressing +// gzip if indicated by Content-Encoding and enforcing maxMessageSize. This +// allows the underlying TCP connection to be reused for subsequent requests. +func (h *HTTPSender) discardResponseBody(resp *http.Response) error { + defer resp.Body.Close() + if resp.Header.Get(headerContentEncoding) == encodingTypeGZip { + gr, err := gzip.NewReader(resp.Body) + if err != nil { + return err + } + defer gr.Close() + return internal.CopyDiscardLimited(gr, h.maxMessageSize, "response body") } - - h.receiveProcessor.ProcessReceivedMessage(ctx, &response) + return internal.CopyDiscardLimited(resp.Body, h.maxMessageSize, "response body") } func (h *HTTPSender) SetHeartbeatInterval(duration time.Duration) error { @@ -460,10 +519,6 @@ func (h *HTTPSender) EnableCompression() { h.compressionEnabled = true } -func (h *HTTPSender) SetMaxMessageSize(maxMessageSize int64) { - h.maxMessageSize = internal.ResolveMaxMessageSize(maxMessageSize) -} - func (h *HTTPSender) AddTLSConfig(config *tls.Config) { if config != nil { tlsTransport := &http.Transport{} diff --git a/client/internal/wsreceiver.go b/client/internal/wsreceiver.go index 834036ee..37b1bf69 100644 --- a/client/internal/wsreceiver.go +++ b/client/internal/wsreceiver.go @@ -3,6 +3,7 @@ package internal import ( "context" "fmt" + "net/url" "sync" "time" @@ -10,6 +11,7 @@ import ( "github.com/open-telemetry/opamp-go/client/types" "github.com/open-telemetry/opamp-go/internal" "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" ) // wsReceiver implements the WebSocket client's receiving portion of OpAMP protocol. @@ -20,12 +22,29 @@ type wsReceiver struct { callbacks types.Callbacks processor receivedProcessor + // attestation, when non-nil, decodes inbound messages as + // SignedServerToAgent envelopes, validates the trust chain on the + // first message, verifies the signature on subsequent ones, and + // surfaces the inner ServerToAgent for normal processing. + attestation *attestationState + // Indicates that the receiver has fully stopped. stopped chan struct{} + + // Set to true (before stopped is closed) when the loop exits because + // of a payload trust verification failure. Safe to read only after + // <-IsStopped() returns. + attestationFailure bool } // NewWSReceiver creates a new Receiver that uses WebSocket to receive -// messages from the server. +// messages from the server. If payloadVerifier is non-nil, every +// inbound message is treated as a SignedServerToAgent envelope: the +// trust chain is validated on the first message, signatures are +// verified on every subsequent one, and any failure terminates the +// receive loop (and, by extension, the connection). When +// payloadVerifier is nil, the receiver uses the standard ServerToAgent +// wire format (identical to upstream OpAMP). func NewWSReceiver( logger types.Logger, callbacks types.Callbacks, @@ -35,6 +54,9 @@ func NewWSReceiver( packagesStateProvider types.PackagesStateProvider, packageSyncMutex *sync.Mutex, reporterInterval time.Duration, + payloadVerifier signing.Verifier, + serverURL string, + tofuStore signing.TOFUStore, ) *wsReceiver { w := &wsReceiver{ conn: conn, @@ -44,6 +66,13 @@ func NewWSReceiver( processor: newReceivedProcessor(logger, callbacks, sender, clientSyncedState, packagesStateProvider, packageSyncMutex, reporterInterval), stopped: make(chan struct{}), } + if payloadVerifier != nil || tofuStore != nil { + var serverName string + if parsed, err := url.Parse(serverURL); err == nil { + serverName = parsed.Hostname() + } + w.attestation = newAttestationState(payloadVerifier, serverName, tofuStore) + } return w } @@ -58,6 +87,12 @@ func (r *wsReceiver) IsStopped() <-chan struct{} { return r.stopped } +// WasAttestationFailure reports whether the receiver stopped because of a +// payload trust verification failure. Only valid after <-IsStopped() returns. +func (r *wsReceiver) WasAttestationFailure() bool { + return r.attestationFailure +} + // ReceiverLoop runs the receiver loop. // To stop the receiver cancel the context and close the websocket connection func (r *wsReceiver) ReceiverLoop(ctx context.Context) { @@ -78,7 +113,7 @@ func (r *wsReceiver) ReceiverLoop(ctx context.Context) { // To stop this goroutine, close the websocket connection go func() { var message protobufs.ServerToAgent - err := r.receiveMessage(&message) + err := r.receiveMessage(ctx, &message) result <- receivedMessage{&message, err} }() @@ -87,6 +122,27 @@ func (r *wsReceiver) ReceiverLoop(ctx context.Context) { return case res := <-result: if res.err != nil { + if isAttestationFailure(res.err) { + // Per the Message Attestation spec, the Agent + // MUST terminate the connection on any + // payload-trust verification failure. + // Returning here ends the receive loop, but + // the sender goroutine might still write + // pending AgentToServer messages on the same + // conn until the wsclient owner observes the + // stopped signal and closes; eagerly closing + // the conn here prevents that small leak + // window of agent messages to an untrusted + // server. + r.logger.Errorf(ctx, "Payload trust verification failed; terminating connection: %v", res.err) + if r.conn != nil { + _ = r.conn.Close() + } + // Mark before returning so the caller can read + // WasAttestationFailure() after <-IsStopped(). + r.attestationFailure = true + return + } if !websocket.IsCloseError(res.err, websocket.CloseNormalClosure) { r.logger.Errorf(ctx, "Unexpected error while receiving: %v", res.err) } @@ -98,7 +154,7 @@ func (r *wsReceiver) ReceiverLoop(ctx context.Context) { } } -func (r *wsReceiver) receiveMessage(msg *protobufs.ServerToAgent) error { +func (r *wsReceiver) receiveMessage(ctx context.Context, msg *protobufs.ServerToAgent) error { mt, bytes, err := r.conn.ReadMessage() if err != nil { return err @@ -106,9 +162,12 @@ func (r *wsReceiver) receiveMessage(msg *protobufs.ServerToAgent) error { if mt != websocket.BinaryMessage { return fmt.Errorf("unsupported message type: %v", mt) } - err = internal.DecodeWSMessage(bytes, msg) + protoBytes, err := internal.StripWSMessageHeader(bytes) if err != nil { return fmt.Errorf("cannot decode received message: %w", err) } - return err + if err := unwrapServerToAgent(ctx, r.attestation, protoBytes, msg); err != nil { + return fmt.Errorf("cannot decode received message: %w", err) + } + return nil } diff --git a/client/types/startsettings.go b/client/types/startsettings.go index 934335c1..66ff21c6 100644 --- a/client/types/startsettings.go +++ b/client/types/startsettings.go @@ -6,6 +6,7 @@ import ( "time" "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" ) // StartSettings defines the parameters for starting the OpAMP Client. @@ -57,6 +58,44 @@ type StartSettings struct { // i.e. package status reporting and syncing from the Server will be disabled. PackagesStateProvider PackagesStateProvider + // PayloadVerifier validates the X.509 trust chain delivered in the + // initial SignedServerToAgent.trust_chain_response of a connection + // and verifies the detached signature on every subsequent + // ServerToAgent message. MUST be set when the Agent's capability + // set includes + // AgentCapabilities_RequiresPayloadTrustVerification. When nil + // (the default), payload trust verification is disabled and the + // Server-to-Agent wire format is the standard ServerToAgent + // protobuf — identical to upstream OpAMP. + // + // See the signing package for the in-process LocalVerifier + // implementation and the VerifierFromFile helper that constructs + // one from a PEM-encoded CA bundle. + PayloadVerifier signing.Verifier + + // PayloadTOFUStore enables Trust On First Use (TOFU) enrollment for the + // payload trust anchor. Mutually exclusive with PayloadVerifier: if + // PayloadVerifier is also set it takes precedence and PayloadTOFUStore + // is ignored. + // + // On startup the client calls PayloadTOFUStore.Load(): + // - If a trust anchor is returned, it is used as PayloadVerifier for + // this session (normal attestation path). + // - If no anchor is stored yet, the client advertises + // AgentCapabilities_AcceptsPayloadTrustAnchorTOFU alongside + // AgentCapabilities_RequiresPayloadTrustVerification, accepts the + // root CA from the first TrustChainResponse.tofu_trust_anchor, and + // persists it via PayloadTOFUStore.Save(). + // + // WARNING: TOFU provides no security on the first connection; a + // compromised distribution server can install an attacker-controlled + // trust anchor. Disable by default and enable only for environments + // where the first connection is considered sufficiently trusted. + // Requires persistent storage across restarts — agents running in + // stateless container environments without a persistent volume will + // repeat TOFU enrollment on every restart. + PayloadTOFUStore signing.TOFUStore + // Defines the capabilities of the Agent. AgentCapabilities_ReportsStatus bit does not need to // be set in this field, it will be set automatically since it is required by OpAMP protocol. // Deprecated: Use client.SetCapabilities() instead. diff --git a/client/wsclient.go b/client/wsclient.go index 1f412269..3c61c52d 100644 --- a/client/wsclient.go +++ b/client/wsclient.go @@ -362,7 +362,11 @@ func (c *wsClient) ensureConnected(ctx context.Context) error { // When Stop() is called (ctx is cancelled, isStopping is set), wsClient will shutdown gracefully: // 1. sender will be cancelled by the ctx, send the close message to server and return the error via sender.Err(). // 2. runOneCycle will handle that error and wait for the close message from server until timeout. -func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) { +// +// Returns true if the cycle ended because of a payload trust verification +// failure (wrong CA, bad signature, etc.). The caller should apply exponential +// backoff before retrying in that case. +func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) (attestationFailed bool) { if err := c.ensureConnected(ctx); err != nil { // Can't connect, so can't move forward. This currently happens when we // are being stopped. @@ -409,6 +413,9 @@ func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) { c.common.PackagesStateProvider, &c.common.PackageSyncMutex, c.common.DownloadReporterInterval, + c.common.PayloadVerifier, + c.url.String(), + c.common.PayloadTOFUStore, ) // When the wsclient is closed, the context passed to runOneCycle will be canceled. @@ -444,18 +451,48 @@ func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) { stopSender() <-c.sender.IsStopped() + attestationFailed = r.WasAttestationFailure() } + return } func (c *wsClient) runUntilStopped(ctx context.Context) { // Iterates until we detect that the client is stopping. sendFirstMessage := true + + // Separate backoff for attestation failures. ensureConnected already + // backs off TCP-level failures within a single runOneCycle call, but + // when the transport connects and only the application-level + // attestation check fails the receiver stops, runOneCycle returns, + // and ensureConnected would immediately succeed again on the next + // call (TCP is fine). Without this outer backoff the client would + // spin in a tight reject-reconnect loop as fast as the network + // allows, which is contrary to the spec's SHOULD-exponential-backoff + // requirement for attestation failures. + attestBackoff := backoff.NewExponentialBackOff() + attestBackoff.MaxElapsedTime = 0 // retry forever + for { if c.common.IsStopping() { return } - c.runOneCycle(ctx, sendFirstMessage) + if attestationFailed := c.runOneCycle(ctx, sendFirstMessage); attestationFailed { + interval := attestBackoff.NextBackOff() + c.common.Logger.Errorf(ctx, "Payload trust verification failed, will retry in %v.", interval) + timer := time.NewTimer(interval) + select { + case <-timer.C: + case <-ctx.Done(): + timer.Stop() + return + } + } else { + // Non-attestation cycle: reset so the next attestation + // failure starts backoff from the initial interval again. + attestBackoff.Reset() + } + sendFirstMessage = false } } diff --git a/internal/wsmessage.go b/internal/wsmessage.go index cfaaaa66..0118caca 100644 --- a/internal/wsmessage.go +++ b/internal/wsmessage.go @@ -12,29 +12,35 @@ import ( // Message header is currently uint64 zero value. const wsMsgHeader = uint64(0) -// DecodeWSMessage decodes a websocket message as bytes into a proto.Message. -func DecodeWSMessage(bytes []byte, msg proto.Message) error { - // Message header is optional until the end of grace period that ends Feb 1, 2023. - // Check if the header is present. +// StripWSMessageHeader removes the optional varint header from a +// WebSocket message and returns the protobuf payload bytes ready for +// proto.Unmarshal. The header is currently always uint64(0). When the +// header is absent (pre-2023 grace-period message format), the input +// is returned unchanged. +// +// This helper exists so that callers that need to choose a proto type +// at runtime (for example, the OpAMP client unwrapping a +// SignedServerToAgent envelope vs. a plain ServerToAgent) can strip +// the framing first and then unmarshal into the appropriate message +// type. +func StripWSMessageHeader(bytes []byte) ([]byte, error) { if len(bytes) > 0 && bytes[0] == 0 { - // New message format. The Protobuf message is preceded by a zero byte header. - // Decode the header. header, n := binary.Uvarint(bytes) if header != wsMsgHeader { - return errors.New("unexpected non-zero header") + return nil, errors.New("unexpected non-zero header") } - // Skip the header. It really is just a single zero byte for now. - bytes = bytes[n:] + return bytes[n:], nil } - // If no header was present (the "if" check above), then this is the old - // message format. No header is present. + return bytes, nil +} - // Decode WebSocket message as a Protobuf message. - err := proto.Unmarshal(bytes, msg) +// DecodeWSMessage decodes a websocket message as bytes into a proto.Message. +func DecodeWSMessage(bytes []byte, msg proto.Message) error { + protoBytes, err := StripWSMessageHeader(bytes) if err != nil { return err } - return nil + return proto.Unmarshal(protoBytes, msg) } func WriteWSMessage(conn *websocket.Conn, msg proto.Message, maxMessageSize int64) error { diff --git a/protobufs/anyvalue.pb.go b/protobufs/anyvalue.pb.go index 453fd583..c65e6d45 100644 --- a/protobufs/anyvalue.pb.go +++ b/protobufs/anyvalue.pb.go @@ -20,8 +20,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.17.3 +// protoc-gen-go v1.36.11 +// protoc v7.34.1 // source: anyvalue.proto package protobufs @@ -29,6 +29,7 @@ package protobufs import ( reflect "reflect" sync "sync" + unsafe "unsafe" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -45,14 +46,12 @@ const ( // primitive value such as a string or integer or it may contain an arbitrary nested // object containing arrays, key-value lists and primitives. type AnyValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The value is one of the listed fields. It is valid for all values to be unspecified // in which case this AnyValue is considered to be "null". // - // Types that are assignable to Value: + // Types that are valid to be assigned to Value: + // // *AnyValue_StringValue // *AnyValue_BoolValue // *AnyValue_IntValue @@ -60,16 +59,16 @@ type AnyValue struct { // *AnyValue_ArrayValue // *AnyValue_KvlistValue // *AnyValue_BytesValue - Value isAnyValue_Value `protobuf_oneof:"value"` + Value isAnyValue_Value `protobuf_oneof:"value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AnyValue) Reset() { *x = AnyValue{} - if protoimpl.UnsafeEnabled { - mi := &file_anyvalue_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_anyvalue_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AnyValue) String() string { @@ -80,7 +79,7 @@ func (*AnyValue) ProtoMessage() {} func (x *AnyValue) ProtoReflect() protoreflect.Message { mi := &file_anyvalue_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -95,58 +94,72 @@ func (*AnyValue) Descriptor() ([]byte, []int) { return file_anyvalue_proto_rawDescGZIP(), []int{0} } -func (m *AnyValue) GetValue() isAnyValue_Value { - if m != nil { - return m.Value +func (x *AnyValue) GetValue() isAnyValue_Value { + if x != nil { + return x.Value } return nil } func (x *AnyValue) GetStringValue() string { - if x, ok := x.GetValue().(*AnyValue_StringValue); ok { - return x.StringValue + if x != nil { + if x, ok := x.Value.(*AnyValue_StringValue); ok { + return x.StringValue + } } return "" } func (x *AnyValue) GetBoolValue() bool { - if x, ok := x.GetValue().(*AnyValue_BoolValue); ok { - return x.BoolValue + if x != nil { + if x, ok := x.Value.(*AnyValue_BoolValue); ok { + return x.BoolValue + } } return false } func (x *AnyValue) GetIntValue() int64 { - if x, ok := x.GetValue().(*AnyValue_IntValue); ok { - return x.IntValue + if x != nil { + if x, ok := x.Value.(*AnyValue_IntValue); ok { + return x.IntValue + } } return 0 } func (x *AnyValue) GetDoubleValue() float64 { - if x, ok := x.GetValue().(*AnyValue_DoubleValue); ok { - return x.DoubleValue + if x != nil { + if x, ok := x.Value.(*AnyValue_DoubleValue); ok { + return x.DoubleValue + } } return 0 } func (x *AnyValue) GetArrayValue() *ArrayValue { - if x, ok := x.GetValue().(*AnyValue_ArrayValue); ok { - return x.ArrayValue + if x != nil { + if x, ok := x.Value.(*AnyValue_ArrayValue); ok { + return x.ArrayValue + } } return nil } func (x *AnyValue) GetKvlistValue() *KeyValueList { - if x, ok := x.GetValue().(*AnyValue_KvlistValue); ok { - return x.KvlistValue + if x != nil { + if x, ok := x.Value.(*AnyValue_KvlistValue); ok { + return x.KvlistValue + } } return nil } func (x *AnyValue) GetBytesValue() []byte { - if x, ok := x.GetValue().(*AnyValue_BytesValue); ok { - return x.BytesValue + if x != nil { + if x, ok := x.Value.(*AnyValue_BytesValue); ok { + return x.BytesValue + } } return nil } @@ -200,21 +213,18 @@ func (*AnyValue_BytesValue) isAnyValue_Value() {} // ArrayValue is a list of AnyValue messages. We need ArrayValue as a message // since oneof in AnyValue does not allow repeated fields. type ArrayValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Array of values. The array may be empty (contain 0 elements). - Values []*AnyValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + Values []*AnyValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ArrayValue) Reset() { *x = ArrayValue{} - if protoimpl.UnsafeEnabled { - mi := &file_anyvalue_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_anyvalue_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ArrayValue) String() string { @@ -225,7 +235,7 @@ func (*ArrayValue) ProtoMessage() {} func (x *ArrayValue) ProtoReflect() protoreflect.Message { mi := &file_anyvalue_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -253,22 +263,19 @@ func (x *ArrayValue) GetValues() []*AnyValue { // avoid unnecessary extra wrapping (which slows down the protocol). The 2 approaches // are semantically equivalent. type KeyValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A collection of key/value pairs of key-value pairs. The list may be empty (may // contain 0 elements). - Values []*KeyValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + Values []*KeyValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *KeyValueList) Reset() { *x = KeyValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_anyvalue_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_anyvalue_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *KeyValueList) String() string { @@ -279,7 +286,7 @@ func (*KeyValueList) ProtoMessage() {} func (x *KeyValueList) ProtoReflect() protoreflect.Message { mi := &file_anyvalue_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -304,21 +311,18 @@ func (x *KeyValueList) GetValues() []*KeyValue { // KeyValue is a key-value pair that is used to store Span attributes, Link // attributes, etc. type KeyValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value *AnyValue `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value *AnyValue `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + sizeCache protoimpl.SizeCache } func (x *KeyValue) Reset() { *x = KeyValue{} - if protoimpl.UnsafeEnabled { - mi := &file_anyvalue_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_anyvalue_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *KeyValue) String() string { @@ -329,7 +333,7 @@ func (*KeyValue) ProtoMessage() {} func (x *KeyValue) ProtoReflect() protoreflect.Message { mi := &file_anyvalue_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -360,61 +364,44 @@ func (x *KeyValue) GetValue() *AnyValue { var File_anyvalue_proto protoreflect.FileDescriptor -var file_anyvalue_proto_rawDesc = []byte{ - 0x0a, 0x0e, 0x61, 0x6e, 0x79, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0b, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x02, - 0x0a, 0x08, 0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x0b, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x3e, 0x0a, 0x0c, 0x6b, 0x76, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6b, 0x76, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x0a, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, - 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x0c, 0x4b, 0x65, 0x79, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, - 0x2f, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_anyvalue_proto_rawDesc = "" + + "\n" + + "\x0eanyvalue.proto\x12\vopamp.proto\"\xbc\x02\n" + + "\bAnyValue\x12#\n" + + "\fstring_value\x18\x01 \x01(\tH\x00R\vstringValue\x12\x1f\n" + + "\n" + + "bool_value\x18\x02 \x01(\bH\x00R\tboolValue\x12\x1d\n" + + "\tint_value\x18\x03 \x01(\x03H\x00R\bintValue\x12#\n" + + "\fdouble_value\x18\x04 \x01(\x01H\x00R\vdoubleValue\x12:\n" + + "\varray_value\x18\x05 \x01(\v2\x17.opamp.proto.ArrayValueH\x00R\n" + + "arrayValue\x12>\n" + + "\fkvlist_value\x18\x06 \x01(\v2\x19.opamp.proto.KeyValueListH\x00R\vkvlistValue\x12!\n" + + "\vbytes_value\x18\a \x01(\fH\x00R\n" + + "bytesValueB\a\n" + + "\x05value\";\n" + + "\n" + + "ArrayValue\x12-\n" + + "\x06values\x18\x01 \x03(\v2\x15.opamp.proto.AnyValueR\x06values\"=\n" + + "\fKeyValueList\x12-\n" + + "\x06values\x18\x01 \x03(\v2\x15.opamp.proto.KeyValueR\x06values\"I\n" + + "\bKeyValue\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12+\n" + + "\x05value\x18\x02 \x01(\v2\x15.opamp.proto.AnyValueR\x05valueB.Z,github.com/open-telemetry/opamp-go/protobufsb\x06proto3" var ( file_anyvalue_proto_rawDescOnce sync.Once - file_anyvalue_proto_rawDescData = file_anyvalue_proto_rawDesc + file_anyvalue_proto_rawDescData []byte ) func file_anyvalue_proto_rawDescGZIP() []byte { file_anyvalue_proto_rawDescOnce.Do(func() { - file_anyvalue_proto_rawDescData = protoimpl.X.CompressGZIP(file_anyvalue_proto_rawDescData) + file_anyvalue_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_anyvalue_proto_rawDesc), len(file_anyvalue_proto_rawDesc))) }) return file_anyvalue_proto_rawDescData } var file_anyvalue_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_anyvalue_proto_goTypes = []interface{}{ +var file_anyvalue_proto_goTypes = []any{ (*AnyValue)(nil), // 0: opamp.proto.AnyValue (*ArrayValue)(nil), // 1: opamp.proto.ArrayValue (*KeyValueList)(nil), // 2: opamp.proto.KeyValueList @@ -438,57 +425,7 @@ func file_anyvalue_proto_init() { if File_anyvalue_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_anyvalue_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AnyValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_anyvalue_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArrayValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_anyvalue_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_anyvalue_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_anyvalue_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_anyvalue_proto_msgTypes[0].OneofWrappers = []any{ (*AnyValue_StringValue)(nil), (*AnyValue_BoolValue)(nil), (*AnyValue_IntValue)(nil), @@ -501,7 +438,7 @@ func file_anyvalue_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_anyvalue_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_anyvalue_proto_rawDesc), len(file_anyvalue_proto_rawDesc)), NumEnums: 0, NumMessages: 4, NumExtensions: 0, @@ -512,7 +449,6 @@ func file_anyvalue_proto_init() { MessageInfos: file_anyvalue_proto_msgTypes, }.Build() File_anyvalue_proto = out.File - file_anyvalue_proto_rawDesc = nil file_anyvalue_proto_goTypes = nil file_anyvalue_proto_depIdxs = nil } diff --git a/protobufs/opamp.pb.go b/protobufs/opamp.pb.go index e7f154d8..133a84de 100644 --- a/protobufs/opamp.pb.go +++ b/protobufs/opamp.pb.go @@ -16,18 +16,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.17.3 +// protoc-gen-go v1.36.9 +// protoc v7.35.0 // source: opamp.proto package protobufs import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" ) const ( @@ -169,19 +169,25 @@ const ( // The Server can accept ConnectionSettingsRequest and respond with an offer. // Status: [Development] ServerCapabilities_ServerCapabilities_AcceptsConnectionSettingsRequest ServerCapabilities = 64 + // The Server can respond to the payload trust verification handshake and + // sign every ServerToAgent message it sends after the handshake. See the + // Message Attestation section of the specification. + // Status: [Development] + ServerCapabilities_ServerCapabilities_OffersPayloadTrustVerification ServerCapabilities = 128 ) // Enum value maps for ServerCapabilities. var ( ServerCapabilities_name = map[int32]string{ - 0: "ServerCapabilities_Unspecified", - 1: "ServerCapabilities_AcceptsStatus", - 2: "ServerCapabilities_OffersRemoteConfig", - 4: "ServerCapabilities_AcceptsEffectiveConfig", - 8: "ServerCapabilities_OffersPackages", - 16: "ServerCapabilities_AcceptsPackagesStatus", - 32: "ServerCapabilities_OffersConnectionSettings", - 64: "ServerCapabilities_AcceptsConnectionSettingsRequest", + 0: "ServerCapabilities_Unspecified", + 1: "ServerCapabilities_AcceptsStatus", + 2: "ServerCapabilities_OffersRemoteConfig", + 4: "ServerCapabilities_AcceptsEffectiveConfig", + 8: "ServerCapabilities_OffersPackages", + 16: "ServerCapabilities_AcceptsPackagesStatus", + 32: "ServerCapabilities_OffersConnectionSettings", + 64: "ServerCapabilities_AcceptsConnectionSettingsRequest", + 128: "ServerCapabilities_OffersPayloadTrustVerification", } ServerCapabilities_value = map[string]int32{ "ServerCapabilities_Unspecified": 0, @@ -192,6 +198,7 @@ var ( "ServerCapabilities_AcceptsPackagesStatus": 16, "ServerCapabilities_OffersConnectionSettings": 32, "ServerCapabilities_AcceptsConnectionSettingsRequest": 64, + "ServerCapabilities_OffersPayloadTrustVerification": 128, } ) @@ -430,48 +437,67 @@ const ( AgentCapabilities_AgentCapabilities_ReportsAvailableComponents AgentCapabilities = 16384 // The agent will report ConnectionSettingsOffers status via AgentToServer.connection_settings_status field. // Status: [Development] - AgentCapabilities_AgentCapabilities_ReportsConnectionSettingsStatus AgentCapabilities = 32768 // Add new capabilities here, continuing with the least significant unused bit. + AgentCapabilities_AgentCapabilities_ReportsConnectionSettingsStatus AgentCapabilities = 32768 + // The Agent requires the payload trust verification handshake on connection + // and signature verification on every subsequent ServerToAgent message. + // If the Server does not offer this capability, the Agent MUST terminate + // the connection. See the Message Attestation section of the specification. + // Status: [Development] + AgentCapabilities_AgentCapabilities_RequiresPayloadTrustVerification AgentCapabilities = 65536 + // The Agent supports Trust On First Use (TOFU) enrollment for the payload + // trust anchor. When set alongside + // AgentCapabilities_RequiresPayloadTrustVerification it signals that the + // Agent has no pre-configured trust anchor and asks the Server to include + // the root CA in trust_chain_response.tofu_trust_anchor so the Agent can + // bootstrap and persist it. MUST NOT be set if the Agent already has a + // persisted or operator-configured trust anchor. + // Status: [Development] + AgentCapabilities_AgentCapabilities_AcceptsPayloadTrustAnchorTOFU AgentCapabilities = 131072 // Add new capabilities here, continuing with the least significant unused bit. ) // Enum value maps for AgentCapabilities. var ( AgentCapabilities_name = map[int32]string{ - 0: "AgentCapabilities_Unspecified", - 1: "AgentCapabilities_ReportsStatus", - 2: "AgentCapabilities_AcceptsRemoteConfig", - 4: "AgentCapabilities_ReportsEffectiveConfig", - 8: "AgentCapabilities_AcceptsPackages", - 16: "AgentCapabilities_ReportsPackageStatuses", - 32: "AgentCapabilities_ReportsOwnTraces", - 64: "AgentCapabilities_ReportsOwnMetrics", - 128: "AgentCapabilities_ReportsOwnLogs", - 256: "AgentCapabilities_AcceptsOpAMPConnectionSettings", - 512: "AgentCapabilities_AcceptsOtherConnectionSettings", - 1024: "AgentCapabilities_AcceptsRestartCommand", - 2048: "AgentCapabilities_ReportsHealth", - 4096: "AgentCapabilities_ReportsRemoteConfig", - 8192: "AgentCapabilities_ReportsHeartbeat", - 16384: "AgentCapabilities_ReportsAvailableComponents", - 32768: "AgentCapabilities_ReportsConnectionSettingsStatus", + 0: "AgentCapabilities_Unspecified", + 1: "AgentCapabilities_ReportsStatus", + 2: "AgentCapabilities_AcceptsRemoteConfig", + 4: "AgentCapabilities_ReportsEffectiveConfig", + 8: "AgentCapabilities_AcceptsPackages", + 16: "AgentCapabilities_ReportsPackageStatuses", + 32: "AgentCapabilities_ReportsOwnTraces", + 64: "AgentCapabilities_ReportsOwnMetrics", + 128: "AgentCapabilities_ReportsOwnLogs", + 256: "AgentCapabilities_AcceptsOpAMPConnectionSettings", + 512: "AgentCapabilities_AcceptsOtherConnectionSettings", + 1024: "AgentCapabilities_AcceptsRestartCommand", + 2048: "AgentCapabilities_ReportsHealth", + 4096: "AgentCapabilities_ReportsRemoteConfig", + 8192: "AgentCapabilities_ReportsHeartbeat", + 16384: "AgentCapabilities_ReportsAvailableComponents", + 32768: "AgentCapabilities_ReportsConnectionSettingsStatus", + 65536: "AgentCapabilities_RequiresPayloadTrustVerification", + 131072: "AgentCapabilities_AcceptsPayloadTrustAnchorTOFU", } AgentCapabilities_value = map[string]int32{ - "AgentCapabilities_Unspecified": 0, - "AgentCapabilities_ReportsStatus": 1, - "AgentCapabilities_AcceptsRemoteConfig": 2, - "AgentCapabilities_ReportsEffectiveConfig": 4, - "AgentCapabilities_AcceptsPackages": 8, - "AgentCapabilities_ReportsPackageStatuses": 16, - "AgentCapabilities_ReportsOwnTraces": 32, - "AgentCapabilities_ReportsOwnMetrics": 64, - "AgentCapabilities_ReportsOwnLogs": 128, - "AgentCapabilities_AcceptsOpAMPConnectionSettings": 256, - "AgentCapabilities_AcceptsOtherConnectionSettings": 512, - "AgentCapabilities_AcceptsRestartCommand": 1024, - "AgentCapabilities_ReportsHealth": 2048, - "AgentCapabilities_ReportsRemoteConfig": 4096, - "AgentCapabilities_ReportsHeartbeat": 8192, - "AgentCapabilities_ReportsAvailableComponents": 16384, - "AgentCapabilities_ReportsConnectionSettingsStatus": 32768, + "AgentCapabilities_Unspecified": 0, + "AgentCapabilities_ReportsStatus": 1, + "AgentCapabilities_AcceptsRemoteConfig": 2, + "AgentCapabilities_ReportsEffectiveConfig": 4, + "AgentCapabilities_AcceptsPackages": 8, + "AgentCapabilities_ReportsPackageStatuses": 16, + "AgentCapabilities_ReportsOwnTraces": 32, + "AgentCapabilities_ReportsOwnMetrics": 64, + "AgentCapabilities_ReportsOwnLogs": 128, + "AgentCapabilities_AcceptsOpAMPConnectionSettings": 256, + "AgentCapabilities_AcceptsOtherConnectionSettings": 512, + "AgentCapabilities_AcceptsRestartCommand": 1024, + "AgentCapabilities_ReportsHealth": 2048, + "AgentCapabilities_ReportsRemoteConfig": 4096, + "AgentCapabilities_ReportsHeartbeat": 8192, + "AgentCapabilities_ReportsAvailableComponents": 16384, + "AgentCapabilities_ReportsConnectionSettingsStatus": 32768, + "AgentCapabilities_RequiresPayloadTrustVerification": 65536, + "AgentCapabilities_AcceptsPayloadTrustAnchorTOFU": 131072, } ) @@ -689,10 +715,7 @@ func (PackageStatusEnum) EnumDescriptor() ([]byte, []int) { } type AgentToServer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Globally unique identifier of the running instance of the Agent. SHOULD remain // unchanged for the lifetime of the Agent process. // MUST be 16 bytes long and SHOULD be generated using the UUID v7 spec. @@ -757,15 +780,15 @@ type AgentToServer struct { // settings status is unchanged since the last AgentToServer message. // Status: [Development] ConnectionSettingsStatus *ConnectionSettingsStatus `protobuf:"bytes,15,opt,name=connection_settings_status,json=connectionSettingsStatus,proto3" json:"connection_settings_status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentToServer) Reset() { *x = AgentToServer{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentToServer) String() string { @@ -776,7 +799,7 @@ func (*AgentToServer) ProtoMessage() {} func (x *AgentToServer) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -904,18 +927,16 @@ func (x *AgentToServer) GetConnectionSettingsStatus() *ConnectionSettingsStatus // this message stream using AgentConnect message, even if the corresponding // AgentDisconnect message were not explicitly received from the Agent. type AgentDisconnect struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentDisconnect) Reset() { *x = AgentDisconnect{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentDisconnect) String() string { @@ -926,7 +947,7 @@ func (*AgentDisconnect) ProtoMessage() {} func (x *AgentDisconnect) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -945,23 +966,20 @@ func (*AgentDisconnect) Descriptor() ([]byte, []int) { // and respond with an offer of connection settings for the Agent. // Status: [Development] type ConnectionSettingsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Request for OpAMP connection settings. If this field is unset // then the ConnectionSettingsRequest message is empty and is not actionable // for the Server. - Opamp *OpAMPConnectionSettingsRequest `protobuf:"bytes,1,opt,name=opamp,proto3" json:"opamp,omitempty"` + Opamp *OpAMPConnectionSettingsRequest `protobuf:"bytes,1,opt,name=opamp,proto3" json:"opamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConnectionSettingsRequest) Reset() { *x = ConnectionSettingsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ConnectionSettingsRequest) String() string { @@ -972,7 +990,7 @@ func (*ConnectionSettingsRequest) ProtoMessage() {} func (x *ConnectionSettingsRequest) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -998,23 +1016,20 @@ func (x *ConnectionSettingsRequest) GetOpamp() *OpAMPConnectionSettingsRequest { // a OpAMPConnectionSettings in its response. // Status: [Development] type OpAMPConnectionSettingsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A request to create a client certificate. This is used to initiate a // Client Signing Request (CSR) flow. // Required. CertificateRequest *CertificateRequest `protobuf:"bytes,1,opt,name=certificate_request,json=certificateRequest,proto3" json:"certificate_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *OpAMPConnectionSettingsRequest) Reset() { *x = OpAMPConnectionSettingsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *OpAMPConnectionSettingsRequest) String() string { @@ -1025,7 +1040,7 @@ func (*OpAMPConnectionSettingsRequest) ProtoMessage() {} func (x *OpAMPConnectionSettingsRequest) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1049,24 +1064,21 @@ func (x *OpAMPConnectionSettingsRequest) GetCertificateRequest() *CertificateReq // Status: [Development] type CertificateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // PEM-encoded Client Certificate Signing Request (CSR), signed by client's private key. // The Server SHOULD validate the request and SHOULD respond with a // OpAMPConnectionSettings where the certificate.cert contains the issued // certificate. - Csr []byte `protobuf:"bytes,1,opt,name=csr,proto3" json:"csr,omitempty"` + Csr []byte `protobuf:"bytes,1,opt,name=csr,proto3" json:"csr,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CertificateRequest) Reset() { *x = CertificateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CertificateRequest) String() string { @@ -1077,7 +1089,7 @@ func (*CertificateRequest) ProtoMessage() {} func (x *CertificateRequest) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1103,27 +1115,24 @@ func (x *CertificateRequest) GetCsr() []byte { // within the agent. // status: [Development] type AvailableComponents struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A map of a unique component ID to details about the component. // This may be omitted from the message if the server has not // explicitly requested it be sent by setting the ReportAvailableComponents // flag in the previous ServerToAgent message. - Components map[string]*ComponentDetails `protobuf:"bytes,1,rep,name=components,proto3" json:"components,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Components map[string]*ComponentDetails `protobuf:"bytes,1,rep,name=components,proto3" json:"components,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Agent-calculated hash of the components. // This hash should be included in every AvailableComponents message. - Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AvailableComponents) Reset() { *x = AvailableComponents{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AvailableComponents) String() string { @@ -1134,7 +1143,7 @@ func (*AvailableComponents) ProtoMessage() {} func (x *AvailableComponents) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1164,10 +1173,7 @@ func (x *AvailableComponents) GetHash() []byte { } type ComponentDetails struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Extra key/value pairs that may be used to describe the component. // The key/value pairs are according to semantic conventions, see: // https://opentelemetry.io/docs/specs/semconv/ @@ -1182,16 +1188,16 @@ type ComponentDetails struct { Metadata []*KeyValue `protobuf:"bytes,1,rep,name=metadata,proto3" json:"metadata,omitempty"` // A map of component ID to sub components details. It can nest as deeply as needed to // describe the underlying system. - SubComponentMap map[string]*ComponentDetails `protobuf:"bytes,2,rep,name=sub_component_map,json=subComponentMap,proto3" json:"sub_component_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + SubComponentMap map[string]*ComponentDetails `protobuf:"bytes,2,rep,name=sub_component_map,json=subComponentMap,proto3" json:"sub_component_map,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ComponentDetails) Reset() { *x = ComponentDetails{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ComponentDetails) String() string { @@ -1202,7 +1208,7 @@ func (*ComponentDetails) ProtoMessage() {} func (x *ComponentDetails) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1232,10 +1238,7 @@ func (x *ComponentDetails) GetSubComponentMap() map[string]*ComponentDetails { } type ServerToAgent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Agent instance uid. MUST match the instance_uid field in AgentToServer message. // Used for multiplexing messages from/to multiple agents using one message stream. InstanceUid []byte `protobuf:"bytes,1,opt,name=instance_uid,json=instanceUid,proto3" json:"instance_uid,omitempty"` @@ -1278,15 +1281,15 @@ type ServerToAgent struct { // A custom message sent from the Server to an Agent. // Status: [Development] CustomMessage *CustomMessage `protobuf:"bytes,11,opt,name=custom_message,json=customMessage,proto3" json:"custom_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerToAgent) Reset() { *x = ServerToAgent{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServerToAgent) String() string { @@ -1297,7 +1300,7 @@ func (*ServerToAgent) ProtoMessage() {} func (x *ServerToAgent) ProtoReflect() protoreflect.Message { mi := &file_opamp_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1389,17 +1392,184 @@ func (x *ServerToAgent) GetCustomMessage() *CustomMessage { return nil } +// TrustChainResponse carries the signing certificate chain used by the Server +// to sign subsequent ServerToAgent messages, as part of the payload trust +// verification handshake. See the Message Attestation section of the +// specification. +// Status: [Development] +type TrustChainResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // PEM-encoded certificate chain, ordered from the first intermediate + // certificate down to the signing leaf certificate. The root certificate + // is excluded; the Agent already possesses the root as its pre-configured + // payload trust anchor. Multiple certificates are concatenated in a single + // PEM blob, consistent with the encoding used by TLSCertificate. + CertificateChain []byte `protobuf:"bytes,1,opt,name=certificate_chain,json=certificateChain,proto3" json:"certificate_chain,omitempty"` + // Human-readable error message indicating why the Server could not + // satisfy the trust chain request. If error_message is set, the Agent + // MUST terminate the connection. + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + // PEM-encoded root CA certificate used as the payload trust anchor. + // Set only during Trust On First Use (TOFU) enrollment: the Server + // includes this when the Agent has advertised + // AgentCapabilities_AcceptsPayloadTrustAnchorTOFU and has no + // pre-configured trust anchor. The Agent MUST persist this certificate + // and use it as the payload trust anchor for all subsequent connections. + // The Agent MUST NOT update a previously persisted or operator-configured + // trust anchor. If the Agent has a pre-configured trust anchor this + // field MUST be ignored. + // Status: [Development] + TofuTrustAnchor []byte `protobuf:"bytes,3,opt,name=tofu_trust_anchor,json=tofuTrustAnchor,proto3" json:"tofu_trust_anchor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TrustChainResponse) Reset() { + *x = TrustChainResponse{} + mi := &file_opamp_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TrustChainResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrustChainResponse) ProtoMessage() {} + +func (x *TrustChainResponse) ProtoReflect() protoreflect.Message { + mi := &file_opamp_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TrustChainResponse.ProtoReflect.Descriptor instead. +func (*TrustChainResponse) Descriptor() ([]byte, []int) { + return file_opamp_proto_rawDescGZIP(), []int{8} +} + +func (x *TrustChainResponse) GetCertificateChain() []byte { + if x != nil { + return x.CertificateChain + } + return nil +} + +func (x *TrustChainResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +func (x *TrustChainResponse) GetTofuTrustAnchor() []byte { + if x != nil { + return x.TofuTrustAnchor + } + return nil +} + +// SignedServerToAgent wraps a ServerToAgent message when the payload trust +// verification handshake has been negotiated between Server and Agent. When +// both AgentCapabilities_RequiresPayloadTrustVerification (set by the Agent) +// and ServerCapabilities_OffersPayloadTrustVerification (set by the Server) +// are advertised, every Server-to-Agent message on the connection is wrapped +// in SignedServerToAgent. +// +// The signature is computed and verified over the bytes of the payload field +// exactly as they appear on the wire (a "detached" signature). This avoids +// any dependency on canonical protobuf encoding, which is not guaranteed +// across protobuf library versions, schema changes, or build flags. +// +// See the Message Attestation section of the specification. +// Status: [Development] +type SignedServerToAgent struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Serialised bytes of a ServerToAgent message. The Agent verifies the + // detached signature over these exact bytes, without re-marshalling, + // and then unmarshals them into a ServerToAgent for normal processing. + Payload []byte `protobuf:"bytes,14,opt,name=payload,proto3" json:"payload,omitempty"` + // Detached signature over the bytes of the payload field. MUST be + // present and verifiable on every SignedServerToAgent, including the + // first. There is no exception for the first message. + Signature []byte `protobuf:"bytes,15,opt,name=signature,proto3" json:"signature,omitempty"` + // Sent only in the first SignedServerToAgent on a connection. Carries + // the signing certificate chain the Agent uses to validate the leaf + // certificate and verify signatures on all messages including this one. + // If the Agent set + // RequiresPayloadTrustVerification but the first SignedServerToAgent + // does not include a usable trust_chain_response, the Agent MUST + // terminate the connection. + TrustChainResponse *TrustChainResponse `protobuf:"bytes,16,opt,name=trust_chain_response,json=trustChainResponse,proto3" json:"trust_chain_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SignedServerToAgent) Reset() { + *x = SignedServerToAgent{} + mi := &file_opamp_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SignedServerToAgent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedServerToAgent) ProtoMessage() {} + +func (x *SignedServerToAgent) ProtoReflect() protoreflect.Message { + mi := &file_opamp_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedServerToAgent.ProtoReflect.Descriptor instead. +func (*SignedServerToAgent) Descriptor() ([]byte, []int) { + return file_opamp_proto_rawDescGZIP(), []int{9} +} + +func (x *SignedServerToAgent) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +func (x *SignedServerToAgent) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *SignedServerToAgent) GetTrustChainResponse() *TrustChainResponse { + if x != nil { + return x.TrustChainResponse + } + return nil +} + // The OpAMPConnectionSettings message is a collection of fields which comprise an // offer from the Server to the Agent to use the specified settings for OpAMP // connection. // Status: [Beta] type OpAMPConnectionSettings struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // OpAMP Server URL This MUST be a WebSocket or HTTP URL and MUST be non-empty, for - // example: "wss://example.com:4318/v1/opamp" + // example: "wss://example.com:4320/v1/opamp" DestinationEndpoint string `protobuf:"bytes,1,opt,name=destination_endpoint,json=destinationEndpoint,proto3" json:"destination_endpoint,omitempty"` // Optional headers to use when connecting. Typically used to set access tokens or // other authorization headers. For HTTP-based protocols the Agent should @@ -1431,16 +1601,16 @@ type OpAMPConnectionSettings struct { Tls *TLSConnectionSettings `protobuf:"bytes,5,opt,name=tls,proto3" json:"tls,omitempty"` // Optional connection specific proxy settings. // Status: [Development] - Proxy *ProxyConnectionSettings `protobuf:"bytes,6,opt,name=proxy,proto3" json:"proxy,omitempty"` + Proxy *ProxyConnectionSettings `protobuf:"bytes,6,opt,name=proxy,proto3" json:"proxy,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *OpAMPConnectionSettings) Reset() { *x = OpAMPConnectionSettings{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *OpAMPConnectionSettings) String() string { @@ -1450,8 +1620,8 @@ func (x *OpAMPConnectionSettings) String() string { func (*OpAMPConnectionSettings) ProtoMessage() {} func (x *OpAMPConnectionSettings) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[10] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1463,7 +1633,7 @@ func (x *OpAMPConnectionSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use OpAMPConnectionSettings.ProtoReflect.Descriptor instead. func (*OpAMPConnectionSettings) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{8} + return file_opamp_proto_rawDescGZIP(), []int{10} } func (x *OpAMPConnectionSettings) GetDestinationEndpoint() string { @@ -1513,10 +1683,7 @@ func (x *OpAMPConnectionSettings) GetProxy() *ProxyConnectionSettings { // connection to report own telemetry. // Status: [Beta] type TelemetryConnectionSettings struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The value MUST be a full URL an OTLP/HTTP/Protobuf receiver with path. Schema // SHOULD begin with "https://", for example "https://example.com:4318/v1/metrics" // The Agent MAY refuse to send the telemetry if the URL begins with "http://". @@ -1539,16 +1706,16 @@ type TelemetryConnectionSettings struct { Tls *TLSConnectionSettings `protobuf:"bytes,4,opt,name=tls,proto3" json:"tls,omitempty"` // Optional connection specific proxy settings. // Status: [Development] - Proxy *ProxyConnectionSettings `protobuf:"bytes,5,opt,name=proxy,proto3" json:"proxy,omitempty"` + Proxy *ProxyConnectionSettings `protobuf:"bytes,5,opt,name=proxy,proto3" json:"proxy,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TelemetryConnectionSettings) Reset() { *x = TelemetryConnectionSettings{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TelemetryConnectionSettings) String() string { @@ -1558,8 +1725,8 @@ func (x *TelemetryConnectionSettings) String() string { func (*TelemetryConnectionSettings) ProtoMessage() {} func (x *TelemetryConnectionSettings) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[11] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1571,7 +1738,7 @@ func (x *TelemetryConnectionSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryConnectionSettings.ProtoReflect.Descriptor instead. func (*TelemetryConnectionSettings) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{9} + return file_opamp_proto_rawDescGZIP(), []int{11} } func (x *TelemetryConnectionSettings) GetDestinationEndpoint() string { @@ -1631,10 +1798,7 @@ func (x *TelemetryConnectionSettings) GetProxy() *ProxyConnectionSettings { // the field. // Status: [Beta] type OtherConnectionSettings struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A URL, host:port or some other destination specifier. DestinationEndpoint string `protobuf:"bytes,1,opt,name=destination_endpoint,json=destinationEndpoint,proto3" json:"destination_endpoint,omitempty"` // Optional headers to use when connecting. Typically used to set access tokens or @@ -1652,22 +1816,22 @@ type OtherConnectionSettings struct { Certificate *TLSCertificate `protobuf:"bytes,3,opt,name=certificate,proto3" json:"certificate,omitempty"` // Other connection settings. These are Agent-specific and are up to the Agent // interpret. - OtherSettings map[string]string `protobuf:"bytes,4,rep,name=other_settings,json=otherSettings,proto3" json:"other_settings,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + OtherSettings map[string]string `protobuf:"bytes,4,rep,name=other_settings,json=otherSettings,proto3" json:"other_settings,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Optional connection specific TLS settings. // Status: [Development] Tls *TLSConnectionSettings `protobuf:"bytes,5,opt,name=tls,proto3" json:"tls,omitempty"` // Optional connection specific proxy settings. // Status: [Development] - Proxy *ProxyConnectionSettings `protobuf:"bytes,6,opt,name=proxy,proto3" json:"proxy,omitempty"` + Proxy *ProxyConnectionSettings `protobuf:"bytes,6,opt,name=proxy,proto3" json:"proxy,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *OtherConnectionSettings) Reset() { *x = OtherConnectionSettings{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *OtherConnectionSettings) String() string { @@ -1677,8 +1841,8 @@ func (x *OtherConnectionSettings) String() string { func (*OtherConnectionSettings) ProtoMessage() {} func (x *OtherConnectionSettings) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[12] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1690,7 +1854,7 @@ func (x *OtherConnectionSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use OtherConnectionSettings.ProtoReflect.Descriptor instead. func (*OtherConnectionSettings) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{10} + return file_opamp_proto_rawDescGZIP(), []int{12} } func (x *OtherConnectionSettings) GetDestinationEndpoint() string { @@ -1739,31 +1903,28 @@ func (x *OtherConnectionSettings) GetProxy() *ProxyConnectionSettings { // the client in order to specify TLS configuration. // Status: [Development] type TLSConnectionSettings struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Provides CA cert contents as a string. CaPemContents string `protobuf:"bytes,1,opt,name=ca_pem_contents,json=caPemContents,proto3" json:"ca_pem_contents,omitempty"` // Load system CA pool alongside any passed CAs. IncludeSystemCaCertsPool bool `protobuf:"varint,2,opt,name=include_system_ca_certs_pool,json=includeSystemCaCertsPool,proto3" json:"include_system_ca_certs_pool,omitempty"` // skip certificate verification. InsecureSkipVerify bool `protobuf:"varint,3,opt,name=insecure_skip_verify,json=insecureSkipVerify,proto3" json:"insecure_skip_verify,omitempty"` - // Miniumum accepted TLS version; default "1.2". + // Minimum accepted TLS version; default "1.2". MinVersion string `protobuf:"bytes,4,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"` - // Maxiumum accepted TLS version; default "". + // Maximum accepted TLS version; default "". MaxVersion string `protobuf:"bytes,5,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"` // Explicit list of cipher suites. - CipherSuites []string `protobuf:"bytes,6,rep,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"` + CipherSuites []string `protobuf:"bytes,6,rep,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TLSConnectionSettings) Reset() { *x = TLSConnectionSettings{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TLSConnectionSettings) String() string { @@ -1773,8 +1934,8 @@ func (x *TLSConnectionSettings) String() string { func (*TLSConnectionSettings) ProtoMessage() {} func (x *TLSConnectionSettings) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[13] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1786,7 +1947,7 @@ func (x *TLSConnectionSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use TLSConnectionSettings.ProtoReflect.Descriptor instead. func (*TLSConnectionSettings) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{11} + return file_opamp_proto_rawDescGZIP(), []int{13} } func (x *TLSConnectionSettings) GetCaPemContents() string { @@ -1833,10 +1994,7 @@ func (x *TLSConnectionSettings) GetCipherSuites() []string { // Status: [Development] type ProxyConnectionSettings struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A URL, host:port or some other destination specifier. Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` // Optional headers to send to proxies during CONNECT requests. @@ -1844,15 +2002,15 @@ type ProxyConnectionSettings struct { // For example: // key="Authorization", Value="Basic YWxhZGRpbjpvcGVuc2VzYW1l". ConnectHeaders *Headers `protobuf:"bytes,2,opt,name=connect_headers,json=connectHeaders,proto3" json:"connect_headers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ProxyConnectionSettings) Reset() { *x = ProxyConnectionSettings{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ProxyConnectionSettings) String() string { @@ -1862,8 +2020,8 @@ func (x *ProxyConnectionSettings) String() string { func (*ProxyConnectionSettings) ProtoMessage() {} func (x *ProxyConnectionSettings) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[14] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1875,7 +2033,7 @@ func (x *ProxyConnectionSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use ProxyConnectionSettings.ProtoReflect.Descriptor instead. func (*ProxyConnectionSettings) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{12} + return file_opamp_proto_rawDescGZIP(), []int{14} } func (x *ProxyConnectionSettings) GetUrl() string { @@ -1894,20 +2052,17 @@ func (x *ProxyConnectionSettings) GetConnectHeaders() *Headers { // Status: [Beta] type Headers struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Headers []*Header `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty"` unknownFields protoimpl.UnknownFields - - Headers []*Header `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Headers) Reset() { *x = Headers{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Headers) String() string { @@ -1917,8 +2072,8 @@ func (x *Headers) String() string { func (*Headers) ProtoMessage() {} func (x *Headers) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[15] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1930,7 +2085,7 @@ func (x *Headers) ProtoReflect() protoreflect.Message { // Deprecated: Use Headers.ProtoReflect.Descriptor instead. func (*Headers) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{13} + return file_opamp_proto_rawDescGZIP(), []int{15} } func (x *Headers) GetHeaders() []*Header { @@ -1942,21 +2097,18 @@ func (x *Headers) GetHeaders() []*Header { // Status: [Beta] type Header struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Header) Reset() { *x = Header{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Header) String() string { @@ -1966,8 +2118,8 @@ func (x *Header) String() string { func (*Header) ProtoMessage() {} func (x *Header) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[16] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1979,7 +2131,7 @@ func (x *Header) ProtoReflect() protoreflect.Message { // Deprecated: Use Header.ProtoReflect.Descriptor instead. func (*Header) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{14} + return file_opamp_proto_rawDescGZIP(), []int{16} } func (x *Header) GetKey() string { @@ -1998,10 +2150,7 @@ func (x *Header) GetValue() string { // Status: [Beta] type TLSCertificate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // PEM-encoded certificate. Required. Cert []byte `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` // PEM-encoded private key of the certificate. Required. @@ -2012,16 +2161,16 @@ type TLSCertificate struct { // the connecting client's certificate in the future. // It is not recommended that the Agent accepts this CA as an authority for // any purposes. - CaCert []byte `protobuf:"bytes,3,opt,name=ca_cert,json=caCert,proto3" json:"ca_cert,omitempty"` + CaCert []byte `protobuf:"bytes,3,opt,name=ca_cert,json=caCert,proto3" json:"ca_cert,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TLSCertificate) Reset() { *x = TLSCertificate{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TLSCertificate) String() string { @@ -2031,8 +2180,8 @@ func (x *TLSCertificate) String() string { func (*TLSCertificate) ProtoMessage() {} func (x *TLSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[17] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2044,7 +2193,7 @@ func (x *TLSCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use TLSCertificate.ProtoReflect.Descriptor instead. func (*TLSCertificate) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{15} + return file_opamp_proto_rawDescGZIP(), []int{17} } func (x *TLSCertificate) GetCert() []byte { @@ -2070,10 +2219,7 @@ func (x *TLSCertificate) GetCaCert() []byte { // Status: [Beta] type ConnectionSettingsOffers struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Hash of all settings, including settings that may be omitted from this message // because they are unchanged. Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` @@ -2111,16 +2257,16 @@ type ConnectionSettingsOffers struct { // the name of the destination to connect to (as it is known to the Agent). // If this field is not set then the Agent should assume that the other_connections // settings are unchanged. - OtherConnections map[string]*OtherConnectionSettings `protobuf:"bytes,6,rep,name=other_connections,json=otherConnections,proto3" json:"other_connections,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + OtherConnections map[string]*OtherConnectionSettings `protobuf:"bytes,6,rep,name=other_connections,json=otherConnections,proto3" json:"other_connections,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConnectionSettingsOffers) Reset() { *x = ConnectionSettingsOffers{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ConnectionSettingsOffers) String() string { @@ -2130,8 +2276,8 @@ func (x *ConnectionSettingsOffers) String() string { func (*ConnectionSettingsOffers) ProtoMessage() {} func (x *ConnectionSettingsOffers) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[18] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2143,7 +2289,7 @@ func (x *ConnectionSettingsOffers) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectionSettingsOffers.ProtoReflect.Descriptor instead. func (*ConnectionSettingsOffers) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{16} + return file_opamp_proto_rawDescGZIP(), []int{18} } func (x *ConnectionSettingsOffers) GetHash() []byte { @@ -2191,12 +2337,9 @@ func (x *ConnectionSettingsOffers) GetOtherConnections() map[string]*OtherConnec // List of packages that the Server offers to the Agent. // Status: [Beta] type PackagesAvailable struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Map of packages. Keys are package names, values are the packages available for download. - Packages map[string]*PackageAvailable `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Packages map[string]*PackageAvailable `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Aggregate hash of all remotely installed packages. The Agent SHOULD include this // value in subsequent PackageStatuses messages. This in turn allows the management // Server to identify that a different set of packages is available for the Agent @@ -2207,15 +2350,15 @@ type PackagesAvailable struct { // // The hash is calculated as an aggregate of all packages names and content. AllPackagesHash []byte `protobuf:"bytes,2,opt,name=all_packages_hash,json=allPackagesHash,proto3" json:"all_packages_hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PackagesAvailable) Reset() { *x = PackagesAvailable{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PackagesAvailable) String() string { @@ -2225,8 +2368,8 @@ func (x *PackagesAvailable) String() string { func (*PackagesAvailable) ProtoMessage() {} func (x *PackagesAvailable) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[19] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2238,7 +2381,7 @@ func (x *PackagesAvailable) ProtoReflect() protoreflect.Message { // Deprecated: Use PackagesAvailable.ProtoReflect.Descriptor instead. func (*PackagesAvailable) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{17} + return file_opamp_proto_rawDescGZIP(), []int{19} } func (x *PackagesAvailable) GetPackages() map[string]*PackageAvailable { @@ -2272,11 +2415,8 @@ func (x *PackagesAvailable) GetAllPackagesHash() []byte { // has the right version of the package. // Status: [Beta] type PackageAvailable struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type PackageType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.PackageType" json:"type,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Type PackageType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.v1.PackageType" json:"type,omitempty"` // The package version that is available on the Server side. The Agent may for // example use this information to avoid downloading a package that was previously // already downloaded and failed to install. @@ -2287,16 +2427,16 @@ type PackageAvailable struct { // PackageAvailable message and content of the file of the package. The hash is // used by the Agent to determine if the package it has is different from the // package the Server is offering. - Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PackageAvailable) Reset() { *x = PackageAvailable{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PackageAvailable) String() string { @@ -2306,8 +2446,8 @@ func (x *PackageAvailable) String() string { func (*PackageAvailable) ProtoMessage() {} func (x *PackageAvailable) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[20] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2319,7 +2459,7 @@ func (x *PackageAvailable) ProtoReflect() protoreflect.Message { // Deprecated: Use PackageAvailable.ProtoReflect.Descriptor instead. func (*PackageAvailable) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{18} + return file_opamp_proto_rawDescGZIP(), []int{20} } func (x *PackageAvailable) GetType() PackageType { @@ -2352,10 +2492,7 @@ func (x *PackageAvailable) GetHash() []byte { // Status: [Beta] type DownloadableFile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The URL from which the file can be downloaded using HTTP GET request. // The Server at the specified URL SHOULD support range requests // to allow for resuming downloads. @@ -2376,16 +2513,16 @@ type DownloadableFile struct { // For example: // key="Authorization", Value="Basic YWxhZGRpbjpvcGVuc2VzYW1l". // Status: [Development] - Headers *Headers `protobuf:"bytes,4,opt,name=headers,proto3" json:"headers,omitempty"` + Headers *Headers `protobuf:"bytes,4,opt,name=headers,proto3" json:"headers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DownloadableFile) Reset() { *x = DownloadableFile{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DownloadableFile) String() string { @@ -2395,8 +2532,8 @@ func (x *DownloadableFile) String() string { func (*DownloadableFile) ProtoMessage() {} func (x *DownloadableFile) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[21] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2408,7 +2545,7 @@ func (x *DownloadableFile) ProtoReflect() protoreflect.Message { // Deprecated: Use DownloadableFile.ProtoReflect.Descriptor instead. func (*DownloadableFile) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{19} + return file_opamp_proto_rawDescGZIP(), []int{21} } func (x *DownloadableFile) GetDownloadUrl() string { @@ -2440,25 +2577,23 @@ func (x *DownloadableFile) GetHeaders() *Headers { } type ServerErrorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type ServerErrorResponseType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.ServerErrorResponseType" json:"type,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Type ServerErrorResponseType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.v1.ServerErrorResponseType" json:"type,omitempty"` // Error message in the string form, typically human readable. ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - // Types that are assignable to Details: + // Types that are valid to be assigned to Details: + // // *ServerErrorResponse_RetryInfo - Details isServerErrorResponse_Details `protobuf_oneof:"Details"` + Details isServerErrorResponse_Details `protobuf_oneof:"Details"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerErrorResponse) Reset() { *x = ServerErrorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServerErrorResponse) String() string { @@ -2468,8 +2603,8 @@ func (x *ServerErrorResponse) String() string { func (*ServerErrorResponse) ProtoMessage() {} func (x *ServerErrorResponse) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[22] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2481,7 +2616,7 @@ func (x *ServerErrorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerErrorResponse.ProtoReflect.Descriptor instead. func (*ServerErrorResponse) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{20} + return file_opamp_proto_rawDescGZIP(), []int{22} } func (x *ServerErrorResponse) GetType() ServerErrorResponseType { @@ -2498,16 +2633,18 @@ func (x *ServerErrorResponse) GetErrorMessage() string { return "" } -func (m *ServerErrorResponse) GetDetails() isServerErrorResponse_Details { - if m != nil { - return m.Details +func (x *ServerErrorResponse) GetDetails() isServerErrorResponse_Details { + if x != nil { + return x.Details } return nil } func (x *ServerErrorResponse) GetRetryInfo() *RetryInfo { - if x, ok := x.GetDetails().(*ServerErrorResponse_RetryInfo); ok { - return x.RetryInfo + if x != nil { + if x, ok := x.Details.(*ServerErrorResponse_RetryInfo); ok { + return x.RetryInfo + } } return nil } @@ -2524,20 +2661,17 @@ type ServerErrorResponse_RetryInfo struct { func (*ServerErrorResponse_RetryInfo) isServerErrorResponse_Details() {} type RetryInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RetryAfterNanoseconds uint64 `protobuf:"varint,1,opt,name=retry_after_nanoseconds,json=retryAfterNanoseconds,proto3" json:"retry_after_nanoseconds,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RetryAfterNanoseconds uint64 `protobuf:"varint,1,opt,name=retry_after_nanoseconds,json=retryAfterNanoseconds,proto3" json:"retry_after_nanoseconds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RetryInfo) Reset() { *x = RetryInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RetryInfo) String() string { @@ -2547,8 +2681,8 @@ func (x *RetryInfo) String() string { func (*RetryInfo) ProtoMessage() {} func (x *RetryInfo) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[23] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2560,7 +2694,7 @@ func (x *RetryInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryInfo.ProtoReflect.Descriptor instead. func (*RetryInfo) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{21} + return file_opamp_proto_rawDescGZIP(), []int{23} } func (x *RetryInfo) GetRetryAfterNanoseconds() uint64 { @@ -2574,20 +2708,17 @@ func (x *RetryInfo) GetRetryAfterNanoseconds() uint64 { // perform a command. // Status: [Beta] type ServerToAgentCommand struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Type CommandType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.v1.CommandType" json:"type,omitempty"` unknownFields protoimpl.UnknownFields - - Type CommandType `protobuf:"varint,1,opt,name=type,proto3,enum=opamp.proto.CommandType" json:"type,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ServerToAgentCommand) Reset() { *x = ServerToAgentCommand{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServerToAgentCommand) String() string { @@ -2597,8 +2728,8 @@ func (x *ServerToAgentCommand) String() string { func (*ServerToAgentCommand) ProtoMessage() {} func (x *ServerToAgentCommand) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[24] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2610,7 +2741,7 @@ func (x *ServerToAgentCommand) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerToAgentCommand.ProtoReflect.Descriptor instead. func (*ServerToAgentCommand) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{22} + return file_opamp_proto_rawDescGZIP(), []int{24} } func (x *ServerToAgentCommand) GetType() CommandType { @@ -2621,25 +2752,22 @@ func (x *ServerToAgentCommand) GetType() CommandType { } type AgentDescription struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Attributes that identify the Agent. // Keys/values are according to OpenTelemetry semantic conventions, see: // https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions // // For standalone running Agents (such as OpenTelemetry Collector) the following // attributes SHOULD be specified: - // - service.name should be set to a reverse FQDN that uniquely identifies the - // Agent type, e.g. "io.opentelemetry.collector" - // - service.namespace if it is used in the environment where the Agent runs. - // - service.version should be set to version number of the Agent build. - // - service.instance.id should be set. It may be set equal to the Agent's - // instance uid (equal to ServerToAgent.instance_uid field) or any other value - // that uniquely identifies the Agent in combination with other attributes. - // - any other attributes that are necessary for uniquely identifying the Agent's - // own telemetry. + // - service.name should be set to a reverse FQDN that uniquely identifies the + // Agent type, e.g. "io.opentelemetry.collector" + // - service.namespace if it is used in the environment where the Agent runs. + // - service.version should be set to version number of the Agent build. + // - service.instance.id should be set. It may be set equal to the Agent's + // instance uid (equal to ServerToAgent.instance_uid field) or any other value + // that uniquely identifies the Agent in combination with other attributes. + // - any other attributes that are necessary for uniquely identifying the Agent's + // own telemetry. // // The Agent SHOULD also include these attributes in the Resource of its own // telemetry. The combination of identifying attributes SHOULD be sufficient to @@ -2649,23 +2777,23 @@ type AgentDescription struct { // Attributes that do not necessarily identify the Agent but help describe // where it runs. // The following attributes SHOULD be included: - // - os.type, os.version - to describe where the Agent runs. - // - host.* to describe the host the Agent runs on. - // - cloud.* to describe the cloud where the host is located. - // - any other relevant Resource attributes that describe this Agent and the - // environment it runs in. - // - any user-defined attributes that the end user would like to associate - // with this Agent. + // - os.type, os.version - to describe where the Agent runs. + // - host.* to describe the host the Agent runs on. + // - cloud.* to describe the cloud where the host is located. + // - any other relevant Resource attributes that describe this Agent and the + // environment it runs in. + // - any user-defined attributes that the end user would like to associate + // with this Agent. NonIdentifyingAttributes []*KeyValue `protobuf:"bytes,2,rep,name=non_identifying_attributes,json=nonIdentifyingAttributes,proto3" json:"non_identifying_attributes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentDescription) Reset() { *x = AgentDescription{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentDescription) String() string { @@ -2675,8 +2803,8 @@ func (x *AgentDescription) String() string { func (*AgentDescription) ProtoMessage() {} func (x *AgentDescription) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[25] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2688,7 +2816,7 @@ func (x *AgentDescription) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentDescription.ProtoReflect.Descriptor instead. func (*AgentDescription) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{23} + return file_opamp_proto_rawDescGZIP(), []int{25} } func (x *AgentDescription) GetIdentifyingAttributes() []*KeyValue { @@ -2708,10 +2836,7 @@ func (x *AgentDescription) GetNonIdentifyingAttributes() []*KeyValue { // The health of the Agent and sub-components // Status: [Beta] type ComponentHealth struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Set to true if the component is up and healthy. Healthy bool `protobuf:"varint,1,opt,name=healthy,proto3" json:"healthy,omitempty"` // Timestamp since the component is up, i.e. when the component was started. @@ -2729,16 +2854,16 @@ type ComponentHealth struct { StatusTimeUnixNano uint64 `protobuf:"fixed64,5,opt,name=status_time_unix_nano,json=statusTimeUnixNano,proto3" json:"status_time_unix_nano,omitempty"` // A map to store more granular, sub-component health. It can nest as deeply as needed to // describe the underlying system. - ComponentHealthMap map[string]*ComponentHealth `protobuf:"bytes,6,rep,name=component_health_map,json=componentHealthMap,proto3" json:"component_health_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ComponentHealthMap map[string]*ComponentHealth `protobuf:"bytes,6,rep,name=component_health_map,json=componentHealthMap,proto3" json:"component_health_map,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ComponentHealth) Reset() { *x = ComponentHealth{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ComponentHealth) String() string { @@ -2748,8 +2873,8 @@ func (x *ComponentHealth) String() string { func (*ComponentHealth) ProtoMessage() {} func (x *ComponentHealth) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[26] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2761,7 +2886,7 @@ func (x *ComponentHealth) ProtoReflect() protoreflect.Message { // Deprecated: Use ComponentHealth.ProtoReflect.Descriptor instead. func (*ComponentHealth) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{24} + return file_opamp_proto_rawDescGZIP(), []int{26} } func (x *ComponentHealth) GetHealthy() bool { @@ -2807,21 +2932,18 @@ func (x *ComponentHealth) GetComponentHealthMap() map[string]*ComponentHealth { } type EffectiveConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The effective config of the Agent. - ConfigMap *AgentConfigMap `protobuf:"bytes,1,opt,name=config_map,json=configMap,proto3" json:"config_map,omitempty"` + ConfigMap *AgentConfigMap `protobuf:"bytes,1,opt,name=config_map,json=configMap,proto3" json:"config_map,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *EffectiveConfig) Reset() { *x = EffectiveConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EffectiveConfig) String() string { @@ -2831,8 +2953,8 @@ func (x *EffectiveConfig) String() string { func (*EffectiveConfig) ProtoMessage() {} func (x *EffectiveConfig) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[27] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2844,7 +2966,7 @@ func (x *EffectiveConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use EffectiveConfig.ProtoReflect.Descriptor instead. func (*EffectiveConfig) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{25} + return file_opamp_proto_rawDescGZIP(), []int{27} } func (x *EffectiveConfig) GetConfigMap() *AgentConfigMap { @@ -2855,28 +2977,25 @@ func (x *EffectiveConfig) GetConfigMap() *AgentConfigMap { } type RemoteConfigStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The hash of the remote config that was last received by this Agent in the // AgentRemoteConfig.config_hash field. // The Server SHOULD compare this hash with the config hash // it has for the Agent and if the hashes are different the Server MUST include // the remote_config field in the response in the ServerToAgent message. LastRemoteConfigHash []byte `protobuf:"bytes,1,opt,name=last_remote_config_hash,json=lastRemoteConfigHash,proto3" json:"last_remote_config_hash,omitempty"` - Status RemoteConfigStatuses `protobuf:"varint,2,opt,name=status,proto3,enum=opamp.proto.RemoteConfigStatuses" json:"status,omitempty"` + Status RemoteConfigStatuses `protobuf:"varint,2,opt,name=status,proto3,enum=opamp.proto.v1.RemoteConfigStatuses" json:"status,omitempty"` // Optional error message if status==FAILED. - ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RemoteConfigStatus) Reset() { *x = RemoteConfigStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RemoteConfigStatus) String() string { @@ -2886,8 +3005,8 @@ func (x *RemoteConfigStatus) String() string { func (*RemoteConfigStatus) ProtoMessage() {} func (x *RemoteConfigStatus) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[28] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2899,7 +3018,7 @@ func (x *RemoteConfigStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoteConfigStatus.ProtoReflect.Descriptor instead. func (*RemoteConfigStatus) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{26} + return file_opamp_proto_rawDescGZIP(), []int{28} } func (x *RemoteConfigStatus) GetLastRemoteConfigHash() []byte { @@ -2925,28 +3044,25 @@ func (x *RemoteConfigStatus) GetErrorMessage() string { // Status: [Development] type ConnectionSettingsStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The hash of the connection settings that was last recieved by this Agent + state protoimpl.MessageState `protogen:"open.v1"` + // The hash of the connection settings that was last received by this Agent // in the connection_settings.hash field. The Server SHOULD compare this // hash with the OfferedConnectionSettings hash it has for the Agent and if // the hashes are different the Server MUST include the connection_settings // field in the response in the ServerToAgent message. LastConnectionSettingsHash []byte `protobuf:"bytes,1,opt,name=last_connection_settings_hash,json=lastConnectionSettingsHash,proto3" json:"last_connection_settings_hash,omitempty"` - Status ConnectionSettingsStatuses `protobuf:"varint,2,opt,name=status,proto3,enum=opamp.proto.ConnectionSettingsStatuses" json:"status,omitempty"` + Status ConnectionSettingsStatuses `protobuf:"varint,2,opt,name=status,proto3,enum=opamp.proto.v1.ConnectionSettingsStatuses" json:"status,omitempty"` // Optional error message if status==FAILED. - ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConnectionSettingsStatus) Reset() { *x = ConnectionSettingsStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ConnectionSettingsStatus) String() string { @@ -2956,8 +3072,8 @@ func (x *ConnectionSettingsStatus) String() string { func (*ConnectionSettingsStatus) ProtoMessage() {} func (x *ConnectionSettingsStatus) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[29] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2969,7 +3085,7 @@ func (x *ConnectionSettingsStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectionSettingsStatus.ProtoReflect.Descriptor instead. func (*ConnectionSettingsStatus) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{27} + return file_opamp_proto_rawDescGZIP(), []int{29} } func (x *ConnectionSettingsStatus) GetLastConnectionSettingsHash() []byte { @@ -2997,13 +3113,10 @@ func (x *ConnectionSettingsStatus) GetErrorMessage() string { // has or was offered. // Status: [Beta] type PackageStatuses struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A map of PackageStatus messages, where the keys are package names. // The key MUST match the name field of PackageStatus message. - Packages map[string]*PackageStatus `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Packages map[string]*PackageStatus `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // The aggregate hash of all packages that this Agent previously received from the // Server via PackagesAvailable message. // @@ -3015,16 +3128,16 @@ type PackageStatuses struct { // PackagesAvailable message and that error is not related to any particular single // package. // The field must be unset is there were no processing errors. - ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PackageStatuses) Reset() { *x = PackageStatuses{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PackageStatuses) String() string { @@ -3034,8 +3147,8 @@ func (x *PackageStatuses) String() string { func (*PackageStatuses) ProtoMessage() {} func (x *PackageStatuses) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[30] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3047,7 +3160,7 @@ func (x *PackageStatuses) ProtoReflect() protoreflect.Message { // Deprecated: Use PackageStatuses.ProtoReflect.Descriptor instead. func (*PackageStatuses) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{28} + return file_opamp_proto_rawDescGZIP(), []int{30} } func (x *PackageStatuses) GetPackages() map[string]*PackageStatus { @@ -3074,10 +3187,7 @@ func (x *PackageStatuses) GetErrorMessage() string { // The status of a single package. // Status: [Beta] type PackageStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Package name. MUST be always set and MUST match the key in the packages field // of PackageStatuses message. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -3117,22 +3227,22 @@ type PackageStatus struct { // the Agent already has a version of the package successfully installed, the // Server offers a different version, but the Agent fails to install that version. ServerOfferedHash []byte `protobuf:"bytes,5,opt,name=server_offered_hash,json=serverOfferedHash,proto3" json:"server_offered_hash,omitempty"` - Status PackageStatusEnum `protobuf:"varint,6,opt,name=status,proto3,enum=opamp.proto.PackageStatusEnum" json:"status,omitempty"` + Status PackageStatusEnum `protobuf:"varint,6,opt,name=status,proto3,enum=opamp.proto.v1.PackageStatusEnum" json:"status,omitempty"` // Error message if the status is erroneous. ErrorMessage string `protobuf:"bytes,7,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` // Optional details that may be of interest to a user. // Should only be set if status is Downloading. // Status: [Development] DownloadDetails *PackageDownloadDetails `protobuf:"bytes,8,opt,name=download_details,json=downloadDetails,proto3" json:"download_details,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PackageStatus) Reset() { *x = PackageStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PackageStatus) String() string { @@ -3142,8 +3252,8 @@ func (x *PackageStatus) String() string { func (*PackageStatus) ProtoMessage() {} func (x *PackageStatus) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[31] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3155,7 +3265,7 @@ func (x *PackageStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use PackageStatus.ProtoReflect.Descriptor instead. func (*PackageStatus) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{29} + return file_opamp_proto_rawDescGZIP(), []int{31} } func (x *PackageStatus) GetName() string { @@ -3217,23 +3327,20 @@ func (x *PackageStatus) GetDownloadDetails() *PackageDownloadDetails { // Additional details that an agent can use to describe an in-progress package download. // Status: [Development] type PackageDownloadDetails struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The package download progress as a percentage. DownloadPercent float64 `protobuf:"fixed64,1,opt,name=download_percent,json=downloadPercent,proto3" json:"download_percent,omitempty"` // The current package download rate in bytes per second. DownloadBytesPerSecond float64 `protobuf:"fixed64,2,opt,name=download_bytes_per_second,json=downloadBytesPerSecond,proto3" json:"download_bytes_per_second,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PackageDownloadDetails) Reset() { *x = PackageDownloadDetails{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PackageDownloadDetails) String() string { @@ -3243,8 +3350,8 @@ func (x *PackageDownloadDetails) String() string { func (*PackageDownloadDetails) ProtoMessage() {} func (x *PackageDownloadDetails) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[32] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3256,7 +3363,7 @@ func (x *PackageDownloadDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use PackageDownloadDetails.ProtoReflect.Descriptor instead. func (*PackageDownloadDetails) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{30} + return file_opamp_proto_rawDescGZIP(), []int{32} } func (x *PackageDownloadDetails) GetDownloadPercent() float64 { @@ -3276,23 +3383,20 @@ func (x *PackageDownloadDetails) GetDownloadBytesPerSecond() float64 { // Properties related to identification of the Agent, which can be overridden // by the Server if needed type AgentIdentification struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // When new_instance_uid is set, Agent MUST update instance_uid // to the value provided and use it for all further communication. // MUST be 16 bytes long and SHOULD be generated using the UUID v7 spec. NewInstanceUid []byte `protobuf:"bytes,1,opt,name=new_instance_uid,json=newInstanceUid,proto3" json:"new_instance_uid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentIdentification) Reset() { *x = AgentIdentification{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentIdentification) String() string { @@ -3302,8 +3406,8 @@ func (x *AgentIdentification) String() string { func (*AgentIdentification) ProtoMessage() {} func (x *AgentIdentification) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[33] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3315,7 +3419,7 @@ func (x *AgentIdentification) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentIdentification.ProtoReflect.Descriptor instead. func (*AgentIdentification) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{31} + return file_opamp_proto_rawDescGZIP(), []int{33} } func (x *AgentIdentification) GetNewInstanceUid() []byte { @@ -3326,10 +3430,7 @@ func (x *AgentIdentification) GetNewInstanceUid() []byte { } type AgentRemoteConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Agent config offered by the management Server to the Agent instance. SHOULD NOT be // set if the config for this Agent has not changed since it was last requested (i.e. // AgentConfigRequest.last_remote_config_hash field is equal to @@ -3344,16 +3445,16 @@ type AgentRemoteConfig struct { // // Management Server must choose a hashing function that guarantees lack of hash // collisions in practice. - ConfigHash []byte `protobuf:"bytes,2,opt,name=config_hash,json=configHash,proto3" json:"config_hash,omitempty"` + ConfigHash []byte `protobuf:"bytes,2,opt,name=config_hash,json=configHash,proto3" json:"config_hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentRemoteConfig) Reset() { *x = AgentRemoteConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentRemoteConfig) String() string { @@ -3363,8 +3464,8 @@ func (x *AgentRemoteConfig) String() string { func (*AgentRemoteConfig) ProtoMessage() {} func (x *AgentRemoteConfig) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[34] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3376,7 +3477,7 @@ func (x *AgentRemoteConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentRemoteConfig.ProtoReflect.Descriptor instead. func (*AgentRemoteConfig) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{32} + return file_opamp_proto_rawDescGZIP(), []int{34} } func (x *AgentRemoteConfig) GetConfig() *AgentConfigMap { @@ -3394,25 +3495,22 @@ func (x *AgentRemoteConfig) GetConfigHash() []byte { } type AgentConfigMap struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Map of configs. Keys are config file names or config section names. // The configuration is assumed to be a collection of one or more named config files // or sections. // For agents that use a single config file or section the map SHOULD contain a single // entry and the key may be an empty string. - ConfigMap map[string]*AgentConfigFile `protobuf:"bytes,1,rep,name=config_map,json=configMap,proto3" json:"config_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ConfigMap map[string]*AgentConfigFile `protobuf:"bytes,1,rep,name=config_map,json=configMap,proto3" json:"config_map,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentConfigMap) Reset() { *x = AgentConfigMap{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentConfigMap) String() string { @@ -3422,8 +3520,8 @@ func (x *AgentConfigMap) String() string { func (*AgentConfigMap) ProtoMessage() {} func (x *AgentConfigMap) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[35] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3435,7 +3533,7 @@ func (x *AgentConfigMap) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentConfigMap.ProtoReflect.Descriptor instead. func (*AgentConfigMap) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{33} + return file_opamp_proto_rawDescGZIP(), []int{35} } func (x *AgentConfigMap) GetConfigMap() map[string]*AgentConfigFile { @@ -3446,25 +3544,22 @@ func (x *AgentConfigMap) GetConfigMap() map[string]*AgentConfigFile { } type AgentConfigFile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Config file or section body. The content, format and encoding depends on the Agent // type. The content_type field may optionally describe the MIME type of the body. Body []byte `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` // Optional MIME Content-Type that describes what's in the body field, for // example "text/yaml". - ContentType string `protobuf:"bytes,2,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"` + ContentType string `protobuf:"bytes,2,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgentConfigFile) Reset() { *x = AgentConfigFile{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AgentConfigFile) String() string { @@ -3474,8 +3569,8 @@ func (x *AgentConfigFile) String() string { func (*AgentConfigFile) ProtoMessage() {} func (x *AgentConfigFile) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[36] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3487,7 +3582,7 @@ func (x *AgentConfigFile) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentConfigFile.ProtoReflect.Descriptor instead. func (*AgentConfigFile) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{34} + return file_opamp_proto_rawDescGZIP(), []int{36} } func (x *AgentConfigFile) GetBody() []byte { @@ -3505,24 +3600,21 @@ func (x *AgentConfigFile) GetContentType() string { } type CustomCapabilities struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A list of custom capabilities that are supported. Each capability is a reverse FQDN // with optional version information that uniquely identifies the custom capability // and should match a capability specified in a supported CustomMessage. // Status: [Development] - Capabilities []string `protobuf:"bytes,1,rep,name=capabilities,proto3" json:"capabilities,omitempty"` + Capabilities []string `protobuf:"bytes,1,rep,name=capabilities,proto3" json:"capabilities,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CustomCapabilities) Reset() { *x = CustomCapabilities{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CustomCapabilities) String() string { @@ -3532,8 +3624,8 @@ func (x *CustomCapabilities) String() string { func (*CustomCapabilities) ProtoMessage() {} func (x *CustomCapabilities) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[37] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3545,7 +3637,7 @@ func (x *CustomCapabilities) ProtoReflect() protoreflect.Message { // Deprecated: Use CustomCapabilities.ProtoReflect.Descriptor instead. func (*CustomCapabilities) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{35} + return file_opamp_proto_rawDescGZIP(), []int{37} } func (x *CustomCapabilities) GetCapabilities() []string { @@ -3556,10 +3648,7 @@ func (x *CustomCapabilities) GetCapabilities() []string { } type CustomMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // A reverse FQDN that uniquely identifies the capability and matches one of the // capabilities in the CustomCapabilities message. // Status: [Development] @@ -3572,16 +3661,16 @@ type CustomMessage struct { // Binary data of the message. The capability must specify the format of the contents // of the data for each custom message type it defines. // Status: [Development] - Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CustomMessage) Reset() { *x = CustomMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_opamp_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_opamp_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CustomMessage) String() string { @@ -3591,8 +3680,8 @@ func (x *CustomMessage) String() string { func (*CustomMessage) ProtoMessage() {} func (x *CustomMessage) ProtoReflect() protoreflect.Message { - mi := &file_opamp_proto_msgTypes[36] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_opamp_proto_msgTypes[38] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3604,7 +3693,7 @@ func (x *CustomMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use CustomMessage.ProtoReflect.Descriptor instead. func (*CustomMessage) Descriptor() ([]byte, []int) { - return file_opamp_proto_rawDescGZIP(), []int{36} + return file_opamp_proto_rawDescGZIP(), []int{38} } func (x *CustomMessage) GetCapability() string { @@ -3630,806 +3719,431 @@ func (x *CustomMessage) GetData() []byte { var File_opamp_proto protoreflect.FileDescriptor -var file_opamp_proto_rawDesc = []byte{ - 0x0a, 0x0b, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0e, 0x61, 0x6e, 0x79, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf6, 0x07, 0x0a, 0x0d, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x12, - 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, - 0x75, 0x6d, 0x12, 0x4a, 0x0a, 0x11, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, - 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x34, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x47, 0x0a, 0x10, 0x65, 0x66, 0x66, 0x65, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x51, 0x0a, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, 0x0f, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x47, 0x0a, - 0x10, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x0f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x66, 0x0a, 0x1b, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x19, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x52, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x53, 0x0a, 0x14, 0x61, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, - 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x63, - 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x22, 0x5e, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, - 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x22, 0x72, 0x0a, 0x1e, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x12, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x26, 0x0a, 0x12, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x10, 0x0a, 0x03, 0x63, 0x73, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, - 0x73, 0x72, 0x22, 0xd9, 0x01, 0x0a, 0x13, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x0a, 0x63, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, - 0x1a, 0x5c, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, - 0x02, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x5e, 0x0a, 0x11, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, - 0x2e, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, - 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x1a, 0x61, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x6d, - 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x05, 0x0a, 0x0d, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x12, 0x47, - 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x56, 0x0a, 0x13, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, - 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4d, 0x0a, 0x12, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, - 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x53, 0x0a, - 0x14, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x70, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, - 0x50, 0x0a, 0x13, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x12, 0x63, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0xeb, 0x02, 0x0a, 0x17, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, - 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x12, 0x34, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x05, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x22, 0xb1, 0x02, 0x0a, 0x1b, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, - 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x22, 0xcf, 0x03, 0x0a, 0x17, 0x4f, 0x74, 0x68, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, - 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x12, 0x5e, 0x0a, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x34, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x98, 0x02, 0x0a, 0x15, 0x54, 0x4c, 0x53, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x61, 0x5f, 0x70, 0x65, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x61, 0x50, - 0x65, 0x6d, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x1c, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x63, 0x61, 0x5f, - 0x63, 0x65, 0x72, 0x74, 0x73, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x18, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, - 0x61, 0x43, 0x65, 0x72, 0x74, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x6e, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1f, 0x0a, 0x0b, - 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, - 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, - 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, - 0x74, 0x65, 0x73, 0x22, 0x6a, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x10, - 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, - 0x12, 0x3d, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, - 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, - 0x38, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6f, 0x70, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x5e, 0x0a, 0x0e, 0x54, - 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x61, 0x43, 0x65, 0x72, 0x74, 0x22, 0x98, 0x04, 0x0a, 0x18, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x05, - 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x12, 0x49, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x5f, - 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x08, - 0x6f, 0x77, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x4c, 0x6f, 0x67, - 0x73, 0x12, 0x68, 0x0a, 0x11, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66, - 0x65, 0x72, 0x73, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x69, 0x0a, 0x15, 0x4f, - 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x08, - 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x48, 0x61, - 0x73, 0x68, 0x1a, 0x5a, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa1, - 0x01, 0x0a, 0x10, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x18, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 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, 0x31, 0x0a, 0x04, 0x66, - 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, - 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, - 0x73, 0x68, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x61, - 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0xb8, 0x01, 0x0a, 0x13, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, - 0x52, 0x09, 0x72, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x09, 0x0a, 0x07, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x43, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x61, 0x66, 0x74, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x72, 0x65, 0x74, 0x72, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x44, 0x0a, 0x14, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x18, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x22, 0xb5, 0x01, 0x0a, 0x10, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x16, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x1a, 0x6e, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x18, 0x6e, 0x6f, 0x6e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x93, 0x03, 0x0a, 0x0f, 0x43, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x18, 0x0a, - 0x07, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x06, 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x61, - 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x31, 0x0a, 0x15, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, - 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x12, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, - 0x6e, 0x6f, 0x12, 0x66, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x34, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x43, - 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x4d, 0x61, - 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, - 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x1a, 0x63, 0x0a, 0x17, 0x43, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x4d, 0x61, 0x70, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0x4d, 0x0a, 0x0f, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x4d, 0x61, 0x70, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x22, 0xab, - 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x39, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc3, 0x01, 0x0a, - 0x18, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x41, 0x0a, 0x1d, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3f, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6f, - 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, - 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0xa1, 0x02, 0x0a, 0x0f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x48, - 0x0a, 0x21, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1d, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x57, 0x0a, - 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x03, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x48, 0x61, - 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x34, - 0x0a, 0x16, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, - 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x4e, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x64, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, - 0x52, 0x0f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x73, 0x22, 0x7e, 0x0a, 0x16, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x77, 0x6e, - 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, - 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, - 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x16, 0x64, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x22, 0x3f, 0x0a, 0x13, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x77, 0x5f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0e, 0x6e, 0x65, 0x77, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x55, - 0x69, 0x64, 0x22, 0x69, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x4d, 0x61, 0x70, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x22, 0xb7, 0x01, - 0x0a, 0x0e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, - 0x12, 0x49, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, - 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x1a, 0x5a, 0x0a, 0x0e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x48, 0x0a, 0x0f, 0x41, 0x67, 0x65, 0x6e, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x21, - 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x22, 0x38, 0x0a, 0x12, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x57, 0x0a, 0x0d, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x2a, 0x63, 0x0a, 0x12, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x5f, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x29, - 0x0a, 0x25, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x10, 0x01, 0x2a, 0x92, 0x01, 0x0a, 0x12, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0x01, 0x12, 0x30, 0x0a, 0x2c, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x10, 0x02, 0x2a, 0xf7, - 0x02, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x55, 0x6e, 0x73, 0x70, - 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, - 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x01, 0x12, - 0x29, 0x0a, 0x25, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x02, 0x12, 0x2d, 0x0a, 0x29, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x04, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, - 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x10, 0x08, - 0x12, 0x2c, 0x0a, 0x28, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x10, 0x12, 0x2f, - 0x0a, 0x2b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x5f, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x20, 0x12, - 0x37, 0x0a, 0x33, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x40, 0x2a, 0x3e, 0x0a, 0x0b, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x6f, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x10, - 0x00, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x5f, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x10, 0x01, 0x2a, 0x8f, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, - 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, - 0x01, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x61, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x2a, 0x26, 0x0a, 0x0b, 0x43, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x10, 0x00, 0x2a, 0x85, 0x06, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x55, 0x6e, - 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x01, - 0x12, 0x29, 0x0a, 0x25, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x52, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x04, 0x12, 0x25, 0x0a, 0x21, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x10, 0x08, - 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x10, 0x10, 0x12, 0x26, - 0x0a, 0x22, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x54, 0x72, - 0x61, 0x63, 0x65, 0x73, 0x10, 0x20, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x10, 0x40, 0x12, - 0x25, 0x0a, 0x20, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x4c, - 0x6f, 0x67, 0x73, 0x10, 0x80, 0x01, 0x12, 0x35, 0x0a, 0x30, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x73, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x80, 0x02, 0x12, 0x35, 0x0a, - 0x30, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x10, 0x80, 0x04, 0x12, 0x2c, 0x0a, 0x27, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x10, - 0x80, 0x08, 0x12, 0x24, 0x0a, 0x1f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x10, 0x80, 0x10, 0x12, 0x2a, 0x0a, 0x25, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x10, 0x80, 0x20, 0x12, 0x27, 0x0a, 0x22, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x10, 0x80, 0x40, 0x12, 0x32, 0x0a, - 0x2c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x10, 0x80, 0x80, - 0x01, 0x12, 0x37, 0x0a, 0x31, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x80, 0x80, 0x02, 0x2a, 0xba, 0x01, 0x0a, 0x1a, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x20, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x55, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x00, 0x12, - 0x26, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x41, 0x50, - 0x50, 0x4c, 0x49, 0x45, 0x44, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x59, 0x49, 0x4e, 0x47, 0x10, 0x02, - 0x12, 0x25, 0x0a, 0x21, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x9c, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, - 0x12, 0x1e, 0x0a, 0x1a, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x55, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x00, - 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x59, - 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x2a, 0xc4, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x1f, 0x0a, 0x1b, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, - 0x6d, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x24, 0x0a, - 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, - 0x75, 0x6d, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x03, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x5f, - 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x04, 0x42, 0x2e, 0x5a, - 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, - 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2f, 0x6f, 0x70, 0x61, 0x6d, 0x70, - 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_opamp_proto_rawDesc = "" + + "\n" + + "\vopamp.proto\x12\x0eopamp.proto.v1\x1a\x0eanyvalue.proto\"\x97\b\n" + + "\rAgentToServer\x12!\n" + + "\finstance_uid\x18\x01 \x01(\fR\vinstanceUid\x12!\n" + + "\fsequence_num\x18\x02 \x01(\x04R\vsequenceNum\x12M\n" + + "\x11agent_description\x18\x03 \x01(\v2 .opamp.proto.v1.AgentDescriptionR\x10agentDescription\x12\"\n" + + "\fcapabilities\x18\x04 \x01(\x04R\fcapabilities\x127\n" + + "\x06health\x18\x05 \x01(\v2\x1f.opamp.proto.v1.ComponentHealthR\x06health\x12J\n" + + "\x10effective_config\x18\x06 \x01(\v2\x1f.opamp.proto.v1.EffectiveConfigR\x0feffectiveConfig\x12T\n" + + "\x14remote_config_status\x18\a \x01(\v2\".opamp.proto.v1.RemoteConfigStatusR\x12remoteConfigStatus\x12J\n" + + "\x10package_statuses\x18\b \x01(\v2\x1f.opamp.proto.v1.PackageStatusesR\x0fpackageStatuses\x12J\n" + + "\x10agent_disconnect\x18\t \x01(\v2\x1f.opamp.proto.v1.AgentDisconnectR\x0fagentDisconnect\x12\x14\n" + + "\x05flags\x18\n" + + " \x01(\x04R\x05flags\x12i\n" + + "\x1bconnection_settings_request\x18\v \x01(\v2).opamp.proto.v1.ConnectionSettingsRequestR\x19connectionSettingsRequest\x12S\n" + + "\x13custom_capabilities\x18\f \x01(\v2\".opamp.proto.v1.CustomCapabilitiesR\x12customCapabilities\x12D\n" + + "\x0ecustom_message\x18\r \x01(\v2\x1d.opamp.proto.v1.CustomMessageR\rcustomMessage\x12V\n" + + "\x14available_components\x18\x0e \x01(\v2#.opamp.proto.v1.AvailableComponentsR\x13availableComponents\x12f\n" + + "\x1aconnection_settings_status\x18\x0f \x01(\v2(.opamp.proto.v1.ConnectionSettingsStatusR\x18connectionSettingsStatus\"\x11\n" + + "\x0fAgentDisconnect\"a\n" + + "\x19ConnectionSettingsRequest\x12D\n" + + "\x05opamp\x18\x01 \x01(\v2..opamp.proto.v1.OpAMPConnectionSettingsRequestR\x05opamp\"u\n" + + "\x1eOpAMPConnectionSettingsRequest\x12S\n" + + "\x13certificate_request\x18\x01 \x01(\v2\".opamp.proto.v1.CertificateRequestR\x12certificateRequest\"&\n" + + "\x12CertificateRequest\x12\x10\n" + + "\x03csr\x18\x01 \x01(\fR\x03csr\"\xdf\x01\n" + + "\x13AvailableComponents\x12S\n" + + "\n" + + "components\x18\x01 \x03(\v23.opamp.proto.v1.AvailableComponents.ComponentsEntryR\n" + + "components\x12\x12\n" + + "\x04hash\x18\x02 \x01(\fR\x04hash\x1a_\n" + + "\x0fComponentsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x126\n" + + "\x05value\x18\x02 \x01(\v2 .opamp.proto.v1.ComponentDetailsR\x05value:\x028\x01\"\x91\x02\n" + + "\x10ComponentDetails\x124\n" + + "\bmetadata\x18\x01 \x03(\v2\x18.opamp.proto.v1.KeyValueR\bmetadata\x12a\n" + + "\x11sub_component_map\x18\x02 \x03(\v25.opamp.proto.v1.ComponentDetails.SubComponentMapEntryR\x0fsubComponentMap\x1ad\n" + + "\x14SubComponentMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x126\n" + + "\x05value\x18\x02 \x01(\v2 .opamp.proto.v1.ComponentDetailsR\x05value:\x028\x01\"\xa8\x06\n" + + "\rServerToAgent\x12!\n" + + "\finstance_uid\x18\x01 \x01(\fR\vinstanceUid\x12J\n" + + "\x0eerror_response\x18\x02 \x01(\v2#.opamp.proto.v1.ServerErrorResponseR\rerrorResponse\x12F\n" + + "\rremote_config\x18\x03 \x01(\v2!.opamp.proto.v1.AgentRemoteConfigR\fremoteConfig\x12Y\n" + + "\x13connection_settings\x18\x04 \x01(\v2(.opamp.proto.v1.ConnectionSettingsOffersR\x12connectionSettings\x12P\n" + + "\x12packages_available\x18\x05 \x01(\v2!.opamp.proto.v1.PackagesAvailableR\x11packagesAvailable\x12\x14\n" + + "\x05flags\x18\x06 \x01(\x04R\x05flags\x12\"\n" + + "\fcapabilities\x18\a \x01(\x04R\fcapabilities\x12V\n" + + "\x14agent_identification\x18\b \x01(\v2#.opamp.proto.v1.AgentIdentificationR\x13agentIdentification\x12>\n" + + "\acommand\x18\t \x01(\v2$.opamp.proto.v1.ServerToAgentCommandR\acommand\x12S\n" + + "\x13custom_capabilities\x18\n" + + " \x01(\v2\".opamp.proto.v1.CustomCapabilitiesR\x12customCapabilities\x12D\n" + + "\x0ecustom_message\x18\v \x01(\v2\x1d.opamp.proto.v1.CustomMessageR\rcustomMessageJ\x04\b\f\x10\rJ\x04\b\r\x10\x0eJ\x04\b\x0e\x10\x0fJ\x04\b\x0f\x10\x10J\x04\b\x10\x10\x11R\x14trust_chain_responseR\tsignatureR\apayload\"\x92\x01\n" + + "\x12TrustChainResponse\x12+\n" + + "\x11certificate_chain\x18\x01 \x01(\fR\x10certificateChain\x12#\n" + + "\rerror_message\x18\x02 \x01(\tR\ferrorMessage\x12*\n" + + "\x11tofu_trust_anchor\x18\x03 \x01(\fR\x0ftofuTrustAnchor\"\xa3\x01\n" + + "\x13SignedServerToAgent\x12\x18\n" + + "\apayload\x18\x0e \x01(\fR\apayload\x12\x1c\n" + + "\tsignature\x18\x0f \x01(\fR\tsignature\x12T\n" + + "\x14trust_chain_response\x18\x10 \x01(\v2\".opamp.proto.v1.TrustChainResponseR\x12trustChainResponse\"\xf7\x02\n" + + "\x17OpAMPConnectionSettings\x121\n" + + "\x14destination_endpoint\x18\x01 \x01(\tR\x13destinationEndpoint\x121\n" + + "\aheaders\x18\x02 \x01(\v2\x17.opamp.proto.v1.HeadersR\aheaders\x12@\n" + + "\vcertificate\x18\x03 \x01(\v2\x1e.opamp.proto.v1.TLSCertificateR\vcertificate\x12<\n" + + "\x1aheartbeat_interval_seconds\x18\x04 \x01(\x04R\x18heartbeatIntervalSeconds\x127\n" + + "\x03tls\x18\x05 \x01(\v2%.opamp.proto.v1.TLSConnectionSettingsR\x03tls\x12=\n" + + "\x05proxy\x18\x06 \x01(\v2'.opamp.proto.v1.ProxyConnectionSettingsR\x05proxy\"\xbd\x02\n" + + "\x1bTelemetryConnectionSettings\x121\n" + + "\x14destination_endpoint\x18\x01 \x01(\tR\x13destinationEndpoint\x121\n" + + "\aheaders\x18\x02 \x01(\v2\x17.opamp.proto.v1.HeadersR\aheaders\x12@\n" + + "\vcertificate\x18\x03 \x01(\v2\x1e.opamp.proto.v1.TLSCertificateR\vcertificate\x127\n" + + "\x03tls\x18\x04 \x01(\v2%.opamp.proto.v1.TLSConnectionSettingsR\x03tls\x12=\n" + + "\x05proxy\x18\x05 \x01(\v2'.opamp.proto.v1.ProxyConnectionSettingsR\x05proxy\"\xde\x03\n" + + "\x17OtherConnectionSettings\x121\n" + + "\x14destination_endpoint\x18\x01 \x01(\tR\x13destinationEndpoint\x121\n" + + "\aheaders\x18\x02 \x01(\v2\x17.opamp.proto.v1.HeadersR\aheaders\x12@\n" + + "\vcertificate\x18\x03 \x01(\v2\x1e.opamp.proto.v1.TLSCertificateR\vcertificate\x12a\n" + + "\x0eother_settings\x18\x04 \x03(\v2:.opamp.proto.v1.OtherConnectionSettings.OtherSettingsEntryR\rotherSettings\x127\n" + + "\x03tls\x18\x05 \x01(\v2%.opamp.proto.v1.TLSConnectionSettingsR\x03tls\x12=\n" + + "\x05proxy\x18\x06 \x01(\v2'.opamp.proto.v1.ProxyConnectionSettingsR\x05proxy\x1a@\n" + + "\x12OtherSettingsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x98\x02\n" + + "\x15TLSConnectionSettings\x12&\n" + + "\x0fca_pem_contents\x18\x01 \x01(\tR\rcaPemContents\x12>\n" + + "\x1cinclude_system_ca_certs_pool\x18\x02 \x01(\bR\x18includeSystemCaCertsPool\x120\n" + + "\x14insecure_skip_verify\x18\x03 \x01(\bR\x12insecureSkipVerify\x12\x1f\n" + + "\vmin_version\x18\x04 \x01(\tR\n" + + "minVersion\x12\x1f\n" + + "\vmax_version\x18\x05 \x01(\tR\n" + + "maxVersion\x12#\n" + + "\rcipher_suites\x18\x06 \x03(\tR\fcipherSuites\"m\n" + + "\x17ProxyConnectionSettings\x12\x10\n" + + "\x03url\x18\x01 \x01(\tR\x03url\x12@\n" + + "\x0fconnect_headers\x18\x02 \x01(\v2\x17.opamp.proto.v1.HeadersR\x0econnectHeaders\";\n" + + "\aHeaders\x120\n" + + "\aheaders\x18\x01 \x03(\v2\x16.opamp.proto.v1.HeaderR\aheaders\"0\n" + + "\x06Header\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value\"^\n" + + "\x0eTLSCertificate\x12\x12\n" + + "\x04cert\x18\x01 \x01(\fR\x04cert\x12\x1f\n" + + "\vprivate_key\x18\x02 \x01(\fR\n" + + "privateKey\x12\x17\n" + + "\aca_cert\x18\x03 \x01(\fR\x06caCert\"\xaa\x04\n" + + "\x18ConnectionSettingsOffers\x12\x12\n" + + "\x04hash\x18\x01 \x01(\fR\x04hash\x12=\n" + + "\x05opamp\x18\x02 \x01(\v2'.opamp.proto.v1.OpAMPConnectionSettingsR\x05opamp\x12L\n" + + "\vown_metrics\x18\x03 \x01(\v2+.opamp.proto.v1.TelemetryConnectionSettingsR\n" + + "ownMetrics\x12J\n" + + "\n" + + "own_traces\x18\x04 \x01(\v2+.opamp.proto.v1.TelemetryConnectionSettingsR\townTraces\x12F\n" + + "\bown_logs\x18\x05 \x01(\v2+.opamp.proto.v1.TelemetryConnectionSettingsR\aownLogs\x12k\n" + + "\x11other_connections\x18\x06 \x03(\v2>.opamp.proto.v1.ConnectionSettingsOffers.OtherConnectionsEntryR\x10otherConnections\x1al\n" + + "\x15OtherConnectionsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12=\n" + + "\x05value\x18\x02 \x01(\v2'.opamp.proto.v1.OtherConnectionSettingsR\x05value:\x028\x01\"\xeb\x01\n" + + "\x11PackagesAvailable\x12K\n" + + "\bpackages\x18\x01 \x03(\v2/.opamp.proto.v1.PackagesAvailable.PackagesEntryR\bpackages\x12*\n" + + "\x11all_packages_hash\x18\x02 \x01(\fR\x0fallPackagesHash\x1a]\n" + + "\rPackagesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x126\n" + + "\x05value\x18\x02 \x01(\v2 .opamp.proto.v1.PackageAvailableR\x05value:\x028\x01\"\xa7\x01\n" + + "\x10PackageAvailable\x12/\n" + + "\x04type\x18\x01 \x01(\x0e2\x1b.opamp.proto.v1.PackageTypeR\x04type\x12\x18\n" + + "\aversion\x18\x02 \x01(\tR\aversion\x124\n" + + "\x04file\x18\x03 \x01(\v2 .opamp.proto.v1.DownloadableFileR\x04file\x12\x12\n" + + "\x04hash\x18\x04 \x01(\fR\x04hash\"\xa9\x01\n" + + "\x10DownloadableFile\x12!\n" + + "\fdownload_url\x18\x01 \x01(\tR\vdownloadUrl\x12!\n" + + "\fcontent_hash\x18\x02 \x01(\fR\vcontentHash\x12\x1c\n" + + "\tsignature\x18\x03 \x01(\fR\tsignature\x121\n" + + "\aheaders\x18\x04 \x01(\v2\x17.opamp.proto.v1.HeadersR\aheaders\"\xbe\x01\n" + + "\x13ServerErrorResponse\x12;\n" + + "\x04type\x18\x01 \x01(\x0e2'.opamp.proto.v1.ServerErrorResponseTypeR\x04type\x12#\n" + + "\rerror_message\x18\x02 \x01(\tR\ferrorMessage\x12:\n" + + "\n" + + "retry_info\x18\x03 \x01(\v2\x19.opamp.proto.v1.RetryInfoH\x00R\tretryInfoB\t\n" + + "\aDetails\"C\n" + + "\tRetryInfo\x126\n" + + "\x17retry_after_nanoseconds\x18\x01 \x01(\x04R\x15retryAfterNanoseconds\"G\n" + + "\x14ServerToAgentCommand\x12/\n" + + "\x04type\x18\x01 \x01(\x0e2\x1b.opamp.proto.v1.CommandTypeR\x04type\"\xbb\x01\n" + + "\x10AgentDescription\x12O\n" + + "\x16identifying_attributes\x18\x01 \x03(\v2\x18.opamp.proto.v1.KeyValueR\x15identifyingAttributes\x12V\n" + + "\x1anon_identifying_attributes\x18\x02 \x03(\v2\x18.opamp.proto.v1.KeyValueR\x18nonIdentifyingAttributes\"\x99\x03\n" + + "\x0fComponentHealth\x12\x18\n" + + "\ahealthy\x18\x01 \x01(\bR\ahealthy\x12/\n" + + "\x14start_time_unix_nano\x18\x02 \x01(\x06R\x11startTimeUnixNano\x12\x1d\n" + + "\n" + + "last_error\x18\x03 \x01(\tR\tlastError\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x121\n" + + "\x15status_time_unix_nano\x18\x05 \x01(\x06R\x12statusTimeUnixNano\x12i\n" + + "\x14component_health_map\x18\x06 \x03(\v27.opamp.proto.v1.ComponentHealth.ComponentHealthMapEntryR\x12componentHealthMap\x1af\n" + + "\x17ComponentHealthMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x125\n" + + "\x05value\x18\x02 \x01(\v2\x1f.opamp.proto.v1.ComponentHealthR\x05value:\x028\x01\"P\n" + + "\x0fEffectiveConfig\x12=\n" + + "\n" + + "config_map\x18\x01 \x01(\v2\x1e.opamp.proto.v1.AgentConfigMapR\tconfigMap\"\xae\x01\n" + + "\x12RemoteConfigStatus\x125\n" + + "\x17last_remote_config_hash\x18\x01 \x01(\fR\x14lastRemoteConfigHash\x12<\n" + + "\x06status\x18\x02 \x01(\x0e2$.opamp.proto.v1.RemoteConfigStatusesR\x06status\x12#\n" + + "\rerror_message\x18\x03 \x01(\tR\ferrorMessage\"\xc6\x01\n" + + "\x18ConnectionSettingsStatus\x12A\n" + + "\x1dlast_connection_settings_hash\x18\x01 \x01(\fR\x1alastConnectionSettingsHash\x12B\n" + + "\x06status\x18\x02 \x01(\x0e2*.opamp.proto.v1.ConnectionSettingsStatusesR\x06status\x12#\n" + + "\rerror_message\x18\x03 \x01(\tR\ferrorMessage\"\xa7\x02\n" + + "\x0fPackageStatuses\x12I\n" + + "\bpackages\x18\x01 \x03(\v2-.opamp.proto.v1.PackageStatuses.PackagesEntryR\bpackages\x12H\n" + + "!server_provided_all_packages_hash\x18\x02 \x01(\fR\x1dserverProvidedAllPackagesHash\x12#\n" + + "\rerror_message\x18\x03 \x01(\tR\ferrorMessage\x1aZ\n" + + "\rPackagesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x123\n" + + "\x05value\x18\x02 \x01(\v2\x1d.opamp.proto.v1.PackageStatusR\x05value:\x028\x01\"\x8e\x03\n" + + "\rPackageStatus\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12*\n" + + "\x11agent_has_version\x18\x02 \x01(\tR\x0fagentHasVersion\x12$\n" + + "\x0eagent_has_hash\x18\x03 \x01(\fR\fagentHasHash\x124\n" + + "\x16server_offered_version\x18\x04 \x01(\tR\x14serverOfferedVersion\x12.\n" + + "\x13server_offered_hash\x18\x05 \x01(\fR\x11serverOfferedHash\x129\n" + + "\x06status\x18\x06 \x01(\x0e2!.opamp.proto.v1.PackageStatusEnumR\x06status\x12#\n" + + "\rerror_message\x18\a \x01(\tR\ferrorMessage\x12Q\n" + + "\x10download_details\x18\b \x01(\v2&.opamp.proto.v1.PackageDownloadDetailsR\x0fdownloadDetails\"~\n" + + "\x16PackageDownloadDetails\x12)\n" + + "\x10download_percent\x18\x01 \x01(\x01R\x0fdownloadPercent\x129\n" + + "\x19download_bytes_per_second\x18\x02 \x01(\x01R\x16downloadBytesPerSecond\"?\n" + + "\x13AgentIdentification\x12(\n" + + "\x10new_instance_uid\x18\x01 \x01(\fR\x0enewInstanceUid\"l\n" + + "\x11AgentRemoteConfig\x126\n" + + "\x06config\x18\x01 \x01(\v2\x1e.opamp.proto.v1.AgentConfigMapR\x06config\x12\x1f\n" + + "\vconfig_hash\x18\x02 \x01(\fR\n" + + "configHash\"\xbd\x01\n" + + "\x0eAgentConfigMap\x12L\n" + + "\n" + + "config_map\x18\x01 \x03(\v2-.opamp.proto.v1.AgentConfigMap.ConfigMapEntryR\tconfigMap\x1a]\n" + + "\x0eConfigMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x125\n" + + "\x05value\x18\x02 \x01(\v2\x1f.opamp.proto.v1.AgentConfigFileR\x05value:\x028\x01\"H\n" + + "\x0fAgentConfigFile\x12\x12\n" + + "\x04body\x18\x01 \x01(\fR\x04body\x12!\n" + + "\fcontent_type\x18\x02 \x01(\tR\vcontentType\"8\n" + + "\x12CustomCapabilities\x12\"\n" + + "\fcapabilities\x18\x01 \x03(\tR\fcapabilities\"W\n" + + "\rCustomMessage\x12\x1e\n" + + "\n" + + "capability\x18\x01 \x01(\tR\n" + + "capability\x12\x12\n" + + "\x04type\x18\x02 \x01(\tR\x04type\x12\x12\n" + + "\x04data\x18\x03 \x01(\fR\x04data*c\n" + + "\x12AgentToServerFlags\x12\"\n" + + "\x1eAgentToServerFlags_Unspecified\x10\x00\x12)\n" + + "%AgentToServerFlags_RequestInstanceUid\x10\x01*\x92\x01\n" + + "\x12ServerToAgentFlags\x12\"\n" + + "\x1eServerToAgentFlags_Unspecified\x10\x00\x12&\n" + + "\"ServerToAgentFlags_ReportFullState\x10\x01\x120\n" + + ",ServerToAgentFlags_ReportAvailableComponents\x10\x02*\xaf\x03\n" + + "\x12ServerCapabilities\x12\"\n" + + "\x1eServerCapabilities_Unspecified\x10\x00\x12$\n" + + " ServerCapabilities_AcceptsStatus\x10\x01\x12)\n" + + "%ServerCapabilities_OffersRemoteConfig\x10\x02\x12-\n" + + ")ServerCapabilities_AcceptsEffectiveConfig\x10\x04\x12%\n" + + "!ServerCapabilities_OffersPackages\x10\b\x12,\n" + + "(ServerCapabilities_AcceptsPackagesStatus\x10\x10\x12/\n" + + "+ServerCapabilities_OffersConnectionSettings\x10 \x127\n" + + "3ServerCapabilities_AcceptsConnectionSettingsRequest\x10@\x126\n" + + "1ServerCapabilities_OffersPayloadTrustVerification\x10\x80\x01*>\n" + + "\vPackageType\x12\x18\n" + + "\x14PackageType_TopLevel\x10\x00\x12\x15\n" + + "\x11PackageType_Addon\x10\x01*\x8f\x01\n" + + "\x17ServerErrorResponseType\x12#\n" + + "\x1fServerErrorResponseType_Unknown\x10\x00\x12&\n" + + "\"ServerErrorResponseType_BadRequest\x10\x01\x12'\n" + + "#ServerErrorResponseType_Unavailable\x10\x02*&\n" + + "\vCommandType\x12\x17\n" + + "\x13CommandType_Restart\x10\x00*\xf6\x06\n" + + "\x11AgentCapabilities\x12!\n" + + "\x1dAgentCapabilities_Unspecified\x10\x00\x12#\n" + + "\x1fAgentCapabilities_ReportsStatus\x10\x01\x12)\n" + + "%AgentCapabilities_AcceptsRemoteConfig\x10\x02\x12,\n" + + "(AgentCapabilities_ReportsEffectiveConfig\x10\x04\x12%\n" + + "!AgentCapabilities_AcceptsPackages\x10\b\x12,\n" + + "(AgentCapabilities_ReportsPackageStatuses\x10\x10\x12&\n" + + "\"AgentCapabilities_ReportsOwnTraces\x10 \x12'\n" + + "#AgentCapabilities_ReportsOwnMetrics\x10@\x12%\n" + + " AgentCapabilities_ReportsOwnLogs\x10\x80\x01\x125\n" + + "0AgentCapabilities_AcceptsOpAMPConnectionSettings\x10\x80\x02\x125\n" + + "0AgentCapabilities_AcceptsOtherConnectionSettings\x10\x80\x04\x12,\n" + + "'AgentCapabilities_AcceptsRestartCommand\x10\x80\b\x12$\n" + + "\x1fAgentCapabilities_ReportsHealth\x10\x80\x10\x12*\n" + + "%AgentCapabilities_ReportsRemoteConfig\x10\x80 \x12'\n" + + "\"AgentCapabilities_ReportsHeartbeat\x10\x80@\x122\n" + + ",AgentCapabilities_ReportsAvailableComponents\x10\x80\x80\x01\x127\n" + + "1AgentCapabilities_ReportsConnectionSettingsStatus\x10\x80\x80\x02\x128\n" + + "2AgentCapabilities_RequiresPayloadTrustVerification\x10\x80\x80\x04\x125\n" + + "/AgentCapabilities_AcceptsPayloadTrustAnchorTOFU\x10\x80\x80\b*\xba\x01\n" + + "\x1aConnectionSettingsStatuses\x12$\n" + + " ConnectionSettingsStatuses_UNSET\x10\x00\x12&\n" + + "\"ConnectionSettingsStatuses_APPLIED\x10\x01\x12'\n" + + "#ConnectionSettingsStatuses_APPLYING\x10\x02\x12%\n" + + "!ConnectionSettingsStatuses_FAILED\x10\x03*\x9c\x01\n" + + "\x14RemoteConfigStatuses\x12\x1e\n" + + "\x1aRemoteConfigStatuses_UNSET\x10\x00\x12 \n" + + "\x1cRemoteConfigStatuses_APPLIED\x10\x01\x12!\n" + + "\x1dRemoteConfigStatuses_APPLYING\x10\x02\x12\x1f\n" + + "\x1bRemoteConfigStatuses_FAILED\x10\x03*\xc4\x01\n" + + "\x11PackageStatusEnum\x12\x1f\n" + + "\x1bPackageStatusEnum_Installed\x10\x00\x12$\n" + + " PackageStatusEnum_InstallPending\x10\x01\x12 \n" + + "\x1cPackageStatusEnum_Installing\x10\x02\x12#\n" + + "\x1fPackageStatusEnum_InstallFailed\x10\x03\x12!\n" + + "\x1dPackageStatusEnum_Downloading\x10\x04B?Z,github.com/open-telemetry/opamp-go/protobufs\xaa\x02\x0eOpAmp.Proto.V1b\x06proto3" var ( file_opamp_proto_rawDescOnce sync.Once - file_opamp_proto_rawDescData = file_opamp_proto_rawDesc + file_opamp_proto_rawDescData []byte ) func file_opamp_proto_rawDescGZIP() []byte { file_opamp_proto_rawDescOnce.Do(func() { - file_opamp_proto_rawDescData = protoimpl.X.CompressGZIP(file_opamp_proto_rawDescData) + file_opamp_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_opamp_proto_rawDesc), len(file_opamp_proto_rawDesc))) }) return file_opamp_proto_rawDescData } var file_opamp_proto_enumTypes = make([]protoimpl.EnumInfo, 10) -var file_opamp_proto_msgTypes = make([]protoimpl.MessageInfo, 45) -var file_opamp_proto_goTypes = []interface{}{ - (AgentToServerFlags)(0), // 0: opamp.proto.AgentToServerFlags - (ServerToAgentFlags)(0), // 1: opamp.proto.ServerToAgentFlags - (ServerCapabilities)(0), // 2: opamp.proto.ServerCapabilities - (PackageType)(0), // 3: opamp.proto.PackageType - (ServerErrorResponseType)(0), // 4: opamp.proto.ServerErrorResponseType - (CommandType)(0), // 5: opamp.proto.CommandType - (AgentCapabilities)(0), // 6: opamp.proto.AgentCapabilities - (ConnectionSettingsStatuses)(0), // 7: opamp.proto.ConnectionSettingsStatuses - (RemoteConfigStatuses)(0), // 8: opamp.proto.RemoteConfigStatuses - (PackageStatusEnum)(0), // 9: opamp.proto.PackageStatusEnum - (*AgentToServer)(nil), // 10: opamp.proto.AgentToServer - (*AgentDisconnect)(nil), // 11: opamp.proto.AgentDisconnect - (*ConnectionSettingsRequest)(nil), // 12: opamp.proto.ConnectionSettingsRequest - (*OpAMPConnectionSettingsRequest)(nil), // 13: opamp.proto.OpAMPConnectionSettingsRequest - (*CertificateRequest)(nil), // 14: opamp.proto.CertificateRequest - (*AvailableComponents)(nil), // 15: opamp.proto.AvailableComponents - (*ComponentDetails)(nil), // 16: opamp.proto.ComponentDetails - (*ServerToAgent)(nil), // 17: opamp.proto.ServerToAgent - (*OpAMPConnectionSettings)(nil), // 18: opamp.proto.OpAMPConnectionSettings - (*TelemetryConnectionSettings)(nil), // 19: opamp.proto.TelemetryConnectionSettings - (*OtherConnectionSettings)(nil), // 20: opamp.proto.OtherConnectionSettings - (*TLSConnectionSettings)(nil), // 21: opamp.proto.TLSConnectionSettings - (*ProxyConnectionSettings)(nil), // 22: opamp.proto.ProxyConnectionSettings - (*Headers)(nil), // 23: opamp.proto.Headers - (*Header)(nil), // 24: opamp.proto.Header - (*TLSCertificate)(nil), // 25: opamp.proto.TLSCertificate - (*ConnectionSettingsOffers)(nil), // 26: opamp.proto.ConnectionSettingsOffers - (*PackagesAvailable)(nil), // 27: opamp.proto.PackagesAvailable - (*PackageAvailable)(nil), // 28: opamp.proto.PackageAvailable - (*DownloadableFile)(nil), // 29: opamp.proto.DownloadableFile - (*ServerErrorResponse)(nil), // 30: opamp.proto.ServerErrorResponse - (*RetryInfo)(nil), // 31: opamp.proto.RetryInfo - (*ServerToAgentCommand)(nil), // 32: opamp.proto.ServerToAgentCommand - (*AgentDescription)(nil), // 33: opamp.proto.AgentDescription - (*ComponentHealth)(nil), // 34: opamp.proto.ComponentHealth - (*EffectiveConfig)(nil), // 35: opamp.proto.EffectiveConfig - (*RemoteConfigStatus)(nil), // 36: opamp.proto.RemoteConfigStatus - (*ConnectionSettingsStatus)(nil), // 37: opamp.proto.ConnectionSettingsStatus - (*PackageStatuses)(nil), // 38: opamp.proto.PackageStatuses - (*PackageStatus)(nil), // 39: opamp.proto.PackageStatus - (*PackageDownloadDetails)(nil), // 40: opamp.proto.PackageDownloadDetails - (*AgentIdentification)(nil), // 41: opamp.proto.AgentIdentification - (*AgentRemoteConfig)(nil), // 42: opamp.proto.AgentRemoteConfig - (*AgentConfigMap)(nil), // 43: opamp.proto.AgentConfigMap - (*AgentConfigFile)(nil), // 44: opamp.proto.AgentConfigFile - (*CustomCapabilities)(nil), // 45: opamp.proto.CustomCapabilities - (*CustomMessage)(nil), // 46: opamp.proto.CustomMessage - nil, // 47: opamp.proto.AvailableComponents.ComponentsEntry - nil, // 48: opamp.proto.ComponentDetails.SubComponentMapEntry - nil, // 49: opamp.proto.OtherConnectionSettings.OtherSettingsEntry - nil, // 50: opamp.proto.ConnectionSettingsOffers.OtherConnectionsEntry - nil, // 51: opamp.proto.PackagesAvailable.PackagesEntry - nil, // 52: opamp.proto.ComponentHealth.ComponentHealthMapEntry - nil, // 53: opamp.proto.PackageStatuses.PackagesEntry - nil, // 54: opamp.proto.AgentConfigMap.ConfigMapEntry - (*KeyValue)(nil), // 55: opamp.proto.KeyValue +var file_opamp_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_opamp_proto_goTypes = []any{ + (AgentToServerFlags)(0), // 0: opamp.proto.v1.AgentToServerFlags + (ServerToAgentFlags)(0), // 1: opamp.proto.v1.ServerToAgentFlags + (ServerCapabilities)(0), // 2: opamp.proto.v1.ServerCapabilities + (PackageType)(0), // 3: opamp.proto.v1.PackageType + (ServerErrorResponseType)(0), // 4: opamp.proto.v1.ServerErrorResponseType + (CommandType)(0), // 5: opamp.proto.v1.CommandType + (AgentCapabilities)(0), // 6: opamp.proto.v1.AgentCapabilities + (ConnectionSettingsStatuses)(0), // 7: opamp.proto.v1.ConnectionSettingsStatuses + (RemoteConfigStatuses)(0), // 8: opamp.proto.v1.RemoteConfigStatuses + (PackageStatusEnum)(0), // 9: opamp.proto.v1.PackageStatusEnum + (*AgentToServer)(nil), // 10: opamp.proto.v1.AgentToServer + (*AgentDisconnect)(nil), // 11: opamp.proto.v1.AgentDisconnect + (*ConnectionSettingsRequest)(nil), // 12: opamp.proto.v1.ConnectionSettingsRequest + (*OpAMPConnectionSettingsRequest)(nil), // 13: opamp.proto.v1.OpAMPConnectionSettingsRequest + (*CertificateRequest)(nil), // 14: opamp.proto.v1.CertificateRequest + (*AvailableComponents)(nil), // 15: opamp.proto.v1.AvailableComponents + (*ComponentDetails)(nil), // 16: opamp.proto.v1.ComponentDetails + (*ServerToAgent)(nil), // 17: opamp.proto.v1.ServerToAgent + (*TrustChainResponse)(nil), // 18: opamp.proto.v1.TrustChainResponse + (*SignedServerToAgent)(nil), // 19: opamp.proto.v1.SignedServerToAgent + (*OpAMPConnectionSettings)(nil), // 20: opamp.proto.v1.OpAMPConnectionSettings + (*TelemetryConnectionSettings)(nil), // 21: opamp.proto.v1.TelemetryConnectionSettings + (*OtherConnectionSettings)(nil), // 22: opamp.proto.v1.OtherConnectionSettings + (*TLSConnectionSettings)(nil), // 23: opamp.proto.v1.TLSConnectionSettings + (*ProxyConnectionSettings)(nil), // 24: opamp.proto.v1.ProxyConnectionSettings + (*Headers)(nil), // 25: opamp.proto.v1.Headers + (*Header)(nil), // 26: opamp.proto.v1.Header + (*TLSCertificate)(nil), // 27: opamp.proto.v1.TLSCertificate + (*ConnectionSettingsOffers)(nil), // 28: opamp.proto.v1.ConnectionSettingsOffers + (*PackagesAvailable)(nil), // 29: opamp.proto.v1.PackagesAvailable + (*PackageAvailable)(nil), // 30: opamp.proto.v1.PackageAvailable + (*DownloadableFile)(nil), // 31: opamp.proto.v1.DownloadableFile + (*ServerErrorResponse)(nil), // 32: opamp.proto.v1.ServerErrorResponse + (*RetryInfo)(nil), // 33: opamp.proto.v1.RetryInfo + (*ServerToAgentCommand)(nil), // 34: opamp.proto.v1.ServerToAgentCommand + (*AgentDescription)(nil), // 35: opamp.proto.v1.AgentDescription + (*ComponentHealth)(nil), // 36: opamp.proto.v1.ComponentHealth + (*EffectiveConfig)(nil), // 37: opamp.proto.v1.EffectiveConfig + (*RemoteConfigStatus)(nil), // 38: opamp.proto.v1.RemoteConfigStatus + (*ConnectionSettingsStatus)(nil), // 39: opamp.proto.v1.ConnectionSettingsStatus + (*PackageStatuses)(nil), // 40: opamp.proto.v1.PackageStatuses + (*PackageStatus)(nil), // 41: opamp.proto.v1.PackageStatus + (*PackageDownloadDetails)(nil), // 42: opamp.proto.v1.PackageDownloadDetails + (*AgentIdentification)(nil), // 43: opamp.proto.v1.AgentIdentification + (*AgentRemoteConfig)(nil), // 44: opamp.proto.v1.AgentRemoteConfig + (*AgentConfigMap)(nil), // 45: opamp.proto.v1.AgentConfigMap + (*AgentConfigFile)(nil), // 46: opamp.proto.v1.AgentConfigFile + (*CustomCapabilities)(nil), // 47: opamp.proto.v1.CustomCapabilities + (*CustomMessage)(nil), // 48: opamp.proto.v1.CustomMessage + nil, // 49: opamp.proto.v1.AvailableComponents.ComponentsEntry + nil, // 50: opamp.proto.v1.ComponentDetails.SubComponentMapEntry + nil, // 51: opamp.proto.v1.OtherConnectionSettings.OtherSettingsEntry + nil, // 52: opamp.proto.v1.ConnectionSettingsOffers.OtherConnectionsEntry + nil, // 53: opamp.proto.v1.PackagesAvailable.PackagesEntry + nil, // 54: opamp.proto.v1.ComponentHealth.ComponentHealthMapEntry + nil, // 55: opamp.proto.v1.PackageStatuses.PackagesEntry + nil, // 56: opamp.proto.v1.AgentConfigMap.ConfigMapEntry + (*KeyValue)(nil), // 57: opamp.proto.v1.KeyValue } var file_opamp_proto_depIdxs = []int32{ - 33, // 0: opamp.proto.AgentToServer.agent_description:type_name -> opamp.proto.AgentDescription - 34, // 1: opamp.proto.AgentToServer.health:type_name -> opamp.proto.ComponentHealth - 35, // 2: opamp.proto.AgentToServer.effective_config:type_name -> opamp.proto.EffectiveConfig - 36, // 3: opamp.proto.AgentToServer.remote_config_status:type_name -> opamp.proto.RemoteConfigStatus - 38, // 4: opamp.proto.AgentToServer.package_statuses:type_name -> opamp.proto.PackageStatuses - 11, // 5: opamp.proto.AgentToServer.agent_disconnect:type_name -> opamp.proto.AgentDisconnect - 12, // 6: opamp.proto.AgentToServer.connection_settings_request:type_name -> opamp.proto.ConnectionSettingsRequest - 45, // 7: opamp.proto.AgentToServer.custom_capabilities:type_name -> opamp.proto.CustomCapabilities - 46, // 8: opamp.proto.AgentToServer.custom_message:type_name -> opamp.proto.CustomMessage - 15, // 9: opamp.proto.AgentToServer.available_components:type_name -> opamp.proto.AvailableComponents - 37, // 10: opamp.proto.AgentToServer.connection_settings_status:type_name -> opamp.proto.ConnectionSettingsStatus - 13, // 11: opamp.proto.ConnectionSettingsRequest.opamp:type_name -> opamp.proto.OpAMPConnectionSettingsRequest - 14, // 12: opamp.proto.OpAMPConnectionSettingsRequest.certificate_request:type_name -> opamp.proto.CertificateRequest - 47, // 13: opamp.proto.AvailableComponents.components:type_name -> opamp.proto.AvailableComponents.ComponentsEntry - 55, // 14: opamp.proto.ComponentDetails.metadata:type_name -> opamp.proto.KeyValue - 48, // 15: opamp.proto.ComponentDetails.sub_component_map:type_name -> opamp.proto.ComponentDetails.SubComponentMapEntry - 30, // 16: opamp.proto.ServerToAgent.error_response:type_name -> opamp.proto.ServerErrorResponse - 42, // 17: opamp.proto.ServerToAgent.remote_config:type_name -> opamp.proto.AgentRemoteConfig - 26, // 18: opamp.proto.ServerToAgent.connection_settings:type_name -> opamp.proto.ConnectionSettingsOffers - 27, // 19: opamp.proto.ServerToAgent.packages_available:type_name -> opamp.proto.PackagesAvailable - 41, // 20: opamp.proto.ServerToAgent.agent_identification:type_name -> opamp.proto.AgentIdentification - 32, // 21: opamp.proto.ServerToAgent.command:type_name -> opamp.proto.ServerToAgentCommand - 45, // 22: opamp.proto.ServerToAgent.custom_capabilities:type_name -> opamp.proto.CustomCapabilities - 46, // 23: opamp.proto.ServerToAgent.custom_message:type_name -> opamp.proto.CustomMessage - 23, // 24: opamp.proto.OpAMPConnectionSettings.headers:type_name -> opamp.proto.Headers - 25, // 25: opamp.proto.OpAMPConnectionSettings.certificate:type_name -> opamp.proto.TLSCertificate - 21, // 26: opamp.proto.OpAMPConnectionSettings.tls:type_name -> opamp.proto.TLSConnectionSettings - 22, // 27: opamp.proto.OpAMPConnectionSettings.proxy:type_name -> opamp.proto.ProxyConnectionSettings - 23, // 28: opamp.proto.TelemetryConnectionSettings.headers:type_name -> opamp.proto.Headers - 25, // 29: opamp.proto.TelemetryConnectionSettings.certificate:type_name -> opamp.proto.TLSCertificate - 21, // 30: opamp.proto.TelemetryConnectionSettings.tls:type_name -> opamp.proto.TLSConnectionSettings - 22, // 31: opamp.proto.TelemetryConnectionSettings.proxy:type_name -> opamp.proto.ProxyConnectionSettings - 23, // 32: opamp.proto.OtherConnectionSettings.headers:type_name -> opamp.proto.Headers - 25, // 33: opamp.proto.OtherConnectionSettings.certificate:type_name -> opamp.proto.TLSCertificate - 49, // 34: opamp.proto.OtherConnectionSettings.other_settings:type_name -> opamp.proto.OtherConnectionSettings.OtherSettingsEntry - 21, // 35: opamp.proto.OtherConnectionSettings.tls:type_name -> opamp.proto.TLSConnectionSettings - 22, // 36: opamp.proto.OtherConnectionSettings.proxy:type_name -> opamp.proto.ProxyConnectionSettings - 23, // 37: opamp.proto.ProxyConnectionSettings.connect_headers:type_name -> opamp.proto.Headers - 24, // 38: opamp.proto.Headers.headers:type_name -> opamp.proto.Header - 18, // 39: opamp.proto.ConnectionSettingsOffers.opamp:type_name -> opamp.proto.OpAMPConnectionSettings - 19, // 40: opamp.proto.ConnectionSettingsOffers.own_metrics:type_name -> opamp.proto.TelemetryConnectionSettings - 19, // 41: opamp.proto.ConnectionSettingsOffers.own_traces:type_name -> opamp.proto.TelemetryConnectionSettings - 19, // 42: opamp.proto.ConnectionSettingsOffers.own_logs:type_name -> opamp.proto.TelemetryConnectionSettings - 50, // 43: opamp.proto.ConnectionSettingsOffers.other_connections:type_name -> opamp.proto.ConnectionSettingsOffers.OtherConnectionsEntry - 51, // 44: opamp.proto.PackagesAvailable.packages:type_name -> opamp.proto.PackagesAvailable.PackagesEntry - 3, // 45: opamp.proto.PackageAvailable.type:type_name -> opamp.proto.PackageType - 29, // 46: opamp.proto.PackageAvailable.file:type_name -> opamp.proto.DownloadableFile - 23, // 47: opamp.proto.DownloadableFile.headers:type_name -> opamp.proto.Headers - 4, // 48: opamp.proto.ServerErrorResponse.type:type_name -> opamp.proto.ServerErrorResponseType - 31, // 49: opamp.proto.ServerErrorResponse.retry_info:type_name -> opamp.proto.RetryInfo - 5, // 50: opamp.proto.ServerToAgentCommand.type:type_name -> opamp.proto.CommandType - 55, // 51: opamp.proto.AgentDescription.identifying_attributes:type_name -> opamp.proto.KeyValue - 55, // 52: opamp.proto.AgentDescription.non_identifying_attributes:type_name -> opamp.proto.KeyValue - 52, // 53: opamp.proto.ComponentHealth.component_health_map:type_name -> opamp.proto.ComponentHealth.ComponentHealthMapEntry - 43, // 54: opamp.proto.EffectiveConfig.config_map:type_name -> opamp.proto.AgentConfigMap - 8, // 55: opamp.proto.RemoteConfigStatus.status:type_name -> opamp.proto.RemoteConfigStatuses - 7, // 56: opamp.proto.ConnectionSettingsStatus.status:type_name -> opamp.proto.ConnectionSettingsStatuses - 53, // 57: opamp.proto.PackageStatuses.packages:type_name -> opamp.proto.PackageStatuses.PackagesEntry - 9, // 58: opamp.proto.PackageStatus.status:type_name -> opamp.proto.PackageStatusEnum - 40, // 59: opamp.proto.PackageStatus.download_details:type_name -> opamp.proto.PackageDownloadDetails - 43, // 60: opamp.proto.AgentRemoteConfig.config:type_name -> opamp.proto.AgentConfigMap - 54, // 61: opamp.proto.AgentConfigMap.config_map:type_name -> opamp.proto.AgentConfigMap.ConfigMapEntry - 16, // 62: opamp.proto.AvailableComponents.ComponentsEntry.value:type_name -> opamp.proto.ComponentDetails - 16, // 63: opamp.proto.ComponentDetails.SubComponentMapEntry.value:type_name -> opamp.proto.ComponentDetails - 20, // 64: opamp.proto.ConnectionSettingsOffers.OtherConnectionsEntry.value:type_name -> opamp.proto.OtherConnectionSettings - 28, // 65: opamp.proto.PackagesAvailable.PackagesEntry.value:type_name -> opamp.proto.PackageAvailable - 34, // 66: opamp.proto.ComponentHealth.ComponentHealthMapEntry.value:type_name -> opamp.proto.ComponentHealth - 39, // 67: opamp.proto.PackageStatuses.PackagesEntry.value:type_name -> opamp.proto.PackageStatus - 44, // 68: opamp.proto.AgentConfigMap.ConfigMapEntry.value:type_name -> opamp.proto.AgentConfigFile - 69, // [69:69] is the sub-list for method output_type - 69, // [69:69] is the sub-list for method input_type - 69, // [69:69] is the sub-list for extension type_name - 69, // [69:69] is the sub-list for extension extendee - 0, // [0:69] is the sub-list for field type_name + 35, // 0: opamp.proto.v1.AgentToServer.agent_description:type_name -> opamp.proto.v1.AgentDescription + 36, // 1: opamp.proto.v1.AgentToServer.health:type_name -> opamp.proto.v1.ComponentHealth + 37, // 2: opamp.proto.v1.AgentToServer.effective_config:type_name -> opamp.proto.v1.EffectiveConfig + 38, // 3: opamp.proto.v1.AgentToServer.remote_config_status:type_name -> opamp.proto.v1.RemoteConfigStatus + 40, // 4: opamp.proto.v1.AgentToServer.package_statuses:type_name -> opamp.proto.v1.PackageStatuses + 11, // 5: opamp.proto.v1.AgentToServer.agent_disconnect:type_name -> opamp.proto.v1.AgentDisconnect + 12, // 6: opamp.proto.v1.AgentToServer.connection_settings_request:type_name -> opamp.proto.v1.ConnectionSettingsRequest + 47, // 7: opamp.proto.v1.AgentToServer.custom_capabilities:type_name -> opamp.proto.v1.CustomCapabilities + 48, // 8: opamp.proto.v1.AgentToServer.custom_message:type_name -> opamp.proto.v1.CustomMessage + 15, // 9: opamp.proto.v1.AgentToServer.available_components:type_name -> opamp.proto.v1.AvailableComponents + 39, // 10: opamp.proto.v1.AgentToServer.connection_settings_status:type_name -> opamp.proto.v1.ConnectionSettingsStatus + 13, // 11: opamp.proto.v1.ConnectionSettingsRequest.opamp:type_name -> opamp.proto.v1.OpAMPConnectionSettingsRequest + 14, // 12: opamp.proto.v1.OpAMPConnectionSettingsRequest.certificate_request:type_name -> opamp.proto.v1.CertificateRequest + 49, // 13: opamp.proto.v1.AvailableComponents.components:type_name -> opamp.proto.v1.AvailableComponents.ComponentsEntry + 57, // 14: opamp.proto.v1.ComponentDetails.metadata:type_name -> opamp.proto.v1.KeyValue + 50, // 15: opamp.proto.v1.ComponentDetails.sub_component_map:type_name -> opamp.proto.v1.ComponentDetails.SubComponentMapEntry + 32, // 16: opamp.proto.v1.ServerToAgent.error_response:type_name -> opamp.proto.v1.ServerErrorResponse + 44, // 17: opamp.proto.v1.ServerToAgent.remote_config:type_name -> opamp.proto.v1.AgentRemoteConfig + 28, // 18: opamp.proto.v1.ServerToAgent.connection_settings:type_name -> opamp.proto.v1.ConnectionSettingsOffers + 29, // 19: opamp.proto.v1.ServerToAgent.packages_available:type_name -> opamp.proto.v1.PackagesAvailable + 43, // 20: opamp.proto.v1.ServerToAgent.agent_identification:type_name -> opamp.proto.v1.AgentIdentification + 34, // 21: opamp.proto.v1.ServerToAgent.command:type_name -> opamp.proto.v1.ServerToAgentCommand + 47, // 22: opamp.proto.v1.ServerToAgent.custom_capabilities:type_name -> opamp.proto.v1.CustomCapabilities + 48, // 23: opamp.proto.v1.ServerToAgent.custom_message:type_name -> opamp.proto.v1.CustomMessage + 18, // 24: opamp.proto.v1.SignedServerToAgent.trust_chain_response:type_name -> opamp.proto.v1.TrustChainResponse + 25, // 25: opamp.proto.v1.OpAMPConnectionSettings.headers:type_name -> opamp.proto.v1.Headers + 27, // 26: opamp.proto.v1.OpAMPConnectionSettings.certificate:type_name -> opamp.proto.v1.TLSCertificate + 23, // 27: opamp.proto.v1.OpAMPConnectionSettings.tls:type_name -> opamp.proto.v1.TLSConnectionSettings + 24, // 28: opamp.proto.v1.OpAMPConnectionSettings.proxy:type_name -> opamp.proto.v1.ProxyConnectionSettings + 25, // 29: opamp.proto.v1.TelemetryConnectionSettings.headers:type_name -> opamp.proto.v1.Headers + 27, // 30: opamp.proto.v1.TelemetryConnectionSettings.certificate:type_name -> opamp.proto.v1.TLSCertificate + 23, // 31: opamp.proto.v1.TelemetryConnectionSettings.tls:type_name -> opamp.proto.v1.TLSConnectionSettings + 24, // 32: opamp.proto.v1.TelemetryConnectionSettings.proxy:type_name -> opamp.proto.v1.ProxyConnectionSettings + 25, // 33: opamp.proto.v1.OtherConnectionSettings.headers:type_name -> opamp.proto.v1.Headers + 27, // 34: opamp.proto.v1.OtherConnectionSettings.certificate:type_name -> opamp.proto.v1.TLSCertificate + 51, // 35: opamp.proto.v1.OtherConnectionSettings.other_settings:type_name -> opamp.proto.v1.OtherConnectionSettings.OtherSettingsEntry + 23, // 36: opamp.proto.v1.OtherConnectionSettings.tls:type_name -> opamp.proto.v1.TLSConnectionSettings + 24, // 37: opamp.proto.v1.OtherConnectionSettings.proxy:type_name -> opamp.proto.v1.ProxyConnectionSettings + 25, // 38: opamp.proto.v1.ProxyConnectionSettings.connect_headers:type_name -> opamp.proto.v1.Headers + 26, // 39: opamp.proto.v1.Headers.headers:type_name -> opamp.proto.v1.Header + 20, // 40: opamp.proto.v1.ConnectionSettingsOffers.opamp:type_name -> opamp.proto.v1.OpAMPConnectionSettings + 21, // 41: opamp.proto.v1.ConnectionSettingsOffers.own_metrics:type_name -> opamp.proto.v1.TelemetryConnectionSettings + 21, // 42: opamp.proto.v1.ConnectionSettingsOffers.own_traces:type_name -> opamp.proto.v1.TelemetryConnectionSettings + 21, // 43: opamp.proto.v1.ConnectionSettingsOffers.own_logs:type_name -> opamp.proto.v1.TelemetryConnectionSettings + 52, // 44: opamp.proto.v1.ConnectionSettingsOffers.other_connections:type_name -> opamp.proto.v1.ConnectionSettingsOffers.OtherConnectionsEntry + 53, // 45: opamp.proto.v1.PackagesAvailable.packages:type_name -> opamp.proto.v1.PackagesAvailable.PackagesEntry + 3, // 46: opamp.proto.v1.PackageAvailable.type:type_name -> opamp.proto.v1.PackageType + 31, // 47: opamp.proto.v1.PackageAvailable.file:type_name -> opamp.proto.v1.DownloadableFile + 25, // 48: opamp.proto.v1.DownloadableFile.headers:type_name -> opamp.proto.v1.Headers + 4, // 49: opamp.proto.v1.ServerErrorResponse.type:type_name -> opamp.proto.v1.ServerErrorResponseType + 33, // 50: opamp.proto.v1.ServerErrorResponse.retry_info:type_name -> opamp.proto.v1.RetryInfo + 5, // 51: opamp.proto.v1.ServerToAgentCommand.type:type_name -> opamp.proto.v1.CommandType + 57, // 52: opamp.proto.v1.AgentDescription.identifying_attributes:type_name -> opamp.proto.v1.KeyValue + 57, // 53: opamp.proto.v1.AgentDescription.non_identifying_attributes:type_name -> opamp.proto.v1.KeyValue + 54, // 54: opamp.proto.v1.ComponentHealth.component_health_map:type_name -> opamp.proto.v1.ComponentHealth.ComponentHealthMapEntry + 45, // 55: opamp.proto.v1.EffectiveConfig.config_map:type_name -> opamp.proto.v1.AgentConfigMap + 8, // 56: opamp.proto.v1.RemoteConfigStatus.status:type_name -> opamp.proto.v1.RemoteConfigStatuses + 7, // 57: opamp.proto.v1.ConnectionSettingsStatus.status:type_name -> opamp.proto.v1.ConnectionSettingsStatuses + 55, // 58: opamp.proto.v1.PackageStatuses.packages:type_name -> opamp.proto.v1.PackageStatuses.PackagesEntry + 9, // 59: opamp.proto.v1.PackageStatus.status:type_name -> opamp.proto.v1.PackageStatusEnum + 42, // 60: opamp.proto.v1.PackageStatus.download_details:type_name -> opamp.proto.v1.PackageDownloadDetails + 45, // 61: opamp.proto.v1.AgentRemoteConfig.config:type_name -> opamp.proto.v1.AgentConfigMap + 56, // 62: opamp.proto.v1.AgentConfigMap.config_map:type_name -> opamp.proto.v1.AgentConfigMap.ConfigMapEntry + 16, // 63: opamp.proto.v1.AvailableComponents.ComponentsEntry.value:type_name -> opamp.proto.v1.ComponentDetails + 16, // 64: opamp.proto.v1.ComponentDetails.SubComponentMapEntry.value:type_name -> opamp.proto.v1.ComponentDetails + 22, // 65: opamp.proto.v1.ConnectionSettingsOffers.OtherConnectionsEntry.value:type_name -> opamp.proto.v1.OtherConnectionSettings + 30, // 66: opamp.proto.v1.PackagesAvailable.PackagesEntry.value:type_name -> opamp.proto.v1.PackageAvailable + 36, // 67: opamp.proto.v1.ComponentHealth.ComponentHealthMapEntry.value:type_name -> opamp.proto.v1.ComponentHealth + 41, // 68: opamp.proto.v1.PackageStatuses.PackagesEntry.value:type_name -> opamp.proto.v1.PackageStatus + 46, // 69: opamp.proto.v1.AgentConfigMap.ConfigMapEntry.value:type_name -> opamp.proto.v1.AgentConfigFile + 70, // [70:70] is the sub-list for method output_type + 70, // [70:70] is the sub-list for method input_type + 70, // [70:70] is the sub-list for extension type_name + 70, // [70:70] is the sub-list for extension extendee + 0, // [0:70] is the sub-list for field type_name } func init() { file_opamp_proto_init() } @@ -4438,462 +4152,16 @@ func file_opamp_proto_init() { return } file_anyvalue_proto_init() - if !protoimpl.UnsafeEnabled { - file_opamp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentToServer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentDisconnect); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionSettingsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OpAMPConnectionSettingsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CertificateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AvailableComponents); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComponentDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServerToAgent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OpAMPConnectionSettings); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TelemetryConnectionSettings); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OtherConnectionSettings); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLSConnectionSettings); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyConnectionSettings); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Headers); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Header); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLSCertificate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionSettingsOffers); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PackagesAvailable); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PackageAvailable); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DownloadableFile); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServerErrorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServerToAgentCommand); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentDescription); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComponentHealth); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EffectiveConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoteConfigStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionSettingsStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PackageStatuses); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PackageStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PackageDownloadDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentIdentification); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentRemoteConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentConfigMap); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AgentConfigFile); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CustomCapabilities); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_opamp_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CustomMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_opamp_proto_msgTypes[20].OneofWrappers = []interface{}{ + file_opamp_proto_msgTypes[22].OneofWrappers = []any{ (*ServerErrorResponse_RetryInfo)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_opamp_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_opamp_proto_rawDesc), len(file_opamp_proto_rawDesc)), NumEnums: 10, - NumMessages: 45, + NumMessages: 47, NumExtensions: 0, NumServices: 0, }, @@ -4903,7 +4171,6 @@ func file_opamp_proto_init() { MessageInfos: file_opamp_proto_msgTypes, }.Build() File_opamp_proto = out.File - file_opamp_proto_rawDesc = nil file_opamp_proto_goTypes = nil file_opamp_proto_depIdxs = nil } diff --git a/server/attestation.go b/server/attestation.go new file mode 100644 index 00000000..ed27ae56 --- /dev/null +++ b/server/attestation.go @@ -0,0 +1,126 @@ +package server + +import ( + "context" + "encoding/pem" + "fmt" + "sync/atomic" + + "google.golang.org/protobuf/proto" + + "github.com/open-telemetry/opamp-go/protobufs" + "github.com/open-telemetry/opamp-go/signing" +) + +// connectionSigningState holds the per-connection state needed to wrap +// outbound ServerToAgent messages in SignedServerToAgent envelopes +// when payload trust verification has been negotiated. +// +// The signer is held by reference; the certificate chain is +// snapshotted at construction time so that operator-side cert +// rotation does not affect a live connection (the agent only +// revalidates the chain on reconnect). firstSent atomically tracks +// whether the chain has already been delivered on this connection so +// that exactly one outbound envelope carries it. +type connectionSigningState struct { + signer signing.Signer + chainDER [][]byte // snapshot + tofuAnchorPEM []byte // non-empty iff this connection is a TOFU enrollment + tofuError string // non-empty when TOFU requested but anchor unavailable + firstSent atomic.Bool +} + +// newConnectionSigningState constructs the per-connection state by +// asking the signer for its current chain. When tofu is true the signer +// must also implement TrustAnchorProvider; the root CA is fetched and +// stored to be included in the first outbound TrustChainResponse. +func newConnectionSigningState(ctx context.Context, signer signing.Signer, tofu bool) (*connectionSigningState, error) { + if signer == nil { + return nil, fmt.Errorf("server: nil signer") + } + chain, err := signer.ChainDER(ctx) + if err != nil { + return nil, fmt.Errorf("server: fetch signing chain: %w", err) + } + state := &connectionSigningState{ + signer: signer, + chainDER: chain, + } + if tofu { + tap, ok := signer.(signing.TrustAnchorProvider) + if !ok { + state.tofuError = "server cannot provide TOFU trust anchor: signer does not implement TrustAnchorProvider" + } else { + anchorPEM, err := tap.TrustAnchorPEM(ctx) + if err != nil { + state.tofuError = fmt.Sprintf("server cannot provide TOFU trust anchor: %v", err) + } else { + state.tofuAnchorPEM = anchorPEM + } + } + } + return state, nil +} + +// signOutgoing produces a SignedServerToAgent envelope wrapping msg. +// The first call on a given state additionally populates +// trust_chain_response with the snapshotted chain; subsequent calls +// carry only payload + signature. +func (s *connectionSigningState) signOutgoing(ctx context.Context, msg *protobufs.ServerToAgent) (*protobufs.SignedServerToAgent, error) { + payload, err := proto.Marshal(msg) + if err != nil { + return nil, fmt.Errorf("server: marshal inner ServerToAgent: %w", err) + } + sig, err := s.signer.Sign(ctx, payload) + if err != nil { + return nil, fmt.Errorf("server: sign payload: %w", err) + } + env := &protobufs.SignedServerToAgent{ + Payload: payload, + Signature: sig, + } + + // CompareAndSwap returns true iff we were the goroutine that + // transitioned firstSent from false to true — guaranteeing exactly + // one envelope carries the trust chain across concurrent callers. + if s.firstSent.CompareAndSwap(false, true) { + if s.tofuError != "" { + // TOFU was requested but the server cannot fulfil it. Per the + // spec the server MUST set error_message; the agent will + // terminate the connection on receipt. + env.TrustChainResponse = &protobufs.TrustChainResponse{ + ErrorMessage: s.tofuError, + } + } else { + var pemChain []byte + for _, der := range s.chainDER { + pemChain = append(pemChain, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der})...) + } + env.TrustChainResponse = &protobufs.TrustChainResponse{ + CertificateChain: pemChain, + TofuTrustAnchor: s.tofuAnchorPEM, // nil unless TOFU enrollment + } + } + } + return env, nil +} + +// agentRequiresAttestation reports whether the supplied +// AgentToServer.capabilities bitmask requests payload trust +// verification. +func agentRequiresAttestation(capabilities uint64) bool { + return capabilities&uint64(protobufs.AgentCapabilities_AgentCapabilities_RequiresPayloadTrustVerification) != 0 +} + +// agentRequestsTOFU reports whether the agent is requesting TOFU +// enrollment (no pre-configured trust anchor; needs the root CA). +func agentRequestsTOFU(capabilities uint64) bool { + return capabilities&uint64(protobufs.AgentCapabilities_AgentCapabilities_AcceptsPayloadTrustAnchorTOFU) != 0 +} + +// addOffersAttestationBit returns capabilities with the +// ServerCapabilities_OffersPayloadTrustVerification bit set. It is a +// no-op if the bit is already set. +func addOffersAttestationBit(capabilities uint64) uint64 { + return capabilities | uint64(protobufs.ServerCapabilities_ServerCapabilities_OffersPayloadTrustVerification) +} diff --git a/server/server.go b/server/server.go index 6570d2fe..8f4839f8 100644 --- a/server/server.go +++ b/server/server.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/open-telemetry/opamp-go/server/types" + "github.com/open-telemetry/opamp-go/signing" ) // Settings contains the settings for attaching an OpAMP Server. @@ -35,6 +36,20 @@ type Settings struct { // https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#customcapabilities // for more details. CustomCapabilities []string + + // PayloadSigner produces detached signatures over outbound + // ServerToAgent messages and supplies the certificate chain that + // authenticates the Server to the Agent. When non-nil and the + // connecting Agent declares + // AgentCapabilities_RequiresPayloadTrustVerification, every + // ServerToAgent the Server sends on that connection is wrapped in + // a SignedServerToAgent envelope per the Message Attestation + // section of the OpAMP specification. The + // ServerCapabilities_OffersPayloadTrustVerification bit is + // automatically set on outgoing capabilities when this field is + // non-nil. nil disables payload trust signing — wire-identical to + // upstream OpAMP. + PayloadSigner signing.Signer } // StartSettings contains the settings for starting an OpAMP Server. diff --git a/server/serverimpl.go b/server/serverimpl.go index ae65b270..e2232ad6 100644 --- a/server/serverimpl.go +++ b/server/serverimpl.go @@ -242,7 +242,7 @@ func (s *server) handleWSConnection(reqCtx context.Context, wsConn *websocket.Co if s.settings.MaxMessageSize >= 0 { wsConn.SetReadLimit(s.settings.MaxMessageSize) } - agentConn := newWSConnection(wsConn, s.settings.MaxMessageSize) + agentConn := newWSConnection(wsConn, s.settings.MaxMessageSize, s.settings.PayloadSigner != nil) defer func() { // Close the connection when all is done. @@ -305,6 +305,27 @@ func (s *server) handleWSConnection(reqCtx context.Context, wsConn *websocket.Co continue } + // On the first AgentToServer of this connection, decide + // whether payload trust verification is negotiated. The Agent + // declares its requirement via capabilities; the Server has + // to have a configured PayloadSigner. If both line up, snapshot + // the chain and attach a signing state to the connection so + // subsequent Sends wrap their messages in a SignedServerToAgent + // envelope. markNegotiated also unblocks Send for callers that + // were rejected pre-negotiation (see ErrSendBeforeNegotiated). + if !agentConn.isNegotiated() { + if s.settings.PayloadSigner != nil && agentRequiresAttestation(request.Capabilities) { + tofu := agentRequestsTOFU(request.Capabilities) + state, err := newConnectionSigningState(msgContext, s.settings.PayloadSigner, tofu) + if err != nil { + s.logger.Errorf(msgContext, "Cannot fetch signing certificate chain: %v", err) + break + } + agentConn.enableSigning(state) + } + agentConn.markNegotiated() + } + response := connectionCallbacks.OnMessage(msgContext, agentConn, &request) if response == nil { // No send message when 'response' is empty continue @@ -319,6 +340,15 @@ func (s *server) handleWSConnection(reqCtx context.Context, wsConn *websocket.Co } sentCustomCapabilities = true } + // Auto-advertise OffersPayloadTrustVerification whenever the + // server has a PayloadSigner configured — independent of + // whether THIS agent declared the Requires bit. Per the spec's + // negotiation matrix, the bit signals server capability. + // Agents that don't require attestation still see the bit and + // can choose to opt in on reconnect. + if s.settings.PayloadSigner != nil { + response.Capabilities = addOffersAttestationBit(response.Capabilities) + } err = agentConn.Send(msgContext, response) if err != nil { @@ -434,8 +464,45 @@ func (s *server) handlePlainHTTPRequest(req *http.Request, w http.ResponseWriter Capabilities: s.settings.CustomCapabilities, } - // Marshal the response. - bodyBytes, err = proto.Marshal(response) + // Payload trust verification (HTTP path). HTTP is request-response + // with no persistent connection, so the trust handshake happens + // per-response: every signed response carries the chain alongside + // the signature. The Agent's HTTP receive path is stateful across + // polls (see client/internal/attestation.go) but tolerates the + // chain being re-sent — it just ignores it after the first. + // + // TODO(perf): for RPC-backed signers, newConnectionSigningState + // re-fetches the chain on every request — at 10⁶ agents polling + // every 30s that's ~33k RPS just for ChainDER. A server-level + // cache (or a TTL-aware Signer wrapper) would amortise the cost. + // Defer until LocalSigner is no longer the only impl in use. + var responseMessage proto.Message = response + if s.settings.PayloadSigner != nil { + // Always advertise Offers when the server is capable, even + // if THIS agent didn't declare Requires (per spec's + // negotiation matrix). + response.Capabilities = addOffersAttestationBit(response.Capabilities) + + if agentRequiresAttestation(request.Capabilities) { + tofu := agentRequestsTOFU(request.Capabilities) + state, sigErr := newConnectionSigningState(req.Context(), s.settings.PayloadSigner, tofu) + if sigErr != nil { + s.logger.Errorf(req.Context(), "Cannot fetch signing certificate chain: %v", sigErr) + w.WriteHeader(http.StatusInternalServerError) + return + } + envelope, sigErr := state.signOutgoing(req.Context(), response) + if sigErr != nil { + s.logger.Errorf(req.Context(), "Cannot sign HTTP response: %v", sigErr) + w.WriteHeader(http.StatusInternalServerError) + return + } + responseMessage = envelope + } + } + + // Marshal the response (or its envelope). + bodyBytes, err = proto.Marshal(responseMessage) if err != nil { w.WriteHeader(http.StatusInternalServerError) return diff --git a/server/wsconnection.go b/server/wsconnection.go index 9f59aad7..416a2e32 100644 --- a/server/wsconnection.go +++ b/server/wsconnection.go @@ -2,6 +2,7 @@ package server import ( "context" + "errors" "net" "sync" "sync/atomic" @@ -13,6 +14,18 @@ import ( "github.com/open-telemetry/opamp-go/server/types" ) +// ErrSendBeforeNegotiated is returned from Send when the server has +// a PayloadSigner configured but no AgentToServer has been processed +// yet on this connection. In that window the server cannot know +// whether the agent will declare RequiresPayloadTrustVerification, so +// emitting a message risks bypassing attestation. Push outbound +// messages from OnMessage (or any callback that runs after the first +// agent message), not from OnConnected. +var ErrSendBeforeNegotiated = errors.New( + "server: Send called before Message Attestation negotiation completed; " + + "push outbound messages from OnMessage rather than OnConnected", +) + // wsConnection represents a persistent OpAMP connection over a WebSocket. type wsConnection struct { // The websocket library does not allow multiple concurrent write operations, @@ -23,22 +36,87 @@ type wsConnection struct { closed atomic.Bool maxMessageSize int64 + + // requiresNegotiation is fixed at construction. When true the + // server has a PayloadSigner configured and Send is rejected until + // negotiated flips to true. When false (no server-side signer), + // Send is always permitted — wire-identical to upstream OpAMP. + requiresNegotiation bool + + // negotiated flips to true after the connection's first + // AgentToServer has been processed by handleWSConnection. After + // that point the server has had its chance to decide whether to + // enable signing based on the agent's capability bits, so Send is + // safe to call. + negotiated atomic.Bool + + // signing, when loaded as non-nil, indicates that this connection + // has negotiated payload trust verification with the Agent. + // Outbound ServerToAgent messages are wrapped in a + // SignedServerToAgent envelope and the first send carries the + // trust chain. atomic.Pointer because enableSigning and Send may + // be called from different goroutines (Send is part of the public + // Connection callback API and may be invoked by user code). + signing atomic.Pointer[connectionSigningState] } var _ types.Connection = (*wsConnection)(nil) -func newWSConnection(wsConn *websocket.Conn, maxMessageSize int64) types.Connection { - return &wsConnection{wsConn: wsConn, maxMessageSize: maxMessageSize} +func newWSConnection(wsConn *websocket.Conn, maxMessageSize int64, requiresNegotiation bool) *wsConnection { + return &wsConnection{ + wsConn: wsConn, + maxMessageSize: maxMessageSize, + requiresNegotiation: requiresNegotiation, + } +} + +// enableSigning marks this connection as one that has negotiated +// payload trust verification. Outbound Send calls will wrap their +// ServerToAgent argument in a SignedServerToAgent envelope using the +// supplied state. +func (c *wsConnection) enableSigning(state *connectionSigningState) { + c.signing.Store(state) +} + +// signingEnabled reports whether this connection has negotiated +// payload trust verification. +func (c *wsConnection) signingEnabled() bool { + return c.signing.Load() != nil +} + +// markNegotiated records that the connection has processed its first +// AgentToServer message. After this point Send is no longer blocked +// by the pre-negotiation guard. +func (c *wsConnection) markNegotiated() { + c.negotiated.Store(true) +} + +// isNegotiated reports whether the connection has processed its +// first AgentToServer message. +func (c *wsConnection) isNegotiated() bool { + return c.negotiated.Load() } func (c *wsConnection) Connection() net.Conn { return c.wsConn.UnderlyingConn() } -func (c *wsConnection) Send(_ context.Context, message *protobufs.ServerToAgent) error { +func (c *wsConnection) Send(ctx context.Context, message *protobufs.ServerToAgent) error { + if c.requiresNegotiation && !c.negotiated.Load() { + return ErrSendBeforeNegotiated + } + c.connMutex.Lock() defer c.connMutex.Unlock() + if state := c.signing.Load(); state != nil { + env, err := state.signOutgoing(ctx, message) + if err != nil { + return err + } + return internal.WriteWSMessage(c.wsConn, env, c.maxMessageSize) + } + return internal.WriteWSMessage(c.wsConn, message, c.maxMessageSize) } diff --git a/signing/algorithm.go b/signing/algorithm.go new file mode 100644 index 00000000..4b2b166a --- /dev/null +++ b/signing/algorithm.go @@ -0,0 +1,187 @@ +package signing + +import ( + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "errors" + "fmt" +) + +// rsaMinModulusBits is the minimum acceptable RSA modulus size. Keys +// below this size are rejected even if the rest of the chain validates. +const rsaMinModulusBits = 2048 + +// ErrUnsupportedAlgorithm indicates that a certificate's public key +// (or the algorithm declared by the issuer's signature on the cert) +// is not in the supported set: it is the wrong key type, an +// unsupported ECDSA curve, an RSA key below rsaMinModulusBits, or the +// declared SignatureAlgorithm does not match the leaf's actual key +// type/curve. +var ErrUnsupportedAlgorithm = errors.New("signing: unsupported signature algorithm") + +// algorithmFromCert derives the Algorithm to use for signature +// operations involving cert. Dispatching on the leaf's own public key +// type (rather than on cert.SignatureAlgorithm, which describes the +// issuer's signing of the cert itself) is the correct authority: the +// Algorithm controls how a payload is signed/verified, and that has to +// match the leaf key's algorithm and curve, not the issuer's. +// +// The function additionally cross-checks cert.SignatureAlgorithm +// against the leaf key so that a certificate whose declared algorithm +// is inconsistent with its pubkey is rejected up front. This prevents +// a within-family mismatch (e.g., a P-384 CA issuing a P-256 leaf with +// SignatureAlgorithm=ECDSAWithSHA384) from silently accepting the +// wrong hash size at sign/verify time. +// +// Minimum RSA modulus is rsaMinModulusBits. +func algorithmFromCert(cert *x509.Certificate) (Algorithm, error) { + switch pub := cert.PublicKey.(type) { + case *ecdsa.PublicKey: + switch pub.Curve { + case elliptic.P256(): + if cert.SignatureAlgorithm != x509.ECDSAWithSHA256 { + return AlgorithmUnspecified, fmt.Errorf("%w: P-256 leaf with mismatched declared algorithm %s", + ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) + } + return AlgorithmECDSAP256SHA256, nil + case elliptic.P384(): + if cert.SignatureAlgorithm != x509.ECDSAWithSHA384 { + return AlgorithmUnspecified, fmt.Errorf("%w: P-384 leaf with mismatched declared algorithm %s", + ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) + } + return AlgorithmECDSAP384SHA384, nil + default: + curveName := "unknown" + if pub.Curve != nil && pub.Curve.Params() != nil { + curveName = pub.Curve.Params().Name + } + return AlgorithmUnspecified, fmt.Errorf("%w: unsupported ECDSA curve %s", + ErrUnsupportedAlgorithm, curveName) + } + case *rsa.PublicKey: + if pub.N == nil || pub.N.BitLen() < rsaMinModulusBits { + bits := 0 + if pub.N != nil { + bits = pub.N.BitLen() + } + return AlgorithmUnspecified, fmt.Errorf("%w: RSA key %d bits < %d", + ErrUnsupportedAlgorithm, bits, rsaMinModulusBits) + } + if cert.SignatureAlgorithm != x509.SHA256WithRSA { + return AlgorithmUnspecified, fmt.Errorf("%w: RSA leaf with mismatched declared algorithm %s", + ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) + } + return AlgorithmRSAPKCS1v15SHA256, nil + case ed25519.PublicKey: + if cert.SignatureAlgorithm != x509.PureEd25519 { + return AlgorithmUnspecified, fmt.Errorf("%w: Ed25519 leaf with mismatched declared algorithm %s", + ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) + } + return AlgorithmEd25519, nil + default: + return AlgorithmUnspecified, fmt.Errorf("%w: unsupported public key type %T", + ErrUnsupportedAlgorithm, pub) + } +} + +// signWithKey produces a detached signature over payload using key, +// dispatching on alg. The caller is responsible for matching alg to +// the type of key (private key types are not switchable at runtime). +func signWithKey(key crypto.Signer, alg Algorithm, payload []byte) ([]byte, error) { + switch alg { + case AlgorithmECDSAP256SHA256: + k, ok := key.(*ecdsa.PrivateKey) + if !ok { + return nil, fmt.Errorf("%w: ECDSA-P256 requires *ecdsa.PrivateKey, got %T", ErrUnsupportedAlgorithm, key) + } + h := sha256.Sum256(payload) + return ecdsa.SignASN1(rand.Reader, k, h[:]) + + case AlgorithmECDSAP384SHA384: + k, ok := key.(*ecdsa.PrivateKey) + if !ok { + return nil, fmt.Errorf("%w: ECDSA-P384 requires *ecdsa.PrivateKey, got %T", ErrUnsupportedAlgorithm, key) + } + h := sha512.Sum384(payload) + return ecdsa.SignASN1(rand.Reader, k, h[:]) + + case AlgorithmRSAPKCS1v15SHA256: + k, ok := key.(*rsa.PrivateKey) + if !ok { + return nil, fmt.Errorf("%w: RSA-PKCS1v15-SHA256 requires *rsa.PrivateKey, got %T", ErrUnsupportedAlgorithm, key) + } + h := sha256.Sum256(payload) + return rsa.SignPKCS1v15(rand.Reader, k, crypto.SHA256, h[:]) + + case AlgorithmEd25519: + k, ok := key.(ed25519.PrivateKey) + if !ok { + return nil, fmt.Errorf("%w: Ed25519 requires ed25519.PrivateKey, got %T", ErrUnsupportedAlgorithm, key) + } + return ed25519.Sign(k, payload), nil + + default: + return nil, fmt.Errorf("%w: %d", ErrUnsupportedAlgorithm, alg) + } +} + +// verifyWithPub verifies signature over payload using the supplied +// public key under alg. Returns ErrSignatureMismatch when the +// signature does not verify, or ErrUnsupportedAlgorithm if alg or pub +// is unsupported. +func verifyWithPub(pub crypto.PublicKey, alg Algorithm, payload, signature []byte) error { + switch alg { + case AlgorithmECDSAP256SHA256: + p, ok := pub.(*ecdsa.PublicKey) + if !ok { + return fmt.Errorf("%w: ECDSA-P256 requires *ecdsa.PublicKey, got %T", ErrUnsupportedAlgorithm, pub) + } + h := sha256.Sum256(payload) + if !ecdsa.VerifyASN1(p, h[:], signature) { + return ErrSignatureMismatch + } + return nil + + case AlgorithmECDSAP384SHA384: + p, ok := pub.(*ecdsa.PublicKey) + if !ok { + return fmt.Errorf("%w: ECDSA-P384 requires *ecdsa.PublicKey, got %T", ErrUnsupportedAlgorithm, pub) + } + h := sha512.Sum384(payload) + if !ecdsa.VerifyASN1(p, h[:], signature) { + return ErrSignatureMismatch + } + return nil + + case AlgorithmRSAPKCS1v15SHA256: + p, ok := pub.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("%w: RSA-PKCS1v15-SHA256 requires *rsa.PublicKey, got %T", ErrUnsupportedAlgorithm, pub) + } + h := sha256.Sum256(payload) + if err := rsa.VerifyPKCS1v15(p, crypto.SHA256, h[:], signature); err != nil { + return fmt.Errorf("%w: %v", ErrSignatureMismatch, err) + } + return nil + + case AlgorithmEd25519: + p, ok := pub.(ed25519.PublicKey) + if !ok { + return fmt.Errorf("%w: Ed25519 requires ed25519.PublicKey, got %T", ErrUnsupportedAlgorithm, pub) + } + if !ed25519.Verify(p, payload, signature) { + return ErrSignatureMismatch + } + return nil + + default: + return fmt.Errorf("%w: %d", ErrUnsupportedAlgorithm, alg) + } +} diff --git a/signing/certs.go b/signing/certs.go new file mode 100644 index 00000000..557a79ed --- /dev/null +++ b/signing/certs.go @@ -0,0 +1,187 @@ +package signing + +import ( + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "math/big" + "net" + "time" +) + +// CertOptions configures certificate generation in [GenerateCA] and +// [GenerateLeaf]. The zero value yields a 24-hour validity window +// starting one hour in the past (to absorb minor clock skew). +type CertOptions struct { + // NotBefore overrides the validity start. Zero means + // time.Now().Add(-1 * time.Hour). + NotBefore time.Time + // NotAfter overrides the validity end. Zero means + // time.Now().Add(24 * time.Hour). + NotAfter time.Time + // CommonName overrides the certificate's Subject CommonName. + CommonName string + // DNSNames sets the dNSName Subject Alternative Name entries on the + // leaf certificate. Per the OpAMP Message Attestation spec the leaf + // MUST include a SAN that matches the OpAMP distribution server's + // hostname so the Agent can bind the signing certificate to a + // specific server during the connection-time handshake. + DNSNames []string + // IPAddresses sets the iPAddress Subject Alternative Name entries + // on the leaf certificate. Use when the Agent connects to the + // OpAMP server by IP address rather than hostname. + IPAddresses []net.IP +} + +func (o CertOptions) notBefore() time.Time { + if !o.NotBefore.IsZero() { + return o.NotBefore + } + return time.Now().Add(-1 * time.Hour) +} + +func (o CertOptions) notAfter() time.Time { + if !o.NotAfter.IsZero() { + return o.NotAfter + } + return time.Now().Add(24 * time.Hour) +} + +// GenerateCA produces a self-signed CA certificate and its +// corresponding private key for the supplied algorithm. The CA has +// KeyUsageCertSign + KeyUsageDigitalSignature and is marked CA:TRUE +// with a critical basicConstraints extension. +// +// Intended primarily for tests and for the opamp-go example server. +// Production deployments will use externally-managed CA infrastructure. +func GenerateCA(alg Algorithm, opts CertOptions) (*x509.Certificate, crypto.Signer, error) { + key, sigAlg, pub, err := newKey(alg) + if err != nil { + return nil, nil, err + } + + serial, err := randomSerial() + if err != nil { + return nil, nil, err + } + + cn := opts.CommonName + if cn == "" { + cn = fmt.Sprintf("opamp-go test CA (%s)", alg) + } + + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: opts.notBefore(), + NotAfter: opts.notAfter(), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + IsCA: true, + BasicConstraintsValid: true, + SignatureAlgorithm: sigAlg, + } + + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, pub, key) + if err != nil { + return nil, nil, fmt.Errorf("signing: create CA cert: %w", err) + } + cert, err := x509.ParseCertificate(der) + if err != nil { + return nil, nil, fmt.Errorf("signing: parse CA cert: %w", err) + } + return cert, key, nil +} + +// GenerateLeaf produces a leaf signing certificate signed by ca with +// caKey, using alg. The leaf carries ExtKeyUsageCodeSigning (the EKU +// required by the OpAMP Message Attestation spec) and +// KeyUsageDigitalSignature. +// +// Intended primarily for tests and example servers. +func GenerateLeaf(alg Algorithm, ca *x509.Certificate, caKey crypto.Signer, opts CertOptions) (*x509.Certificate, crypto.Signer, error) { + key, sigAlg, pub, err := newKey(alg) + if err != nil { + return nil, nil, err + } + + serial, err := randomSerial() + if err != nil { + return nil, nil, err + } + + cn := opts.CommonName + if cn == "" { + cn = fmt.Sprintf("opamp-go test leaf (%s)", alg) + } + + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: opts.notBefore(), + NotAfter: opts.notAfter(), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + SignatureAlgorithm: sigAlg, + DNSNames: opts.DNSNames, + IPAddresses: opts.IPAddresses, + } + + der, err := x509.CreateCertificate(rand.Reader, tmpl, ca, pub, caKey) + if err != nil { + return nil, nil, fmt.Errorf("signing: create leaf cert: %w", err) + } + cert, err := x509.ParseCertificate(der) + if err != nil { + return nil, nil, fmt.Errorf("signing: parse leaf cert: %w", err) + } + return cert, key, nil +} + +// newKey creates a private key for alg and returns the corresponding +// x509.SignatureAlgorithm to record in certificates, along with the +// public-key form needed by x509.CreateCertificate. +func newKey(alg Algorithm) (crypto.Signer, x509.SignatureAlgorithm, crypto.PublicKey, error) { + switch alg { + case AlgorithmECDSAP256SHA256: + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, 0, nil, fmt.Errorf("signing: generate ECDSA-P256 key: %w", err) + } + return k, x509.ECDSAWithSHA256, &k.PublicKey, nil + case AlgorithmECDSAP384SHA384: + k, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, 0, nil, fmt.Errorf("signing: generate ECDSA-P384 key: %w", err) + } + return k, x509.ECDSAWithSHA384, &k.PublicKey, nil + case AlgorithmRSAPKCS1v15SHA256: + k, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, 0, nil, fmt.Errorf("signing: generate RSA-2048 key: %w", err) + } + return k, x509.SHA256WithRSA, &k.PublicKey, nil + case AlgorithmEd25519: + pub, priv, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, 0, nil, fmt.Errorf("signing: generate Ed25519 key: %w", err) + } + return priv, x509.PureEd25519, pub, nil + default: + return nil, 0, nil, fmt.Errorf("%w: %d", ErrUnsupportedAlgorithm, alg) + } +} + +func randomSerial() (*big.Int, error) { + limit := new(big.Int).Lsh(big.NewInt(1), 128) + n, err := rand.Int(rand.Reader, limit) + if err != nil { + return nil, fmt.Errorf("signing: generate serial: %w", err) + } + return n, nil +} diff --git a/signing/chain.go b/signing/chain.go new file mode 100644 index 00000000..d7a62ef3 --- /dev/null +++ b/signing/chain.go @@ -0,0 +1,92 @@ +package signing + +import ( + "context" + "crypto/x509" + "errors" + "fmt" + "time" +) + +// Sentinel errors for chain validation. Callers can use errors.Is to +// distinguish failure modes (for example, to log a structured reason +// for terminating a connection). +var ( + // ErrEmptyChain is returned when ValidateChain is called with an + // empty chainDER slice. The OpAMP spec requires at least the leaf + // signing certificate to be present. + ErrEmptyChain = errors.New("signing: empty certificate chain") + + // ErrParseCertificate wraps an inner x509 parse failure on one of + // the chain entries. + ErrParseCertificate = errors.New("signing: parse certificate") + + // ErrChainValidation wraps an inner x509 path-validation failure + // (expired cert, unknown issuer, missing EKU, etc.). The wrapped + // error preserves the original x509-level reason. + ErrChainValidation = errors.New("signing: chain validation") + + // ErrSignatureMismatch is returned when a detached signature does + // not verify against the supplied public key and payload bytes. + ErrSignatureMismatch = errors.New("signing: signature does not verify") +) + +// ValidateChain performs RFC 5280 §6 X.509 path validation of the +// supplied DER certificate chain against the trust anchor pool in +// roots. +// +// The chain MUST be ordered intermediates first, leaf last, matching +// the on-wire ordering of SignedServerToAgent.trust_chain_response. +// The root certificate (the Agent's pre-configured payload trust +// anchor) is supplied via roots and MUST NOT appear in chainDER. +// +// The leaf certificate MUST carry the id-kp-codeSigning Extended Key +// Usage (OID 1.3.6.1.5.5.7.3.3). This prevents certificates issued +// for TLS server authentication from being repurposed to sign OpAMP +// messages. +// +// Other RFC 5280 checks — per-certificate signature, validity window, +// basicConstraints, pathLenConstraint, critical extensions — are +// enforced by the underlying crypto/x509 implementation. +// +// Revocation checking via CRL/OCSP is RECOMMENDED by the OpAMP spec +// but not performed here in the current implementation; that is a +// follow-up. Operators MAY rely on short-lived signing certificates +// as a complementary mitigation. +func ValidateChain(_ context.Context, chainDER [][]byte, roots *x509.CertPool, now time.Time) (*x509.Certificate, error) { + if len(chainDER) == 0 { + return nil, ErrEmptyChain + } + if roots == nil { + return nil, fmt.Errorf("%w: nil trust anchor pool", ErrChainValidation) + } + + certs := make([]*x509.Certificate, 0, len(chainDER)) + for i, der := range chainDER { + cert, err := x509.ParseCertificate(der) + if err != nil { + return nil, fmt.Errorf("%w: chain[%d]: %v", ErrParseCertificate, i, err) + } + certs = append(certs, cert) + } + + leaf := certs[len(certs)-1] + + intermediates := x509.NewCertPool() + for i := 0; i < len(certs)-1; i++ { + intermediates.AddCert(certs[i]) + } + + opts := x509.VerifyOptions{ + Roots: roots, + Intermediates: intermediates, + CurrentTime: now, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + } + + if _, err := leaf.Verify(opts); err != nil { + return nil, fmt.Errorf("%w: %v", ErrChainValidation, err) + } + + return leaf, nil +} diff --git a/signing/doc.go b/signing/doc.go new file mode 100644 index 00000000..92ed5d45 --- /dev/null +++ b/signing/doc.go @@ -0,0 +1,30 @@ +// Package signing implements payload trust verification (Message +// Attestation) for the OpAMP protocol. +// +// The package exposes two interfaces — [Signer] and [Verifier] — together +// with in-process reference implementations [LocalSigner] and +// [LocalVerifier]. The split between interface and implementation lets +// downstream consumers plug in alternative signers backed by remote +// signing services (for example HSM-backed RPC endpoints or hosted +// signing platforms with policy gating) without touching the wire-level +// code in the opamp-go client or server. +// +// Signing is performed over the raw bytes of a marshalled +// [protobufs.ServerToAgent] (the bytes carried in +// SignedServerToAgent.payload on the wire), producing a detached +// signature placed in SignedServerToAgent.signature. The receiver +// verifies the signature over the bytes exactly as they arrive on the +// wire — no re-marshalling is required, sidestepping protobuf's +// non-canonical-encoding caveat. See the Message Attestation section +// of the OpAMP specification for the wire protocol. +// +// The signing algorithm for a given connection is determined by the +// signing certificate's SignatureAlgorithm field; the OpAMP protocol +// does not negotiate algorithms. +// +// [GenerateCA] and [GenerateLeaf] are exported test helpers; they +// also serve smoke tests and the example server. Production +// deployments use externally-managed PKI and only need the +// [LocalSigner] / [LocalVerifier] constructors, the loader helpers, +// or a custom [Signer] / [Verifier] implementation. +package signing diff --git a/signing/loader.go b/signing/loader.go new file mode 100644 index 00000000..53898984 --- /dev/null +++ b/signing/loader.go @@ -0,0 +1,147 @@ +package signing + +import ( + "crypto" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "os" +) + +// ErrLoadCAFile wraps failures to read or parse the operator-supplied +// trust anchor PEM file. +var ErrLoadCAFile = errors.New("signing: load CA file") + +// ErrParsePrivateKey wraps failures to decode a PEM-encoded private +// key. Multiple PKCS encodings are tried in turn (PKCS#8, EC, PKCS#1). +var ErrParsePrivateKey = errors.New("signing: parse private key") + +// VerifierFromFile constructs a LocalVerifier whose trust anchor pool +// is populated from a PEM file at caPath. The file MUST contain one or +// more PEM-encoded X.509 certificates; any non-CERTIFICATE PEM blocks +// (for example RSA PRIVATE KEY blocks accidentally left in the file) +// are ignored. +// +// Typical use: the opamp-go client supervisor or extension calls this +// at startup with the operator-supplied payload_ca path. +func VerifierFromFile(caPath string) (*LocalVerifier, error) { + if caPath == "" { + return nil, fmt.Errorf("%w: empty path", ErrLoadCAFile) + } + data, err := os.ReadFile(caPath) + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrLoadCAFile, err) + } + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(data) { + return nil, fmt.Errorf("%w: no valid PEM certificates in %s", ErrLoadCAFile, caPath) + } + return NewLocalVerifier(pool) +} + +// VerifierFromPEM constructs a LocalVerifier whose trust anchor pool is +// populated from pemBytes. Useful when the CA certificate bytes are already +// in memory (for example, after a TOFU enrollment). +func VerifierFromPEM(pemBytes []byte) (*LocalVerifier, error) { + if len(pemBytes) == 0 { + return nil, fmt.Errorf("%w: empty PEM bytes", ErrLoadCAFile) + } + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(pemBytes) { + return nil, fmt.Errorf("%w: no valid PEM certificates in supplied bytes", ErrLoadCAFile) + } + return NewLocalVerifier(pool) +} + +// LocalSignerFromFiles constructs a LocalSigner from PEM-encoded files: +// +// - keyPath: path to a PEM file containing the leaf signing private +// key. PKCS#8, EC, and PKCS#1 encodings are accepted. +// - chainPath: path to a PEM file containing the certificate chain. +// The chain MUST be ordered intermediates first, leaf last, and the +// leaf cert MUST correspond to the private key. The root MUST NOT +// be included. +// +// Intended for example servers, smoke tests, and any deployment that +// stores signing material as PEM files on disk. +func LocalSignerFromFiles(keyPath, chainPath string) (*LocalSigner, error) { + if keyPath == "" { + return nil, errors.New("signing: empty key path") + } + if chainPath == "" { + return nil, errors.New("signing: empty chain path") + } + + keyBytes, err := os.ReadFile(keyPath) + if err != nil { + return nil, fmt.Errorf("signing: read key: %w", err) + } + chainBytes, err := os.ReadFile(chainPath) + if err != nil { + return nil, fmt.Errorf("signing: read chain: %w", err) + } + + key, err := parsePrivateKeyPEM(keyBytes) + if err != nil { + return nil, err + } + + chain, err := parseCertChainPEM(chainBytes) + if err != nil { + return nil, err + } + if len(chain) == 0 { + return nil, ErrEmptyChain + } + + return NewLocalSigner(key, chain) +} + +func parsePrivateKeyPEM(data []byte) (crypto.Signer, error) { + block, _ := pem.Decode(data) + if block == nil { + return nil, fmt.Errorf("%w: no PEM block found", ErrParsePrivateKey) + } + // PKCS#8 first — covers RSA, ECDSA, and Ed25519 in one call. If it + // succeeds, we accept any key type that implements crypto.Signer + // (which all current and likely-future stdlib private-key types + // do). + if k, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil { + s, ok := k.(crypto.Signer) + if !ok { + return nil, fmt.Errorf("%w: PKCS#8 key type %T does not implement crypto.Signer", ErrParsePrivateKey, k) + } + return s, nil + } + // PKCS#1 for legacy RSA private keys. + if k, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil { + return k, nil + } + // EC for legacy ECDSA private keys. + if k, err := x509.ParseECPrivateKey(block.Bytes); err == nil { + return k, nil + } + return nil, fmt.Errorf("%w: tried PKCS#8, PKCS#1, EC — none matched", ErrParsePrivateKey) +} + +func parseCertChainPEM(data []byte) ([]*x509.Certificate, error) { + var chain []*x509.Certificate + rest := data + for { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + continue + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf("signing: parse certificate in chain: %w", err) + } + chain = append(chain, cert) + } + return chain, nil +} diff --git a/signing/local_signer.go b/signing/local_signer.go new file mode 100644 index 00000000..550a0891 --- /dev/null +++ b/signing/local_signer.go @@ -0,0 +1,130 @@ +package signing + +import ( + "context" + "crypto" + "crypto/x509" + "encoding/pem" + "errors" +) + +// ErrNilKey is returned by NewLocalSigner when key is nil. +var ErrNilKey = errors.New("signing: nil private key") + +// LocalSigner is the in-process reference implementation of [Signer]. +// It holds a private key and certificate chain in memory and signs +// requests synchronously without any network IO. +// +// LocalSigner is suitable for tests, the opamp-go example server, and +// any deployment where the signing private key is colocated with the +// OpAMP server process. Deployments that delegate signing to a hosted +// platform (HSM-backed RPC, central signing service) should provide +// their own Signer implementation; the wire-level opamp-go code is +// agnostic to which Signer is in use. +// +// LocalSigner is safe for concurrent use: the underlying crypto.Signer +// implementations in the Go standard library are themselves +// concurrency-safe. +type LocalSigner struct { + key crypto.Signer + alg Algorithm + chainDER [][]byte + rootCADER []byte // set via WithRootCA; nil unless TOFU is supported +} + +// NewLocalSigner constructs a LocalSigner from the supplied private +// key (typically a crypto.Signer implementation from the standard +// library) and certificate chain. +// +// The chain MUST be ordered intermediates first, leaf last; the leaf +// is the certificate whose private key signs payloads. The root MUST +// NOT be included — the Agent supplies the root via its pre-configured +// trust anchor pool. +// +// The signing algorithm is determined by the leaf certificate's public +// key type and (for ECDSA) curve, cross-checked against the cert's +// SignatureAlgorithm field. ErrUnsupportedAlgorithm is returned for +// any pubkey type/curve outside the supported baseline, for RSA keys +// below the minimum modulus (rsaMinModulusBits), or when +// SignatureAlgorithm does not match the leaf's actual key. +func NewLocalSigner(key crypto.Signer, chain []*x509.Certificate) (*LocalSigner, error) { + if key == nil { + return nil, ErrNilKey + } + if len(chain) == 0 { + return nil, ErrEmptyChain + } + leaf := chain[len(chain)-1] + alg, err := algorithmFromCert(leaf) + if err != nil { + return nil, err + } + + chainDER := make([][]byte, len(chain)) + for i, cert := range chain { + // cert.Raw is the DER bytes the certificate was parsed from + // (or that x509.CreateCertificate produced). Copy to defend + // against later mutation of cert.Raw by callers, even though + // it's expected to be immutable in practice. + raw := make([]byte, len(cert.Raw)) + copy(raw, cert.Raw) + chainDER[i] = raw + } + + return &LocalSigner{ + key: key, + alg: alg, + chainDER: chainDER, + }, nil +} + +// Sign implements [Signer]. The context is honoured only for +// cancellation; the in-process signing operation itself does not block. +func (s *LocalSigner) Sign(ctx context.Context, payload []byte) ([]byte, error) { + if err := ctx.Err(); err != nil { + return nil, err + } + return signWithKey(s.key, s.alg, payload) +} + +// ChainDER implements [Signer]. Returns a defensive copy so callers +// cannot mutate the signer's internal state. +func (s *LocalSigner) ChainDER(ctx context.Context) ([][]byte, error) { + if err := ctx.Err(); err != nil { + return nil, err + } + out := make([][]byte, len(s.chainDER)) + for i, der := range s.chainDER { + clone := make([]byte, len(der)) + copy(clone, der) + out[i] = clone + } + return out, nil +} + +// Algorithm reports the algorithm dispatched by this signer (derived +// from the leaf certificate). Exposed for diagnostics and tests. +func (s *LocalSigner) Algorithm() Algorithm { + return s.alg +} + +// WithRootCA attaches the root CA certificate to this signer, enabling +// [TrustAnchorProvider] support. The root CA is included in +// trust_chain_response.tofu_trust_anchor during TOFU enrollment so that +// Agents with no pre-configured trust anchor can bootstrap and persist it. +// Returns the receiver for chaining. +func (s *LocalSigner) WithRootCA(ca *x509.Certificate) *LocalSigner { + der := make([]byte, len(ca.Raw)) + copy(der, ca.Raw) + s.rootCADER = der + return s +} + +// TrustAnchorPEM implements [TrustAnchorProvider]. Returns the PEM-encoded +// root CA set by [WithRootCA]. Returns an error if WithRootCA was not called. +func (s *LocalSigner) TrustAnchorPEM(_ context.Context) ([]byte, error) { + if len(s.rootCADER) == 0 { + return nil, errors.New("signing: no root CA configured on LocalSigner (call WithRootCA first)") + } + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.rootCADER}), nil +} diff --git a/signing/local_verifier.go b/signing/local_verifier.go new file mode 100644 index 00000000..92468c52 --- /dev/null +++ b/signing/local_verifier.go @@ -0,0 +1,67 @@ +package signing + +import ( + "context" + "crypto/x509" + "errors" + "time" +) + +// ErrNilRoots is returned by NewLocalVerifier when roots is nil. +var ErrNilRoots = errors.New("signing: nil trust anchor pool") + +// LocalVerifier is the in-process reference implementation of +// [Verifier]. It wraps a trust anchor pool and uses [ValidateChain] +// for path validation plus the algorithm-dispatch table in +// algorithm.go for signature verification. +// +// LocalVerifier is safe for concurrent use. +type LocalVerifier struct { + roots *x509.CertPool +} + +// NewLocalVerifier constructs a LocalVerifier that will validate +// delivered certificate chains against the supplied trust anchor pool. +// +// The trust anchor pool MUST be operator-managed and supplied +// out-of-band (typically a PEM file path read at startup); it MUST NOT +// be installed or modified by any OpAMP message. +func NewLocalVerifier(roots *x509.CertPool) (*LocalVerifier, error) { + if roots == nil { + return nil, ErrNilRoots + } + return &LocalVerifier{roots: roots}, nil +} + +// ValidateChain implements [Verifier], delegating to the package-level +// [ValidateChain] function with the verifier's trust anchor pool. +func (v *LocalVerifier) ValidateChain(ctx context.Context, chainDER [][]byte, now time.Time) (*x509.Certificate, error) { + if err := ctx.Err(); err != nil { + return nil, err + } + return ValidateChain(ctx, chainDER, v.roots, now) +} + +// Verify implements [Verifier]. The signature algorithm is derived +// from the leaf certificate's public-key type and (for ECDSA) curve, +// cross-checked against leaf.SignatureAlgorithm. +// ErrUnsupportedAlgorithm is returned for any pubkey type/curve +// outside the supported baseline (or when leaf.SignatureAlgorithm +// disagrees with the actual key). ErrSignatureMismatch is returned +// when the signature does not verify. +func (v *LocalVerifier) Verify(ctx context.Context, payload, signature []byte, leaf *x509.Certificate) error { + if err := ctx.Err(); err != nil { + return err + } + if leaf == nil { + return errors.New("signing: nil leaf certificate") + } + if len(signature) == 0 { + return errors.New("signing: empty signature") + } + alg, err := algorithmFromCert(leaf) + if err != nil { + return err + } + return verifyWithPub(leaf.PublicKey, alg, payload, signature) +} diff --git a/signing/remote_signer.go b/signing/remote_signer.go new file mode 100644 index 00000000..47ddaab4 --- /dev/null +++ b/signing/remote_signer.go @@ -0,0 +1,138 @@ +package signing + +import ( + "bytes" + "context" + "encoding/pem" + "fmt" + "io" + "net/http" + "strings" + "time" +) + +// RemoteSigner implements [Signer] by delegating to an out-of-process HTTP +// signing service. This is the recommended production deployment pattern +// described in supplementary-guidelines.md: the OpAMP distribution server +// holds no private key material, and signing is performed by a separate +// policy server that is not reachable from the network edge. +// +// The signing service must expose two endpoints: +// +// POST /v1/sign — request body: raw payload bytes to sign +// — response body: raw signature bytes +// GET /v1/chain — response body: PEM-encoded certificate chain +// — (intermediates first, signing leaf last, root excluded) +// +// In production the policy server may additionally enforce organizational +// policy — inspecting the decoded payload to deny message types, enforce +// per-team permissions, or apply fleet-wide invariants — before delegating +// to an HSM or secrets manager for the actual signature. +type RemoteSigner struct { + baseURL string + client *http.Client +} + +var _ Signer = (*RemoteSigner)(nil) +var _ TrustAnchorProvider = (*RemoteSigner)(nil) + +// NewRemoteSigner returns a RemoteSigner that calls the signing service at +// baseURL (e.g. "http://policy-server:4322"). A 10-second per-request +// timeout is applied. +func NewRemoteSigner(baseURL string) *RemoteSigner { + return &RemoteSigner{ + baseURL: strings.TrimRight(baseURL, "/"), + client: &http.Client{Timeout: 10 * time.Second}, + } +} + +// Sign implements [Signer] by POST-ing payload to /v1/sign and returning +// the response body as the detached signature. +func (s *RemoteSigner) Sign(ctx context.Context, payload []byte) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodPost, + s.baseURL+"/v1/sign", bytes.NewReader(payload)) + if err != nil { + return nil, fmt.Errorf("remote signer: build sign request: %w", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + resp, err := s.client.Do(req) + if err != nil { + return nil, fmt.Errorf("remote signer: sign request: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("remote signer: read sign response: %w", err) + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("remote signer: sign returned HTTP %d: %s", resp.StatusCode, body) + } + return body, nil +} + +// TrustAnchorPEM implements [TrustAnchorProvider] by GET-ing /v1/ca on the +// remote policy server. The response MUST be a PEM-encoded CA certificate. +func (s *RemoteSigner) TrustAnchorPEM(ctx context.Context) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, + s.baseURL+"/v1/ca", nil) + if err != nil { + return nil, fmt.Errorf("remote signer: build CA request: %w", err) + } + resp, err := s.client.Do(req) + if err != nil { + return nil, fmt.Errorf("remote signer: CA request: %w", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("remote signer: read CA response: %w", err) + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("remote signer: CA returned HTTP %d: %s", resp.StatusCode, body) + } + return body, nil +} + +// ChainDER implements [Signer] by GET-ing /v1/chain and decoding the +// returned PEM blob into DER byte slices ordered intermediates-first, +// leaf-last. +func (s *RemoteSigner) ChainDER(ctx context.Context) ([][]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, + s.baseURL+"/v1/chain", nil) + if err != nil { + return nil, fmt.Errorf("remote signer: build chain request: %w", err) + } + + resp, err := s.client.Do(req) + if err != nil { + return nil, fmt.Errorf("remote signer: chain request: %w", err) + } + defer resp.Body.Close() + + pemBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("remote signer: read chain response: %w", err) + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("remote signer: chain returned HTTP %d: %s", resp.StatusCode, pemBytes) + } + + var chain [][]byte + rest := pemBytes + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type == "CERTIFICATE" { + chain = append(chain, block.Bytes) + } + } + if len(chain) == 0 { + return nil, fmt.Errorf("remote signer: chain response contained no CERTIFICATE PEM blocks") + } + return chain, nil +} diff --git a/signing/tofu.go b/signing/tofu.go new file mode 100644 index 00000000..39686173 --- /dev/null +++ b/signing/tofu.go @@ -0,0 +1,76 @@ +package signing + +import ( + "errors" + "fmt" + "os" +) + +// TOFUStore persists the payload trust anchor acquired during a Trust On First +// Use (TOFU) enrollment. The Agent calls Save once — on first connection — and +// Load on every subsequent startup. +// +// Implementations MUST be idempotent on Save: if a trust anchor is already +// stored, a second Save call MUST be a no-op. This prevents a reconnecting +// agent from overwriting a valid anchor with a potentially attacker-supplied +// one. +type TOFUStore interface { + // Load returns the PEM-encoded trust anchor bytes saved by a previous + // Save call, or nil if no anchor has been stored yet. + Load() ([]byte, error) + + // Save persists pemBytes as the trust anchor. Called at most once per + // store lifetime; subsequent calls MUST be ignored if an anchor is + // already present. + Save(pemBytes []byte) error +} + +// ErrTOFUStoreSave wraps failures to persist the TOFU trust anchor. +var ErrTOFUStoreSave = errors.New("signing: save TOFU trust anchor") + +// FileTOFUStore implements [TOFUStore] by reading and writing a single PEM +// file. The file is created on first Save with 0o600 permissions. If the +// file already exists when Save is called, Save is a no-op (idempotent as +// required by the interface contract). +// +// The store is safe for concurrent use within one process, but does not use +// file locking; two processes writing to the same path concurrently may +// corrupt the file. +type FileTOFUStore struct { + path string +} + +// NewFileTOFUStore returns a FileTOFUStore that persists the trust anchor at +// path. The path does not need to exist yet; it is created on first Save. +func NewFileTOFUStore(path string) *FileTOFUStore { + return &FileTOFUStore{path: path} +} + +// Load reads the trust anchor from the file. Returns nil, nil if the file +// does not exist. +func (s *FileTOFUStore) Load() ([]byte, error) { + data, err := os.ReadFile(s.path) + if errors.Is(err, os.ErrNotExist) { + return nil, nil + } + if err != nil { + return nil, fmt.Errorf("signing: load TOFU trust anchor: %w", err) + } + return data, nil +} + +// Save writes pemBytes to the file only if the file does not already exist. +func (s *FileTOFUStore) Save(pemBytes []byte) error { + f, err := os.OpenFile(s.path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) + if errors.Is(err, os.ErrExist) { + return nil // idempotent: already stored + } + if err != nil { + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + defer f.Close() + if _, err := f.Write(pemBytes); err != nil { + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + return nil +} diff --git a/signing/types.go b/signing/types.go new file mode 100644 index 00000000..b8b34be8 --- /dev/null +++ b/signing/types.go @@ -0,0 +1,116 @@ +package signing + +import ( + "context" + "crypto/x509" + "time" +) + +// Algorithm identifies the signature algorithm used by a signing +// certificate. The OpAMP protocol does not negotiate algorithms; the +// algorithm in use is determined by the certificate's SignatureAlgorithm +// field. This enum exists so that test helpers, cert generators, and +// internal dispatch tables can refer to a specific algorithm by name. +type Algorithm uint8 + +const ( + // AlgorithmUnspecified is the zero value and is never a valid + // algorithm in production. + AlgorithmUnspecified Algorithm = iota + // AlgorithmECDSAP256SHA256 — ECDSA over the P-256 curve with + // SHA-256, DER-encoded (r,s) signatures. + AlgorithmECDSAP256SHA256 + // AlgorithmECDSAP384SHA384 — ECDSA over the P-384 curve with + // SHA-384, DER-encoded (r,s) signatures. + AlgorithmECDSAP384SHA384 + // AlgorithmRSAPKCS1v15SHA256 — RSA with PKCS#1 v1.5 padding and + // SHA-256. Minimum 2048-bit modulus recommended. + AlgorithmRSAPKCS1v15SHA256 + // AlgorithmEd25519 — Ed25519 (signs the payload directly; no + // pre-hash). + AlgorithmEd25519 +) + +// String returns the canonical name of the algorithm. +func (a Algorithm) String() string { + switch a { + case AlgorithmECDSAP256SHA256: + return "ECDSA-P256-SHA256" + case AlgorithmECDSAP384SHA384: + return "ECDSA-P384-SHA384" + case AlgorithmRSAPKCS1v15SHA256: + return "RSA-PKCS1v15-SHA256" + case AlgorithmEd25519: + return "Ed25519" + default: + return "unspecified" + } +} + +// Signer produces detached signatures over arbitrary payload bytes and +// supplies the signing certificate chain. +// +// Implementations may sign locally with an in-process key (see +// [LocalSigner]) or delegate to an external signing service (HSM, +// remote signing RPC, hosted platforms with policy gating). Sign and +// ChainDER both accept a context so RPC-backed implementations can +// cancel, set deadlines, and propagate trace IDs. +type Signer interface { + // Sign computes a signature over payload. The OpAMP server places + // the returned bytes into SignedServerToAgent.signature on the + // wire. The signing algorithm is determined by the signing + // certificate; the caller does not pass it explicitly. + Sign(ctx context.Context, payload []byte) ([]byte, error) + + // ChainDER returns the signing certificate chain in DER form, + // ordered from the first intermediate down to the signing leaf. + // The root certificate (which the Agent already possesses as its + // pre-configured payload trust anchor) is excluded. + // + // The OpAMP server snapshots this once per new client connection + // and reuses the result for the connection's lifetime so that + // mid-session rotation on the signer side does not change the + // chain mid-stream. + ChainDER(ctx context.Context) ([][]byte, error) +} + +// TrustAnchorProvider is an optional interface that [Signer] implementations +// may satisfy when they also hold the root CA certificate. The OpAMP server +// checks for this interface (via type assertion) to populate +// trust_chain_response.tofu_trust_anchor during TOFU enrollment. +// Signers that do not hold the root CA (for example, a remote HSM-backed +// signer that only exposes the leaf chain) need not implement this interface; +// TOFU enrollment will simply not be available for those deployments. +type TrustAnchorProvider interface { + // TrustAnchorPEM returns the PEM-encoded root CA certificate that Agents + // should use as their payload trust anchor. + TrustAnchorPEM(ctx context.Context) ([]byte, error) +} + +// Verifier validates a delivered trust chain and verifies detached +// signatures against the resulting leaf certificate. +// +// Implementations are expected to perform RFC 5280 §6 X.509 path +// validation in ValidateChain. The Verify method performs the +// signature-only check against the leaf returned by a successful +// ValidateChain call. +type Verifier interface { + // ValidateChain performs RFC 5280 §6 path validation of the + // supplied DER certificate chain against the verifier's + // pre-configured trust anchor pool. The chain MUST be ordered + // intermediates first, leaf last; the root is supplied via the + // verifier's configuration and MUST NOT appear in chainDER. + // + // Returns the validated leaf certificate on success. The Agent + // stores the leaf for the duration of the connection and passes + // it to Verify on every subsequent message. + ValidateChain(ctx context.Context, chainDER [][]byte, now time.Time) (*x509.Certificate, error) + + // Verify validates signature over payload using the public key of + // leaf. The signature algorithm is derived from leaf's public-key + // type and (for ECDSA) curve, cross-checked against + // leaf.SignatureAlgorithm. The payload bytes are the wire bytes of + // SignedServerToAgent.payload — the receiver does not re-marshal + // anything. + Verify(ctx context.Context, payload, signature []byte, leaf *x509.Certificate) error +} From ab5428a70603de05125416e087a21c8758effd30 Mon Sep 17 00:00:00 2001 From: Stanley Liu Date: Thu, 2 Jul 2026 19:26:17 -0400 Subject: [PATCH 2/3] Fix bugs with TOFU atomic write, leaf-key algorithm, and SAN check for empty string hostname --- client/internal/attestation.go | 21 ++++++++++++--- client/internal/wsreceiver.go | 7 ++++- signing/algorithm.go | 48 +++++++++++----------------------- signing/tofu.go | 46 +++++++++++++++++++++++++++++--- 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/client/internal/attestation.go b/client/internal/attestation.go index 52986998..d0a4321c 100644 --- a/client/internal/attestation.go +++ b/client/internal/attestation.go @@ -36,6 +36,14 @@ var ( // spec this is a fatal handshake error. ErrSANMismatch = errors.New("client: leaf certificate SAN does not match server hostname") + // ErrServerNameUnavailable is returned when payload trust + // verification is enabled but the Agent could not determine the + // server hostname to check the leaf certificate's SAN against (for + // example, the server URL was empty or unparseable). SAN + // verification is mandatory when attestation is on, so rather than + // silently skip it the handshake fails closed. + ErrServerNameUnavailable = errors.New("client: cannot verify leaf certificate SAN: server hostname unavailable") + // ErrTOFUAnchorMissing is returned during TOFU enrollment when the // Server's TrustChainResponse does not include the expected // tofu_trust_anchor field. @@ -191,10 +199,15 @@ func (s *attestationState) ProcessEnvelope(ctx context.Context, envelope *protob if err != nil { return nil, fmt.Errorf("client: validate trust chain: %w", err) } - if s.serverName != "" { - if err := leaf.VerifyHostname(s.serverName); err != nil { - return nil, fmt.Errorf("%w: %v", ErrSANMismatch, err) - } + // SAN verification is mandatory when attestation is enabled. An + // empty serverName means the server hostname could not be + // resolved from the connection URL; fail closed rather than + // silently accept any certificate. + if s.serverName == "" { + return nil, ErrServerNameUnavailable + } + if err := leaf.VerifyHostname(s.serverName); err != nil { + return nil, fmt.Errorf("%w: %v", ErrSANMismatch, err) } s.leaf = leaf s.firstSeen = true diff --git a/client/internal/wsreceiver.go b/client/internal/wsreceiver.go index 37b1bf69..55eaef4a 100644 --- a/client/internal/wsreceiver.go +++ b/client/internal/wsreceiver.go @@ -68,7 +68,12 @@ func NewWSReceiver( } if payloadVerifier != nil || tofuStore != nil { var serverName string - if parsed, err := url.Parse(serverURL); err == nil { + if parsed, err := url.Parse(serverURL); err != nil { + // Fail closed downstream: an empty serverName makes + // ProcessEnvelope reject the handshake with + // ErrServerNameUnavailable rather than skip SAN verification. + logger.Errorf(context.Background(), "Cannot parse server URL %q for SAN verification: %v", serverURL, err) + } else { serverName = parsed.Hostname() } w.attestation = newAttestationState(payloadVerifier, serverName, tofuStore) diff --git a/signing/algorithm.go b/signing/algorithm.go index 4b2b166a..da102485 100644 --- a/signing/algorithm.go +++ b/signing/algorithm.go @@ -18,27 +18,25 @@ import ( // below this size are rejected even if the rest of the chain validates. const rsaMinModulusBits = 2048 -// ErrUnsupportedAlgorithm indicates that a certificate's public key -// (or the algorithm declared by the issuer's signature on the cert) -// is not in the supported set: it is the wrong key type, an -// unsupported ECDSA curve, an RSA key below rsaMinModulusBits, or the -// declared SignatureAlgorithm does not match the leaf's actual key -// type/curve. +// ErrUnsupportedAlgorithm indicates that a certificate's public key is +// not in the supported set: it is the wrong key type, an unsupported +// ECDSA curve, or an RSA key below rsaMinModulusBits. var ErrUnsupportedAlgorithm = errors.New("signing: unsupported signature algorithm") // algorithmFromCert derives the Algorithm to use for signature -// operations involving cert. Dispatching on the leaf's own public key -// type (rather than on cert.SignatureAlgorithm, which describes the -// issuer's signing of the cert itself) is the correct authority: the -// Algorithm controls how a payload is signed/verified, and that has to -// match the leaf key's algorithm and curve, not the issuer's. +// operations involving cert, dispatching on the leaf's own public key +// type and (for ECDSA) curve. This is the correct authority: the +// Algorithm controls how a payload is signed/verified, so it must match +// the leaf key's type and curve. // -// The function additionally cross-checks cert.SignatureAlgorithm -// against the leaf key so that a certificate whose declared algorithm -// is inconsistent with its pubkey is rejected up front. This prevents -// a within-family mismatch (e.g., a P-384 CA issuing a P-256 leaf with -// SignatureAlgorithm=ECDSAWithSHA384) from silently accepting the -// wrong hash size at sign/verify time. +// cert.SignatureAlgorithm is deliberately NOT consulted. That field +// describes the algorithm the issuer used to sign this certificate, +// which is independent of the leaf key: a P-384 CA may legitimately +// issue a P-256 leaf, in which case cert.SignatureAlgorithm is +// ECDSAWithSHA384 even though the leaf signs payloads with P-256/SHA-256. +// The payload algorithm is fully determined by the leaf key returned +// here, so the issuer's signing algorithm is irrelevant and checking it +// would only reject valid cross-algorithm PKI hierarchies. // // Minimum RSA modulus is rsaMinModulusBits. func algorithmFromCert(cert *x509.Certificate) (Algorithm, error) { @@ -46,16 +44,8 @@ func algorithmFromCert(cert *x509.Certificate) (Algorithm, error) { case *ecdsa.PublicKey: switch pub.Curve { case elliptic.P256(): - if cert.SignatureAlgorithm != x509.ECDSAWithSHA256 { - return AlgorithmUnspecified, fmt.Errorf("%w: P-256 leaf with mismatched declared algorithm %s", - ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) - } return AlgorithmECDSAP256SHA256, nil case elliptic.P384(): - if cert.SignatureAlgorithm != x509.ECDSAWithSHA384 { - return AlgorithmUnspecified, fmt.Errorf("%w: P-384 leaf with mismatched declared algorithm %s", - ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) - } return AlgorithmECDSAP384SHA384, nil default: curveName := "unknown" @@ -74,16 +64,8 @@ func algorithmFromCert(cert *x509.Certificate) (Algorithm, error) { return AlgorithmUnspecified, fmt.Errorf("%w: RSA key %d bits < %d", ErrUnsupportedAlgorithm, bits, rsaMinModulusBits) } - if cert.SignatureAlgorithm != x509.SHA256WithRSA { - return AlgorithmUnspecified, fmt.Errorf("%w: RSA leaf with mismatched declared algorithm %s", - ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) - } return AlgorithmRSAPKCS1v15SHA256, nil case ed25519.PublicKey: - if cert.SignatureAlgorithm != x509.PureEd25519 { - return AlgorithmUnspecified, fmt.Errorf("%w: Ed25519 leaf with mismatched declared algorithm %s", - ErrUnsupportedAlgorithm, cert.SignatureAlgorithm) - } return AlgorithmEd25519, nil default: return AlgorithmUnspecified, fmt.Errorf("%w: unsupported public key type %T", diff --git a/signing/tofu.go b/signing/tofu.go index 39686173..77a866f9 100644 --- a/signing/tofu.go +++ b/signing/tofu.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "path/filepath" ) // TOFUStore persists the payload trust anchor acquired during a Trust On First @@ -60,16 +61,53 @@ func (s *FileTOFUStore) Load() ([]byte, error) { } // Save writes pemBytes to the file only if the file does not already exist. +// +// The write is atomic: pemBytes is first written in full to a temporary +// file in the same directory, then hard-linked into place with os.Link, +// which fails if the target already exists. This preserves the write-once +// (idempotent) contract while guaranteeing the anchor file is never left +// in a partially-written state — a crash, disk-full, or short write during +// the temp write leaves only the temp file (which is removed), never a +// truncated or empty anchor that would permanently shadow future Saves. func (s *FileTOFUStore) Save(pemBytes []byte) error { - f, err := os.OpenFile(s.path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) - if errors.Is(err, os.ErrExist) { + // Fast path: anchor already present, nothing to do. + if _, err := os.Stat(s.path); err == nil { return nil // idempotent: already stored + } else if !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) } + + tmp, err := os.CreateTemp(filepath.Dir(s.path), ".tofu-*.tmp") if err != nil { return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) } - defer f.Close() - if _, err := f.Write(pemBytes); err != nil { + tmpName := tmp.Name() + // Remove the temp file on every path: on error, and after a successful + // link (the linked target keeps the content; the temp name is redundant). + defer os.Remove(tmpName) + + if err := tmp.Chmod(0o600); err != nil { + tmp.Close() + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + if _, err := tmp.Write(pemBytes); err != nil { + tmp.Close() + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + if err := tmp.Sync(); err != nil { + tmp.Close() + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + if err := tmp.Close(); err != nil { + return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) + } + + // os.Link fails with ErrExist if the anchor was created concurrently + // (or between the Stat above and here), preserving write-once semantics. + if err := os.Link(tmpName, s.path); err != nil { + if errors.Is(err, os.ErrExist) { + return nil // idempotent: another writer won the race + } return fmt.Errorf("%w: %v", ErrTOFUStoreSave, err) } return nil From a6706ac426799441f6eb96d524568bea8e869012 Mon Sep 17 00:00:00 2001 From: Stanley Liu Date: Thu, 2 Jul 2026 22:56:44 -0400 Subject: [PATCH 3/3] Fix WS client tight reconnect loop: back off on abnormal close when attestation enabled --- client/internal/wsreceiver.go | 24 +++++++++++ client/wsclient.go | 75 ++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 23 deletions(-) diff --git a/client/internal/wsreceiver.go b/client/internal/wsreceiver.go index 55eaef4a..f661b6b1 100644 --- a/client/internal/wsreceiver.go +++ b/client/internal/wsreceiver.go @@ -35,6 +35,15 @@ type wsReceiver struct { // of a payload trust verification failure. Safe to read only after // <-IsStopped() returns. attestationFailure bool + + // Set to true (before stopped is closed) when the loop exits because + // of an abnormal connection close while attestation is enabled. A + // server that accepts the connection and then drops it without a + // normal-closure handshake is, in an attestation deployment, almost + // always failing to sign (e.g. its signing/policy backend is down); + // the caller uses this to back off instead of reconnecting in a tight + // loop. Safe to read only after <-IsStopped() returns. + connectionError bool } // NewWSReceiver creates a new Receiver that uses WebSocket to receive @@ -98,6 +107,13 @@ func (r *wsReceiver) WasAttestationFailure() bool { return r.attestationFailure } +// WasConnectionError reports whether the receiver stopped because of an +// abnormal connection close while attestation is enabled. Only valid after +// <-IsStopped() returns. +func (r *wsReceiver) WasConnectionError() bool { + return r.connectionError +} + // ReceiverLoop runs the receiver loop. // To stop the receiver cancel the context and close the websocket connection func (r *wsReceiver) ReceiverLoop(ctx context.Context) { @@ -150,6 +166,14 @@ func (r *wsReceiver) ReceiverLoop(ctx context.Context) { } if !websocket.IsCloseError(res.err, websocket.CloseNormalClosure) { r.logger.Errorf(ctx, "Unexpected error while receiving: %v", res.err) + // When attestation is enabled, an abnormal close + // usually means the server terminated the connection + // because it could not attest (e.g. its signing/policy + // backend is unavailable). Signal the caller so it + // applies backoff instead of a tight reconnect loop. + if r.attestation != nil { + r.connectionError = true + } } return } diff --git a/client/wsclient.go b/client/wsclient.go index 3c61c52d..94c15bb1 100644 --- a/client/wsclient.go +++ b/client/wsclient.go @@ -366,7 +366,7 @@ func (c *wsClient) ensureConnected(ctx context.Context) error { // Returns true if the cycle ended because of a payload trust verification // failure (wrong CA, bad signature, etc.). The caller should apply exponential // backoff before retrying in that case. -func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) (attestationFailed bool) { +func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) (attestationFailed bool, connectionFailed bool) { if err := c.ensureConnected(ctx); err != nil { // Can't connect, so can't move forward. This currently happens when we // are being stopped. @@ -431,6 +431,13 @@ func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) (atte if err := c.sender.StoppingErr(); err != nil { c.common.Logger.Debugf(ctx, "Error stopping the sender: %v", err) + // If the sender noticed the broken connection first (before the + // receiver), still treat it as an abnormal connection failure + // when attestation is enabled so the caller backs off. + if c.common.PayloadVerifier != nil || c.common.PayloadTOFUStore != nil { + connectionFailed = true + } + stopReceiver() <-r.IsStopped() break @@ -452,6 +459,7 @@ func (c *wsClient) runOneCycle(ctx context.Context, sendFirstMessage bool) (atte stopSender() <-c.sender.IsStopped() attestationFailed = r.WasAttestationFailure() + connectionFailed = r.WasConnectionError() } return } @@ -460,43 +468,64 @@ func (c *wsClient) runUntilStopped(ctx context.Context) { // Iterates until we detect that the client is stopping. sendFirstMessage := true - // Separate backoff for attestation failures. ensureConnected already - // backs off TCP-level failures within a single runOneCycle call, but - // when the transport connects and only the application-level - // attestation check fails the receiver stops, runOneCycle returns, - // and ensureConnected would immediately succeed again on the next - // call (TCP is fine). Without this outer backoff the client would - // spin in a tight reject-reconnect loop as fast as the network - // allows, which is contrary to the spec's SHOULD-exponential-backoff - // requirement for attestation failures. - attestBackoff := backoff.NewExponentialBackOff() - attestBackoff.MaxElapsedTime = 0 // retry forever + // Separate backoff for application-level reconnects. ensureConnected + // already backs off TCP-level dial failures within a single + // runOneCycle call, but two failure modes connect successfully at the + // transport layer and only fail afterwards: + // 1. the client's own attestation check rejects a message, or + // 2. the server accepts the connection and then drops it abnormally + // (with attestation on, this almost always means the server + // cannot sign — e.g. its signing/policy backend is down). + // In both cases ensureConnected would immediately succeed again on the + // next call (TCP is fine). Without this outer backoff the client would + // spin in a tight reconnect loop as fast as the network allows, which + // is contrary to the spec's SHOULD-exponential-backoff requirement. + reconnectBackoff := backoff.NewExponentialBackOff() + reconnectBackoff.MaxElapsedTime = 0 // retry forever for { if c.common.IsStopping() { return } - if attestationFailed := c.runOneCycle(ctx, sendFirstMessage); attestationFailed { - interval := attestBackoff.NextBackOff() + attestationFailed, connectionFailed := c.runOneCycle(ctx, sendFirstMessage) + switch { + case attestationFailed: + interval := reconnectBackoff.NextBackOff() c.common.Logger.Errorf(ctx, "Payload trust verification failed, will retry in %v.", interval) - timer := time.NewTimer(interval) - select { - case <-timer.C: - case <-ctx.Done(): - timer.Stop() + if !c.sleepWithBackoff(ctx, interval) { + return + } + case connectionFailed: + interval := reconnectBackoff.NextBackOff() + c.common.Logger.Errorf(ctx, "Connection closed abnormally, will retry in %v.", interval) + if !c.sleepWithBackoff(ctx, interval) { return } - } else { - // Non-attestation cycle: reset so the next attestation - // failure starts backoff from the initial interval again. - attestBackoff.Reset() + default: + // Productive cycle: reset so the next failure starts backoff + // from the initial interval again. + reconnectBackoff.Reset() } sendFirstMessage = false } } +// sleepWithBackoff waits for the given interval or until the context is +// cancelled. It returns true if the interval elapsed, or false if the +// context was cancelled (the caller should stop). +func (c *wsClient) sleepWithBackoff(ctx context.Context, interval time.Duration) bool { + timer := time.NewTimer(interval) + defer timer.Stop() + select { + case <-timer.C: + return true + case <-ctx.Done(): + return false + } +} + // useProxy sets the websocket dialer to use the passed proxy URL. // If the proxy has no schema http is used. // This method is not thread safe and must be called before c.dialer is used.