Skip to content

Commit

Permalink
Merge pull request #5372 from sbueringer/pr-fix-certificate-target-na…
Browse files Browse the repository at this point in the history
…mespace

🐛 clusterctl: fix Certificate target namespace
  • Loading branch information
k8s-ci-robot committed Oct 4, 2021
2 parents cab465d + 1bf3a10 commit 6ab9c28
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 5 deletions.
44 changes: 39 additions & 5 deletions cmd/clusterctl/client/repository/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,12 @@ const (
clusterRoleKind = "ClusterRole"
clusterRoleBindingKind = "ClusterRoleBinding"
roleBindingKind = "RoleBinding"
certificateKind = "Certificate"
mutatingWebhookConfigurationKind = "MutatingWebhookConfiguration"
validatingWebhookConfigurationKind = "ValidatingWebhookConfiguration"
customResourceDefinitionKind = "CustomResourceDefinition"
)

const (
// WebhookNamespaceName is the namespace used to deploy Cluster API webhooks.
WebhookNamespaceName = "capi-webhook-system"
)

// Components wraps a YAML file that defines the provider components
// to be installed in a management cluster (CRD, Controller, RBAC etc.)
// It is important to notice that clusterctl applies a set of processing steps to the “raw” component YAML read
Expand Down Expand Up @@ -313,6 +309,8 @@ func fixTargetNamespace(objs []unstructured.Unstructured, targetNamespace string
o.SetName(targetNamespace)
}

originalNamespace := o.GetNamespace()

// if the object is namespaced, set the namespace name
if util.IsResourceNamespaced(o.GetKind()) {
o.SetNamespace(targetNamespace)
Expand All @@ -325,6 +323,14 @@ func fixTargetNamespace(objs []unstructured.Unstructured, targetNamespace string
return nil, err
}
}

if o.GetKind() == certificateKind {
var err error
o, err = fixCertificate(o, originalNamespace, targetNamespace)
if err != nil {
return nil, err
}
}
objs[i] = o
}
return objs, nil
Expand Down Expand Up @@ -413,6 +419,7 @@ func fixValidatingWebhookNamespaceReferences(o unstructured.Unstructured, target
}
return o, errors.Errorf("failed to patch %s ValidatingWebhookConfiguration", version)
}

func fixCRDWebhookNamespaceReference(o unstructured.Unstructured, targetNamespace string) (unstructured.Unstructured, error) {
version := o.GroupVersionKind().Version
switch version {
Expand All @@ -439,6 +446,33 @@ func fixCRDWebhookNamespaceReference(o unstructured.Unstructured, targetNamespac
return o, errors.Errorf("failed to patch %s CustomResourceDefinition", version)
}

// fixCertificate fixes the dnsNames of cert-manager Certificates. The DNS names contain the dns names of the provider
// services (including the namespace) and thus have to be modified to use the target namespace instead.
func fixCertificate(o unstructured.Unstructured, originalNamespace, targetNamespace string) (unstructured.Unstructured, error) {
dnsNames, ok, err := unstructured.NestedStringSlice(o.UnstructuredContent(), "spec", "dnsNames")
if err != nil {
return o, errors.Wrapf(err, "failed to get .spec.dnsNames from Certificate %s/%s", o.GetNamespace(), o.GetName())
}
// Return if we don't find .spec.dnsNames.
if !ok {
return o, nil
}

// Iterate through dnsNames and adjust the namespace.
// The dnsNames slice usually looks like this:
// - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
// - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
for i, dnsName := range dnsNames {
dnsNames[i] = strings.Replace(dnsName, fmt.Sprintf(".%s.", originalNamespace), fmt.Sprintf(".%s.", targetNamespace), 1)
}

if err := unstructured.SetNestedStringSlice(o.UnstructuredContent(), dnsNames, "spec", "dnsNames"); err != nil {
return o, errors.Wrapf(err, "failed to set .spec.dnsNames to Certificate %s/%s", o.GetNamespace(), o.GetName())
}

return o, nil
}

// fixRBAC ensures all the ClusterRole and ClusterRoleBinding have the name prefixed with the namespace name and that
// all the clusterRole/clusterRoleBinding namespaced subjects refers to targetNamespace.
func fixRBAC(objs []unstructured.Unstructured, targetNamespace string) ([]unstructured.Unstructured, error) {
Expand Down
52 changes: 52 additions & 0 deletions cmd/clusterctl/client/repository/components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,58 @@ func Test_fixTargetNamespace(t *testing.T) {
},
},
},
{
name: "fix cert-manager Certificate",
objs: []unstructured.Unstructured{
{
Object: map[string]interface{}{
"apiVersion": "cert-manager.io/v1",
"kind": "Certificate",
"metadata": map[string]interface{}{
"name": "capi-serving-cert",
"namespace": "capi-system",
},
"spec": map[string]interface{}{
"dnsNames": []interface{}{
"capi-webhook-service.capi-system.svc",
"capi-webhook-service.capi-system.svc.cluster.local",
"random-other-dns-name",
},
"issuerRef": map[string]interface{}{
"kind": "Issuer",
"name": "capi-selfsigned-issuer",
},
"secretName": "capi-webhook-service-cert",
},
},
},
},
targetNamespace: "bar",
want: []unstructured.Unstructured{
{
Object: map[string]interface{}{
"apiVersion": "cert-manager.io/v1",
"kind": "Certificate",
"metadata": map[string]interface{}{
"name": "capi-serving-cert",
"namespace": "bar",
},
"spec": map[string]interface{}{
"dnsNames": []interface{}{
"capi-webhook-service.bar.svc",
"capi-webhook-service.bar.svc.cluster.local",
"random-other-dns-name",
},
"issuerRef": map[string]interface{}{
"kind": "Issuer",
"name": "capi-selfsigned-issuer",
},
"secretName": "capi-webhook-service-cert",
},
},
},
},
},