istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/csrctrl/signer/signer.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  
    15  // Package signer implements a CA signer that uses keys stored on local disk.
    16  package signer
    17  
    18  import (
    19  	"bytes"
    20  	"crypto/x509"
    21  	"encoding/pem"
    22  	"fmt"
    23  	"time"
    24  
    25  	capi "k8s.io/api/certificates/v1"
    26  
    27  	"istio.io/istio/pkg/test/csrctrl/authority"
    28  	"istio.io/istio/security/pkg/pki/util"
    29  )
    30  
    31  type Signer struct {
    32  	caProvider *caProvider
    33  	CertTTL    time.Duration
    34  }
    35  
    36  func NewSigner(signerRoot, signerName string, certificateDuration time.Duration) (*Signer, error) {
    37  	caProvider, err := newCAProvider(signerRoot, signerName)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	ret := &Signer{
    43  		caProvider: caProvider,
    44  		CertTTL:    certificateDuration,
    45  	}
    46  	return ret, nil
    47  }
    48  
    49  func (s *Signer) Sign(x509cr *x509.CertificateRequest, usages []capi.KeyUsage, requestedLifetime time.Duration, appendRootCert bool) ([]byte, error) {
    50  	currCA, err := s.caProvider.currentCA()
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	der, err := currCA.Sign(x509cr.Raw, authority.PermissiveSigningPolicy{
    55  		TTL:    requestedLifetime,
    56  		Usages: usages,
    57  	})
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	_, err = x509.ParseCertificate(der)
    63  	if err != nil {
    64  		return nil, fmt.Errorf("error decoding DER certificate bytes: %s", err.Error())
    65  	}
    66  
    67  	pemBytes := bytes.NewBuffer([]byte{})
    68  	err = pem.Encode(pemBytes, &pem.Block{Type: "CERTIFICATE", Bytes: der})
    69  	if err != nil {
    70  		return nil, fmt.Errorf("error encoding certificate PEM: %s", err.Error())
    71  	}
    72  
    73  	intermediateCerts, err := util.AppendRootCerts(pemBytes.Bytes(), s.caProvider.caIntermediate.CertFile)
    74  	if err != nil {
    75  		return nil, fmt.Errorf("failed to append intermediate certificates (%v)", err)
    76  	}
    77  	if appendRootCert {
    78  		rootCerts, err := util.AppendRootCerts(intermediateCerts, s.caProvider.caLoader.CertFile)
    79  		if err != nil {
    80  			return nil, fmt.Errorf("failed to append root certificates (%v)", err)
    81  		}
    82  		return rootCerts, nil
    83  	}
    84  	return intermediateCerts, nil
    85  }
    86  
    87  func (s *Signer) GetRootCerts() string {
    88  	return s.caProvider.caLoader.CertFile
    89  }