diff --git a/README.md b/README.md index f377570b..1ade2752 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ We use `docker compose` to test CRS components locally during development. Copy `env.template` to `.env` and set variables. +Modify `competition-server/scantron.yaml` to use your own `github.pat` (make sure to create it with `repo` and `package:read` permissions). Start the services with ``` diff --git a/competition-server/compose.yaml b/competition-server/compose.yaml new file mode 100644 index 00000000..cc2f40a8 --- /dev/null +++ b/competition-server/compose.yaml @@ -0,0 +1,65 @@ +name: "competitor-test-server" + +x-default-logging: &logging + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + tag: "{{.Name}}|{{.ImageName}}|{{.ID}}" + +# include: +# - ./signoz/compose.yaml + +services: + # dind: + # image: docker:28-dind + # command: + # [ + # "dockerd", + # "-H", + # "tcp://0.0.0.0:2375", + # "--tls=false", + # "--storage-driver=overlay2", + # ] + # restart: always + # privileged: true + # networks: + # - dind-internal + # - internet + # expose: + # - "2375" + # environment: + # - DOCKER_TLS_CERTDIR= # Ensure this is correctly formatted (empty value) + # - DOCKER_DEFAULT_PLATFORM=linux/amd64 + # volumes: + # - shared-tmp:/tmp + + scantron: + image: ghcr.io/aixcc-finals/example-crs-architecture/competition-test-api:v1.1-rc2 + platform: linux/amd64 + privileged: true + volumes: + - "./scantron.yaml:/etc/scantron/scantron.yaml" + - ../crs_scratch:/tmp + depends_on: + - dind + ports: + - "1323:1323" + command: server + # networks: + # - dind-internal + # - internet + extra_hosts: + - "host.docker.internal:host-gateway" + environment: + - "DOCKER_HOST=tcp://dind:2375" + - DOCKER_DEFAULT_PLATFORM=linux/amd64 + logging: *logging + +# networks: +# dind-internal: +# internal: true +# internet: {} + +# volumes: +# shared-tmp: diff --git a/competition-server/scantron.yaml b/competition-server/scantron.yaml new file mode 100644 index 00000000..d203cc9c --- /dev/null +++ b/competition-server/scantron.yaml @@ -0,0 +1,39 @@ +--- +# Example Config File + +teams: + # This is the API key your CRS uses to get access + # to the submission endpoints + - id: 11111111-1111-1111-1111-111111111111 + note: Test Key for Local Auth + api_key: + token: secret + active: true + permissions: + crs: true + competition_management: true + + crs: + # The url of your CRS. If you are running your CRS on localhost, keep the + # url as host.docker.internal + # url: http://host.docker.internal:1324 # This should stay the same, so the scantron docker container can communicate with the outside world + url: http://task-server:8000 + api_key_id: 515cc8a0-3019-4c9f-8c1c-72d0b54ae561 + api_key_token: VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB + +logging: + gorm: + level: 0 + trace_queries: true + app: + level: -4 + +round_id: testing + +# Listen address outside the container +listen_address: "scantron:1323" + +github: + # github Personal Access token. This is used by the server to download the + # appropriate fuzz tooling if not using public repositories + pat: ghp_XXXXXXXXXXXXXXXXXXXXX diff --git a/compose.yaml b/compose.yaml index e3d24890..b14eb8b3 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,3 +1,6 @@ +include: + - ./competition-server/compose.yaml + services: # ugh the only solution i can come up with is a dind instance paired with every single build-bot we will need like k8s groups or something dind: @@ -294,9 +297,6 @@ services: timeout: 5s retries: 10 - competition-api: - image: ghcr.io/aixcc-finals/example-crs-architecture/example-competition-api:v0.1 - configs: litellm_config: file: ./litellm/litellm_config.yaml diff --git a/env.dev.compose b/env.dev.compose index b5c65595..5042a2b0 100644 --- a/env.dev.compose +++ b/env.dev.compose @@ -22,13 +22,13 @@ BUTTERCUP_TASK_SERVER_API_TOKEN_HASH='$argon2id$v=19$m=65536,t=3,p=4$Dg1v6NPGTyX # CRS_API_TOKEN=VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB # Competition API Authentication -COMPETITION_API_KEY_ID=api_key_id -COMPETITION_API_KEY_TOKEN=api_key_token +COMPETITION_API_KEY_ID=11111111-1111-1111-1111-111111111111 +COMPETITION_API_KEY_TOKEN=secret BUTTERCUP_SCHEDULER_SERVE__REDIS_URL=redis://redis:6379 BUTTERCUP_SCHEDULER_LOG_LEVEL=debug BUTTERCUP_SCHEDULER_SERVE__SLEEP_TIME=5 -BUTTERCUP_SCHEDULER_SERVE__COMPETITION_API_URL=http://competition-api:1323 +BUTTERCUP_SCHEDULER_SERVE__COMPETITION_API_URL=http://scantron:1323 BUTTERCUP_SCHEDULER_TASKS_STORAGE_DIR=/tasks_storage BUTTERCUP_SCHEDULER_SCRATCH_DIR=/crs_scratch diff --git a/orchestrator/docs/SarifApi.md b/orchestrator/docs/BroadcastSarifAssessmentApi.md similarity index 67% rename from orchestrator/docs/SarifApi.md rename to orchestrator/docs/BroadcastSarifAssessmentApi.md index cba1af34..09181cc6 100644 --- a/orchestrator/docs/SarifApi.md +++ b/orchestrator/docs/BroadcastSarifAssessmentApi.md @@ -1,18 +1,18 @@ -# competition_api_client.SarifApi +# competition_api_client.BroadcastSarifAssessmentApi All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- -[**v1_task_task_id_sarif_sarif_id_post**](SarifApi.md#v1_task_task_id_sarif_sarif_id_post) | **POST** /v1/task/{task_id}/sarif/{sarif_id}/ | Submit Sarif Assessment +[**v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post**](BroadcastSarifAssessmentApi.md#v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post) | **POST** /v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/ | Submit a SARIF Assessment -# **v1_task_task_id_sarif_sarif_id_post** -> TypesSarifAssessmentResponse v1_task_task_id_sarif_sarif_id_post(task_id, sarif_id, payload) +# **v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post** +> TypesSarifAssessmentResponse v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post(task_id, broadcast_sarif_id, payload) -Submit Sarif Assessment +Submit a SARIF Assessment -submit a sarif assessment +Submit a SARIF assessment ### Example @@ -45,18 +45,18 @@ configuration = competition_api_client.Configuration( # Enter a context with an instance of the API client with competition_api_client.ApiClient(configuration) as api_client: # Create an instance of the API class - api_instance = competition_api_client.SarifApi(api_client) + api_instance = competition_api_client.BroadcastSarifAssessmentApi(api_client) task_id = 'task_id_example' # str | Task ID - sarif_id = 'sarif_id_example' # str | SARIF ID + broadcast_sarif_id = 'broadcast_sarif_id_example' # str | Broadcast SARIF ID payload = competition_api_client.TypesSarifAssessmentSubmission() # TypesSarifAssessmentSubmission | Submission body try: - # Submit Sarif Assessment - api_response = api_instance.v1_task_task_id_sarif_sarif_id_post(task_id, sarif_id, payload) - print("The response of SarifApi->v1_task_task_id_sarif_sarif_id_post:\n") + # Submit a SARIF Assessment + api_response = api_instance.v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post(task_id, broadcast_sarif_id, payload) + print("The response of BroadcastSarifAssessmentApi->v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post:\n") pprint(api_response) except Exception as e: - print("Exception when calling SarifApi->v1_task_task_id_sarif_sarif_id_post: %s\n" % e) + print("Exception when calling BroadcastSarifAssessmentApi->v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post: %s\n" % e) ``` @@ -67,7 +67,7 @@ with competition_api_client.ApiClient(configuration) as api_client: Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **task_id** | **str**| Task ID | - **sarif_id** | **str**| SARIF ID | + **broadcast_sarif_id** | **str**| Broadcast SARIF ID | **payload** | [**TypesSarifAssessmentSubmission**](TypesSarifAssessmentSubmission.md)| Submission body | ### Return type diff --git a/orchestrator/docs/BundleApi.md b/orchestrator/docs/BundleApi.md new file mode 100644 index 00000000..56f750ac --- /dev/null +++ b/orchestrator/docs/BundleApi.md @@ -0,0 +1,355 @@ +# competition_api_client.BundleApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**v1_task_task_id_bundle_bundle_id_delete**](BundleApi.md#v1_task_task_id_bundle_bundle_id_delete) | **DELETE** /v1/task/{task_id}/bundle/{bundle_id}/ | Delete Bundle +[**v1_task_task_id_bundle_bundle_id_get**](BundleApi.md#v1_task_task_id_bundle_bundle_id_get) | **GET** /v1/task/{task_id}/bundle/{bundle_id}/ | Get Bundle +[**v1_task_task_id_bundle_bundle_id_patch**](BundleApi.md#v1_task_task_id_bundle_bundle_id_patch) | **PATCH** /v1/task/{task_id}/bundle/{bundle_id}/ | Update Bundle +[**v1_task_task_id_bundle_post**](BundleApi.md#v1_task_task_id_bundle_post) | **POST** /v1/task/{task_id}/bundle/ | Submit Bundle + + +# **v1_task_task_id_bundle_bundle_id_delete** +> str v1_task_task_id_bundle_bundle_id_delete(task_id, bundle_id) + +Delete Bundle + +delete a bundle + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.BundleApi(api_client) + task_id = 'task_id_example' # str | Task ID + bundle_id = 'bundle_id_example' # str | Bundle ID + + try: + # Delete Bundle + api_response = api_instance.v1_task_task_id_bundle_bundle_id_delete(task_id, bundle_id) + print("The response of BundleApi->v1_task_task_id_bundle_bundle_id_delete:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling BundleApi->v1_task_task_id_bundle_bundle_id_delete: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **bundle_id** | **str**| Bundle ID | + +### Return type + +**str** + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**204** | No Content | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **v1_task_task_id_bundle_bundle_id_get** +> TypesBundleSubmissionResponseVerbose v1_task_task_id_bundle_bundle_id_get(task_id, bundle_id) + +Get Bundle + +get a bundle + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.BundleApi(api_client) + task_id = 'task_id_example' # str | Task ID + bundle_id = 'bundle_id_example' # str | Bundle ID + + try: + # Get Bundle + api_response = api_instance.v1_task_task_id_bundle_bundle_id_get(task_id, bundle_id) + print("The response of BundleApi->v1_task_task_id_bundle_bundle_id_get:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling BundleApi->v1_task_task_id_bundle_bundle_id_get: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **bundle_id** | **str**| Bundle ID | + +### Return type + +[**TypesBundleSubmissionResponseVerbose**](TypesBundleSubmissionResponseVerbose.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **v1_task_task_id_bundle_bundle_id_patch** +> TypesBundleSubmissionResponseVerbose v1_task_task_id_bundle_bundle_id_patch(task_id, bundle_id, payload) + +Update Bundle + +updates a bundle + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.BundleApi(api_client) + task_id = 'task_id_example' # str | Task ID + bundle_id = 'bundle_id_example' # str | Bundle ID + payload = competition_api_client.TypesBundleSubmission() # TypesBundleSubmission | Submission Body + + try: + # Update Bundle + api_response = api_instance.v1_task_task_id_bundle_bundle_id_patch(task_id, bundle_id, payload) + print("The response of BundleApi->v1_task_task_id_bundle_bundle_id_patch:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling BundleApi->v1_task_task_id_bundle_bundle_id_patch: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **bundle_id** | **str**| Bundle ID | + **payload** | [**TypesBundleSubmission**](TypesBundleSubmission.md)| Submission Body | + +### Return type + +[**TypesBundleSubmissionResponseVerbose**](TypesBundleSubmissionResponseVerbose.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **v1_task_task_id_bundle_post** +> TypesBundleSubmissionResponse v1_task_task_id_bundle_post(task_id, payload) + +Submit Bundle + +submits a bundle + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.BundleApi(api_client) + task_id = 'task_id_example' # str | Task ID + payload = competition_api_client.TypesBundleSubmission() # TypesBundleSubmission | Submission Body + + try: + # Submit Bundle + api_response = api_instance.v1_task_task_id_bundle_post(task_id, payload) + print("The response of BundleApi->v1_task_task_id_bundle_post:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling BundleApi->v1_task_task_id_bundle_post: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **payload** | [**TypesBundleSubmission**](TypesBundleSubmission.md)| Submission Body | + +### Return type + +[**TypesBundleSubmissionResponse**](TypesBundleSubmissionResponse.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/orchestrator/docs/FeeformApi.md b/orchestrator/docs/FeeformApi.md new file mode 100644 index 00000000..061367bb --- /dev/null +++ b/orchestrator/docs/FeeformApi.md @@ -0,0 +1,95 @@ +# competition_api_client.FeeformApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**v1_task_task_id_freeform_post**](FeeformApi.md#v1_task_task_id_freeform_post) | **POST** /v1/task/{task_id}/freeform/ | Submit Freeform + + +# **v1_task_task_id_freeform_post** +> TypesFreeformResponse v1_task_task_id_freeform_post(task_id, payload) + +Submit Freeform + +submits a freeform pov + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.FeeformApi(api_client) + task_id = 'task_id_example' # str | Task ID + payload = competition_api_client.TypesFreeformSubmission() # TypesFreeformSubmission | Submission Body + + try: + # Submit Freeform + api_response = api_instance.v1_task_task_id_freeform_post(task_id, payload) + print("The response of FeeformApi->v1_task_task_id_freeform_post:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling FeeformApi->v1_task_task_id_freeform_post: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **payload** | [**TypesFreeformSubmission**](TypesFreeformSubmission.md)| Submission Body | + +### Return type + +[**TypesFreeformResponse**](TypesFreeformResponse.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/orchestrator/docs/PingApi.md b/orchestrator/docs/PingApi.md new file mode 100644 index 00000000..5c96a83a --- /dev/null +++ b/orchestrator/docs/PingApi.md @@ -0,0 +1,84 @@ +# competition_api_client.PingApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**v1_ping_get**](PingApi.md#v1_ping_get) | **GET** /v1/ping/ | Test authentication creds and network connectivity + + +# **v1_ping_get** +> TypesPingResponse v1_ping_get() + +Test authentication creds and network connectivity + +Test authentication creds and network connectivity + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.PingApi(api_client) + + try: + # Test authentication creds and network connectivity + api_response = api_instance.v1_ping_get() + print("The response of PingApi->v1_ping_get:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling PingApi->v1_ping_get: %s\n" % e) +``` + + + +### Parameters + +This endpoint does not need any parameter. + +### Return type + +[**TypesPingResponse**](TypesPingResponse.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: */* + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/orchestrator/docs/VulnerabilityApi.md b/orchestrator/docs/PovApi.md similarity index 70% rename from orchestrator/docs/VulnerabilityApi.md rename to orchestrator/docs/PovApi.md index f4d0bbde..86a4d340 100644 --- a/orchestrator/docs/VulnerabilityApi.md +++ b/orchestrator/docs/PovApi.md @@ -1,15 +1,15 @@ -# competition_api_client.VulnerabilityApi +# competition_api_client.PovApi All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- -[**v1_task_task_id_vuln_post**](VulnerabilityApi.md#v1_task_task_id_vuln_post) | **POST** /v1/task/{task_id}/vuln/ | Submit Vulnerability -[**v1_task_task_id_vuln_vuln_id_get**](VulnerabilityApi.md#v1_task_task_id_vuln_vuln_id_get) | **GET** /v1/task/{task_id}/vuln/{vuln_id}/ | Vulnerability Status +[**v1_task_task_id_pov_post**](PovApi.md#v1_task_task_id_pov_post) | **POST** /v1/task/{task_id}/pov/ | Submit Vulnerability +[**v1_task_task_id_pov_pov_id_get**](PovApi.md#v1_task_task_id_pov_pov_id_get) | **GET** /v1/task/{task_id}/pov/{pov_id}/ | Vulnerability Status -# **v1_task_task_id_vuln_post** -> TypesVulnSubmissionResponse v1_task_task_id_vuln_post(task_id, payload) +# **v1_task_task_id_pov_post** +> TypesPOVSubmissionResponse v1_task_task_id_pov_post(task_id, payload) Submit Vulnerability @@ -21,8 +21,8 @@ submit a vulnerability for testing ```python import competition_api_client -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse from buttercup.orchestrator.competition_api_client.rest import ApiException from pprint import pprint @@ -46,17 +46,17 @@ configuration = competition_api_client.Configuration( # Enter a context with an instance of the API client with competition_api_client.ApiClient(configuration) as api_client: # Create an instance of the API class - api_instance = competition_api_client.VulnerabilityApi(api_client) + api_instance = competition_api_client.PovApi(api_client) task_id = 'task_id_example' # str | Task ID - payload = competition_api_client.TypesVulnSubmission() # TypesVulnSubmission | Submission body + payload = competition_api_client.TypesPOVSubmission() # TypesPOVSubmission | Submission body try: # Submit Vulnerability - api_response = api_instance.v1_task_task_id_vuln_post(task_id, payload) - print("The response of VulnerabilityApi->v1_task_task_id_vuln_post:\n") + api_response = api_instance.v1_task_task_id_pov_post(task_id, payload) + print("The response of PovApi->v1_task_task_id_pov_post:\n") pprint(api_response) except Exception as e: - print("Exception when calling VulnerabilityApi->v1_task_task_id_vuln_post: %s\n" % e) + print("Exception when calling PovApi->v1_task_task_id_pov_post: %s\n" % e) ``` @@ -67,11 +67,11 @@ with competition_api_client.ApiClient(configuration) as api_client: Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **task_id** | **str**| Task ID | - **payload** | [**TypesVulnSubmission**](TypesVulnSubmission.md)| Submission body | + **payload** | [**TypesPOVSubmission**](TypesPOVSubmission.md)| Submission body | ### Return type -[**TypesVulnSubmissionResponse**](TypesVulnSubmissionResponse.md) +[**TypesPOVSubmissionResponse**](TypesPOVSubmissionResponse.md) ### Authorization @@ -94,8 +94,8 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -# **v1_task_task_id_vuln_vuln_id_get** -> TypesVulnSubmissionResponse v1_task_task_id_vuln_vuln_id_get(task_id, vuln_id) +# **v1_task_task_id_pov_pov_id_get** +> TypesPOVSubmissionResponse v1_task_task_id_pov_pov_id_get(task_id, pov_id) Vulnerability Status @@ -107,7 +107,7 @@ yield the status of vuln testing ```python import competition_api_client -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse from buttercup.orchestrator.competition_api_client.rest import ApiException from pprint import pprint @@ -131,17 +131,17 @@ configuration = competition_api_client.Configuration( # Enter a context with an instance of the API client with competition_api_client.ApiClient(configuration) as api_client: # Create an instance of the API class - api_instance = competition_api_client.VulnerabilityApi(api_client) + api_instance = competition_api_client.PovApi(api_client) task_id = 'task_id_example' # str | Task ID - vuln_id = 'vuln_id_example' # str | Vuln ID + pov_id = 'pov_id_example' # str | POV ID try: # Vulnerability Status - api_response = api_instance.v1_task_task_id_vuln_vuln_id_get(task_id, vuln_id) - print("The response of VulnerabilityApi->v1_task_task_id_vuln_vuln_id_get:\n") + api_response = api_instance.v1_task_task_id_pov_pov_id_get(task_id, pov_id) + print("The response of PovApi->v1_task_task_id_pov_pov_id_get:\n") pprint(api_response) except Exception as e: - print("Exception when calling VulnerabilityApi->v1_task_task_id_vuln_vuln_id_get: %s\n" % e) + print("Exception when calling PovApi->v1_task_task_id_pov_pov_id_get: %s\n" % e) ``` @@ -152,11 +152,11 @@ with competition_api_client.ApiClient(configuration) as api_client: Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **task_id** | **str**| Task ID | - **vuln_id** | **str**| Vuln ID | + **pov_id** | **str**| POV ID | ### Return type -[**TypesVulnSubmissionResponse**](TypesVulnSubmissionResponse.md) +[**TypesPOVSubmissionResponse**](TypesPOVSubmissionResponse.md) ### Authorization diff --git a/orchestrator/docs/SubmittedSarifApi.md b/orchestrator/docs/SubmittedSarifApi.md new file mode 100644 index 00000000..973e4667 --- /dev/null +++ b/orchestrator/docs/SubmittedSarifApi.md @@ -0,0 +1,95 @@ +# competition_api_client.SubmittedSarifApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**v1_task_task_id_submitted_sarif_post**](SubmittedSarifApi.md#v1_task_task_id_submitted_sarif_post) | **POST** /v1/task/{task_id}/submitted-sarif/ | Submit a CRS generated SARIF + + +# **v1_task_task_id_submitted_sarif_post** +> TypesSARIFSubmissionResponse v1_task_task_id_submitted_sarif_post(task_id, payload) + +Submit a CRS generated SARIF + +Submit a CRS generated SARIF + +### Example + +* Basic Authentication (BasicAuth): + +```python +import competition_api_client +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse +from buttercup.orchestrator.competition_api_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = competition_api_client.Configuration( + host = "http://localhost" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure HTTP basic authorization: BasicAuth +configuration = competition_api_client.Configuration( + username = os.environ["USERNAME"], + password = os.environ["PASSWORD"] +) + +# Enter a context with an instance of the API client +with competition_api_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = competition_api_client.SubmittedSarifApi(api_client) + task_id = 'task_id_example' # str | Task ID + payload = competition_api_client.TypesSARIFSubmission() # TypesSARIFSubmission | Submission body + + try: + # Submit a CRS generated SARIF + api_response = api_instance.v1_task_task_id_submitted_sarif_post(task_id, payload) + print("The response of SubmittedSarifApi->v1_task_task_id_submitted_sarif_post:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling SubmittedSarifApi->v1_task_task_id_submitted_sarif_post: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| Task ID | + **payload** | [**TypesSARIFSubmission**](TypesSARIFSubmission.md)| Submission body | + +### Return type + +[**TypesSARIFSubmissionResponse**](TypesSARIFSubmissionResponse.md) + +### Authorization + +[BasicAuth](../README.md#BasicAuth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**404** | Not Found | - | +**500** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/orchestrator/docs/TypesBundleSubmission.md b/orchestrator/docs/TypesBundleSubmission.md new file mode 100644 index 00000000..3f8f049c --- /dev/null +++ b/orchestrator/docs/TypesBundleSubmission.md @@ -0,0 +1,34 @@ +# TypesBundleSubmission + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**broadcast_sarif_id** | **str** | | [optional] +**description** | **str** | optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report | [optional] +**freeform_id** | **str** | | [optional] +**patch_id** | **str** | | [optional] +**pov_id** | **str** | | [optional] +**submitted_sarif_id** | **str** | | [optional] + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesBundleSubmission from a JSON string +types_bundle_submission_instance = TypesBundleSubmission.from_json(json) +# print the JSON string representation of the object +print(TypesBundleSubmission.to_json()) + +# convert the object into a dict +types_bundle_submission_dict = types_bundle_submission_instance.to_dict() +# create an instance of TypesBundleSubmission from a dict +types_bundle_submission_from_dict = TypesBundleSubmission.from_dict(types_bundle_submission_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesBundleSubmissionResponse.md b/orchestrator/docs/TypesBundleSubmissionResponse.md new file mode 100644 index 00000000..481f6cf5 --- /dev/null +++ b/orchestrator/docs/TypesBundleSubmissionResponse.md @@ -0,0 +1,30 @@ +# TypesBundleSubmissionResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**bundle_id** | **str** | | +**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesBundleSubmissionResponse from a JSON string +types_bundle_submission_response_instance = TypesBundleSubmissionResponse.from_json(json) +# print the JSON string representation of the object +print(TypesBundleSubmissionResponse.to_json()) + +# convert the object into a dict +types_bundle_submission_response_dict = types_bundle_submission_response_instance.to_dict() +# create an instance of TypesBundleSubmissionResponse from a dict +types_bundle_submission_response_from_dict = TypesBundleSubmissionResponse.from_dict(types_bundle_submission_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesBundleSubmissionResponseVerbose.md b/orchestrator/docs/TypesBundleSubmissionResponseVerbose.md new file mode 100644 index 00000000..fb154b7b --- /dev/null +++ b/orchestrator/docs/TypesBundleSubmissionResponseVerbose.md @@ -0,0 +1,36 @@ +# TypesBundleSubmissionResponseVerbose + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**broadcast_sarif_id** | **str** | | [optional] +**bundle_id** | **str** | | +**description** | **str** | | [optional] +**freeform_id** | **str** | | [optional] +**patch_id** | **str** | | [optional] +**pov_id** | **str** | | [optional] +**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | +**submitted_sarif_id** | **str** | | [optional] + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesBundleSubmissionResponseVerbose from a JSON string +types_bundle_submission_response_verbose_instance = TypesBundleSubmissionResponseVerbose.from_json(json) +# print the JSON string representation of the object +print(TypesBundleSubmissionResponseVerbose.to_json()) + +# convert the object into a dict +types_bundle_submission_response_verbose_dict = types_bundle_submission_response_verbose_instance.to_dict() +# create an instance of TypesBundleSubmissionResponseVerbose from a dict +types_bundle_submission_response_verbose_from_dict = TypesBundleSubmissionResponseVerbose.from_dict(types_bundle_submission_response_verbose_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesFreeformResponse.md b/orchestrator/docs/TypesFreeformResponse.md new file mode 100644 index 00000000..ededd2f9 --- /dev/null +++ b/orchestrator/docs/TypesFreeformResponse.md @@ -0,0 +1,30 @@ +# TypesFreeformResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**freeform_id** | **str** | | +**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesFreeformResponse from a JSON string +types_freeform_response_instance = TypesFreeformResponse.from_json(json) +# print the JSON string representation of the object +print(TypesFreeformResponse.to_json()) + +# convert the object into a dict +types_freeform_response_dict = types_freeform_response_instance.to_dict() +# create an instance of TypesFreeformResponse from a dict +types_freeform_response_from_dict = TypesFreeformResponse.from_dict(types_freeform_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesFreeformSubmission.md b/orchestrator/docs/TypesFreeformSubmission.md new file mode 100644 index 00000000..0f6abcfa --- /dev/null +++ b/orchestrator/docs/TypesFreeformSubmission.md @@ -0,0 +1,29 @@ +# TypesFreeformSubmission + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**submission** | **str** | Base64 encoded arbitrary data 2MiB max size before Base64 encoding | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesFreeformSubmission from a JSON string +types_freeform_submission_instance = TypesFreeformSubmission.from_json(json) +# print the JSON string representation of the object +print(TypesFreeformSubmission.to_json()) + +# convert the object into a dict +types_freeform_submission_dict = types_freeform_submission_instance.to_dict() +# create an instance of TypesFreeformSubmission from a dict +types_freeform_submission_from_dict = TypesFreeformSubmission.from_dict(types_freeform_submission_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesPOVSubmission.md b/orchestrator/docs/TypesPOVSubmission.md new file mode 100644 index 00000000..33e245d2 --- /dev/null +++ b/orchestrator/docs/TypesPOVSubmission.md @@ -0,0 +1,33 @@ +# TypesPOVSubmission + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**architecture** | [**TypesArchitecture**](TypesArchitecture.md) | | +**engine** | **str** | Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml. 4KiB max size | +**fuzzer_name** | **str** | Fuzz Tooling fuzzer that exercises this vuln 4KiB max size | +**sanitizer** | **str** | Fuzz Tooling Sanitizer that exercises this vuln 4KiB max size | +**testcase** | **str** | Base64 encoded vuln trigger 2MiB max size before Base64 encoding | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesPOVSubmission from a JSON string +types_pov_submission_instance = TypesPOVSubmission.from_json(json) +# print the JSON string representation of the object +print(TypesPOVSubmission.to_json()) + +# convert the object into a dict +types_pov_submission_dict = types_pov_submission_instance.to_dict() +# create an instance of TypesPOVSubmission from a dict +types_pov_submission_from_dict = TypesPOVSubmission.from_dict(types_pov_submission_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesPOVSubmissionResponse.md b/orchestrator/docs/TypesPOVSubmissionResponse.md new file mode 100644 index 00000000..c51834f0 --- /dev/null +++ b/orchestrator/docs/TypesPOVSubmissionResponse.md @@ -0,0 +1,30 @@ +# TypesPOVSubmissionResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**pov_id** | **str** | | +**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesPOVSubmissionResponse from a JSON string +types_pov_submission_response_instance = TypesPOVSubmissionResponse.from_json(json) +# print the JSON string representation of the object +print(TypesPOVSubmissionResponse.to_json()) + +# convert the object into a dict +types_pov_submission_response_dict = types_pov_submission_response_instance.to_dict() +# create an instance of TypesPOVSubmissionResponse from a dict +types_pov_submission_response_from_dict = TypesPOVSubmissionResponse.from_dict(types_pov_submission_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesPatchSubmission.md b/orchestrator/docs/TypesPatchSubmission.md index a11eab8e..99a010c0 100644 --- a/orchestrator/docs/TypesPatchSubmission.md +++ b/orchestrator/docs/TypesPatchSubmission.md @@ -5,10 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**description** | **str** | Optional plain text reasoning for the assessment 128KiB max size | [optional] **patch** | **str** | Base64 encoded patch in unified diff format 100KiB max size before Base64 encoding | -**sarif_id** | **str** | Optional ID of SARIF Broadcast this patch is associated with | [optional] -**vuln_id** | **str** | Optional ID of Vuln this patch is associated with | [optional] ## Example diff --git a/orchestrator/docs/TypesPatchSubmissionResponse.md b/orchestrator/docs/TypesPatchSubmissionResponse.md index ee0b2fe8..933e07df 100644 --- a/orchestrator/docs/TypesPatchSubmissionResponse.md +++ b/orchestrator/docs/TypesPatchSubmissionResponse.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**functionality_tests_passing** | **bool** | null indicates the tests have not been run | [optional] **patch_id** | **str** | | **status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | diff --git a/orchestrator/docs/TypesPingResponse.md b/orchestrator/docs/TypesPingResponse.md new file mode 100644 index 00000000..8f2c2b03 --- /dev/null +++ b/orchestrator/docs/TypesPingResponse.md @@ -0,0 +1,29 @@ +# TypesPingResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**status** | **str** | | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesPingResponse from a JSON string +types_ping_response_instance = TypesPingResponse.from_json(json) +# print the JSON string representation of the object +print(TypesPingResponse.to_json()) + +# convert the object into a dict +types_ping_response_dict = types_ping_response_instance.to_dict() +# create an instance of TypesPingResponse from a dict +types_ping_response_from_dict = TypesPingResponse.from_dict(types_ping_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesSARIFSubmission.md b/orchestrator/docs/TypesSARIFSubmission.md new file mode 100644 index 00000000..d30a2e77 --- /dev/null +++ b/orchestrator/docs/TypesSARIFSubmission.md @@ -0,0 +1,29 @@ +# TypesSARIFSubmission + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**sarif** | **object** | SARIF object compliant with the provided schema | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesSARIFSubmission from a JSON string +types_sarif_submission_instance = TypesSARIFSubmission.from_json(json) +# print the JSON string representation of the object +print(TypesSARIFSubmission.to_json()) + +# convert the object into a dict +types_sarif_submission_dict = types_sarif_submission_instance.to_dict() +# create an instance of TypesSARIFSubmission from a dict +types_sarif_submission_from_dict = TypesSARIFSubmission.from_dict(types_sarif_submission_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesSARIFSubmissionResponse.md b/orchestrator/docs/TypesSARIFSubmissionResponse.md new file mode 100644 index 00000000..79c74248 --- /dev/null +++ b/orchestrator/docs/TypesSARIFSubmissionResponse.md @@ -0,0 +1,30 @@ +# TypesSARIFSubmissionResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | +**submitted_sarif_id** | **str** | | + +## Example + +```python +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesSARIFSubmissionResponse from a JSON string +types_sarif_submission_response_instance = TypesSARIFSubmissionResponse.from_json(json) +# print the JSON string representation of the object +print(TypesSARIFSubmissionResponse.to_json()) + +# convert the object into a dict +types_sarif_submission_response_dict = types_sarif_submission_response_instance.to_dict() +# create an instance of TypesSARIFSubmissionResponse from a dict +types_sarif_submission_response_from_dict = TypesSARIFSubmissionResponse.from_dict(types_sarif_submission_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/orchestrator/docs/TypesSubmissionStatus.md b/orchestrator/docs/TypesSubmissionStatus.md index 1ab418b5..13a9401c 100644 --- a/orchestrator/docs/TypesSubmissionStatus.md +++ b/orchestrator/docs/TypesSubmissionStatus.md @@ -5,14 +5,14 @@ * `ACCEPTED` (value: `'accepted'`) -* `INVALID` (value: `'invalid'`) - * `PASSED` (value: `'passed'`) * `FAILED` (value: `'failed'`) * `DEADLINE_EXCEEDED` (value: `'deadline_exceeded'`) +* `ERRORED` (value: `'errored'`) + [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/orchestrator/docs/TypesVulnSubmission.md b/orchestrator/docs/TypesVulnSubmission.md deleted file mode 100644 index b98714fa..00000000 --- a/orchestrator/docs/TypesVulnSubmission.md +++ /dev/null @@ -1,33 +0,0 @@ -# TypesVulnSubmission - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**architecture** | [**TypesArchitecture**](TypesArchitecture.md) | | -**data_file** | **str** | Base64 encoded vuln trigger 2MiB max size before Base64 encoding | -**harness_name** | **str** | Fuzz Tooling Harness Name that exercises this vuln 4KiB max size | -**sanitizer** | **str** | Fuzz Tooling Sanitizer that exercises this vuln 4KiB max size | -**sarif** | **object** | Optional SARIF Report compliant with the provided versioned SARIF schema | [optional] - -## Example - -```python -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission - -# TODO update the JSON string below -json = "{}" -# create an instance of TypesVulnSubmission from a JSON string -types_vuln_submission_instance = TypesVulnSubmission.from_json(json) -# print the JSON string representation of the object -print(TypesVulnSubmission.to_json()) - -# convert the object into a dict -types_vuln_submission_dict = types_vuln_submission_instance.to_dict() -# create an instance of TypesVulnSubmission from a dict -types_vuln_submission_from_dict = TypesVulnSubmission.from_dict(types_vuln_submission_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/orchestrator/docs/TypesVulnSubmissionResponse.md b/orchestrator/docs/TypesVulnSubmissionResponse.md deleted file mode 100644 index 22a2b3ef..00000000 --- a/orchestrator/docs/TypesVulnSubmissionResponse.md +++ /dev/null @@ -1,30 +0,0 @@ -# TypesVulnSubmissionResponse - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**status** | [**TypesSubmissionStatus**](TypesSubmissionStatus.md) | | -**vuln_id** | **str** | | - -## Example - -```python -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse - -# TODO update the JSON string below -json = "{}" -# create an instance of TypesVulnSubmissionResponse from a JSON string -types_vuln_submission_response_instance = TypesVulnSubmissionResponse.from_json(json) -# print the JSON string representation of the object -print(TypesVulnSubmissionResponse.to_json()) - -# convert the object into a dict -types_vuln_submission_response_dict = types_vuln_submission_response_instance.to_dict() -# create an instance of TypesVulnSubmissionResponse from a dict -types_vuln_submission_response_from_dict = TypesVulnSubmissionResponse.from_dict(types_vuln_submission_response_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/orchestrator/docs/api/CHANGELOG.md b/orchestrator/docs/api/CHANGELOG.md index c0a6ad35..a8b2eea8 100644 --- a/orchestrator/docs/api/CHANGELOG.md +++ b/orchestrator/docs/api/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## v1.1 + +- add ping endpoint to test network connectivity and credentials +- crs status endpoint requires authentication + +## v1.0 + +- add freeform submission +- add freeform submission to bundle +- add `harnesses_included` boolean to task broadcasts +- **BREAKING CHANGE**: add new required `engine` field to pov submission. valid values are found in the `project.yaml` + +## v0.4 + +- added bundle workflow +- removed SARIF Broadcast ID, Vuln ID, and description from patch submission +- renamed vuln submissions to pov submissions +- renamed sarif assessments to broadcast-sarif-assessments +- removed sarif submissions from vuln +- added new endpoint for sarif submissions +- added new errored state to possible statuses for server-side testing errors + +For more information, see: + +- [The v0.4 readme](./api-v0.4-readme.md) +- [The v0.4 OpenAPI specification](./competition-swagger-v0.4.yaml) + ## v0.3 - Change invalid / valid in SARIF assessment to correct / incorrect diff --git a/orchestrator/docs/api/README.md b/orchestrator/docs/api/README.md index 10eca906..57e61007 100644 --- a/orchestrator/docs/api/README.md +++ b/orchestrator/docs/api/README.md @@ -1,7 +1,9 @@ # API -- Competitors will consume the API described by `competition-swagger-v0.3.yaml` -- Competitors will provide the API described by `crs-swagger-v0.3.yaml` +See the [API Changelog](./docs/api/CHANGELOG.md) for information on recent API changes. + +- Competitors will consume the API described by `competition-swagger-v1.1.yaml` +- Competitors will provide the API described by `crs-swagger-v1.1.yaml` NOTE: The JSON and YAML documents contain the same information and are generated from the same source. @@ -51,17 +53,17 @@ The competition-time workflows for interacting with the Competition API are docu ```mermaid sequenceDiagram - accTitle: CRS Vuln Submission Workflow + accTitle: CRS POV Submission Workflow API->>CRS: Task(s) - CRS->>API: Vuln Submission - API->>CRS: Vuln ID, Vuln Status "accepted" - API->>API: Vuln Testing - CRS->>API: Vuln Status Polling - API->>CRS: Current Vuln Status ("accepted") - API->>API: Vuln Testing Complete, update status to "passed" or "failed" - CRS->>API: Vuln Status Polling - API->>CRS: Current Vuln Status ("passed" or "failed") + CRS->>API: POV Submission + API->>CRS: POV ID, Vuln Status "accepted" + API->>API: POV Testing + CRS->>API: POV Status Polling + API->>CRS: Current POV Status ("accepted") + API->>API: POV Testing Complete, update status to "passed", "failed", or "errored" + CRS->>API: POV Status Polling + API->>CRS: Current POV Status ("passed", "failed", or "errored") ``` ### Submitting a SARIF assessment @@ -81,15 +83,27 @@ sequenceDiagram sequenceDiagram accTitle: CRS Patch Submission Workflow - API->>CRS: Task(s) and/or SARIF Broadcast - CRS->>API: Patch Submission (optionally against an existing vuln or SARIF broadcast) + API->>CRS: Task(s) + CRS->>API: Patch Submission API->>CRS: Patch ID, Patch Status "accepted" API->>API: Patch Testing CRS->>API: Patch Status Polling API->>CRS: Current Patch Status ("accepted") - API->>API: Patch Testing Complete, update status to "passed" or "failed" + API->>API: Patch Testing Complete, update status to "passed", "failed", or "errored" CRS->>API: Patch Status Polling - API->>CRS: Current Patch Status ("passed" or "failed") + API->>CRS: Current Patch Status ("passed", "failed", "errored") +``` + +### Submitting a bundle + +```mermaid +sequenceDiagram + accTitle: CRS Bundle Submission Workflow + +API->>CRS: Task(s) +CRS->>API: POV Submission, Patch Submission, SARIF Assessment, SARIF Submission, ... +CRS->>API: Create Bundle "accepted" +CRS->>API: Modify Bundle ``` ## CRS API Task Statuses diff --git a/orchestrator/docs/api/api-v0.4-readme.md b/orchestrator/docs/api/api-v0.4-readme.md new file mode 100644 index 00000000..01d071c7 --- /dev/null +++ b/orchestrator/docs/api/api-v0.4-readme.md @@ -0,0 +1,287 @@ +# Competition API v0.4 + +## Competition API Endpoints + +### Proof of Vulnerability + +#### Changes in v0.4 + +- The optional SARIF field has been moved to its own endpoint. +- This endpoint moved from `/v1/task//vuln` to `/v1/task//pov` to remove use of the overloaded term "vulnerability". +- Initial returned submission status can never be `invalid`. +- The `invalid` status was removed since there was no way for it to be hit. +- There is a new status `errored` indicating a server-side issue when testing a PoV. If you see this status, your CRS should resubmit. +- Two fields have been renamed to match the corresponding argument names from OSSFuzz’s `helper.py`: `data_file` is now `testcase` and `harness_name` is now `fuzzer_name`. + +#### Submission + +```javascript +POST /v1/task//pov + +{ + "testcase": "base64 data", + "fuzzer_name": "which harness to pass the data file to", + "sanitizer": "which sanitizer to build the project with", + "architecture": "x86_64", # required to be this value +} +``` + +##### Response + +Submissions that do not fit the schema will receive a 400 error describing the schema mismatch. They do not receive an ID. + +All complete and on-time submissions will get an `accepted` status back. Submissions after the deadline will get `deadline_exceeeded`. + +```javascript +200 OK +{ + "pov_id": "", + "status": "accepted" | "deadline_exceeded" +} +``` + +#### Status + +```javascript +GET /v1/task//pov/ +``` + +##### Response + +Requests for a nonexistent `pov_id` will get a 404 back with no body. + +The additional statuses which submissions can enter over time are: + +- `passed`: the submission was tested and all tests passed. +- `failed`: the submission was tested and failed at least one test. +- `errored`: the submission was tested and there was a server-side error testing it. + +```javascript +200 OK +{ + "pov_id": "", + "status": "accepted" | "passed" | "failed" | "deadline_exceeded" | "errored" +} +``` + +### Patch + +#### Changes in v0.4 + +- The optional proof of vulnerability ID, broadcast SARIF ID, and plaintext description have been moved to a separate endpoint (the `bundle` endpoint). +- Functionality test results are now available to competitors separate from overall patch status. + +#### Submission + +```javascript +POST /v1/task//patch + +{ + "patch": "base64 data" +} +``` + +##### Response + +Submissions that do not fit the schema will receive a 400 error describing the schema mismatch. They do not receive an ID. + +All complete and on-time submissions will get an `accepted` status back. Submissions after the deadline will get `deadline_exceeeded`. + +```javascript +200 OK +{ + "patch_id": "", + "status": "accepted" | "deadline_exceeded" +} +``` + +#### Status + +```javascript +GET /v1/task//patch/ +``` + +##### Response + +Requests for a nonexistent `patch_id` will get a 404 back with no body. + +The additional statuses which submissions can enter over time are: + +- `passed`: the submission applied, the project built, and the functionality tests passed. +- `failed`: the submission failed to apply, build, or pass the tests. +- `errored`: there was a server-side error testing the submission. + +There is an additional field, `functionality_tests_passing`, which contains a separate status for the functionality tests. The overall patch status still includes the functionality test result (i.e. the functionality +tests must have passed for the patch to be `passed`). + +If the functionality tests have not been run, the `functionality_tests_passing` field will be `null`. + +```javascript +{ + "patch_id": "", + "status": "accepted" | "passed" | "failed" | "deadline_exceeded" | "errored", + "functionality_tests_passing": true | false | null +} +``` + +### Broadcast SARIF Assessment + +#### Changes in v0.4 + +- SARIFs sent to CRSs are now referred to as "broadcast SARIFs" to distinguish them from those submitted by the CRS. +- This endpoint moved from `/v1/task//sarif/` to `/v1/task//broadcast-sarif-assessment/` +- It is worth noting that only Broadcast SARIFs can be assessed using this endpoint. CRS-submitted SARIFs receive an ID (via a separate endpoint which is new in v0.4) but that ID cannot be used with this endpoint. + +#### Submission + +```javascript +POST /v1/task//broadcast-sarif-assessment/ +``` + +##### Response + +Broadcast SARIF Assessments do not return an ID since there is no further action to be taken with them. + +Submissions that do not fit the schema will receive a 400 error describing the schema mismatch. They do not receive an ID. + +All complete and on-time submissions will get an `accepted` status back. Submissions after the deadline will get `deadline_exceeeded`. + +```javascript +200 OK +{ + "status": "accepted" | "deadline_exceeded" +} +``` + +### SARIF Submission + +#### Changes in v0.4 + +- CRS-submitted SARIFs are now referred to as "submitted SARIFs" to distinguish them from those broadcasted by the Competition Infrastructure ("broadcast SARIFs"). +- This endpoint is brand new in v0.4, but it should receive the content your CRS was already sending via the Proof of Vulnerability Submission Endpoint's optional SARIF field. +- Submitted SARIFs must use explicit rules, not just text descriptions attached to locations in code. Submitted SARIFs must have `rule_id` set on any `result` objects. + +#### Submission + +```javascript +POST /v1/task//submitted-sarif +{ + "sarif": {} # SARIF-formatted object. +} +``` + +##### Response + +Submissions that do not fit the schema will receive a 400 error describing the schema mismatch. They do not receive an ID. + +All complete and on-time submissions will get an `accepted` status back. Submissions after the deadline will get `deadline_exceeeded`. + +```javascript +200 OK +{ + "submitted_sarif_id": "", + "status": "accepted" | "deadline_exceeded" +} +``` + +### Submission Association ("Bundling") + +Previously, your CRS was able to submit SARIFs only when submitting vulnerabilities. It could also attach vulnerabilities it found, or broadcast SARIFs it received, to any patches it created later. + +It could not: + +- Submit patches first and attach vulnerabilities found later +- Submit patches first and attach broadcast SARIFs it received later (the organizers think this will be a common use case) +- Submit vulnerabilities first and attach SARIFs generated later + +It could also not attach SARIFs to patches it generated. There were several associations the organizers wanted to enable CRSs to make that were not possible. + +This endpoint introduces a new entity called a "bundle" which represents an association of any subset of other entities (broadcast SARIF, submitted SARIF, patch, and proof of vulnerability). + +#### Creation + +All fields are optional, but new bundles containing less than two items are rejected with a 400 error and do not receive an ID. + +```javascript +POST /v1/task//bundle +{ + "pov_id": "", + "patch_id": "", + "submitted_sarif_id": "", + "broadcast_sarif_id": "", + "description": "optional plaintext description containing any additional information to explain the CRS's findings" +} +``` + +##### Response + +Bundles that do not fit the schema will receive a 400 error describing the schema mismatch. They do not receive an ID. + +All complete and on-time submissions will get an `accepted` status back. Submissions after the deadline will get `deadline_exceeeded`. + +```javascript +200 OK +{ + "bundle_id": "", + "status": "accepted" | "deadline_exceeded" +} +``` + +#### Adding to a bundle + +Already created bundles can have any of their fields changed, additional fields set, or any field unset. + +Pass only the fields you want to modify. Other fields will be unchanged. + +Patching with an invalid schema will return a 400\. + +Patching a field to `null` unsets it. + +```javascript +PATCH /v1/task//bundle/ +{ + "pov_id": "" | null, + "patch_id": "" | null, + "submitted_sarif_id": "" | null, + "broadcast_sarif_id": "" | null, + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report" | null +} +``` + +#### Status + +Requests for a nonexistent `bundle_id` will get a 404 back with no body. + +This endpoint returns the content of the bundle with a couple of additional fields to describe the status of the bundle. + +```javascript +GET /v1/task//bundle/ +``` + +##### Response + +```javascript +200 OK +{ + "pov_id": "", + "patch_id": "", + "submitted_sarif_id": "", + "broadcast_sarif_id": "", + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report", + "status": "accepted" | "deadline_exceeded" +} +``` + +#### Deleting a bundle + +Requests for a nonexistent `bundle_id` will get a 404 back with no body. + +```javascript +DELETE /v1/task//bundle/ +``` + +##### Response + +```javascript +204 No Content +``` diff --git a/orchestrator/docs/api/auth.md b/orchestrator/docs/api/auth.md deleted file mode 100644 index 952e6939..00000000 --- a/orchestrator/docs/api/auth.md +++ /dev/null @@ -1,106 +0,0 @@ -# CRS Task Server Authentication - -The CRS Task Server uses HTTP Basic Authentication with Argon2id-hashed tokens for secure access control. - -## Authentication System - -The authentication system uses: - -- **Key ID**: A UUID that identifies the API key (used as username in HTTP Basic Auth) -- **Token**: A secure random string (used as password in HTTP Basic Auth) -- **Argon2id**: A modern, secure hashing algorithm for password storage - -Tokens are stored as Argon2id hashes, which provides strong protection against various attacks, including: -- Brute force attacks -- Rainbow table attacks -- Side-channel attacks - -## Generating API Keys - -To generate a new API key and token, use the provided CLI tool: - -```bash -# Generate a new API key and display the information -buttercup-auth-tool - -# Generate a new API key and format as environment variables -buttercup-auth-tool --env - -# Generate a new API key with a custom token length -buttercup-auth-tool --token-length 64 -``` - -## Configuring API Keys - -Configure the Task Server by setting the following environment variables: - -### Environment Variables - -Configure the authentication using the following environment variables: - -- `BUTTERCUP_TASK_SERVER_API_KEY_ID`: The UUID key identifier for authentication -- `BUTTERCUP_TASK_SERVER_API_TOKEN_HASH`: The Argon2id hash of the authentication token - -Example: -```bash -export BUTTERCUP_TASK_SERVER_API_KEY_ID="123e4567-e89b-12d3-a456-426614174000" -export BUTTERCUP_TASK_SERVER_API_TOKEN_HASH="$argon2id$v=19$m=65536,t=3,p=4$..." -``` - -### Using the Auth Tool - -The `buttercup-auth-tool` can be used to generate these values in the correct format: - -```bash -# Generate values and display them -buttercup-auth-tool --env -``` - -The tool will output: -1. Server-side environment variables (with the `BUTTERCUP_TASK_SERVER_` prefix) -2. Client-side authentication credentials (API_KEY_ID and API_TOKEN) for use in API requests - -You can export the server-side environment variables directly: -```bash -# Export server environment variables directly -$(buttercup-auth-tool --env | grep BUTTERCUP | sed 's/^/export /') -``` - -## Making Authenticated Requests - -When making requests to the Task Server, clients must provide authentication credentials using HTTP Basic Auth: - -1. **Username**: The UUID API key ID (generated by the auth tool) -2. **Password**: The plaintext token (generated by the auth tool) - -Example with curl: -```bash -curl -X POST "http://localhost:8000/v1/task/" \ - -H "Content-Type: application/json" \ - -u "550e8400-e29b-41d4-a716-446655440000:abcDEF123456XYZghi789jklMNOP" \ - -d '{"name":"example"}' -``` - -Example in Python: -```python -import requests - -# API key ID and token generated by buttercup-auth-tool -api_key_id = "550e8400-e29b-41d4-a716-446655440000" -api_token = "abcDEF123456XYZghi789jklMNOP" - -response = requests.post( - "http://localhost:8000/v1/task/", - auth=(api_key_id, api_token), - json={"name": "example"} -) -``` - -**Important**: The client only needs the key ID and plaintext token - NOT the Argon2id hash. The hash is only used server-side to verify the token. - -## Security Considerations - -- Store API tokens securely and never commit them to version control -- Use HTTPS in production environments to protect tokens in transit -- Rotate tokens periodically for improved security -- Consider using environment-specific tokens for different deployment environments \ No newline at end of file diff --git a/orchestrator/docs/api/competition-swagger-v0.4.json b/orchestrator/docs/api/competition-swagger-v0.4.json new file mode 100644 index 00000000..ef00ca70 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v0.4.json @@ -0,0 +1,899 @@ +{ + "swagger": "2.0", + "info": { + "title": "Example Competition API", + "contact": {}, + "version": "0.4" + }, + "paths": { + "/v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a SARIF assessment", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["broadcast-sarif-assessment"], + "summary": "Submit a SARIF Assessment", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Broadcast SARIF ID", + "name": "broadcast_sarif_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SarifAssessmentSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SarifAssessmentResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Submit Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/{bundle_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "get a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Get Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "delete a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Delete Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "patch": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "updates a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Update Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a patch for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Submit Patch", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.PatchSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/{patch_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of patch testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Patch Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Patch ID", + "name": "patch_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a vulnerability for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Submit Vulnerability", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.POVSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/{pov_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of vuln testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Vulnerability Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "POV ID", + "name": "pov_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/submitted-sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a CRS generated SARIF", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["submitted-sarif"], + "summary": "Submit a CRS generated SARIF", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SARIFSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + } + }, + "definitions": { + "types.Architecture": { + "type": "string", + "enum": ["x86_64"], + "x-enum-varnames": ["ArchitectureX864"] + }, + "types.Assessment": { + "type": "string", + "enum": ["correct", "incorrect"], + "x-enum-varnames": ["AssessmentCorrect", "AssessmentIncorrect"] + }, + "types.BundleSubmission": { + "type": "object", + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report", + "type": "string" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.BundleSubmissionResponse": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.BundleSubmissionResponseVerbose": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "type": "string" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.Error": { + "type": "object", + "required": ["message"], + "properties": { + "fields": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "message": { + "type": "string" + } + } + }, + "types.POVSubmission": { + "type": "object", + "required": ["architecture", "fuzzer_name", "sanitizer", "testcase"], + "properties": { + "architecture": { + "$ref": "#/definitions/types.Architecture" + }, + "fuzzer_name": { + "description": "Fuzz Tooling Harness Name that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "sanitizer": { + "description": "Fuzz Tooling Sanitizer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "testcase": { + "description": "Base64 encoded vuln trigger\n\n2MiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.POVSubmissionResponse": { + "type": "object", + "required": ["pov_id", "status"], + "properties": { + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.PatchSubmission": { + "type": "object", + "required": ["patch"], + "properties": { + "patch": { + "description": "Base64 encoded patch in unified diff format\n\n100KiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.PatchSubmissionResponse": { + "type": "object", + "required": ["patch_id", "status"], + "properties": { + "functionality_tests_passing": { + "description": "null indicates the tests have not been run", + "type": "boolean" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.SARIFSubmission": { + "type": "object", + "required": ["sarif"], + "properties": { + "sarif": { + "description": "SARIF object compliant with the provided schema", + "type": "object" + } + } + }, + "types.SARIFSubmissionResponse": { + "type": "object", + "required": ["status", "submitted_sarif_id"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.SarifAssessmentResponse": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.SarifAssessmentSubmission": { + "type": "object", + "required": ["assessment", "description"], + "properties": { + "assessment": { + "$ref": "#/definitions/types.Assessment" + }, + "description": { + "description": "Plain text reasoning for the assessment\n\n128KiB max size", + "type": "string", + "maxLength": 131072 + } + } + }, + "types.SubmissionStatus": { + "type": "string", + "enum": ["accepted", "passed", "failed", "deadline_exceeded", "errored"], + "x-enum-comments": { + "SubmissionStatusAccepted": "Successfully submitted", + "SubmissionStatusDeadlineExceeded": "Task deadline exceeded. All submissions marked accepted before the deadline will be evaluated.", + "SubmissionStatusErrored": "Server side error when testing submission", + "SubmissionStatusFailed": "Submission failed testing", + "SubmissionStatusPassed": "Successfully evaluated submission" + }, + "x-enum-varnames": [ + "SubmissionStatusAccepted", + "SubmissionStatusPassed", + "SubmissionStatusFailed", + "SubmissionStatusDeadlineExceeded", + "SubmissionStatusErrored" + ] + } + }, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + } + } +} diff --git a/orchestrator/docs/api/competition-swagger-v0.4.yaml b/orchestrator/docs/api/competition-swagger-v0.4.yaml new file mode 100644 index 00000000..c1d879b9 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v0.4.yaml @@ -0,0 +1,692 @@ +definitions: + types.Architecture: + enum: + - x86_64 + type: string + x-enum-varnames: + - ArchitectureX864 + types.Assessment: + enum: + - correct + - incorrect + type: string + x-enum-varnames: + - AssessmentCorrect + - AssessmentIncorrect + types.BundleSubmission: + properties: + broadcast_sarif_id: + format: uuid + type: string + description: + description: + optional plaintext description of the components of the bundle, + such as would be found in a pull request description or bug report + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + submitted_sarif_id: + format: uuid + type: string + type: object + types.BundleSubmissionResponse: + properties: + bundle_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - bundle_id + - status + type: object + types.BundleSubmissionResponseVerbose: + properties: + broadcast_sarif_id: + format: uuid + type: string + bundle_id: + format: uuid + type: string + description: + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - bundle_id + - status + type: object + types.Error: + properties: + fields: + additionalProperties: + type: string + type: object + message: + type: string + required: + - message + type: object + types.POVSubmission: + properties: + architecture: + $ref: "#/definitions/types.Architecture" + fuzzer_name: + description: |- + Fuzz Tooling Harness Name that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + sanitizer: + description: |- + Fuzz Tooling Sanitizer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + testcase: + description: |- + Base64 encoded vuln trigger + + 2MiB max size before Base64 encoding + format: base64 + type: string + required: + - architecture + - fuzzer_name + - sanitizer + - testcase + type: object + types.POVSubmissionResponse: + properties: + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - pov_id + - status + type: object + types.PatchSubmission: + properties: + patch: + description: |- + Base64 encoded patch in unified diff format + + 100KiB max size before Base64 encoding + format: base64 + type: string + required: + - patch + type: object + types.PatchSubmissionResponse: + properties: + functionality_tests_passing: + description: null indicates the tests have not been run + type: boolean + patch_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - patch_id + - status + type: object + types.SARIFSubmission: + properties: + sarif: + description: SARIF object compliant with the provided schema + type: object + required: + - sarif + type: object + types.SARIFSubmissionResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - status + - submitted_sarif_id + type: object + types.SarifAssessmentResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - status + type: object + types.SarifAssessmentSubmission: + properties: + assessment: + $ref: "#/definitions/types.Assessment" + description: + description: |- + Plain text reasoning for the assessment + + 128KiB max size + maxLength: 131072 + type: string + required: + - assessment + - description + type: object + types.SubmissionStatus: + enum: + - accepted + - passed + - failed + - deadline_exceeded + - errored + type: string + x-enum-comments: + SubmissionStatusAccepted: Successfully submitted + SubmissionStatusDeadlineExceeded: + Task deadline exceeded. All submissions marked + accepted before the deadline will be evaluated. + SubmissionStatusErrored: Server side error when testing submission + SubmissionStatusFailed: Submission failed testing + SubmissionStatusPassed: Successfully evaluated submission + x-enum-varnames: + - SubmissionStatusAccepted + - SubmissionStatusPassed + - SubmissionStatusFailed + - SubmissionStatusDeadlineExceeded + - SubmissionStatusErrored +info: + contact: {} + title: Example Competition API + version: "0.4" +paths: + /v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/: + post: + consumes: + - application/json + description: Submit a SARIF assessment + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Broadcast SARIF ID + format: uuid + in: path + name: broadcast_sarif_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SarifAssessmentSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SarifAssessmentResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a SARIF Assessment + tags: + - broadcast-sarif-assessment + /v1/task/{task_id}/bundle/: + post: + consumes: + - application/json + description: submits a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Bundle + tags: + - bundle + /v1/task/{task_id}/bundle/{bundle_id}/: + delete: + consumes: + - application/json + description: delete a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Delete Bundle + tags: + - bundle + get: + consumes: + - application/json + description: get a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Get Bundle + tags: + - bundle + patch: + consumes: + - application/json + description: updates a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Update Bundle + tags: + - bundle + /v1/task/{task_id}/patch/: + post: + consumes: + - application/json + description: submit a patch for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Payload + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.PatchSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Patch + tags: + - patch + /v1/task/{task_id}/patch/{patch_id}/: + get: + consumes: + - application/json + description: yield the status of patch testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Patch ID + format: uuid + in: path + name: patch_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Patch Status + tags: + - patch + /v1/task/{task_id}/pov/: + post: + consumes: + - application/json + description: submit a vulnerability for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.POVSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Vulnerability + tags: + - pov + /v1/task/{task_id}/pov/{pov_id}/: + get: + consumes: + - application/json + description: yield the status of vuln testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: POV ID + format: uuid + in: path + name: pov_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Vulnerability Status + tags: + - pov + /v1/task/{task_id}/submitted-sarif/: + post: + consumes: + - application/json + description: Submit a CRS generated SARIF + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SARIFSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a CRS generated SARIF + tags: + - submitted-sarif +securityDefinitions: + BasicAuth: + type: basic +swagger: "2.0" diff --git a/orchestrator/docs/api/competition-swagger-v1.0.json b/orchestrator/docs/api/competition-swagger-v1.0.json new file mode 100644 index 00000000..04e076a2 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v1.0.json @@ -0,0 +1,1006 @@ +{ + "swagger": "2.0", + "info": { + "title": "Example Competition API", + "contact": {}, + "version": "1.0" + }, + "paths": { + "/v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a SARIF assessment", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["broadcast-sarif-assessment"], + "summary": "Submit a SARIF Assessment", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Broadcast SARIF ID", + "name": "broadcast_sarif_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SarifAssessmentSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SarifAssessmentResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Submit Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/{bundle_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "get a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Get Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "delete a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Delete Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "patch": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "updates a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Update Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/freeform/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a freeform pov", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["feeform"], + "summary": "Submit Freeform", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.FreeformSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.FreeformResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a patch for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Submit Patch", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.PatchSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/{patch_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of patch testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Patch Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Patch ID", + "name": "patch_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a vulnerability for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Submit Vulnerability", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.POVSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/{pov_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of vuln testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Vulnerability Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "POV ID", + "name": "pov_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/submitted-sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a CRS generated SARIF", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["submitted-sarif"], + "summary": "Submit a CRS generated SARIF", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SARIFSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + } + }, + "definitions": { + "types.Architecture": { + "type": "string", + "enum": ["x86_64"], + "x-enum-varnames": ["ArchitectureX8664"] + }, + "types.Assessment": { + "type": "string", + "enum": ["correct", "incorrect"], + "x-enum-varnames": ["AssessmentCorrect", "AssessmentIncorrect"] + }, + "types.BundleSubmission": { + "type": "object", + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report", + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.BundleSubmissionResponse": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.BundleSubmissionResponseVerbose": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.Error": { + "type": "object", + "required": ["message"], + "properties": { + "fields": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "message": { + "type": "string" + } + } + }, + "types.FreeformResponse": { + "type": "object", + "required": ["freeform_id", "status"], + "properties": { + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.FreeformSubmission": { + "type": "object", + "required": ["submission"], + "properties": { + "submission": { + "description": "Base64 encoded arbitrary data\n\n2MiB max size before Base64 encoding", + "type": "string" + } + } + }, + "types.POVSubmission": { + "type": "object", + "required": [ + "architecture", + "engine", + "fuzzer_name", + "sanitizer", + "testcase" + ], + "properties": { + "architecture": { + "$ref": "#/definitions/types.Architecture" + }, + "engine": { + "description": "Fuzz Tooling Engine that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "fuzzer_name": { + "description": "Fuzz Tooling fuzzer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "sanitizer": { + "description": "Fuzz Tooling Sanitizer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "testcase": { + "description": "Base64 encoded vuln trigger\n\n2MiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.POVSubmissionResponse": { + "type": "object", + "required": ["pov_id", "status"], + "properties": { + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.PatchSubmission": { + "type": "object", + "required": ["patch"], + "properties": { + "patch": { + "description": "Base64 encoded patch in unified diff format\n\n100KiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.PatchSubmissionResponse": { + "type": "object", + "required": ["patch_id", "status"], + "properties": { + "functionality_tests_passing": { + "description": "null indicates the tests have not been run", + "type": "boolean" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.SARIFSubmission": { + "type": "object", + "required": ["sarif"], + "properties": { + "sarif": { + "description": "SARIF object compliant with the provided schema", + "type": "object" + } + } + }, + "types.SARIFSubmissionResponse": { + "type": "object", + "required": ["status", "submitted_sarif_id"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.SarifAssessmentResponse": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.SarifAssessmentSubmission": { + "type": "object", + "required": ["assessment", "description"], + "properties": { + "assessment": { + "$ref": "#/definitions/types.Assessment" + }, + "description": { + "description": "Plain text reasoning for the assessment\n\n128KiB max size", + "type": "string", + "maxLength": 131072 + } + } + }, + "types.SubmissionStatus": { + "type": "string", + "enum": ["accepted", "passed", "failed", "deadline_exceeded", "errored"], + "x-enum-comments": { + "SubmissionStatusAccepted": "Successfully submitted", + "SubmissionStatusDeadlineExceeded": "Task deadline exceeded. All submissions marked accepted before the deadline will be evaluated.", + "SubmissionStatusErrored": "Server side error when testing submission", + "SubmissionStatusFailed": "Submission failed testing", + "SubmissionStatusPassed": "Successfully evaluated submission" + }, + "x-enum-varnames": [ + "SubmissionStatusAccepted", + "SubmissionStatusPassed", + "SubmissionStatusFailed", + "SubmissionStatusDeadlineExceeded", + "SubmissionStatusErrored" + ] + } + }, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + } + } +} diff --git a/orchestrator/docs/api/competition-swagger-v1.0.yaml b/orchestrator/docs/api/competition-swagger-v1.0.yaml new file mode 100644 index 00000000..995e08c2 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v1.0.yaml @@ -0,0 +1,774 @@ +definitions: + types.Architecture: + enum: + - x86_64 + type: string + x-enum-varnames: + - ArchitectureX8664 + types.Assessment: + enum: + - correct + - incorrect + type: string + x-enum-varnames: + - AssessmentCorrect + - AssessmentIncorrect + types.BundleSubmission: + properties: + broadcast_sarif_id: + format: uuid + type: string + description: + description: + optional plaintext description of the components of the bundle, + such as would be found in a pull request description or bug report + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + submitted_sarif_id: + format: uuid + type: string + type: object + types.BundleSubmissionResponse: + properties: + bundle_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - bundle_id + - status + type: object + types.BundleSubmissionResponseVerbose: + properties: + broadcast_sarif_id: + format: uuid + type: string + bundle_id: + format: uuid + type: string + description: + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - bundle_id + - status + type: object + types.Error: + properties: + fields: + additionalProperties: + type: string + type: object + message: + type: string + required: + - message + type: object + types.FreeformResponse: + properties: + freeform_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - freeform_id + - status + type: object + types.FreeformSubmission: + properties: + submission: + description: |- + Base64 encoded arbitrary data + + 2MiB max size before Base64 encoding + type: string + required: + - submission + type: object + types.POVSubmission: + properties: + architecture: + $ref: "#/definitions/types.Architecture" + engine: + description: |- + Fuzz Tooling Engine that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + fuzzer_name: + description: |- + Fuzz Tooling fuzzer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + sanitizer: + description: |- + Fuzz Tooling Sanitizer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + testcase: + description: |- + Base64 encoded vuln trigger + + 2MiB max size before Base64 encoding + format: base64 + type: string + required: + - architecture + - engine + - fuzzer_name + - sanitizer + - testcase + type: object + types.POVSubmissionResponse: + properties: + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - pov_id + - status + type: object + types.PatchSubmission: + properties: + patch: + description: |- + Base64 encoded patch in unified diff format + + 100KiB max size before Base64 encoding + format: base64 + type: string + required: + - patch + type: object + types.PatchSubmissionResponse: + properties: + functionality_tests_passing: + description: null indicates the tests have not been run + type: boolean + patch_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - patch_id + - status + type: object + types.SARIFSubmission: + properties: + sarif: + description: SARIF object compliant with the provided schema + type: object + required: + - sarif + type: object + types.SARIFSubmissionResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - status + - submitted_sarif_id + type: object + types.SarifAssessmentResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - status + type: object + types.SarifAssessmentSubmission: + properties: + assessment: + $ref: "#/definitions/types.Assessment" + description: + description: |- + Plain text reasoning for the assessment + + 128KiB max size + maxLength: 131072 + type: string + required: + - assessment + - description + type: object + types.SubmissionStatus: + enum: + - accepted + - passed + - failed + - deadline_exceeded + - errored + type: string + x-enum-comments: + SubmissionStatusAccepted: Successfully submitted + SubmissionStatusDeadlineExceeded: + Task deadline exceeded. All submissions marked + accepted before the deadline will be evaluated. + SubmissionStatusErrored: Server side error when testing submission + SubmissionStatusFailed: Submission failed testing + SubmissionStatusPassed: Successfully evaluated submission + x-enum-varnames: + - SubmissionStatusAccepted + - SubmissionStatusPassed + - SubmissionStatusFailed + - SubmissionStatusDeadlineExceeded + - SubmissionStatusErrored +info: + contact: {} + title: Example Competition API + version: "1.0" +paths: + /v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/: + post: + consumes: + - application/json + description: Submit a SARIF assessment + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Broadcast SARIF ID + format: uuid + in: path + name: broadcast_sarif_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SarifAssessmentSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SarifAssessmentResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a SARIF Assessment + tags: + - broadcast-sarif-assessment + /v1/task/{task_id}/bundle/: + post: + consumes: + - application/json + description: submits a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Bundle + tags: + - bundle + /v1/task/{task_id}/bundle/{bundle_id}/: + delete: + consumes: + - application/json + description: delete a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Delete Bundle + tags: + - bundle + get: + consumes: + - application/json + description: get a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Get Bundle + tags: + - bundle + patch: + consumes: + - application/json + description: updates a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Update Bundle + tags: + - bundle + /v1/task/{task_id}/freeform/: + post: + consumes: + - application/json + description: submits a freeform pov + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.FreeformSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.FreeformResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Freeform + tags: + - feeform + /v1/task/{task_id}/patch/: + post: + consumes: + - application/json + description: submit a patch for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Payload + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.PatchSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Patch + tags: + - patch + /v1/task/{task_id}/patch/{patch_id}/: + get: + consumes: + - application/json + description: yield the status of patch testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Patch ID + format: uuid + in: path + name: patch_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Patch Status + tags: + - patch + /v1/task/{task_id}/pov/: + post: + consumes: + - application/json + description: submit a vulnerability for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.POVSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Vulnerability + tags: + - pov + /v1/task/{task_id}/pov/{pov_id}/: + get: + consumes: + - application/json + description: yield the status of vuln testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: POV ID + format: uuid + in: path + name: pov_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Vulnerability Status + tags: + - pov + /v1/task/{task_id}/submitted-sarif/: + post: + consumes: + - application/json + description: Submit a CRS generated SARIF + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SARIFSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a CRS generated SARIF + tags: + - submitted-sarif +securityDefinitions: + BasicAuth: + type: basic +swagger: "2.0" diff --git a/orchestrator/docs/api/competition-swagger-v1.1.json b/orchestrator/docs/api/competition-swagger-v1.1.json new file mode 100644 index 00000000..9fd35f44 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v1.1.json @@ -0,0 +1,1036 @@ +{ + "swagger": "2.0", + "info": { + "title": "Example Competition API", + "contact": {}, + "version": "1.1" + }, + "paths": { + "/v1/ping/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Test authentication creds and network connectivity", + "consumes": ["application/json"], + "tags": ["ping"], + "summary": "Test authentication creds and network connectivity", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PingResponse" + } + } + } + } + }, + "/v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a SARIF assessment", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["broadcast-sarif-assessment"], + "summary": "Submit a SARIF Assessment", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Broadcast SARIF ID", + "name": "broadcast_sarif_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SarifAssessmentSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SarifAssessmentResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Submit Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/{bundle_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "get a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Get Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "delete a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Delete Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "patch": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "updates a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Update Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/freeform/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a freeform pov", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["feeform"], + "summary": "Submit Freeform", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.FreeformSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.FreeformResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a patch for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Submit Patch", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.PatchSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/patch/{patch_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of patch testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["patch"], + "summary": "Patch Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Patch ID", + "name": "patch_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PatchSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a vulnerability for testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Submit Vulnerability", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.POVSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/pov/{pov_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "yield the status of vuln testing", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["pov"], + "summary": "Vulnerability Status", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "POV ID", + "name": "pov_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/submitted-sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a CRS generated SARIF", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["submitted-sarif"], + "summary": "Submit a CRS generated SARIF", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SARIFSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + } + }, + "definitions": { + "types.Architecture": { + "type": "string", + "enum": ["x86_64"], + "x-enum-varnames": ["ArchitectureX8664"] + }, + "types.Assessment": { + "type": "string", + "enum": ["correct", "incorrect"], + "x-enum-varnames": ["AssessmentCorrect", "AssessmentIncorrect"] + }, + "types.BundleSubmission": { + "type": "object", + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report", + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.BundleSubmissionResponse": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.BundleSubmissionResponseVerbose": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.Error": { + "type": "object", + "required": ["message"], + "properties": { + "fields": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "message": { + "type": "string" + } + } + }, + "types.FreeformResponse": { + "type": "object", + "required": ["freeform_id", "status"], + "properties": { + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.FreeformSubmission": { + "type": "object", + "required": ["submission"], + "properties": { + "submission": { + "description": "Base64 encoded arbitrary data\n\n2MiB max size before Base64 encoding", + "type": "string" + } + } + }, + "types.POVSubmission": { + "type": "object", + "required": [ + "architecture", + "engine", + "fuzzer_name", + "sanitizer", + "testcase" + ], + "properties": { + "architecture": { + "$ref": "#/definitions/types.Architecture" + }, + "engine": { + "description": "Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml.\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "fuzzer_name": { + "description": "Fuzz Tooling fuzzer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "sanitizer": { + "description": "Fuzz Tooling Sanitizer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "testcase": { + "description": "Base64 encoded vuln trigger\n\n2MiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.POVSubmissionResponse": { + "type": "object", + "required": ["pov_id", "status"], + "properties": { + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.PatchSubmission": { + "type": "object", + "required": ["patch"], + "properties": { + "patch": { + "description": "Base64 encoded patch in unified diff format\n\n100KiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.PatchSubmissionResponse": { + "type": "object", + "required": ["patch_id", "status"], + "properties": { + "functionality_tests_passing": { + "description": "null indicates the tests have not been run", + "type": "boolean" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.PingResponse": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + } + }, + "types.SARIFSubmission": { + "type": "object", + "required": ["sarif"], + "properties": { + "sarif": { + "description": "SARIF object compliant with the provided schema", + "type": "object" + } + } + }, + "types.SARIFSubmissionResponse": { + "type": "object", + "required": ["status", "submitted_sarif_id"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.SarifAssessmentResponse": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.SarifAssessmentSubmission": { + "type": "object", + "required": ["assessment", "description"], + "properties": { + "assessment": { + "$ref": "#/definitions/types.Assessment" + }, + "description": { + "description": "Plain text reasoning for the assessment\n\n128KiB max size", + "type": "string", + "maxLength": 131072 + } + } + }, + "types.SubmissionStatus": { + "type": "string", + "enum": ["accepted", "passed", "failed", "deadline_exceeded", "errored"], + "x-enum-comments": { + "SubmissionStatusAccepted": "Successfully submitted", + "SubmissionStatusDeadlineExceeded": "Task deadline exceeded. All submissions marked accepted before the deadline will be evaluated.", + "SubmissionStatusErrored": "Server side error when testing submission", + "SubmissionStatusFailed": "Submission failed testing", + "SubmissionStatusPassed": "Successfully evaluated submission" + }, + "x-enum-varnames": [ + "SubmissionStatusAccepted", + "SubmissionStatusPassed", + "SubmissionStatusFailed", + "SubmissionStatusDeadlineExceeded", + "SubmissionStatusErrored" + ] + } + }, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + } + } +} diff --git a/orchestrator/docs/api/competition-swagger-v1.1.yaml b/orchestrator/docs/api/competition-swagger-v1.1.yaml new file mode 100644 index 00000000..baeb1a44 --- /dev/null +++ b/orchestrator/docs/api/competition-swagger-v1.1.yaml @@ -0,0 +1,796 @@ +definitions: + types.Architecture: + enum: + - x86_64 + type: string + x-enum-varnames: + - ArchitectureX8664 + types.Assessment: + enum: + - correct + - incorrect + type: string + x-enum-varnames: + - AssessmentCorrect + - AssessmentIncorrect + types.BundleSubmission: + properties: + broadcast_sarif_id: + format: uuid + type: string + description: + description: + optional plaintext description of the components of the bundle, + such as would be found in a pull request description or bug report + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + submitted_sarif_id: + format: uuid + type: string + type: object + types.BundleSubmissionResponse: + properties: + bundle_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - bundle_id + - status + type: object + types.BundleSubmissionResponseVerbose: + properties: + broadcast_sarif_id: + format: uuid + type: string + bundle_id: + format: uuid + type: string + description: + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - bundle_id + - status + type: object + types.Error: + properties: + fields: + additionalProperties: + type: string + type: object + message: + type: string + required: + - message + type: object + types.FreeformResponse: + properties: + freeform_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - freeform_id + - status + type: object + types.FreeformSubmission: + properties: + submission: + description: |- + Base64 encoded arbitrary data + + 2MiB max size before Base64 encoding + type: string + required: + - submission + type: object + types.POVSubmission: + properties: + architecture: + $ref: "#/definitions/types.Architecture" + engine: + description: |- + Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml. + + 4KiB max size + maxLength: 4096 + type: string + fuzzer_name: + description: |- + Fuzz Tooling fuzzer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + sanitizer: + description: |- + Fuzz Tooling Sanitizer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + testcase: + description: |- + Base64 encoded vuln trigger + + 2MiB max size before Base64 encoding + format: base64 + type: string + required: + - architecture + - engine + - fuzzer_name + - sanitizer + - testcase + type: object + types.POVSubmissionResponse: + properties: + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - pov_id + - status + type: object + types.PatchSubmission: + properties: + patch: + description: |- + Base64 encoded patch in unified diff format + + 100KiB max size before Base64 encoding + format: base64 + type: string + required: + - patch + type: object + types.PatchSubmissionResponse: + properties: + functionality_tests_passing: + description: null indicates the tests have not been run + type: boolean + patch_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - patch_id + - status + type: object + types.PingResponse: + properties: + status: + type: string + required: + - status + type: object + types.SARIFSubmission: + properties: + sarif: + description: SARIF object compliant with the provided schema + type: object + required: + - sarif + type: object + types.SARIFSubmissionResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - status + - submitted_sarif_id + type: object + types.SarifAssessmentResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - status + type: object + types.SarifAssessmentSubmission: + properties: + assessment: + $ref: "#/definitions/types.Assessment" + description: + description: |- + Plain text reasoning for the assessment + + 128KiB max size + maxLength: 131072 + type: string + required: + - assessment + - description + type: object + types.SubmissionStatus: + enum: + - accepted + - passed + - failed + - deadline_exceeded + - errored + type: string + x-enum-comments: + SubmissionStatusAccepted: Successfully submitted + SubmissionStatusDeadlineExceeded: + Task deadline exceeded. All submissions marked + accepted before the deadline will be evaluated. + SubmissionStatusErrored: Server side error when testing submission + SubmissionStatusFailed: Submission failed testing + SubmissionStatusPassed: Successfully evaluated submission + x-enum-varnames: + - SubmissionStatusAccepted + - SubmissionStatusPassed + - SubmissionStatusFailed + - SubmissionStatusDeadlineExceeded + - SubmissionStatusErrored +info: + contact: {} + title: Example Competition API + version: "1.1" +paths: + /v1/ping/: + get: + consumes: + - application/json + description: Test authentication creds and network connectivity + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PingResponse" + security: + - BasicAuth: [] + summary: Test authentication creds and network connectivity + tags: + - ping + /v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/: + post: + consumes: + - application/json + description: Submit a SARIF assessment + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Broadcast SARIF ID + format: uuid + in: path + name: broadcast_sarif_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SarifAssessmentSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SarifAssessmentResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a SARIF Assessment + tags: + - broadcast-sarif-assessment + /v1/task/{task_id}/bundle/: + post: + consumes: + - application/json + description: submits a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Bundle + tags: + - bundle + /v1/task/{task_id}/bundle/{bundle_id}/: + delete: + consumes: + - application/json + description: delete a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Delete Bundle + tags: + - bundle + get: + consumes: + - application/json + description: get a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Get Bundle + tags: + - bundle + patch: + consumes: + - application/json + description: updates a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Update Bundle + tags: + - bundle + /v1/task/{task_id}/freeform/: + post: + consumes: + - application/json + description: submits a freeform pov + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.FreeformSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.FreeformResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Freeform + tags: + - feeform + /v1/task/{task_id}/patch/: + post: + consumes: + - application/json + description: submit a patch for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Payload + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.PatchSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Patch + tags: + - patch + /v1/task/{task_id}/patch/{patch_id}/: + get: + consumes: + - application/json + description: yield the status of patch testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Patch ID + format: uuid + in: path + name: patch_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PatchSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Patch Status + tags: + - patch + /v1/task/{task_id}/pov/: + post: + consumes: + - application/json + description: submit a vulnerability for testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.POVSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Vulnerability + tags: + - pov + /v1/task/{task_id}/pov/{pov_id}/: + get: + consumes: + - application/json + description: yield the status of vuln testing + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: POV ID + format: uuid + in: path + name: pov_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.POVSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Vulnerability Status + tags: + - pov + /v1/task/{task_id}/submitted-sarif/: + post: + consumes: + - application/json + description: Submit a CRS generated SARIF + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SARIFSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a CRS generated SARIF + tags: + - submitted-sarif +securityDefinitions: + BasicAuth: + type: basic +swagger: "2.0" diff --git a/orchestrator/docs/api/competition-swagger.json b/orchestrator/docs/api/competition-swagger.json index c88ffa90..9fd35f44 100644 --- a/orchestrator/docs/api/competition-swagger.json +++ b/orchestrator/docs/api/competition-swagger.json @@ -3,9 +3,430 @@ "info": { "title": "Example Competition API", "contact": {}, - "version": "0.3" + "version": "1.1" }, "paths": { + "/v1/ping/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Test authentication creds and network connectivity", + "consumes": ["application/json"], + "tags": ["ping"], + "summary": "Test authentication creds and network connectivity", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.PingResponse" + } + } + } + } + }, + "/v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a SARIF assessment", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["broadcast-sarif-assessment"], + "summary": "Submit a SARIF Assessment", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Broadcast SARIF ID", + "name": "broadcast_sarif_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SarifAssessmentSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SarifAssessmentResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Submit Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/bundle/{bundle_id}/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "get a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Get Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "delete a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Delete Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + }, + "patch": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "updates a bundle", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["bundle"], + "summary": "Update Bundle", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Bundle ID", + "name": "bundle_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.BundleSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.BundleSubmissionResponseVerbose" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/freeform/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submits a freeform pov", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["feeform"], + "summary": "Submit Freeform", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission Body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.FreeformSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.FreeformResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, "/v1/task/{task_id}/patch/": { "post": { "security": [ @@ -135,80 +556,7 @@ } } }, - "/v1/task/{task_id}/sarif/{sarif_id}/": { - "post": { - "security": [ - { - "BasicAuth": [] - } - ], - "description": "submit a sarif assessment", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["sarif"], - "summary": "Submit Sarif Assessment", - "parameters": [ - { - "type": "string", - "format": "uuid", - "description": "Task ID", - "name": "task_id", - "in": "path", - "required": true - }, - { - "type": "string", - "format": "uuid", - "description": "SARIF ID", - "name": "sarif_id", - "in": "path", - "required": true - }, - { - "description": "Submission body", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/types.SarifAssessmentSubmission" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/types.SarifAssessmentResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/types.Error" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/types.Error" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/types.Error" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/types.Error" - } - } - } - } - }, - "/v1/task/{task_id}/vuln/": { + "/v1/task/{task_id}/pov/": { "post": { "security": [ { @@ -218,7 +566,7 @@ "description": "submit a vulnerability for testing", "consumes": ["application/json"], "produces": ["application/json"], - "tags": ["vulnerability"], + "tags": ["pov"], "summary": "Submit Vulnerability", "parameters": [ { @@ -235,7 +583,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/types.VulnSubmission" + "$ref": "#/definitions/types.POVSubmission" } } ], @@ -243,7 +591,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/types.VulnSubmissionResponse" + "$ref": "#/definitions/types.POVSubmissionResponse" } }, "400": { @@ -273,7 +621,7 @@ } } }, - "/v1/task/{task_id}/vuln/{vuln_id}/": { + "/v1/task/{task_id}/pov/{pov_id}/": { "get": { "security": [ { @@ -283,7 +631,7 @@ "description": "yield the status of vuln testing", "consumes": ["application/json"], "produces": ["application/json"], - "tags": ["vulnerability"], + "tags": ["pov"], "summary": "Vulnerability Status", "parameters": [ { @@ -297,8 +645,8 @@ { "type": "string", "format": "uuid", - "description": "Vuln ID", - "name": "vuln_id", + "description": "POV ID", + "name": "pov_id", "in": "path", "required": true } @@ -307,7 +655,72 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/types.VulnSubmissionResponse" + "$ref": "#/definitions/types.POVSubmissionResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/types.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/types.Error" + } + } + } + } + }, + "/v1/task/{task_id}/submitted-sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Submit a CRS generated SARIF", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["submitted-sarif"], + "summary": "Submit a CRS generated SARIF", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + }, + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFSubmission" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.SARIFSubmissionResponse" } }, "400": { @@ -342,13 +755,91 @@ "types.Architecture": { "type": "string", "enum": ["x86_64"], - "x-enum-varnames": ["ArchitectureX864"] + "x-enum-varnames": ["ArchitectureX8664"] }, "types.Assessment": { "type": "string", "enum": ["correct", "incorrect"], "x-enum-varnames": ["AssessmentCorrect", "AssessmentIncorrect"] }, + "types.BundleSubmission": { + "type": "object", + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "description": "optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report", + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.BundleSubmissionResponse": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.BundleSubmissionResponseVerbose": { + "type": "object", + "required": ["bundle_id", "status"], + "properties": { + "broadcast_sarif_id": { + "type": "string", + "format": "uuid" + }, + "bundle_id": { + "type": "string", + "format": "uuid" + }, + "description": { + "type": "string" + }, + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "patch_id": { + "type": "string", + "format": "uuid" + }, + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, "types.Error": { "type": "object", "required": ["message"], @@ -364,29 +855,85 @@ } } }, + "types.FreeformResponse": { + "type": "object", + "required": ["freeform_id", "status"], + "properties": { + "freeform_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, + "types.FreeformSubmission": { + "type": "object", + "required": ["submission"], + "properties": { + "submission": { + "description": "Base64 encoded arbitrary data\n\n2MiB max size before Base64 encoding", + "type": "string" + } + } + }, + "types.POVSubmission": { + "type": "object", + "required": [ + "architecture", + "engine", + "fuzzer_name", + "sanitizer", + "testcase" + ], + "properties": { + "architecture": { + "$ref": "#/definitions/types.Architecture" + }, + "engine": { + "description": "Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml.\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "fuzzer_name": { + "description": "Fuzz Tooling fuzzer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "sanitizer": { + "description": "Fuzz Tooling Sanitizer that exercises this vuln\n\n4KiB max size", + "type": "string", + "maxLength": 4096 + }, + "testcase": { + "description": "Base64 encoded vuln trigger\n\n2MiB max size before Base64 encoding", + "type": "string", + "format": "base64" + } + } + }, + "types.POVSubmissionResponse": { + "type": "object", + "required": ["pov_id", "status"], + "properties": { + "pov_id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + } + } + }, "types.PatchSubmission": { "type": "object", "required": ["patch"], "properties": { - "description": { - "description": "Optional plain text reasoning for the assessment\n\n128KiB max size", - "type": "string", - "maxLength": 131072 - }, "patch": { "description": "Base64 encoded patch in unified diff format\n\n100KiB max size before Base64 encoding", "type": "string", "format": "base64" - }, - "sarif_id": { - "description": "Optional ID of SARIF Broadcast this patch is associated with", - "type": "string", - "format": "uuid" - }, - "vuln_id": { - "description": "Optional ID of Vuln this patch is associated with", - "type": "string", - "format": "uuid" } } }, @@ -394,6 +941,10 @@ "type": "object", "required": ["patch_id", "status"], "properties": { + "functionality_tests_passing": { + "description": "null indicates the tests have not been run", + "type": "boolean" + }, "patch_id": { "type": "string", "format": "uuid" @@ -403,6 +954,38 @@ } } }, + "types.PingResponse": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + } + }, + "types.SARIFSubmission": { + "type": "object", + "required": ["sarif"], + "properties": { + "sarif": { + "description": "SARIF object compliant with the provided schema", + "type": "object" + } + } + }, + "types.SARIFSubmissionResponse": { + "type": "object", + "required": ["status", "submitted_sarif_id"], + "properties": { + "status": { + "$ref": "#/definitions/types.SubmissionStatus" + }, + "submitted_sarif_id": { + "type": "string", + "format": "uuid" + } + } + }, "types.SarifAssessmentResponse": { "type": "object", "required": ["status"], @@ -428,61 +1011,21 @@ }, "types.SubmissionStatus": { "type": "string", - "enum": ["accepted", "invalid", "passed", "failed", "deadline_exceeded"], + "enum": ["accepted", "passed", "failed", "deadline_exceeded", "errored"], "x-enum-comments": { "SubmissionStatusAccepted": "Successfully submitted", "SubmissionStatusDeadlineExceeded": "Task deadline exceeded. All submissions marked accepted before the deadline will be evaluated.", + "SubmissionStatusErrored": "Server side error when testing submission", "SubmissionStatusFailed": "Submission failed testing", "SubmissionStatusPassed": "Successfully evaluated submission" }, "x-enum-varnames": [ "SubmissionStatusAccepted", - "SubmissionStatusInvalid", "SubmissionStatusPassed", "SubmissionStatusFailed", - "SubmissionStatusDeadlineExceeded" + "SubmissionStatusDeadlineExceeded", + "SubmissionStatusErrored" ] - }, - "types.VulnSubmission": { - "type": "object", - "required": ["architecture", "data_file", "harness_name", "sanitizer"], - "properties": { - "architecture": { - "$ref": "#/definitions/types.Architecture" - }, - "data_file": { - "description": "Base64 encoded vuln trigger\n\n2MiB max size before Base64 encoding", - "type": "string", - "format": "base64" - }, - "harness_name": { - "description": "Fuzz Tooling Harness Name that exercises this vuln\n\n4KiB max size", - "type": "string", - "maxLength": 4096 - }, - "sanitizer": { - "description": "Fuzz Tooling Sanitizer that exercises this vuln\n\n4KiB max size", - "type": "string", - "maxLength": 4096 - }, - "sarif": { - "description": "Optional SARIF Report compliant with the provided versioned SARIF schema", - "type": "object" - } - } - }, - "types.VulnSubmissionResponse": { - "type": "object", - "required": ["status", "vuln_id"], - "properties": { - "status": { - "$ref": "#/definitions/types.SubmissionStatus" - }, - "vuln_id": { - "type": "string", - "format": "uuid" - } - } } }, "securityDefinitions": { diff --git a/orchestrator/docs/api/competition-swagger.yaml b/orchestrator/docs/api/competition-swagger.yaml index c039dbfe..baeb1a44 100644 --- a/orchestrator/docs/api/competition-swagger.yaml +++ b/orchestrator/docs/api/competition-swagger.yaml @@ -4,7 +4,7 @@ definitions: - x86_64 type: string x-enum-varnames: - - ArchitectureX864 + - ArchitectureX8664 types.Assessment: enum: - correct @@ -13,6 +13,68 @@ definitions: x-enum-varnames: - AssessmentCorrect - AssessmentIncorrect + types.BundleSubmission: + properties: + broadcast_sarif_id: + format: uuid + type: string + description: + description: + optional plaintext description of the components of the bundle, + such as would be found in a pull request description or bug report + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + submitted_sarif_id: + format: uuid + type: string + type: object + types.BundleSubmissionResponse: + properties: + bundle_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - bundle_id + - status + type: object + types.BundleSubmissionResponseVerbose: + properties: + broadcast_sarif_id: + format: uuid + type: string + bundle_id: + format: uuid + type: string + description: + type: string + freeform_id: + format: uuid + type: string + patch_id: + format: uuid + type: string + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - bundle_id + - status + type: object types.Error: properties: fields: @@ -24,35 +86,95 @@ definitions: required: - message type: object + types.FreeformResponse: + properties: + freeform_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - freeform_id + - status + type: object + types.FreeformSubmission: + properties: + submission: + description: |- + Base64 encoded arbitrary data + + 2MiB max size before Base64 encoding + type: string + required: + - submission + type: object + types.POVSubmission: + properties: + architecture: + $ref: "#/definitions/types.Architecture" + engine: + description: |- + Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml. + + 4KiB max size + maxLength: 4096 + type: string + fuzzer_name: + description: |- + Fuzz Tooling fuzzer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + sanitizer: + description: |- + Fuzz Tooling Sanitizer that exercises this vuln + + 4KiB max size + maxLength: 4096 + type: string + testcase: + description: |- + Base64 encoded vuln trigger + + 2MiB max size before Base64 encoding + format: base64 + type: string + required: + - architecture + - engine + - fuzzer_name + - sanitizer + - testcase + type: object + types.POVSubmissionResponse: + properties: + pov_id: + format: uuid + type: string + status: + $ref: "#/definitions/types.SubmissionStatus" + required: + - pov_id + - status + type: object types.PatchSubmission: properties: - description: - description: |- - Optional plain text reasoning for the assessment - - 128KiB max size - maxLength: 131072 - type: string patch: description: |- Base64 encoded patch in unified diff format - 128KiB max size before Base64 encoding + 100KiB max size before Base64 encoding format: base64 type: string - sarif_id: - description: Optional ID of SARIF Broadcast this patch is associated with - format: uuid - type: string - vuln_id: - description: Optional ID of Vuln this patch is associated with - format: uuid - type: string required: - patch type: object types.PatchSubmissionResponse: properties: + functionality_tests_passing: + description: null indicates the tests have not been run + type: boolean patch_id: format: uuid type: string @@ -62,6 +184,32 @@ definitions: - patch_id - status type: object + types.PingResponse: + properties: + status: + type: string + required: + - status + type: object + types.SARIFSubmission: + properties: + sarif: + description: SARIF object compliant with the provided schema + type: object + required: + - sarif + type: object + types.SARIFSubmissionResponse: + properties: + status: + $ref: "#/definitions/types.SubmissionStatus" + submitted_sarif_id: + format: uuid + type: string + required: + - status + - submitted_sarif_id + type: object types.SarifAssessmentResponse: properties: status: @@ -87,76 +235,331 @@ definitions: types.SubmissionStatus: enum: - accepted - - invalid - passed - failed - deadline_exceeded + - errored type: string x-enum-comments: SubmissionStatusAccepted: Successfully submitted SubmissionStatusDeadlineExceeded: Task deadline exceeded. All submissions marked accepted before the deadline will be evaluated. + SubmissionStatusErrored: Server side error when testing submission SubmissionStatusFailed: Submission failed testing SubmissionStatusPassed: Successfully evaluated submission x-enum-varnames: - SubmissionStatusAccepted - - SubmissionStatusInvalid - SubmissionStatusPassed - SubmissionStatusFailed - SubmissionStatusDeadlineExceeded - types.VulnSubmission: - properties: - architecture: - $ref: "#/definitions/types.Architecture" - data_file: - description: |- - Base64 encoded vuln trigger - - 2MiB max size before Base64 encoding - format: base64 - type: string - harness_name: - description: |- - Fuzz Tooling Harness Name that exercises this vuln - - 4KiB max size - maxLength: 4096 - type: string - sanitizer: - description: |- - Fuzz Tooling Sanitizer that exercises this vuln - - 4KiB max size - maxLength: 4096 - type: string - sarif: - description: - Optional SARIF Report compliant with the provided versioned SARIF - schema - type: object - required: - - architecture - - data_file - - harness_name - - sanitizer - type: object - types.VulnSubmissionResponse: - properties: - status: - $ref: "#/definitions/types.SubmissionStatus" - vuln_id: - format: uuid - type: string - required: - - status - - vuln_id - type: object + - SubmissionStatusErrored info: contact: {} title: Example Competition API - version: "0.3" + version: "1.1" paths: + /v1/ping/: + get: + consumes: + - application/json + description: Test authentication creds and network connectivity + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.PingResponse" + security: + - BasicAuth: [] + summary: Test authentication creds and network connectivity + tags: + - ping + /v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/: + post: + consumes: + - application/json + description: Submit a SARIF assessment + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Broadcast SARIF ID + format: uuid + in: path + name: broadcast_sarif_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SarifAssessmentSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SarifAssessmentResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a SARIF Assessment + tags: + - broadcast-sarif-assessment + /v1/task/{task_id}/bundle/: + post: + consumes: + - application/json + description: submits a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Bundle + tags: + - bundle + /v1/task/{task_id}/bundle/{bundle_id}/: + delete: + consumes: + - application/json + description: delete a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Delete Bundle + tags: + - bundle + get: + consumes: + - application/json + description: get a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Get Bundle + tags: + - bundle + patch: + consumes: + - application/json + description: updates a bundle + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Bundle ID + format: uuid + in: path + name: bundle_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.BundleSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.BundleSubmissionResponseVerbose" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Update Bundle + tags: + - bundle + /v1/task/{task_id}/freeform/: + post: + consumes: + - application/json + description: submits a freeform pov + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission Body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.FreeformSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.FreeformResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit Freeform + tags: + - feeform /v1/task/{task_id}/patch/: post: consumes: @@ -249,59 +652,7 @@ paths: summary: Patch Status tags: - patch - /v1/task/{task_id}/sarif/{sarif_id}/: - post: - consumes: - - application/json - description: submit a sarif assessment - parameters: - - description: Task ID - format: uuid - in: path - name: task_id - required: true - type: string - - description: SARIF ID - format: uuid - in: path - name: sarif_id - required: true - type: string - - description: Submission body - in: body - name: payload - required: true - schema: - $ref: "#/definitions/types.SarifAssessmentSubmission" - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: "#/definitions/types.SarifAssessmentResponse" - "400": - description: Bad Request - schema: - $ref: "#/definitions/types.Error" - "401": - description: Unauthorized - schema: - $ref: "#/definitions/types.Error" - "404": - description: Not Found - schema: - $ref: "#/definitions/types.Error" - "500": - description: Internal Server Error - schema: - $ref: "#/definitions/types.Error" - security: - - BasicAuth: [] - summary: Submit Sarif Assessment - tags: - - sarif - /v1/task/{task_id}/vuln/: + /v1/task/{task_id}/pov/: post: consumes: - application/json @@ -318,14 +669,14 @@ paths: name: payload required: true schema: - $ref: "#/definitions/types.VulnSubmission" + $ref: "#/definitions/types.POVSubmission" produces: - application/json responses: "200": description: OK schema: - $ref: "#/definitions/types.VulnSubmissionResponse" + $ref: "#/definitions/types.POVSubmissionResponse" "400": description: Bad Request schema: @@ -346,8 +697,8 @@ paths: - BasicAuth: [] summary: Submit Vulnerability tags: - - vulnerability - /v1/task/{task_id}/vuln/{vuln_id}/: + - pov + /v1/task/{task_id}/pov/{pov_id}/: get: consumes: - application/json @@ -359,10 +710,10 @@ paths: name: task_id required: true type: string - - description: Vuln ID + - description: POV ID format: uuid in: path - name: vuln_id + name: pov_id required: true type: string produces: @@ -371,7 +722,7 @@ paths: "200": description: OK schema: - $ref: "#/definitions/types.VulnSubmissionResponse" + $ref: "#/definitions/types.POVSubmissionResponse" "400": description: Bad Request schema: @@ -392,7 +743,53 @@ paths: - BasicAuth: [] summary: Vulnerability Status tags: - - vulnerability + - pov + /v1/task/{task_id}/submitted-sarif/: + post: + consumes: + - application/json + description: Submit a CRS generated SARIF + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFSubmission" + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: "#/definitions/types.SARIFSubmissionResponse" + "400": + description: Bad Request + schema: + $ref: "#/definitions/types.Error" + "401": + description: Unauthorized + schema: + $ref: "#/definitions/types.Error" + "404": + description: Not Found + schema: + $ref: "#/definitions/types.Error" + "500": + description: Internal Server Error + schema: + $ref: "#/definitions/types.Error" + security: + - BasicAuth: [] + summary: Submit a CRS generated SARIF + tags: + - submitted-sarif securityDefinitions: BasicAuth: type: basic diff --git a/orchestrator/docs/api/crs-swagger-v1.0.json b/orchestrator/docs/api/crs-swagger-v1.0.json new file mode 100644 index 00000000..8fb89f4c --- /dev/null +++ b/orchestrator/docs/api/crs-swagger-v1.0.json @@ -0,0 +1,394 @@ +{ + "swagger": "2.0", + "info": { + "title": "Example CRS API", + "contact": {}, + "version": "1.0" + }, + "paths": { + "/status/": { + "get": { + "description": "UNAUTHENTICATED! report the status of the CRS", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["status"], + "summary": "CRS Status", + "responses": { + "200": { + "description": "Status Obect", + "schema": { + "$ref": "#/definitions/types.Status" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Reset all stats in the status endpoint.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["status"], + "summary": "Reset status stats", + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a sarif broadcast", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["sarif"], + "summary": "Submit Sarif Broadcast", + "parameters": [ + { + "description": "Vulnerability Broadcast", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFBroadcast" + } + } + ], + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/task/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a task for work", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Submit Task", + "parameters": [ + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.Task" + } + } + ], + "responses": { + "202": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Cancel all previously submitted tasks. This is meant for edge case recovery in case something goes wrong.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Cancel Tasks", + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/task/{task_id}/": { + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Cancel a task by id. This is meant for edge case recovery in case something goes wrong.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Cancel Task", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "types.SARIFBroadcast": { + "type": "object", + "required": ["broadcasts", "message_id", "message_time"], + "properties": { + "broadcasts": { + "type": "array", + "items": { + "$ref": "#/definitions/types.SARIFBroadcastDetail" + } + }, + "message_id": { + "type": "string", + "format": "uuid" + }, + "message_time": { + "type": "integer" + } + } + }, + "types.SARIFBroadcastDetail": { + "type": "object", + "required": ["metadata", "sarif", "sarif_id", "task_id"], + "properties": { + "metadata": { + "description": "String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability", + "type": "object" + }, + "sarif": { + "description": "SARIF Report compliant with provided schema", + "type": "object" + }, + "sarif_id": { + "type": "string", + "format": "uuid" + }, + "task_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.SourceDetail": { + "type": "object", + "required": ["sha256", "type", "url"], + "properties": { + "sha256": { + "description": "Integrity hash of the gzipped tarball", + "type": "string" + }, + "type": { + "$ref": "#/definitions/types.SourceType" + }, + "url": { + "description": "URL to fetch the source gzipped tarball", + "type": "string" + } + } + }, + "types.SourceType": { + "type": "string", + "enum": ["repo", "fuzz-tooling", "diff"], + "x-enum-varnames": [ + "SourceTypeRepo", + "SourceTypeFuzzTooling", + "SourceTypeDiff" + ] + }, + "types.Status": { + "type": "object", + "required": ["ready", "since", "state", "version"], + "properties": { + "details": { + "description": "This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting.\n\nKeep in mind this endpoint is unauthenticated. Do not place sensitive details in this object.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "ready": { + "type": "boolean" + }, + "since": { + "description": "Last time task and submission stats were reset", + "type": "integer" + }, + "state": { + "description": "State of the currently running tasks and submissions", + "allOf": [ + { + "$ref": "#/definitions/types.StatusState" + } + ] + }, + "version": { + "description": "Version string for verification and reproducibility\n\n- git commit\n\n- SemVer\n\n- etc", + "type": "string" + } + } + }, + "types.StatusState": { + "type": "object", + "required": ["tasks"], + "properties": { + "tasks": { + "$ref": "#/definitions/types.StatusTasksState" + } + } + }, + "types.StatusTasksState": { + "type": "object", + "required": [ + "canceled", + "errored", + "failed", + "pending", + "processing", + "succeeded", + "waiting" + ], + "properties": { + "canceled": { + "description": "Number of tasks that competition infrastructure has cancelled", + "type": "integer" + }, + "errored": { + "description": "Number of tasks that the CRS encountered an unrecoverable issue for", + "type": "integer" + }, + "failed": { + "description": "Number of submissions that the competition infrastructure marked failed", + "type": "integer" + }, + "pending": { + "description": "Number of tasks that the CRS has not started work on", + "type": "integer" + }, + "processing": { + "description": "Number of tasks that the CRS is currently processing", + "type": "integer" + }, + "succeeded": { + "description": "Number of submissions that the competition infrastructure marked passed", + "type": "integer" + }, + "waiting": { + "description": "Number of submissions that the competition infrastructure is currently testing", + "type": "integer" + } + } + }, + "types.Task": { + "type": "object", + "required": ["message_id", "message_time", "tasks"], + "properties": { + "message_id": { + "type": "string", + "format": "uuid" + }, + "message_time": { + "type": "integer" + }, + "tasks": { + "type": "array", + "items": { + "$ref": "#/definitions/types.TaskDetail" + } + } + } + }, + "types.TaskDetail": { + "type": "object", + "required": [ + "deadline", + "focus", + "harnesses_included", + "metadata", + "project_name", + "source", + "task_id", + "type" + ], + "properties": { + "deadline": { + "description": "UNIX timestamp by which any submissions for this task must be in", + "type": "integer" + }, + "focus": { + "description": "Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project.\nIt is still set when there is only one repository.\n\nThis is the project the CRS is meant to submit vulns, patches, and SARIF assessments against.", + "type": "string" + }, + "harnesses_included": { + "type": "boolean" + }, + "metadata": { + "description": "String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability", + "type": "object" + }, + "project_name": { + "description": "OSS Fuzz project name", + "type": "string" + }, + "source": { + "description": "List of sources needed to evaluate a task", + "type": "array", + "items": { + "$ref": "#/definitions/types.SourceDetail" + } + }, + "task_id": { + "type": "string", + "format": "uuid" + }, + "type": { + "$ref": "#/definitions/types.TaskType" + } + } + }, + "types.TaskType": { + "type": "string", + "enum": ["full", "delta"], + "x-enum-varnames": ["TaskTypeFull", "TaskTypeDelta"] + } + }, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + } + } +} diff --git a/orchestrator/docs/api/crs-swagger-v1.0.yaml b/orchestrator/docs/api/crs-swagger-v1.0.yaml new file mode 100644 index 00000000..96e86531 --- /dev/null +++ b/orchestrator/docs/api/crs-swagger-v1.0.yaml @@ -0,0 +1,346 @@ +definitions: + types.SARIFBroadcast: + properties: + broadcasts: + items: + $ref: "#/definitions/types.SARIFBroadcastDetail" + type: array + message_id: + format: uuid + type: string + message_time: + type: integer + required: + - broadcasts + - message_id + - message_time + type: object + types.SARIFBroadcastDetail: + properties: + metadata: + description: + String to string map containing data that should be attached + to outputs like log messages and OpenTelemetry trace attributes for traceability + type: object + sarif: + description: SARIF Report compliant with provided schema + type: object + sarif_id: + format: uuid + type: string + task_id: + format: uuid + type: string + required: + - metadata + - sarif + - sarif_id + - task_id + type: object + types.SourceDetail: + properties: + sha256: + description: Integrity hash of the gzipped tarball + type: string + type: + $ref: "#/definitions/types.SourceType" + url: + description: URL to fetch the source gzipped tarball + type: string + required: + - sha256 + - type + - url + type: object + types.SourceType: + enum: + - repo + - fuzz-tooling + - diff + type: string + x-enum-varnames: + - SourceTypeRepo + - SourceTypeFuzzTooling + - SourceTypeDiff + types.Status: + properties: + details: + additionalProperties: + type: string + description: |- + This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting. + + Keep in mind this endpoint is unauthenticated. Do not place sensitive details in this object. + type: object + ready: + type: boolean + since: + description: Last time task and submission stats were reset + type: integer + state: + allOf: + - $ref: "#/definitions/types.StatusState" + description: State of the currently running tasks and submissions + version: + description: |- + Version string for verification and reproducibility + + - git commit + + - SemVer + + - etc + type: string + required: + - ready + - since + - state + - version + type: object + types.StatusState: + properties: + tasks: + $ref: "#/definitions/types.StatusTasksState" + required: + - tasks + type: object + types.StatusTasksState: + properties: + canceled: + description: Number of tasks that competition infrastructure has cancelled + type: integer + errored: + description: + Number of tasks that the CRS encountered an unrecoverable issue + for + type: integer + failed: + description: + Number of submissions that the competition infrastructure marked + failed + type: integer + pending: + description: Number of tasks that the CRS has not started work on + type: integer + processing: + description: Number of tasks that the CRS is currently processing + type: integer + succeeded: + description: + Number of submissions that the competition infrastructure marked + passed + type: integer + waiting: + description: + Number of submissions that the competition infrastructure is + currently testing + type: integer + required: + - canceled + - errored + - failed + - pending + - processing + - succeeded + - waiting + type: object + types.Task: + properties: + message_id: + format: uuid + type: string + message_time: + type: integer + tasks: + items: + $ref: "#/definitions/types.TaskDetail" + type: array + required: + - message_id + - message_time + - tasks + type: object + types.TaskDetail: + properties: + deadline: + description: + UNIX timestamp by which any submissions for this task must be + in + type: integer + focus: + description: |- + Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project. + It is still set when there is only one repository. + + This is the project the CRS is meant to submit vulns, patches, and SARIF assessments against. + type: string + harnesses_included: + type: boolean + metadata: + description: + String to string map containing data that should be attached + to outputs like log messages and OpenTelemetry trace attributes for traceability + type: object + project_name: + description: OSS Fuzz project name + type: string + source: + description: List of sources needed to evaluate a task + items: + $ref: "#/definitions/types.SourceDetail" + type: array + task_id: + format: uuid + type: string + type: + $ref: "#/definitions/types.TaskType" + required: + - deadline + - focus + - harnesses_included + - metadata + - project_name + - source + - task_id + - type + type: object + types.TaskType: + enum: + - full + - delta + type: string + x-enum-varnames: + - TaskTypeFull + - TaskTypeDelta +info: + contact: {} + title: Example CRS API + version: "1.0" +paths: + /status/: + delete: + consumes: + - application/json + description: Reset all stats in the status endpoint. + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Reset status stats + tags: + - status + get: + consumes: + - application/json + description: UNAUTHENTICATED! report the status of the CRS + produces: + - application/json + responses: + "200": + description: Status Obect + schema: + $ref: "#/definitions/types.Status" + summary: CRS Status + tags: + - status + /v1/sarif/: + post: + consumes: + - application/json + description: submit a sarif broadcast + parameters: + - description: Vulnerability Broadcast + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFBroadcast" + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Submit Sarif Broadcast + tags: + - sarif + /v1/task/: + delete: + consumes: + - application/json + description: + Cancel all previously submitted tasks. This is meant for edge case + recovery in case something goes wrong. + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Cancel Tasks + tags: + - task + post: + consumes: + - application/json + description: submit a task for work + parameters: + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.Task" + produces: + - application/json + responses: + "202": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Submit Task + tags: + - task + /v1/task/{task_id}/: + delete: + consumes: + - application/json + description: + Cancel a task by id. This is meant for edge case recovery in case + something goes wrong. + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Cancel Task + tags: + - task +securityDefinitions: + BasicAuth: + type: basic +swagger: "2.0" diff --git a/orchestrator/docs/api/crs-swagger-v1.1.json b/orchestrator/docs/api/crs-swagger-v1.1.json new file mode 100644 index 00000000..d8b2c961 --- /dev/null +++ b/orchestrator/docs/api/crs-swagger-v1.1.json @@ -0,0 +1,400 @@ +{ + "swagger": "2.0", + "info": { + "title": "Example CRS API", + "contact": {}, + "version": "1.1" + }, + "paths": { + "/status/": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "report the status of the CRS", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["status"], + "summary": "CRS Status", + "responses": { + "200": { + "description": "Status Obect", + "schema": { + "$ref": "#/definitions/types.Status" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Reset all stats in the status endpoint.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["status"], + "summary": "Reset status stats", + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/sarif/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a sarif broadcast", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["sarif"], + "summary": "Submit Sarif Broadcast", + "parameters": [ + { + "description": "Vulnerability Broadcast", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.SARIFBroadcast" + } + } + ], + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/task/": { + "post": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "submit a task for work", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Submit Task", + "parameters": [ + { + "description": "Submission body", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.Task" + } + } + ], + "responses": { + "202": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Cancel all previously submitted tasks. This is meant for edge case recovery in case something goes wrong.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Cancel Tasks", + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + }, + "/v1/task/{task_id}/": { + "delete": { + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Cancel a task by id. This is meant for edge case recovery in case something goes wrong.", + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["task"], + "summary": "Cancel Task", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Task ID", + "name": "task_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "No Content", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "types.SARIFBroadcast": { + "type": "object", + "required": ["broadcasts", "message_id", "message_time"], + "properties": { + "broadcasts": { + "type": "array", + "items": { + "$ref": "#/definitions/types.SARIFBroadcastDetail" + } + }, + "message_id": { + "type": "string", + "format": "uuid" + }, + "message_time": { + "type": "integer" + } + } + }, + "types.SARIFBroadcastDetail": { + "type": "object", + "required": ["metadata", "sarif", "sarif_id", "task_id"], + "properties": { + "metadata": { + "description": "String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability", + "type": "object" + }, + "sarif": { + "description": "SARIF Report compliant with provided schema", + "type": "object" + }, + "sarif_id": { + "type": "string", + "format": "uuid" + }, + "task_id": { + "type": "string", + "format": "uuid" + } + } + }, + "types.SourceDetail": { + "type": "object", + "required": ["sha256", "type", "url"], + "properties": { + "sha256": { + "description": "Integrity hash of the gzipped tarball", + "type": "string" + }, + "type": { + "$ref": "#/definitions/types.SourceType" + }, + "url": { + "description": "URL to fetch the source gzipped tarball", + "type": "string" + } + } + }, + "types.SourceType": { + "type": "string", + "enum": ["repo", "fuzz-tooling", "diff"], + "x-enum-varnames": [ + "SourceTypeRepo", + "SourceTypeFuzzTooling", + "SourceTypeDiff" + ] + }, + "types.Status": { + "type": "object", + "required": ["ready", "since", "state", "version"], + "properties": { + "details": { + "description": "This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "ready": { + "description": "Boolean indicating if the CRS is prepared to work on tasks. Do not return true unless you have successfully tested connectivity to the Competition API via /v1/ping/", + "type": "boolean" + }, + "since": { + "description": "Last time task and submission stats were reset", + "type": "integer" + }, + "state": { + "description": "State of the currently running tasks and submissions", + "allOf": [ + { + "$ref": "#/definitions/types.StatusState" + } + ] + }, + "version": { + "description": "Version string for verification and reproducibility.\n\n- git commit\n\n- SemVer\n\n- etc", + "type": "string" + } + } + }, + "types.StatusState": { + "type": "object", + "required": ["tasks"], + "properties": { + "tasks": { + "$ref": "#/definitions/types.StatusTasksState" + } + } + }, + "types.StatusTasksState": { + "type": "object", + "required": [ + "canceled", + "errored", + "failed", + "pending", + "processing", + "succeeded", + "waiting" + ], + "properties": { + "canceled": { + "description": "Number of tasks that competition infrastructure has cancelled", + "type": "integer" + }, + "errored": { + "description": "Number of tasks that the CRS encountered an unrecoverable issue for", + "type": "integer" + }, + "failed": { + "description": "Number of submissions that the competition infrastructure marked failed", + "type": "integer" + }, + "pending": { + "description": "Number of tasks that the CRS has not started work on", + "type": "integer" + }, + "processing": { + "description": "Number of tasks that the CRS is currently processing", + "type": "integer" + }, + "succeeded": { + "description": "Number of submissions that the competition infrastructure marked passed", + "type": "integer" + }, + "waiting": { + "description": "Number of submissions that the competition infrastructure is currently testing", + "type": "integer" + } + } + }, + "types.Task": { + "type": "object", + "required": ["message_id", "message_time", "tasks"], + "properties": { + "message_id": { + "type": "string", + "format": "uuid" + }, + "message_time": { + "type": "integer" + }, + "tasks": { + "type": "array", + "items": { + "$ref": "#/definitions/types.TaskDetail" + } + } + } + }, + "types.TaskDetail": { + "type": "object", + "required": [ + "deadline", + "focus", + "harnesses_included", + "metadata", + "project_name", + "source", + "task_id", + "type" + ], + "properties": { + "deadline": { + "description": "UNIX timestamp by which any submissions for this task must be in", + "type": "integer" + }, + "focus": { + "description": "Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project.\nIt is still set when there is only one repository.\n\nThis is the project the CRS is meant to submit vulns, patches, and SARIF assessments against.", + "type": "string" + }, + "harnesses_included": { + "type": "boolean" + }, + "metadata": { + "description": "String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability", + "type": "object" + }, + "project_name": { + "description": "OSS Fuzz project name", + "type": "string" + }, + "source": { + "description": "List of sources needed to evaluate a task", + "type": "array", + "items": { + "$ref": "#/definitions/types.SourceDetail" + } + }, + "task_id": { + "type": "string", + "format": "uuid" + }, + "type": { + "$ref": "#/definitions/types.TaskType" + } + } + }, + "types.TaskType": { + "type": "string", + "enum": ["full", "delta"], + "x-enum-varnames": ["TaskTypeFull", "TaskTypeDelta"] + } + }, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + } + } +} diff --git a/orchestrator/docs/api/crs-swagger-v1.1.yaml b/orchestrator/docs/api/crs-swagger-v1.1.yaml new file mode 100644 index 00000000..dc26eac3 --- /dev/null +++ b/orchestrator/docs/api/crs-swagger-v1.1.yaml @@ -0,0 +1,351 @@ +definitions: + types.SARIFBroadcast: + properties: + broadcasts: + items: + $ref: "#/definitions/types.SARIFBroadcastDetail" + type: array + message_id: + format: uuid + type: string + message_time: + type: integer + required: + - broadcasts + - message_id + - message_time + type: object + types.SARIFBroadcastDetail: + properties: + metadata: + description: + String to string map containing data that should be attached + to outputs like log messages and OpenTelemetry trace attributes for traceability + type: object + sarif: + description: SARIF Report compliant with provided schema + type: object + sarif_id: + format: uuid + type: string + task_id: + format: uuid + type: string + required: + - metadata + - sarif + - sarif_id + - task_id + type: object + types.SourceDetail: + properties: + sha256: + description: Integrity hash of the gzipped tarball + type: string + type: + $ref: "#/definitions/types.SourceType" + url: + description: URL to fetch the source gzipped tarball + type: string + required: + - sha256 + - type + - url + type: object + types.SourceType: + enum: + - repo + - fuzz-tooling + - diff + type: string + x-enum-varnames: + - SourceTypeRepo + - SourceTypeFuzzTooling + - SourceTypeDiff + types.Status: + properties: + details: + additionalProperties: + type: string + description: + This is optional arbitrary content that may be logged in error + cases, but is mainly for interactive troubleshooting. + type: object + ready: + description: + Boolean indicating if the CRS is prepared to work on tasks. Do + not return true unless you have successfully tested connectivity to the + Competition API via /v1/ping/ + type: boolean + since: + description: Last time task and submission stats were reset + type: integer + state: + allOf: + - $ref: "#/definitions/types.StatusState" + description: State of the currently running tasks and submissions + version: + description: |- + Version string for verification and reproducibility. + + - git commit + + - SemVer + + - etc + type: string + required: + - ready + - since + - state + - version + type: object + types.StatusState: + properties: + tasks: + $ref: "#/definitions/types.StatusTasksState" + required: + - tasks + type: object + types.StatusTasksState: + properties: + canceled: + description: Number of tasks that competition infrastructure has cancelled + type: integer + errored: + description: + Number of tasks that the CRS encountered an unrecoverable issue + for + type: integer + failed: + description: + Number of submissions that the competition infrastructure marked + failed + type: integer + pending: + description: Number of tasks that the CRS has not started work on + type: integer + processing: + description: Number of tasks that the CRS is currently processing + type: integer + succeeded: + description: + Number of submissions that the competition infrastructure marked + passed + type: integer + waiting: + description: + Number of submissions that the competition infrastructure is + currently testing + type: integer + required: + - canceled + - errored + - failed + - pending + - processing + - succeeded + - waiting + type: object + types.Task: + properties: + message_id: + format: uuid + type: string + message_time: + type: integer + tasks: + items: + $ref: "#/definitions/types.TaskDetail" + type: array + required: + - message_id + - message_time + - tasks + type: object + types.TaskDetail: + properties: + deadline: + description: + UNIX timestamp by which any submissions for this task must be + in + type: integer + focus: + description: |- + Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project. + It is still set when there is only one repository. + + This is the project the CRS is meant to submit vulns, patches, and SARIF assessments against. + type: string + harnesses_included: + type: boolean + metadata: + description: + String to string map containing data that should be attached + to outputs like log messages and OpenTelemetry trace attributes for traceability + type: object + project_name: + description: OSS Fuzz project name + type: string + source: + description: List of sources needed to evaluate a task + items: + $ref: "#/definitions/types.SourceDetail" + type: array + task_id: + format: uuid + type: string + type: + $ref: "#/definitions/types.TaskType" + required: + - deadline + - focus + - harnesses_included + - metadata + - project_name + - source + - task_id + - type + type: object + types.TaskType: + enum: + - full + - delta + type: string + x-enum-varnames: + - TaskTypeFull + - TaskTypeDelta +info: + contact: {} + title: Example CRS API + version: "1.1" +paths: + /status/: + delete: + consumes: + - application/json + description: Reset all stats in the status endpoint. + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Reset status stats + tags: + - status + get: + consumes: + - application/json + description: report the status of the CRS + produces: + - application/json + responses: + "200": + description: Status Obect + schema: + $ref: "#/definitions/types.Status" + security: + - BasicAuth: [] + summary: CRS Status + tags: + - status + /v1/sarif/: + post: + consumes: + - application/json + description: submit a sarif broadcast + parameters: + - description: Vulnerability Broadcast + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.SARIFBroadcast" + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Submit Sarif Broadcast + tags: + - sarif + /v1/task/: + delete: + consumes: + - application/json + description: + Cancel all previously submitted tasks. This is meant for edge case + recovery in case something goes wrong. + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Cancel Tasks + tags: + - task + post: + consumes: + - application/json + description: submit a task for work + parameters: + - description: Submission body + in: body + name: payload + required: true + schema: + $ref: "#/definitions/types.Task" + produces: + - application/json + responses: + "202": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Submit Task + tags: + - task + /v1/task/{task_id}/: + delete: + consumes: + - application/json + description: + Cancel a task by id. This is meant for edge case recovery in case + something goes wrong. + parameters: + - description: Task ID + format: uuid + in: path + name: task_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: No Content + schema: + type: string + security: + - BasicAuth: [] + summary: Cancel Task + tags: + - task +securityDefinitions: + BasicAuth: + type: basic +swagger: "2.0" diff --git a/orchestrator/docs/api/crs-swagger.json b/orchestrator/docs/api/crs-swagger.json index e3272012..d8b2c961 100644 --- a/orchestrator/docs/api/crs-swagger.json +++ b/orchestrator/docs/api/crs-swagger.json @@ -3,12 +3,17 @@ "info": { "title": "Example CRS API", "contact": {}, - "version": "0.3" + "version": "1.1" }, "paths": { "/status/": { "get": { - "description": "UNAUTHENTICATED! report the status of the CRS", + "security": [ + { + "BasicAuth": [] + } + ], + "description": "report the status of the CRS", "consumes": ["application/json"], "produces": ["application/json"], "tags": ["status"], @@ -235,13 +240,14 @@ "required": ["ready", "since", "state", "version"], "properties": { "details": { - "description": "This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting.\n\nKeep in mind this endpoint is unauthenticated. Do not place sensitive details in this object.", + "description": "This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting.", "type": "object", "additionalProperties": { "type": "string" } }, "ready": { + "description": "Boolean indicating if the CRS is prepared to work on tasks. Do not return true unless you have successfully tested connectivity to the Competition API via /v1/ping/", "type": "boolean" }, "since": { @@ -257,7 +263,7 @@ ] }, "version": { - "description": "Version string for verification and reproducibility\n\n- git commit\n\n- SemVer\n\n- etc", + "description": "Version string for verification and reproducibility.\n\n- git commit\n\n- SemVer\n\n- etc", "type": "string" } } @@ -337,6 +343,7 @@ "required": [ "deadline", "focus", + "harnesses_included", "metadata", "project_name", "source", @@ -352,6 +359,9 @@ "description": "Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project.\nIt is still set when there is only one repository.\n\nThis is the project the CRS is meant to submit vulns, patches, and SARIF assessments against.", "type": "string" }, + "harnesses_included": { + "type": "boolean" + }, "metadata": { "description": "String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability", "type": "object" diff --git a/orchestrator/docs/api/crs-swagger.yaml b/orchestrator/docs/api/crs-swagger.yaml index 5f7d56db..dc26eac3 100644 --- a/orchestrator/docs/api/crs-swagger.yaml +++ b/orchestrator/docs/api/crs-swagger.yaml @@ -67,12 +67,15 @@ definitions: details: additionalProperties: type: string - description: |- - This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting. - - Keep in mind this endpoint is unauthenticated. Do not place sensitive details in this object. + description: + This is optional arbitrary content that may be logged in error + cases, but is mainly for interactive troubleshooting. type: object ready: + description: + Boolean indicating if the CRS is prepared to work on tasks. Do + not return true unless you have successfully tested connectivity to the + Competition API via /v1/ping/ type: boolean since: description: Last time task and submission stats were reset @@ -83,7 +86,7 @@ definitions: description: State of the currently running tasks and submissions version: description: |- - Version string for verification and reproducibility + Version string for verification and reproducibility. - git commit @@ -174,6 +177,8 @@ definitions: This is the project the CRS is meant to submit vulns, patches, and SARIF assessments against. type: string + harnesses_included: + type: boolean metadata: description: String to string map containing data that should be attached @@ -195,6 +200,7 @@ definitions: required: - deadline - focus + - harnesses_included - metadata - project_name - source @@ -212,7 +218,7 @@ definitions: info: contact: {} title: Example CRS API - version: "0.3" + version: "1.1" paths: /status/: delete: @@ -234,7 +240,7 @@ paths: get: consumes: - application/json - description: UNAUTHENTICATED! report the status of the CRS + description: report the status of the CRS produces: - application/json responses: @@ -242,6 +248,8 @@ paths: description: Status Obect schema: $ref: "#/definitions/types.Status" + security: + - BasicAuth: [] summary: CRS Status tags: - status diff --git a/orchestrator/docs/telemetry/README.md b/orchestrator/docs/telemetry/README.md new file mode 100644 index 00000000..4572aaea --- /dev/null +++ b/orchestrator/docs/telemetry/README.md @@ -0,0 +1,393 @@ +# CRS Telemetry Specification v1.0 + +Telemetry generated by a CRS is submitted in two distinct ways: + +1. GenAI (LLM requests and responses) +1. CRS Actions + +## GenAI (LLM requests and responses) + +GenAI Semantic Convention is being used to track LLM Telemetry, including Prompts and Responses. + +Learn more here: + +Any OpenTelemetry-compatible library may be used to generate and submit this LLM telemetry data. +If teams are using Python or TypeScript, OpenLIT is known to work well. +See OpenLIT documentation: + +```python +import openlit +openlit.init() +``` + +If you are are not using OpenLIT, and instead using the native OpenTelemetry Instrumentation Library, make sure `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true` + +## CRS Actions + +In order to track Tasks that a CRS is working on, the `metadata` field of each TaskDetail (received by the CRS API) should be +added to each Span as attributes. The metadata is a string,string map. For example: + +```python +for key, value in task_data["metadata"].items(): + span.set_attribute(key, value) +``` + +## Resource Attributes + +These attributes describe the overarching context of the telemetry data. + +| Attribute Key | Type | Description | +| -------------- | ------ | ----------------------------------------- | +| `service.name` | string | Name of CRS component generating the span | + +## Mandatory Span Attributes + +These attributes capture the details of individual tasks or activities. + +| Attribute Key | Type | Description | +| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `crs.action.category` | string | Category of the work a CRS is performing. | +| | | Values: `static_analysis`, `dynamic_analysis`, `fuzzing`, `program_analysis`, `building`, `input_generation`, `patch_generation`, `testing`, `scoring_submission`. | +| `crs.action.name` | string | Descriptive name of a CRS action. User-defined | +| `` | | Comes from Task request given to the CRS API. This should be passed on as attributes. | + +### Optional Attributes + +| Attribute Key | Type | Description | +| --------------------------- | ------- | ----------------------------------------------------------- | +| `crs.action.code.file` | string | Code file involved in the task. | +| `crs.action.code.lines` | string | Line numbers involved in the task, if applicable. | +| `crs.action.target.harness` | string | Identifier for the target harness involved. | +| `crs.action.effort.weight` | integer | Measure of effort, e.g., number of processes or cores used. | + +## Specialized Attributes for LLM Requests + +| Attribute Key | Type | Description | +| ---------------------- | ------ | ----------------------------------------- | +| `crs.action.gen_ai.id` | string | GenAI Response ID tied to the CRS action. | + +## Specialized Attributes for Fuzzing + +| Attribute Key | Type | Description | +| --------------------------- | -------- | ----------------------------------------------------------------- | +| `fuzz.corpus.update.method` | string | Update method for the input corpus: `periodic`, `on_change`, etc. | +| `fuzz.corpus.update.time` | datetime | Timestamp of the corpus update. | +| `fuzz.corpus.size` | integer | Size of the input corpus at the time of logging. | +| `fuzz.corpus.additions` | array | List of new inputs added to the corpus. | +| `fuzz.corpus.full_snapshot` | boolean | Indicates whether this is a full snapshot of the corpus. | + +--- + +## Example Python Implementation + +Change the endpoint and authentication to your telemetry solution as appropriate. + +1. Install OpenLIT + +```bash +pip install openlit +``` + +1. Run with environment variables set. + +```bash +export OPENAI_API_KEY=. +OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317" OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic " OTEL_EXPORTER_OTLP_PROTOCOL=grpc python3 main.py +``` + +```python +import logging +from openai import OpenAI +from opentelemetry import trace +import openlit + +# Initialize openlit +openlit.init(application_name="mycrsllmservice") + +# Acquire a tracer +tracer = trace.get_tracer(__name__) + + +def get_current_task(): + # Context for the task + return { + "metadata": { + "round.id": "round-1", + "task.id": "task-1", + "team.id": "team-1", + } + } + + +def main(): + client = OpenAI() + task_data = get_current_task() + + with tracer.start_as_current_span("patch_generation") as span: + logging.info("Generating a patch for the following code...") + span.set_attribute("crs.action.category", "patch_generation") + span.set_attribute("crs.action.name", "generating_patch_from_llm") + + for key, value in task_data["metadata"].items(): + span.set_attribute(key, value) + + response = fetch_llm_completion(client, "Write a short poem about OpenTelemetry", "gpt-4o-mini") + + span.set_attribute("crs.action.gen_ai.id", response.id) + + print(response) + + +def fetch_llm_completion(client, prompt, model): + response = client.chat.completions.create( + model=model, + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt, + } + ], + }, + ], + response_format={"type": "text"}, + temperature=1, + max_completion_tokens=2048, + top_p=1, + frequency_penalty=0, + presence_penalty=0, + ) + + return response + + +if __name__ == "__main__": + main() + +``` + +## Alternative Python Implementation + +```python +import logging +from openai import OpenAI +from opentelemetry import trace +import openlit + +# Initialize openlit +openlit.init(application_name="mycrsllmservice") + +# Acquire a tracer +tracer = trace.get_tracer(__name__) + +def get_current_task(): + # Context for the task + return { + "metadata": { + "round.id": "round-1", + "task.id": "task-1", + "team.id": "team-1", + } + } + + +def log_action(crs_action_category: str, crs_action_name: str, task_metadata: dict, extra_attributes: dict | None = None): + extra_attributes = extra_attributes or {} + with tracer.start_as_current_span(crs_action_category) as span: + span.set_attribute("crs.action.category", crs_action_category) + span.set_attribute("crs.action.name", crs_action_name) + + for key, value in task_metadata.items(): + span.set_attribute(key, value) + + for key, value in extra_attributes.items(): + span.set_attribute(key, value) + + span.set_status(Status(StatusCode.OK)) + + print(f"Logged crs action: {crs_action_category} - {crs_action_name}") + +def main(): + client = OpenAI() + task_metadata = get_current_task()["metadata"] + + response = fetch_llm_completion(client, "Write a short poem about OpenTelemetry", "gpt-4o-mini") + + log_action("static_analysis", "check_security_flaws", task_metadata, {"crs.action.gen_ai.id": response.id}) + + +def fetch_llm_completion(client, prompt, model): + response = client.chat.completions.create( + model=model, + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt, + } + ], + }, + ], + response_format={"type": "text"}, + temperature=1, + max_completion_tokens=2048, + top_p=1, + frequency_penalty=0, + presence_penalty=0, + ) + + return response + + +if __name__ == "__main__": + main() + +``` + +## Example CRS Webservice + +CRS web service example adapted from `example-crs-webservice/my_crs/task_server/server.py` + +```python +@app.post( + "/v1/task/", + response_model=None, + responses={"202": {"model": str}}, + tags=["task"], +) +def post_v1_task_( + credentials: Annotated[HTTPBasicCredentials, Depends(check_auth)], + body: Task, +) -> Optional[str]: + """ + Receive Task + """ + tasks: List[TaskDetail] = body.tasks + for task in tasks: + do_task(task) + +def do_task(task: TaskDetail): + metadata_dict: dict = task.metadata + log_action("category", "name", metadata_dict, {}) + +def log_action(crs_action_category: str, crs_action_name: str, task_metadata: dict, extra_attributes: dict | None = None): + extra_attributes = extra_attributes or {} + with tracer.start_as_current_span(crs_action_category) as span: + span.set_attribute("crs.action.category", crs_action_category) + span.set_attribute("crs.action.name", crs_action_name) + + for key, value in task_metadata.items(): + span.set_attribute(key, value) + + for key, value in extra_attributes.items(): + span.set_attribute(key, value) + + span.set_status(Status(StatusCode.OK)) + + print(f"Logged crs action: {crs_action_category} - {crs_action_name}") +``` + +--- + +## Other Usage Examples + +Static Analysis + +```python +{ + "crs.action.category": "static_analysis", + "crs.action.name": "analyze_vulnerabilities", + "crs.action.code.file": "file1.c", + "crs.action.code.lines": "10-50" +} +``` + +Dynamic Analysis + +```python +{ + "crs.action.category": "dynamic_analysis", + "crs.action.name": "runtime_behavior_monitoring", + "crs.action.code.file": "main.c", + "crs.action.code.lines": "120-180", + "crs.action.target.harness": "test_harness_1", + "crs.action.effort.weight": 8 +} +``` + +Fuzzing + +```python +{ + "crs.action.category": "fuzzing", + "crs.action.name": "fuzz_test_network_inputs", + "crs.action.target.harness": "network_harness", + "fuzz.corpus.update.method": "periodic", + "fuzz.corpus.size": 1500, + "fuzz.corpus.additions": ["inputA", "inputB"] +} +``` + +Program Analysis + +```python +{ + "crs.action.category": "program_analysis", + "crs.action.name": "analyze_control_flow", + "crs.action.code.file": "utils.c" +} +``` + +Building + +```python +{ + "crs.action.category": "building", + "crs.action.name": "compile_source_code", + "crs.action.code.file": "module1.c" +} +``` + +Input Generation + +```python +{ + "crs.action.category": "input_generation", + "crs.action.name": "generate_test_cases", + "crs.action.code.file": "input_parser.c" +} +``` + +Patch Generation + +```python +{ + "crs.action.category": "patch_generation", + "crs.action.name": "generate_security_patch", + "crs.action.code.files": "vuln_module.c" +} +``` + +Testing + +```python +{ + "crs.action.category": "testing", + "crs.action.name": "run_unit_tests" +} +``` + +Scoring Submission + +```python +{ + "crs.action.category": "scoring_submission", + "crs.action.name": "submit_final_results" +} +``` + +--- diff --git a/orchestrator/scripts/task_crs.sh b/orchestrator/scripts/task_crs.sh index 1e26acd2..4127c8d5 100755 --- a/orchestrator/scripts/task_crs.sh +++ b/orchestrator/scripts/task_crs.sh @@ -1,2 +1,10 @@ #!/bin/bash -curl -s -X POST "127.0.0.1:8000/v1/task/" -H "Content-Type: application/json" --user "515cc8a0-3019-4c9f-8c1c-72d0b54ae561":"VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB" -d '{"message_id":"a70e802a-e3ae-4abf-ab06-3fbc428768e3","message_time":1739917788000,"tasks":[{"task_id":"5cea8f59-a7ab-4c77-97a9-f92fcfeb33d8","type":"delta","metadata":{"round_id":"local-dev","task_id":"5cea8f59-a7ab-4c77-97a9-f92fcfeb33d8"},"deadline":1739932188000,"focus":"example-libpng","project_name":"libpng","source":[{"type":"repo","url":"https://challengesact.blob.core.windows.net/challenges/c516e2b73f58fe163be48f5bc0ca36995ee100c752e30883f9acaa0a95ca2bb6.tar.gz?se=2025-08-18T22%3A29%3A44Z&sp=r&sv=2022-11-02&sr=b&sig=7lj49Z6vXsFuKp4DqVrVVMwHU4xEAQJ%2BSCZ7BAQnbvY%3D","sha256":"c516e2b73f58fe163be48f5bc0ca36995ee100c752e30883f9acaa0a95ca2bb6"},{"type":"fuzz-tooling","url":"https://challengesact.blob.core.windows.net/challenges/910913fd13eb2e7cb7ca9a39fce4cc753d54579c938a5c60d478788101fdde3e.tar.gz?se=2025-08-18T22%3A29%3A47Z&sp=r&sv=2022-11-02&sr=b&sig=M6JoI0pGccbSARTqVLm23yQZUbUwsQsFyBpRMoADnYc%3D","sha256":"910913fd13eb2e7cb7ca9a39fce4cc753d54579c938a5c60d478788101fdde3e"},{"type":"diff","url":"https://challengesact.blob.core.windows.net/challenges/04ffd1402d868846d6812112c4bc2ec50722aa1adfaf02aab7233ad20bd1b495.tar.gz?se=2025-08-18T22%3A29%3A42Z&sp=r&sv=2022-11-02&sr=b&sig=M63mfyTls1CJhxelj%2BdtGmmO9fIVimybM6yqOMCkRac%3D","sha256":"04ffd1402d868846d6812112c4bc2ec50722aa1adfaf02aab7233ad20bd1b495"}]}]}' +curl -X 'POST' 'http://localhost:1323/webhook/trigger_task' -H 'Content-Type: application/json' -d '{ + "challenge_repo_url": "git@github.com:aixcc-finals/example-libpng.git", + "challenge_repo_base_ref": "0cc367aaeaac3f888f255cee5d394968996f736e", + "challenge_repo_head_ref": "2c894c66108f0724331a9e5b4826e351bf2d094b", + "fuzz_tooling_url": "git@github.com:aixcc-finals/oss-fuzz-aixcc.git", + "fuzz_tooling_ref": "d5fbd68fca66e6fa4f05899170d24e572b01853d", + "fuzz_tooling_project_name": "libpng", + "duration": 3600 +}' diff --git a/orchestrator/scripts/update_apis.sh b/orchestrator/scripts/update_apis.sh index 05491ce0..11d6132f 100755 --- a/orchestrator/scripts/update_apis.sh +++ b/orchestrator/scripts/update_apis.sh @@ -37,7 +37,7 @@ $PYTHON_CMD -m venv "$TEMPDIR/venv" USER_ID=$(id -u) GROUP_ID=$(id -g) docker run --rm --user $USER_ID:$GROUP_ID -v "$(realpath example-crs-architecture/docs/api):/local" -v "$OUTPUT_DIR/src/buttercup/orchestrator:/out" openapitools/openapi-generator-cli generate \ - -i /local/competition-swagger-v0.3.json \ + -i /local/competition-swagger-v1.1.json \ -g python \ -o /out \ --package-name competition_api_client @@ -61,7 +61,7 @@ pip install uvicorn pip install fastapi TEMPDIR=$(mktemp -d) -curl -o "$TEMPDIR/openapi.json" -X POST https://converter.swagger.io/api/convert -H "Content-Type: application/json" --data-binary "@example-crs-architecture/docs/api/crs-swagger-v0.3.json" +curl -o "$TEMPDIR/openapi.json" -X POST https://converter.swagger.io/api/convert -H "Content-Type: application/json" --data-binary "@example-crs-architecture/docs/api/crs-swagger-v1.1.json" fastapi-codegen --input "$TEMPDIR/openapi.json" --output "$OUTPUT_DIR/src/buttercup/orchestrator/task_server" diff --git a/orchestrator/src/buttercup/orchestrator/.openapi-generator/FILES b/orchestrator/src/buttercup/orchestrator/.openapi-generator/FILES index ccf58b14..6791fc55 100644 --- a/orchestrator/src/buttercup/orchestrator/.openapi-generator/FILES +++ b/orchestrator/src/buttercup/orchestrator/.openapi-generator/FILES @@ -1,9 +1,13 @@ .gitignore competition_api_client/__init__.py competition_api_client/api/__init__.py +competition_api_client/api/broadcast_sarif_assessment_api.py +competition_api_client/api/bundle_api.py +competition_api_client/api/feeform_api.py competition_api_client/api/patch_api.py -competition_api_client/api/sarif_api.py -competition_api_client/api/vulnerability_api.py +competition_api_client/api/ping_api.py +competition_api_client/api/pov_api.py +competition_api_client/api/submitted_sarif_api.py competition_api_client/api_client.py competition_api_client/api_response.py competition_api_client/configuration.py @@ -11,40 +15,72 @@ competition_api_client/exceptions.py competition_api_client/models/__init__.py competition_api_client/models/types_architecture.py competition_api_client/models/types_assessment.py +competition_api_client/models/types_bundle_submission.py +competition_api_client/models/types_bundle_submission_response.py +competition_api_client/models/types_bundle_submission_response_verbose.py competition_api_client/models/types_error.py +competition_api_client/models/types_freeform_response.py +competition_api_client/models/types_freeform_submission.py competition_api_client/models/types_patch_submission.py competition_api_client/models/types_patch_submission_response.py +competition_api_client/models/types_ping_response.py +competition_api_client/models/types_pov_submission.py +competition_api_client/models/types_pov_submission_response.py competition_api_client/models/types_sarif_assessment_response.py competition_api_client/models/types_sarif_assessment_submission.py +competition_api_client/models/types_sarif_submission.py +competition_api_client/models/types_sarif_submission_response.py competition_api_client/models/types_submission_status.py -competition_api_client/models/types_vuln_submission.py -competition_api_client/models/types_vuln_submission_response.py competition_api_client/py.typed competition_api_client/rest.py +docs/BroadcastSarifAssessmentApi.md +docs/BundleApi.md +docs/FeeformApi.md docs/PatchApi.md -docs/SarifApi.md +docs/PingApi.md +docs/PovApi.md +docs/SubmittedSarifApi.md docs/TypesArchitecture.md docs/TypesAssessment.md +docs/TypesBundleSubmission.md +docs/TypesBundleSubmissionResponse.md +docs/TypesBundleSubmissionResponseVerbose.md docs/TypesError.md +docs/TypesFreeformResponse.md +docs/TypesFreeformSubmission.md +docs/TypesPOVSubmission.md +docs/TypesPOVSubmissionResponse.md docs/TypesPatchSubmission.md docs/TypesPatchSubmissionResponse.md +docs/TypesPingResponse.md +docs/TypesSARIFSubmission.md +docs/TypesSARIFSubmissionResponse.md docs/TypesSarifAssessmentResponse.md docs/TypesSarifAssessmentSubmission.md docs/TypesSubmissionStatus.md -docs/TypesVulnSubmission.md -docs/TypesVulnSubmissionResponse.md -docs/VulnerabilityApi.md test/__init__.py +test/test_broadcast_sarif_assessment_api.py +test/test_bundle_api.py +test/test_feeform_api.py test/test_patch_api.py -test/test_sarif_api.py +test/test_ping_api.py +test/test_pov_api.py +test/test_submitted_sarif_api.py test/test_types_architecture.py test/test_types_assessment.py +test/test_types_bundle_submission.py +test/test_types_bundle_submission_response.py +test/test_types_bundle_submission_response_verbose.py test/test_types_error.py +test/test_types_freeform_response.py +test/test_types_freeform_submission.py test/test_types_patch_submission.py test/test_types_patch_submission_response.py +test/test_types_ping_response.py +test/test_types_pov_submission.py +test/test_types_pov_submission_response.py test/test_types_sarif_assessment_response.py test/test_types_sarif_assessment_submission.py +test/test_types_sarif_submission.py +test/test_types_sarif_submission_response.py test/test_types_submission_status.py -test/test_types_vuln_submission.py -test/test_types_vuln_submission_response.py -test/test_vulnerability_api.py diff --git a/orchestrator/src/buttercup/orchestrator/.openapi-generator/VERSION b/orchestrator/src/buttercup/orchestrator/.openapi-generator/VERSION index de37f5c4..96cfbb19 100644 --- a/orchestrator/src/buttercup/orchestrator/.openapi-generator/VERSION +++ b/orchestrator/src/buttercup/orchestrator/.openapi-generator/VERSION @@ -1 +1 @@ -7.12.0-SNAPSHOT +7.13.0-SNAPSHOT diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/__init__.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/__init__.py index 8243cc43..25d640e3 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/__init__.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/__init__.py @@ -7,7 +7,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -17,9 +17,13 @@ __version__ = "1.0.0" # import apis into sdk package +from buttercup.orchestrator.competition_api_client.api.broadcast_sarif_assessment_api import BroadcastSarifAssessmentApi +from buttercup.orchestrator.competition_api_client.api.bundle_api import BundleApi +from buttercup.orchestrator.competition_api_client.api.feeform_api import FeeformApi from buttercup.orchestrator.competition_api_client.api.patch_api import PatchApi -from buttercup.orchestrator.competition_api_client.api.sarif_api import SarifApi -from buttercup.orchestrator.competition_api_client.api.vulnerability_api import VulnerabilityApi +from buttercup.orchestrator.competition_api_client.api.ping_api import PingApi +from buttercup.orchestrator.competition_api_client.api.pov_api import PovApi +from buttercup.orchestrator.competition_api_client.api.submitted_sarif_api import SubmittedSarifApi # import ApiClient from buttercup.orchestrator.competition_api_client.api_response import ApiResponse @@ -35,11 +39,19 @@ from buttercup.orchestrator.competition_api_client.exceptions import ApiExceptio # import models into sdk package from buttercup.orchestrator.competition_api_client.models.types_architecture import TypesArchitecture from buttercup.orchestrator.competition_api_client.models.types_assessment import TypesAssessment +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose from buttercup.orchestrator.competition_api_client.models.types_error import TypesError +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse from buttercup.orchestrator.competition_api_client.models.types_patch_submission import TypesPatchSubmission from buttercup.orchestrator.competition_api_client.models.types_patch_submission_response import TypesPatchSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse from buttercup.orchestrator.competition_api_client.models.types_sarif_assessment_response import TypesSarifAssessmentResponse from buttercup.orchestrator.competition_api_client.models.types_sarif_assessment_submission import TypesSarifAssessmentSubmission from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/__init__.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/__init__.py index 334a891e..1e30cd3b 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/__init__.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/__init__.py @@ -1,7 +1,11 @@ # flake8: noqa # import apis into api package +from buttercup.orchestrator.competition_api_client.api.broadcast_sarif_assessment_api import BroadcastSarifAssessmentApi +from buttercup.orchestrator.competition_api_client.api.bundle_api import BundleApi +from buttercup.orchestrator.competition_api_client.api.feeform_api import FeeformApi from buttercup.orchestrator.competition_api_client.api.patch_api import PatchApi -from buttercup.orchestrator.competition_api_client.api.sarif_api import SarifApi -from buttercup.orchestrator.competition_api_client.api.vulnerability_api import VulnerabilityApi +from buttercup.orchestrator.competition_api_client.api.ping_api import PingApi +from buttercup.orchestrator.competition_api_client.api.pov_api import PovApi +from buttercup.orchestrator.competition_api_client.api.submitted_sarif_api import SubmittedSarifApi diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/sarif_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/broadcast_sarif_assessment_api.py similarity index 86% rename from orchestrator/src/buttercup/orchestrator/competition_api_client/api/sarif_api.py rename to orchestrator/src/buttercup/orchestrator/competition_api_client/api/broadcast_sarif_assessment_api.py index e8450626..a9670b83 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/sarif_api.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/broadcast_sarif_assessment_api.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -26,7 +26,7 @@ from buttercup.orchestrator.competition_api_client.api_response import ApiRespon from buttercup.orchestrator.competition_api_client.rest import RESTResponseType -class SarifApi: +class BroadcastSarifAssessmentApi: """NOTE: This class is auto generated by OpenAPI Generator Ref: https://openapi-generator.tech @@ -40,10 +40,10 @@ class SarifApi: @validate_call - def v1_task_task_id_sarif_sarif_id_post( + def v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - sarif_id: Annotated[StrictStr, Field(description="SARIF ID")], + broadcast_sarif_id: Annotated[StrictStr, Field(description="Broadcast SARIF ID")], payload: Annotated[TypesSarifAssessmentSubmission, Field(description="Submission body")], _request_timeout: Union[ None, @@ -58,14 +58,14 @@ class SarifApi: _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> TypesSarifAssessmentResponse: - """Submit Sarif Assessment + """Submit a SARIF Assessment - submit a sarif assessment + Submit a SARIF assessment :param task_id: Task ID (required) :type task_id: str - :param sarif_id: SARIF ID (required) - :type sarif_id: str + :param broadcast_sarif_id: Broadcast SARIF ID (required) + :type broadcast_sarif_id: str :param payload: Submission body (required) :type payload: TypesSarifAssessmentSubmission :param _request_timeout: timeout setting for this request. If one @@ -90,9 +90,9 @@ class SarifApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_sarif_sarif_id_post_serialize( + _param = self._v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_serialize( task_id=task_id, - sarif_id=sarif_id, + broadcast_sarif_id=broadcast_sarif_id, payload=payload, _request_auth=_request_auth, _content_type=_content_type, @@ -119,10 +119,10 @@ class SarifApi: @validate_call - def v1_task_task_id_sarif_sarif_id_post_with_http_info( + def v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_with_http_info( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - sarif_id: Annotated[StrictStr, Field(description="SARIF ID")], + broadcast_sarif_id: Annotated[StrictStr, Field(description="Broadcast SARIF ID")], payload: Annotated[TypesSarifAssessmentSubmission, Field(description="Submission body")], _request_timeout: Union[ None, @@ -137,14 +137,14 @@ class SarifApi: _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> ApiResponse[TypesSarifAssessmentResponse]: - """Submit Sarif Assessment + """Submit a SARIF Assessment - submit a sarif assessment + Submit a SARIF assessment :param task_id: Task ID (required) :type task_id: str - :param sarif_id: SARIF ID (required) - :type sarif_id: str + :param broadcast_sarif_id: Broadcast SARIF ID (required) + :type broadcast_sarif_id: str :param payload: Submission body (required) :type payload: TypesSarifAssessmentSubmission :param _request_timeout: timeout setting for this request. If one @@ -169,9 +169,9 @@ class SarifApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_sarif_sarif_id_post_serialize( + _param = self._v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_serialize( task_id=task_id, - sarif_id=sarif_id, + broadcast_sarif_id=broadcast_sarif_id, payload=payload, _request_auth=_request_auth, _content_type=_content_type, @@ -198,10 +198,10 @@ class SarifApi: @validate_call - def v1_task_task_id_sarif_sarif_id_post_without_preload_content( + def v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_without_preload_content( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - sarif_id: Annotated[StrictStr, Field(description="SARIF ID")], + broadcast_sarif_id: Annotated[StrictStr, Field(description="Broadcast SARIF ID")], payload: Annotated[TypesSarifAssessmentSubmission, Field(description="Submission body")], _request_timeout: Union[ None, @@ -216,14 +216,14 @@ class SarifApi: _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Submit Sarif Assessment + """Submit a SARIF Assessment - submit a sarif assessment + Submit a SARIF assessment :param task_id: Task ID (required) :type task_id: str - :param sarif_id: SARIF ID (required) - :type sarif_id: str + :param broadcast_sarif_id: Broadcast SARIF ID (required) + :type broadcast_sarif_id: str :param payload: Submission body (required) :type payload: TypesSarifAssessmentSubmission :param _request_timeout: timeout setting for this request. If one @@ -248,9 +248,9 @@ class SarifApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_sarif_sarif_id_post_serialize( + _param = self._v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_serialize( task_id=task_id, - sarif_id=sarif_id, + broadcast_sarif_id=broadcast_sarif_id, payload=payload, _request_auth=_request_auth, _content_type=_content_type, @@ -272,10 +272,10 @@ class SarifApi: return response_data.response - def _v1_task_task_id_sarif_sarif_id_post_serialize( + def _v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post_serialize( self, task_id, - sarif_id, + broadcast_sarif_id, payload, _request_auth, _content_type, @@ -300,8 +300,8 @@ class SarifApi: # process the path parameters if task_id is not None: _path_params['task_id'] = task_id - if sarif_id is not None: - _path_params['sarif_id'] = sarif_id + if broadcast_sarif_id is not None: + _path_params['broadcast_sarif_id'] = broadcast_sarif_id # process the query parameters # process the header parameters # process the form parameters @@ -339,7 +339,7 @@ class SarifApi: return self.api_client.param_serialize( method='POST', - resource_path='/v1/task/{task_id}/sarif/{sarif_id}/', + resource_path='/v1/task/{task_id}/broadcast-sarif-assessment/{broadcast_sarif_id}/', path_params=_path_params, query_params=_query_params, header_params=_header_params, diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/bundle_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/bundle_api.py new file mode 100644 index 00000000..d732824b --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/bundle_api.py @@ -0,0 +1,1233 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing_extensions import Annotated +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose + +from buttercup.orchestrator.competition_api_client.api_client import ApiClient, RequestSerialized +from buttercup.orchestrator.competition_api_client.api_response import ApiResponse +from buttercup.orchestrator.competition_api_client.rest import RESTResponseType + + +class BundleApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def v1_task_task_id_bundle_bundle_id_delete( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> str: + """Delete Bundle + + delete a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_delete_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': "str", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_bundle_bundle_id_delete_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[str]: + """Delete Bundle + + delete a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_delete_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': "str", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_bundle_bundle_id_delete_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Bundle + + delete a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_delete_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': "str", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_bundle_bundle_id_delete_serialize( + self, + task_id, + bundle_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + if bundle_id is not None: + _path_params['bundle_id'] = bundle_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/task/{task_id}/bundle/{bundle_id}/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def v1_task_task_id_bundle_bundle_id_get( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesBundleSubmissionResponseVerbose: + """Get Bundle + + get a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_get_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_bundle_bundle_id_get_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesBundleSubmissionResponseVerbose]: + """Get Bundle + + get a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_get_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_bundle_bundle_id_get_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Bundle + + get a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_get_serialize( + task_id=task_id, + bundle_id=bundle_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_bundle_bundle_id_get_serialize( + self, + task_id, + bundle_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + if bundle_id is not None: + _path_params['bundle_id'] = bundle_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/task/{task_id}/bundle/{bundle_id}/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def v1_task_task_id_bundle_bundle_id_patch( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesBundleSubmissionResponseVerbose: + """Update Bundle + + updates a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_patch_serialize( + task_id=task_id, + bundle_id=bundle_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_bundle_bundle_id_patch_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesBundleSubmissionResponseVerbose]: + """Update Bundle + + updates a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_patch_serialize( + task_id=task_id, + bundle_id=bundle_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_bundle_bundle_id_patch_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + bundle_id: Annotated[StrictStr, Field(description="Bundle ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update Bundle + + updates a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param bundle_id: Bundle ID (required) + :type bundle_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_bundle_id_patch_serialize( + task_id=task_id, + bundle_id=bundle_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponseVerbose", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_bundle_bundle_id_patch_serialize( + self, + task_id, + bundle_id, + payload, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + if bundle_id is not None: + _path_params['bundle_id'] = bundle_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if payload is not None: + _body_params = payload + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/task/{task_id}/bundle/{bundle_id}/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def v1_task_task_id_bundle_post( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesBundleSubmissionResponse: + """Submit Bundle + + submits a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_bundle_post_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesBundleSubmissionResponse]: + """Submit Bundle + + submits a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_bundle_post_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesBundleSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Submit Bundle + + submits a bundle + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesBundleSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_bundle_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesBundleSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_bundle_post_serialize( + self, + task_id, + payload, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if payload is not None: + _body_params = payload + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/task/{task_id}/bundle/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/feeform_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/feeform_api.py new file mode 100644 index 00000000..47b52b1f --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/feeform_api.py @@ -0,0 +1,340 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing_extensions import Annotated +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission + +from buttercup.orchestrator.competition_api_client.api_client import ApiClient, RequestSerialized +from buttercup.orchestrator.competition_api_client.api_response import ApiResponse +from buttercup.orchestrator.competition_api_client.rest import RESTResponseType + + +class FeeformApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def v1_task_task_id_freeform_post( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesFreeformSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesFreeformResponse: + """Submit Freeform + + submits a freeform pov + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesFreeformSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_freeform_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesFreeformResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_freeform_post_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesFreeformSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesFreeformResponse]: + """Submit Freeform + + submits a freeform pov + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesFreeformSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_freeform_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesFreeformResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_freeform_post_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesFreeformSubmission, Field(description="Submission Body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Submit Freeform + + submits a freeform pov + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission Body (required) + :type payload: TypesFreeformSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_freeform_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesFreeformResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_freeform_post_serialize( + self, + task_id, + payload, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if payload is not None: + _body_params = payload + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/task/{task_id}/freeform/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/patch_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/patch_api.py index d6c18756..ff4014dd 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/patch_api.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/patch_api.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/ping_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/ping_api.py new file mode 100644 index 00000000..230d205f --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/ping_api.py @@ -0,0 +1,282 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse + +from buttercup.orchestrator.competition_api_client.api_client import ApiClient, RequestSerialized +from buttercup.orchestrator.competition_api_client.api_response import ApiResponse +from buttercup.orchestrator.competition_api_client.rest import RESTResponseType + + +class PingApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def v1_ping_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesPingResponse: + """Test authentication creds and network connectivity + + Test authentication creds and network connectivity + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_ping_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesPingResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_ping_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesPingResponse]: + """Test authentication creds and network connectivity + + Test authentication creds and network connectivity + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_ping_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesPingResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_ping_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Test authentication creds and network connectivity + + Test authentication creds and network connectivity + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_ping_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesPingResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_ping_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + '*/*' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/ping/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/vulnerability_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/pov_api.py similarity index 89% rename from orchestrator/src/buttercup/orchestrator/competition_api_client/api/vulnerability_api.py rename to orchestrator/src/buttercup/orchestrator/competition_api_client/api/pov_api.py index fa924f66..862c11dc 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/vulnerability_api.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/pov_api.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,15 +18,15 @@ from typing_extensions import Annotated from pydantic import Field, StrictStr from typing_extensions import Annotated -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse from buttercup.orchestrator.competition_api_client.api_client import ApiClient, RequestSerialized from buttercup.orchestrator.competition_api_client.api_response import ApiResponse from buttercup.orchestrator.competition_api_client.rest import RESTResponseType -class VulnerabilityApi: +class PovApi: """NOTE: This class is auto generated by OpenAPI Generator Ref: https://openapi-generator.tech @@ -40,10 +40,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_post( + def v1_task_task_id_pov_post( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - payload: Annotated[TypesVulnSubmission, Field(description="Submission body")], + payload: Annotated[TypesPOVSubmission, Field(description="Submission body")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -56,7 +56,7 @@ class VulnerabilityApi: _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> TypesVulnSubmissionResponse: + ) -> TypesPOVSubmissionResponse: """Submit Vulnerability submit a vulnerability for testing @@ -64,7 +64,7 @@ class VulnerabilityApi: :param task_id: Task ID (required) :type task_id: str :param payload: Submission body (required) - :type payload: TypesVulnSubmission + :type payload: TypesPOVSubmission :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -87,7 +87,7 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_post_serialize( + _param = self._v1_task_task_id_pov_post_serialize( task_id=task_id, payload=payload, _request_auth=_request_auth, @@ -97,7 +97,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -115,10 +115,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_post_with_http_info( + def v1_task_task_id_pov_post_with_http_info( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - payload: Annotated[TypesVulnSubmission, Field(description="Submission body")], + payload: Annotated[TypesPOVSubmission, Field(description="Submission body")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -131,7 +131,7 @@ class VulnerabilityApi: _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[TypesVulnSubmissionResponse]: + ) -> ApiResponse[TypesPOVSubmissionResponse]: """Submit Vulnerability submit a vulnerability for testing @@ -139,7 +139,7 @@ class VulnerabilityApi: :param task_id: Task ID (required) :type task_id: str :param payload: Submission body (required) - :type payload: TypesVulnSubmission + :type payload: TypesPOVSubmission :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -162,7 +162,7 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_post_serialize( + _param = self._v1_task_task_id_pov_post_serialize( task_id=task_id, payload=payload, _request_auth=_request_auth, @@ -172,7 +172,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -190,10 +190,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_post_without_preload_content( + def v1_task_task_id_pov_post_without_preload_content( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - payload: Annotated[TypesVulnSubmission, Field(description="Submission body")], + payload: Annotated[TypesPOVSubmission, Field(description="Submission body")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -214,7 +214,7 @@ class VulnerabilityApi: :param task_id: Task ID (required) :type task_id: str :param payload: Submission body (required) - :type payload: TypesVulnSubmission + :type payload: TypesPOVSubmission :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -237,7 +237,7 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_post_serialize( + _param = self._v1_task_task_id_pov_post_serialize( task_id=task_id, payload=payload, _request_auth=_request_auth, @@ -247,7 +247,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -260,7 +260,7 @@ class VulnerabilityApi: return response_data.response - def _v1_task_task_id_vuln_post_serialize( + def _v1_task_task_id_pov_post_serialize( self, task_id, payload, @@ -324,7 +324,7 @@ class VulnerabilityApi: return self.api_client.param_serialize( method='POST', - resource_path='/v1/task/{task_id}/vuln/', + resource_path='/v1/task/{task_id}/pov/', path_params=_path_params, query_params=_query_params, header_params=_header_params, @@ -341,10 +341,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_vuln_id_get( + def v1_task_task_id_pov_pov_id_get( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - vuln_id: Annotated[StrictStr, Field(description="Vuln ID")], + pov_id: Annotated[StrictStr, Field(description="POV ID")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -357,15 +357,15 @@ class VulnerabilityApi: _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> TypesVulnSubmissionResponse: + ) -> TypesPOVSubmissionResponse: """Vulnerability Status yield the status of vuln testing :param task_id: Task ID (required) :type task_id: str - :param vuln_id: Vuln ID (required) - :type vuln_id: str + :param pov_id: POV ID (required) + :type pov_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -388,9 +388,9 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_vuln_id_get_serialize( + _param = self._v1_task_task_id_pov_pov_id_get_serialize( task_id=task_id, - vuln_id=vuln_id, + pov_id=pov_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -398,7 +398,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -416,10 +416,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_vuln_id_get_with_http_info( + def v1_task_task_id_pov_pov_id_get_with_http_info( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - vuln_id: Annotated[StrictStr, Field(description="Vuln ID")], + pov_id: Annotated[StrictStr, Field(description="POV ID")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -432,15 +432,15 @@ class VulnerabilityApi: _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[TypesVulnSubmissionResponse]: + ) -> ApiResponse[TypesPOVSubmissionResponse]: """Vulnerability Status yield the status of vuln testing :param task_id: Task ID (required) :type task_id: str - :param vuln_id: Vuln ID (required) - :type vuln_id: str + :param pov_id: POV ID (required) + :type pov_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -463,9 +463,9 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_vuln_id_get_serialize( + _param = self._v1_task_task_id_pov_pov_id_get_serialize( task_id=task_id, - vuln_id=vuln_id, + pov_id=pov_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -473,7 +473,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -491,10 +491,10 @@ class VulnerabilityApi: @validate_call - def v1_task_task_id_vuln_vuln_id_get_without_preload_content( + def v1_task_task_id_pov_pov_id_get_without_preload_content( self, task_id: Annotated[StrictStr, Field(description="Task ID")], - vuln_id: Annotated[StrictStr, Field(description="Vuln ID")], + pov_id: Annotated[StrictStr, Field(description="POV ID")], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -514,8 +514,8 @@ class VulnerabilityApi: :param task_id: Task ID (required) :type task_id: str - :param vuln_id: Vuln ID (required) - :type vuln_id: str + :param pov_id: POV ID (required) + :type pov_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -538,9 +538,9 @@ class VulnerabilityApi: :return: Returns the result object. """ # noqa: E501 - _param = self._v1_task_task_id_vuln_vuln_id_get_serialize( + _param = self._v1_task_task_id_pov_pov_id_get_serialize( task_id=task_id, - vuln_id=vuln_id, + pov_id=pov_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -548,7 +548,7 @@ class VulnerabilityApi: ) _response_types_map: Dict[str, Optional[str]] = { - '200': "TypesVulnSubmissionResponse", + '200': "TypesPOVSubmissionResponse", '400': "TypesError", '401': "TypesError", '404': "TypesError", @@ -561,10 +561,10 @@ class VulnerabilityApi: return response_data.response - def _v1_task_task_id_vuln_vuln_id_get_serialize( + def _v1_task_task_id_pov_pov_id_get_serialize( self, task_id, - vuln_id, + pov_id, _request_auth, _content_type, _headers, @@ -588,8 +588,8 @@ class VulnerabilityApi: # process the path parameters if task_id is not None: _path_params['task_id'] = task_id - if vuln_id is not None: - _path_params['vuln_id'] = vuln_id + if pov_id is not None: + _path_params['pov_id'] = pov_id # process the query parameters # process the header parameters # process the form parameters @@ -612,7 +612,7 @@ class VulnerabilityApi: return self.api_client.param_serialize( method='GET', - resource_path='/v1/task/{task_id}/vuln/{vuln_id}/', + resource_path='/v1/task/{task_id}/pov/{pov_id}/', path_params=_path_params, query_params=_query_params, header_params=_header_params, diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api/submitted_sarif_api.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/submitted_sarif_api.py new file mode 100644 index 00000000..46c8ac4a --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api/submitted_sarif_api.py @@ -0,0 +1,340 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing_extensions import Annotated +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse + +from buttercup.orchestrator.competition_api_client.api_client import ApiClient, RequestSerialized +from buttercup.orchestrator.competition_api_client.api_response import ApiResponse +from buttercup.orchestrator.competition_api_client.rest import RESTResponseType + + +class SubmittedSarifApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def v1_task_task_id_submitted_sarif_post( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesSARIFSubmission, Field(description="Submission body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> TypesSARIFSubmissionResponse: + """Submit a CRS generated SARIF + + Submit a CRS generated SARIF + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission body (required) + :type payload: TypesSARIFSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_submitted_sarif_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesSARIFSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def v1_task_task_id_submitted_sarif_post_with_http_info( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesSARIFSubmission, Field(description="Submission body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[TypesSARIFSubmissionResponse]: + """Submit a CRS generated SARIF + + Submit a CRS generated SARIF + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission body (required) + :type payload: TypesSARIFSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_submitted_sarif_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesSARIFSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def v1_task_task_id_submitted_sarif_post_without_preload_content( + self, + task_id: Annotated[StrictStr, Field(description="Task ID")], + payload: Annotated[TypesSARIFSubmission, Field(description="Submission body")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Submit a CRS generated SARIF + + Submit a CRS generated SARIF + + :param task_id: Task ID (required) + :type task_id: str + :param payload: Submission body (required) + :type payload: TypesSARIFSubmission + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._v1_task_task_id_submitted_sarif_post_serialize( + task_id=task_id, + payload=payload, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypesSARIFSubmissionResponse", + '400': "TypesError", + '401': "TypesError", + '404': "TypesError", + '500': "TypesError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v1_task_task_id_submitted_sarif_post_serialize( + self, + task_id, + payload, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if task_id is not None: + _path_params['task_id'] = task_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if payload is not None: + _body_params = payload + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'BasicAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/task/{task_id}/submitted-sarif/', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/api_client.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/api_client.py index bc1f87a2..274ece3e 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/api_client.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/api_client.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/configuration.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/configuration.py index 37dd4676..8dbb13d8 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/configuration.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/configuration.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,7 +18,7 @@ import logging from logging import FileHandler import multiprocessing import sys -from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict +from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union from typing_extensions import NotRequired, Self import urllib3 @@ -161,6 +161,8 @@ class Configuration: :param ssl_ca_cert: str - the path to a file of concatenated CA certificates in PEM format. :param retries: Number of retries for API requests. + :param ca_cert_data: verify the peer using concatenated CA certificate data + in PEM (str) or DER (bytes) format. :Example: @@ -191,13 +193,14 @@ conf = competition_api_client.Configuration( username: Optional[str]=None, password: Optional[str]=None, access_token: Optional[str]=None, - server_index: Optional[int]=None, + server_index: Optional[int]=None, server_variables: Optional[ServerVariablesT]=None, server_operation_index: Optional[Dict[int, int]]=None, server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None, ignore_operation_servers: bool=False, ssl_ca_cert: Optional[str]=None, retries: Optional[int] = None, + ca_cert_data: Optional[Union[str, bytes]] = None, *, debug: Optional[bool] = None, ) -> None: @@ -275,6 +278,10 @@ conf = competition_api_client.Configuration( self.ssl_ca_cert = ssl_ca_cert """Set this to customize the certificate file to verify the peer. """ + self.ca_cert_data = ca_cert_data + """Set this to verify the peer using PEM (str) or DER (bytes) + certificate data. + """ self.cert_file = None """client certificate file """ @@ -518,7 +525,7 @@ conf = competition_api_client.Configuration( return "Python SDK Debug Report:\n"\ "OS: {env}\n"\ "Python Version: {pyversion}\n"\ - "Version of the API: 0.3\n"\ + "Version of the API: 1.1\n"\ "SDK Package Version: 1.0.0".\ format(env=sys.platform, pyversion=sys.version) diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/exceptions.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/exceptions.py index c9ccecdc..34f20f3b 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/exceptions.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/exceptions.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/__init__.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/__init__.py index d90f4153..afdd1047 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/__init__.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/__init__.py @@ -6,7 +6,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -16,11 +16,19 @@ # import models into model package from buttercup.orchestrator.competition_api_client.models.types_architecture import TypesArchitecture from buttercup.orchestrator.competition_api_client.models.types_assessment import TypesAssessment +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose from buttercup.orchestrator.competition_api_client.models.types_error import TypesError +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse from buttercup.orchestrator.competition_api_client.models.types_patch_submission import TypesPatchSubmission from buttercup.orchestrator.competition_api_client.models.types_patch_submission_response import TypesPatchSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse from buttercup.orchestrator.competition_api_client.models.types_sarif_assessment_response import TypesSarifAssessmentResponse from buttercup.orchestrator.competition_api_client.models.types_sarif_assessment_submission import TypesSarifAssessmentSubmission from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_architecture.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_architecture.py index b97a8905..f081eac1 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_architecture.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_architecture.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_assessment.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_assessment.py index a7d51a25..42955a26 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_assessment.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_assessment.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission.py new file mode 100644 index 00000000..896800e9 --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class TypesBundleSubmission(BaseModel): + """ + TypesBundleSubmission + """ # noqa: E501 + broadcast_sarif_id: Optional[StrictStr] = None + description: Optional[StrictStr] = Field(default=None, description="optional plaintext description of the components of the bundle, such as would be found in a pull request description or bug report") + freeform_id: Optional[StrictStr] = None + patch_id: Optional[StrictStr] = None + pov_id: Optional[StrictStr] = None + submitted_sarif_id: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["broadcast_sarif_id", "description", "freeform_id", "patch_id", "pov_id", "submitted_sarif_id"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesBundleSubmission from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesBundleSubmission from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "broadcast_sarif_id": obj.get("broadcast_sarif_id"), + "description": obj.get("description"), + "freeform_id": obj.get("freeform_id"), + "patch_id": obj.get("patch_id"), + "pov_id": obj.get("pov_id"), + "submitted_sarif_id": obj.get("submitted_sarif_id") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response.py new file mode 100644 index 00000000..afc388fd --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus +from typing import Optional, Set +from typing_extensions import Self + +class TypesBundleSubmissionResponse(BaseModel): + """ + TypesBundleSubmissionResponse + """ # noqa: E501 + bundle_id: StrictStr + status: TypesSubmissionStatus + __properties: ClassVar[List[str]] = ["bundle_id", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesBundleSubmissionResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesBundleSubmissionResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bundle_id": obj.get("bundle_id"), + "status": obj.get("status") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response_verbose.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response_verbose.py new file mode 100644 index 00000000..44e20bf3 --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_bundle_submission_response_verbose.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus +from typing import Optional, Set +from typing_extensions import Self + +class TypesBundleSubmissionResponseVerbose(BaseModel): + """ + TypesBundleSubmissionResponseVerbose + """ # noqa: E501 + broadcast_sarif_id: Optional[StrictStr] = None + bundle_id: StrictStr + description: Optional[StrictStr] = None + freeform_id: Optional[StrictStr] = None + patch_id: Optional[StrictStr] = None + pov_id: Optional[StrictStr] = None + status: TypesSubmissionStatus + submitted_sarif_id: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["broadcast_sarif_id", "bundle_id", "description", "freeform_id", "patch_id", "pov_id", "status", "submitted_sarif_id"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesBundleSubmissionResponseVerbose from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesBundleSubmissionResponseVerbose from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "broadcast_sarif_id": obj.get("broadcast_sarif_id"), + "bundle_id": obj.get("bundle_id"), + "description": obj.get("description"), + "freeform_id": obj.get("freeform_id"), + "patch_id": obj.get("patch_id"), + "pov_id": obj.get("pov_id"), + "status": obj.get("status"), + "submitted_sarif_id": obj.get("submitted_sarif_id") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_error.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_error.py index 02b32391..1bff13d3 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_error.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_error.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_response.py new file mode 100644 index 00000000..5c42e237 --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_response.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus +from typing import Optional, Set +from typing_extensions import Self + +class TypesFreeformResponse(BaseModel): + """ + TypesFreeformResponse + """ # noqa: E501 + freeform_id: StrictStr + status: TypesSubmissionStatus + __properties: ClassVar[List[str]] = ["freeform_id", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesFreeformResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesFreeformResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "freeform_id": obj.get("freeform_id"), + "status": obj.get("status") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_submission.py new file mode 100644 index 00000000..b9f5952e --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_freeform_submission.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class TypesFreeformSubmission(BaseModel): + """ + TypesFreeformSubmission + """ # noqa: E501 + submission: StrictStr = Field(description="Base64 encoded arbitrary data 2MiB max size before Base64 encoding") + __properties: ClassVar[List[str]] = ["submission"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesFreeformSubmission from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesFreeformSubmission from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "submission": obj.get("submission") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission.py index a0d44cad..887d8a4c 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,8 +18,7 @@ import re # noqa: F401 import json from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing_extensions import Annotated +from typing import Any, ClassVar, Dict, List from typing import Optional, Set from typing_extensions import Self @@ -27,11 +26,8 @@ class TypesPatchSubmission(BaseModel): """ TypesPatchSubmission """ # noqa: E501 - description: Optional[Annotated[str, Field(strict=True, max_length=131072)]] = Field(default=None, description="Optional plain text reasoning for the assessment 128KiB max size") patch: StrictStr = Field(description="Base64 encoded patch in unified diff format 100KiB max size before Base64 encoding") - sarif_id: Optional[StrictStr] = Field(default=None, description="Optional ID of SARIF Broadcast this patch is associated with") - vuln_id: Optional[StrictStr] = Field(default=None, description="Optional ID of Vuln this patch is associated with") - __properties: ClassVar[List[str]] = ["description", "patch", "sarif_id", "vuln_id"] + __properties: ClassVar[List[str]] = ["patch"] model_config = ConfigDict( populate_by_name=True, @@ -84,10 +80,7 @@ class TypesPatchSubmission(BaseModel): return cls.model_validate(obj) _obj = cls.model_validate({ - "description": obj.get("description"), - "patch": obj.get("patch"), - "sarif_id": obj.get("sarif_id"), - "vuln_id": obj.get("vuln_id") + "patch": obj.get("patch") }) return _obj diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission_response.py index f6470c5a..d03055d5 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission_response.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_patch_submission_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -17,8 +17,8 @@ import pprint import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus from typing import Optional, Set from typing_extensions import Self @@ -27,9 +27,10 @@ class TypesPatchSubmissionResponse(BaseModel): """ TypesPatchSubmissionResponse """ # noqa: E501 + functionality_tests_passing: Optional[StrictBool] = Field(default=None, description="null indicates the tests have not been run") patch_id: StrictStr status: TypesSubmissionStatus - __properties: ClassVar[List[str]] = ["patch_id", "status"] + __properties: ClassVar[List[str]] = ["functionality_tests_passing", "patch_id", "status"] model_config = ConfigDict( populate_by_name=True, @@ -82,6 +83,7 @@ class TypesPatchSubmissionResponse(BaseModel): return cls.model_validate(obj) _obj = cls.model_validate({ + "functionality_tests_passing": obj.get("functionality_tests_passing"), "patch_id": obj.get("patch_id"), "status": obj.get("status") }) diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_ping_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_ping_response.py new file mode 100644 index 00000000..49e9caf6 --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_ping_response.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class TypesPingResponse(BaseModel): + """ + TypesPingResponse + """ # noqa: E501 + status: StrictStr + __properties: ClassVar[List[str]] = ["status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesPingResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesPingResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "status": obj.get("status") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission.py similarity index 71% rename from orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission.py rename to orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission.py index fe732c76..4f922458 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,22 +18,22 @@ import re # noqa: F401 import json from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional +from typing import Any, ClassVar, Dict, List from typing_extensions import Annotated from buttercup.orchestrator.competition_api_client.models.types_architecture import TypesArchitecture from typing import Optional, Set from typing_extensions import Self -class TypesVulnSubmission(BaseModel): +class TypesPOVSubmission(BaseModel): """ - TypesVulnSubmission + TypesPOVSubmission """ # noqa: E501 architecture: TypesArchitecture - data_file: StrictStr = Field(description="Base64 encoded vuln trigger 2MiB max size before Base64 encoding") - harness_name: Annotated[str, Field(strict=True, max_length=4096)] = Field(description="Fuzz Tooling Harness Name that exercises this vuln 4KiB max size") + engine: Annotated[str, Field(strict=True, max_length=4096)] = Field(description="Fuzz Tooling Engine that exercises this vuln. Allowable engine values are specified in project.yaml. 4KiB max size") + fuzzer_name: Annotated[str, Field(strict=True, max_length=4096)] = Field(description="Fuzz Tooling fuzzer that exercises this vuln 4KiB max size") sanitizer: Annotated[str, Field(strict=True, max_length=4096)] = Field(description="Fuzz Tooling Sanitizer that exercises this vuln 4KiB max size") - sarif: Optional[Dict[str, Any]] = Field(default=None, description="Optional SARIF Report compliant with the provided versioned SARIF schema") - __properties: ClassVar[List[str]] = ["architecture", "data_file", "harness_name", "sanitizer", "sarif"] + testcase: StrictStr = Field(description="Base64 encoded vuln trigger 2MiB max size before Base64 encoding") + __properties: ClassVar[List[str]] = ["architecture", "engine", "fuzzer_name", "sanitizer", "testcase"] model_config = ConfigDict( populate_by_name=True, @@ -53,7 +53,7 @@ class TypesVulnSubmission(BaseModel): @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of TypesVulnSubmission from a JSON string""" + """Create an instance of TypesPOVSubmission from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -78,7 +78,7 @@ class TypesVulnSubmission(BaseModel): @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of TypesVulnSubmission from a dict""" + """Create an instance of TypesPOVSubmission from a dict""" if obj is None: return None @@ -87,10 +87,10 @@ class TypesVulnSubmission(BaseModel): _obj = cls.model_validate({ "architecture": obj.get("architecture"), - "data_file": obj.get("data_file"), - "harness_name": obj.get("harness_name"), + "engine": obj.get("engine"), + "fuzzer_name": obj.get("fuzzer_name"), "sanitizer": obj.get("sanitizer"), - "sarif": obj.get("sarif") + "testcase": obj.get("testcase") }) return _obj diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission_response.py new file mode 100644 index 00000000..f25a46f4 --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_pov_submission_response.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus +from typing import Optional, Set +from typing_extensions import Self + +class TypesPOVSubmissionResponse(BaseModel): + """ + TypesPOVSubmissionResponse + """ # noqa: E501 + pov_id: StrictStr + status: TypesSubmissionStatus + __properties: ClassVar[List[str]] = ["pov_id", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesPOVSubmissionResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesPOVSubmissionResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "pov_id": obj.get("pov_id"), + "status": obj.get("status") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_response.py index 4153c5dd..72a42168 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_response.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_submission.py index 9a1ac002..73c278b7 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_submission.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_assessment_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission.py new file mode 100644 index 00000000..4bf77cba --- /dev/null +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class TypesSARIFSubmission(BaseModel): + """ + TypesSARIFSubmission + """ # noqa: E501 + sarif: Dict[str, Any] = Field(description="SARIF object compliant with the provided schema") + __properties: ClassVar[List[str]] = ["sarif"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TypesSARIFSubmission from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesSARIFSubmission from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "sarif": obj.get("sarif") + }) + return _obj + + diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission_response.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission_response.py similarity index 83% rename from orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission_response.py rename to orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission_response.py index 406cec75..cb595819 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_vuln_submission_response.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_sarif_submission_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -23,13 +23,13 @@ from buttercup.orchestrator.competition_api_client.models.types_submission_statu from typing import Optional, Set from typing_extensions import Self -class TypesVulnSubmissionResponse(BaseModel): +class TypesSARIFSubmissionResponse(BaseModel): """ - TypesVulnSubmissionResponse + TypesSARIFSubmissionResponse """ # noqa: E501 status: TypesSubmissionStatus - vuln_id: StrictStr - __properties: ClassVar[List[str]] = ["status", "vuln_id"] + submitted_sarif_id: StrictStr + __properties: ClassVar[List[str]] = ["status", "submitted_sarif_id"] model_config = ConfigDict( populate_by_name=True, @@ -49,7 +49,7 @@ class TypesVulnSubmissionResponse(BaseModel): @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of TypesVulnSubmissionResponse from a JSON string""" + """Create an instance of TypesSARIFSubmissionResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -74,7 +74,7 @@ class TypesVulnSubmissionResponse(BaseModel): @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of TypesVulnSubmissionResponse from a dict""" + """Create an instance of TypesSARIFSubmissionResponse from a dict""" if obj is None: return None @@ -83,7 +83,7 @@ class TypesVulnSubmissionResponse(BaseModel): _obj = cls.model_validate({ "status": obj.get("status"), - "vuln_id": obj.get("vuln_id") + "submitted_sarif_id": obj.get("submitted_sarif_id") }) return _obj diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_submission_status.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_submission_status.py index a8b85bd6..b4646173 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_submission_status.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/models/types_submission_status.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -27,10 +27,10 @@ class TypesSubmissionStatus(str, Enum): allowed enum values """ ACCEPTED = 'accepted' - INVALID = 'invalid' PASSED = 'passed' FAILED = 'failed' DEADLINE_EXCEEDED = 'deadline_exceeded' + ERRORED = 'errored' @classmethod def from_json(cls, json_str: str) -> Self: diff --git a/orchestrator/src/buttercup/orchestrator/competition_api_client/rest.py b/orchestrator/src/buttercup/orchestrator/competition_api_client/rest.py index 75acf97c..596ce5c8 100644 --- a/orchestrator/src/buttercup/orchestrator/competition_api_client/rest.py +++ b/orchestrator/src/buttercup/orchestrator/competition_api_client/rest.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -76,6 +76,7 @@ class RESTClientObject: "ca_certs": configuration.ssl_ca_cert, "cert_file": configuration.cert_file, "key_file": configuration.key_file, + "ca_cert_data": configuration.ca_cert_data, } if configuration.assert_hostname is not None: pool_args['assert_hostname'] = ( diff --git a/orchestrator/src/buttercup/orchestrator/scheduler/patches.py b/orchestrator/src/buttercup/orchestrator/scheduler/patches.py index 94c5fd0a..51a289df 100644 --- a/orchestrator/src/buttercup/orchestrator/scheduler/patches.py +++ b/orchestrator/src/buttercup/orchestrator/scheduler/patches.py @@ -52,7 +52,6 @@ class Patches: # Create submission payload from patch data submission = TypesPatchSubmission( patch=encoded_patch, - vuln_id=patch.vulnerability_id, ) # Submit patch and get response diff --git a/orchestrator/src/buttercup/orchestrator/scheduler/vulnerabilities.py b/orchestrator/src/buttercup/orchestrator/scheduler/vulnerabilities.py index 2a10df13..73ae5cf6 100644 --- a/orchestrator/src/buttercup/orchestrator/scheduler/vulnerabilities.py +++ b/orchestrator/src/buttercup/orchestrator/scheduler/vulnerabilities.py @@ -11,9 +11,9 @@ from buttercup.common.queues import ( GroupNames, ) from buttercup.common.datastructures.msg_pb2 import ConfirmedVulnerability, Crash, TracedCrash -from buttercup.orchestrator.competition_api_client.api.vulnerability_api import VulnerabilityApi +from buttercup.orchestrator.competition_api_client.api.pov_api import PovApi from buttercup.orchestrator.competition_api_client.api_client import ApiClient -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus from buttercup.orchestrator.registry import TaskRegistry @@ -29,7 +29,7 @@ class Vulnerabilities: unique_vulnerabilities_queue: ReliableQueue = field(init=False) confirmed_vulnerabilities_queue: ReliableQueue = field(init=False) task_registry: TaskRegistry = field(init=False) - vulnerability_api: VulnerabilityApi = field(init=False) + pov_api: PovApi = field(init=False) def __post_init__(self): queue_factory = QueueFactory(self.redis) @@ -40,8 +40,8 @@ class Vulnerabilities: QueueNames.CONFIRMED_VULNERABILITIES, block_time=None ) self.task_registry = TaskRegistry(self.redis) - self.vulnerability_api = VulnerabilityApi(api_client=self.api_client) - logger.info(f"Competition vulnerability API initialized: {self.vulnerability_api is not None}") + self.pov_api = PovApi(api_client=self.api_client) + logger.info(f"Competition Pov API initialized: {self.pov_api is not None}") def process_traced_vulnerabilities(self) -> bool: """Process traced vulnerabilities from the traced vulnerabilities queue. @@ -69,7 +69,7 @@ class Vulnerabilities: f"[{crash.crash.target.task_id}] Skipping cancelled task for harness: {crash.crash.harness_name}" ) else: - confirmed_vuln = self.submit_vulnerability(crash) + confirmed_vuln = self.submit_pov(crash) if confirmed_vuln is not None: self.confirmed_vulnerabilities_queue.push(confirmed_vuln) @@ -88,9 +88,9 @@ class Vulnerabilities: # For now, treating all crashes as unique return crash - def submit_vulnerability(self, crash: TracedCrash) -> ConfirmedVulnerability | None: + def submit_pov(self, crash: TracedCrash) -> ConfirmedVulnerability | None: """ - Submit the vulnerability to the competition API + Submit the Pov to the competition API Returns: ConfirmedVulnerability | None: The confirmed vulnerability with API-provided ID if successful, @@ -106,16 +106,16 @@ class Vulnerabilities: crash_data = base64.b64encode(f.read()).decode() # Create submission payload from crash data - submission = TypesVulnSubmission( + submission = TypesPOVSubmission( architecture=ARCHITECTURE, - data_file=crash_data, - harness_name=crash.crash.harness_name, + engine=crash.crash.target.engine, + fuzzer_name=crash.crash.harness_name, sanitizer=crash.crash.target.sanitizer, - sarif=None, # Optional, not provided in crash data + testcase=crash_data, ) - # Submit vulnerability and get response - response = self.vulnerability_api.v1_task_task_id_vuln_post( + # Submit Pov and get response + response = self.pov_api.v1_task_task_id_pov_post( task_id=crash.crash.target.task_id, payload=submission, ) @@ -126,25 +126,25 @@ class Vulnerabilities: # If we don't acknowledge the PASSED status, we may miss a successful submission. if response.status not in [TypesSubmissionStatus.ACCEPTED, TypesSubmissionStatus.PASSED]: logger.error( - f"[{crash.crash.target.task_id}] Vulnerability submission rejected (status: {response.status}) for harness: {crash.crash.harness_name}" + f"[{crash.crash.target.task_id}] POV submission rejected (status: {response.status}) for harness: {crash.crash.harness_name}" ) return None # TODO: Could a successful response be PASSED? logger.info( - f"[{crash.crash.target.task_id}] Vulnerability {response.vuln_id} accepted for harness: {crash.crash.harness_name}" + f"[{crash.crash.target.task_id}] POV {response.pov_id} accepted for harness: {crash.crash.harness_name}" ) # Create confirmed vulnerability with API-provided ID confirmed_vuln = ConfirmedVulnerability() confirmed_vuln.crash.CopyFrom(crash) - confirmed_vuln.vuln_id = response.vuln_id + confirmed_vuln.vuln_id = response.pov_id return confirmed_vuln except Exception as e: logger.error( - f"[{crash.crash.target.task_id}] Failed to submit vulnerability: {str(e)} (harness: {crash.crash.harness_name})" + f"[{crash.crash.target.task_id}] Failed to submit POV: {str(e)} (harness: {crash.crash.harness_name})" ) raise diff --git a/orchestrator/src/buttercup/orchestrator/task_server/models/__init__.py b/orchestrator/src/buttercup/orchestrator/task_server/models/__init__.py deleted file mode 100644 index 50eb55c6..00000000 --- a/orchestrator/src/buttercup/orchestrator/task_server/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# generated by fastapi-codegen: -# filename: /tmp/tmp.YexQI4p6wu/openapi.json -# timestamp: 2025-02-18T14:23:33+00:00 diff --git a/orchestrator/src/buttercup/orchestrator/task_server/models/types.py b/orchestrator/src/buttercup/orchestrator/task_server/models/types.py deleted file mode 100644 index fad019e6..00000000 --- a/orchestrator/src/buttercup/orchestrator/task_server/models/types.py +++ /dev/null @@ -1,122 +0,0 @@ -# generated by fastapi-codegen: -# filename: /tmp/tmp.YexQI4p6wu/openapi.json -# timestamp: 2025-02-18T14:23:33+00:00 - -from __future__ import annotations - -from enum import Enum -from typing import Any, Dict, List, Optional - -from pydantic import BaseModel, Field - - -class SARIFBroadcastDetail(BaseModel): - metadata: Dict[str, Any] = Field( - ..., - description='String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability', - ) - sarif: Dict[str, Any] = Field( - ..., description='SARIF Report compliant with provided schema' - ) - sarif_id: str - task_id: str - - -class SourceType(Enum): - SourceTypeRepo = 'repo' - SourceTypeFuzzTooling = 'fuzz-tooling' - SourceTypeDiff = 'diff' - - -class StatusTasksState(BaseModel): - canceled: int = Field( - ..., description='Number of tasks that competition infrastructure has cancelled' - ) - errored: int = Field( - ..., - description='Number of tasks that the CRS encountered an unrecoverable issue for', - ) - failed: int = Field( - ..., - description='Number of submissions that the competition infrastructure marked failed', - ) - pending: int = Field( - ..., description='Number of tasks that the CRS has not started work on' - ) - processing: int = Field( - ..., description='Number of tasks that the CRS is currently processing' - ) - succeeded: int = Field( - ..., - description='Number of submissions that the competition infrastructure marked passed', - ) - waiting: int = Field( - ..., - description='Number of submissions that the competition infrastructure is currently testing', - ) - - -class TaskType(Enum): - TaskTypeFull = 'full' - TaskTypeDelta = 'delta' - - -class SARIFBroadcast(BaseModel): - broadcasts: List[SARIFBroadcastDetail] - message_id: str - message_time: int - - -class SourceDetail(BaseModel): - sha256: str = Field(..., description='Integrity hash of the gzipped tarball') - type: SourceType - url: str = Field(..., description='URL to fetch the source gzipped tarball') - - -class StatusState(BaseModel): - tasks: StatusTasksState - - -class TaskDetail(BaseModel): - deadline: int = Field( - ..., - description='UNIX timestamp by which any submissions for this task must be in', - ) - focus: str = Field( - ..., - description='Because the challenge task may contain multiple repositories, the folder in the type repo source tarball containing the main project.\nIt is still set when there is only one repository.\n\nThis is the project the CRS is meant to submit vulns, patches, and SARIF assessments against.', - ) - metadata: Dict[str, Any] = Field( - ..., - description='String to string map containing data that should be attached to outputs like log messages and OpenTelemetry trace attributes for traceability', - ) - project_name: str = Field(..., description='OSS Fuzz project name') - source: List[SourceDetail] = Field( - ..., description='List of sources needed to evaluate a task' - ) - task_id: str - type: TaskType - - -class Status(BaseModel): - details: Optional[Dict[str, str]] = Field( - None, - description='This is optional arbitrary content that may be logged in error cases, but is mainly for interactive troubleshooting.\n\nKeep in mind this endpoint is unauthenticated. Do not place sensitive details in this object.', - ) - ready: bool - since: int = Field( - ..., description='Last time task and submission stats were reset' - ) - state: StatusState = Field( - ..., description='State of the currently running tasks and submissions' - ) - version: str = Field( - ..., - description='Version string for verification and reproducibility\n\n- git commit\n\n- SemVer\n\n- etc', - ) - - -class Task(BaseModel): - message_id: str - message_time: int - tasks: List[TaskDetail] diff --git a/orchestrator/src/buttercup/orchestrator/task_server/server.py b/orchestrator/src/buttercup/orchestrator/task_server/server.py index 97825f08..9bf460e9 100644 --- a/orchestrator/src/buttercup/orchestrator/task_server/server.py +++ b/orchestrator/src/buttercup/orchestrator/task_server/server.py @@ -119,7 +119,9 @@ def check_auth( @app.get("/status/", response_model=Status, tags=["status"]) -def get_status_() -> Status: +def get_status_( + credentials: Annotated[HTTPBasicCredentials, Depends(check_auth)], +) -> Status: """ CRS Status """ @@ -127,7 +129,9 @@ def get_status_() -> Status: @app.delete("/status/", response_model=str, tags=["status"]) -def delete_status_() -> str: +def delete_status_( + credentials: Annotated[HTTPBasicCredentials, Depends(check_auth)], +) -> str: """ Reset status stats """ diff --git a/orchestrator/test/test_broadcast_sarif_assessment_api.py b/orchestrator/test/test_broadcast_sarif_assessment_api.py new file mode 100644 index 00000000..7a6875e4 --- /dev/null +++ b/orchestrator/test/test_broadcast_sarif_assessment_api.py @@ -0,0 +1,37 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.broadcast_sarif_assessment_api import BroadcastSarifAssessmentApi + + +class TestBroadcastSarifAssessmentApi(unittest.TestCase): + """BroadcastSarifAssessmentApi unit test stubs""" + + def setUp(self) -> None: + self.api = BroadcastSarifAssessmentApi() + + def tearDown(self) -> None: + pass + + def test_v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post(self) -> None: + """Test case for v1_task_task_id_broadcast_sarif_assessment_broadcast_sarif_id_post + + Submit a SARIF Assessment + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_bundle_api.py b/orchestrator/test/test_bundle_api.py new file mode 100644 index 00000000..d4b7ff49 --- /dev/null +++ b/orchestrator/test/test_bundle_api.py @@ -0,0 +1,58 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.bundle_api import BundleApi + + +class TestBundleApi(unittest.TestCase): + """BundleApi unit test stubs""" + + def setUp(self) -> None: + self.api = BundleApi() + + def tearDown(self) -> None: + pass + + def test_v1_task_task_id_bundle_bundle_id_delete(self) -> None: + """Test case for v1_task_task_id_bundle_bundle_id_delete + + Delete Bundle + """ + pass + + def test_v1_task_task_id_bundle_bundle_id_get(self) -> None: + """Test case for v1_task_task_id_bundle_bundle_id_get + + Get Bundle + """ + pass + + def test_v1_task_task_id_bundle_bundle_id_patch(self) -> None: + """Test case for v1_task_task_id_bundle_bundle_id_patch + + Update Bundle + """ + pass + + def test_v1_task_task_id_bundle_post(self) -> None: + """Test case for v1_task_task_id_bundle_post + + Submit Bundle + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_feeform_api.py b/orchestrator/test/test_feeform_api.py new file mode 100644 index 00000000..f82be70f --- /dev/null +++ b/orchestrator/test/test_feeform_api.py @@ -0,0 +1,37 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.feeform_api import FeeformApi + + +class TestFeeformApi(unittest.TestCase): + """FeeformApi unit test stubs""" + + def setUp(self) -> None: + self.api = FeeformApi() + + def tearDown(self) -> None: + pass + + def test_v1_task_task_id_freeform_post(self) -> None: + """Test case for v1_task_task_id_freeform_post + + Submit Freeform + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_patch_api.py b/orchestrator/test/test_patch_api.py index 933e98cb..fb5ed65b 100644 --- a/orchestrator/test/test_patch_api.py +++ b/orchestrator/test/test_patch_api.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_patches.py b/orchestrator/test/test_patches.py index 66c62da5..854336b1 100644 --- a/orchestrator/test/test_patches.py +++ b/orchestrator/test/test_patches.py @@ -74,7 +74,6 @@ class TestSubmitPatch: # Verify the patch content is base64 encoded expected_encoded_patch = base64.b64encode(sample_patch.patch.encode()).decode() assert call_args[1]["payload"].patch == expected_encoded_patch - assert call_args[1]["payload"].vuln_id == sample_patch.vulnerability_id # Verify returned response assert result == mock_response @@ -125,7 +124,7 @@ class TestProcessPatches: mock_item = RQItem(item_id="test_id", deserialized=sample_patch) mock_queues["patches"].pop.return_value = mock_item - mock_response = TypesPatchSubmissionResponse(status=TypesSubmissionStatus.INVALID, patch_id="rejected-789") + mock_response = TypesPatchSubmissionResponse(status=TypesSubmissionStatus.ERRORED, patch_id="rejected-789") patches.patch_api.v1_task_task_id_patch_post.return_value = mock_response assert patches.process_patches() is True diff --git a/orchestrator/test/test_ping_api.py b/orchestrator/test/test_ping_api.py new file mode 100644 index 00000000..4b611822 --- /dev/null +++ b/orchestrator/test/test_ping_api.py @@ -0,0 +1,37 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.ping_api import PingApi + + +class TestPingApi(unittest.TestCase): + """PingApi unit test stubs""" + + def setUp(self) -> None: + self.api = PingApi() + + def tearDown(self) -> None: + pass + + def test_v1_ping_get(self) -> None: + """Test case for v1_ping_get + + Test authentication creds and network connectivity + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_pov_api.py b/orchestrator/test/test_pov_api.py new file mode 100644 index 00000000..41276d61 --- /dev/null +++ b/orchestrator/test/test_pov_api.py @@ -0,0 +1,44 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.pov_api import PovApi + + +class TestPovApi(unittest.TestCase): + """PovApi unit test stubs""" + + def setUp(self) -> None: + self.api = PovApi() + + def tearDown(self) -> None: + pass + + def test_v1_task_task_id_pov_post(self) -> None: + """Test case for v1_task_task_id_pov_post + + Submit Vulnerability + """ + pass + + def test_v1_task_task_id_pov_pov_id_get(self) -> None: + """Test case for v1_task_task_id_pov_pov_id_get + + Vulnerability Status + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_sarif_api.py b/orchestrator/test/test_sarif_api.py deleted file mode 100644 index 56698a58..00000000 --- a/orchestrator/test/test_sarif_api.py +++ /dev/null @@ -1,38 +0,0 @@ -# coding: utf-8 - -""" - Example Competition API - - No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - - The version of the OpenAPI document: 0.3 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from buttercup.orchestrator.competition_api_client.api.sarif_api import SarifApi - - -class TestSarifApi(unittest.TestCase): - """SarifApi unit test stubs""" - - def setUp(self) -> None: - self.api = SarifApi() - - def tearDown(self) -> None: - pass - - def test_v1_task_task_id_sarif_sarif_id_post(self) -> None: - """Test case for v1_task_task_id_sarif_sarif_id_post - - Submit Sarif Assessment - """ - pass - - -if __name__ == '__main__': - unittest.main() diff --git a/orchestrator/test/test_submitted_sarif_api.py b/orchestrator/test/test_submitted_sarif_api.py new file mode 100644 index 00000000..350c088d --- /dev/null +++ b/orchestrator/test/test_submitted_sarif_api.py @@ -0,0 +1,37 @@ +# coding: utf-8 + +""" +Example Competition API + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +The version of the OpenAPI document: 1.1 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + +import unittest + +from buttercup.orchestrator.competition_api_client.api.submitted_sarif_api import SubmittedSarifApi + + +class TestSubmittedSarifApi(unittest.TestCase): + """SubmittedSarifApi unit test stubs""" + + def setUp(self) -> None: + self.api = SubmittedSarifApi() + + def tearDown(self) -> None: + pass + + def test_v1_task_task_id_submitted_sarif_post(self) -> None: + """Test case for v1_task_task_id_submitted_sarif_post + + Submit a CRS generated SARIF + """ + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/orchestrator/test/test_types_architecture.py b/orchestrator/test/test_types_architecture.py index 9f3c9dfa..84d745c0 100644 --- a/orchestrator/test/test_types_architecture.py +++ b/orchestrator/test/test_types_architecture.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_types_assessment.py b/orchestrator/test/test_types_assessment.py index c9398268..82d2b95b 100644 --- a/orchestrator/test/test_types_assessment.py +++ b/orchestrator/test/test_types_assessment.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_types_bundle_submission.py b/orchestrator/test/test_types_bundle_submission.py new file mode 100644 index 00000000..f9cf75c1 --- /dev/null +++ b/orchestrator/test/test_types_bundle_submission.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission import TypesBundleSubmission + +class TestTypesBundleSubmission(unittest.TestCase): + """TypesBundleSubmission unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesBundleSubmission: + """Test TypesBundleSubmission + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesBundleSubmission` + """ + model = TypesBundleSubmission() + if include_optional: + return TypesBundleSubmission( + broadcast_sarif_id = '', + description = '', + freeform_id = '', + patch_id = '', + pov_id = '', + submitted_sarif_id = '' + ) + else: + return TypesBundleSubmission( + ) + """ + + def testTypesBundleSubmission(self): + """Test TypesBundleSubmission""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_bundle_submission_response.py b/orchestrator/test/test_types_bundle_submission_response.py new file mode 100644 index 00000000..1cee89f2 --- /dev/null +++ b/orchestrator/test/test_types_bundle_submission_response.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response import TypesBundleSubmissionResponse + +class TestTypesBundleSubmissionResponse(unittest.TestCase): + """TypesBundleSubmissionResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesBundleSubmissionResponse: + """Test TypesBundleSubmissionResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesBundleSubmissionResponse` + """ + model = TypesBundleSubmissionResponse() + if include_optional: + return TypesBundleSubmissionResponse( + bundle_id = '', + status = 'accepted' + ) + else: + return TypesBundleSubmissionResponse( + bundle_id = '', + status = 'accepted', + ) + """ + + def testTypesBundleSubmissionResponse(self): + """Test TypesBundleSubmissionResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_bundle_submission_response_verbose.py b/orchestrator/test/test_types_bundle_submission_response_verbose.py new file mode 100644 index 00000000..b9f2109c --- /dev/null +++ b/orchestrator/test/test_types_bundle_submission_response_verbose.py @@ -0,0 +1,60 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_bundle_submission_response_verbose import TypesBundleSubmissionResponseVerbose + +class TestTypesBundleSubmissionResponseVerbose(unittest.TestCase): + """TypesBundleSubmissionResponseVerbose unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesBundleSubmissionResponseVerbose: + """Test TypesBundleSubmissionResponseVerbose + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesBundleSubmissionResponseVerbose` + """ + model = TypesBundleSubmissionResponseVerbose() + if include_optional: + return TypesBundleSubmissionResponseVerbose( + broadcast_sarif_id = '', + bundle_id = '', + description = '', + freeform_id = '', + patch_id = '', + pov_id = '', + status = 'accepted', + submitted_sarif_id = '' + ) + else: + return TypesBundleSubmissionResponseVerbose( + bundle_id = '', + status = 'accepted', + ) + """ + + def testTypesBundleSubmissionResponseVerbose(self): + """Test TypesBundleSubmissionResponseVerbose""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_error.py b/orchestrator/test/test_types_error.py index 847a025c..a62855a3 100644 --- a/orchestrator/test/test_types_error.py +++ b/orchestrator/test/test_types_error.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_types_freeform_response.py b/orchestrator/test/test_types_freeform_response.py new file mode 100644 index 00000000..050f4040 --- /dev/null +++ b/orchestrator/test/test_types_freeform_response.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_freeform_response import TypesFreeformResponse + +class TestTypesFreeformResponse(unittest.TestCase): + """TypesFreeformResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesFreeformResponse: + """Test TypesFreeformResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesFreeformResponse` + """ + model = TypesFreeformResponse() + if include_optional: + return TypesFreeformResponse( + freeform_id = '', + status = 'accepted' + ) + else: + return TypesFreeformResponse( + freeform_id = '', + status = 'accepted', + ) + """ + + def testTypesFreeformResponse(self): + """Test TypesFreeformResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_freeform_submission.py b/orchestrator/test/test_types_freeform_submission.py new file mode 100644 index 00000000..c431a36f --- /dev/null +++ b/orchestrator/test/test_types_freeform_submission.py @@ -0,0 +1,52 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_freeform_submission import TypesFreeformSubmission + +class TestTypesFreeformSubmission(unittest.TestCase): + """TypesFreeformSubmission unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesFreeformSubmission: + """Test TypesFreeformSubmission + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesFreeformSubmission` + """ + model = TypesFreeformSubmission() + if include_optional: + return TypesFreeformSubmission( + submission = '' + ) + else: + return TypesFreeformSubmission( + submission = '', + ) + """ + + def testTypesFreeformSubmission(self): + """Test TypesFreeformSubmission""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_patch_submission.py b/orchestrator/test/test_types_patch_submission.py index 0a7c6375..37456dbf 100644 --- a/orchestrator/test/test_types_patch_submission.py +++ b/orchestrator/test/test_types_patch_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -35,10 +35,7 @@ class TestTypesPatchSubmission(unittest.TestCase): model = TypesPatchSubmission() if include_optional: return TypesPatchSubmission( - description = '', - patch = '', - sarif_id = '', - vuln_id = '' + patch = '' ) else: return TypesPatchSubmission( diff --git a/orchestrator/test/test_types_patch_submission_response.py b/orchestrator/test/test_types_patch_submission_response.py index 1c0b72b7..a433d479 100644 --- a/orchestrator/test/test_types_patch_submission_response.py +++ b/orchestrator/test/test_types_patch_submission_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -35,6 +35,7 @@ class TestTypesPatchSubmissionResponse(unittest.TestCase): model = TypesPatchSubmissionResponse() if include_optional: return TypesPatchSubmissionResponse( + functionality_tests_passing = True, patch_id = '', status = 'accepted' ) diff --git a/orchestrator/test/test_types_ping_response.py b/orchestrator/test/test_types_ping_response.py new file mode 100644 index 00000000..d348f505 --- /dev/null +++ b/orchestrator/test/test_types_ping_response.py @@ -0,0 +1,52 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_ping_response import TypesPingResponse + +class TestTypesPingResponse(unittest.TestCase): + """TypesPingResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesPingResponse: + """Test TypesPingResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesPingResponse` + """ + model = TypesPingResponse() + if include_optional: + return TypesPingResponse( + status = '' + ) + else: + return TypesPingResponse( + status = '', + ) + """ + + def testTypesPingResponse(self): + """Test TypesPingResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_vuln_submission.py b/orchestrator/test/test_types_pov_submission.py similarity index 58% rename from orchestrator/test/test_types_vuln_submission.py rename to orchestrator/test/test_types_pov_submission.py index e88ce89c..7e577ad6 100644 --- a/orchestrator/test/test_types_vuln_submission.py +++ b/orchestrator/test/test_types_pov_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -14,10 +14,10 @@ import unittest -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission import TypesVulnSubmission +from buttercup.orchestrator.competition_api_client.models.types_pov_submission import TypesPOVSubmission -class TestTypesVulnSubmission(unittest.TestCase): - """TypesVulnSubmission unit test stubs""" +class TestTypesPOVSubmission(unittest.TestCase): + """TypesPOVSubmission unit test stubs""" def setUp(self): pass @@ -25,33 +25,34 @@ class TestTypesVulnSubmission(unittest.TestCase): def tearDown(self): pass - def make_instance(self, include_optional) -> TypesVulnSubmission: - """Test TypesVulnSubmission + def make_instance(self, include_optional) -> TypesPOVSubmission: + """Test TypesPOVSubmission include_optional is a boolean, when False only required params are included, when True both required and optional params are included """ - # uncomment below to create an instance of `TypesVulnSubmission` + # uncomment below to create an instance of `TypesPOVSubmission` """ - model = TypesVulnSubmission() + model = TypesPOVSubmission() if include_optional: - return TypesVulnSubmission( + return TypesPOVSubmission( architecture = 'x86_64', - data_file = '', - harness_name = '', + engine = '', + fuzzer_name = '', sanitizer = '', - sarif = None + testcase = '' ) else: - return TypesVulnSubmission( + return TypesPOVSubmission( architecture = 'x86_64', - data_file = '', - harness_name = '', + engine = '', + fuzzer_name = '', sanitizer = '', + testcase = '', ) """ - def testTypesVulnSubmission(self): - """Test TypesVulnSubmission""" + def testTypesPOVSubmission(self): + """Test TypesPOVSubmission""" # inst_req_only = self.make_instance(include_optional=False) # inst_req_and_optional = self.make_instance(include_optional=True) diff --git a/orchestrator/test/test_types_pov_submission_response.py b/orchestrator/test/test_types_pov_submission_response.py new file mode 100644 index 00000000..df2b1b8c --- /dev/null +++ b/orchestrator/test/test_types_pov_submission_response.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import TypesPOVSubmissionResponse + +class TestTypesPOVSubmissionResponse(unittest.TestCase): + """TypesPOVSubmissionResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesPOVSubmissionResponse: + """Test TypesPOVSubmissionResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesPOVSubmissionResponse` + """ + model = TypesPOVSubmissionResponse() + if include_optional: + return TypesPOVSubmissionResponse( + pov_id = '', + status = 'accepted' + ) + else: + return TypesPOVSubmissionResponse( + pov_id = '', + status = 'accepted', + ) + """ + + def testTypesPOVSubmissionResponse(self): + """Test TypesPOVSubmissionResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_sarif_assessment_response.py b/orchestrator/test/test_types_sarif_assessment_response.py index 95ba0b3a..5d095c28 100644 --- a/orchestrator/test/test_types_sarif_assessment_response.py +++ b/orchestrator/test/test_types_sarif_assessment_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_types_sarif_assessment_submission.py b/orchestrator/test/test_types_sarif_assessment_submission.py index 197b1f92..1b9cceaf 100644 --- a/orchestrator/test/test_types_sarif_assessment_submission.py +++ b/orchestrator/test/test_types_sarif_assessment_submission.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_types_sarif_submission.py b/orchestrator/test/test_types_sarif_submission.py new file mode 100644 index 00000000..5a9713df --- /dev/null +++ b/orchestrator/test/test_types_sarif_submission.py @@ -0,0 +1,52 @@ +# coding: utf-8 + +""" + Example Competition API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: 1.1 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission import TypesSARIFSubmission + +class TestTypesSARIFSubmission(unittest.TestCase): + """TypesSARIFSubmission unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> TypesSARIFSubmission: + """Test TypesSARIFSubmission + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `TypesSARIFSubmission` + """ + model = TypesSARIFSubmission() + if include_optional: + return TypesSARIFSubmission( + sarif = None + ) + else: + return TypesSARIFSubmission( + sarif = None, + ) + """ + + def testTypesSARIFSubmission(self): + """Test TypesSARIFSubmission""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/orchestrator/test/test_types_vuln_submission_response.py b/orchestrator/test/test_types_sarif_submission_response.py similarity index 56% rename from orchestrator/test/test_types_vuln_submission_response.py rename to orchestrator/test/test_types_sarif_submission_response.py index 0929c2bf..5425c813 100644 --- a/orchestrator/test/test_types_vuln_submission_response.py +++ b/orchestrator/test/test_types_sarif_submission_response.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -14,10 +14,10 @@ import unittest -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import TypesVulnSubmissionResponse +from buttercup.orchestrator.competition_api_client.models.types_sarif_submission_response import TypesSARIFSubmissionResponse -class TestTypesVulnSubmissionResponse(unittest.TestCase): - """TypesVulnSubmissionResponse unit test stubs""" +class TestTypesSARIFSubmissionResponse(unittest.TestCase): + """TypesSARIFSubmissionResponse unit test stubs""" def setUp(self): pass @@ -25,28 +25,28 @@ class TestTypesVulnSubmissionResponse(unittest.TestCase): def tearDown(self): pass - def make_instance(self, include_optional) -> TypesVulnSubmissionResponse: - """Test TypesVulnSubmissionResponse + def make_instance(self, include_optional) -> TypesSARIFSubmissionResponse: + """Test TypesSARIFSubmissionResponse include_optional is a boolean, when False only required params are included, when True both required and optional params are included """ - # uncomment below to create an instance of `TypesVulnSubmissionResponse` + # uncomment below to create an instance of `TypesSARIFSubmissionResponse` """ - model = TypesVulnSubmissionResponse() + model = TypesSARIFSubmissionResponse() if include_optional: - return TypesVulnSubmissionResponse( + return TypesSARIFSubmissionResponse( status = 'accepted', - vuln_id = '' + submitted_sarif_id = '' ) else: - return TypesVulnSubmissionResponse( + return TypesSARIFSubmissionResponse( status = 'accepted', - vuln_id = '', + submitted_sarif_id = '', ) """ - def testTypesVulnSubmissionResponse(self): - """Test TypesVulnSubmissionResponse""" + def testTypesSARIFSubmissionResponse(self): + """Test TypesSARIFSubmissionResponse""" # inst_req_only = self.make_instance(include_optional=False) # inst_req_and_optional = self.make_instance(include_optional=True) diff --git a/orchestrator/test/test_types_submission_status.py b/orchestrator/test/test_types_submission_status.py index 7ca41adc..7f377d21 100644 --- a/orchestrator/test/test_types_submission_status.py +++ b/orchestrator/test/test_types_submission_status.py @@ -5,7 +5,7 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - The version of the OpenAPI document: 0.3 + The version of the OpenAPI document: 1.1 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/orchestrator/test/test_vulnerabilities.py b/orchestrator/test/test_vulnerabilities.py index b644a317..db16b104 100644 --- a/orchestrator/test/test_vulnerabilities.py +++ b/orchestrator/test/test_vulnerabilities.py @@ -4,8 +4,8 @@ from unittest.mock import Mock, patch from buttercup.orchestrator.scheduler.vulnerabilities import Vulnerabilities from buttercup.common.queues import RQItem, QueueFactory from buttercup.common.datastructures.msg_pb2 import Crash, BuildOutput, TracedCrash -from buttercup.orchestrator.competition_api_client.models.types_vuln_submission_response import ( - TypesVulnSubmissionResponse, +from buttercup.orchestrator.competition_api_client.models.types_pov_submission_response import ( + TypesPOVSubmissionResponse, ) from buttercup.orchestrator.competition_api_client.models.types_submission_status import TypesSubmissionStatus @@ -73,7 +73,7 @@ def vulnerabilities(mock_redis, mock_api_client, mock_queues): vuln.task_registry.is_cancelled = Mock(return_value=False) # Mock the vulnerability API method we use - vuln.vulnerability_api.v1_task_task_id_vuln_post = Mock() + vuln.pov_api.v1_task_task_id_pov_post = Mock() return vuln @@ -95,8 +95,8 @@ class TestProcessTracedVulnerabilities: mock_item = RQItem(item_id="test_id", deserialized=sample_crash) mock_queues["traced"].pop.return_value = mock_item - mock_response = TypesVulnSubmissionResponse(status=TypesSubmissionStatus.ACCEPTED, vuln_id="test-vuln-123") - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.return_value = mock_response + mock_response = TypesPOVSubmissionResponse(status=TypesSubmissionStatus.ACCEPTED, pov_id="test-pov-123") + vulnerabilities.pov_api.v1_task_task_id_pov_post.return_value = mock_response assert vulnerabilities.process_traced_vulnerabilities() is True mock_queues["traced"].pop.assert_called_once() @@ -113,8 +113,8 @@ class TestProcessTracedVulnerabilities: mock_item = RQItem(item_id="test_id", deserialized=sample_crash) mock_queues["traced"].pop.return_value = mock_item - mock_response = TypesVulnSubmissionResponse(status=TypesSubmissionStatus.INVALID, vuln_id="rejected-123") - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.return_value = mock_response + mock_response = TypesPOVSubmissionResponse(status=TypesSubmissionStatus.ERRORED, pov_id="rejected-123") + vulnerabilities.pov_api.v1_task_task_id_pov_post.return_value = mock_response assert vulnerabilities.process_traced_vulnerabilities() is True mock_queues["traced"].pop.assert_called_once() @@ -131,7 +131,7 @@ class TestProcessTracedVulnerabilities: mock_item = RQItem(item_id="test_id", deserialized=sample_crash) mock_queues["traced"].pop.return_value = mock_item - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.side_effect = Exception("API Error") + vulnerabilities.pov_api.v1_task_task_id_pov_post.side_effect = Exception("API Error") assert vulnerabilities.process_traced_vulnerabilities() is True mock_queues["traced"].pop.assert_called_once() @@ -158,24 +158,24 @@ class TestSubmitVulnerability: mock_file.read.return_value = b"test crash data" mock_open.return_value.__enter__.return_value = mock_file - mock_response = TypesVulnSubmissionResponse(status=TypesSubmissionStatus.ACCEPTED, vuln_id="test-vuln-123") - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.return_value = mock_response + mock_response = TypesPOVSubmissionResponse(status=TypesSubmissionStatus.ACCEPTED, pov_id="test-pov-123") + vulnerabilities.pov_api.v1_task_task_id_pov_post.return_value = mock_response - result = vulnerabilities.submit_vulnerability(sample_crash) + result = vulnerabilities.submit_pov(sample_crash) # Verify file was read correctly mock_open.assert_called_once_with(sample_crash.crash.crash_input_path, "rb") # Verify API was called with correct data - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.assert_called_once() - call_args = vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.call_args + vulnerabilities.pov_api.v1_task_task_id_pov_post.assert_called_once() + call_args = vulnerabilities.pov_api.v1_task_task_id_pov_post.call_args assert call_args[1]["task_id"] == sample_crash.crash.target.task_id - assert call_args[1]["payload"].data_file == "dGVzdCBjcmFzaCBkYXRh" # base64 encoded "test crash data" + assert call_args[1]["payload"].testcase == "dGVzdCBjcmFzaCBkYXRh" # base64 encoded "test crash data" # Verify returned vulnerability object assert result is not None assert result.crash == sample_crash - assert result.vuln_id == "test-vuln-123" + assert result.vuln_id == "test-pov-123" @patch("builtins.open") def test_api_error_raises_exception(self, mock_open, vulnerabilities, sample_crash): @@ -184,10 +184,10 @@ class TestSubmitVulnerability: mock_file.read.return_value = b"test crash data" mock_open.return_value.__enter__.return_value = mock_file - vulnerabilities.vulnerability_api.v1_task_task_id_vuln_post.side_effect = Exception("API Error") + vulnerabilities.pov_api.v1_task_task_id_pov_post.side_effect = Exception("API Error") with pytest.raises(Exception) as exc_info: - vulnerabilities.submit_vulnerability(sample_crash) + vulnerabilities.submit_pov(sample_crash) assert "API Error" in str(exc_info.value) @patch("builtins.open") @@ -196,7 +196,7 @@ class TestSubmitVulnerability: mock_open.side_effect = FileNotFoundError("File not found") with pytest.raises(Exception) as exc_info: - vulnerabilities.submit_vulnerability(sample_crash) + vulnerabilities.submit_pov(sample_crash) assert "File not found" in str(exc_info.value) diff --git a/orchestrator/test/test_vulnerability_api.py b/orchestrator/test/test_vulnerability_api.py deleted file mode 100644 index 2585bdb0..00000000 --- a/orchestrator/test/test_vulnerability_api.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 - -""" - Example Competition API - - No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - - The version of the OpenAPI document: 0.3 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from buttercup.orchestrator.competition_api_client.api.vulnerability_api import VulnerabilityApi - - -class TestVulnerabilityApi(unittest.TestCase): - """VulnerabilityApi unit test stubs""" - - def setUp(self) -> None: - self.api = VulnerabilityApi() - - def tearDown(self) -> None: - pass - - def test_v1_task_task_id_vuln_post(self) -> None: - """Test case for v1_task_task_id_vuln_post - - Submit Vulnerability - """ - pass - - def test_v1_task_task_id_vuln_vuln_id_get(self) -> None: - """Test case for v1_task_task_id_vuln_vuln_id_get - - Vulnerability Status - """ - pass - - -if __name__ == '__main__': - unittest.main()