Skip to content

Commit

Permalink
add matched indices
Browse files Browse the repository at this point in the history
Signed-off-by: linus-sun <[email protected]>
  • Loading branch information
linus-sun committed Nov 19, 2024
1 parent 1253656 commit 8698c76
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 13 deletions.
45 changes: 38 additions & 7 deletions pkg/ct/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ func GetCTLogEntries(logClient *ctclient.LogClient, startIndex int, endIndex int
return entries, nil
}

func ScanEntryCertSubject(logEntry ct.LogEntry, monitoredCertIDs []identity.CertificateIdentity) ([]*identity.LogEntry, error) {
func ScanEntryCertSubject(logEntry ct.LogEntry, monitoredCertIDs []identity.CertificateIdentity) ([]identity.LogEntry, error) {
subject := logEntry.X509Cert.Subject.String()
certIssuer := logEntry.X509Cert.Issuer.String()
matchedEntries := []*identity.LogEntry{}
matchedEntries := []identity.LogEntry{}
for _, monitoredCertID := range monitoredCertIDs {
regex, err := regexp.Compile(monitoredCertID.CertSubject)
if err != nil {
Expand All @@ -54,15 +54,15 @@ func ScanEntryCertSubject(logEntry ct.LogEntry, monitoredCertIDs []identity.Cert
return nil, fmt.Errorf("error compiling regex for issuer: %v", err)
}
if regex.MatchString(certIssuer) {
matchedEntries = append(matchedEntries, &identity.LogEntry{
matchedEntries = append(matchedEntries, identity.LogEntry{
Index: logEntry.Index,
CertSubject: match,
Issuer: expectedIssuer,
})
}
}
} else {
matchedEntries = append(matchedEntries, &identity.LogEntry{
matchedEntries = append(matchedEntries, identity.LogEntry{
Index: logEntry.Index,
CertSubject: match,
})
Expand All @@ -73,16 +73,16 @@ func ScanEntryCertSubject(logEntry ct.LogEntry, monitoredCertIDs []identity.Cert
return matchedEntries, nil
}

func ScanEntryOIDExtensions(logEntry ct.LogEntry, monitoredOIDMatchers []extensions.OIDExtension) ([]*identity.LogEntry, error) {
matchedEntries := []*identity.LogEntry{}
func ScanEntryOIDExtensions(logEntry ct.LogEntry, monitoredOIDMatchers []extensions.OIDExtension) ([]identity.LogEntry, error) {
matchedEntries := []identity.LogEntry{}
cert := logEntry.X509Cert
for _, monitoredOID := range monitoredOIDMatchers {
match, _, extValue, err := identity.OIDMatchesPolicy(cert, monitoredOID.ObjectIdentifier, monitoredOID.ExtensionValues)
if err != nil {
return nil, fmt.Errorf("error with policy matching at index %d: %w", logEntry.Index, err)
}
if match {
matchedEntries = append(matchedEntries, &identity.LogEntry{
matchedEntries = append(matchedEntries, identity.LogEntry{
Index: logEntry.Index,
OIDExtension: monitoredOID.ObjectIdentifier,
ExtensionValue: extValue,
Expand All @@ -91,3 +91,34 @@ func ScanEntryOIDExtensions(logEntry ct.LogEntry, monitoredOIDMatchers []extensi
}
return matchedEntries, nil
}

func MatchedIndices(logEntries []ct.LogEntry, mvs identity.MonitoredValues) ([]identity.LogEntry, error) {
matchedEntries := []identity.LogEntry{}
for _, entry := range logEntries {
matchedCertSubjectEntries, err := ScanEntryCertSubject(entry, mvs.CertificateIdentities)
if err != nil {
return nil, err
}
matchedEntries = append(matchedEntries, matchedCertSubjectEntries...)

matchedOIDEntries, err := ScanEntryOIDExtensions(entry, mvs.OIDMatchers)
if err != nil {
return nil, err
}
matchedEntries = append(matchedEntries, matchedOIDEntries...)
}

return matchedEntries, nil
}

func IdentitySearch(client *ctclient.LogClient, startIndex int, endIndex int, mvs identity.MonitoredValues) ([]identity.LogEntry, error) {
retrievedEntries, err := GetCTLogEntries(client, startIndex, endIndex)
if err != nil {
return nil, err
}
matchedEntries, err := MatchedIndices(retrievedEntries, mvs)
if err != nil {
return nil, err
}
return matchedEntries, nil
}
139 changes: 133 additions & 6 deletions pkg/ct/monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestScanEntryCertSubject(t *testing.T) {
testCases := map[string]struct {
inputEntry ct.LogEntry
inputSubjects []identity.CertificateIdentity
expected []*identity.LogEntry
expected []identity.LogEntry
}{
"no matching subject": {
inputEntry: ct.LogEntry{
Expand All @@ -50,7 +50,7 @@ func TestScanEntryCertSubject(t *testing.T) {
},
},
inputSubjects: []identity.CertificateIdentity{},
expected: []*identity.LogEntry{},
expected: []identity.LogEntry{},
},
"matching subject": {
inputEntry: ct.LogEntry{
Expand All @@ -75,7 +75,7 @@ func TestScanEntryCertSubject(t *testing.T) {
Issuers: []string{},
},
},
expected: []*identity.LogEntry{
expected: []identity.LogEntry{
{Index: 1,
CertSubject: subjectName,
Issuer: issuerName},
Expand Down Expand Up @@ -114,7 +114,7 @@ func TestScanEntryOIDExtensions(t *testing.T) {
testCases := map[string]struct {
inputEntry ct.LogEntry
inputOIDExtensions []extensions.OIDExtension
expected []*identity.LogEntry
expected []identity.LogEntry
}{
"no matching subject": {
inputEntry: ct.LogEntry{
Expand All @@ -127,7 +127,7 @@ func TestScanEntryOIDExtensions(t *testing.T) {
ExtensionValues: []string{extValueString},
},
},
expected: []*identity.LogEntry{},
expected: []identity.LogEntry{},
},
"matching subject": {
inputEntry: ct.LogEntry{
Expand All @@ -140,7 +140,7 @@ func TestScanEntryOIDExtensions(t *testing.T) {
ExtensionValues: []string{extValueString},
},
},
expected: []*identity.LogEntry{
expected: []identity.LogEntry{
{
Index: 1,
OIDExtension: matchedAsn1OID,
Expand All @@ -167,3 +167,130 @@ func TestScanEntryOIDExtensions(t *testing.T) {
}
}
}

func TestMatchedIndices(t *testing.T) {
extCert, err := mockCertificateWithExtension(google_asn1.ObjectIdentifier{2, 5, 29, 17}, "test cert value")
if err != nil {
t.Errorf("Expected nil got %v", err)
}
unmatchedAsn1OID := asn1.ObjectIdentifier{2}
matchedAsn1OID := asn1.ObjectIdentifier{2, 5, 29, 17}
extValueString := "test cert value"
inputEntries := []ct.LogEntry{
{Index: 1,
X509Cert: &x509.Certificate{
Subject: pkix.Name{
CommonName: subjectName,
},
Issuer: pkix.Name{
CommonName: issuerName,
},
Extensions: extCert.Extensions,
},
},
}
testCases := map[string]struct {
inputEntries []ct.LogEntry
inputMonitoredValues identity.MonitoredValues
expected []identity.LogEntry
}{
"empty case": {
inputEntries: []ct.LogEntry{},
inputMonitoredValues: identity.MonitoredValues{},
expected: []identity.LogEntry{},
},
"no matching entries": {
inputEntries: inputEntries,
inputMonitoredValues: identity.MonitoredValues{
CertificateIdentities: []identity.CertificateIdentity{
{
CertSubject: "non-matched-subject",
},
},
OIDMatchers: []extensions.OIDExtension{
{
ObjectIdentifier: unmatchedAsn1OID,
ExtensionValues: []string{"unmatched extension value"},
},
},
},
expected: []identity.LogEntry{},
},
"matching certificate identity and issuer": {
inputEntries: inputEntries,
inputMonitoredValues: identity.MonitoredValues{
CertificateIdentities: []identity.CertificateIdentity{
{
CertSubject: subjectName,
Issuers: []string{issuerName},
},
},
},
expected: []identity.LogEntry{
{
Index: 1,
CertSubject: subjectName,
Issuer: issuerName,
},
},
},
"matching OID extension": {
inputEntries: inputEntries,
inputMonitoredValues: identity.MonitoredValues{
OIDMatchers: []extensions.OIDExtension{
{
ObjectIdentifier: matchedAsn1OID,
ExtensionValues: []string{extValueString},
},
},
},
expected: []identity.LogEntry{
{
Index: 1,
OIDExtension: matchedAsn1OID,
ExtensionValue: extValueString,
},
},
},
"matching certificate subject and issuer and OID extension": {
inputEntries: inputEntries,
inputMonitoredValues: identity.MonitoredValues{
CertificateIdentities: []identity.CertificateIdentity{
{
CertSubject: subjectName,
Issuers: []string{issuerName},
},
},
OIDMatchers: []extensions.OIDExtension{
{
ObjectIdentifier: matchedAsn1OID,
ExtensionValues: []string{extValueString},
},
},
},
expected: []identity.LogEntry{
{
Index: 1,
CertSubject: subjectName,
Issuer: issuerName,
},
{
Index: 1,
OIDExtension: matchedAsn1OID,
ExtensionValue: extValueString,
},
},
},
}

for _, tc := range testCases {
matchedEntries, err := MatchedIndices(tc.inputEntries, tc.inputMonitoredValues)
if err != nil {
t.Errorf("error matching indices: %v", err)
}
expected := tc.expected
if !reflect.DeepEqual(matchedEntries, expected) {
t.Errorf("received %v, expected %v", matchedEntries, expected)
}
}
}

0 comments on commit 8698c76

Please sign in to comment.