Skip to content

Commit 7e3f46f

Browse files
author
tomjo
committed
feat: TLS authentication
1 parent 286c252 commit 7e3f46f

10 files changed

Lines changed: 187 additions & 6 deletions

File tree

api/v1alpha1/common.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type PulsarAuthentication struct {
4545

4646
// +optional
4747
OAuth2 *PulsarAuthenticationOAuth2 `json:"oauth2,omitempty"`
48+
49+
// +optional
50+
TLS *PulsarAuthenticationTLS `json:"tls,omitempty"`
4851
}
4952

5053
// PulsarResourceLifeCyclePolicy indicates whether it will keep or delete the resource
@@ -67,6 +70,12 @@ type PulsarAuthenticationOAuth2 struct {
6770
Key ValueOrSecretRef `json:"key"`
6871
}
6972

73+
// PulsarAuthenticationTLS indicates the parameters which are need by pulsar TLS Authentication
74+
type PulsarAuthenticationTLS struct {
75+
ClientCertificatePath string `json:"clientCertificatePath"`
76+
ClientCertificateKeyPath string `json:"clientCertificateKeyPath"`
77+
}
78+
7079
// IsPulsarResourceReady returns true if resource satisfies with these condition
7180
// 1. The instance is not deleted
7281
// 2. Status ObservedGeneration is equal with meta.ObservedGeneration

api/v1alpha1/pulsarconnection_types.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type PulsarConnectionSpec struct {
2929
// AdminServiceURL is the admin service url of the pulsar cluster
3030
// +optional
3131
// +kubebuilder:validation:Pattern="^https?://.+$"
32-
AdminServiceURL string `json:"adminServiceURL"`
32+
AdminServiceURL string `json:"adminServiceURL,omitempty"`
3333

3434
// Authentication defines authentication configurations
3535
// +optional
@@ -58,6 +58,19 @@ type PulsarConnectionSpec struct {
5858
// set when enabling the Geo Replication
5959
// +optional
6060
ClusterName string `json:"clusterName,omitempty"`
61+
62+
// TLSEnableHostnameVerification indicates whether to verify the hostname of the broker.
63+
// Only used when using secure urls.
64+
// +optional
65+
TLSEnableHostnameVerification bool `json:"tlsEnableHostnameVerification,omitempty"`
66+
67+
// TLSAllowInsecureConnection indicates whether to allow insecure connection to the broker.
68+
// +optional
69+
TLSAllowInsecureConnection bool `json:"tlsAllowInsecureConnection,omitempty"`
70+
71+
// TLSTrustCertsFilePath Path for the TLS certificate used to validate the broker endpoint when using TLS.
72+
// +optional
73+
TLSTrustCertsFilePath string `json:"tlsTrustCertsFilePath,omitempty"`
6174
}
6275

6376
// PulsarConnectionStatus defines the observed state of PulsarConnection

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/pulsar-resources-operator/crds/resource.streamnative.io_pulsarconnections.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ spec:
128128
- issuerEndpoint
129129
- key
130130
type: object
131+
tls:
132+
description: PulsarAuthenticationTLS indicates the parameters
133+
which are need by pulsar TLS Authentication
134+
properties:
135+
clientCertificateKeyPath:
136+
type: string
137+
clientCertificatePath:
138+
type: string
139+
required:
140+
- clientCertificateKeyPath
141+
- clientCertificatePath
142+
type: object
131143
token:
132144
description: ValueOrSecretRef is a string or a secret reference
133145
of the authentication
@@ -165,6 +177,18 @@ spec:
165177
description: ClusterName indicates the local cluster name of the pulsar
166178
cluster. It should set when enabling the Geo Replication
167179
type: string
180+
tlsAllowInsecureConnection:
181+
description: TLSAllowInsecureConnection indicates whether to allow
182+
insecure connection to the broker.
183+
type: boolean
184+
tlsEnableHostnameVerification:
185+
description: TLSEnableHostnameVerification indicates whether to verify
186+
the hostname of the broker. Only used when using secure urls.
187+
type: boolean
188+
tlsTrustCertsFilePath:
189+
description: TLSTrustCertsFilePath Path for the TLS certificate used
190+
to validate the broker endpoint when using TLS.
191+
type: string
168192
type: object
169193
status:
170194
description: PulsarConnectionStatus defines the observed state of PulsarConnection

charts/pulsar-resources-operator/templates/deployment.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ spec:
7575
periodSeconds: 20
7676
resources:
7777
{{- toYaml .Values.resources | nindent 10 }}
78+
{{- if .Values.volumeMounts }}
79+
volumeMounts:
80+
{{- toYaml .Values.volumeMounts | nindent 10 }}
81+
{{- end }}
82+
{{- if .Values.volumes }}
83+
volumes:
84+
{{- toYaml .Values.volumes | nindent 8 }}
85+
{{- end }}
7886
nodeSelector:
7987
{{- toYaml .Values.nodeSelector | nindent 8 }}
8088
affinity:

charts/pulsar-resources-operator/values.schema.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,32 @@
333333
},
334334
"additionalProperties": true
335335
},
336+
"volumes": {
337+
"$id": "#/properties/volumes",
338+
"type": "array",
339+
"title": "The volumes schema",
340+
"description": "An explanation about the purpose of this instance.",
341+
"examples": [
342+
[]
343+
],
344+
"additionalItems": true,
345+
"items": {
346+
"$id": "#/properties/volumes/items"
347+
}
348+
},
349+
"volumeMounts": {
350+
"$id": "#/properties/volumeMounts",
351+
"type": "array",
352+
"title": "The volumeMounts schema",
353+
"description": "An explanation about the purpose of this instance.",
354+
"examples": [
355+
[]
356+
],
357+
"additionalItems": true,
358+
"items": {
359+
"$id": "#/properties/volumeMounts/items"
360+
}
361+
},
336362
"nodeSelector": {
337363
"$id": "#/properties/nodeSelector",
338364
"type": "object",

config/crd/bases/resource.streamnative.io_pulsarconnections.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ spec:
128128
- issuerEndpoint
129129
- key
130130
type: object
131+
tls:
132+
description: PulsarAuthenticationTLS indicates the parameters
133+
which are need by pulsar TLS Authentication
134+
properties:
135+
clientCertificateKeyPath:
136+
type: string
137+
clientCertificatePath:
138+
type: string
139+
required:
140+
- clientCertificateKeyPath
141+
- clientCertificatePath
142+
type: object
131143
token:
132144
description: ValueOrSecretRef is a string or a secret reference
133145
of the authentication
@@ -165,6 +177,18 @@ spec:
165177
description: ClusterName indicates the local cluster name of the pulsar
166178
cluster. It should set when enabling the Geo Replication
167179
type: string
180+
tlsAllowInsecureConnection:
181+
description: TLSAllowInsecureConnection indicates whether to allow
182+
insecure connection to the broker.
183+
type: boolean
184+
tlsEnableHostnameVerification:
185+
description: TLSEnableHostnameVerification indicates whether to verify
186+
the hostname of the broker. Only used when using secure urls.
187+
type: boolean
188+
tlsTrustCertsFilePath:
189+
description: TLSTrustCertsFilePath Path for the TLS certificate used
190+
to validate the broker endpoint when using TLS.
191+
type: string
168192
type: object
169193
status:
170194
description: PulsarConnectionStatus defines the observed state of PulsarConnection

docs/pulsar_connection.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ Other `PulsarConnection` configuration examples:
117117
# Use the keyFile contents as the oauth2 key value
118118
value: {"type":"sn_service_account","client_id":"zvex72oGvFQMBQGZ2ozMxOus2s4tQASJ","client_secret":"60J6fo81j-h69_vVvYvqFOHs2NfOyy6pqGqwIhTgnxpQ7O3UH8PdCbVtdm_SJjIf","client_email":"contoso@sndev.auth.streamnative.cloud","issuer_url":"https://auth.streamnative.cloud"}
119119
120+
* TLS authentication
121+
122+
```yaml
123+
apiVersion: resource.streamnative.io/v1alpha1
124+
kind: PulsarConnection
125+
metadata:
126+
name: test-tls-auth-pulsar-connection
127+
namespace: test
128+
spec:
129+
adminServiceURL: http://test-pulsar-sn-platform-broker.test.svc.cluster.local:8080
130+
brokerServiceURL: pulsar://test-pulsar-sn-platform-broker.test.svc.cluster.local:6650
131+
clusterName: pulsar-cluster
132+
authentication:
133+
tls:
134+
clientCertificateKeyPath: /certs/tls.key
135+
clientCertificatePath: /certs/tls.crt
136+
```
137+
120138
This table lists specifications available for the `PulsarConnection` resource.
121139

122140
| Option | Description | Required or not |
@@ -127,7 +145,9 @@ This table lists specifications available for the `PulsarConnection` resource.
127145
| `brokerServiceSecureURL` | The broker service URL for secure connection to the Pulsar cluster, such as `pulsar+ssl://cluster-broker.test.svc.cluster.local:6651`. This option is required for configuring Geo-replication when TLS is enabled. This option is available for version `0.3.0` or above. | No |
128146
| `adminServiceSecureURL` | The admin service URL for secure connection to the Pulsar cluster, such as `https://cluster-broker.test.svc.cluster.local:443`. This option is available for version `0.3.0` or above. | No |
129147
| `clusterName` | The Pulsar cluster name. You can use the `pulsar-admin clusters list` command to get the Pulsar cluster name. This option is required for configuring Geo-replication. Provided from `0.3.0` | No |
130-
148+
| `tlsAllowInsecureConnection` | A flag that indicates whether to allow insecure connection to the broker. Provided from `0.5.0` | No |
149+
| `tlsEnableHostnameVerification` | A flag that indicates wether hostname verification is enabled. Provided from `0.5.0` | No |
150+
| `tlsTrustCertsFilePath` | The path to the certificate used during hostname verfification. Provided from `0.5.0` | No |
131151

132152
1. Apply the YAML file to create the Pulsar Connection.
133153

pkg/admin/interface.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package admin
1616

1717
import (
18+
"fmt"
1819
"io/ioutil"
1920
"os"
2021

@@ -177,6 +178,10 @@ type PulsarAdminConfig struct {
177178
ClientID string
178179
Audience string
179180
Key string
181+
182+
// TLS Authentication related configuration
183+
ClientCertificatePath string
184+
ClientCertificateKeyPath string
180185
}
181186

182187
// NewPulsarAdmin initialize a pulsar admin client with configuration
@@ -187,8 +192,10 @@ func NewPulsarAdmin(conf PulsarAdminConfig) (PulsarAdmin, error) {
187192
var adminClient admin.Client
188193

189194
config := &config.Config{
190-
WebServiceURL: conf.WebServiceURL,
191-
TLSAllowInsecureConnection: true,
195+
WebServiceURL: conf.WebServiceURL,
196+
TLSAllowInsecureConnection: conf.TLSAllowInsecureConnection,
197+
TLSEnableHostnameVerification: conf.TLSEnableHostnameVerification,
198+
TLSTrustCertsFilePath: conf.TLSTrustCertsFilePath,
192199
// V2 admin endpoint contains operations for tenant, namespace and topic.
193200
PulsarAPIVersion: config.V2,
194201
}
@@ -218,9 +225,22 @@ func NewPulsarAdmin(conf PulsarAdminConfig) (PulsarAdmin, error) {
218225
return nil, err
219226
}
220227
adminClient = admin.NewWithAuthProvider(config, oauthProvider)
221-
} else {
228+
} else if conf.Token != "" {
222229
config.Token = conf.Token
223230

231+
adminClient, err = admin.New(config)
232+
if err != nil {
233+
return nil, err
234+
}
235+
} else if conf.ClientCertificatePath != "" {
236+
config.AuthPlugin = auth.TLSPluginName
237+
config.AuthParams = fmt.Sprintf("{\"tlsCertFile\": %q, \"tlsKeyFile\": %q}", conf.ClientCertificatePath, conf.ClientCertificateKeyPath)
238+
239+
adminClient, err = admin.New(config)
240+
if err != nil {
241+
return nil, err
242+
}
243+
} else {
224244
adminClient, err = admin.New(config)
225245
if err != nil {
226246
return nil, err

pkg/connection/reconciler.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,21 @@ func (r *PulsarConnectionReconciler) MakePulsarAdminConfig(ctx context.Context)
192192
if r.connection.Spec.AdminServiceURL == "" && r.connection.Spec.AdminServiceSecureURL == "" {
193193
return nil, fmt.Errorf("adminServiceURL or adminServiceSecureURL must not be empty")
194194
}
195+
196+
tlsEnableHostnameVerification := r.connection.Spec.TLSEnableHostnameVerification
197+
tlsAllowInsecureConnection := r.connection.Spec.TLSAllowInsecureConnection
198+
tlsTrustCertsFilePath := r.connection.Spec.TLSTrustCertsFilePath
199+
200+
if r.connection.Spec.AdminServiceSecureURL == "" {
201+
tlsEnableHostnameVerification = false
202+
tlsAllowInsecureConnection = true
203+
tlsTrustCertsFilePath = ""
204+
}
195205
cfg := admin.PulsarAdminConfig{
196-
WebServiceURL: r.connection.Spec.AdminServiceURL,
206+
WebServiceURL: r.connection.Spec.AdminServiceURL,
207+
TLSAllowInsecureConnection: tlsAllowInsecureConnection,
208+
TLSEnableHostnameVerification: tlsEnableHostnameVerification,
209+
TLSTrustCertsFilePath: tlsTrustCertsFilePath,
197210
}
198211
hasAuth := false
199212
if authn := r.connection.Spec.Authentication; authn != nil {
@@ -219,6 +232,10 @@ func (r *PulsarConnectionReconciler) MakePulsarAdminConfig(ctx context.Context)
219232
cfg.Key = *value
220233
}
221234
}
235+
if tls := authn.TLS; tls != nil {
236+
cfg.ClientCertificatePath = tls.ClientCertificatePath
237+
cfg.ClientCertificateKeyPath = tls.ClientCertificateKeyPath
238+
}
222239
}
223240
return &cfg, nil
224241
}

0 commit comments

Comments
 (0)