Найбільше вузьке місце до запуску: агент заводився 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>
376 lines
17 KiB
Go
376 lines
17 KiB
Go
// =====================================================================
|
||
// 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",
|
||
}
|