Skip to content

Commit b128ce3

Browse files
committed
Certificate support for image registry
Remove the InsecureSkipTLSVerify annotations. * Create a ClusterIssuer CA (via openssl) that is used by OLMv1 e2e * Update the operator controller to specify a cert directory, rather than a single file. * Use this directory for catalogd and image-registries * Update the deployment to reference CAs appropriately Signed-off-by: Todd Short <[email protected]>
1 parent 58b4363 commit b128ce3

File tree

13 files changed

+149
-56
lines changed

13 files changed

+149
-56
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ test-e2e: GO_BUILD_FLAGS := -cover
155155
test-e2e: run image-registry build-push-e2e-catalog registry-load-bundles e2e e2e-coverage kind-clean #HELP Run e2e test suite on local kind cluster
156156

157157
.PHONY: extension-developer-e2e
158+
extension-developer-e2e: KUSTOMIZE_BUILD_DIR := config/overlays/certs
158159
extension-developer-e2e: KIND_CLUSTER_NAME := operator-controller-ext-dev-e2e #EXHELP Run extension-developer e2e on local kind cluster
159160
extension-developer-e2e: run image-registry test-ext-dev-e2e kind-clean
160161

cmd/manager/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ func main() {
7979
cachePath string
8080
operatorControllerVersion bool
8181
systemNamespace string
82-
caCert string
82+
caCertDir string
8383
)
8484
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
8585
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
86-
flag.StringVar(&caCert, "ca-cert", "", "The TLS certificate to use for verifying HTTPS connections to the Catalogd web server.")
86+
flag.StringVar(&caCertDir, "ca-cert", "", "The directory of TLS certificate to use for verifying HTTPS connections to the Catalogd and docker-registry web servers.")
8787
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
8888
"Enable leader election for controller manager. "+
8989
"Enabling this will ensure there is only one active controller manager.")
@@ -151,7 +151,7 @@ func main() {
151151
os.Exit(1)
152152
}
153153

154-
httpClient, err := httputil.BuildHTTPClient(caCert)
154+
httpClient, err := httputil.BuildHTTPClient(caCertDir)
155155
if err != nil {
156156
setupLog.Error(err, "unable to create catalogd http client")
157157
}
@@ -217,6 +217,7 @@ func main() {
217217
InstalledBundleGetter: &controllers.DefaultInstalledBundleGetter{ActionClientGetter: acg},
218218
Handler: registryv1handler.HandlerFunc(registry.HandleBundleDeployment),
219219
Finalizers: clusterExtensionFinalizers,
220+
CaCertDir: caCertDir,
220221
}).SetupWithManager(mgr); err != nil {
221222
setupLog.Error(err, "unable to create controller", "controller", "ClusterExtension")
222223
os.Exit(1)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace: olmv1-system
2+
3+
resources:
4+
- ../../overlays/tls
5+
- manager_cert.yaml
6+
7+
patches:
8+
- path: manager_cert_patch.yaml
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Certificate
3+
metadata:
4+
name: olmv1-cert
5+
spec:
6+
secretName: olmv1-cert
7+
dnsNames:
8+
- operator-controller.olmv1-system.svc
9+
- operator-controller.olmv1-system.svc.cluster.local
10+
privateKey:
11+
algorithm: ECDSA
12+
size: 256
13+
issuerRef:
14+
name: olmv1-ca
15+
kind: ClusterIssuer
16+
group: cert-manager.io
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: controller-manager
5+
namespace: system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: kube-rbac-proxy
11+
- name: manager
12+
volumeMounts:
13+
- name: e2e-cert
14+
mountPath: /var/certs/olm-ca.crt
15+
subPath: olm-ca.crt
16+
readOnly: true
17+
volumes:
18+
- name: e2e-cert
19+
secret:
20+
secretName: olmv1-cert
21+
items:
22+
- key: ca.crt
23+
path: olm-ca.crt

config/overlays/e2e/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace: olmv1-system
22

33
resources:
4-
- ../../overlays/tls
4+
- ../../overlays/certs
55
- manager_e2e_coverage_pvc.yaml
66
- manager_e2e_coverage_copy_pod.yaml
77

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
- op: add
22
path: /spec/template/spec/volumes/-
3-
value: {"name":"ca-certificate", "secret":{"secretName":"catalogd-catalogserver-cert", "optional": false, "items": [{"key": "tls.crt", "path": "tls.crt"}]}}
3+
value: {"name":"catalogd-certificate", "secret":{"secretName":"catalogd-catalogserver-cert", "optional": false, "items": [{"key": "ca.crt", "path": "catalogd.crt"}]}}
44
- op: add
55
path: /spec/template/spec/containers/0/volumeMounts/-
6-
value: {"name":"ca-certificate", "readOnly": true, "mountPath":"/var/certs"}
6+
value: {"name":"catalogd-certificate", "readOnly": true, "mountPath":"/var/certs/catalogd.crt", "subPath":"catalogd.crt"}
77
- op: add
88
path: /spec/template/spec/containers/0/args/-
9-
value: "--ca-cert=/var/certs/tls.crt"
9+
value: "--ca-cert=/var/certs"

internal/controllers/clusterextension_controller.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import (
7373
catalogfilter "github.com/operator-framework/operator-controller/internal/catalogmetadata/filter"
7474
catalogsort "github.com/operator-framework/operator-controller/internal/catalogmetadata/sort"
7575
"github.com/operator-framework/operator-controller/internal/conditionsets"
76+
"github.com/operator-framework/operator-controller/internal/httputil"
7677
"github.com/operator-framework/operator-controller/internal/labels"
7778
)
7879

@@ -90,16 +91,13 @@ type ClusterExtensionReconciler struct {
9091
cache cache.Cache
9192
InstalledBundleGetter InstalledBundleGetter
9293
Finalizers crfinalizer.Finalizers
94+
CaCertDir string
9395
}
9496

9597
type InstalledBundleGetter interface {
9698
GetInstalledBundle(ctx context.Context, ext *ocv1alpha1.ClusterExtension) (*ocv1alpha1.BundleMetadata, error)
9799
}
98100

99-
const (
100-
bundleConnectionAnnotation string = "bundle.connection.config/insecureSkipTLSVerify"
101-
)
102-
103101
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensions,verbs=get;list;watch
104102
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensions/status,verbs=update;patch
105103
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensions/finalizers,verbs=update
@@ -249,7 +247,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
249247
// Generate a BundleDeployment from the ClusterExtension to Unpack.
250248
// Note: The BundleDeployment here is not a k8s API, its a simple Go struct which
251249
// necessary embedded values.
252-
bd := r.generateBundleDeploymentForUnpack(bundle.Image, ext)
250+
bd := r.generateBundleDeploymentForUnpack(ctx, bundle.Image, ext)
253251
unpackResult, err := r.Unpacker.Unpack(ctx, bd)
254252
if err != nil {
255253
setStatusUnpackFailed(ext, err.Error())
@@ -533,7 +531,11 @@ func SetDeprecationStatus(ext *ocv1alpha1.ClusterExtension, bundle *catalogmetad
533531
}
534532
}
535533

536-
func (r *ClusterExtensionReconciler) generateBundleDeploymentForUnpack(bundlePath string, ce *ocv1alpha1.ClusterExtension) *rukpakv1alpha2.BundleDeployment {
534+
func (r *ClusterExtensionReconciler) generateBundleDeploymentForUnpack(ctx context.Context, bundlePath string, ce *ocv1alpha1.ClusterExtension) *rukpakv1alpha2.BundleDeployment {
535+
certData, err := httputil.LoadCerts(r.CaCertDir)
536+
if err != nil {
537+
log.FromContext(ctx).WithName("operator-controller").WithValues("cluster-extension", ce.GetName()).Error(err, "unable to get TLS certificate")
538+
}
537539
return &rukpakv1alpha2.BundleDeployment{
538540
TypeMeta: metav1.TypeMeta{
539541
Kind: ce.Kind,
@@ -549,24 +551,14 @@ func (r *ClusterExtensionReconciler) generateBundleDeploymentForUnpack(bundlePat
549551
Type: rukpakv1alpha2.SourceTypeImage,
550552
Image: &rukpakv1alpha2.ImageSource{
551553
Ref: bundlePath,
552-
InsecureSkipTLSVerify: isInsecureSkipTLSVerifySet(ce),
554+
InsecureSkipTLSVerify: false,
555+
CertificateData: certData,
553556
},
554557
},
555558
},
556559
}
557560
}
558561

559-
func isInsecureSkipTLSVerifySet(ce *ocv1alpha1.ClusterExtension) bool {
560-
if ce == nil {
561-
return false
562-
}
563-
value, ok := ce.Annotations[bundleConnectionAnnotation]
564-
if !ok {
565-
return false
566-
}
567-
return value == "true"
568-
}
569-
570562
// SetupWithManager sets up the controller with the Manager.
571563
func (r *ClusterExtensionReconciler) SetupWithManager(mgr ctrl.Manager) error {
572564
controller, err := ctrl.NewControllerManagedBy(mgr).

internal/httputil/httputil.go

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,60 @@ import (
55
"crypto/x509"
66
"net/http"
77
"os"
8+
"path/filepath"
9+
"strings"
810
"time"
911
)
1012

11-
func BuildHTTPClient(caCert string) (*http.Client, error) {
12-
httpClient := &http.Client{Timeout: 10 * time.Second}
13-
14-
if caCert != "" {
15-
// tlsFileWatcher, err := certwatcher.New(caCert, "")
13+
func LoadCerts(caDir string) (string, error) {
14+
if caDir == "" {
15+
return "", nil
16+
}
1617

17-
cert, err := os.ReadFile(caCert)
18+
var certs []string
19+
err := filepath.Walk(caDir, func(path string, info os.FileInfo, err error) error {
1820
if err != nil {
19-
return nil, err
21+
return err
2022
}
21-
caCertPool := x509.NewCertPool()
22-
caCertPool.AppendCertsFromPEM(cert)
23-
tlsConfig := &tls.Config{
24-
RootCAs: caCertPool,
25-
MinVersion: tls.VersionTLS12,
23+
if info.IsDir() {
24+
return nil
2625
}
27-
tlsTransport := &http.Transport{
28-
TLSClientConfig: tlsConfig,
26+
data, err := os.ReadFile(path)
27+
if err != nil {
28+
return err
2929
}
30-
httpClient.Transport = tlsTransport
30+
certs = append(certs, string(data))
31+
return nil
32+
})
33+
if err != nil {
34+
return "", err
35+
}
36+
return strings.Join(certs, "\n"), nil
37+
}
38+
39+
func BuildHTTPClient(caDir string) (*http.Client, error) {
40+
httpClient := &http.Client{Timeout: 10 * time.Second}
41+
42+
// use the SystemCertPool as a default
43+
caCertPool, err := x509.SystemCertPool()
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
certs, err := LoadCerts(caDir)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
caCertPool.AppendCertsFromPEM([]byte(certs))
54+
tlsConfig := &tls.Config{
55+
RootCAs: caCertPool,
56+
MinVersion: tls.VersionTLS12,
57+
}
58+
tlsTransport := &http.Transport{
59+
TLSClientConfig: tlsConfig,
3160
}
61+
httpClient.Transport = tlsTransport
3262

3363
return httpClient, nil
3464
}

scripts/install.tpl.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,42 @@ function kubectl_wait() {
3535
kubectl apply -f "https://github.com/cert-manager/cert-manager/releases/download/${cert_mgr_version}/cert-manager.yaml"
3636
kubectl_wait "cert-manager" "deployment/cert-manager-webhook" "60s"
3737

38+
# Create the self-signed certificate for the ClusterIssuer and the ClusterIssuer
39+
kubectl apply -f - <<EOF
40+
apiVersion: cert-manager.io/v1
41+
kind: Issuer
42+
metadata:
43+
name: self-sign-issuer
44+
namespace: cert-manager
45+
spec:
46+
selfSigned: {}
47+
---
48+
apiVersion: cert-manager.io/v1
49+
kind: Certificate
50+
metadata:
51+
name: olmv1-ca
52+
namespace: cert-manager
53+
spec:
54+
isCA: true
55+
commonName: olmv1-ca
56+
secretName: olmv1-ca
57+
privateKey:
58+
algorithm: ECDSA
59+
size: 256
60+
issuerRef:
61+
name: self-sign-issuer
62+
kind: Issuer
63+
group: cert-manager.io
64+
---
65+
apiVersion: cert-manager.io/v1
66+
kind: ClusterIssuer
67+
metadata:
68+
name: olmv1-ca
69+
spec:
70+
ca:
71+
secretName: olmv1-ca
72+
EOF
73+
3874
kubectl apply -f "https://github.com/operator-framework/catalogd/releases/download/${catalogd_version}/catalogd.yaml"
3975
kubectl_wait "olmv1-system" "deployment/catalogd-controller-manager" "60s"
4076

0 commit comments

Comments
 (0)