Skip to content

Commit

Permalink
Add SANs configurability for API server
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdoherty4 committed Oct 27, 2023
1 parent 6ba1416 commit 2873381
Show file tree
Hide file tree
Showing 40 changed files with 4,485 additions and 82 deletions.
6 changes: 6 additions & 0 deletions config/crd/bases/anywhere.eks.amazonaws.com_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ spec:
type: object
controlPlaneConfiguration:
properties:
certSans:
description: CertSANs is a slice of domain names or IPs to be
added as Subject Name Alternatives of the Kube API Servers Certificate.
items:
type: string
type: array
count:
description: Count defines the number of desired control plane
nodes. Defaults to 1.
Expand Down
20 changes: 20 additions & 0 deletions pkg/api/v1alpha1/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/validation"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
k8sclientvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/yaml"
Expand Down Expand Up @@ -188,6 +189,7 @@ var clusterConfigValidations = []func(*Cluster) error{
validateControlPlaneLabels,
validatePackageControllerConfiguration,
validateEksaVersion,
validateControlPlaneCertSANs,
}

// GetClusterConfig parses a Cluster object from a multiobject yaml file in disk
Expand Down Expand Up @@ -419,6 +421,24 @@ func validateControlPlaneEndpoint(clusterConfig *Cluster) error {
return nil
}

func validateControlPlaneCertSANs(cfg *Cluster) error {
var invalid []string
for _, san := range cfg.Spec.ControlPlaneConfiguration.CertSANs {
isDomain := k8sclientvalidation.IsDNS1123Subdomain(san)
isIP := net.ParseIP(san)

if len(isDomain) > 0 && isIP == nil {
invalid = append(invalid, san)
}
}

if len(invalid) > 0 {
return fmt.Errorf("invalid ControlPlaneConfiguration.CertSANs; must be an IP or domain name: [%v]", strings.Join(invalid, ", "))
}

return nil
}

func validateWorkerNodeGroups(clusterConfig *Cluster) error {
workerNodeGroupConfigs := clusterConfig.Spec.WorkerNodeGroupConfigurations
if len(workerNodeGroupConfigs) <= 0 {
Expand Down
3 changes: 3 additions & 0 deletions pkg/api/v1alpha1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ type ControlPlaneConfiguration struct {
// SkipLoadBalancerDeployment skip deploying control plane load balancer.
// Make sure your infrastructure can handle control plane load balancing when you set this field to true.
SkipLoadBalancerDeployment bool `json:"skipLoadBalancerDeployment,omitempty"`
// CertSANs is a slice of domain names or IPs to be added as Subject Name Alternatives of the
// Kube API Servers Certificate.
CertSANs []string `json:"certSans,omitempty"`
}

// MachineHealthCheck allows to configure timeouts for machine health checks. Machine Health Checks are responsible for remediating unhealthy Machines.
Expand Down
5 changes: 5 additions & 0 deletions pkg/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/providers/cloudstack/config/template-cp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ spec:
imageRepository: {{.corednsRepository}}
imageTag: {{.corednsVersion}}
apiServer:
{{- with .apiServerCertSANs }}
certSANs:
{{- toYaml . | nindent 8 }}
{{- end }}
extraArgs:
cloud-provider: external
audit-policy-file: /etc/kubernetes/audit-policy.yaml
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/cloudstack/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ func buildTemplateMapCP(clusterSpec *cluster.Spec) (map[string]interface{}, erro
"controlPlaneEndpointHost": host,
"controlPlaneEndpointPort": port,
"controlPlaneReplicas": clusterSpec.Cluster.Spec.ControlPlaneConfiguration.Count,
"apiServerCertSANs": clusterSpec.Cluster.Spec.ControlPlaneConfiguration.CertSANs,
"kubernetesRepository": versionsBundle.KubeDistro.Kubernetes.Repository,
"kubernetesVersion": versionsBundle.KubeDistro.Kubernetes.Tag,
"etcdRepository": versionsBundle.KubeDistro.Etcd.Repository,
Expand Down
28 changes: 28 additions & 0 deletions pkg/providers/cloudstack/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,31 @@ func TestTemplateBuilderGenerateCAPISpecWorkersInvalidEndpoint(t *testing.T) {
_, err := templateBuilder.GenerateCAPISpecWorkers(clusterSpec, machineTemplateNames, kubeadmConfigTemplateNames)
g.Expect(err).To(MatchError(ContainSubstring("building template map for MD host 1.1.1.1:: is invalid: address 1.1.1.1::: too many colons in address")))
}

func TestTemplateBuilder_CertSANs(t *testing.T) {
for _, tc := range []struct {
Input string
Output string
}{
{
Input: "testdata/cluster_api_server_cert_san_domain_name.yaml",
Output: "testdata/expected_cluster_api_server_cert_san_domain_name.yaml",
},
{
Input: "testdata/cluster_api_server_cert_san_ip.yaml",
Output: "testdata/expected_cluster_api_server_cert_san_ip.yaml",
},
} {
g := NewWithT(t)
clusterSpec := test.NewFullClusterSpec(t, tc.Input)

bldr := cloudstack.NewTemplateBuilder(time.Now)

data, err := bldr.GenerateCAPISpecControlPlane(clusterSpec, func(values map[string]interface{}) {
values["controlPlaneTemplateName"] = clusterapi.ControlPlaneMachineTemplateName(clusterSpec.Cluster)
})
g.Expect(err).ToNot(HaveOccurred())

test.AssertContentToFile(t, string(data), tc.Output)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Cluster
metadata:
name: test
namespace: test
spec:
clusterNetwork:
cniConfig:
cilium: {}
pods:
cidrBlocks:
- 192.168.0.0/16
services:
cidrBlocks:
- 10.96.0.0/12
controlPlaneConfiguration:
count: 1
endpoint:
host: 0.0.0.0
certSANs: ["foo.bar"]
machineGroupRef:
kind: CloudStackMachineConfig
name: test
datacenterRef:
kind: CloudStackDatacenterConfig
name: test
kubernetesVersion: "1.21"
---
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: CloudStackDatacenterConfig
metadata:
name: test
namespace: test
spec:
availabilityZones:
- account: "admin"
domain: "domain1"
name: "default-az-0"
credentialsRef: "global"
zone:
name: "zone1"
network:
name: "net1"
managementApiEndpoint: "http://127.16.0.1:8080/client/api"
---
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: CloudStackMachineConfig
metadata:
name: test
namespace: test
spec:
computeOffering:
name: "m4-large"
users:
- name: "mySshUsername"
sshAuthorizedKeys: # The key below was manually generated and not used in any production systems
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1BK73XhIzjX+meUr7pIYh6RHbvI3tmHeQIXY5lv7aztN1UoX+bhPo3dwo2sfSQn5kuxgQdnxIZ/CTzy0p0GkEYVv3gwspCeurjmu0XmrdmaSGcGxCEWT/65NtvYrQtUE5ELxJ+N/aeZNlK2B7IWANnw/82913asXH4VksV1NYNduP0o1/G4XcwLLSyVFB078q/oEnmvdNIoS61j4/o36HVtENJgYr0idcBvwJdvcGxGnPaqOhx477t+kfJAa5n5dSA5wilIaoXH5i1Tf/HsTCM52L+iNCARvQzJYZhzbWI1MDQwzILtIBEQCJsl2XSqIupleY8CxqQ6jCXt2mhae+wPc3YmbO5rFvr2/EvC57kh3yDs1Nsuj8KOvD78KeeujbR8n8pScm3WDp62HFQ8lEKNdeRNj6kB8WnuaJvPnyZfvzOhwG65/9w13IBl7B1sWxbFnq2rMpm5uHVK7mAmjL0Tt8zoDhcE1YJEnp9xte3/pvmKPkST5Q/9ZtR9P5sI+02jY0fvPkPyC03j2gsPixG7rpOCwpOdbny4dcj0TDeeXJX8er+oVfJuLYz0pNWJcT2raDdFfcqvYA0B0IyNYlj5nWX4RuEcyT3qocLReWPnZojetvAG/H8XwOh7fEVGqHAKOVSnPXCSQJPl6s0H12jPJBDJMTydtYPEszl4/CeQ== [email protected]"
template:
name: "kubernetes_1_21"
diskOffering:
name: "Small"
mountPath: "/data-small"
device: "/dev/vdb"
filesystem: "ext4"
label: "data_disk"
symlinks:
/var/log/kubernetes: /data-small/var/log/kubernetes
affinityGroupIds:
- control-plane-anti-affinity
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Cluster
metadata:
name: test
namespace: test
spec:
clusterNetwork:
cniConfig:
cilium: {}
pods:
cidrBlocks:
- 192.168.0.0/16
services:
cidrBlocks:
- 10.96.0.0/12
controlPlaneConfiguration:
count: 1
endpoint:
host: 0.0.0.0
certSANs: ["11.11.11.11"]
machineGroupRef:
kind: CloudStackMachineConfig
name: test
datacenterRef:
kind: CloudStackDatacenterConfig
name: test
kubernetesVersion: "1.21"
---
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: CloudStackDatacenterConfig
metadata:
name: test
namespace: test
spec:
availabilityZones:
- account: "admin"
domain: "domain1"
name: "default-az-0"
credentialsRef: "global"
zone:
name: "zone1"
network:
name: "net1"
managementApiEndpoint: "http://127.16.0.1:8080/client/api"

---
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: CloudStackMachineConfig
metadata:
name: test
namespace: test
spec:
computeOffering:
name: "m4-large"
users:
- name: "mySshUsername"
sshAuthorizedKeys: # The key below was manually generated and not used in any production systems
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1BK73XhIzjX+meUr7pIYh6RHbvI3tmHeQIXY5lv7aztN1UoX+bhPo3dwo2sfSQn5kuxgQdnxIZ/CTzy0p0GkEYVv3gwspCeurjmu0XmrdmaSGcGxCEWT/65NtvYrQtUE5ELxJ+N/aeZNlK2B7IWANnw/82913asXH4VksV1NYNduP0o1/G4XcwLLSyVFB078q/oEnmvdNIoS61j4/o36HVtENJgYr0idcBvwJdvcGxGnPaqOhx477t+kfJAa5n5dSA5wilIaoXH5i1Tf/HsTCM52L+iNCARvQzJYZhzbWI1MDQwzILtIBEQCJsl2XSqIupleY8CxqQ6jCXt2mhae+wPc3YmbO5rFvr2/EvC57kh3yDs1Nsuj8KOvD78KeeujbR8n8pScm3WDp62HFQ8lEKNdeRNj6kB8WnuaJvPnyZfvzOhwG65/9w13IBl7B1sWxbFnq2rMpm5uHVK7mAmjL0Tt8zoDhcE1YJEnp9xte3/pvmKPkST5Q/9ZtR9P5sI+02jY0fvPkPyC03j2gsPixG7rpOCwpOdbny4dcj0TDeeXJX8er+oVfJuLYz0pNWJcT2raDdFfcqvYA0B0IyNYlj5nWX4RuEcyT3qocLReWPnZojetvAG/H8XwOh7fEVGqHAKOVSnPXCSQJPl6s0H12jPJBDJMTydtYPEszl4/CeQ== [email protected]"
template:
name: "kubernetes_1_21"
diskOffering:
name: "Small"
mountPath: "/data-small"
device: "/dev/vdb"
filesystem: "ext4"
label: "data_disk"
symlinks:
/var/log/kubernetes: /data-small/var/log/kubernetes
affinityGroupIds:
- control-plane-anti-affinity
Loading

0 comments on commit 2873381

Please sign in to comment.