istio.io/istio@v0.0.0-20240520182934-d79c90f27776/security/pkg/pki/ra/common.go (about) 1 // Copyright Istio 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 package ra 15 16 import ( 17 "fmt" 18 "time" 19 20 clientset "k8s.io/client-go/kubernetes" 21 22 meshconfig "istio.io/api/mesh/v1alpha1" 23 "istio.io/istio/pkg/slices" 24 raerror "istio.io/istio/security/pkg/pki/error" 25 "istio.io/istio/security/pkg/pki/util" 26 caserver "istio.io/istio/security/pkg/server/ca" 27 ) 28 29 // RegistrationAuthority : Registration Authority interface. 30 type RegistrationAuthority interface { 31 caserver.CertificateAuthority 32 // SetCACertificatesFromMeshConfig sets the CACertificates using the ones from mesh config 33 SetCACertificatesFromMeshConfig([]*meshconfig.MeshConfig_CertificateData) 34 // GetRootCertFromMeshConfig returns the root cert for the specific signer in mesh config 35 GetRootCertFromMeshConfig(signerName string) ([]byte, error) 36 } 37 38 // CaExternalType : Type of External CA integration 39 type CaExternalType string 40 41 // IstioRAOptions : Configuration Options for the IstioRA 42 type IstioRAOptions struct { 43 // ExternalCAType: Integration API type with external CA 44 ExternalCAType CaExternalType 45 // DefaultCertTTL: Default Certificate TTL 46 DefaultCertTTL time.Duration 47 // MaxCertTTL: Maximum Certificate TTL that can be requested 48 MaxCertTTL time.Duration 49 // CaCertFile : File containing PEM encoded CA root certificate of external CA 50 CaCertFile string 51 // CaSigner : To indicate custom CA Signer name when using external K8s CA 52 CaSigner string 53 // VerifyAppendCA : Whether to use caCertFile containing CA root cert to verify and append to signed cert-chain 54 VerifyAppendCA bool 55 // K8sClient : K8s API client 56 K8sClient clientset.Interface 57 // TrustDomain 58 TrustDomain string 59 // CertSignerDomain info 60 CertSignerDomain string 61 } 62 63 const ( 64 // ExtCAK8s : Integrate with external CA using k8s CSR API 65 ExtCAK8s CaExternalType = "ISTIOD_RA_KUBERNETES_API" 66 67 // DefaultExtCACertDir : Location of external CA certificate 68 DefaultExtCACertDir string = "./etc/external-ca-cert" 69 ) 70 71 // ValidateCSR : Validate all SAN extensions in csrPEM match authenticated identities 72 func ValidateCSR(csrPEM []byte, subjectIDs []string) bool { 73 csr, err := util.ParsePemEncodedCSR(csrPEM) 74 if err != nil { 75 return false 76 } 77 if err := csr.CheckSignature(); err != nil { 78 return false 79 } 80 csrIDs, err := util.ExtractIDs(csr.Extensions) 81 if err != nil { 82 return false 83 } 84 for _, s1 := range csrIDs { 85 if !slices.Contains(subjectIDs, s1) { 86 return false 87 } 88 } 89 return true 90 } 91 92 // NewIstioRA is a factory method that returns an RA that implements the RegistrationAuthority functionality. 93 // the caOptions defines the external provider 94 func NewIstioRA(opts *IstioRAOptions) (RegistrationAuthority, error) { 95 if opts.ExternalCAType == ExtCAK8s { 96 istioRA, err := NewKubernetesRA(opts) 97 if err != nil { 98 return nil, fmt.Errorf("failed to create an K8s CA: %v", err) 99 } 100 return istioRA, err 101 } 102 return nil, fmt.Errorf("invalid CA Name %s", opts.ExternalCAType) 103 } 104 105 // preSign : Validation checks to execute before signing certificates 106 func preSign(raOpts *IstioRAOptions, csrPEM []byte, subjectIDs []string, requestedLifetime time.Duration, forCA bool) (time.Duration, error) { 107 if forCA { 108 return requestedLifetime, raerror.NewError(raerror.CSRError, 109 fmt.Errorf("unable to generate CA certifificates")) 110 } 111 if !ValidateCSR(csrPEM, subjectIDs) { 112 return requestedLifetime, raerror.NewError(raerror.CSRError, fmt.Errorf( 113 "unable to validate SAN Identities in CSR")) 114 } 115 // If the requested requestedLifetime is non-positive, apply the default TTL. 116 lifetime := requestedLifetime 117 if requestedLifetime.Seconds() <= 0 { 118 lifetime = raOpts.DefaultCertTTL 119 } 120 // If the requested TTL is greater than maxCertTTL, return an error 121 if requestedLifetime.Seconds() > raOpts.MaxCertTTL.Seconds() { 122 return lifetime, raerror.NewError(raerror.TTLError, fmt.Errorf( 123 "requested TTL %s is greater than the max allowed TTL %s", requestedLifetime, raOpts.MaxCertTTL)) 124 } 125 return lifetime, nil 126 }