Skip to content

Commit 56e6b45

Browse files
committed
[THREESCALE-7921] New APIcast CRD field: caCertificateSecretRef
1 parent 553a40c commit 56e6b45

File tree

7 files changed

+104
-0
lines changed

7 files changed

+104
-0
lines changed

apis/apps/v1alpha1/apicast_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ type APIcastSpec struct {
177177
// HTTPSCertificateSecretRef references secret containing the X.509 certificate in the PEM format and the X.509 certificate secret key.
178178
// +optional
179179
HTTPSCertificateSecretRef *v1.LocalObjectReference `json:"httpsCertificateSecretRef,omitempty"`
180+
// CACertificateSecretRef references secret containing the X.509 CA certificate in the PEM format.
181+
// +optional
182+
CACertificateSecretRef *v1.LocalObjectReference `json:"caCertificateSecretRef,omitempty"`
180183
// Workers defines the number of APIcast's worker processes per pod.
181184
// +optional
182185
// +kubebuilder:validation:Minimum=1

apis/apps/v1alpha1/zz_generated.deepcopy.go

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

bundle/manifests/apps.3scale.net_apicasts.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ spec:
6565
a protocol-specific proxy is not specified. Authentication is not supported.
6666
Format is <scheme>://<host>:<port>
6767
type: string
68+
caCertificateSecretRef:
69+
description: CACertificateSecretRef references secret containing the X.509 CA certificate in the PEM format.
70+
properties:
71+
name:
72+
description: |-
73+
Name of the referent.
74+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
75+
TODO: Add other useful fields. apiVersion, kind, uid?
76+
type: string
77+
type: object
78+
x-kubernetes-map-type: atomic
6879
cacheConfigurationSeconds:
6980
description: |-
7081
The period (in seconds) that the APIcast configuration will be stored in

config/crd/bases/apps.3scale.net_apicasts.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ spec:
5858
a protocol-specific proxy is not specified. Authentication is not supported.
5959
Format is <scheme>://<host>:<port>
6060
type: string
61+
caCertificateSecretRef:
62+
description: CACertificateSecretRef references secret containing the
63+
X.509 CA certificate in the PEM format.
64+
properties:
65+
name:
66+
description: |-
67+
Name of the referent.
68+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
69+
TODO: Add other useful fields. apiVersion, kind, uid?
70+
type: string
71+
type: object
72+
x-kubernetes-map-type: atomic
6173
cacheConfigurationSeconds:
6274
description: |-
6375
The period (in seconds) that the APIcast configuration will be stored in

pkg/apicast/apicast.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const (
4242
const (
4343
HTTPSCertificatesMountPath = "/var/run/secrets/apicast"
4444
HTTPSCertificatesVolumeName = "https-certificates"
45+
CACertificatesSecretKey = "ca-bundle.crt"
46+
CACertificatesVolumeName = "ca-certificate"
4547
CustomPoliciesMountBasePath = "/opt/app-root/src/policies"
4648
CustomEnvsMountBasePath = "/opt/app-root/src/custom-environments"
4749
TracingConfigMountBasePath = "/opt/app-root/src/tracing-configs"
@@ -91,6 +93,15 @@ func (a *APIcast) deploymentVolumeMounts() []v1.VolumeMount {
9193
})
9294
}
9395

96+
// Use the same mount path with https certificate
97+
if a.options.CACertificateSecret != nil {
98+
volumeMounts = append(volumeMounts, v1.VolumeMount{
99+
Name: CACertificatesVolumeName,
100+
MountPath: HTTPSCertificatesMountPath,
101+
ReadOnly: true,
102+
})
103+
}
104+
94105
for _, customPolicy := range a.options.CustomPolicies {
95106
volumeMounts = append(volumeMounts, v1.VolumeMount{
96107
Name: policyVolumeName(customPolicy),
@@ -167,6 +178,23 @@ func (a *APIcast) deploymentVolumes() []v1.Volume {
167178
})
168179
}
169180

181+
if a.options.CACertificateSecret != nil {
182+
volumes = append(volumes, v1.Volume{
183+
Name: CACertificatesVolumeName,
184+
VolumeSource: v1.VolumeSource{
185+
Secret: &v1.SecretVolumeSource{
186+
SecretName: a.options.CACertificateSecret.Name,
187+
Items: []v1.KeyToPath{
188+
{
189+
Key: CACertificatesSecretKey,
190+
Path: "ca-bundle.crt", // Map the secret key to the ca-bundle.crt file in the container
191+
},
192+
},
193+
},
194+
},
195+
})
196+
}
197+
170198
for _, customPolicy := range a.options.CustomPolicies {
171199
volumes = append(volumes, v1.Volume{
172200
Name: policyVolumeName(customPolicy),
@@ -324,6 +352,11 @@ func (a *APIcast) deploymentEnv() []v1.EnvVar {
324352
k8sutils.EnvVarFromValue("APICAST_HTTPS_CERTIFICATE_KEY", fmt.Sprintf("%s/%s", HTTPSCertificatesMountPath, v1.TLSPrivateKeyKey)))
325353
}
326354

355+
if a.options.CACertificateSecret != nil {
356+
env = append(env,
357+
k8sutils.EnvVarFromValue("SSL_CERT_FILE", path.Join(HTTPSCertificatesMountPath, "ca-bundle.crt")))
358+
}
359+
327360
if a.options.Workers != nil {
328361
env = append(env, k8sutils.EnvVarFromValue("APICAST_WORKERS", strconv.Itoa(int(*a.options.Workers))))
329362
}

pkg/apicast/apicast_option_provider.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ func (a *APIcastOptionsProvider) GetApicastOptions(ctx context.Context) (*APIcas
136136
}
137137
a.APIcastOptions.HTTPSCertificateSecret = httpsCertificateSecret
138138

139+
caCertificateSecret, err := a.getCACertificateSecret(ctx)
140+
if err != nil {
141+
return nil, err
142+
}
143+
a.APIcastOptions.CACertificateSecret = caCertificateSecret
144+
139145
// Resource requirements
140146
resourceRequirements := DefaultResourceRequirements(a.APIcastCR.Spec.Hpa)
141147

@@ -368,6 +374,39 @@ func (a *APIcastOptionsProvider) getHTTPSCertificateSecret(ctx context.Context)
368374
return secret, err
369375
}
370376

377+
func (a *APIcastOptionsProvider) getCACertificateSecret(ctx context.Context) (*v1.Secret, error) {
378+
if a.APIcastCR.Spec.CACertificateSecretRef == nil {
379+
return nil, nil
380+
}
381+
382+
errors := field.ErrorList{}
383+
specFldPath := field.NewPath("spec")
384+
caCertificateSecretRefFldPath := specFldPath.Child("caCertificateSecretRef")
385+
secretNameFldPath := caCertificateSecretRefFldPath.Child("name")
386+
387+
ns := a.APIcastCR.Namespace
388+
389+
if a.APIcastCR.Spec.CACertificateSecretRef.Name == "" {
390+
errors = append(errors, field.Required(secretNameFldPath, "secret name not provided"))
391+
return nil, errors.ToAggregate()
392+
}
393+
394+
namespacedName := types.NamespacedName{
395+
Name: a.APIcastCR.Spec.CACertificateSecretRef.Name,
396+
Namespace: ns,
397+
}
398+
399+
secret := &v1.Secret{}
400+
err := a.Client.Get(ctx, namespacedName, secret)
401+
402+
if err != nil {
403+
// NotFoundError is also an error, it is required to exist
404+
return nil, err
405+
}
406+
407+
return secret, nil
408+
}
409+
371410
func (a *APIcastOptionsProvider) validateCustomPolicySecret(ctx context.Context, nn types.NamespacedName) (*v1.Secret, error) {
372411
secret := &v1.Secret{}
373412
err := a.Client.Get(ctx, nn, secret)

pkg/apicast/apicast_options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ type APIcastOptions struct {
6666
HTTPSPort *int32
6767
HTTPSVerifyDepth *int64
6868
HTTPSCertificateSecret *v1.Secret
69+
CACertificateSecret *v1.Secret
6970
Workers *int32
7071
Timezone *string
7172
CustomPolicies []CustomPolicy

0 commit comments

Comments
 (0)