Skip to content

Commit

Permalink
Merge pull request #16 from mitre-attack/bugfix-14-fix-behavior-of-th…
Browse files Browse the repository at this point in the history
…e-match-filter

Fix Match Filter, Bruno Tests, & Other Small Changes
  • Loading branch information
seansica authored Apr 23, 2024
2 parents 045b5f3 + 57c4040 commit 7ae91ff
Show file tree
Hide file tree
Showing 28 changed files with 4,858 additions and 733 deletions.
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
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');
});
}
});
}
});
}
78 changes: 78 additions & 0 deletions bruno/Get Object Manifests.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
meta {
name: Get Object Manifests
type: http
seq: 7
}

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

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

vars:pre-request {
collectionId: x-mitre-collection--dac0d2d7-8653-445c-9bff-82f934c1e858
}

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 structure", function() {
const data = res.getBody();
expect(data).to.have.property('more').that.is.a('boolean');

if (data.hasOwnProperty('objects')) {
expect(data.objects).to.be.an('array');
} else {
expect(data).to.be.an('object').and.to.be.empty;
}
});

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

if (data.hasOwnProperty('objects')) {
data.objects.forEach((obj, index) => {
try {
expect(obj).to.have.property('id').that.is.a('string');
expect(obj).to.have.property('date_added').that.is.a('string');

if (!obj.id.includes('marking-definition')) {
expect(obj).to.have.property('version').that.is.a('string');
}

if (obj.hasOwnProperty('media_type')) {
expect(obj.media_type).to.be.a('string');
}
} 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);
}
});
}
});
}
Loading

0 comments on commit 7ae91ff

Please sign in to comment.