github.com/symfony-cli/symfony-cli@v0.0.0-20240514161054-ece2df437dfa/local/proxy/cert_store.go (about)

     1  /*
     2   * Copyright (c) 2021-present Fabien Potencier <fabien@symfony.com>
     3   *
     4   * This file is part of Symfony CLI project
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU Affero General Public License as
     8   * published by the Free Software Foundation, either version 3 of the
     9   * License, or (at your option) any later version.
    10   *
    11   * This program is distributed in the hope that it will be useful,
    12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    14   * GNU Affero General Public License for more details.
    15   *
    16   * You should have received a copy of the GNU Affero General Public License
    17   * along with this program. If not, see <http://www.gnu.org/licenses/>.
    18   */
    19  
    20  package proxy
    21  
    22  import (
    23  	"crypto/tls"
    24  	"sync"
    25  
    26  	"github.com/hashicorp/golang-lru/arc/v2"
    27  	"github.com/symfony-cli/cert"
    28  )
    29  
    30  type certStore struct {
    31  	proxyCfg *Config
    32  	ca       *cert.CA
    33  	lock     sync.Mutex
    34  	cache    *arc.ARCCache[string, tls.Certificate]
    35  }
    36  
    37  // newCertStore creates a store to keep SSL certificates in memory
    38  func (p *Proxy) newCertStore(ca *cert.CA) *certStore {
    39  	cache, _ := arc.NewARC[string, tls.Certificate](1024)
    40  	return &certStore{
    41  		proxyCfg: p.Config,
    42  		ca:       ca,
    43  		cache:    cache,
    44  	}
    45  }
    46  
    47  // getCertificate returns a valid certificate for the given domain name
    48  func (c *certStore) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
    49  	c.lock.Lock()
    50  	defer c.lock.Unlock()
    51  	name := c.proxyCfg.NormalizeDomain(clientHello.ServerName)
    52  	if val, ok := c.cache.Get(name); ok {
    53  		cert := val
    54  		return &cert, nil
    55  	}
    56  	cert, err := c.ca.CreateCert([]string{name})
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	c.cache.Add(name, cert)
    61  	return &cert, nil
    62  }