Skip to content

Commit bb9b064

Browse files
authored
Merge pull request #147 from arangodb/feature/sync-access-pkg
Sync access packages
2 parents 4ab7a63 + 2745c9f commit bb9b064

File tree

16 files changed

+530
-173
lines changed

16 files changed

+530
-173
lines changed

deps/github.com/arangodb/arangosync/client/client_cache.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ func (cc *ClientCache) createClient(source Endpoint, auth Authentication, insecu
8585
return nil, maskAny(err)
8686
}
8787
ac := AuthenticationConfig{}
88-
if auth.JWTSecret != "" {
88+
if auth.Username != "" {
89+
ac.UserName = auth.Username
90+
ac.Password = auth.Password
91+
} else if auth.JWTSecret != "" {
8992
ac.JWTSecret = auth.JWTSecret
9093
} else if auth.ClientToken != "" {
9194
ac.BearerToken = auth.ClientToken
@@ -113,11 +116,13 @@ func NewAuthentication(tlsAuth TLSAuthentication, jwtSecret string) Authenticati
113116
type Authentication struct {
114117
TLSAuthentication
115118
JWTSecret string
119+
Username string
120+
Password string
116121
}
117122

118123
// String returns a string used to unique identify the authentication settings.
119124
func (a Authentication) String() string {
120-
return a.TLSAuthentication.String() + ":" + a.JWTSecret
125+
return a.TLSAuthentication.String() + ":" + a.JWTSecret + ":" + a.Username + ":" + a.Password
121126
}
122127

123128
// AuthProxy is a helper that implements github.com/arangodb-helper/go-certificates#TLSAuthentication.

docs/Manual/Deployment/Kubernetes/DeploymentReplicationResource.md

Lines changed: 126 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ The ArangoDB Replication Operator creates and maintains ArangoDB
55
This replication specification is a `CustomResource` following
66
a `CustomResourceDefinition` created by the operator.
77

8-
Example minimal replication definition:
8+
Example minimal replication definition for 2 ArangoDB cluster with sync in the same Kubernetes cluster:
99

1010
```yaml
1111
apiVersion: "replication.database.arangodb.com/v1alpha"
@@ -15,17 +15,46 @@ metadata:
1515
spec:
1616
source:
1717
deploymentName: cluster-a
18+
auth:
19+
keyfileSecretName: cluster-a-sync-auth
1820
destination:
1921
deploymentName: cluster-b
20-
auth:
21-
clientAuthSecretName: client-auth-cert
2222
```
2323
2424
This definition results in:
2525
2626
- the arangosync `SyncMaster` in deployment `cluster-b` is called to configure a synchronization
27-
from `cluster-a` to `cluster-b`, using the client authentication certificate stored in
28-
`Secret` `client-auth-cert`.
27+
from the syncmasters in `cluster-a` to the syncmasters in `cluster-b`,
28+
using the client authentication certificate stored in `Secret` `cluster-a-sync-auth`.
29+
To access `cluster-a`, the JWT secret found in the deployment of `cluster-a` is used.
30+
To access `cluster-b`, the JWT secret found in the deployment of `cluster-b` is used.
31+
32+
Example replication definition for replicating from a source that is outside the current Kubernetes cluster
33+
to a destination that is in the same Kubernetes cluster:
34+
35+
```yaml
36+
apiVersion: "replication.database.arangodb.com/v1alpha"
37+
kind: "ArangoDeploymentReplication"
38+
metadata:
39+
name: "replication-from-a-to-b"
40+
spec:
41+
source:
42+
endpoint: ["https://163.172.149.229:31888", "https://51.15.225.110:31888", "https://51.15.229.133:31888"]
43+
auth:
44+
keyfileSecretName: cluster-a-sync-auth
45+
tls:
46+
caSecretName: cluster-a-sync-ca
47+
destination:
48+
deploymentName: cluster-b
49+
```
50+
51+
This definition results in:
52+
53+
- the arangosync `SyncMaster` in deployment `cluster-b` is called to configure a synchronization
54+
from the syncmasters located at the given list of endpoint URL's to the syncmasters `cluster-b`,
55+
using the client authentication certificate stored in `Secret` `cluster-a-sync-auth`.
56+
To access `cluster-a`, the keyfile (containing a client authentication certificate) is used.
57+
To access `cluster-b`, the JWT secret found in the deployment of `cluster-b` is used.
2958

3059
## Specification reference
3160

@@ -38,13 +67,7 @@ with sync enabled.
3867

3968
This cluster configured as the replication source.
4069

41-
### `spec.source.deploymentNamespace: string`
42-
43-
This setting specifies the Kubernetes namespace of an `ArangoDeployment` resource specified in `spec.source.deploymentName`.
44-
45-
If this setting is empty, the namespace of the `ArangoDeploymentReplication` is used.
46-
47-
### `spec.source.masterEndpoints: []string`
70+
### `spec.source.endpoint: []string`
4871

4972
This setting specifies zero or more master endpoint URL's of the source cluster.
5073

@@ -53,12 +76,23 @@ that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication`
5376

5477
Specifying this setting and `spec.source.deploymentName` at the same time is not allowed.
5578

56-
### `spec.source.auth.jwtSecretName: string`
79+
### `spec.source.auth.keyfileSecretName: string`
5780

58-
This setting specifies the name of a `Secret` containing a JWT `token` used to authenticate
81+
This setting specifies the name of a `Secret` containing a client authentication certificate called `tls.keyfile` used to authenticate
5982
with the SyncMaster at the specified source.
6083

61-
This setting is required, unless `spec.source.deploymentName` has been set.
84+
If `spec.source.auth.userSecretName` has not been set,
85+
the client authentication certificate found in the secret with this name is also used to configure
86+
the synchronization and fetch the synchronization status.
87+
88+
This setting is required.
89+
90+
### `spec.source.auth.userSecretName: string`
91+
92+
This setting specifies the name of a `Secret` containing a `username` & `password` used to authenticate
93+
with the SyncMaster at the specified source in order to configure synchronization and fetch synchronization status.
94+
95+
The user identified by the username must have write access in the `_system` database of the source ArangoDB cluster.
6296

6397
### `spec.source.tls.caSecretName: string`
6498

@@ -74,13 +108,7 @@ with sync enabled.
74108

75109
This cluster configured as the replication destination.
76110

77-
### `spec.destination.deploymentNamespace: string`
78-
79-
This setting specifies the Kubernetes namespace of an `ArangoDeployment` resource specified in `spec.destination.deploymentName`.
80-
81-
If this setting is empty, the namespace of the `ArangoDeploymentReplication` is used.
82-
83-
### `spec.destination.masterEndpoints: []string`
111+
### `spec.destination.endpoint: []string`
84112

85113
This setting specifies zero or more master endpoint URL's of the destination cluster.
86114

@@ -89,12 +117,27 @@ that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication`
89117

90118
Specifying this setting and `spec.destination.deploymentName` at the same time is not allowed.
91119

92-
### `spec.destination.auth.jwtSecretName: string`
120+
### `spec.destination.auth.keyfileSecretName: string`
93121

94-
This setting specifies the name of a `Secret` containing a JWT `token` used to authenticate
122+
This setting specifies the name of a `Secret` containing a client authentication certificate called `tls.keyfile` used to authenticate
95123
with the SyncMaster at the specified destination.
96124

97-
This setting is required, unless `spec.destination.deploymentName` has been set.
125+
If `spec.destination.auth.userSecretName` has not been set,
126+
the client authentication certificate found in the secret with this name is also used to configure
127+
the synchronization and fetch the synchronization status.
128+
129+
This setting is required, unless `spec.destination.deploymentName` or `spec.destination.auth.userSecretName` has been set.
130+
131+
Specifying this setting and `spec.destination.userSecretName` at the same time is not allowed.
132+
133+
### `spec.destination.auth.userSecretName: string`
134+
135+
This setting specifies the name of a `Secret` containing a `username` & `password` used to authenticate
136+
with the SyncMaster at the specified destination in order to configure synchronization and fetch synchronization status.
137+
138+
The user identified by the username must have write access in the `_system` database of the destination ArangoDB cluster.
139+
140+
Specifying this setting and `spec.destination.keyfileSecretName` at the same time is not allowed.
98141

99142
### `spec.destination.tls.caSecretName: string`
100143

@@ -103,8 +146,62 @@ the TLS connection created by the SyncMaster at the specified destination.
103146

104147
This setting is required, unless `spec.destination.deploymentName` has been set.
105148

106-
### `spec.auth.clientAuthSecretName: string`
149+
## Authentication details
150+
151+
The authentication settings in a `ArangoDeploymentReplication` resource are used for two distinct purposes.
152+
153+
The first use is the authentication of the syncmasters at the destination with the syncmasters at the source.
154+
This is always done using a client authentication certificate which is found in a `tls.keyfile` field
155+
in a secret identified by `spec.source.auth.keyfileSecretName`.
156+
157+
The second use is the authentication of the ArangoDB Replication operator with the syncmasters at the source
158+
or destination. These connections are made to configure synchronization, stop configuration and fetch the status
159+
of the configuration.
160+
The method used for this authentication is derived as follows (where `X` is either `source` or `destination`):
161+
162+
- If `spec.X.userSecretName` is set, the username + password found in the `Secret` identified by this name is used.
163+
- If `spec.X.keyfileSecretName` is set, the client authentication certificate (keyfile) found in the `Secret` identifier by this name is used.
164+
- If `spec.X.deploymentName` is set, the JWT secret found in the deployment is used.
165+
166+
## Creating client authentication certificate keyfiles
167+
168+
The client authentication certificates needed for the `Secrets` identified by `spec.source.auth.keyfileSecretName` & `spec.destination.auth.keyfileSecretName`
169+
are normal ArangoDB keyfiles that can be created by the `arangosync create client-auth keyfile` command.
170+
In order to do so, you must have access to the client authentication CA of the source/destination.
171+
172+
If the client authentication CA at the source/destination also contains a private key (`ca.key`), the ArangoDeployment operator
173+
can be used to create such a keyfile for you, without the need to have `arangosync` installed locally.
174+
Read the following paragraphs for instructions on how to do that.
175+
176+
## Creating and using access packages
177+
178+
An access package is a YAML file that contains:
179+
180+
- A client authentication certificate, wrapped in a `Secret` in a `tls.keyfile` data field.
181+
- A TLS certificate authority public key, wrapped in a `Secret` in a `ca.crt` data field.
182+
183+
The format of the access package is such that it can be inserted into a Kubernetes cluster using the standard `kubectl` tool.
184+
185+
To create an access package that can be used to authenticate with the ArangoDB SyncMasters of an `ArangoDeployment`,
186+
add a name of a non-existing `Secret` to the `spec.sync.externalAccess.accessPackageSecretNames` field of the `ArangoDeployment`.
187+
In response, a `Secret` is created in that Kubernetes cluster, with the given name, that contains a `accessPackage.yaml` data field
188+
that contains a Kubernetes resource specification that can be inserted into the other Kubernetes cluster.
189+
190+
The process for creating and using an access package for authentication at the source cluster is as follows:
191+
192+
- Edit the `ArangoDeployment` resource of the source cluster, set `spec.sync.externalAccess.accessPackageSecretNames` to `["my-access-package"]`
193+
- Wait for the `ArangoDeployment` operator to create a `Secret` named `my-access-package`.
194+
- Extract the access package from the Kubernetes source cluster using:
195+
196+
```bash
197+
kubectl get secret my-access-package --template='{{index .data "accessPackage.yaml"}}' | base64 -D > accessPackage.yaml
198+
```
199+
200+
- Insert the secrets found in the access package in the Kubernetes destination cluster using:
201+
202+
```bash
203+
kubectl apply -f accessPackage.yaml
204+
```
107205

108-
This setting specifies the name of a `Secret` containing a client authentication certificate,
109-
used to authenticate the SyncMaster in the destination cluster with the SyncMaster in the
110-
source cluster.
206+
As a result, the destination Kubernetes cluster will have 2 additional `Secrets`. One contains a client authentication certificate
207+
formatted as a keyfile. Another contains the public key of the TLS CA certificate of the source cluster.

docs/Manual/Deployment/Kubernetes/DeploymentResource.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,19 @@ If not set, this setting defaults to:
241241
- If `spec.sync.externalAccess.loadBalancerIP` is set, it defaults to `https://<load-balancer-ip>:<8629>`.
242242
- Otherwise it defaults to `https://<sync-service-dns-name>:<8629>`.
243243

244+
### `spec.sync.externalAccess.accessPackageSecretNames: []string`
245+
246+
This setting specifies the names of zero of more `Secrets` that will be created by the deployment
247+
operator containing "access packages". An access package contains those `Secrets` that are needed
248+
to access the SyncMasters of this `ArangoDeployment`.
249+
250+
By removing a name from this setting, the corresponding `Secret` is also deleted.
251+
Note that to remove all access packages, leave an empty array in place (`[]`).
252+
Completely removing the setting results in not modifying the list.
253+
254+
See [the `ArangoDeploymentReplication` specification](./DeploymentReplicationResource.md) for more information
255+
on access packages.
256+
244257
### `spec.sync.auth.jwtSecretName: string`
245258

246259
This setting specifies the name of a kubernetes `Secret` that contains

pkg/apis/deployment/v1alpha/sync_external_access_spec.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,27 @@ import (
2727
"net"
2828
"net/url"
2929
"strconv"
30+
31+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3032
)
3133

3234
// SyncExternalAccessSpec holds configuration for the external access provided for the sync deployment.
3335
type SyncExternalAccessSpec struct {
3436
ExternalAccessSpec
35-
MasterEndpoint []string `json:"masterEndpoint,omitempty"`
37+
MasterEndpoint []string `json:"masterEndpoint,omitempty"`
38+
AccessPackageSecretNames []string `json:accessPackageSecretNames,omitempty"`
3639
}
3740

3841
// GetMasterEndpoint returns the value of masterEndpoint.
3942
func (s SyncExternalAccessSpec) GetMasterEndpoint() []string {
4043
return s.MasterEndpoint
4144
}
4245

46+
// GetAccessPackageSecretNames returns the value of accessPackageSecretNames.
47+
func (s SyncExternalAccessSpec) GetAccessPackageSecretNames() []string {
48+
return s.AccessPackageSecretNames
49+
}
50+
4351
// ResolveMasterEndpoint returns the value of `--master.endpoint` option passed to arangosync.
4452
func (s SyncExternalAccessSpec) ResolveMasterEndpoint(syncServiceHostName string, syncServicePort int) []string {
4553
if len(s.MasterEndpoint) > 0 {
@@ -61,6 +69,11 @@ func (s SyncExternalAccessSpec) Validate() error {
6169
return maskAny(fmt.Errorf("Failed to parse master endpoint '%s': %s", ep, err))
6270
}
6371
}
72+
for _, name := range s.AccessPackageSecretNames {
73+
if err := k8sutil.ValidateResourceName(name); err != nil {
74+
return maskAny(fmt.Errorf("Invalid name '%s' in accessPackageSecretNames: %s", name, err))
75+
}
76+
}
6477
return nil
6578
}
6679

@@ -75,6 +88,9 @@ func (s *SyncExternalAccessSpec) SetDefaultsFrom(source SyncExternalAccessSpec)
7588
if s.MasterEndpoint == nil && source.MasterEndpoint != nil {
7689
s.MasterEndpoint = append([]string{}, source.MasterEndpoint...)
7790
}
91+
if s.AccessPackageSecretNames == nil && source.AccessPackageSecretNames != nil {
92+
s.AccessPackageSecretNames = append([]string{}, source.AccessPackageSecretNames...)
93+
}
7894
}
7995

8096
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,11 @@ func (in *SyncExternalAccessSpec) DeepCopyInto(out *SyncExternalAccessSpec) {
653653
*out = make([]string, len(*in))
654654
copy(*out, *in)
655655
}
656+
if in.AccessPackageSecretNames != nil {
657+
in, out := &in.AccessPackageSecretNames, &out.AccessPackageSecretNames
658+
*out = make([]string, len(*in))
659+
copy(*out, *in)
660+
}
656661
return
657662
}
658663

pkg/apis/replication/v1alpha/authentication_spec.go

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)