Explore the Attack Surface Management type system
The Surface Command model is a network of strongly-typed entities and their relationships. The type system that defines these entities and their interconnections is dynamic and extensible. Surface Command uses OpenAPI to describe each entity type’s schema, including its relationships to other types. When data is imported from a source, each entity is validated against the schema for the corresponding source type.
The type system includes unified types that support common, consistent behavior. Users can write queries using unified types for a generic, standardized view of the data (for example, viewing endpoint properties across different endpoint detection and response (EDR) systems), or use source types to query specific properties. Unified types also enable correlation, which groups multiple source entities that represent the same physical object.
Types are defined as part of a connector. To learn more about creating and installing connectors, see Build custom connectors with the SDK and Connectors respectively.
Type definition structure
Each type definition includes:
- Metadata: ID, title, description, keys, and Surface Command-specific flags
- Property definitions
- Optional derived and virtual properties
- UI hints for table and detail views
OpenAPI schema
A Surface Command type definition is an OpenAPI schema, with annotations and extensions (x-samos-*) that are used to define the graph behavior. The type definition is a single file in YAML format.
Many security products already provide OpenAPI or Swagger definitions for their REST APIs, including schemas to describe the return data. These OpenAPI or Swagger schemas can be incorporated by reference into a Surface Command type. To do this, the connector includes a copy of the OpenAPI or Swagger definition as a “reference-schema” file, and references the relevant data schema using a $ref directive in the type definition. The resulting type consists of the reference schema, with the type definition “overlay” applied.
Typically, a connector uses a reference-schema document (the security product’s schema) and a type file that overlays Surface Command annotations (x-samos-*). The type file is a complete OpenAPI document that may reference the product schema with $ref and define or annotate properties.
Example:
The NIST NVD API includes a JSON file that includes the schema definition for a cve_item. A connector for NVD can include and reference that JSON schema file, and a type definition can incorporate all the properties of the cve_item to build a Surface Command type (extended and annotated with the x-samos-* attributes described in this document).
x-samos-type-name: NistCVE
x-samos-namespace: nist.nvd
title: CVE
description: Common Vulnerabilities and Exposures, from the NIST National Vulnerability Database
$ref: https://csrc.nist.gov/.../cve_api_json_2.0.schema#/definitions/cve_itemThe x-samos-type-name defines the name of the type as it appears in Surface Command. The x-samos-namespace is generated from the ID of the connector. Every type should also have title and description.
Keys and immutable properties
Keys are top-level properties that identify the entity, like a Primary Key column in a relational database table. A type must have at least one key, which is immutable and required (not nullable). The key values do not need to be globally unique across all data, only within this type’s data per connector profile. Additional keys support referencing from other entities.
Example:
x-samos-type-name: MyEndpointAgent
x-samos-keys:
- id
required:
- id
properties:
id:
title: Agent ID
description: Unique identifier for the device
type: string
x-samos-immutable: trueReferences
Any property can be marked as being a reference. The value of this property is used as a pointer to the key of some other entity. In the unified asset model, references create relationships between entities by identifying target types and keys.
Example:
properties:
cves:
title: CVEs
type: array
items:
type: string
x-samos-ref-types:
- type-name: Vulnerability
key-name: idDerived properties
Derived properties provide expressions that are evaluated to build values that aren’t in the raw type content but are convenient for reference or display. These properties are computed at import time using one of three supported syntaxes: jsonpath, jmespath, or expression.
Example (jsonpath):
The jsonpath syntax is suitable for addressing, extracting, and combining portions of the original content in flexible ways. It also includes a few extension functions for common operations. To learn more about the syntax, see the documentation .
x-samos-derived-properties:
num_macs:
title: MAC Count
type: integer
syntax: jsonpath
value: "$.macs.`len`"Example (jmespath):
The jmespath syntax has similar capabilities to jsonpath. To learn more about the jmespath syntax, see the website .
x-samos-derived-properties:
num_macs:
title: "MAC Count"
type: integer
syntax: jmespath
value: "length(macs)"Example (expression):
A simple expression-substitution language where you can combine string values from existing properties. To learn more about this, see the Python f-strings syntax documentation.
const:
type: string
syntax: expression
value: "{id} (from {source})"Hidden and excluded properties
Use x-samos-hidden for properties that are not shown in the interface but should still be queryable. Use x-samos-exclude to avoid indexing large, unnecessary data.
Example:
properties:
# internal-use API data, no need to display
api_version_uuid:
type: string
x-samos-hidden: true
# base-64 blob data, not necessary to index
b64_object_data:
type: object
x-samos-exclude: trueInterface configuration
Two annotations at the top level of the type are used to define the user interface layout. Each consists of a list of property names. These names can be top-level properties in the schema, nested properties (address.street for an object property address that has a nested property street), or derived properties.
x-samos-table: Properties to show in the default table view, shown when querying for this type.x-samos-detail: Properties to show in the detail view, shown when an entity of this type is selected.
Inheritance and unified types
Unified types standardize queries, support correlation, and allow you to reference properties that are common across types. A source type can extend multiple unified types as long as there’s no circular references.
Example:
x-samos-extends-types:
- type-name: Machine
subtype-priority: 4There are two kinds of unified types:
- Base types, which have common properties for a generic object in the model. Base types often define a primary key and are able to be correlated.
- Mix-in types, which have common properties to several different base types (for example, properties that allow tagging).
Fulfilling unified properties
The goal of the unified model is to give users a consistent, simplified view across the data from multiple security tools. It helps users (and connector authors) write queries independently from the available data sources. For example, queries for machines without EDR active or machines that have a high-severity vulnerability can be written using only the unified types. These queries don’t need to depend on whether you have installed the connectors for any specific EDR system, more than one EDR system, or any particular threat intelligence source.
The type system includes two ways to map from a source type’s data model onto the unified model: fulfills and virtual properties.
Fulfills
When a source property fulfills a property of an unified type, the value is available for query under both the original property name (on the source type) and also the property name on the unified type. The source property is aliased to the unified name. Fulfilled properties allow a source type to provide values for a property of an unified type.
For example, the Machine unified type has a property hostnames, which is an array of strings representing the hostnames for the machine. This property should be populated by each of the source Machine types. To do that, the corresponding property in the source type should be marked as fulfilling the base property:
properties:
computerDnsName:
type: string
x-samos-fulfills:
type-name: Machine
property-name: hostnamesFulfills criteria:
- Array properties can be fulfilled by single-valued (scalar) properties on the source type but scalar properties cannot be fulfilled by array properties.
- Fulfilling unified properties is optional but recommended. A source type must fulfill at least one of the base type’s key properties.
- If the appropriate value for a unified property isn’t directly available in the source data, derived properties can be used to fulfill the base.
- Enumerated lists, such as operating system family or severity, can be mapped using the
enumtype.
Virtual Properties
When data structures differ, virtual properties can fulfill unified types. Virtual properties are implemented as queries. For example, the Machine unified type has a vulnerabilities property, which is a list of its vulnerabilities. Rather than populating this explicitly with data from the vulnerability source, a query can access the model’s source content to resolve the value.
Correlation
Unified types that can be correlated (x-samos-correlatable: true) allow Surface Command to match and merge source entities into a single logical entity.
For example, a source Machine record from Active Directory can be matched with source records from ServiceNow and Rapid7. Correlation means that these each provide a different system’s viewpoint on a single Machine entity that exists independently of the various security tools. The unified entity collects the best available view of this machine. The rules for which property takes priority are defined in the unified type and are configurable.
Correlation keys are property values from each of the relevant source types. If a unified type is able to be correlated, then each source type must provide at least one correlation key. Where correlation keys match, the source entities are joined into the correlated unified entity.
The set of available correlation keys is defined in sys.correlation-key values pre-installed into Surface Command. For example, a machine with a MAC address, a plain hostname, and an X.500 DN might declare all three as correlation keys:
properties:
distinguishedName:
title: DN
x-samos-immutable: true
x-samos-fulfills:
type-name: core.component
property-name: id
x-samos-correlation:
correlation-key: Machine.x500-dn
correlation-type: Machine
priority: 4
hostname:
title: Name
x-samos-fulfills:
type-name: core.named-object
property-name: name
x-samos-correlation:
correlation-key: Machine.unqualified-hostname
correlation-type: Machine
priority: 3
mac:
title: MAC Addresses
x-samos-correlation:
correlation-key: MacAddr.value
correlation-type: Machine
priority: 3Correlation display priority
Correlated entities are often treated as a single object for display and searching. Two settings determine which source value is chosen in these situations.
First, each property in the unified type has a x-samos-best-rule-type property that defines the algorithm used to select a single source value for display. The options for this property are:
priority: the default behavior. The top property is chosen according to thesubtype-priorityof the correlated type. If there are multiple source records with the same type, the most recent is chosen.max-value: choose the maximum value from among the source records.min-value: choose the minimum value from among the source records.most-recent: choose the value from the most recently-updated source record.prefer-true: if any source value istrue, the top value is settrue.prefer-false: if any source value isfalse, the top value is setfalse.
An example of this can be found in the Vulnerability type. If any source of vulnerability information says that it has been exploited in the wild, the property should show as true in a result table, in the General tab on the asset details panel, and in searches.
properties:
is_exploited:
type: boolean
title: Exploited
x-samos-best-rule-type: "prefer-true"Second, the subtype priority indicates the overall priority of a source. This is set on each source type. For example, when extending a correlated type such as Machine:
x-samos-extends-types:
- type-name: Machine
subtype-priority: 4The following convention is used for subtype priority levels. The highest level (7) is reserved for user values. The lower levels are suitable for sources that are not the primary authoritative data.
| Priority | Description |
|---|---|
| 7 | Data that represents a user override (not from an API connector) |
| 6 | Definitive values provided by the system that manages this object (for example, cloud infrastructure) |
| 5 | Physical data discovered locally (for example, by an endpoint agent) |
| 4 | Physical data discovered remotely (for example, by a network scanner) |
| 3 | Normative catalog data |
| 2 | Non-normative catalog data |
| 1 | Other |