Skip to content

Commit

Permalink
Add support for db-audit logging
Browse files Browse the repository at this point in the history
  • Loading branch information
aquatiko committed Feb 18, 2024
1 parent 7182b7a commit 7fabd19
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 1 deletion.
147 changes: 147 additions & 0 deletions cmd/db_audit/db_audit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Licensed to Yugabyte, Inc. under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership. Yugabyte
// licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package db_audit

import (
"fmt"
"os"
"encoding/json"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
ybmAuthClient "github.com/yugabyte/ybm-cli/internal/client"
"github.com/yugabyte/ybm-cli/internal/formatter"
ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal"
)

var DbAuditCmd = &cobra.Command{
Use: "db-audit",
Short: "Manage DB Audit",
Long: "Manage DB Audit",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

var associateDbAuditCmd = &cobra.Command{
Use: "associate",
Short: "Associate DB Audit",
Long: "Associate DB Audit",
Run: func(cmd *cobra.Command, args []string) {

clusterId, _ := cmd.Flags().GetString("cluster-id")
telemetryProviderId, _ := cmd.Flags().GetString("telemetry-provider-id")
ysqlConfig, _ := cmd.Flags().GetString("ysql-config")

fmt.Println(ysqlConfig)
dbAuditExporterConfigSpec, err := setDbAuditExporterConfigSpec(ysqlConfig, telemetryProviderId)

if err != nil {
logrus.Fatalf(err.Error())
}

authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf(ybmAuthClient.GetApiErrorDetails(err))
}
authApi.GetInfo("", "")

resp, r, err := authApi.AssociateDbAuditExporterConfig(clusterId).DbAuditExporterConfigSpec(*dbAuditExporterConfigSpec).Execute()

if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf(ybmAuthClient.GetApiErrorDetails(err))
}

dbAudittelemetryProviderId := resp.GetData().Info.Id

msg := fmt.Sprintf("The db audit exporter config %s is being created", formatter.Colorize(dbAudittelemetryProviderId, formatter.GREEN_COLOR))

fmt.Println(msg)

dbAuditExporterCtx := formatter.Context{
Output: os.Stdout,
Format: formatter.NewDbAuditFormat(viper.GetString("output")),
}

formatter.SingleDbAuditWrite(dbAuditExporterCtx, resp.GetData())
},
}

var listDbAuditCmd = &cobra.Command{
Use: "list",
Short: "List DB Audit Export Config",
Long: "List DB Audit Export Config",
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf(ybmAuthClient.GetApiErrorDetails(err))
}
authApi.GetInfo("", "")

clusterId, _ := cmd.Flags().GetString("cluster-id")

resp, r, err := authApi.ListDbAuditExportConfigs(clusterId).Execute()

if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf(ybmAuthClient.GetApiErrorDetails(err))
}

dbAuditExporterCtx := formatter.Context{
Output: os.Stdout,
Format: formatter.NewDbAuditFormat(viper.GetString("output")),
}

if len(resp.GetData()) < 1 {
fmt.Println("No DB audit Export config found")
return
}

formatter.DbAuditWrite(dbAuditExporterCtx, resp.GetData())
},
}

func init() {
DbAuditCmd.AddCommand(associateDbAuditCmd)
associateDbAuditCmd.Flags().SortFlags = false
associateDbAuditCmd.Flags().String("telemetry-provider-id", "", "[REQUIRED] The ID of the telemetry provider")
associateDbAuditCmd.MarkFlagRequired("telemetry-provider-id")
associateDbAuditCmd.Flags().String("ysql-config", "", "[REQUIRED] The ysql config to setup DB auditting")
associateDbAuditCmd.MarkFlagRequired("ysql-config")
associateDbAuditCmd.Flags().String("cluster-id", "", "[REQUIRED] The cluster ID to associate DB auditting")
associateDbAuditCmd.MarkFlagRequired("cluster-id")

DbAuditCmd.AddCommand(listDbAuditCmd)
listDbAuditCmd.Flags().SortFlags = false
listDbAuditCmd.Flags().String("cluster-id", "", "[REQUIRED] The cluster ID to list DB audit export config")
listDbAuditCmd.MarkFlagRequired("cluster-id")
}

func setDbAuditExporterConfigSpec(ysqlConfigString string, telemetryProviderId string) (*ybmclient.DbAuditExporterConfigSpec, error) {
var ysqlConfig ybmclient.DbAuditYsqlExportConfig;
tmp := []byte(ysqlConfigString)
fmt.Println(tmp)
fmt.Println(ysqlConfigString)
var err error = json.Unmarshal(tmp, &ysqlConfig)

if err != nil {
logrus.Fatal("Failed to parse ysql config: invalid JSON format. ", err)
}

return ybmclient.NewDbAuditExporterConfigSpec(ysqlConfig ,telemetryProviderId), nil;
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/yugabyte/ybm-cli/cmd/cdc"
"github.com/yugabyte/ybm-cli/cmd/cluster"
"github.com/yugabyte/ybm-cli/cmd/metrics_exporter"
"github.com/yugabyte/ybm-cli/cmd/db_audit"
"github.com/yugabyte/ybm-cli/cmd/nal"
"github.com/yugabyte/ybm-cli/cmd/permission"
"github.com/yugabyte/ybm-cli/cmd/region"
Expand Down Expand Up @@ -135,6 +136,7 @@ func init() {
rootCmd.AddCommand(api_key.ApiKeyCmd)
rootCmd.AddCommand(user.UserCmd)
rootCmd.AddCommand(metrics_exporter.MetricsExporterCmd)
rootCmd.AddCommand(db_audit.DbAuditCmd)
util.AddCommandIfFeatureFlag(rootCmd, tools.ToolsCmd, util.TOOLS)
util.AddCommandIfFeatureFlag(rootCmd, cdc.CdcCmd, util.CDC)

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.17.0
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240131113907-1ba9d5e67a7a
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240212235036-b591c98709c3
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/mod v0.14.0
golang.org/x/term v0.15.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240131113907-1ba9d5e67a7a h1:Lj0hIO1LuXJ4jO0dEe8dIBX9X06CSvo6xNfdV8spJKs=
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240131113907-1ba9d5e67a7a/go.mod h1:5vW0xIzIZw+1djkiWKx0qqNmqbRBSf4mjc4qw8lIMik=
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240212235036-b591c98709c3 h1:5WlWq7q60p5f4NhMKET9ZMvrxiMGHpr6W5thnXIwY0A=
github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20240212235036-b591c98709c3/go.mod h1:5vW0xIzIZw+1djkiWKx0qqNmqbRBSf4mjc4qw8lIMik=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
8 changes: 8 additions & 0 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,10 @@ func (a *AuthApiClient) CreatePrivateServiceEndpoint(clusterId string) ybmclient
return a.ApiClient.ClusterApi.CreatePrivateServiceEndpoint(a.ctx, a.AccountID, a.ProjectID, clusterId)
}

func (a *AuthApiClient) AssociateDbAuditExporterConfig(clusterId string) ybmclient.ApiAssociateDbAuditExporterConfigRequest {
return a.ApiClient.ClusterApi.AssociateDbAuditExporterConfig(a.ctx, a.AccountID, a.ProjectID, clusterId)
}

func (a *AuthApiClient) CreatePrivateServiceEndpointRegionSpec(regionArnMap map[string][]string) []ybmclient.PrivateServiceEndpointRegionSpec {
pseSpecs := []ybmclient.PrivateServiceEndpointRegionSpec{}

Expand Down Expand Up @@ -1457,6 +1461,10 @@ func (a *AuthApiClient) ListMetricsExporterConfigs() ybmclient.ApiListMetricsExp
return a.ApiClient.MetricsExporterConfigApi.ListMetricsExporterConfigs(a.ctx, a.AccountID, a.ProjectID)
}

func (a *AuthApiClient) ListDbAuditExportConfigs(clusterId string) ybmclient.ApiListDbAuditExporterConfigRequest {
return a.ApiClient.ClusterApi.ListDbAuditExporterConfig(a.ctx, a.AccountID, a.ProjectID, clusterId)
}

func (a *AuthApiClient) DeleteMetricsExporterConfig(configId string) ybmclient.ApiDeleteMetricsExporterConfigRequest {
return a.ApiClient.MetricsExporterConfigApi.DeleteMetricsExporterConfig(a.ctx, a.AccountID, a.ProjectID, configId)
}
Expand Down
118 changes: 118 additions & 0 deletions internal/formatter/db_audit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Licensed to Yugabyte, Inc. under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership. Yugabyte
// licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package formatter

import (
"encoding/json"

"github.com/sirupsen/logrus"
ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal"
)

const (
defaultDbAuditListing = "table {{.ID}}\t{{.CreatedAt}}\t{{.ClusterId}}\t{{.TelemetryProviderId}}\t{{.State}}\t{{.YsqlConfig}}"
exportConfigCreatedAtHeader = "Date Created"
clusterIdHeader = "Cluster ID"
telemetryProviderIdHeader = "Telemetry Provider ID"
exportConfigState = "State"
ysqlConfigHeader = "Ysql Config"
)

type DbAuditContext struct {
HeaderContext
Context
a ybmclient.DbAuditExporterConfigurationData
}

func NewDbAuditFormat(source string) Format {
switch source {
case "table", "":
format := defaultDbAuditListing
return Format(format)
default: // custom format or json or pretty
return Format(source)
}
}

// DbAuditWrite renders the context for a list of Db Audit Export config
func DbAuditWrite(ctx Context, dbAuditConfigs []ybmclient.DbAuditExporterConfigurationData) error {
render := func(format func(subContext SubContext) error) error {
for _, dbAuditConfig := range dbAuditConfigs {
err := format(&DbAuditContext{a: dbAuditConfig})
if err != nil {
logrus.Debugf("Error rendering DB Audit Config: %v", err)
return err
}
}
return nil
}
return ctx.Write(NewDbAuditContext(), render)
}

func SingleDbAuditWrite(ctx Context, dbAuditConfig ybmclient.DbAuditExporterConfigurationData) error {
render := func(format func(subContext SubContext) error) error {
err := format(&DbAuditContext{a: dbAuditConfig})
if err != nil {
logrus.Debugf("Error rendering DB Audit Config: %v", err)
return err
}
return nil
}
return ctx.Write(NewDbAuditContext(), render)
}

// NewDbAuditContext creates a new context for rendering Db Audit Export Config
func NewDbAuditContext() *DbAuditContext {
dbAuditCtx := DbAuditContext{}
dbAuditCtx.Header = SubHeaderContext{
"YsqlConfig": ysqlConfigHeader,
"ID": "ID",
"State": exportConfigState,
"TelemetryProviderId": telemetryProviderIdHeader,
"ClusterId": clusterIdHeader,
"CreatedAt": exportConfigCreatedAtHeader,
}
return &dbAuditCtx
}

func (a *DbAuditContext) ID() string {
return a.a.Info.Id
}

func (a *DbAuditContext) State() string {
return string(a.a.Info.State)
}

func (a *DbAuditContext) TelemetryProviderId() string {
return a.a.Spec.ExporterId
}

func (a *DbAuditContext) ClusterId() string {
return a.a.Info.ClusterId
}

func (a *DbAuditContext) YsqlConfig() string {
ysqlConfig, _ := json.Marshal(a.a.Spec.YsqlConfig)
return string(ysqlConfig)
}

func (a *DbAuditContext) CreatedAt() string {
return a.a.Info.Metadata.Get().GetCreatedOn()
}

func (a *DbAuditContext) MarshalJSON() ([]byte, error) {
return json.Marshal(a.a)
}
Binary file added ybm-cli
Binary file not shown.

0 comments on commit 7fabd19

Please sign in to comment.