Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ Built on STIX 2.1 compliance, it uses Zod schemas and TypeScript types to ensure

- **Type-Safe Data Parsing**: ADM validates STIX 2.1 bundles using Zod schemas, ensuring data model compliance and type safety.
- **Easy Relationship Navigation**: Each object instance contains pointers to related objects, simplifying the process of navigating between techniques, tactics, and other ATT&CK elements.
- **Supports Multiple Data Sources**: Load ATT&CK datasets from different sources, including GitHub, local files, URLs, and TAXII 2.1 servers (more data sources in development).
- **Supports Multiple Content Origins**: Load ATT&CK datasets from different content origins, including GitHub, local files, URLs, and TAXII 2.1 servers (more content origins in development).
- Parsing, validation, and serialization of ATT&CK data
- ES6 classes for object-oriented data manipulation

## Supported Data Sources
## Supported Content Origins

- **`attack`**: Load ATT&CK data from the official MITRE ATT&CK STIX 2.1 GitHub repository. This serves as the source of truth for MITRE ATT&CK content.
- **`mitre`**: Load ATT&CK data from the official MITRE ATT&CK STIX 2.1 GitHub repository. This serves as the source of truth for MITRE ATT&CK content.
- **`file`**: Load ATT&CK data from a local JSON file containing a STIX 2.1 bundle.
- **`url`**: Load ATT&CK data from a URL endpoint serving STIX 2.1 content.
- **`taxii`**: (Coming soon) Load ATT&CK data from a TAXII 2.1 server.
Expand Down Expand Up @@ -90,17 +90,17 @@ For most users, we recommend:

Example of loading the latest ATT&CK data:
```javascript
import { registerDataSource, loadDataModel, DataSourceRegistration } from '@mitre-attack/attack-data-model';
import { registerContentOrigin, loadDataModel, ContentOriginRegistration } from '@mitre-attack/attack-data-model';

const dataSource = new DataSourceRegistration({
source: 'attack',
const contentOrigin = new ContentOriginRegistration({
source: 'mitre',
domain: 'enterprise-attack',
version: '17.1',
parsingMode: 'strict'
});

const dataSource = await registerDataSource(dataSource);
const attackEnterpriseLatest = loadDataModel(dataSource);
const dataSourceId = await registerContentOrigin(contentOrigin);
const attackEnterpriseLatest = loadDataModel(dataSourceId);
```

For more details on version compatibility, see the [Compatibility Guide](./COMPATIBILITY.md).
Expand Down Expand Up @@ -132,21 +132,21 @@ For additional context about the ATT&CK specification, please refer to the [ATT&
Here's an example script that demonstrates how to use the ADM library to load ATT&CK data from the official MITRE ATT&CK GitHub repository:

```typescript
import { registerDataSource, loadDataModel, DataSourceRegistration } from '@mitre-attack/attack-data-model';
import { registerContentOrigin, loadDataModel, ContentOriginRegistration } from '@mitre-attack/attack-data-model';

(async () => {

// Instantiating a DataSourceRegistration object will validate that the data source is accessible and readable
const dataSource = new DataSourceRegistration({
source: 'attack', // Built-in index to retrieve ATT&CK content from the official MITRE ATT&CK STIX 2.1 GitHub repository
// Instantiating a ContentOriginRegistration object will validate that the content origin is accessible and readable
const contentOrigin = new ContentOriginRegistration({
source: 'mitre', // Built-in index to retrieve ATT&CK content from the official MITRE ATT&CK STIX 2.1 GitHub repository
domain: 'enterprise-attack',
version: '15.1', // Omitting 'version' will default to the latest version available in the repository
parsingMode: 'relaxed' // 'strict' or 'relaxed' - 'relaxed' mode will attempt to parse and serialize data even if it contains errors or warnings
});

try {
// Register the data source and retrieve the unique ID
const uuid = await registerDataSource(dataSource);
// Register the content origin and retrieve the unique ID
const uuid = await registerContentOrigin(contentOrigin);
if (uuid) {
// Load the dataset using the unique ID
const attackEnterpriseLatest = loadDataModel(uuid);
Expand Down Expand Up @@ -217,7 +217,7 @@ For more detailed examples, please refer to the [examples](./examples/README.md)

## How It Works

1. **Data Registration**: Datasets are registered via `registerDataSource`. You specify the source of the data (e.g., `attack`, `file`, `url`, `taxii`) and provide any necessary options (such as `domain` and `version` for ATT&CK datasets). This function returns a unique identifier for the registered data source.
1. **Content Origin Registration**: Datasets are registered via `registerContentOrigin`. You specify the content origin (e.g., `mitre`, `file`, `url`, `taxii`) and provide any necessary options (such as `domain` and `version` for ATT&CK datasets). This function returns a unique identifier for the registered content origin.
2. **Data Loading**: The `loadDataModel` function is used to load registered data models by their unique identifier.
3. **Parsing and Validation**: Once the data is loaded, it is parsed by Zod schemas, ensuring that the data conforms to the expected STIX 2.1 specification.
4. **Serialization**: Valid objects are converted into TypeScript class instances, allowing for type-safe interaction and relationship navigation.
Expand Down
43 changes: 21 additions & 22 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The ATT&CK Data Model (ADM) TypeScript API provides a structured and type-safe w
- **Type-Safe Data Parsing**: Validates STIX 2.1 data using Zod schemas, ensuring compliance with the ATT&CK Data Model.
- **Object-Oriented Interface**: Provides ES6 class wrappers for ATT&CK objects, enabling intuitive interaction and relationship navigation.
- **Relationship Mapping**: Automatically processes relationships between objects, allowing easy traversal of the ATT&CK data model.
- **Flexible Data Sources**: Supports loading data from various sources, including the official MITRE ATT&CK GitHub repository, local files, URLs, and TAXII 2.1 servers (some data sources are under development).
- **Flexible Content Origins**: Supports loading data from various content origins, including the official MITRE ATT&CK GitHub repository, local files, URLs, and TAXII 2.1 servers (some content origins are under development).

## Installation

Expand Down Expand Up @@ -65,7 +65,7 @@ When installed, the library has the following directory structure:
│ ├── sdo
│ ├── smo
│ └── sro
├── data-sources
├── content-origins
├── errors
└── schemas
├── common
Expand All @@ -84,16 +84,15 @@ Each sub-package serves a specific purpose:
- **`classes`**: Contains ES6 class wrappers for ATT&CK objects, providing methods for relationship navigation and data manipulation.
- **`common`**: Base classes and shared components.
- **`sdo`**, **`smo`**, **`sro`**: Class implementations corresponding to the schemas.
- **`data-sources`**: Modules for loading ATT&CK data from various sources.
- **`content-origins`**: Modules for loading ATT&CK data from various content origins.
- **`errors`**: Custom error classes used throughout the library.

### Hierarchical Structure

The library is designed with a hierarchical structure. Every directory exports its modules through an `index.ts` file, creating a clear and organized namespace. The top-level `index.ts` file exports all components, allowing for straightforward imports:

```typescript
export * from './classes/index.js';
export * from './data-sources/index.js';
export * from './api/index.js';
export * from './errors/index.js';
export * from './schemas/index.js';
export * from './main.js';
Expand Down Expand Up @@ -210,20 +209,20 @@ console.log(attackDataModel.campaigns); // Access campaigns

### Initializing with Data

To use the `AttackDataModel`, you need to load it with data from a data source:
To use the `AttackDataModel`, you need to load it with data from a content origin:

```typescript
import { registerDataSource, loadDataModel, DataSource } from '@mitre-attack/attack-data-model';
import { registerContentOrigin, loadDataModel, ContentOriginRegistration } from '@mitre-attack/attack-data-model';

(async () => {
const dataSource = new DataSource({
source: 'attack',
const contentOrigin = new ContentOriginRegistration({
source: 'mitre',
domain: 'enterprise-attack',
version: '15.1',
parsingMode: 'relaxed',
});

const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const attackDataModel = loadDataModel(uuid);

// Now you can interact with the data model
Expand Down Expand Up @@ -289,31 +288,31 @@ console.log(campaign.name);
const techniques = campaign.getTechniques();
```

## Data Sources
## Content Origins

The library supports loading data from various sources through the `DataSource` class.
The library supports loading data from various content origins through the `ContentOriginRegistration` class.

### Supported Data Sources
### Supported Content Origins

- **`attack`**: Official MITRE ATT&CK STIX 2.1 GitHub repository.
- **`mitre`**: Official MITRE ATT&CK STIX 2.1 GitHub repository.
- **`file`**: (Coming soon) Local JSON files containing STIX 2.1 bundles.
- **`url`**: (Coming soon) URLs serving STIX 2.1 content.
- **`taxii`**: (Coming soon) TAXII 2.1 servers.

### Loading Data from the ATT&CK GitHub Repository

```typescript
import { registerDataSource, loadDataModel, DataSource } from '@mitre-attack/attack-data-model';
import { registerContentOrigin, loadDataModel, ContentOriginRegistration } from '@mitre-attack/attack-data-model';

(async () => {
const dataSource = new DataSource({
source: 'attack',
const contentOrigin = new ContentOriginRegistration({
source: 'mitre',
domain: 'enterprise-attack',
version: '15.1',
parsingMode: 'relaxed',
});

const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const attackDataModel = loadDataModel(uuid);

// Access ATT&CK objects
Expand Down Expand Up @@ -400,18 +399,18 @@ try {

## Advanced Usage

### Custom Data Sources
### Custom Content Origins

You can create custom data sources by extending the `DataSource` class or by providing your own data loading logic.
You can create custom content origins by extending the `ContentOriginRegistration` class or by providing your own data loading logic.

```typescript
import { DataSource } from '@mitre-attack/attack-data-model';

class CustomDataSource extends DataSource {
class CustomContentOrigin extends ContentOriginRegistration {
// Implement custom data loading logic
}

const customDataSource = new CustomDataSource({
const customContentOrigin = new CustomContentOrigin({
source: 'custom',
// ... other options
});
Expand Down
46 changes: 23 additions & 23 deletions docusaurus/docs/how-to-guides/manage-data-sources.mdx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import WorkInProgressNotice from '@site/src/components/WorkInProgressNotice';

# How to Manage Data Sources
# How to Manage Content Origins

<WorkInProgressNotice />

**Switch between different ATT&CK data sources efficiently**
**Switch between different ATT&CK content origins efficiently**

This guide shows you how to manage multiple ATT&CK data sources, switch between different versions, and work with local files, URLs, and the official repository.
This guide shows you how to manage multiple ATT&CK content origins, switch between different versions, and work with local files, URLs, and the official repository.

## Problem Scenarios

Expand All @@ -15,30 +15,30 @@ Use this guide when you need to:
- Switch between different ATT&CK versions for compatibility testing
- Load ATT&CK data from local files instead of the internet
- Fetch data from custom URLs or mirrors
- Manage multiple data sources in a production application
- Cache and reuse data sources efficiently
- Manage multiple content origins in a production application
- Cache and reuse content origins efficiently

## Switch Between ATT&CK Versions

### Compare Multiple Versions

```typescript
import { registerDataSource, loadDataModel, DataSource } from '@mitre-attack/attack-data-model';
import { registerContentOrigin, loadDataModel, ContentOriginRegistration } from '@mitre-attack/attack-data-model';

async function compareVersions() {
const versions = ['15.0', '15.1'];
const models: { [version: string]: any } = {};

// Load multiple versions
for (const version of versions) {
const dataSource = new DataSource({
source: 'attack',
const contentOrigin = new ContentOriginRegistration({
source: 'mitre',
domain: 'enterprise-attack',
version: version,
parsingMode: 'relaxed'
});

const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
models[version] = loadDataModel(uuid);
}

Expand All @@ -55,7 +55,7 @@ async function compareVersions() {
```typescript
// Omit version to get the latest available
const latestDataSource = new DataSource({
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
// No version specified = latest
parsingMode: 'relaxed'
Expand Down Expand Up @@ -130,7 +130,7 @@ async function loadFromUrl() {

```typescript
async function loadWithAuth() {
const dataSource = new DataSource({
const contentOrigin = new ContentOriginRegistration({
source: 'url',
url: 'https://private-server.com/attack-data.json',
requestOptions: {
Expand All @@ -142,7 +142,7 @@ async function loadWithAuth() {
parsingMode: 'strict'
});

const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
return loadDataModel(uuid);
}
```
Expand All @@ -157,7 +157,7 @@ class AttackDataManager {

async registerSource(name: string, config: any): Promise<string> {
const dataSource = new DataSource(config);
const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
this.dataSources.set(name, uuid);
return uuid;
}
Expand All @@ -173,22 +173,22 @@ class AttackDataManager {
async setupCommonSources() {
// Enterprise latest
await this.registerSource('enterprise-latest', {
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
parsingMode: 'relaxed'
});

// Enterprise v15.0
await this.registerSource('enterprise-v15', {
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
version: '15.0',
parsingMode: 'relaxed'
});

// Mobile latest
await this.registerSource('mobile-latest', {
source: 'attack',
source: 'mitre',
domain: 'mobile-attack',
parsingMode: 'relaxed'
});
Expand All @@ -212,13 +212,13 @@ async function loadWithFallback() {
const fallbackSources = [
// Try latest first
{
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
parsingMode: 'relaxed'
},
// Fallback to specific version
{
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
version: '15.1',
parsingMode: 'relaxed'
Expand All @@ -234,7 +234,7 @@ async function loadWithFallback() {
for (const config of fallbackSources) {
try {
const dataSource = new DataSource(config);
const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const model = loadDataModel(uuid);

console.log(`Successfully loaded from source: ${config.source}`);
Expand All @@ -256,7 +256,7 @@ async function loadWithFallback() {
async function validateDataSource(config: any): Promise<boolean> {
try {
const dataSource = new DataSource(config);
const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const model = loadDataModel(uuid);

// Basic validation checks
Expand Down Expand Up @@ -303,7 +303,7 @@ class CachedDataManager {
// Load fresh data
console.log('🌐 Loading fresh data');
const dataSource = new DataSource(config);
const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const model = loadDataModel(uuid);

// Cache the result
Expand All @@ -330,7 +330,7 @@ function getDataSourceConfig(): any {
switch (environment) {
case 'production':
return {
source: 'attack',
source: 'mitre',
domain: 'enterprise-attack',
version: '15.1', // Pin version in production
parsingMode: 'strict' // Strict validation in production
Expand Down Expand Up @@ -370,7 +370,7 @@ async function loadWithMonitoring(config: any) {
console.log('📡 Starting data source load:', config.source);

const dataSource = new DataSource(config);
const uuid = await registerDataSource(dataSource);
const uuid = await registerContentOrigin(contentOrigin);
const model = loadDataModel(uuid);

const loadTime = Date.now() - startTime;
Expand Down
Loading