mirror of
https://github.com/ngrok/ngrok-operator.git
synced 2026-05-17 16:50:44 +00:00
bake ca into image (#626)
* bake ca into image * Update README.md and values.schema.json with readme-generator-for-helm * certs/ -> certs/* * update configmap for forwarder pods * change when we add cert and remove volumes * update snapshot * update tunnel driver with cert utl function * make path const and re-add volume mount block * const -> var * re-add extra volume mounts correctly ty mason Co-authored-by: Mason Johnson <mason@ngrok.com> * remove test --------- Co-authored-by: Megalonia <Megalonia@users.noreply.github.com> Co-authored-by: Mason Johnson <mason@ngrok.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
!internal/
|
||||
!pkg/
|
||||
!scripts/
|
||||
!certs/*
|
||||
!**/*.go
|
||||
!**/*.mod
|
||||
!**/*.sum
|
||||
|
||||
+2
-1
@@ -18,12 +18,13 @@ ARG TARGETOS TARGETARCH
|
||||
# Build
|
||||
RUN --mount=type=cache,target=/go \
|
||||
CGO_ENABLED=0 GOOS="${TARGETOS}" GOARCH="${TARGETARCH}" make _build
|
||||
|
||||
# Use distroless as minimal base image to package the manager binary
|
||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||
FROM gcr.io/distroless/static:nonroot
|
||||
COPY certs /etc/ssl/certs/ngrok
|
||||
WORKDIR /
|
||||
COPY --from=builder /workspace/bin/api-manager /workspace/bin/agent-manager /workspace/bin/bindings-forwarder-manager ./
|
||||
USER 65532:65532
|
||||
|
||||
|
||||
ENTRYPOINT ["/api-manager"]
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDwjCCAqqgAwIBAgIUZqF2AkB17pISojTndgc2U5BDt7wwDQYJKoZIhvcNAQEL
|
||||
BQAwbzEQMA4GA1UEAwwHUm9vdCBDQTENMAsGA1UECwwEcHJvZDESMBAGA1UECgwJ
|
||||
bmdyb2sgSW5jMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxp
|
||||
Zm9ybmlhMQswCQYDVQQGEwJVUzAeFw0yMjA4MzExNDU5NDhaFw0zMjA4MjgxNDU5
|
||||
NDhaMF8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQK
|
||||
DAluZ3JvayBJbmMxDTALBgNVBAsMBHByb2QxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+t8q9Ost9BxCWX
|
||||
fyGG0mVQOpIiyrzzZWyqT6CZpMY2fpOadLuZeBP7ti2Iw4FgCpfLntL0RldvMMNY
|
||||
4qq61dVrCwhL/v2ldsaHUdzjtFj1i+ZNGUtV4E9korHxm2YdsD91w6WIjF/J0lvo
|
||||
X2koLwFlGc/CkhT8z2VWebY8a6mYNyz5S7yPTQh2/mQ14lx/QPJgZSFEE/EEkMDC
|
||||
bs4BoMuqKMhCpqEP8m4+CxPQ5/V6POSqUIxT4A7eWWj2MRpnmirmVbXOc24Aznqk
|
||||
bdQUP4qagiR/i7qPsRx+f4mFfDninPsXp/djjByo0xzdh+i1HFyOR/7nyNDKlJ+e
|
||||
rymRgnUCAwEAAaNmMGQwHQYDVR0OBBYEFJ47nRzHaOT+vY44N3TCMYtGlBjIMB8G
|
||||
A1UdIwQYMBaAFNxeUxPIM8G7cX0DhFc81pLD4W+HMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBRmnMoOtQbYL7P
|
||||
Co1B5Chslb86HP2WI1jGRXhbfwAF2ySDFnX2ZbRPVtoQ+IuqXWxyXAeicYjXR6kz
|
||||
xX8hLWfD14kWUIz6ZgT3uZrDSIzmQ+tz8ztbT6mTI1ECWdjLV/i58f6vKzgLD8Vp
|
||||
3VdVns8NA9ee6a65QNjZEnwBVeccysoWkOwM/KzuazhSGcGu44y/S4ny9pAg7Pol
|
||||
2kV4NicDKD6tSAdXmPmjFalYUfnMmyhurZIPrS2dgYgpOrGVMwronTOZ3BUf4DL4
|
||||
zkkmcLXss1KztQnLd23nuNiIscwMcGM58a3O5zUp7aorfrm7cdRgkFmcYVNO/6uG
|
||||
Q5iJ+Ppk
|
||||
-----END CERTIFICATE-----
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
bindingsv1alpha1 "github.com/ngrok/ngrok-operator/api/bindings/v1alpha1"
|
||||
ngrokv1alpha1 "github.com/ngrok/ngrok-operator/api/ngrok/v1alpha1"
|
||||
bindingscontroller "github.com/ngrok/ngrok-operator/internal/controller/bindings"
|
||||
"github.com/ngrok/ngrok-operator/internal/util"
|
||||
"github.com/ngrok/ngrok-operator/internal/version"
|
||||
"github.com/ngrok/ngrok-operator/pkg/bindingsdriver"
|
||||
// +kubebuilder:scaffold:imports
|
||||
@@ -137,6 +138,11 @@ func runController(_ context.Context, opts managerOpts) error {
|
||||
|
||||
bd := bindingsdriver.New()
|
||||
|
||||
certPool, err := util.LoadCerts()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = (&bindingscontroller.ForwarderReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Log: ctrl.Log.WithName("controllers").WithName("bindings-forwarder"),
|
||||
@@ -144,6 +150,7 @@ func runController(_ context.Context, opts managerOpts) error {
|
||||
Recorder: mgr.GetEventRecorderFor("bindings-forwarder-controller"),
|
||||
BindingsDriver: bd,
|
||||
KubernetesOperatorName: opts.releaseName,
|
||||
RootCAs: certPool,
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "BindingsForwarder")
|
||||
os.Exit(1)
|
||||
|
||||
@@ -153,43 +153,19 @@ To uninstall the chart:
|
||||
|
||||
### Kubernetes Bindings feature configuration
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `bindings.enabled` | Whether to enable the Endpoint Bindings feature | `false` |
|
||||
| `bindings.endpointSelectors` | List of cel expressions used to filter which kubernetes-bound endpoints should be projected into this cluster | `["true"]` |
|
||||
| `bindings.serviceAnnotations` | Annotations to add to projected services bound to an endpoint | `{}` |
|
||||
| `bindings.serviceLabels` | Labels to add to projected services bound to an endpoint | `{}` |
|
||||
| `bindings.ingressEndpoint` | The hostname of the ingress endpoint for the bindings | `kubernetes-binding-ingress.ngrok.io:443` |
|
||||
| `bindings.forwarder.replicaCount` | The number of bindings forwarders to run. | `1` |
|
||||
| `bindings.forwarder.resources.limits` | The resources limits for the container | `{}` |
|
||||
| `bindings.forwarder.resources.requests` | The requested resources for the container | `{}` |
|
||||
| `bindings.forwarder.serviceAccount.create` | Specifies whether a ServiceAccount should be created for the bindings forwarder pod(s). | `true` |
|
||||
| `bindings.forwarder.serviceAccount.name` | The name of the ServiceAccount to use for the bindings forwarder pod(s). | `""` |
|
||||
| `bindings.forwarder.serviceAccount.annotations` | Additional annotations to add to the bindings-forwarder ServiceAccount | `{}` |
|
||||
| `bindings.forwarder.tolerations` | Tolerations for the bindings forwarder pod(s) | `[]` |
|
||||
| `bindings.forwarder.nodeSelector` | Node labels for the bindings forwarder pod(s) | `{}` |
|
||||
| `bindings.forwarder.topologySpreadConstraints` | Topology Spread Constraints for the bindings forwarder pod(s) | `[]` |
|
||||
| `bindings.ngrokCA` | The ngrok intermediate CA certificate to use for verifyng self-signed TLS certs from ngrok | `-----BEGIN CERTIFICATE-----
|
||||
MIIDwjCCAqqgAwIBAgIUZqF2AkB17pISojTndgc2U5BDt7wwDQYJKoZIhvcNAQEL
|
||||
BQAwbzEQMA4GA1UEAwwHUm9vdCBDQTENMAsGA1UECwwEcHJvZDESMBAGA1UECgwJ
|
||||
bmdyb2sgSW5jMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxp
|
||||
Zm9ybmlhMQswCQYDVQQGEwJVUzAeFw0yMjA4MzExNDU5NDhaFw0zMjA4MjgxNDU5
|
||||
NDhaMF8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQK
|
||||
DAluZ3JvayBJbmMxDTALBgNVBAsMBHByb2QxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+t8q9Ost9BxCWX
|
||||
fyGG0mVQOpIiyrzzZWyqT6CZpMY2fpOadLuZeBP7ti2Iw4FgCpfLntL0RldvMMNY
|
||||
4qq61dVrCwhL/v2ldsaHUdzjtFj1i+ZNGUtV4E9korHxm2YdsD91w6WIjF/J0lvo
|
||||
X2koLwFlGc/CkhT8z2VWebY8a6mYNyz5S7yPTQh2/mQ14lx/QPJgZSFEE/EEkMDC
|
||||
bs4BoMuqKMhCpqEP8m4+CxPQ5/V6POSqUIxT4A7eWWj2MRpnmirmVbXOc24Aznqk
|
||||
bdQUP4qagiR/i7qPsRx+f4mFfDninPsXp/djjByo0xzdh+i1HFyOR/7nyNDKlJ+e
|
||||
rymRgnUCAwEAAaNmMGQwHQYDVR0OBBYEFJ47nRzHaOT+vY44N3TCMYtGlBjIMB8G
|
||||
A1UdIwQYMBaAFNxeUxPIM8G7cX0DhFc81pLD4W+HMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBRmnMoOtQbYL7P
|
||||
Co1B5Chslb86HP2WI1jGRXhbfwAF2ySDFnX2ZbRPVtoQ+IuqXWxyXAeicYjXR6kz
|
||||
xX8hLWfD14kWUIz6ZgT3uZrDSIzmQ+tz8ztbT6mTI1ECWdjLV/i58f6vKzgLD8Vp
|
||||
3VdVns8NA9ee6a65QNjZEnwBVeccysoWkOwM/KzuazhSGcGu44y/S4ny9pAg7Pol
|
||||
2kV4NicDKD6tSAdXmPmjFalYUfnMmyhurZIPrS2dgYgpOrGVMwronTOZ3BUf4DL4
|
||||
zkkmcLXss1KztQnLd23nuNiIscwMcGM58a3O5zUp7aorfrm7cdRgkFmcYVNO/6uG
|
||||
Q5iJ+Ppk
|
||||
-----END CERTIFICATE-----
|
||||
` |
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
|
||||
| `bindings.enabled` | Whether to enable the Endpoint Bindings feature | `false` |
|
||||
| `bindings.endpointSelectors` | List of cel expressions used to filter which kubernetes-bound endpoints should be projected into this cluster | `["true"]` |
|
||||
| `bindings.serviceAnnotations` | Annotations to add to projected services bound to an endpoint | `{}` |
|
||||
| `bindings.serviceLabels` | Labels to add to projected services bound to an endpoint | `{}` |
|
||||
| `bindings.ingressEndpoint` | The hostname of the ingress endpoint for the bindings | `kubernetes-binding-ingress.ngrok.io:443` |
|
||||
| `bindings.forwarder.replicaCount` | The number of bindings forwarders to run. | `1` |
|
||||
| `bindings.forwarder.resources.limits` | The resources limits for the container | `{}` |
|
||||
| `bindings.forwarder.resources.requests` | The requested resources for the container | `{}` |
|
||||
| `bindings.forwarder.serviceAccount.create` | Specifies whether a ServiceAccount should be created for the bindings forwarder pod(s). | `true` |
|
||||
| `bindings.forwarder.serviceAccount.name` | The name of the ServiceAccount to use for the bindings forwarder pod(s). | `""` |
|
||||
| `bindings.forwarder.serviceAccount.annotations` | Additional annotations to add to the bindings-forwarder ServiceAccount | `{}` |
|
||||
| `bindings.forwarder.tolerations` | Tolerations for the bindings forwarder pod(s) | `[]` |
|
||||
| `bindings.forwarder.nodeSelector` | Node labels for the bindings forwarder pod(s) | `{}` |
|
||||
| `bindings.forwarder.topologySpreadConstraints` | Topology Spread Constraints for the bindings forwarder pod(s) | `[]` |
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{{- if .Values.bindings.enabled }}
|
||||
---
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "ngrok-operator.labels" . | nindent 4 }}
|
||||
name: ngrok-intermediate-ca
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
root.crt: |
|
||||
{{- .Values.bindings.ngrokCA | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -95,23 +95,13 @@ spec:
|
||||
fieldPath: metadata.namespace
|
||||
- name: HELM_RELEASE_NAME
|
||||
value: {{ .Release.Name | quote }}
|
||||
- name: SSL_CERT_DIR
|
||||
value: /etc/ssl/certs/ngrok
|
||||
{{- range $key, $value := .Values.extraEnv }}
|
||||
- name: {{ $key }}
|
||||
value: {{- toYaml $value | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraVolumeMounts }}
|
||||
{{- if .Values.extraVolumeMounts }}
|
||||
volumeMounts:
|
||||
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
|
||||
- name: ngrok-ca
|
||||
mountPath: /etc/ssl/certs/ngrok
|
||||
readOnly: true
|
||||
{{- else }}
|
||||
volumeMounts:
|
||||
- name: ngrok-ca
|
||||
mountPath: /etc/ssl/certs/ngrok
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if .Values.lifecycle }}
|
||||
lifecycle:
|
||||
@@ -134,13 +124,5 @@ spec:
|
||||
{{- if .Values.extraVolumes }}
|
||||
volumes:
|
||||
{{- toYaml .Values.extraVolumes | nindent 8 }}
|
||||
- name: ngrok-ca
|
||||
configMap:
|
||||
name: ngrok-intermediate-ca
|
||||
{{- else }}
|
||||
volumes:
|
||||
- name: ngrok-ca
|
||||
configMap:
|
||||
name: ngrok-intermediate-ca
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
-10
@@ -71,8 +71,6 @@ Should match snapshot:
|
||||
fieldPath: metadata.namespace
|
||||
- name: HELM_RELEASE_NAME
|
||||
value: RELEASE-NAME
|
||||
- name: SSL_CERT_DIR
|
||||
value: /etc/ssl/certs/ngrok
|
||||
image: docker.io/ngrok/ngrok-operator:0.16.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
@@ -93,12 +91,4 @@ Should match snapshot:
|
||||
requests: {}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
volumeMounts:
|
||||
- mountPath: /etc/ssl/certs/ngrok
|
||||
name: ngrok-ca
|
||||
readOnly: true
|
||||
serviceAccountName: RELEASE-NAME-ngrok-operator-bindings-forwarder
|
||||
volumes:
|
||||
- configMap:
|
||||
name: ngrok-intermediate-ca
|
||||
name: ngrok-ca
|
||||
|
||||
Generated
-5
@@ -504,11 +504,6 @@
|
||||
"items": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ngrokCA": {
|
||||
"type": "string",
|
||||
"description": "The ngrok intermediate CA certificate to use for verifyng self-signed TLS certs from ngrok",
|
||||
"default": "-----BEGIN CERTIFICATE-----\nMIIDwjCCAqqgAwIBAgIUZqF2AkB17pISojTndgc2U5BDt7wwDQYJKoZIhvcNAQEL\nBQAwbzEQMA4GA1UEAwwHUm9vdCBDQTENMAsGA1UECwwEcHJvZDESMBAGA1UECgwJ\nbmdyb2sgSW5jMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxp\nZm9ybmlhMQswCQYDVQQGEwJVUzAeFw0yMjA4MzExNDU5NDhaFw0zMjA4MjgxNDU5\nNDhaMF8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQK\nDAluZ3JvayBJbmMxDTALBgNVBAsMBHByb2QxGDAWBgNVBAMMD0ludGVybWVkaWF0\nZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+t8q9Ost9BxCWX\nfyGG0mVQOpIiyrzzZWyqT6CZpMY2fpOadLuZeBP7ti2Iw4FgCpfLntL0RldvMMNY\n4qq61dVrCwhL/v2ldsaHUdzjtFj1i+ZNGUtV4E9korHxm2YdsD91w6WIjF/J0lvo\nX2koLwFlGc/CkhT8z2VWebY8a6mYNyz5S7yPTQh2/mQ14lx/QPJgZSFEE/EEkMDC\nbs4BoMuqKMhCpqEP8m4+CxPQ5/V6POSqUIxT4A7eWWj2MRpnmirmVbXOc24Aznqk\nbdQUP4qagiR/i7qPsRx+f4mFfDninPsXp/djjByo0xzdh+i1HFyOR/7nyNDKlJ+e\nrymRgnUCAwEAAaNmMGQwHQYDVR0OBBYEFJ47nRzHaOT+vY44N3TCMYtGlBjIMB8G\nA1UdIwQYMBaAFNxeUxPIM8G7cX0DhFc81pLD4W+HMBIGA1UdEwEB/wQIMAYBAf8C\nAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBRmnMoOtQbYL7P\nCo1B5Chslb86HP2WI1jGRXhbfwAF2ySDFnX2ZbRPVtoQ+IuqXWxyXAeicYjXR6kz\nxX8hLWfD14kWUIz6ZgT3uZrDSIzmQ+tz8ztbT6mTI1ECWdjLV/i58f6vKzgLD8Vp\n3VdVns8NA9ee6a65QNjZEnwBVeccysoWkOwM/KzuazhSGcGu44y/S4ny9pAg7Pol\n2kV4NicDKD6tSAdXmPmjFalYUfnMmyhurZIPrS2dgYgpOrGVMwronTOZ3BUf4DL4\nzkkmcLXss1KztQnLd23nuNiIscwMcGM58a3O5zUp7aorfrm7cdRgkFmcYVNO/6uG\nQ5iJ+Ppk\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,30 +371,3 @@ bindings:
|
||||
|
||||
## @param bindings.forwarder.topologySpreadConstraints Topology Spread Constraints for the bindings forwarder pod(s)
|
||||
topologySpreadConstraints: []
|
||||
|
||||
## @param bindings.ngrokCA The ngrok intermediate CA certificate to use for verifyng self-signed TLS certs from ngrok
|
||||
## Note: This is temporarily vendored and will be removed in a future release.
|
||||
ngrokCA: | # ngrok intermediate CA
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDwjCCAqqgAwIBAgIUZqF2AkB17pISojTndgc2U5BDt7wwDQYJKoZIhvcNAQEL
|
||||
BQAwbzEQMA4GA1UEAwwHUm9vdCBDQTENMAsGA1UECwwEcHJvZDESMBAGA1UECgwJ
|
||||
bmdyb2sgSW5jMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxp
|
||||
Zm9ybmlhMQswCQYDVQQGEwJVUzAeFw0yMjA4MzExNDU5NDhaFw0zMjA4MjgxNDU5
|
||||
NDhaMF8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQK
|
||||
DAluZ3JvayBJbmMxDTALBgNVBAsMBHByb2QxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+t8q9Ost9BxCWX
|
||||
fyGG0mVQOpIiyrzzZWyqT6CZpMY2fpOadLuZeBP7ti2Iw4FgCpfLntL0RldvMMNY
|
||||
4qq61dVrCwhL/v2ldsaHUdzjtFj1i+ZNGUtV4E9korHxm2YdsD91w6WIjF/J0lvo
|
||||
X2koLwFlGc/CkhT8z2VWebY8a6mYNyz5S7yPTQh2/mQ14lx/QPJgZSFEE/EEkMDC
|
||||
bs4BoMuqKMhCpqEP8m4+CxPQ5/V6POSqUIxT4A7eWWj2MRpnmirmVbXOc24Aznqk
|
||||
bdQUP4qagiR/i7qPsRx+f4mFfDninPsXp/djjByo0xzdh+i1HFyOR/7nyNDKlJ+e
|
||||
rymRgnUCAwEAAaNmMGQwHQYDVR0OBBYEFJ47nRzHaOT+vY44N3TCMYtGlBjIMB8G
|
||||
A1UdIwQYMBaAFNxeUxPIM8G7cX0DhFc81pLD4W+HMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBRmnMoOtQbYL7P
|
||||
Co1B5Chslb86HP2WI1jGRXhbfwAF2ySDFnX2ZbRPVtoQ+IuqXWxyXAeicYjXR6kz
|
||||
xX8hLWfD14kWUIz6ZgT3uZrDSIzmQ+tz8ztbT6mTI1ECWdjLV/i58f6vKzgLD8Vp
|
||||
3VdVns8NA9ee6a65QNjZEnwBVeccysoWkOwM/KzuazhSGcGu44y/S4ny9pAg7Pol
|
||||
2kV4NicDKD6tSAdXmPmjFalYUfnMmyhurZIPrS2dgYgpOrGVMwronTOZ3BUf4DL4
|
||||
zkkmcLXss1KztQnLd23nuNiIscwMcGM58a3O5zUp7aorfrm7cdRgkFmcYVNO/6uG
|
||||
Q5iJ+Ppk
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -27,6 +27,7 @@ package bindings
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -65,6 +66,7 @@ type ForwarderReconciler struct {
|
||||
|
||||
BindingsDriver *bindingsdriver.BindingsDriver
|
||||
KubernetesOperatorName string
|
||||
RootCAs *x509.CertPool
|
||||
}
|
||||
|
||||
func (r *ForwarderReconciler) SetupWithManager(mgr ctrl.Manager) (err error) {
|
||||
@@ -170,6 +172,10 @@ func (r *ForwarderReconciler) update(ctx context.Context, epb *bindingsv1alpha1.
|
||||
},
|
||||
}
|
||||
|
||||
if r.RootCAs != nil {
|
||||
tlsDialer.Config.RootCAs = r.RootCAs
|
||||
}
|
||||
|
||||
endpointURI, err := url.Parse(epb.Spec.EndpointURI)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO: Make this configurable via helm and document it so users can
|
||||
// use it for things like proxies
|
||||
customCertsPath = "/etc/ssl/certs/ngrok/"
|
||||
ngrokCertPool *x509.CertPool
|
||||
loadCertsOnce sync.Once
|
||||
loadCertsOnceErr error
|
||||
)
|
||||
|
||||
func LoadCerts() (*x509.CertPool, error) {
|
||||
// Load all certificates from the well known ngrok certs directory,
|
||||
// combine them with the default certs, and save the cert pool once.
|
||||
// If we've already done this, just return the cert pool.
|
||||
loadCertsOnce.Do(func() {
|
||||
var err error
|
||||
// Load the system cert pool
|
||||
ngrokCertPool, err = x509.SystemCertPool()
|
||||
if err != nil {
|
||||
loadCertsOnceErr = err
|
||||
return
|
||||
}
|
||||
|
||||
// Now, walk the ngrok certs dir and add all the certs to the cert pool
|
||||
loadCertsOnceErr = filepath.WalkDir(customCertsPath, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open the file
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok := ngrokCertPool.AppendCertsFromPEM(content); !ok {
|
||||
return fmt.Errorf("failed to append certs from %s", path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// if WalkDir or cert appending fails, clear the pool
|
||||
if loadCertsOnceErr != nil {
|
||||
ngrokCertPool = nil
|
||||
}
|
||||
})
|
||||
|
||||
return ngrokCertPool, loadCertsOnceErr
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func resetCertsState() {
|
||||
ngrokCertPool = nil
|
||||
loadCertsOnce = sync.Once{}
|
||||
loadCertsOnceErr = nil
|
||||
}
|
||||
|
||||
func TestLoadCerts_ValidPEM(t *testing.T) {
|
||||
resetCertsState()
|
||||
tmpDir := t.TempDir()
|
||||
customCertsPath = tmpDir
|
||||
|
||||
err := os.WriteFile(filepath.Join(tmpDir, "valid.pem"), []byte(validPEM), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
pool, err := LoadCerts()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, pool)
|
||||
}
|
||||
|
||||
func TestLoadCerts_InvalidPEM(t *testing.T) {
|
||||
resetCertsState()
|
||||
tmpDir := t.TempDir()
|
||||
customCertsPath = tmpDir
|
||||
|
||||
err := os.WriteFile(filepath.Join(tmpDir, "invalid.pem"), []byte("not a cert"), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
pool, err := LoadCerts()
|
||||
|
||||
require.Error(t, err, "expected error, got nil")
|
||||
t.Logf("err: %v", err)
|
||||
|
||||
require.Nil(t, pool, "expected nil pool when certs path is missing")
|
||||
require.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestLoadCerts_MissingPath(t *testing.T) {
|
||||
resetCertsState()
|
||||
tmpDir := filepath.Join(t.TempDir(), "nonexistent")
|
||||
customCertsPath = tmpDir
|
||||
|
||||
pool, err := LoadCerts()
|
||||
|
||||
require.Error(t, err, "expected error, got nil")
|
||||
t.Logf("err: %v", err)
|
||||
|
||||
// pool will be nil because cert loading failed completely
|
||||
require.Nil(t, pool, "expected nil pool when certs path is missing")
|
||||
}
|
||||
|
||||
const validPEM = `-----BEGIN CERTIFICATE-----
|
||||
MIIDwjCCAqqgAwIBAgIUZqF2AkB17pISojTndgc2U5BDt7wwDQYJKoZIhvcNAQEL
|
||||
BQAwbzEQMA4GA1UEAwwHUm9vdCBDQTENMAsGA1UECwwEcHJvZDESMBAGA1UECgwJ
|
||||
bmdyb2sgSW5jMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxp
|
||||
Zm9ybmlhMQswCQYDVQQGEwJVUzAeFw0yMjA4MzExNDU5NDhaFw0zMjA4MjgxNDU5
|
||||
NDhaMF8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQK
|
||||
DAluZ3JvayBJbmMxDTALBgNVBAsMBHByb2QxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+t8q9Ost9BxCWX
|
||||
fyGG0mVQOpIiyrzzZWyqT6CZpMY2fpOadLuZeBP7ti2Iw4FgCpfLntL0RldvMMNY
|
||||
4qq61dVrCwhL/v2ldsaHUdzjtFj1i+ZNGUtV4E9korHxm2YdsD91w6WIjF/J0lvo
|
||||
X2koLwFlGc/CkhT8z2VWebY8a6mYNyz5S7yPTQh2/mQ14lx/QPJgZSFEE/EEkMDC
|
||||
bs4BoMuqKMhCpqEP8m4+CxPQ5/V6POSqUIxT4A7eWWj2MRpnmirmVbXOc24Aznqk
|
||||
bdQUP4qagiR/i7qPsRx+f4mFfDninPsXp/djjByo0xzdh+i1HFyOR/7nyNDKlJ+e
|
||||
rymRgnUCAwEAAaNmMGQwHQYDVR0OBBYEFJ47nRzHaOT+vY44N3TCMYtGlBjIMB8G
|
||||
A1UdIwQYMBaAFNxeUxPIM8G7cX0DhFc81pLD4W+HMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBRmnMoOtQbYL7P
|
||||
Co1B5Chslb86HP2WI1jGRXhbfwAF2ySDFnX2ZbRPVtoQ+IuqXWxyXAeicYjXR6kz
|
||||
xX8hLWfD14kWUIz6ZgT3uZrDSIzmQ+tz8ztbT6mTI1ECWdjLV/i58f6vKzgLD8Vp
|
||||
3VdVns8NA9ee6a65QNjZEnwBVeccysoWkOwM/KzuazhSGcGu44y/S4ny9pAg7Pol
|
||||
2kV4NicDKD6tSAdXmPmjFalYUfnMmyhurZIPrS2dgYgpOrGVMwronTOZ3BUf4DL4
|
||||
zkkmcLXss1KztQnLd23nuNiIscwMcGM58a3O5zUp7aorfrm7cdRgkFmcYVNO/6uG
|
||||
Q5iJ+Ppk
|
||||
-----END CERTIFICATE-----`
|
||||
@@ -3,15 +3,12 @@ package tunneldriver
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -21,6 +18,7 @@ import (
|
||||
commonv1alpha1 "github.com/ngrok/ngrok-operator/api/common/v1alpha1"
|
||||
ingressv1alpha1 "github.com/ngrok/ngrok-operator/api/ingress/v1alpha1"
|
||||
ngrokv1alpha1 "github.com/ngrok/ngrok-operator/api/ngrok/v1alpha1"
|
||||
"github.com/ngrok/ngrok-operator/internal/util"
|
||||
"github.com/ngrok/ngrok-operator/internal/version"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -43,12 +41,6 @@ func (l k8sLogger) Log(_ context.Context, level logrok.LogLevel, msg string, kvs
|
||||
l.logger.V(level-4).Info(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
const (
|
||||
// TODO: Make this configurable via helm and document it so users can
|
||||
// use it for things like proxies
|
||||
customCertsPath = "/etc/ssl/certs/ngrok/"
|
||||
)
|
||||
|
||||
type commonEndpointOption interface {
|
||||
config.HTTPEndpointOption
|
||||
config.TLSEndpointOption
|
||||
@@ -163,14 +155,11 @@ func New(ctx context.Context, logger logr.Logger, opts TunnelDriverOpts) (*Tunne
|
||||
return nil, fmt.Errorf("invalid value for RootCAs: %s", opts.RootCAs)
|
||||
}
|
||||
|
||||
// Configure certs if the custom cert directory exists or host if set
|
||||
if _, err := os.Stat(customCertsPath); !os.IsNotExist(err) || isHostCA {
|
||||
caCerts, err := caCerts(isHostCA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
connOpts = append(connOpts, ngrok.WithCA(caCerts))
|
||||
certPool, err := util.LoadCerts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
connOpts = append(connOpts, ngrok.WithCA(certPool))
|
||||
|
||||
if isHostCA {
|
||||
connOpts = append(connOpts, ngrok.WithTLSConfig(func(c *tls.Config) {
|
||||
@@ -231,7 +220,7 @@ func New(ctx context.Context, logger logr.Logger, opts TunnelDriverOpts) (*Tunne
|
||||
}
|
||||
}),
|
||||
)
|
||||
_, err := ngrok.Connect(ctx, connOpts...)
|
||||
_, err = ngrok.Connect(ctx, connOpts...)
|
||||
|
||||
return td, err
|
||||
}
|
||||
@@ -262,45 +251,6 @@ func (td *TunnelDriver) getSession() (ngrok.Session, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// caCerts combines the system ca certs with a directory of custom ca certs
|
||||
func caCerts(hostCA bool) (*x509.CertPool, error) {
|
||||
systemCertPool, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// we're all set if we're using the host CA
|
||||
if hostCA {
|
||||
return systemCertPool, nil
|
||||
}
|
||||
|
||||
// Clone the system cert pool
|
||||
customCertPool := systemCertPool.Clone()
|
||||
|
||||
// Read each .crt file in the custom cert directory
|
||||
files, err := os.ReadDir(customCertsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) != ".crt" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Read the contents of the .crt file
|
||||
certBytes, err := os.ReadFile(filepath.Join(customCertsPath, file.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Append the cert to the custom cert pool
|
||||
customCertPool.AppendCertsFromPEM(certBytes)
|
||||
}
|
||||
|
||||
return customCertPool, nil
|
||||
}
|
||||
|
||||
// CreateTunnel creates and starts a new tunnel in a goroutine. If a tunnel with the same name already exists,
|
||||
// it will be stopped and replaced with a new tunnel unless the labels match.
|
||||
func (td *TunnelDriver) CreateTunnel(ctx context.Context, name string, spec ingressv1alpha1.TunnelSpec) error {
|
||||
|
||||
@@ -42,15 +42,3 @@ spec:
|
||||
("tls.crt" != null && "tls.crt" != ""): true
|
||||
("tls.csr" != null && "tls.csr" != ""): true
|
||||
("tls.key" != null && "tls.key" != ""): true
|
||||
|
||||
- name: assert Configmap/ngrok-intermediate-ca exists (tunnels/forwarders will work)
|
||||
try:
|
||||
- assert:
|
||||
resource:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ngrok-intermediate-ca
|
||||
namespace: ngrok-operator
|
||||
data:
|
||||
("root.crt" != null): true
|
||||
|
||||
Reference in New Issue
Block a user