ARO-RP/pkg/util/pki/pki.go

139 строки
3.2 KiB
Go
Исходник Обычный вид История

package pki
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"sync"
)
var caMap map[string]x509.CertPool = make(map[string]x509.CertPool)
var mu sync.RWMutex
type RootCAs struct {
RootsInfos []RootInfo `json:"RootsInfos"`
}
type RootInfo struct {
RootName string `json:"rootName"`
CaName string `json:"CaName"`
Cdp string `json:"Cdp"`
AppType string `json:"AppType"`
StoreLocation string `json:"StoreLocation"`
StoreName string `json:"StoreName"`
Body string `json:"Body"`
PEM string `json:"PEM"`
Intermediates []IntermediateInfo `json:"Intermediates"`
}
type IntermediateInfo struct {
IntermediateName string `json:"IntermediateName"`
AppType string `json:"AppType"`
Cdp string `json:"Cdp"`
StoreLocation string `json:"StoreLocation"`
StoreName string `json:"StoreName"`
Body string `json:"Body"`
PEM string `json:"PEM"`
}
// https://aka.ms/getissuers
// The v3 endpoint can be used to get ca certs
// For example https://issuer.pki.azure.com/dsms/issuercertificates?getissuersv3&caName=ame
// returns the ame certs
func FetchDataFromGetIssuerPki(url string) (*RootCAs, error) {
response, err := http.Get(url)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err != nil {
return nil, err
}
// Read in certs from endpoint
body, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}
var rootCAs RootCAs
json.Unmarshal(body, &rootCAs)
return &rootCAs, nil
}
func GetTlsCertPool(urlTemplate, caName string) (*x509.CertPool, error) {
url := fmt.Sprintf(urlTemplate, caName)
caCertPool, ok := getCaCertPoolFromMap(url)
if ok {
return &caCertPool, nil
} else {
caCertPool, err := buildCertPoolForCaName(url)
if err != nil || caCertPool == nil {
return nil, err
}
setCaCertPoolInMap(url, *caCertPool)
return caCertPool, nil
}
}
func getCaCertPoolFromMap(key string) (x509.CertPool, bool) {
mu.RLock()
defer mu.RUnlock()
caCertPool, ok := caMap[key]
return caCertPool, ok
}
func setCaCertPoolInMap(key string, caCertPool x509.CertPool) {
mu.Lock()
defer mu.Unlock()
caMap[key] = caCertPool
}
func buildCertPoolForCaName(url string) (*x509.CertPool, error) {
data, err := FetchDataFromGetIssuerPki(url)
if err != nil {
return nil, err
}
// Create a CertPool
caCertPool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}
for _, rootInfo := range data.RootsInfos {
caCert := rootInfo.PEM
// Append the custom CA certificate to the CertPool
if ok := caCertPool.AppendCertsFromPEM([]byte(caCert)); !ok {
return nil, errors.New("failed to load cert into cert pool")
}
for _, intermediate := range rootInfo.Intermediates {
intermediateCert := intermediate.PEM
// Append the custom CA certificate to the CertPool
if ok := caCertPool.AppendCertsFromPEM([]byte(intermediateCert)); !ok {
return nil, errors.New("failed to load cert into cert pool")
}
}
}
return caCertPool, nil
}