-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
auth_test.go
175 lines (149 loc) · 6.45 KB
/
auth_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controlplane_test
import (
"crypto/tls"
"crypto/x509"
"os"
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/client-go/rest"
kcert "k8s.io/client-go/util/cert"
cp "sigs.k8s.io/controller-runtime/pkg/internal/testing/controlplane"
"sigs.k8s.io/controller-runtime/pkg/internal/testing/process"
)
var _ = Describe("Cert Authentication", func() {
var authn *cp.CertAuthn
BeforeEach(func() {
var err error
authn, err = cp.NewCertAuthn()
Expect(err).NotTo(HaveOccurred(), "should be able to create the cert authn")
})
Context("when starting", func() {
It("should write the verifying CA to the configured directory", func() {
By("setting up a temp dir")
dir, err := os.MkdirTemp("", "envtest_controlplane_*")
Expect(err).NotTo(HaveOccurred(), "should be able to provision a temp dir")
if dir != "" {
defer os.RemoveAll(dir)
}
By("configuring to use that dir")
Expect(authn.Configure(dir, process.EmptyArguments())).To(Succeed())
By("starting and checking the dir")
Expect(authn.Start()).To(Succeed())
defer func() { Expect(authn.Stop()).To(Succeed()) }() // not strictly necessary, but future-proof
_, err = os.Stat(filepath.Join(dir, "client-cert-auth-ca.crt"))
Expect(err).NotTo(HaveOccurred())
})
It("should error out if we haven't been configured yet", func() {
// NB(directxman12): no configure here intentionally
Expect(authn.Start()).NotTo(Succeed())
})
})
Context("when configuring", func() {
It("should have set up the API server to use the written file for client cert auth", func() {
args := process.EmptyArguments()
Expect(authn.Configure("/tmp/____doesnotexist", args)).To(Succeed())
Expect(args.Get("client-ca-file").Get(nil)).To(ConsistOf("/tmp/____doesnotexist/client-cert-auth-ca.crt"))
})
})
Describe("creating users", func() {
user := cp.User{Name: "someuser", Groups: []string{"group1", "group2"}}
Context("before starting", func() {
It("should yield a REST config that contains certs valid for the to-be-written CA", func() {
cfg, err := authn.AddUser(user, &rest.Config{})
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
Expect(cfg.CertData).NotTo(BeEmpty())
Expect(cfg.KeyData).NotTo(BeEmpty())
// double-check the cert (assume the key is fine if it's present
// and the cert is also present, cause it's more annoying to verify
// and we have separate tinyca & integration tests.
By("parsing the config's cert & key data")
certs, err := tls.X509KeyPair(cfg.CertData, cfg.KeyData)
Expect(err).NotTo(HaveOccurred(), "config cert/key data should be valid key pair")
cert, err := x509.ParseCertificate(certs.Certificate[0]) // re-parse cause .Leaf isn't saved
Expect(err).NotTo(HaveOccurred())
By("starting and loading the CA cert")
dir, err := os.MkdirTemp("", "envtest_controlplane_*")
Expect(err).NotTo(HaveOccurred(), "should be able to provision a temp dir")
if dir != "" {
defer os.RemoveAll(dir)
}
Expect(authn.Configure(dir, process.EmptyArguments())).To(Succeed())
Expect(authn.Start()).To(Succeed())
caCerts, err := kcert.CertsFromFile(filepath.Join(dir, "client-cert-auth-ca.crt"))
Expect(err).NotTo(HaveOccurred(), "should be able to read the CA cert file))))")
Expect(cert.CheckSignatureFrom(caCerts[0])).To(Succeed(), "the config's cert should be signed by the written CA")
})
It("should copy the configuration from the base CA without modifying it", func() {
By("creating a user and checking the output config")
base := &rest.Config{Burst: 30}
cfg, err := authn.AddUser(user, base)
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
Expect(cfg.Burst).To(Equal(30))
By("mutating the base and verifying the cfg doesn't change")
base.Burst = 8675
Expect(cfg.Burst).To(Equal(30))
})
})
Context("after starting", func() {
var dir string
BeforeEach(func() {
By("setting up a temp dir & starting with it")
var err error
dir, err = os.MkdirTemp("", "envtest_controlplane_*")
Expect(err).NotTo(HaveOccurred(), "should be able to provision a temp dir")
Expect(authn.Configure(dir, process.EmptyArguments())).To(Succeed())
Expect(authn.Start()).To(Succeed())
})
AfterEach(func() {
if dir != "" {
defer os.RemoveAll(dir)
}
})
It("should yield a REST config that contains certs valid for the written CA", func() {
cfg, err := authn.AddUser(user, &rest.Config{})
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
Expect(cfg.CertData).NotTo(BeEmpty())
Expect(cfg.KeyData).NotTo(BeEmpty())
// double-check the cert (assume the key is fine if it's present
// and the cert is also present, cause it's more annoying to verify
// and we have separate tinyca & integration tests.
By("parsing the config's cert & key data")
certs, err := tls.X509KeyPair(cfg.CertData, cfg.KeyData)
Expect(err).NotTo(HaveOccurred(), "config cert/key data should be valid key pair")
cert, err := x509.ParseCertificate(certs.Certificate[0]) // re-parse cause .Leaf isn't saved
Expect(err).NotTo(HaveOccurred())
By("loading the CA cert")
caCerts, err := kcert.CertsFromFile(filepath.Join(dir, "client-cert-auth-ca.crt"))
Expect(err).NotTo(HaveOccurred(), "should be able to read the CA cert file))))")
Expect(cert.CheckSignatureFrom(caCerts[0])).To(Succeed(), "the config's cert should be signed by the written CA")
})
It("should copy the configuration from the base CA without modifying it", func() {
By("creating a user and checking the output config")
base := &rest.Config{Burst: 30}
cfg, err := authn.AddUser(user, base)
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
Expect(cfg.Burst).To(Equal(30))
By("mutating the base and verifying the cfg doesn't change")
base.Burst = 8675
Expect(cfg.Burst).To(Equal(30))
})
})
})
})