Skip to content

Commit

Permalink
added the initial implementation of the Service
Browse files Browse the repository at this point in the history
  • Loading branch information
caffix committed Sep 14, 2024
1 parent c7f392c commit a66b714
Show file tree
Hide file tree
Showing 41 changed files with 546 additions and 175 deletions.
89 changes: 77 additions & 12 deletions asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@

package open_asset_model

import (
"strings"
)

type Asset interface {
Key() string
AssetType() AssetType
JSON() ([]byte, error)
}
Expand All @@ -30,12 +35,13 @@ const (
TLSCertificate AssetType = "TLSCertificate"
ContactRecord AssetType = "ContactRecord"
Source AssetType = "Source"
Service AssetType = "Service"
)

var AssetList = []AssetType{
IPAddress, Netblock, AutonomousSystem, FQDN, NetworkEndpoint, DomainRecord,
AutnumRecord, Location, Phone, EmailAddress, Person, Organization, SocketAddress,
URL, Fingerprint, TLSCertificate, ContactRecord, Source,
URL, Fingerprint, TLSCertificate, ContactRecord, Source, Service,
}

var locationRels = map[string][]AssetType{
Expand Down Expand Up @@ -108,6 +114,7 @@ var autonomousSystemRels = map[string][]AssetType{
var fqdnRels = map[string][]AssetType{
"source": {Source},
"monitored_by": {Source},
"port": {NetworkEndpoint},
"a_record": {IPAddress},
"aaaa_record": {IPAddress},
"cname_record": {FQDN},
Expand All @@ -125,26 +132,34 @@ var tlscertRels = map[string][]AssetType{
"common_name": {FQDN},
"subject_contact": {ContactRecord},
"issuer_contact": {ContactRecord},
"subject_alt_names": {FQDN},
"san_dns_name": {FQDN},
"san_email_address": {EmailAddress},
"san_ip_address": {IPAddress},
"san_url": {URL},
"issuing_certificate": {TLSCertificate},
"issuing_certificate_url": {URL},
"ocsp_server": {URL},
}

var socketAddressRels = map[string][]AssetType{
"source": {Source},
"monitored_by": {Source},
"service": {Service},
}

var networkEndpointRels = map[string][]AssetType{
"source": {Source},
"monitored_by": {Source},
"service": {Service},
}

var urlRels = map[string][]AssetType{
"source": {Source},
"monitored_by": {Source},
"port": {SocketAddress},
"domain": {FQDN},
"ip_address": {IPAddress},
"port": {SocketAddress, NetworkEndpoint},
"service": {Service},
}

var fingerprintRels = map[string][]AssetType{
Expand All @@ -167,12 +182,49 @@ var sourceRels = map[string][]AssetType{
"contact_record": {ContactRecord},
}

// ValidRelationship returns true if the relation is valid in the taxonomy
// when outgoing from the source asset type to the destination asset type.
func ValidRelationship(src AssetType, relation string, destination AssetType) bool {
var serviceRels = map[string][]AssetType{
"source": {Source},
"monitored_by": {Source},
"fingerprint": {Fingerprint},
"certificate": {TLSCertificate},
}

// GetAssetOutgoingRelations returns the relation types allowed to be used
// when the subject is the asset type provided in the parameter.
// Providing an invalid subject causes a return value of nil.
func GetAssetOutgoingRelations(subject AssetType) []string {
relations := assetTypeRelations(subject)
if relations == nil {
return nil
}

var rtypes []string
for k := range relations {
rtypes = append(rtypes, k)
}
return rtypes
}

// GetAssetOutgoingRelations returns the relation types allowed to be used
// when the subject is the asset type provided in the parameter.
// Providing an invalid subject causes a return value of nil.
func GetTransformAssetTypes(subject AssetType, relation string) []AssetType {
relations := assetTypeRelations(subject)
if relations == nil {
return nil
}

rtype := strings.ToLower(relation)
if atypes, ok := relations[rtype]; ok {
return atypes
}
return nil
}

func assetTypeRelations(atype AssetType) map[string][]AssetType {
var relations map[string][]AssetType

switch src {
switch atype {
case IPAddress:
relations = ipRels
case Netblock:
Expand All @@ -181,6 +233,8 @@ func ValidRelationship(src AssetType, relation string, destination AssetType) bo
relations = autonomousSystemRels
case FQDN:
relations = fqdnRels
case NetworkEndpoint:
relations = networkEndpointRels
case DomainRecord:
relations = domainRecordRels
case AutnumRecord:
Expand All @@ -207,15 +261,26 @@ func ValidRelationship(src AssetType, relation string, destination AssetType) bo
relations = contactRecordRels
case Source:
relations = sourceRels
case Service:
relations = serviceRels
default:
return nil
}

return relations
}

// ValidRelationship returns true if the relation is valid in the taxonomy
// when outgoing from the source asset type to the destination asset type.
func ValidRelationship(src AssetType, relation string, destination AssetType) bool {
atypes := GetTransformAssetTypes(src, relation)
if atypes == nil {
return false
}

if atypes, ok := relations[relation]; ok {
for _, atype := range atypes {
if atype == destination {
return true
}
for _, atype := range atypes {
if atype == destination {
return true
}
}
return false
Expand Down
11 changes: 8 additions & 3 deletions certificate/tls_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// TLSCertificate represents a TLS Certificate asset
type TLSCertificate struct {
Raw string `json:"raw,omitempty"`
Version int `json:"version"`
Version string `json:"version"`
SerialNumber string `json:"serial_number"`
SubjectCommonName string `json:"subject_common_name"`
IssuerCommonName string `json:"issuer_common_name"`
Expand All @@ -28,12 +28,17 @@ type TLSCertificate struct {
AuthorityKeyID string `json:"authority_key_id"`
}

// AssetType returns the asset type.
// Key implements the Asset interface.
func (t TLSCertificate) Key() string {
return t.SerialNumber
}

// AssetType implements the Asset interface.
func (t TLSCertificate) AssetType() model.AssetType {
return model.TLSCertificate
}

// JSON returns the JSON encoding of the struct.
// JSON implements the Asset interface.
func (t TLSCertificate) JSON() ([]byte, error) {
return json.Marshal(t)
}
57 changes: 34 additions & 23 deletions certificate/tls_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,51 @@ package certificate

import (
"testing"
"time"

model "github.com/owasp-amass/open-asset-model"
)

func TestTLSCertificate(t *testing.T) {
cert := TLSCertificate{
SubjectCommonName: "www.example.org",
IssuerCommonName: "DigiCert TLS RSA SHA256 2020 CA1",
NotBefore: time.Date(2023, 1, 13, 12, 0, 0, 0, time.UTC),
NotAfter: time.Date(2024, 2, 13, 11, 59, 59, 0, time.UTC),
FingerprintSHA1: "F2AAD73D32683B716D2A7D61B51C6D5764AB3899",
FingerprintSHA256: "5EF2F214260AB8F58E55EEA42E4AC04B0F171807D8D1185FDDD67470E9AB6096",
}
func TestTLSCertificateKey(t *testing.T) {
want := "12345"
cert := TLSCertificate{SerialNumber: want}

if cert.SubjectCommonName != "www.example.org" {
t.Errorf("Failed to set the Subject Common Name field: %s", cert.SubjectCommonName)
if got := cert.Key(); got != want {
t.Errorf("TLSCertificate.Key() = %v, want %v", got, want)
}
}

if cert.IssuerCommonName != "DigiCert TLS RSA SHA256 2020 CA1" {
t.Errorf("Failed to set the Issuer Common Name field: %s", cert.IssuerCommonName)
}
func TestTLSCertificateAssetType(t *testing.T) {
var _ model.Asset = TLSCertificate{} // Verify proper implementation of the Asset interface
var _ model.Asset = (*TLSCertificate)(nil) // Verify the pointer properly implements the Asset interface.

if cert.NotBefore != time.Date(2023, 1, 13, 12, 0, 0, 0, time.UTC) {
t.Errorf("Failed to set the Not Before field: %s", cert.NotBefore)
cert := TLSCertificate{}
want := model.TLSCertificate

if got := cert.AssetType(); got != want {
t.Errorf("TLSCertificate.AssetType() = %v, want %v", got, want)
}
}

if cert.NotAfter != time.Date(2024, 2, 13, 11, 59, 59, 0, time.UTC) {
t.Errorf("Failed to set the Not After field: %s", cert.NotAfter)
func TestTLSCertificateJSON(t *testing.T) {
cert := TLSCertificate{
SubjectCommonName: "www.example.org",
IssuerCommonName: "DigiCert TLS RSA SHA256 2020 CA1",
NotBefore: "2006-01-02T15:04:05Z07:00",
NotAfter: "2006-01-02T15:04:05Z07:00",
}

if cert.FingerprintSHA1 != "F2AAD73D32683B716D2A7D61B51C6D5764AB3899" {
t.Errorf("Failed to set the FingerprintSHA1 field: %s", cert.FingerprintSHA1)
// test AssetType method
if cert.AssetType() != model.TLSCertificate {
t.Errorf("Expected asset type %s, but got %s", model.TLSCertificate, cert.AssetType())
}

if cert.FingerprintSHA256 != "5EF2F214260AB8F58E55EEA42E4AC04B0F171807D8D1185FDDD67470E9AB6096" {
t.Errorf("Failed to set the FingerprintSHA256 field: %s", cert.FingerprintSHA256)
// test JSON method
expectedJSON := `{"version":"","serial_number":"","subject_common_name":"www.example.org","issuer_common_name":"DigiCert TLS RSA SHA256 2020 CA1","not_before":"2006-01-02T15:04:05Z07:00","not_after":"2006-01-02T15:04:05Z07:00","key_usage":null,"signature_algorithm":"","public_key_algorithm":"","is_ca":false,"crl_distribution_points":null,"subject_key_id":"","authority_key_id":""}`
json, err := cert.JSON()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if string(json) != expectedJSON {
t.Errorf("Expected JSON %s, but got %s", expectedJSON, string(json))
}
}
15 changes: 10 additions & 5 deletions contact/contact_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ type ContactRecord struct {
DiscoveredAt string `json:"discovered_at,omitempty"`
}

// AssetType returns the asset type.
func (r ContactRecord) AssetType() model.AssetType {
// Key implements the Asset interface.
func (cr ContactRecord) Key() string {
return cr.DiscoveredAt
}

// AssetType implements the Asset interface.
func (cr ContactRecord) AssetType() model.AssetType {
return model.ContactRecord
}

// JSON returns the JSON representation of the asset.
func (r ContactRecord) JSON() ([]byte, error) {
return json.Marshal(r)
// JSON implements the Asset interface.
func (cr ContactRecord) JSON() ([]byte, error) {
return json.Marshal(cr)
}
12 changes: 12 additions & 0 deletions contact/contact_record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,19 @@ import (
model "github.com/owasp-amass/open-asset-model"
)

func TestContactRecordKey(t *testing.T) {
want := "https://owasp.org/contacts"
cr := ContactRecord{DiscoveredAt: want}

if got := cr.Key(); got != want {
t.Errorf("ContactRecord.Key() = %v, want %v", got, want)
}
}

func TestContactRecordAssetType(t *testing.T) {
var _ model.Asset = ContactRecord{} // Verify proper implementation of the Asset interface
var _ model.Asset = (*ContactRecord)(nil) // Verify the pointer properly implements the Asset interface.

cr := ContactRecord{}
if cr.AssetType() != model.ContactRecord {
t.Errorf("Expected asset type %s but got %s", model.ContactRecord, cr.AssetType())
Expand Down
9 changes: 7 additions & 2 deletions contact/email_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ type EmailAddress struct {
Domain string `json:"domain"`
}

// AssetType returns the asset type.
// Key implements the Asset interface.
func (e EmailAddress) Key() string {
return e.Address
}

// AssetType implements the Asset interface.
func (e EmailAddress) AssetType() model.AssetType {
return model.EmailAddress
}

// JSON returns the JSON representation of the asset.
// JSON implements the Asset interface.
func (e EmailAddress) JSON() ([]byte, error) {
return json.Marshal(e)
}
16 changes: 14 additions & 2 deletions contact/email_address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@ import (
model "github.com/owasp-amass/open-asset-model"
)

func TestEmailAddress_AssetType(t *testing.T) {
func TestEmailAddressKey(t *testing.T) {
want := "[email protected]"
e := EmailAddress{Address: want}

if got := e.Key(); got != want {
t.Errorf("EmailAddress.Key() = %v, want %v", got, want)
}
}

func TestEmailAddressAssetType(t *testing.T) {
var _ model.Asset = EmailAddress{} // Verify proper implementation of the Asset interface
var _ model.Asset = (*EmailAddress)(nil) // Verify the pointer properly implements the Asset interface.

e := EmailAddress{
Address: "[email protected]",
Username: "test",
Expand All @@ -23,7 +35,7 @@ func TestEmailAddress_AssetType(t *testing.T) {
}
}

func TestEmailAddress_JSON(t *testing.T) {
func TestEmailAddressJSON(t *testing.T) {
e := EmailAddress{
Address: "[email protected]",
Username: "test",
Expand Down
9 changes: 7 additions & 2 deletions contact/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ type Location struct {
PostalCode string `json:"postal_code,omitempty"`
}

// AssetType returns the asset type.
// Key implements the Asset interface.
func (a Location) Key() string {
return a.Address
}

// AssetType implements the Asset interface.
func (a Location) AssetType() model.AssetType {
return model.Location
}

// JSON returns the JSON representation of the asset.
// JSON implements the Asset interface.
func (a Location) JSON() ([]byte, error) {
return json.Marshal(a)
}
Loading

0 comments on commit a66b714

Please sign in to comment.