Skip to content
This repository was archived by the owner on Nov 2, 2023. It is now read-only.

Commit f795736

Browse files
committed
Add SSL and password for Dashboards
Includes a refactor of the password generation and certs to make things cleaner. Signed-off-by: Dan Bason <[email protected]>
1 parent ca0d16a commit f795736

23 files changed

+695
-259
lines changed

README.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,15 @@ spec:
122122
| affinity | No | [Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core) | Affinity settings for the workload pods |
123123
| nodeSelector | No | map | NodeSelector for the workload pods. If this exists it will override the globalNodeSelector |
124124
| tolerations | No | [Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core) *array* | Tolerations for the workload. These will be combined with the globalTolerations (if any) |
125-
| opensearch | No | [OpensearchClusterRef](#opensearchclusterref) | Reference to an existing OpensearchCluster to point the Dashboards deployment at |
125+
| opensearch | No | [LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#localobjectreference-v1-core)| Reference to an existing OpensearchCluster to point the Dashboards deployment at. Must be in the same namespace |
126+
| opensearchConfig | No | [OpensearchConfigSpec](#opensearchconfigspec)| Configuration for an external Opensearch cluster |
127+
| tlsSecret | No | [LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#localobjectreference-v1-core)| A TLS secret containing the cert and key to use for Dashboards SSL. If the opensearch field is preset this isn't required as it will reuse the Opensearch HTTP CA to generate a cert |
126128

127-
#### OpensearchClusterRef
129+
#### OpensearchConfigSpec
128130

129131
| Field | Required | Type | Description |
130132
|:------|:---------|:-----|:------------|
131-
| name | Yes | *string* | Name of the OpensearchCluster resource |
132-
| namespace | No | *string* | Namespace of the OpensearchCluster resource. Defaults to the namespace of the Dashboards resource |
133+
| url | Yes | *string* | Endpoint for the Opensearch cluster |
134+
| username | Yes | *string* | Username to connect to the cluster with |
135+
| passwordFrom | Yes | [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#secretkeyselector-v1-core) | Secret key which contains the password for the cluster |
136+
| verifySSL | No | *bool* | Whether to use strict SSL checking. Defaults to true |

api/v1beta1/dashboards_types.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import (
2323

2424
// DashboardsSpec defines the desired state of OpensearchDashboard
2525
type DashboardsSpec struct {
26-
OpensearchCluster *OpensearchClusterRef `json:"opensearch,omitempty"`
27-
OpensearchURL string `json:"opensearchUrl,omitempty"`
26+
OpensearchCluster *corev1.LocalObjectReference `json:"opensearch,omitempty"`
27+
OpensearchConfig *OpensearchConfigSpec `json:"opensearchConfig,omitempty"`
2828
Version string `json:"version"`
2929
DefaultRepo *string `json:"defaultRepo,omitempty"`
3030
Image *ImageSpec `json:"image,omitempty"`
@@ -34,11 +34,14 @@ type DashboardsSpec struct {
3434
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
3535
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
3636
Persistence *PersistenceSpec `json:"persistence,omitempty"`
37+
TLSSecret *corev1.LocalObjectReference `json:"tlsSecret,omitempty"`
3738
}
3839

39-
type OpensearchClusterRef struct {
40-
Name string `json:"name,omitempty"`
41-
Namespace string `json:"namepace,omitempty"`
40+
type OpensearchConfigSpec struct {
41+
URL string `json:"url,omitempty"`
42+
Username string `json:"username,omitempty"`
43+
PasswordFrom *corev1.SecretKeySelector `json:"passwordFrom,omitempty"`
44+
VerifySSL *bool `json:"verifySSL,omitempty"`
4245
}
4346

4447
// DashboardsStatus defines the observed state of OpensearchDashboard

api/v1beta1/opensearchcluster_types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const (
7474
)
7575

7676
type AuthStatus struct {
77-
GenerateOpensearchHash *bool `json:"generateOpensearchHash"`
77+
GenerateOpensearchHash *bool `json:"generateOpensearchHash,omitempty"`
7878
OpensearchAuthSecretKeyRef *corev1.SecretKeySelector `json:"elasticsearchAuthSecretKeyRef,omitempty"`
7979
}
8080

api/v1beta1/zz_generated.deepcopy.go

+36-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/opensearch.opni.io_dashboards.yaml

+24-3
Original file line numberDiff line numberDiff line change
@@ -406,11 +406,27 @@ spec:
406406
properties:
407407
name:
408408
type: string
409-
namepace:
409+
type: object
410+
opensearchConfig:
411+
properties:
412+
passwordFrom:
413+
properties:
414+
key:
415+
type: string
416+
name:
417+
type: string
418+
optional:
419+
type: boolean
420+
required:
421+
- key
422+
type: object
423+
url:
424+
type: string
425+
username:
410426
type: string
427+
verifySSL:
428+
type: boolean
411429
type: object
412-
opensearchUrl:
413-
type: string
414430
persistence:
415431
properties:
416432
accessModes:
@@ -450,6 +466,11 @@ spec:
450466
x-kubernetes-int-or-string: true
451467
type: object
452468
type: object
469+
tlsSecret:
470+
properties:
471+
name:
472+
type: string
473+
type: object
453474
tolerations:
454475
items:
455476
properties:

config/crd/bases/opensearch.opni.io_opensearchclusters.yaml

-2
Original file line numberDiff line numberDiff line change
@@ -1535,8 +1535,6 @@ spec:
15351535
type: object
15361536
generateOpensearchHash:
15371537
type: boolean
1538-
required:
1539-
- generateOpensearchHash
15401538
type: object
15411539
conditions:
15421540
items:

controllers/dashboards_controller_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var _ = Describe("OpensearchCluster Controller", Label("controller"), func() {
3535
},
3636
Spec: v1beta1.DashboardsSpec{
3737
Version: "1.0.0",
38-
OpensearchCluster: &v1beta1.OpensearchClusterRef{
38+
OpensearchCluster: &corev1.LocalObjectReference{
3939
Name: "test-cluster",
4040
},
4141
NodeSelector: map[string]string{

controllers/opensearchcluster_controller_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ var _ = Describe("OpensearchCluster Controller", Label("controller"), func() {
221221
},
222222
})).Should(ExistAnd(
223223
HaveOwner(osCluster),
224-
HaveData("password", nil),
224+
HaveData("admin", nil),
225+
HaveData("dashboards", nil),
225226
))
226227
Eventually(Object(&corev1.Secret{
227228
ObjectMeta: metav1.ObjectMeta{

pkg/pki/errors.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package pki
33
import "errors"
44

55
var (
6-
ErrDecodeCA = errors.New("unable to decode CA PEM")
7-
ErrDecodeCAKey = errors.New("unabled to decode CA key PEM")
8-
ErrCertExpiring = errors.New("cert expiring within 10 days")
6+
ErrDecodeCA = errors.New("unable to decode CA PEM")
7+
ErrDecodeCAKey = errors.New("unabled to decode CA key PEM")
8+
ErrCertExpiring = errors.New("cert expiring within 10 days")
9+
ErrSecretDataMissing = errors.New("data missing from secret")
10+
ErrCARecreate = errors.New("ca needs to be recreated but can't be")
911
)

pkg/pki/pki.go

+51
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,35 @@ package pki
22

33
import (
44
"bytes"
5+
"context"
56
"crypto/rand"
67
"crypto/rsa"
78
"crypto/tls"
89
"crypto/x509"
910
"crypto/x509/pkix"
1011
"encoding/pem"
12+
"fmt"
1113
"math/big"
1214
"time"
15+
16+
corev1 "k8s.io/api/core/v1"
17+
"k8s.io/apimachinery/pkg/types"
18+
"sigs.k8s.io/controller-runtime/pkg/client"
1319
)
1420

1521
const (
1622
CertificatePEMType = "CERTIFICATE"
1723
RSAKeyPEMType = "RSA PRIVATE KEY"
1824
PKCS8KeyPEMType = "PRIVATE KEY"
25+
26+
TransportCASecretField = "transportca.crt"
27+
TransportCAKeySecretField = "transportca.key"
28+
RESTCASecretField = "httpca.crt"
29+
RESTCAKeySecretField = "httpca.key"
30+
TransportCertField = "transport.crt"
31+
TransportKeyField = "transport.key"
32+
RESTCertField = "http.crt"
33+
RESTKeyField = "http.key"
1934
)
2035

2136
func CreateCA(commonName string) (ca []byte, cakey []byte, err error) {
@@ -100,3 +115,39 @@ func SignCertificate(ca *tls.Certificate, cert *x509.Certificate, pubKey *rsa.Pu
100115

101116
return certPEMBuffer.Bytes(), nil
102117
}
118+
119+
func IsSecretDataMissing(err error) bool {
120+
return err == ErrSecretDataMissing
121+
}
122+
123+
func RetrieveCert(
124+
certField string,
125+
keyField string,
126+
opensearchName string,
127+
namespace string,
128+
client client.Client,
129+
) (
130+
cert []byte,
131+
key []byte,
132+
err error,
133+
) {
134+
secret := &corev1.Secret{}
135+
136+
err = client.Get(context.Background(), types.NamespacedName{
137+
Name: fmt.Sprintf("%s-os-pki", opensearchName),
138+
Namespace: namespace,
139+
}, secret)
140+
141+
if err != nil {
142+
return
143+
}
144+
145+
var certOK, keyOK bool
146+
cert, certOK = secret.Data[certField]
147+
key, keyOK = secret.Data[keyField]
148+
if !certOK || !keyOK {
149+
err = ErrSecretDataMissing
150+
return
151+
}
152+
return
153+
}

0 commit comments

Comments
 (0)