forked from kyma-incubator/compass
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cert_header_parser.go
107 lines (85 loc) · 2.7 KB
/
cert_header_parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package oathkeeper
import (
"net/http"
"regexp"
"github.com/kyma-incubator/compass/components/connector/internal/certificates"
)
//go:generate mockery -name=CertificateHeaderParser
type CertificateHeaderParser interface {
GetCertificateData(r *http.Request) (string, string, bool)
}
type certificateInfo struct {
Hash string
Subject string
}
type headerParser struct {
certHeaderName string
certificates.CSRSubjectConsts
}
func NewHeaderParser(certHeaderName string, csrSubjectConsts certificates.CSRSubjectConsts) CertificateHeaderParser {
return &headerParser{
certHeaderName: certHeaderName,
CSRSubjectConsts: csrSubjectConsts,
}
}
func (hp *headerParser) GetCertificateData(r *http.Request) (string, string, bool) {
certHeader := r.Header.Get(hp.certHeaderName)
if certHeader == "" {
return "", "", false
}
subjectRegex := regexp.MustCompile(`Subject="(.*?)"`)
hashRegex := regexp.MustCompile(`Hash=([0-9a-f]*)`)
subjects := extractFromHeader(certHeader, subjectRegex)
hashes := extractFromHeader(certHeader, hashRegex)
certificateInfos := createCertInfos(subjects, hashes)
certificateInfo, found := hp.getCertificateInfoWithMatchingSubject(certificateInfos)
if !found {
return "", "", false
}
return GetCommonName(certificateInfo.Subject), certificateInfo.Hash, true
}
func createCertInfos(subjects, hashes []string) []certificateInfo {
if len(subjects) != len(hashes) {
return []certificateInfo{}
}
certInfos := make([]certificateInfo, len(subjects))
for i := 0; i < len(subjects); i++ {
certInfo := newCertificateInfo(subjects[i], hashes[i])
certInfos[i] = certInfo
}
return certInfos
}
func (hp *headerParser) getCertificateInfoWithMatchingSubject(infos []certificateInfo) (certificateInfo, bool) {
for _, info := range infos {
if hp.isSubjectMatching(info) {
return info, true
}
}
return certificateInfo{}, false
}
func newCertificateInfo(subject, hash string) certificateInfo {
certInfo := certificateInfo{
Hash: hash,
Subject: subject,
}
return certInfo
}
func (hp *headerParser) isSubjectMatching(i certificateInfo) bool {
return GetOrganization(i.Subject) == hp.Organization && GetOrganizationalUnit(i.Subject) == hp.OrganizationalUnit &&
GetCountry(i.Subject) == hp.Country && GetLocality(i.Subject) == hp.Locality && GetProvince(i.Subject) == hp.Province
}
func extractFromHeader(certHeader string, regex *regexp.Regexp) []string {
var matchedStrings []string
matches := regex.FindAllStringSubmatch(certHeader, -1)
for _, match := range matches {
value := get(match, 1)
matchedStrings = append(matchedStrings, value)
}
return matchedStrings
}
func get(array []string, index int) string {
if len(array) > index {
return array[index]
}
return ""
}