Skip to content

Commit b16029b

Browse files
informalictLars Maier
authored andcommitted
Feature/change user password (#463)
* Change password in a database for a user * Add unit tests * Change password for user when hash secret has changed * Add integration test for changing root password * Add disclaimer * Change comment * Run unit test for whole pkg/deployment/... * Check password in the database * Fix nil receiver * Fix removing root secret password * Fix unit test definition in Makefile * Don't validate non-existing users' secrets
1 parent 07f66d7 commit b16029b

File tree

10 files changed

+467
-39
lines changed

10 files changed

+467
-39
lines changed

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,7 @@ run-unit-tests: $(SOURCES)
308308
$(REPOPATH)/pkg/apis/deployment/v1alpha \
309309
$(REPOPATH)/pkg/apis/replication/v1alpha \
310310
$(REPOPATH)/pkg/apis/storage/v1alpha \
311-
$(REPOPATH)/pkg/deployment/reconcile \
312-
$(REPOPATH)/pkg/deployment/resources \
311+
$(REPOPATH)/pkg/deployment/... \
313312
$(REPOPATH)/pkg/storage \
314313
$(REPOPATH)/pkg/util/k8sutil \
315314
$(REPOPATH)/pkg/util/k8sutil/test \

pkg/apis/deployment/v1alpha/secret_hashes.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type SecretHashes struct {
3434
TLSCA string `json:"tls-ca,omitempty"`
3535
// SyncTLSCA contains the hash of the sync.tls.caSecretName secret
3636
SyncTLSCA string `json:"sync-tls-ca,omitempty"`
37+
// User's map contains hashes for each user
38+
Users map[string]string `json:"users,omitempty"`
3739
}
3840

3941
// Equal compares two SecretHashes
@@ -47,5 +49,40 @@ func (sh *SecretHashes) Equal(other *SecretHashes) bool {
4749
return sh.AuthJWT == other.AuthJWT &&
4850
sh.RocksDBEncryptionKey == other.RocksDBEncryptionKey &&
4951
sh.TLSCA == other.TLSCA &&
50-
sh.SyncTLSCA == other.SyncTLSCA
52+
sh.SyncTLSCA == other.SyncTLSCA &&
53+
isStringMapEqual(sh.Users, other.Users)
54+
}
55+
56+
// NewEmptySecretHashes creates new empty structure
57+
func NewEmptySecretHashes() *SecretHashes {
58+
sh := &SecretHashes{}
59+
sh.Users = make(map[string]string)
60+
return sh
61+
}
62+
63+
func isStringMapEqual(first map[string]string, second map[string]string) bool {
64+
if first == nil && second == nil {
65+
return true
66+
}
67+
68+
if first == nil || second == nil {
69+
return false
70+
}
71+
72+
if len(first) != len(second) {
73+
return false
74+
}
75+
76+
for key, valueF := range first {
77+
valueS, ok := second[key]
78+
if !ok {
79+
return false
80+
}
81+
82+
if valueF != valueS {
83+
return false
84+
}
85+
}
86+
87+
return true
5188
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2019 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
//
22+
23+
package v1alpha
24+
25+
import (
26+
"github.com/magiconair/properties/assert"
27+
28+
"testing"
29+
)
30+
31+
func TestSecretHashes_Equal(t *testing.T) {
32+
// Arrange
33+
sh := SecretHashes{}
34+
testCases := []struct {
35+
Name string
36+
CompareFrom *SecretHashes
37+
CompareTo *SecretHashes
38+
Expected bool
39+
}{
40+
{
41+
Name: "Parameter can not be nil",
42+
CompareFrom: &SecretHashes{},
43+
Expected: false,
44+
},
45+
{
46+
Name: "The addresses are the same",
47+
CompareFrom: &sh,
48+
CompareTo: &sh,
49+
Expected: true,
50+
},
51+
{
52+
Name: "JWT token is different",
53+
CompareFrom: &SecretHashes{
54+
AuthJWT: "1",
55+
},
56+
CompareTo: &SecretHashes{
57+
AuthJWT: "2",
58+
},
59+
Expected: false,
60+
},
61+
{
62+
Name: "Users are different",
63+
CompareFrom: &SecretHashes{
64+
Users: map[string]string{
65+
"root": "",
66+
},
67+
},
68+
CompareTo: &SecretHashes{},
69+
Expected: false,
70+
},
71+
{
72+
Name: "User's table size is different",
73+
CompareFrom: &SecretHashes{
74+
Users: map[string]string{
75+
"root": "",
76+
},
77+
},
78+
CompareTo: &SecretHashes{
79+
Users: map[string]string{
80+
"root": "",
81+
"user": "",
82+
},
83+
},
84+
Expected: false,
85+
},
86+
{
87+
Name: "User's table has got different users",
88+
CompareFrom: &SecretHashes{
89+
Users: map[string]string{
90+
"root": "",
91+
},
92+
},
93+
CompareTo: &SecretHashes{
94+
Users: map[string]string{
95+
"user": "",
96+
},
97+
},
98+
Expected: false,
99+
},
100+
{
101+
Name: "User's table has got different hashes for users",
102+
CompareFrom: &SecretHashes{
103+
Users: map[string]string{
104+
"root": "123",
105+
},
106+
},
107+
CompareTo: &SecretHashes{
108+
Users: map[string]string{
109+
"root": "1234",
110+
},
111+
},
112+
Expected: false,
113+
},
114+
{
115+
Name: "Secret hashes are the same",
116+
CompareFrom: &SecretHashes{
117+
AuthJWT: "1",
118+
RocksDBEncryptionKey: "2",
119+
TLSCA: "3",
120+
SyncTLSCA: "4",
121+
Users: map[string]string{
122+
"root": "123",
123+
},
124+
},
125+
CompareTo: &SecretHashes{
126+
AuthJWT: "1",
127+
RocksDBEncryptionKey: "2",
128+
TLSCA: "3",
129+
SyncTLSCA: "4",
130+
Users: map[string]string{
131+
"root": "123",
132+
},
133+
},
134+
Expected: true,
135+
},
136+
{
137+
Name: "Secret hashes are the same without users",
138+
CompareFrom: &SecretHashes{
139+
AuthJWT: "1",
140+
RocksDBEncryptionKey: "2",
141+
TLSCA: "3",
142+
SyncTLSCA: "4",
143+
},
144+
CompareTo: &SecretHashes{
145+
AuthJWT: "1",
146+
RocksDBEncryptionKey: "2",
147+
TLSCA: "3",
148+
SyncTLSCA: "4",
149+
},
150+
Expected: true,
151+
},
152+
}
153+
154+
for _, testCase := range testCases {
155+
//nolint:scopelint
156+
t.Run(testCase.Name, func(t *testing.T) {
157+
// Act
158+
expected := testCase.CompareFrom.Equal(testCase.CompareTo)
159+
160+
// Assert
161+
assert.Equal(t, testCase.Expected, expected)
162+
})
163+
}
164+
}

pkg/apis/deployment/v1alpha/zz_generated.deepcopy.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/deployment/bootstrap.go

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,7 @@ import (
3232
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3333
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3434

35-
driver "github.com/arangodb/go-driver"
36-
37-
"github.com/arangodb/kube-arangodb/pkg/util/constants"
38-
)
39-
40-
const (
41-
rootUserName = "root"
35+
"github.com/arangodb/go-driver"
4236
)
4337

4438
// EnsureBootstrap executes the bootstrap once as soon as the deployment becomes ready
@@ -81,7 +75,9 @@ func (d *Deployment) ensureUserPasswordSecret(secrets k8sutil.SecretInterface, u
8175
if auth, err := secrets.Get(secretName, metav1.GetOptions{}); k8sutil.IsNotFound(err) {
8276
// Create new one
8377
tokenData := make([]byte, 32)
84-
rand.Read(tokenData)
78+
if _, err = rand.Read(tokenData); err != nil {
79+
return "", err
80+
}
8581
token := hex.EncodeToString(tokenData)
8682
owner := d.GetAPIObject().AsOwner()
8783

@@ -91,12 +87,9 @@ func (d *Deployment) ensureUserPasswordSecret(secrets k8sutil.SecretInterface, u
9187

9288
return token, nil
9389
} else if err == nil {
94-
user, ok := auth.Data[constants.SecretUsername]
95-
if ok && string(user) == username {
96-
pass, ok := auth.Data[constants.SecretPassword]
97-
if ok {
98-
return string(pass), nil
99-
}
90+
user, pass, err := k8sutil.GetSecretAuthCredentials(auth)
91+
if err == nil && user == username {
92+
return pass, nil
10093
}
10194
return "", fmt.Errorf("invalid secret format in secret %s", secretName)
10295
} else {

pkg/deployment/informers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ package deployment
2424

2525
import (
2626
"k8s.io/api/core/v1"
27-
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
27+
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
2828
"k8s.io/client-go/tools/cache"
2929

3030
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"

0 commit comments

Comments
 (0)