Skip to content

Commit

Permalink
Vec 189 tls + auth (#2)
Browse files Browse the repository at this point in the history
* VEC-189 add tls and auth
  • Loading branch information
Jesse S authored Jul 3, 2024
1 parent 938957b commit 5700529
Show file tree
Hide file tree
Showing 50 changed files with 1,451 additions and 408 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/create-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ on:
description: 'Delete existing pre-releases?'
required: false
type: boolean

push:
branches:
- "VEC-189-tls" # remove before merge into main
jobs:
build-and-release:
runs-on: macos-13
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/docker/config/features.conf
features.conf
/bin/*
embed_*.go
/tmp
tmp
/vendor
/coverage
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ linters-settings:
allow:
- $gostd
- github.com/aerospike/tools-common-go
- github.com/aerospike/aerospike-proximus-client-go
- github.com/aerospike/avs-client-go
- asvec/cmd
- github.com/spf13/cobra
- github.com/spf13/viper
Expand Down
25 changes: 0 additions & 25 deletions cmd/constants.go

This file was deleted.

132 changes: 63 additions & 69 deletions cmd/createIndex.go

Large diffs are not rendered by default.

72 changes: 34 additions & 38 deletions cmd/dropIndex.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"log/slog"
"time"

avs "github.com/aerospike/aerospike-proximus-client-go"
commonFlags "github.com/aerospike/tools-common-go/flags"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand All @@ -19,34 +18,29 @@ import (

//nolint:govet // Padding not a concern for a CLI
var dropIndexFlags = &struct {
host *flags.HostPortFlag
seeds *flags.SeedsSliceFlag
listenerName flags.StringOptionalFlag
namespace string
sets []string
indexName string
timeout time.Duration
clientFlags flags.ClientFlags
namespace string
sets []string
indexName string
timeout time.Duration
}{
host: flags.NewDefaultHostPortFlag(),
seeds: &flags.SeedsSliceFlag{},
clientFlags: *flags.NewClientFlags(),
}

func newDropIndexFlagSet() *pflag.FlagSet {
flagSet := &pflag.FlagSet{}
flagSet.VarP(dropIndexFlags.host, flagNameHost, "h", commonFlags.DefaultWrapHelpString(fmt.Sprintf("The AVS host to connect to. If cluster discovery is needed use --%s", flagNameSeeds))) //nolint:lll // For readability
flagSet.Var(dropIndexFlags.seeds, flagNameSeeds, commonFlags.DefaultWrapHelpString(fmt.Sprintf("The AVS seeds to use for cluster discovery. If no cluster discovery is needed (i.e. load-balancer) then use --%s", flagNameHost))) //nolint:lll // For readability
flagSet.VarP(&dropIndexFlags.listenerName, flagNameListenerName, "l", commonFlags.DefaultWrapHelpString("The listener to ask the AVS server for as configured in the AVS server. Likely required for cloud deployments.")) //nolint:lll // For readability
flagSet.StringVarP(&dropIndexFlags.namespace, flagNameNamespace, "n", "", commonFlags.DefaultWrapHelpString("The namespace for the index.")) //nolint:lll // For readability
flagSet.StringArrayVarP(&dropIndexFlags.sets, flagNameSets, "s", nil, commonFlags.DefaultWrapHelpString("The sets for the index.")) //nolint:lll // For readability
flagSet.StringVarP(&dropIndexFlags.indexName, flagNameIndexName, "i", "", commonFlags.DefaultWrapHelpString("The name of the index.")) //nolint:lll // For readability
flagSet.DurationVar(&dropIndexFlags.timeout, flagNameTimeout, time.Second*5, commonFlags.DefaultWrapHelpString("The distance metric for the index.")) //nolint:lll // For readability
flagSet.StringVarP(&dropIndexFlags.namespace, flags.Namespace, "n", "", commonFlags.DefaultWrapHelpString("The namespace for the index.")) //nolint:lll // For readability
flagSet.StringSliceVarP(&dropIndexFlags.sets, flags.Sets, "s", nil, commonFlags.DefaultWrapHelpString("The sets for the index.")) //nolint:lll // For readability
flagSet.StringVarP(&dropIndexFlags.indexName, flags.IndexName, "i", "", commonFlags.DefaultWrapHelpString("The name of the index.")) //nolint:lll // For readability
flagSet.DurationVar(&dropIndexFlags.timeout, flags.Timeout, time.Second*5, commonFlags.DefaultWrapHelpString("The distance metric for the index.")) //nolint:lll // For readability
flagSet.AddFlagSet(dropIndexFlags.clientFlags.NewClientFlagSet())

return flagSet
}

var dropIndexRequiredFlags = []string{
flagNameNamespace,
flagNameIndexName,
flags.Namespace,
flags.IndexName,
}

// dropIndexCmd represents the dropIndex command
Expand All @@ -62,38 +56,40 @@ func newDropIndexCommand() *cobra.Command {
asvec drop index -i myindex -n test
`,
PreRunE: func(_ *cobra.Command, _ []string) error {
if viper.IsSet(flagNameSeeds) && viper.IsSet(flagNameHost) {
return fmt.Errorf("only --%s or --%s allowed", flagNameSeeds, flagNameHost)
if viper.IsSet(flags.Seeds) && viper.IsSet(flags.Host) {
return fmt.Errorf("only --%s or --%s allowed", flags.Seeds, flags.Host)
}

return nil
},
RunE: func(_ *cobra.Command, _ []string) error {
logger.Debug("parsed flags",
slog.String(flagNameHost, dropIndexFlags.host.String()),
slog.String(flagNameSeeds, dropIndexFlags.seeds.String()),
slog.String(flagNameListenerName, dropIndexFlags.listenerName.String()),
slog.String(flagNameNamespace, dropIndexFlags.namespace),
slog.Any(flagNameSets, dropIndexFlags.sets),
slog.String(flagNameIndexName, dropIndexFlags.indexName),
slog.Duration(flagNameTimeout, dropIndexFlags.timeout),
append(dropIndexFlags.clientFlags.NewSLogAttr(),
slog.String(flags.Namespace, dropIndexFlags.namespace),
slog.Any(flags.Sets, dropIndexFlags.sets),
slog.String(flags.IndexName, dropIndexFlags.indexName),
slog.Duration(flags.Timeout, dropIndexFlags.timeout),
)...,
)

hosts, isLoadBalancer := parseBothHostSeedsFlag(dropIndexFlags.seeds, dropIndexFlags.host)

ctx, cancel := context.WithTimeout(context.Background(), dropIndexFlags.timeout)
defer cancel()

adminClient, err := avs.NewAdminClient(ctx, hosts, nil, isLoadBalancer, logger)
adminClient, err := createClientFromFlags(&dropIndexFlags.clientFlags, dropIndexFlags.timeout)
if err != nil {
logger.Error("failed to create AVS client", slog.Any("error", err))
return err
}

cancel()
defer adminClient.Close()

ctx, cancel = context.WithTimeout(context.Background(), dropIndexFlags.timeout)
if !confirm(fmt.Sprintf(
"Are you sure you want to drop the index %s on field %s?",
nsAndSetString(
createIndexFlags.namespace,
createIndexFlags.sets,
),
createIndexFlags.vectorField,
)) {
return nil
}

ctx, cancel := context.WithTimeout(context.Background(), dropIndexFlags.timeout)
defer cancel()

err = adminClient.IndexDrop(ctx, dropIndexFlags.namespace, dropIndexFlags.indexName)
Expand Down
52 changes: 52 additions & 0 deletions cmd/flags/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package flags

import (
"fmt"
"log/slog"

commonFlags "github.com/aerospike/tools-common-go/flags"
"github.com/spf13/pflag"
)

type ClientFlags struct {
Host *HostPortFlag
Seeds *SeedsSliceFlag
ListenerName StringOptionalFlag
User StringOptionalFlag
Password commonFlags.PasswordFlag
TLSFlags
}

func NewClientFlags() *ClientFlags {
return &ClientFlags{
Host: NewDefaultHostPortFlag(),
Seeds: &SeedsSliceFlag{},
TLSFlags: *NewTLSFlags(),
}
}

func (cf *ClientFlags) NewClientFlagSet() *pflag.FlagSet {
flagSet := &pflag.FlagSet{}
flagSet.VarP(cf.Host, Host, "h", commonFlags.DefaultWrapHelpString(fmt.Sprintf("The AVS host to connect to. If cluster discovery is needed use --%s", Seeds))) //nolint:lll // For readability
flagSet.Var(cf.Seeds, Seeds, commonFlags.DefaultWrapHelpString(fmt.Sprintf("The AVS seeds to use for cluster discovery. If no cluster discovery is needed (i.e. load-balancer) then use --%s", Host))) //nolint:lll // For readability
flagSet.VarP(&cf.ListenerName, ListenerName, "l", commonFlags.DefaultWrapHelpString("The listener to ask the AVS server for as configured in the AVS server. Likely required for cloud deployments.")) //nolint:lll // For readability
flagSet.VarP(&cf.User, User, "U", commonFlags.DefaultWrapHelpString("The AVS user to authenticate with.")) //nolint:lll // For readability
flagSet.VarP(&cf.Password, Password, "P", commonFlags.DefaultWrapHelpString("The AVS password for the specified user.")) //nolint:lll // For readability
flagSet.AddFlagSet(cf.NewTLSFlagSet(commonFlags.DefaultWrapHelpString))

return flagSet
}

func (cf *ClientFlags) NewSLogAttr() []any {
return []any{slog.String(Host, cf.Host.String()),
slog.String(Seeds, cf.Seeds.String()),
slog.String(ListenerName, cf.ListenerName.String()),
slog.String(User, cf.User.String()),
slog.String(Password, cf.Password.String()),
slog.Bool(TLSCaFile, cf.TLSRootCAFile != nil),
slog.Bool(TLSCaPath, cf.TLSRootCAPath != nil),
slog.Bool(TLSCertFile, cf.TLSCertFile != nil),
slog.Bool(TLSKeyFile, cf.TLSKeyFile != nil),
slog.Bool(TLSKeyFilePass, cf.TLSKeyFilePass != nil),
}
}
33 changes: 33 additions & 0 deletions cmd/flags/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package flags

const (
LogLevel = "log-level"
Seeds = "seeds"
Host = "host"
ListenerName = "listener-name"
User = "user"
Password = "password"
Namespace = "namespace"
Sets = "sets"
IndexName = "index-name"
VectorField = "vector-field"
Dimension = "dimension"
DistanceMetric = "distance-metric"
IndexMeta = "index-meta"
Timeout = "timeout"
Verbose = "verbose"
StorageNamespace = "storage-namespace"
StorageSet = "storage-set"
MaxEdges = "hnsw-max-edges"
ConstructionEf = "hnsw-ef-construction"
Ef = "hnsw-ef"
BatchMaxRecords = "hnsw-batch-max-records"
BatchInterval = "hnsw-batch-interval"
BatchEnabled = "hnsw-batch-enabled"
TLSProtocols = "tls-protocols"
TLSCaFile = "tls-cafile"
TLSCaPath = "tls-capath"
TLSCertFile = "tls-certfile"
TLSKeyFile = "tls-keyfile"
TLSKeyFilePass = "tls-keyfile-password"

Check failure on line 32 in cmd/flags/constants.go

View workflow job for this annotation

GitHub Actions / lint

G101: Potential hardcoded credentials (gosec)
)
2 changes: 1 addition & 1 deletion cmd/flags/distanceMetric.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"slices"
"strings"

"github.com/aerospike/aerospike-proximus-client-go/protos"
"github.com/aerospike/avs-client-go/protos"
)

type DistanceMetricFlag string
Expand Down
2 changes: 1 addition & 1 deletion cmd/flags/hostPort.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strconv"
"strings"

avs "github.com/aerospike/aerospike-proximus-client-go"
avs "github.com/aerospike/avs-client-go"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion cmd/flags/hostPort_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package flags
import (
"testing"

avs "github.com/aerospike/aerospike-proximus-client-go"
avs "github.com/aerospike/avs-client-go"

"github.com/stretchr/testify/suite"
)
Expand Down
61 changes: 61 additions & 0 deletions cmd/flags/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package flags

import (
"crypto/tls"

commonClient "github.com/aerospike/tools-common-go/client"
commonFlags "github.com/aerospike/tools-common-go/flags"
"github.com/spf13/pflag"
)

type TLSFlags struct {

Check failure on line 11 in cmd/flags/tls.go

View workflow job for this annotation

GitHub Actions / lint

fieldalignment: struct with 112 pointer bytes could be 104 (govet)
TLSProtocols commonFlags.TLSProtocolsFlag
TLSRootCAFile commonFlags.CertFlag
TLSRootCAPath commonFlags.CertPathFlag
TLSCertFile commonFlags.CertFlag
TLSKeyFile commonFlags.CertFlag
TLSKeyFilePass commonFlags.PasswordFlag
}

func NewTLSFlags() *TLSFlags {
return &TLSFlags{
TLSProtocols: commonFlags.NewDefaultTLSProtocolsFlag(),
}
}

// NewTLSFlagSet returns a new pflag.FlagSet with TLS flags defined. Values
// are stored in the TLSFlags struct.
func (tf *TLSFlags) NewTLSFlagSet(fmtUsage commonFlags.UsageFormatter) *pflag.FlagSet {
f := &pflag.FlagSet{}

f.Var(&tf.TLSRootCAFile, "tls-cafile", fmtUsage("The CA used when connecting to AVS."))
f.Var(&tf.TLSRootCAPath, "tls-capath", fmtUsage("A path containing CAs for connecting to AVS."))
f.Var(&tf.TLSCertFile, "tls-certfile", fmtUsage("The certificate file for mutual TLS authentication with AVS."))
f.Var(&tf.TLSKeyFile, "tls-keyfile", fmtUsage("The key file used for mutual TLS authentication with AVS."))
f.Var(&tf.TLSKeyFilePass, "tls-keyfile-password", fmtUsage("The password used to decrypt the key-file if encrypted."))
f.Var(&tf.TLSProtocols, "tls-protocols", fmtUsage(
"Set the TLS protocol selection criteria. This format is the same as"+
" Apache's SSLProtocol documented at https://httpd.apache.org/docs/current/mod/mod_ssl.html#ssl protocol.",
))

return f
}

func (tf *TLSFlags) NewTLSConfig() (*tls.Config, error) {
rootCA := [][]byte{}

if len(tf.TLSRootCAFile) != 0 {
rootCA = append(rootCA, tf.TLSRootCAFile)
}

rootCA = append(rootCA, tf.TLSRootCAPath...)

return commonClient.NewTLSConfig(
rootCA,
tf.TLSCertFile,
tf.TLSKeyFile,
tf.TLSKeyFilePass,
0,
0,
).NewGoTLSConfig()
}
Loading

0 comments on commit 5700529

Please sign in to comment.