Skip to content
This repository was archived by the owner on Apr 30, 2025. It is now read-only.

Commit 9ab6560

Browse files
committed
add option to configure approved password authenticators in Cassandra
Signed-off-by: Jacob Lisi <[email protected]>
1 parent 522546a commit 9ab6560

File tree

3 files changed

+69
-17
lines changed

3 files changed

+69
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# Changelog
22

3-
## master / unreleased
4-
5-
63
## 0.6.1 / 2020-02-05
74

5+
* [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)
86
* [BUGFIX] Fixed parsing of the WAL configuration when specified in the YAML config file. #2071
97

108
## 0.6.0 / 2020-01-28
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package cassandra
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/gocql/gocql"
7+
)
8+
9+
// CustomPasswordAuthenticator provides the default behaviour for Username/Password authentication with
10+
// Cassandra while allowing users to specify a non-default Authenticator to accept.
11+
type CustomPasswordAuthenticator struct {
12+
ApprovedAuthenticators []string
13+
Username string
14+
Password string
15+
}
16+
17+
func (p CustomPasswordAuthenticator) approve(authenticator string) bool {
18+
for _, s := range p.ApprovedAuthenticators {
19+
if authenticator == s {
20+
return true
21+
}
22+
}
23+
return false
24+
}
25+
26+
// Challenge verifies the name of the authenticator and formats the provided username and password
27+
// into a response
28+
func (p CustomPasswordAuthenticator) Challenge(req []byte) ([]byte, gocql.Authenticator, error) {
29+
if !p.approve(string(req)) {
30+
return nil, nil, fmt.Errorf("unexpected authenticator %q", req)
31+
}
32+
resp := make([]byte, 2+len(p.Username)+len(p.Password))
33+
resp[0] = 0
34+
copy(resp[1:], p.Username)
35+
resp[len(p.Username)+1] = 0
36+
copy(resp[2+len(p.Username):], p.Password)
37+
return resp, nil, nil
38+
}
39+
40+
// Success returns nil by default, identical to the default PasswordAuthenticator
41+
func (p CustomPasswordAuthenticator) Success(data []byte) error {
42+
return nil
43+
}

pkg/chunk/cassandra/storage_client.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,26 @@ import (
1212

1313
"github.com/cortexproject/cortex/pkg/chunk"
1414
"github.com/cortexproject/cortex/pkg/chunk/util"
15+
"github.com/cortexproject/cortex/pkg/util/flagext"
1516
)
1617

1718
// Config for a StorageClient
1819
type Config struct {
19-
Addresses string `yaml:"addresses,omitempty"`
20-
Port int `yaml:"port,omitempty"`
21-
Keyspace string `yaml:"keyspace,omitempty"`
22-
Consistency string `yaml:"consistency,omitempty"`
23-
ReplicationFactor int `yaml:"replication_factor,omitempty"`
24-
DisableInitialHostLookup bool `yaml:"disable_initial_host_lookup,omitempty"`
25-
SSL bool `yaml:"SSL,omitempty"`
26-
HostVerification bool `yaml:"host_verification,omitempty"`
27-
CAPath string `yaml:"CA_path,omitempty"`
28-
Auth bool `yaml:"auth,omitempty"`
29-
Username string `yaml:"username,omitempty"`
30-
Password string `yaml:"password,omitempty"`
31-
Timeout time.Duration `yaml:"timeout,omitempty"`
32-
ConnectTimeout time.Duration `yaml:"connect_timeout,omitempty"`
20+
Addresses string `yaml:"addresses,omitempty"`
21+
Port int `yaml:"port,omitempty"`
22+
Keyspace string `yaml:"keyspace,omitempty"`
23+
Consistency string `yaml:"consistency,omitempty"`
24+
ReplicationFactor int `yaml:"replication_factor,omitempty"`
25+
DisableInitialHostLookup bool `yaml:"disable_initial_host_lookup,omitempty"`
26+
SSL bool `yaml:"SSL,omitempty"`
27+
HostVerification bool `yaml:"host_verification,omitempty"`
28+
CAPath string `yaml:"CA_path,omitempty"`
29+
Auth bool `yaml:"auth,omitempty"`
30+
Username string `yaml:"username,omitempty"`
31+
Password string `yaml:"password,omitempty"`
32+
CustomAuthenticators flagext.StringSlice `yaml:"custom_authenticator"`
33+
Timeout time.Duration `yaml:"timeout,omitempty"`
34+
ConnectTimeout time.Duration `yaml:"connect_timeout,omitempty"`
3335
}
3436

3537
// RegisterFlags adds the flags required to config this to the given FlagSet
@@ -46,6 +48,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
4648
f.BoolVar(&cfg.Auth, "cassandra.auth", false, "Enable password authentication when connecting to cassandra.")
4749
f.StringVar(&cfg.Username, "cassandra.username", "", "Username to use when connecting to cassandra.")
4850
f.StringVar(&cfg.Password, "cassandra.password", "", "Password to use when connecting to cassandra.")
51+
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.")
4952
f.DurationVar(&cfg.Timeout, "cassandra.timeout", 600*time.Millisecond, "Timeout when connecting to cassandra.")
5053
f.DurationVar(&cfg.ConnectTimeout, "cassandra.connect-timeout", 600*time.Millisecond, "Initial connection timeout, used during initial dial to server.")
5154
}
@@ -84,6 +87,14 @@ func (cfg *Config) setClusterConfig(cluster *gocql.ClusterConfig) {
8487
}
8588
}
8689
if cfg.Auth {
90+
if len(cfg.CustomAuthenticators) != 0 {
91+
cluster.Authenticator = CustomPasswordAuthenticator{
92+
ApprovedAuthenticators: cfg.CustomAuthenticators,
93+
Username: cfg.Username,
94+
Password: cfg.Password,
95+
}
96+
return
97+
}
8798
cluster.Authenticator = gocql.PasswordAuthenticator{
8899
Username: cfg.Username,
89100
Password: cfg.Password,

0 commit comments

Comments
 (0)