Skip to content

Commit 9520d80

Browse files
palexsteradamjensenbot
authored andcommitted
Fix Certificate generation on K3s and OpenShift
1 parent c89160a commit 9520d80

File tree

5 files changed

+100
-11
lines changed

5 files changed

+100
-11
lines changed

cmd/init-virtual-kubelet/main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"k8s.io/client-go/rest"
2828
"k8s.io/klog/v2"
2929

30+
liqonetutils "github.com/liqotech/liqo/pkg/liqonet/utils"
3031
"github.com/liqotech/liqo/pkg/utils"
3132
vk "github.com/liqotech/liqo/pkg/vkMachinery"
3233
"github.com/liqotech/liqo/pkg/vkMachinery/csr"
@@ -62,6 +63,11 @@ func main() {
6263
klog.Fatal("Unable to create CSR: POD_NAME undefined")
6364
}
6465

66+
podIP, err := liqonetutils.GetPodIP()
67+
if err != nil {
68+
klog.Fatal(err)
69+
}
70+
6571
namespace, ok := os.LookupEnv("POD_NAMESPACE")
6672
if !ok {
6773
klog.Fatal("Unable to create CSR: POD_NAMESPACE undefined")
@@ -91,7 +97,7 @@ func main() {
9197
}
9298

9399
// Generate Key and CSR files in PEM format
94-
if err := csr.CreateCSRResource(ctx, name, client, nodeName, namespace, distribution); err != nil {
100+
if err := csr.CreateCSRResource(ctx, name, client, nodeName, namespace, distribution, podIP); err != nil {
95101
klog.Fatalf("Unable to create CSR: %s", err)
96102
}
97103

pkg/vkMachinery/csr/const.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ package csr
1717
const (
1818
kubeletServingSignerName = "kubernetes.io/kubelet-serving"
1919
kubeletAPIServingSignerName = "kubernetes.io/kube-apiserver-client-kubelet"
20-
)
21-
22-
const (
23-
csrSecretLabel = "liqo.io/virtual-kubelet-csr-secret" // nolint:gosec // not a credential
20+
csrSecretLabel = "liqo.io/virtual-kubelet-csr-secret" // nolint:gosec // not a credential
21+
csrNodeGroup = "system:nodes"
22+
csrNodeGroupMember = "system:node:"
2423
)

pkg/vkMachinery/csr/creation.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package csr
1616

1717
import (
1818
"context"
19+
"net"
1920

2021
certificatesv1 "k8s.io/api/certificates/v1"
2122
errors "k8s.io/apimachinery/pkg/api/errors"
@@ -26,8 +27,8 @@ import (
2627

2728
// CreateCSRResource creates a CSR Resource for a new Virtual Kubelet instance.
2829
func CreateCSRResource(ctx context.Context,
29-
name string, client kubernetes.Interface, nodeName, namespace, distribution string) error {
30-
csrPem, keyPem, err := generateVKCertificateBundle(name)
30+
name string, client kubernetes.Interface, nodeName, namespace, distribution string, podIP net.IP) error {
31+
csrPem, keyPem, err := generateVKCertificateBundle(name, podIP)
3132
var csrResource *certificatesv1.CertificateSigningRequest
3233
if err != nil {
3334
return err

pkg/vkMachinery/csr/generation.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"crypto/x509/pkix"
2222
"encoding/pem"
2323
"fmt"
24+
"net"
2425

2526
certificatesv1 "k8s.io/api/certificates/v1"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -32,7 +33,7 @@ import (
3233

3334
// generateVKCertificateBundle generates respectively a key and a CSR in PEM format compliant
3435
// with the K8s kubelet-serving signer taking a name as input.
35-
func generateVKCertificateBundle(name string) (csrPEM, keyPEM []byte, err error) {
36+
func generateVKCertificateBundle(name string, podIP net.IP) (csrPEM, keyPEM []byte, err error) {
3637
// Generate a new private key.
3738
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
3839
if err != nil {
@@ -48,11 +49,12 @@ func generateVKCertificateBundle(name string) (csrPEM, keyPEM []byte, err error)
4849
template := &x509.CertificateRequest{
4950
Subject: pkix.Name{
5051
Organization: []string{
51-
"system:nodes",
52+
csrNodeGroup,
5253
},
53-
CommonName: "system:node:" + name,
54+
CommonName: csrNodeGroupMember + name,
5455
},
55-
DNSNames: []string{"DNS:" + name},
56+
DNSNames: []string{name},
57+
IPAddresses: []net.IP{podIP},
5658
}
5759
csrPEM, err = cert.MakeCSRFromTemplate(privateKey, template)
5860
if err != nil {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2019-2021 The Liqo Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package csr
16+
17+
import (
18+
"crypto/x509"
19+
"encoding/pem"
20+
"net"
21+
22+
. "github.com/onsi/ginkgo"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
var _ = Describe("Assert the correctness of the virtual-node CSR", func() {
27+
var (
28+
podNameT string
29+
podIP net.IP
30+
csrPEM []byte
31+
keyPEM []byte
32+
csr *x509.CertificateRequest
33+
csrBlock *pem.Block
34+
)
35+
When("Requesting a certificate for a virtual node", func() {
36+
BeforeEach(func() {
37+
podNameT = "podName"
38+
podIP = net.ParseIP("10.0.0.1").To4()
39+
})
40+
41+
JustBeforeEach(func() {
42+
csrPEM, keyPEM, err = generateVKCertificateBundle(podNameT, podIP)
43+
})
44+
45+
It("Should not trigger any error", func() {
46+
Expect(err).NotTo(HaveOccurred())
47+
Expect(csrPEM).NotTo(BeNil())
48+
Expect(keyPEM).NotTo(BeNil())
49+
})
50+
51+
Context("When decoding the certificate", func() {
52+
53+
BeforeEach(func() {
54+
csrBlock, _ = pem.Decode(csrPEM)
55+
csr, err = x509.ParseCertificateRequest(csrBlock.Bytes)
56+
})
57+
58+
It("Should be a valid x509 certificate", func() {
59+
Expect(csrBlock).NotTo(BeNil())
60+
Expect(err).NotTo(HaveOccurred())
61+
})
62+
63+
It("Should include the right subject alternative names (SAN)", func() {
64+
Expect(csr.IPAddresses).To(HaveLen(1))
65+
Expect(csr.DNSNames).To(HaveLen(1))
66+
Expect(csr.IPAddresses[0]).To(BeEquivalentTo(podIP))
67+
Expect(csr.DNSNames[0]).To(BeEquivalentTo(podNameT))
68+
})
69+
70+
It("Should include the right Common Name (CN)", func() {
71+
Expect(csr.Subject.CommonName).To(BeEquivalentTo(csrNodeGroupMember + podNameT))
72+
})
73+
74+
It("Should include the right list of Organizations (O)", func() {
75+
Expect(csr.Subject.Organization).To(HaveLen(1))
76+
Expect(csr.Subject.Organization[0]).To(BeEquivalentTo(csrNodeGroup))
77+
})
78+
})
79+
80+
})
81+
})

0 commit comments

Comments
 (0)