@@ -17,15 +17,113 @@ limitations under the License.
17
17
package v1beta1
18
18
19
19
import (
20
+ "crypto/x509"
21
+ "reflect"
22
+ "strings"
23
+
20
24
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
21
25
"k8s.io/apimachinery/pkg/runtime"
26
+ "k8s.io/apimachinery/pkg/util/sets"
22
27
)
23
28
24
29
func addDefaultingFuncs (scheme * runtime.Scheme ) error {
25
30
return RegisterDefaults (scheme )
26
31
}
32
+
27
33
func SetDefaults_CertificateSigningRequestSpec (obj * certificatesv1beta1.CertificateSigningRequestSpec ) {
28
34
if obj .Usages == nil {
29
35
obj .Usages = []certificatesv1beta1.KeyUsage {certificatesv1beta1 .UsageDigitalSignature , certificatesv1beta1 .UsageKeyEncipherment }
30
36
}
37
+
38
+ if obj .SignerName == nil {
39
+ signerName := DefaultSignerNameFromSpec (obj )
40
+ obj .SignerName = & signerName
41
+ }
42
+ }
43
+
44
+ // DefaultSignerNameFromSpec will determine the signerName that should be set
45
+ // by attempting to inspect the 'request' content and the spec options.
46
+ func DefaultSignerNameFromSpec (obj * certificatesv1beta1.CertificateSigningRequestSpec ) string {
47
+ csr , err := ParseCSR (obj .Request )
48
+ switch {
49
+ case err != nil :
50
+ // Set the signerName to 'legacy-unknown' as the CSR could not be
51
+ // recognised.
52
+ return certificatesv1beta1 .LegacyUnknownSignerName
53
+ case IsKubeletClientCSR (csr , obj .Usages ):
54
+ return certificatesv1beta1 .KubeAPIServerClientKubeletSignerName
55
+ case IsKubeletServingCSR (csr , obj .Usages ):
56
+ return certificatesv1beta1 .KubeletServingSignerName
57
+ default :
58
+ return certificatesv1beta1 .LegacyUnknownSignerName
59
+ }
60
+ }
61
+
62
+ func IsKubeletServingCSR (req * x509.CertificateRequest , usages []certificatesv1beta1.KeyUsage ) bool {
63
+ if ! reflect .DeepEqual ([]string {"system:nodes" }, req .Subject .Organization ) {
64
+ return false
65
+ }
66
+
67
+ // at least one of dnsNames or ipAddresses must be specified
68
+ if len (req .DNSNames ) == 0 && len (req .IPAddresses ) == 0 {
69
+ return false
70
+ }
71
+
72
+ if len (req .EmailAddresses ) > 0 || len (req .URIs ) > 0 {
73
+ return false
74
+ }
75
+
76
+ requiredUsages := []certificatesv1beta1.KeyUsage {
77
+ certificatesv1beta1 .UsageDigitalSignature ,
78
+ certificatesv1beta1 .UsageKeyEncipherment ,
79
+ certificatesv1beta1 .UsageServerAuth ,
80
+ }
81
+ if ! equalUnsorted (requiredUsages , usages ) {
82
+ return false
83
+ }
84
+
85
+ if ! strings .HasPrefix (req .Subject .CommonName , "system:node:" ) {
86
+ return false
87
+ }
88
+
89
+ return true
90
+ }
91
+
92
+ func IsKubeletClientCSR (req * x509.CertificateRequest , usages []certificatesv1beta1.KeyUsage ) bool {
93
+ if ! reflect .DeepEqual ([]string {"system:nodes" }, req .Subject .Organization ) {
94
+ return false
95
+ }
96
+
97
+ if len (req .DNSNames ) > 0 || len (req .EmailAddresses ) > 0 || len (req .IPAddresses ) > 0 || len (req .URIs ) > 0 {
98
+ return false
99
+ }
100
+
101
+ if ! strings .HasPrefix (req .Subject .CommonName , "system:node:" ) {
102
+ return false
103
+ }
104
+
105
+ requiredUsages := []certificatesv1beta1.KeyUsage {
106
+ certificatesv1beta1 .UsageDigitalSignature ,
107
+ certificatesv1beta1 .UsageKeyEncipherment ,
108
+ certificatesv1beta1 .UsageClientAuth ,
109
+ }
110
+ if ! equalUnsorted (requiredUsages , usages ) {
111
+ return false
112
+ }
113
+
114
+ return true
115
+ }
116
+
117
+ // equalUnsorted compares two []string for equality of contents regardless of
118
+ // the order of the elements
119
+ func equalUnsorted (left , right []certificatesv1beta1.KeyUsage ) bool {
120
+ l := sets .NewString ()
121
+ for _ , s := range left {
122
+ l .Insert (string (s ))
123
+ }
124
+ r := sets .NewString ()
125
+ for _ , s := range right {
126
+ r .Insert (string (s ))
127
+ }
128
+ return l .Equal (r )
31
129
}
0 commit comments