in pkg/provider/provider.go [663:760]
func fetchCertChains(data []byte) ([]byte, error) {
var newCertChain []*x509.Certificate
var pemData []byte
nodes := make([]*node, 0)
currData := data
for {
// decode pem to der first
block, rest := pem.Decode(currData)
currData = rest
if block == nil {
break
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return pemData, err
}
// this should not be the case because ParseCertificate should return a non nil
// certificate when there is no error.
if cert == nil {
return pemData, fmt.Errorf("certificate is nil")
}
nodes = append(nodes, &node{
cert: cert,
parent: nil,
isParent: false,
})
}
// at the end of this computation, the output will be a single linked list
// the tail of the list will be the root node (which has no parents)
// the head of the list will be the leaf node (whose parent will be intermediate certs)
// (head) leaf -> intermediates -> root (tail)
for i := range nodes {
for j := range nodes {
// ignore same node to prevent generating a cycle
if i == j {
continue
}
// a leaf cert SubjectKeyId is optional per RFC3280
if nodes[i].cert.AuthorityKeyId == nil && nodes[j].cert.SubjectKeyId == nil {
continue
}
// if ith node AuthorityKeyId is same as jth node SubjectKeyId, jth node was used
// to sign the ith certificate
if string(nodes[i].cert.AuthorityKeyId) == string(nodes[j].cert.SubjectKeyId) {
nodes[j].isParent = true
nodes[i].parent = nodes[j]
break
}
}
}
var leaf *node
for i := range nodes {
if !nodes[i].isParent {
// this is the leaf node as it's not a parent for any other node
// TODO (aramase) handle errors if there are more than 1 leaf nodes
leaf = nodes[i]
break
}
}
if leaf == nil {
return nil, fmt.Errorf("no leaf found")
}
processedNodes := 0
// iterate through the directed list and append the nodes to new cert chain
for leaf != nil {
processedNodes++
// ensure we aren't stuck in a cyclic loop
if processedNodes > len(nodes) {
return pemData, fmt.Errorf("constructing chain resulted in cycle")
}
newCertChain = append(newCertChain, leaf.cert)
leaf = leaf.parent
}
if len(nodes) != len(newCertChain) {
klog.Warning("certificate chain is not complete due to missing intermediate/root certificates in the cert from key vault")
// if we're unable to construct the full chain, return the original order we got from the key vault
return data, nil
}
for _, cert := range newCertChain {
b := &pem.Block{
Type: types.CertificateType,
Bytes: cert.Raw,
}
pemData = append(pemData, pem.EncodeToMemory(b)...)
}
return pemData, nil
}