k8s.io/kubernetes@v1.29.3/pkg/apis/certificates/helpers.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package certificates
    18  
    19  import (
    20  	"crypto/x509"
    21  	"encoding/pem"
    22  	"errors"
    23  	"fmt"
    24  	"reflect"
    25  	"strings"
    26  
    27  	"k8s.io/apimachinery/pkg/util/sets"
    28  )
    29  
    30  // ParseCSR extracts the CSR from the bytes and decodes it.
    31  func ParseCSR(pemBytes []byte) (*x509.CertificateRequest, error) {
    32  	block, _ := pem.Decode(pemBytes)
    33  	if block == nil || block.Type != "CERTIFICATE REQUEST" {
    34  		return nil, errors.New("PEM block type must be CERTIFICATE REQUEST")
    35  	}
    36  	csr, err := x509.ParseCertificateRequest(block.Bytes)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	return csr, nil
    41  }
    42  
    43  var (
    44  	organizationNotSystemNodesErr = fmt.Errorf("subject organization is not system:nodes")
    45  	commonNameNotSystemNode       = fmt.Errorf("subject common name does not begin with system:node:")
    46  	dnsOrIPSANRequiredErr         = fmt.Errorf("DNS or IP subjectAltName is required")
    47  	dnsSANNotAllowedErr           = fmt.Errorf("DNS subjectAltNames are not allowed")
    48  	emailSANNotAllowedErr         = fmt.Errorf("Email subjectAltNames are not allowed")
    49  	ipSANNotAllowedErr            = fmt.Errorf("IP subjectAltNames are not allowed")
    50  	uriSANNotAllowedErr           = fmt.Errorf("URI subjectAltNames are not allowed")
    51  )
    52  
    53  var (
    54  	kubeletServingRequiredUsages = sets.NewString(
    55  		string(UsageDigitalSignature),
    56  		string(UsageKeyEncipherment),
    57  		string(UsageServerAuth),
    58  	)
    59  	kubeletServingRequiredUsagesNoRSA = sets.NewString(
    60  		string(UsageDigitalSignature),
    61  		string(UsageServerAuth),
    62  	)
    63  )
    64  
    65  func IsKubeletServingCSR(req *x509.CertificateRequest, usages sets.String) bool {
    66  	return ValidateKubeletServingCSR(req, usages) == nil
    67  }
    68  func ValidateKubeletServingCSR(req *x509.CertificateRequest, usages sets.String) error {
    69  	if !reflect.DeepEqual([]string{"system:nodes"}, req.Subject.Organization) {
    70  		return organizationNotSystemNodesErr
    71  	}
    72  
    73  	// at least one of dnsNames or ipAddresses must be specified
    74  	if len(req.DNSNames) == 0 && len(req.IPAddresses) == 0 {
    75  		return dnsOrIPSANRequiredErr
    76  	}
    77  
    78  	if len(req.EmailAddresses) > 0 {
    79  		return emailSANNotAllowedErr
    80  	}
    81  	if len(req.URIs) > 0 {
    82  		return uriSANNotAllowedErr
    83  	}
    84  
    85  	if !kubeletServingRequiredUsages.Equal(usages) && !kubeletServingRequiredUsagesNoRSA.Equal(usages) {
    86  		return fmt.Errorf("usages did not match %v", kubeletServingRequiredUsages.List())
    87  	}
    88  
    89  	if !strings.HasPrefix(req.Subject.CommonName, "system:node:") {
    90  		return commonNameNotSystemNode
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  var (
    97  	kubeletClientRequiredUsagesNoRSA = sets.NewString(
    98  		string(UsageDigitalSignature),
    99  		string(UsageClientAuth),
   100  	)
   101  	kubeletClientRequiredUsages = sets.NewString(
   102  		string(UsageDigitalSignature),
   103  		string(UsageKeyEncipherment),
   104  		string(UsageClientAuth),
   105  	)
   106  )
   107  
   108  func IsKubeletClientCSR(req *x509.CertificateRequest, usages sets.String) bool {
   109  	return ValidateKubeletClientCSR(req, usages) == nil
   110  }
   111  func ValidateKubeletClientCSR(req *x509.CertificateRequest, usages sets.String) error {
   112  	if !reflect.DeepEqual([]string{"system:nodes"}, req.Subject.Organization) {
   113  		return organizationNotSystemNodesErr
   114  	}
   115  
   116  	if len(req.DNSNames) > 0 {
   117  		return dnsSANNotAllowedErr
   118  	}
   119  	if len(req.EmailAddresses) > 0 {
   120  		return emailSANNotAllowedErr
   121  	}
   122  	if len(req.IPAddresses) > 0 {
   123  		return ipSANNotAllowedErr
   124  	}
   125  	if len(req.URIs) > 0 {
   126  		return uriSANNotAllowedErr
   127  	}
   128  
   129  	if !strings.HasPrefix(req.Subject.CommonName, "system:node:") {
   130  		return commonNameNotSystemNode
   131  	}
   132  
   133  	if !kubeletClientRequiredUsages.Equal(usages) && !kubeletClientRequiredUsagesNoRSA.Equal(usages) {
   134  		return fmt.Errorf("usages did not match %v", kubeletClientRequiredUsages.List())
   135  	}
   136  
   137  	return nil
   138  }