Skip to content

Commit be86452

Browse files
nasrommvictorraharonh
authored
Add password authentication (#32)
* add options to command line * minor fix * add authentication option to cassandra * remove cqlshrc file and use default credentials instead * add readme and change naming * aff indent * remove mod files --------- Co-authored-by: victorr <victor.romanov@nuvocares.com> Co-authored-by: aharonh <aharon.haravon@gmail.com>
1 parent bdb22f5 commit be86452

File tree

7 files changed

+198
-107
lines changed

7 files changed

+198
-107
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@
1414
# dep/glide
1515
vendor/
1616
bin/
17+
rebuild.sh
18+
go.mod
19+
go.sum

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ TRAVIS := $(shell printenv TRAVIS)
1111
all: bootstrap build docker push
1212

1313
fmt:
14-
go fmt ./pkg/... ./cmd/...
14+
go fmt -mod=mod ./pkg/... ./cmd/...
1515

1616
vet:
17-
go vet ./pkg/... ./cmd/...
17+
go vet -mod=mod ./pkg/... ./cmd/...
1818

1919
# Build cain binary
2020
build: fmt vet
21-
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags $(LDFLAGS) -o bin/cain cmd/cain.go
21+
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=mod -ldflags $(LDFLAGS) -o bin/cain cmd/cain.go
2222

2323
# Build cain docker image
2424
docker: fmt vet

README.md

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,18 @@ Usage:
5555
cain backup [flags]
5656
5757
Flags:
58-
-b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75)
59-
--cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data")
60-
-c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra")
61-
--dst string destination to backup to. Example: s3://bucket/cassandra. Overrides $CAIN_DST
62-
-k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE
63-
-n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default")
64-
-p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1)
65-
-l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra")
58+
-a, --authentication use authentication for nodetool and clqsh. Overrides $CAIN_AUTHENTICATION
59+
-b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75)
60+
--cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data")
61+
-u, --cassandra-username string cassandra username. Overrides $CAIN_CASSANDRA_USERNAME (default "cain")
62+
-c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra")
63+
--dst string destination to backup to. Example: s3://bucket/cassandra. Overrides $CAIN_DST
64+
-h, --help help for backup
65+
-k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE
66+
-n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default")
67+
--nodetool-credentials-file string path to nodetool credentials file. Overrides $CAIN_NODETOOL_CREDENTIALS_FILE (default "/home/cassandra/.nodetool/credentials")
68+
-p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1)
69+
-l, --selector string
6670
```
6771

6872
#### Examples
@@ -77,6 +81,19 @@ cain backup \
7781
--dst s3://db-backup/cassandra
7882
```
7983

84+
Backup to AWS S3 with Cassandra authentication enabled
85+
86+
```
87+
cain backup \
88+
-n default \
89+
-l release=cassandra \
90+
-k keyspace \
91+
--dst s3://db-backup/cassandra
92+
-a
93+
-u cain
94+
--nodetool-credentials-file /home/cassandra/.nodetool/credentials
95+
```
96+
8097
Backup to Azure Blob Storage
8198

8299
```
@@ -105,17 +122,21 @@ Usage:
105122
cain restore [flags]
106123
107124
Flags:
108-
-b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75)
109-
--cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data")
110-
-c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra")
111-
-k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE
112-
-n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default")
113-
-p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1)
114-
-s, --schema string schema version to restore (optional). Overrides $CAIN_SCHEMA
115-
-l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra")
116-
--src string source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name. Overrides $CAIN_SRC
117-
-t, --tag string tag to restore. Overrides $CAIN_TAG
118-
--user-group string user and group who should own restored files. Overrides $CAIN_USER_GROUP (default "cassandra:cassandra")
125+
-a, --authentication use authentication for nodetool and clqsh. Overrides $CAIN_AUTHENTICATION
126+
-b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75)
127+
--cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data")
128+
-u, --cassandra-username string cassandra username. Overrides $CAIN_CASSANDRA_USERNAME (default "cain")
129+
-c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra")
130+
-h, --help help for restore
131+
-k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE
132+
-n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default")
133+
-f, --nodetool-credentials-file string path to nodetool credentials file. Overrides $CAIN_NODETOOL_CREDENTIALS_FILE (default "/home/cassandra/.nodetool/credentials")
134+
-p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1)
135+
-s, --schema string schema version to restore (optional). Overrides $CAIN_SCHEMA
136+
-l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra")
137+
--src string source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name. Overrides $CAIN_SRC
138+
-t, --tag string tag to restore. Overrides $CAIN_TAG
139+
--user-group string user and group who should own restored files. Overrides $CAIN_USER_GROUP (default "cassandra:cassandra")
119140
```
120141

121142
#### Examples
@@ -211,6 +232,7 @@ Since Cain uses [Skbn](https://github.com/nuvo/skbn), adding support for additio
211232

212233
| Cain version | Skbn version |
213234
|--------------|--------------|
235+
| 0.5.2 | 0.4.2 |
214236
| 0.5.1 | 0.4.2 |
215237
| 0.5.0 | 0.4.1 |
216238
| 0.4.2 | 0.4.1 |
@@ -239,6 +261,18 @@ Skbn uses the default AWS [credentials chain](https://docs.aws.amazon.com/sdk-fo
239261

240262
Skbn uses `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_ACCESS_KEY` environment variables for authentication.
241263

264+
### Cassandra Credentials
265+
When Authentication is enabled Cain will look for default credentials
266+
for `cqlsh` in `/home/cassandra/.cassandra/credentials`
267+
if you use authentication please make sure the cassandra
268+
container has this file and the username and password are correct.
269+
270+
For `nodetool` authentications default credentials are in:
271+
`/home/cassandra/.nodetool/credentials` can be overridden by
272+
setting the `--nodetool-credentials-file` flag.
273+
When this flag is used, the username for the nodetool
274+
authentication must be provided as well .
275+
242276
## Examples
243277

244278
1. [Helm example](/examples/helm)

cmd/cain.go

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ func NewRootCmd(args []string) *cobra.Command {
3939
}
4040

4141
type backupCmd struct {
42-
namespace string
43-
selector string
44-
container string
45-
keyspace string
46-
dst string
47-
parallel int
48-
bufferSize float64
49-
cassandraDataDir string
42+
namespace string
43+
selector string
44+
container string
45+
keyspace string
46+
dst string
47+
parallel int
48+
bufferSize float64
49+
cassandraDataDir string
50+
authentication bool
51+
cassandraUsername string
52+
nodetoolCredentialsFile string
5053

5154
out io.Writer
5255
}
@@ -73,14 +76,17 @@ func NewBackupCmd(out io.Writer) *cobra.Command {
7376
},
7477
Run: func(cmd *cobra.Command, args []string) {
7578
options := cain.BackupOptions{
76-
Namespace: b.namespace,
77-
Selector: b.selector,
78-
Container: b.container,
79-
Keyspace: b.keyspace,
80-
Dst: b.dst,
81-
Parallel: b.parallel,
82-
BufferSize: b.bufferSize,
83-
CassandraDataDir: b.cassandraDataDir,
79+
Namespace: b.namespace,
80+
Selector: b.selector,
81+
Container: b.container,
82+
Keyspace: b.keyspace,
83+
Dst: b.dst,
84+
Parallel: b.parallel,
85+
BufferSize: b.bufferSize,
86+
CassandraDataDir: b.cassandraDataDir,
87+
Authentication: b.authentication,
88+
CassandraUsername: b.cassandraUsername,
89+
NodetoolCredentialsFile: b.nodetoolCredentialsFile,
8490
}
8591
if _, err := cain.Backup(options); err != nil {
8692
log.Fatal(err)
@@ -97,22 +103,27 @@ func NewBackupCmd(out io.Writer) *cobra.Command {
97103
f.IntVarP(&b.parallel, "parallel", "p", utils.GetIntEnvVar("CAIN_PARALLEL", 1), "number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL")
98104
f.Float64VarP(&b.bufferSize, "buffer-size", "b", utils.GetFloat64EnvVar("CAIN_BUFFER_SIZE", 6.75), "in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE")
99105
f.StringVar(&b.cassandraDataDir, "cassandra-data-dir", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR")
100-
106+
f.BoolVarP(&b.authentication, "authentication", "a", utils.GetBoolEnvVar("CAIN_AUTHENTICATION", false), "use authentication for nodetool and clqsh. Overrides $CAIN_AUTHENTICATION")
107+
f.StringVarP(&b.cassandraUsername, "cassandra-username", "u", utils.GetStringEnvVar("CAIN_CASSANDRA_USERNAME", "cain"), "cassandra username. Overrides $CAIN_CASSANDRA_USERNAME")
108+
f.StringVar(&b.nodetoolCredentialsFile, "nodetool-credentials-file", utils.GetStringEnvVar("CAIN_NODETOOL_CREDENTIALS_FILE", "/home/cassandra/.nodetool/credentials"), "path to nodetool credentials file. Overrides $CAIN_NODETOOL_CREDENTIALS_FILE")
101109
return cmd
102110
}
103111

104112
type restoreCmd struct {
105-
src string
106-
keyspace string
107-
tag string
108-
schema string
109-
namespace string
110-
selector string
111-
container string
112-
parallel int
113-
bufferSize float64
114-
userGroup string
115-
cassandraDataDir string
113+
src string
114+
keyspace string
115+
tag string
116+
schema string
117+
namespace string
118+
selector string
119+
container string
120+
parallel int
121+
bufferSize float64
122+
userGroup string
123+
cassandraDataDir string
124+
authentication bool
125+
cassandraUsername string
126+
nodetoolCredentialsFile string
116127

117128
out io.Writer
118129
}
@@ -142,17 +153,20 @@ func NewRestoreCmd(out io.Writer) *cobra.Command {
142153
},
143154
Run: func(cmd *cobra.Command, args []string) {
144155
options := cain.RestoreOptions{
145-
Src: r.src,
146-
Keyspace: r.keyspace,
147-
Tag: r.tag,
148-
Schema: r.schema,
149-
Namespace: r.namespace,
150-
Selector: r.selector,
151-
Container: r.container,
152-
Parallel: r.parallel,
153-
BufferSize: r.bufferSize,
154-
UserGroup: r.userGroup,
155-
CassandraDataDir: r.cassandraDataDir,
156+
Src: r.src,
157+
Keyspace: r.keyspace,
158+
Tag: r.tag,
159+
Schema: r.schema,
160+
Namespace: r.namespace,
161+
Selector: r.selector,
162+
Container: r.container,
163+
Parallel: r.parallel,
164+
BufferSize: r.bufferSize,
165+
UserGroup: r.userGroup,
166+
CassandraDataDir: r.cassandraDataDir,
167+
Authentication: r.authentication,
168+
CassandraUsername: r.cassandraUsername,
169+
NodetoolCredentialsFile: r.nodetoolCredentialsFile,
156170
}
157171
if err := cain.Restore(options); err != nil {
158172
log.Fatal(err)
@@ -172,7 +186,9 @@ func NewRestoreCmd(out io.Writer) *cobra.Command {
172186
f.Float64VarP(&r.bufferSize, "buffer-size", "b", utils.GetFloat64EnvVar("CAIN_BUFFER_SIZE", 6.75), "in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE")
173187
f.StringVar(&r.userGroup, "user-group", utils.GetStringEnvVar("CAIN_USER_GROUP", "cassandra:cassandra"), "user and group who should own restored files. Overrides $CAIN_USER_GROUP")
174188
f.StringVar(&r.cassandraDataDir, "cassandra-data-dir", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR")
175-
189+
f.BoolVarP(&r.authentication, "authentication", "a", utils.GetBoolEnvVar("CAIN_AUTHENTICATION", false), "use authentication for nodetool and clqsh. Overrides $CAIN_AUTHENTICATION")
190+
f.StringVarP(&r.cassandraUsername, "cassandra-username", "u", utils.GetStringEnvVar("CAIN_CASSANDRA_USERNAME", "cain"), "cassandra username. Overrides $CAIN_CASSANDRA_USERNAME")
191+
f.StringVarP(&r.nodetoolCredentialsFile, "nodetool-credentials-file", "f", utils.GetStringEnvVar("CAIN_NODETOOL_CREDENTIALS_FILE", "/home/cassandra/.nodetool/credentials"), "path to nodetool credentials file. Overrides $CAIN_NODETOOL_CREDENTIALS_FILE")
176192
return cmd
177193
}
178194

pkg/cain/cain.go

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,26 @@ import (
99
"github.com/nuvo/skbn/pkg/skbn"
1010
)
1111

12+
// Authentication options if cassandra cluster uses authentication
13+
type Credentials struct {
14+
enabled bool
15+
username string
16+
nodetoolCredentialsFile string
17+
}
18+
1219
// BackupOptions are the options to pass to Backup
1320
type BackupOptions struct {
14-
Namespace string
15-
Selector string
16-
Container string
17-
Keyspace string
18-
Dst string
19-
Parallel int
20-
BufferSize float64
21-
CassandraDataDir string
21+
Namespace string
22+
Selector string
23+
Container string
24+
Keyspace string
25+
Dst string
26+
Parallel int
27+
BufferSize float64
28+
CassandraDataDir string
29+
Authentication bool
30+
CassandraUsername string
31+
NodetoolCredentialsFile string
2232
}
2333

2434
// Backup performs backup
@@ -46,15 +56,26 @@ func Backup(o BackupOptions) (string, error) {
4656
if err := utils.TestK8sDirectory(k8sClient, pods, o.Namespace, o.Container, o.CassandraDataDir); err != nil {
4757
return "", err
4858
}
59+
creds := Credentials{
60+
enabled: o.Authentication,
61+
username: o.CassandraUsername,
62+
nodetoolCredentialsFile: o.NodetoolCredentialsFile,
63+
}
64+
if o.Authentication {
65+
log.Println("Testing existence of nodetool credentials file")
66+
if err := utils.TestK8sDirectory(k8sClient, pods, o.Namespace, o.Container, o.NodetoolCredentialsFile); err != nil {
67+
return "", err
68+
}
69+
}
4970

5071
log.Println("Backing up schema")
51-
dstBasePath, err := BackupKeyspaceSchema(k8sClient, dstClient, o.Namespace, pods[0], o.Container, o.Keyspace, dstPrefix, dstPath)
72+
dstBasePath, err := BackupKeyspaceSchema(k8sClient, dstClient, o.Namespace, pods[0], o.Container, o.Keyspace, dstPrefix, dstPath, creds)
5273
if err != nil {
5374
return "", err
5475
}
5576

5677
log.Println("Taking snapshots")
57-
tag := TakeSnapshots(k8sClient, pods, o.Namespace, o.Container, o.Keyspace)
78+
tag := TakeSnapshots(k8sClient, pods, o.Namespace, o.Container, o.Keyspace, creds)
5879

5980
log.Println("Calculating paths. This may take a while...")
6081
fromToPathsAllPods, err := utils.GetFromAndToPathsFromK8s(k8sClient, pods, o.Namespace, o.Container, o.Keyspace, tag, dstBasePath, o.CassandraDataDir)
@@ -68,25 +89,28 @@ func Backup(o BackupOptions) (string, error) {
6889
}
6990

7091
log.Println("Clearing snapshots")
71-
ClearSnapshots(k8sClient, pods, o.Namespace, o.Container, o.Keyspace, tag)
92+
ClearSnapshots(k8sClient, pods, o.Namespace, o.Container, o.Keyspace, tag, creds)
7293

7394
log.Println("All done!")
7495
return tag, nil
7596
}
7697

7798
// RestoreOptions are the options to pass to Restore
7899
type RestoreOptions struct {
79-
Src string
80-
Keyspace string
81-
Tag string
82-
Schema string
83-
Namespace string
84-
Selector string
85-
Container string
86-
Parallel int
87-
BufferSize float64
88-
UserGroup string
89-
CassandraDataDir string
100+
Src string
101+
Keyspace string
102+
Tag string
103+
Schema string
104+
Namespace string
105+
Selector string
106+
Container string
107+
Parallel int
108+
BufferSize float64
109+
UserGroup string
110+
CassandraDataDir string
111+
Authentication bool
112+
CassandraUsername string
113+
NodetoolCredentialsFile string
90114
}
91115

92116
// Restore performs restore
@@ -110,7 +134,17 @@ func Restore(o RestoreOptions) error {
110134
if err := utils.TestK8sDirectory(k8sClient, existingPods, o.Namespace, o.Container, o.CassandraDataDir); err != nil {
111135
return err
112136
}
113-
137+
creds := Credentials{
138+
enabled: o.Authentication,
139+
username: o.CassandraUsername,
140+
nodetoolCredentialsFile: o.NodetoolCredentialsFile,
141+
}
142+
if o.Authentication {
143+
log.Println("Testing existence of nodetool credentials file")
144+
if err := utils.TestK8sDirectory(k8sClient, existingPods, o.Namespace, o.Container, o.NodetoolCredentialsFile); err != nil {
145+
return err
146+
}
147+
}
114148
log.Println("Getting current schema")
115149
_, sum, err := DescribeKeyspaceSchema(k8sClient, o.Namespace, existingPods[0], o.Container, o.Keyspace)
116150
if err != nil {
@@ -163,7 +197,7 @@ func Restore(o RestoreOptions) error {
163197
}
164198

165199
log.Println("Refreshing tables")
166-
RefreshTables(k8sClient, o.Namespace, o.Container, o.Keyspace, podsToBeRestored, tablesToRefresh)
200+
RefreshTables(k8sClient, o.Namespace, o.Container, o.Keyspace, podsToBeRestored, tablesToRefresh, creds)
167201

168202
log.Println("All done!")
169203
return nil

0 commit comments

Comments
 (0)