Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge develop to main #13

Merged
merged 30 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
03c6218
re-work Docker image publishing workflow to use semver
seansica Oct 24, 2022
2ced32d
re-work Docker image publishing workflow to use semver
seansica Oct 24, 2022
03022e3
re-work Docker image publishing workflow to use semver
seansica Oct 24, 2022
693ab8b
re-work Docker image publishing workflow to use semver
seansica Oct 24, 2022
ffa84ba
re-work Docker image publishing workflow to use semver
seansica Oct 24, 2022
007382d
update TAXII dotenv template
seansica Nov 16, 2022
031b725
Modify process for publishing Docker images
seansica Jul 7, 2023
921c4b5
Change target branch ref from master to main
seansica Jul 7, 2023
2444a6a
Change org from ctid to mitre-attack in the Docker image name
seansica Jul 7, 2023
8ad8ac3
Fix docker image name
seansica Jul 7, 2023
53aa457
update docker-build.sh to load dotenv file before execution
seansica Jul 10, 2023
37afd40
Remove cache module
seansica Jul 10, 2023
d6bdfc3
Formatting
seansica Jul 10, 2023
281e2d0
Disable strict mode in AttackObject schema
seansica Jul 10, 2023
a7146ad
Refactor object-collector.service to bulkUpdate the database (instead…
seansica Jul 10, 2023
7e06731
Gitignore the entire .idea directory
seansica Jul 10, 2023
53f6384
Resolve TypeError thrown when STIX object does not belong to a collec…
seansica Jul 28, 2023
0c50500
Merge remote-tracking branch 'origin/main' into develop
seansica Aug 9, 2023
61c89db
Update documentation
seansica Apr 17, 2024
0f1205c
Update documentation
seansica Apr 18, 2024
045b5f3
Optimize the CI pipeline.
seansica Apr 18, 2024
565bba4
Refactor match query parameter processing.
seansica Apr 18, 2024
54f362b
Change default HTTP listener port to 5002
seansica Apr 23, 2024
07e7ec6
Remove unused dependencies
seansica Apr 23, 2024
8b4201d
Move DI of TaxiiLogger from TaxiiModule to AppModule.
seansica Apr 23, 2024
be45b26
Refactor ParseMatchQueryParamPipe
seansica Apr 23, 2024
ffbccc1
Remove ParseMatchQueryParamPipe from match URL query parameter proces…
seansica Apr 23, 2024
7d1aa19
Add Bruno API testing files
seansica Apr 23, 2024
57c4040
Add CI pipeline for testing the public TAXII server via Bruno
seansica Apr 23, 2024
7ae91ff
Merge pull request #16 from mitre-attack/bugfix-14-fix-behavior-of-th…
seansica Apr 23, 2024
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
29 changes: 29 additions & 0 deletions .github/workflows/api-tests-bruno.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This workflow runs the API tests for the bruno application on the latest version of Ubuntu

name: API Tests - Bruno

on:
workflow_dispatch:
permissions:
contents: read
actions: read
checks: write
jobs:
run_bruno_api_test:
name: API Tests by Bruno
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies and run tests
run: |
cd bruno
npm install
npm run test

- name: Publish Test Report
uses: dorny/test-reporter@v1
if: success() || failure() # run this step even if previous step failed
with:
name: Bruno API Tests # Name of the check run which will be created
path: bruno/report.xml # Path to test results
reporter: java-junit # Format of test results
30 changes: 22 additions & 8 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
name: publish
name: Build and Publish Docker Image

on:
push:
branches: [main, develop]
branches:
- develop
release:
types: [published]

jobs:
publish:
Expand All @@ -11,13 +15,23 @@ jobs:
- name: Check out the repo
uses: actions/checkout@v3

- name: Build the Docker image
- name: Extract tag name
if: github.event_name == 'release'
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV

- name: Validate tag
if: github.event_name == 'release'
run: |
if ! [[ "${{ env.TAG }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then
echo "Invalid tag format. The tag must follow the semantic versioning format: X.Y.Z or X.Y.Z-prerelease"
exit 1
fi

- name: Build and publish Docker image
run: |
echo $GITHUB_TOKEN | docker login ghcr.io -u mitre-attack --password-stdin
docker build . --tag ghcr.io/mitre-attack/attack-workbench-taxii-server:$TAG
docker push ghcr.io/mitre-attack/attack-workbench-taxii-server:$TAG
docker build . --tag ghcr.io/mitre-attack/attack-workbench-taxii-server:${TAG:-latest}
docker push ghcr.io/mitre-attack/attack-workbench-taxii-server:${TAG:-latest}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref == 'refs/head/main' && 'latest' || 'develop' }}


TAG: ${{ env.TAG }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
Expand Down
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ The following resources provide supporting documentation about the TAXII protoco
- [Introduction to TAXII](https://oasis-open.github.io/cti-documentation/taxii/intro.html)
- [TAXII 2.1 Specification](https://docs.oasis-open.org/cti/taxii/v2.1/os/taxii-v2.1-os.html)
- [OASIS Open TAXII Resources](https://oasis-open.github.io/cti-documentation/resources.html#taxii-21-specification)
<!-- TODO: this will need to change when the official TAXII 2.1 server is hosted and docs are migrated to attack-workbench-data -->
<!-- [accessing ATT&CK data via TAXII](https://github.com/mitre/cti/blob/master/USAGE.md#access-from-the-attck-taxii-server) -->

The ATT&CK Workbench application requires additional components for full operation.
The [ATT&CK Workbench Frontend](https://github.com/center-for-threat-informed-defense/attack-workbench-frontend)
Expand Down Expand Up @@ -55,7 +53,8 @@ The application uses Swagger UI module to dynamically document the available RES
be accessed at the path: `/api-docs`.

The [docs](/docs/README.md) folder contains additional documentation about using the TAXII Server:
- [USAGE](/docs/USAGE.md): Includes advanced details and instructions for setting up the TAXII Server.
- [SETUP](/docs/SETUP.md): Includes advanced details and instructions for setting up the TAXII Server.
- [USAGE](/docs/USAGE.md): User Guide on how to query/use the TAXII 2.1 REST API.
- [CONTRIBUTING](/docs/CONTRIBUTING.md): information about how to contribute to this project.

## Install and run
Expand Down Expand Up @@ -121,11 +120,9 @@ npm install
##### Step 3. Configure the system

The app is configured using environment variables loaded from a dotenv file. A template is provided for your convenience.
See the [USAGE](./docs/USAGE.md#environment-variables) document for a list of supported environment variables and usage
descriptions.
See the [SETUP](./docs/SETUP.md#environment-variables) document for a list of supported environment variables and usage descriptions.

Store the dotenv file in the root `config/` directory, and ensure that the `TAXII_ENV` environment variable reflects the
dotenv file name. `TAXII_ENV` determines the name of the environment variable which gets loaded by the server. For example:
Store the dotenv file in the root `config/` directory, and ensure that the `TAXII_ENV` environment variable reflects the dotenv file name. `TAXII_ENV` determines the name of the environment variable which gets loaded by the server. For example:
- If `TAXII_ENV` is equal to `dev`, then the server attempts to load `config/dev.env`.
- If `TAXII_ENV` is equal to `prod`, then the server attempts to load `config/prod.env`.

Expand Down
55 changes: 55 additions & 0 deletions bruno/Get A Collection.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
meta {
name: Get A Collection
type: http
seq: 4
}

get {
url: {{host}}/api/v21/collections/{{collectionId}}
body: none
auth: none
}

headers {
Accept: application/taxii+json;version=2.1
}

vars:pre-request {
collectionId: x-mitre-collection--dac0d2d7-8653-445c-9bff-82f934c1e858
~collectionId: x-mitre-collection--1f5f1533-f617-4ca8-9ab4-6a02367fa019
}

tests {
test("Verify response status code", function() {
expect(res.getStatus()).to.equal(200);
});

test("Verify response content type", function() {
const contentType = res.getHeader('content-type');
expect(contentType).to.include('application/stix+json');
expect(contentType).to.include('version=2.1');
});

test("Verify response body", function() {
const collection = res.getBody();

expect(collection).to.have.property('id').that.is.a('string').and.is.not.empty;

expect(collection).to.have.property('title').that.is.a('string').and.is.not.empty;

if (collection.hasOwnProperty('description')) {
expect(collection.description).to.be.a('string');
}

expect(collection).to.have.property('canRead').that.is.a('boolean');

expect(collection).to.have.property('canWrite').that.is.a('boolean');

if (collection.hasOwnProperty('mediaTypes')) {
expect(collection.mediaTypes).to.be.an('array').and.not.be.empty;
collection.mediaTypes.forEach(mediaType => {
expect(mediaType).to.be.a('string').and.include('application/taxii+json');
});
}
});
}
36 changes: 36 additions & 0 deletions bruno/Get API Root Information.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
meta {
name: Get API Root Information
type: http
seq: 2
}

get {
url: {{host}}/api/v21/
body: none
auth: none
}

headers {
Accept: application/taxii+json;version=2.1
}

tests {
test("Verify response status code", function() {
expect(res.getStatus()).to.equal(200);
});

test("Verify response content type", function() {
const contentType = res.getHeader('content-type');
expect(contentType).to.include('application/stix+json');
expect(contentType).to.include('version=2.1');
});

test("Verify response body", function() {
const data = res.getBody();
expect(data).to.have.property('title').that.is.a('string').and.is.not.empty;
expect(data).to.have.property('description').that.is.a('string').and.is.not.empty;
expect(data).to.have.property('version').that.is.a('string').and.startsWith('application/taxii+json');
expect(data).to.have.property('maxContentLength').that.is.a('string');
expect(parseInt(data.maxContentLength)).to.be.a('number').and.not.NaN;
});
}
73 changes: 73 additions & 0 deletions bruno/Get An Object.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
meta {
name: Get An Object
type: http
seq: 6
}

get {
url: {{host}}/api/v21/collections/{{collectionId}}/objects/{{objectId}}
body: none
auth: none
}

headers {
Accept: application/taxii+json;version=2.1
}

vars:pre-request {
collectionId: x-mitre-collection--dac0d2d7-8653-445c-9bff-82f934c1e858
objectId: intrusion-set--bef4c620-0787-42a8-a96d-b7eb6e85917c
}

tests {
const { validateObject } = require('./util/object-validation');

test("Verify response status code", function() {
expect(res.getStatus()).to.equal(200);
});

test("Verify response content type", function() {
const contentType = res.getHeader('content-type');
expect(contentType).to.include('application/stix+json');
expect(contentType).to.include('version=2.1');
});

test("Verify returned object ID matches requested object ID", function() {
const requestedObjectId = 'intrusion-set--bef4c620-0787-42a8-a96d-b7eb6e85917c';
const data = res.getBody();
expect(data.objects).to.be.an('array');
if (data.objects.length > 0) {
data.objects.forEach(obj => {
expect(obj.id).to.equal(requestedObjectId);
});
}
});

test("Verify object properties", function() {
const data = res.getBody();
const failedObjects = [];

expect(data.objects).to.be.an('array');

data.objects.forEach((obj, index) => {
try {
validateObject(obj);
} catch (err) {
failedObjects.push({
index: index,
object: obj,
error: err.message
});
}
});

if (failedObjects.length > 0) {
const failureMessage = `${failedObjects.length} object(s) failed validation:\n\n` +
failedObjects.map(failedObj => {
return `Index: ${failedObj.index}\nObject: ${JSON.stringify(failedObj.object)}\nError: ${failedObj.error}\n`;
}).join('\n');

throw new Error(failureMessage);
}
});
}
61 changes: 61 additions & 0 deletions bruno/Get Collections.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
meta {
name: Get Collections
type: http
seq: 3
}

get {
url: {{host}}/api/v21/collections/
body: none
auth: none
}

headers {
Accept: application/taxii+json;version=2.1
}

tests {
test("Verify response status code", function() {
expect(res.getStatus()).to.equal(200);
});

test("Verify response content type", function() {
const contentType = res.getHeader('content-type');
expect(contentType).to.include('application/stix+json');
expect(contentType).to.include('version=2.1');
});

test("Verify response body", function() {
const data = res.getBody();

if (data.hasOwnProperty('collections')) {
expect(data.collections).to.be.an('array');

data.collections.forEach(collection => {

expect(collection).to.have.property('id').that.is.a('string');

expect(collection).to.have.property('title').that.is.a('string').and.is.not.empty;

if (collection.hasOwnProperty('description')) {
expect(collection.description).to.be.a('string');
}

if (collection.hasOwnProperty('alias')) {
expect(collection.alias).to.be.a('string');
}

expect(collection).to.have.property('canRead').that.is.a('boolean');

expect(collection).to.have.property('canWrite').that.is.a('boolean');

if (collection.hasOwnProperty('mediaTypes')) {
expect(collection.mediaTypes).to.be.an('array').and.not.be.empty;
collection.mediaTypes.forEach(mediaType => {
expect(mediaType).to.be.a('string').and.include('application/taxii+json');
});
}
});
}
});
}
Loading
Loading