Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ CouchDb Info (port is defined in .env):

[http://localhost:5984/](http://localhost:5984/)

### Integration tests with Karate

The folder `src/test/java/de.bsi.secvisogram.csaf_cms_backend.integration/` & `src/test/java/de.bsi.secvisogram.csaf_cms_backend.integration/` contains [Karate](https://github.com/karatelabs/karate) test files.

Use `./gradlew integrationTest` to run the tests. CSAF-CMS-Backend and all other components must be up an running with the development setup described above.

Settings (like hostnames, port, user and password) can can be changed in the feature-files. `template.feature`-file contains all basic request to build that can be used to assemble futher workflow.
Comment thread
mfd2007 marked this conversation as resolved.
Outdated


## Contributing

You can find our guidelines here [CONTRIBUTING.md](https://github.com/secvisogram/secvisogram/blob/main/CONTRIBUTING.md)
Expand Down
15 changes: 15 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ dependencies {
//testImplementation 'org.testcontainers:junit-jupiter:1.17.6'
testImplementation 'org.mockito:mockito-inline:5.2.0'

// used for integration tests in de.bsi.secvisogram.csaf_cms_backend.integration.KarateRunner
testImplementation 'com.intuit.karate:karate-junit5:1.4.0'

spotbugsSlf4j 'org.slf4j:slf4j-simple:2.0.7'
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0'
//spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.6.0'
Expand All @@ -75,6 +78,18 @@ dependencies {
test {
useJUnitPlatform()
testLogging.showStandardStreams = false
filter {
//exclude all integration tests
excludeTestsMatching "de.bsi.secvisogram.csaf_cms_backend.integration.*"
}
}

tasks.register('integrationTest', Test) {
useJUnitPlatform()
testLogging.showStandardStreams = true
filter {
includeTestsMatching("de.bsi.secvisogram.csaf_cms_backend.integration.*")
}
}

tasks.withType(JavaCompile) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.bsi.secvisogram.csaf_cms_backend.integration;

import com.intuit.karate.junit5.Karate;


public class KarateRunner {
@Karate.Test
Karate testExport() {
String[] testCases = new String[] {
"classpath:de/bsi/secvisogram/csaf_cms_backend/integration/export.feature"
};
return Karate.run(testCases);
}

@Karate.Test
Karate testFullWorkflow() {
String[] testCases = new String[] {
"classpath:de/bsi/secvisogram/csaf_cms_backend/integration/fullworkflow.feature"
};
return Karate.run(testCases);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Feature: Test export of documents

Background:
* def authUrl = 'http://localhost:9000'
* def loginPath = '/realms/csaf/protocol/openid-connect/token'
* def logoutPath = '/realms/csaf/protocol/openid-connect/logout'

* def restUrl = 'http://localhost:8081'
* def apiBase = '/api/v1/advisories'

* def username = 'all'
* def password = 'all'

Scenario: Export all formats and store response in folder ./target/
The first document in the list will be exported in all available
formats.

# Login
Given url 'http://localhost:9000/realms/csaf/protocol/openid-connect/token'
* form field client_id = 'secvisogram'
* form field username = 'all'
* form field password = 'all'
* form field grant_type = 'password'
* form field response_type = 'code'
* form field audience = 'secvisogram'
* form field requested_token_type = 'ID'
When method post
Then status 200
* def accessToken = response.access_token
* def refreshToken = response.refresh_token
* def session = response.session_state

#Get advisory list and store first advisory id
Given url 'http://localhost:8081'
* path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method get
Then status 200
* def advisoryId = response[0].advisoryId

# Download advisory as JSON
* def format = 'JSON'
Given path apiBase + '/' + advisoryId + '/csaf'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
* param format = format
When method get
Then status 200
* karate.write(response, 'advisory.json')

# Download advisory as HTML
* def format = 'HTML'
Given path apiBase + '/' + advisoryId + '/csaf'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
* param format = format
When method get
Then status 200
* karate.write(response, 'advisory.html')

# Download advisory as PDF
* def format = 'PDF'
Given path apiBase + '/' + advisoryId + '/csaf'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
* param format = format
When method get
Then status 200
* karate.write(response, 'advisory.pdf')

# Download advisory as Markdown
* def format = 'Markdown'
Given path apiBase + '/' + advisoryId + '/csaf'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
* param format = format
When method get
Then status 200
* karate.write(response, 'advisory.md')

# Logout
Given url 'http://localhost:9000/realms/csaf/protocol/openid-connect/logout'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/x-www-form-urlencoded'
* form field refresh_token = refreshToken
* form field client_id = 'secvisogram'
When method post
* status 204

Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
Feature: Hello World
Comment thread
mfd2007 marked this conversation as resolved.
Outdated

Background:
* url 'http://localhost:8081'
* def apiBase = '/api/v1/advisories'

Scenario: oauth 2 flow
# Login
Given url 'http://localhost:9000/realms/csaf/protocol/openid-connect/token'
* form field client_id = 'secvisogram'
* form field username = 'all'
* form field password = 'all'
* form field grant_type = 'password'
* form field response_type = 'code'
* form field audience = 'secvisogram'
* form field requested_token_type = 'ID'
When method post
Then status 200
* def accessToken = response.access_token
* def refreshToken = response.refresh_token
* def session = response.session_state

########
#Upload
Given url 'http://localhost:8081'
* path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
* request read('min.json')
When method post
Then status 201
* def advisoryId = response.id
* def revision = response.revision

########
#Change workflow state to Review
#
# Draft, Review, Approved, RfPublication, Published
* def workflowStatus = 'Review'
Given path apiBase + '/' + advisoryId + '/workflowstate/' + workflowStatus
* param revision = revision
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method patch
Then status 200

# Get new revision after workflow state change
Given path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method get
Then status 200
* def filt = function(x){ return x.advisoryId == advisoryId }
* def items = get response[*]
* def revision = karate.filter(items, filt)[0].revision
Comment thread
mfd2007 marked this conversation as resolved.
Outdated

########
#Change workflow state to Approved
#
* def workflowStatus = 'Approved'
Given path apiBase + '/' + advisoryId + '/workflowstate/' + workflowStatus
* param revision = revision
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method patch
Then status 200
# Get new revision after workflow state change
Given path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method get
Then status 200
* def filt = function(x){ return x.advisoryId == advisoryId }
* def items = get response[*]
* def revision = karate.filter(items, filt)[0].revision

########
#Change workflow state to RfPublication
#
* def workflowStatus = 'RfPublication'
Given path apiBase + '/' + advisoryId + '/workflowstate/' + workflowStatus
* param revision = revision
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method patch
Then status 200
# Get new revision after workflow state change
Given path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method get
Then status 200
* def filt = function(x){ return x.advisoryId == advisoryId }
* def items = get response[*]
* def revision = karate.filter(items, filt)[0].revision

########
#Change workflow state to Published
#
* def workflowStatus = 'Published'
Given path apiBase + '/' + advisoryId + '/workflowstate/' + workflowStatus
* param revision = revision
# final, interim, draft
* param documentTrackingStatus = 'Final'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method patch
Then status 200

# Get new revision after workflow state change
Given path apiBase
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/json'
When method get
Then status 200
* def filt = function(x){ return x.advisoryId == advisoryId }
* def items = get response[*]
* def revision = karate.filter(items, filt)[0].revision
Comment thread
mfd2007 marked this conversation as resolved.
Outdated

# Logout
Given url 'http://localhost:9000/realms/csaf/protocol/openid-connect/logout'
* header Authorization = 'Bearer ' + accessToken
* header Content-Type = 'application/x-www-form-urlencoded'
* form field refresh_token = refreshToken
* form field client_id = 'secvisogram'
When method post
* status 204

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"csaf": {
"document": {
"category": "csaf_base",
"csaf_version": "2.0",
"publisher": {
"category": "other",
"name": "1",
"namespace": "h:2"
Comment thread
mfd2007 marked this conversation as resolved.
Outdated
},
"title": "title",
"tracking": {
"current_release_date": "2023-07-12T10:00:00.000Z",
"generator": {
"date": "2023-07-12T07:53:29.378Z",
"engine": {
"name": "Secvisogram",
"version": "2.2.5"
}
},
"id": "document-id",
"initial_release_date": "2023-07-12T10:00:00.000Z",
"revision_history": [
{
"date": "2023-07-12T10:00:00.000Z",
"number": "1.0.0",
"summary": "summary"
Comment thread
mfd2007 marked this conversation as resolved.
Outdated
}
],
"status": "final",
"version": "1.0.0"
}
}
},
"summary": "-",
"legacyVersion": ""
}

Loading