Netpulse_SasS/gen/go/netpulse/v1/agent_grpc.pb.go
byrsapty ddaae60fa0 Етап 8: реєстрація зонда одноразовим запрошенням
Найбільше вузьке місце до запуску: агент заводився INSERT-ом у базу, а
токен вписувався в командний рядок руками. Поставити зонд у клієнта було
неможливо.

core.agent_enrollments тримає sha256 одноразового токена; сам токен
повертається рівно один раз. Видача під FOR UPDATE в одній транзакції:
два агенти з однієї скопійованої команди інакше створили б два зонди з
одного запрошення. Відповідь на «немає», «згоріло» і «використано»
однакова — розрізняти їх означає підказувати тому, хто підбирає токени.

Токен зонда їде окремим полем agent_token, а не в certificate:
сертифікат відповідає на інше питання й живе за іншим циклом.

Агент зберігає посвідчення в /etc/netpulse/agent.json з правами 0600,
через тимчасовий файл і перейменування — обрив живлення посеред запису
інакше лишив би половину токена.

Знайдено живим прогоном: реєстрація не проходила автентифікацію, бо
інтерсептор стоїть на всьому сервері, а не на окремому сервісі — мій же
коментар стверджував протилежне. І запуск із самим посвідченням падав:
validate() вимагав -agent-id, не знаючи про файл.

Сторінка зондів: команда встановлення з токеном, відкликання
запрошень, керування модулями й лімітами, видалення.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 00:50:57 +03:00

376 lines
17 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// =====================================================================
// NetPulse :: agent.proto
// Головний контракт агент↔сервер.
//
// ФУНДАМЕНТАЛЬНЕ ОБМЕЖЕННЯ: усі з'єднання ініціює агент.
// Сервер ніколи не стукає в мережу клієнта — там немає ані відкритих
// портів, ані прокидання NAT. Тому "команда з сервера" фізично є
// повідомленням у зустрічному напрямку вже відкритого агентом
// bidi-стріму Control.
// =====================================================================
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.2
// - protoc (unknown)
// source: netpulse/v1/agent.proto
package netpulsev1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
EnrollmentService_Enroll_FullMethodName = "/netpulse.v1.EnrollmentService/Enroll"
)
// EnrollmentServiceClient is the client API for EnrollmentService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type EnrollmentServiceClient interface {
Enroll(ctx context.Context, in *EnrollRequest, opts ...grpc.CallOption) (*EnrollResponse, error)
}
type enrollmentServiceClient struct {
cc grpc.ClientConnInterface
}
func NewEnrollmentServiceClient(cc grpc.ClientConnInterface) EnrollmentServiceClient {
return &enrollmentServiceClient{cc}
}
func (c *enrollmentServiceClient) Enroll(ctx context.Context, in *EnrollRequest, opts ...grpc.CallOption) (*EnrollResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(EnrollResponse)
err := c.cc.Invoke(ctx, EnrollmentService_Enroll_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// EnrollmentServiceServer is the server API for EnrollmentService service.
// All implementations should embed UnimplementedEnrollmentServiceServer
// for forward compatibility.
type EnrollmentServiceServer interface {
Enroll(context.Context, *EnrollRequest) (*EnrollResponse, error)
}
// UnimplementedEnrollmentServiceServer should be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedEnrollmentServiceServer struct{}
func (UnimplementedEnrollmentServiceServer) Enroll(context.Context, *EnrollRequest) (*EnrollResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Enroll not implemented")
}
func (UnimplementedEnrollmentServiceServer) testEmbeddedByValue() {}
// UnsafeEnrollmentServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EnrollmentServiceServer will
// result in compilation errors.
type UnsafeEnrollmentServiceServer interface {
mustEmbedUnimplementedEnrollmentServiceServer()
}
func RegisterEnrollmentServiceServer(s grpc.ServiceRegistrar, srv EnrollmentServiceServer) {
// If the following call panics, it indicates UnimplementedEnrollmentServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&EnrollmentService_ServiceDesc, srv)
}
func _EnrollmentService_Enroll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EnrollRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EnrollmentServiceServer).Enroll(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EnrollmentService_Enroll_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EnrollmentServiceServer).Enroll(ctx, req.(*EnrollRequest))
}
return interceptor(ctx, in, info, handler)
}
// EnrollmentService_ServiceDesc is the grpc.ServiceDesc for EnrollmentService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var EnrollmentService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "netpulse.v1.EnrollmentService",
HandlerType: (*EnrollmentServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Enroll",
Handler: _EnrollmentService_Enroll_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "netpulse/v1/agent.proto",
}
const (
AgentService_Control_FullMethodName = "/netpulse.v1.AgentService/Control"
AgentService_StreamTelemetry_FullMethodName = "/netpulse.v1.AgentService/StreamTelemetry"
AgentService_StreamLogs_FullMethodName = "/netpulse.v1.AgentService/StreamLogs"
AgentService_ReportDiscovery_FullMethodName = "/netpulse.v1.AgentService/ReportDiscovery"
AgentService_UploadConfig_FullMethodName = "/netpulse.v1.AgentService/UploadConfig"
)
// AgentServiceClient is the client API for AgentService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AgentServiceClient interface {
// Довгоживучий двонаправлений канал керування. Одна сесія = одне
// з'єднання. Розрив стріму = кінець сесії з усім її станом
// (таблиця серій, in-flight батчі).
Control(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ControlUp, ControlDown], error)
// Телеметрія окремим стрімом, щоб пачка на 10 000 семплів
// не блокувала heartbeat і не затримувала команду з сервера.
StreamTelemetry(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[TelemetryBatch, TelemetryAck], error)
// Syslog/трапи — теж окремо: сплеск логів під час аварії не має
// топити телеметрію, за якою ця аварія й видно.
StreamLogs(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[LogBatch, LogAck], error)
// Автовиявлення: рідко, великими звітами.
ReportDiscovery(ctx context.Context, in *DiscoveryReport, opts ...grpc.CallOption) (*DiscoveryAck, error)
// Вивантаження зібраного конфігу (чанками).
UploadConfig(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[ConfigUpload, ConfigReceipt], error)
}
type agentServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAgentServiceClient(cc grpc.ClientConnInterface) AgentServiceClient {
return &agentServiceClient{cc}
}
func (c *agentServiceClient) Control(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ControlUp, ControlDown], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &AgentService_ServiceDesc.Streams[0], AgentService_Control_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[ControlUp, ControlDown]{ClientStream: stream}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_ControlClient = grpc.BidiStreamingClient[ControlUp, ControlDown]
func (c *agentServiceClient) StreamTelemetry(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[TelemetryBatch, TelemetryAck], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &AgentService_ServiceDesc.Streams[1], AgentService_StreamTelemetry_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[TelemetryBatch, TelemetryAck]{ClientStream: stream}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_StreamTelemetryClient = grpc.BidiStreamingClient[TelemetryBatch, TelemetryAck]
func (c *agentServiceClient) StreamLogs(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[LogBatch, LogAck], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &AgentService_ServiceDesc.Streams[2], AgentService_StreamLogs_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[LogBatch, LogAck]{ClientStream: stream}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_StreamLogsClient = grpc.BidiStreamingClient[LogBatch, LogAck]
func (c *agentServiceClient) ReportDiscovery(ctx context.Context, in *DiscoveryReport, opts ...grpc.CallOption) (*DiscoveryAck, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DiscoveryAck)
err := c.cc.Invoke(ctx, AgentService_ReportDiscovery_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *agentServiceClient) UploadConfig(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[ConfigUpload, ConfigReceipt], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &AgentService_ServiceDesc.Streams[3], AgentService_UploadConfig_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[ConfigUpload, ConfigReceipt]{ClientStream: stream}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_UploadConfigClient = grpc.ClientStreamingClient[ConfigUpload, ConfigReceipt]
// AgentServiceServer is the server API for AgentService service.
// All implementations should embed UnimplementedAgentServiceServer
// for forward compatibility.
type AgentServiceServer interface {
// Довгоживучий двонаправлений канал керування. Одна сесія = одне
// з'єднання. Розрив стріму = кінець сесії з усім її станом
// (таблиця серій, in-flight батчі).
Control(grpc.BidiStreamingServer[ControlUp, ControlDown]) error
// Телеметрія окремим стрімом, щоб пачка на 10 000 семплів
// не блокувала heartbeat і не затримувала команду з сервера.
StreamTelemetry(grpc.BidiStreamingServer[TelemetryBatch, TelemetryAck]) error
// Syslog/трапи — теж окремо: сплеск логів під час аварії не має
// топити телеметрію, за якою ця аварія й видно.
StreamLogs(grpc.BidiStreamingServer[LogBatch, LogAck]) error
// Автовиявлення: рідко, великими звітами.
ReportDiscovery(context.Context, *DiscoveryReport) (*DiscoveryAck, error)
// Вивантаження зібраного конфігу (чанками).
UploadConfig(grpc.ClientStreamingServer[ConfigUpload, ConfigReceipt]) error
}
// UnimplementedAgentServiceServer should be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAgentServiceServer struct{}
func (UnimplementedAgentServiceServer) Control(grpc.BidiStreamingServer[ControlUp, ControlDown]) error {
return status.Error(codes.Unimplemented, "method Control not implemented")
}
func (UnimplementedAgentServiceServer) StreamTelemetry(grpc.BidiStreamingServer[TelemetryBatch, TelemetryAck]) error {
return status.Error(codes.Unimplemented, "method StreamTelemetry not implemented")
}
func (UnimplementedAgentServiceServer) StreamLogs(grpc.BidiStreamingServer[LogBatch, LogAck]) error {
return status.Error(codes.Unimplemented, "method StreamLogs not implemented")
}
func (UnimplementedAgentServiceServer) ReportDiscovery(context.Context, *DiscoveryReport) (*DiscoveryAck, error) {
return nil, status.Error(codes.Unimplemented, "method ReportDiscovery not implemented")
}
func (UnimplementedAgentServiceServer) UploadConfig(grpc.ClientStreamingServer[ConfigUpload, ConfigReceipt]) error {
return status.Error(codes.Unimplemented, "method UploadConfig not implemented")
}
func (UnimplementedAgentServiceServer) testEmbeddedByValue() {}
// UnsafeAgentServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AgentServiceServer will
// result in compilation errors.
type UnsafeAgentServiceServer interface {
mustEmbedUnimplementedAgentServiceServer()
}
func RegisterAgentServiceServer(s grpc.ServiceRegistrar, srv AgentServiceServer) {
// If the following call panics, it indicates UnimplementedAgentServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AgentService_ServiceDesc, srv)
}
func _AgentService_Control_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(AgentServiceServer).Control(&grpc.GenericServerStream[ControlUp, ControlDown]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_ControlServer = grpc.BidiStreamingServer[ControlUp, ControlDown]
func _AgentService_StreamTelemetry_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(AgentServiceServer).StreamTelemetry(&grpc.GenericServerStream[TelemetryBatch, TelemetryAck]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_StreamTelemetryServer = grpc.BidiStreamingServer[TelemetryBatch, TelemetryAck]
func _AgentService_StreamLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(AgentServiceServer).StreamLogs(&grpc.GenericServerStream[LogBatch, LogAck]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_StreamLogsServer = grpc.BidiStreamingServer[LogBatch, LogAck]
func _AgentService_ReportDiscovery_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DiscoveryReport)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AgentServiceServer).ReportDiscovery(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AgentService_ReportDiscovery_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AgentServiceServer).ReportDiscovery(ctx, req.(*DiscoveryReport))
}
return interceptor(ctx, in, info, handler)
}
func _AgentService_UploadConfig_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(AgentServiceServer).UploadConfig(&grpc.GenericServerStream[ConfigUpload, ConfigReceipt]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AgentService_UploadConfigServer = grpc.ClientStreamingServer[ConfigUpload, ConfigReceipt]
// AgentService_ServiceDesc is the grpc.ServiceDesc for AgentService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AgentService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "netpulse.v1.AgentService",
HandlerType: (*AgentServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ReportDiscovery",
Handler: _AgentService_ReportDiscovery_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "Control",
Handler: _AgentService_Control_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "StreamTelemetry",
Handler: _AgentService_StreamTelemetry_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "StreamLogs",
Handler: _AgentService_StreamLogs_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "UploadConfig",
Handler: _AgentService_UploadConfig_Handler,
ClientStreams: true,
},
},
Metadata: "netpulse/v1/agent.proto",
}