Add commands to list sinks and to read a protocol file to JSON
This commit is contained in:
parent
a76d1d1c04
commit
66f2aab9af
6 changed files with 146 additions and 75 deletions
|
@ -36,8 +36,17 @@ message RemoveFileSinkResponse {
|
|||
bool SinkGotRemoved = 1;
|
||||
}
|
||||
|
||||
message ListSinksRequest {
|
||||
|
||||
}
|
||||
|
||||
message ListSinksResponse {
|
||||
repeated string sinks = 1;
|
||||
}
|
||||
|
||||
service Audit {
|
||||
rpc WatchEvents (WatchEventsRequest) returns (stream inetmock.audit.EventEntity);
|
||||
rpc RegisterFileSink (RegisterFileSinkRequest) returns (RegisterFileSinkResponse);
|
||||
rpc RemoveFileSink (RemoveFileSinkRequest) returns (RemoveFileSinkResponse);
|
||||
rpc ListSinks(ListSinksRequest) returns (ListSinksResponse);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gitlab.com/inetmock/inetmock/internal/rpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
addFileCmd = &cobra.Command{
|
||||
Use: "addFile",
|
||||
Short: "subscribe events to a file",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runAddFile,
|
||||
}
|
||||
|
||||
removeFileCmd = &cobra.Command{
|
||||
Use: "removeFile",
|
||||
Short: "remove file subscription",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runRemoveFile,
|
||||
}
|
||||
|
||||
readFileCmd = &cobra.Command{
|
||||
Use: "readFile",
|
||||
Short: "reads an audit file and prints the events",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runReadFile,
|
||||
}
|
||||
)
|
||||
|
||||
func runAddFile(_ *cobra.Command, args []string) (err error) {
|
||||
var conn *grpc.ClientConn
|
||||
|
||||
if conn, err = grpc.Dial(inetMockSocketPath, grpc.WithInsecure()); err != nil {
|
||||
fmt.Printf("Failed to connecto INetMock socket: %v\n", err)
|
||||
os.Exit(10)
|
||||
}
|
||||
|
||||
auditClient := rpc.NewAuditClient(conn)
|
||||
ctx, cancel := context.WithTimeout(cliApp.Context(), grpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err = auditClient.RegisterFileSink(ctx, &rpc.RegisterFileSinkRequest{TargetPath: args[0]})
|
||||
return
|
||||
}
|
||||
|
||||
func runRemoveFile(_ *cobra.Command, args []string) (err error) {
|
||||
auditClient := rpc.NewAuditClient(conn)
|
||||
ctx, cancel := context.WithTimeout(cliApp.Context(), grpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err = auditClient.RemoveFileSink(ctx, &rpc.RemoveFileSinkRequest{TargetPath: args[0]})
|
||||
return
|
||||
}
|
||||
|
||||
func runReadFile(_ *cobra.Command, args []string) (err error) {
|
||||
return
|
||||
}
|
118
cmd/imctl/audit_sinks.go
Normal file
118
cmd/imctl/audit_sinks.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gitlab.com/inetmock/inetmock/internal/format"
|
||||
"gitlab.com/inetmock/inetmock/internal/rpc"
|
||||
"gitlab.com/inetmock/inetmock/pkg/audit"
|
||||
)
|
||||
|
||||
var (
|
||||
listSinksCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Aliases: []string{"ls", "dir"},
|
||||
Short: "List all subscribed sinks",
|
||||
RunE: runListSinks,
|
||||
}
|
||||
addFileCmd = &cobra.Command{
|
||||
Use: "add-file",
|
||||
Aliases: []string{"add"},
|
||||
Short: "subscribe events to a file",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runAddFile,
|
||||
}
|
||||
|
||||
removeFileCmd = &cobra.Command{
|
||||
Use: "remove-file",
|
||||
Aliases: []string{"rm", "del"},
|
||||
Short: "remove file subscription",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runRemoveFile,
|
||||
}
|
||||
|
||||
readFileCmd = &cobra.Command{
|
||||
Use: "read-file",
|
||||
Aliases: []string{"cat"},
|
||||
Short: "reads an audit file and prints the events",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runReadFile,
|
||||
}
|
||||
)
|
||||
|
||||
type printableSink struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func runListSinks(*cobra.Command, []string) (err error) {
|
||||
auditClient := rpc.NewAuditClient(conn)
|
||||
ctx, cancel := context.WithTimeout(cliApp.Context(), grpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
var resp *rpc.ListSinksResponse
|
||||
if resp, err = auditClient.ListSinks(ctx, &rpc.ListSinksRequest{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var sinks []printableSink
|
||||
for _, s := range resp.Sinks {
|
||||
sinks = append(sinks, printableSink{Name: s})
|
||||
}
|
||||
|
||||
writer := format.Writer(outputFormat, os.Stdout)
|
||||
err = writer.Write(sinks)
|
||||
return
|
||||
}
|
||||
|
||||
func runAddFile(_ *cobra.Command, args []string) (err error) {
|
||||
auditClient := rpc.NewAuditClient(conn)
|
||||
ctx, cancel := context.WithTimeout(cliApp.Context(), grpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err = auditClient.RegisterFileSink(ctx, &rpc.RegisterFileSinkRequest{TargetPath: args[0]})
|
||||
return
|
||||
}
|
||||
|
||||
func runRemoveFile(_ *cobra.Command, args []string) (err error) {
|
||||
auditClient := rpc.NewAuditClient(conn)
|
||||
ctx, cancel := context.WithTimeout(cliApp.Context(), grpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err = auditClient.RemoveFileSink(ctx, &rpc.RemoveFileSinkRequest{TargetPath: args[0]})
|
||||
return
|
||||
}
|
||||
|
||||
func runReadFile(_ *cobra.Command, args []string) (err error) {
|
||||
if len(args) != 1 {
|
||||
return errors.New("expected only 1 argument")
|
||||
}
|
||||
|
||||
var reader io.ReadCloser
|
||||
if reader, err = os.Open(args[0]); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
eventReader := audit.NewEventReader(reader)
|
||||
var ev audit.Event
|
||||
|
||||
for err == nil {
|
||||
if ev, err = eventReader.Read(); err == nil {
|
||||
var jsonBytes []byte
|
||||
if jsonBytes, err = json.Marshal(ev); err == nil {
|
||||
fmt.Println(string(jsonBytes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errors.Is(err, io.EOF) {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -25,7 +25,7 @@ var (
|
|||
)
|
||||
|
||||
type printableEndpoint struct {
|
||||
Id string
|
||||
ID string
|
||||
Name string
|
||||
Handler string
|
||||
ListenAddress string
|
||||
|
@ -34,7 +34,7 @@ type printableEndpoint struct {
|
|||
|
||||
func fromEndpoint(ep *rpc.Endpoint) *printableEndpoint {
|
||||
return &printableEndpoint{
|
||||
Id: ep.Id,
|
||||
ID: ep.Id,
|
||||
Name: ep.Name,
|
||||
Handler: ep.Handler,
|
||||
ListenAddress: ep.ListenAddress,
|
||||
|
|
|
@ -2,6 +2,8 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"time"
|
||||
|
||||
|
@ -20,7 +22,6 @@ var (
|
|||
)
|
||||
|
||||
func main() {
|
||||
|
||||
endpointsCmd.AddCommand(getEndpoints)
|
||||
handlerCmd.AddCommand(getHandlersCmd)
|
||||
healthCmd.AddCommand(generalHealthCmd, containerHealthCmd)
|
||||
|
@ -29,7 +30,8 @@ func main() {
|
|||
WithCommands(endpointsCmd, handlerCmd, healthCmd, auditCmd).
|
||||
WithInitTasks(func(_ *cobra.Command, _ []string) (err error) {
|
||||
return initGRPCConnection()
|
||||
})
|
||||
}).
|
||||
WithLogger()
|
||||
|
||||
cliApp.RootCommand().PersistentFlags().StringVar(&inetMockSocketPath, "socket-path", "unix:///var/run/inetmock.sock", "Path to the INetMock socket file")
|
||||
cliApp.RootCommand().PersistentFlags().StringVarP(&outputFormat, "format", "f", "table", "Output format to use. Possible values: table, json, yaml")
|
||||
|
@ -42,16 +44,15 @@ func main() {
|
|||
currentUser = uuid.New().String()
|
||||
}
|
||||
|
||||
watchEventsCmd.PersistentFlags().StringVar(
|
||||
&listenerName,
|
||||
"listener-name",
|
||||
currentUser,
|
||||
"set listener name - defaults to the current username, if the user cannot be determined a random UUID will be used",
|
||||
)
|
||||
auditCmd.AddCommand(watchEventsCmd, addFileCmd, removeFileCmd)
|
||||
hostname := "."
|
||||
if hn, err := os.Hostname(); err == nil {
|
||||
hostname = hn
|
||||
}
|
||||
|
||||
watchEventsCmd.PersistentFlags().StringVar(&listenerName, "listener-name", fmt.Sprintf("%s\\%s is watching", hostname, currentUser), "set listener name - defaults to the current username, if the user cannot be determined a random UUID will be used")
|
||||
auditCmd.AddCommand(listSinksCmd, watchEventsCmd, addFileCmd, removeFileCmd, readFileCmd)
|
||||
|
||||
cliApp.MustRun()
|
||||
|
||||
}
|
||||
|
||||
func initGRPCConnection() (err error) {
|
||||
|
|
|
@ -17,6 +17,12 @@ type auditServer struct {
|
|||
eventStream audit.EventStream
|
||||
}
|
||||
|
||||
func (a *auditServer) ListSinks(context.Context, *ListSinksRequest) (*ListSinksResponse, error) {
|
||||
return &ListSinksResponse{
|
||||
Sinks: a.eventStream.Sinks(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *auditServer) WatchEvents(req *WatchEventsRequest, srv Audit_WatchEventsServer) (err error) {
|
||||
a.logger.Info("watcher attached", zap.String("name", req.WatcherName))
|
||||
err = a.eventStream.RegisterSink(sink.NewGRPCSink(srv.Context(), req.WatcherName, func(ev audit.Event) {
|
||||
|
|
Loading…
Reference in a new issue