Skip to content
This repository has been archived by the owner on Jan 12, 2023. It is now read-only.

Commit

Permalink
add option to configure approved password authenticators in Cassandra
Browse files Browse the repository at this point in the history
Signed-off-by: Jacob Lisi <jacob.t.lisi@gmail.com>
  • Loading branch information
jtlisi committed Feb 7, 2020
1 parent 522546a commit 9ab6560
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 17 deletions.
4 changes: 1 addition & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Changelog

## master / unreleased


## 0.6.1 / 2020-02-05

* [ENHANCEMENT] Cassandra Authentication: added the `custom_authenticator` config option that allows users to authenticate with cassandra clusters using password authenticators that are not approved by default in [gocql](https://github.com/gocql/gocql/blob/81b8263d9fe526782a588ef94d3fa5c6148e5d67/conn.go#L27)
* [BUGFIX] Fixed parsing of the WAL configuration when specified in the YAML config file. #2071

## 0.6.0 / 2020-01-28
Expand Down
43 changes: 43 additions & 0 deletions pkg/chunk/cassandra/authenticator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cassandra

import (
"fmt"

"github.com/gocql/gocql"
)

// CustomPasswordAuthenticator provides the default behaviour for Username/Password authentication with
// Cassandra while allowing users to specify a non-default Authenticator to accept.
type CustomPasswordAuthenticator struct {
ApprovedAuthenticators []string
Username string
Password string
}

func (p CustomPasswordAuthenticator) approve(authenticator string) bool {
for _, s := range p.ApprovedAuthenticators {
if authenticator == s {
return true
}
}
return false
}

// Challenge verifies the name of the authenticator and formats the provided username and password
// into a response
func (p CustomPasswordAuthenticator) Challenge(req []byte) ([]byte, gocql.Authenticator, error) {
if !p.approve(string(req)) {
return nil, nil, fmt.Errorf("unexpected authenticator %q", req)
}
resp := make([]byte, 2+len(p.Username)+len(p.Password))
resp[0] = 0
copy(resp[1:], p.Username)
resp[len(p.Username)+1] = 0
copy(resp[2+len(p.Username):], p.Password)
return resp, nil, nil
}

// Success returns nil by default, identical to the default PasswordAuthenticator
func (p CustomPasswordAuthenticator) Success(data []byte) error {
return nil
}
39 changes: 25 additions & 14 deletions pkg/chunk/cassandra/storage_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,26 @@ import (

"github.com/cortexproject/cortex/pkg/chunk"
"github.com/cortexproject/cortex/pkg/chunk/util"
"github.com/cortexproject/cortex/pkg/util/flagext"
)

// Config for a StorageClient
type Config struct {
Addresses string `yaml:"addresses,omitempty"`
Port int `yaml:"port,omitempty"`
Keyspace string `yaml:"keyspace,omitempty"`
Consistency string `yaml:"consistency,omitempty"`
ReplicationFactor int `yaml:"replication_factor,omitempty"`
DisableInitialHostLookup bool `yaml:"disable_initial_host_lookup,omitempty"`
SSL bool `yaml:"SSL,omitempty"`
HostVerification bool `yaml:"host_verification,omitempty"`
CAPath string `yaml:"CA_path,omitempty"`
Auth bool `yaml:"auth,omitempty"`
Username string `yaml:"username,omitempty"`
Password string `yaml:"password,omitempty"`
Timeout time.Duration `yaml:"timeout,omitempty"`
ConnectTimeout time.Duration `yaml:"connect_timeout,omitempty"`
Addresses string `yaml:"addresses,omitempty"`
Port int `yaml:"port,omitempty"`
Keyspace string `yaml:"keyspace,omitempty"`
Consistency string `yaml:"consistency,omitempty"`
ReplicationFactor int `yaml:"replication_factor,omitempty"`
DisableInitialHostLookup bool `yaml:"disable_initial_host_lookup,omitempty"`
SSL bool `yaml:"SSL,omitempty"`
HostVerification bool `yaml:"host_verification,omitempty"`
CAPath string `yaml:"CA_path,omitempty"`
Auth bool `yaml:"auth,omitempty"`
Username string `yaml:"username,omitempty"`
Password string `yaml:"password,omitempty"`
CustomAuthenticators flagext.StringSlice `yaml:"custom_authenticator"`
Timeout time.Duration `yaml:"timeout,omitempty"`
ConnectTimeout time.Duration `yaml:"connect_timeout,omitempty"`
}

// RegisterFlags adds the flags required to config this to the given FlagSet
Expand All @@ -46,6 +48,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
f.BoolVar(&cfg.Auth, "cassandra.auth", false, "Enable password authentication when connecting to cassandra.")
f.StringVar(&cfg.Username, "cassandra.username", "", "Username to use when connecting to cassandra.")
f.StringVar(&cfg.Password, "cassandra.password", "", "Password to use when connecting to cassandra.")
f.Var(&cfg.CustomAuthenticators, "cassandra.custom-authenticator", "If set, when authenticating with cassandra a custom authenticator will be expected during the handshake. This flag can be set multiple times.")
f.DurationVar(&cfg.Timeout, "cassandra.timeout", 600*time.Millisecond, "Timeout when connecting to cassandra.")
f.DurationVar(&cfg.ConnectTimeout, "cassandra.connect-timeout", 600*time.Millisecond, "Initial connection timeout, used during initial dial to server.")
}
Expand Down Expand Up @@ -84,6 +87,14 @@ func (cfg *Config) setClusterConfig(cluster *gocql.ClusterConfig) {
}
}
if cfg.Auth {
if len(cfg.CustomAuthenticators) != 0 {
cluster.Authenticator = CustomPasswordAuthenticator{
ApprovedAuthenticators: cfg.CustomAuthenticators,
Username: cfg.Username,
Password: cfg.Password,
}
return
}
cluster.Authenticator = gocql.PasswordAuthenticator{
Username: cfg.Username,
Password: cfg.Password,
Expand Down

0 comments on commit 9ab6560

Please sign in to comment.