Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

NOISSUE - Add property based testing to certs API #168

Closed
wants to merge 8 commits into from
204 changes: 204 additions & 0 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0

name: Property Based Tests

on:
push:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
DOMAINS_URL: http://localhost:8189/domains
USER_IDENTITY: [email protected]
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
THINGS_URL: http://localhost:9000
INVITATIONS_URL: http://localhost:9020
AUTH_URL: http://localhost:8189
BOOTSTRAP_URL: http://localhost:9013
CERTS_URL: http://localhost:9019

jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
cache-dependency-path: "go.sum"

- name: Build images
run: make all -j $(nproc) && make dockers_dev -j $(nproc)

- name: Start containers
run: make run up args="-d" && make run_addons up args="-d"

- name: Set access token
run: |
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\"}" | jq -r .access_token)
export DOMAIN_ID=$(curl -sSX POST $DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"alias\":\"$DOMAIN_NAME\"}" | jq -r .id)
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\",\"domain_id\": \"$DOMAIN_ID\"}" | jq -r .access_token)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV

- name: Check for changes in specific paths
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
auth:
- ".github/workflows/api-tests.yml"
- "api/openapi/auth.yml"
- "auth/api/http/**"

bootstrap:
- ".github/workflows/api-tests.yml"
- "api/openapi/bootstrap.yml"
- "bootstrap/api/**"

certs:
- ".github/workflows/api-tests.yml"
- "api/openapi/certs.yml"
- "certs/api/**"

notifiers:
- ".github/workflows/api-tests.yml"
- "api/openapi/notifiers.yml"
- "consumers/notifiers/api/**"

http:
- ".github/workflows/api-tests.yml"
- "api/openapi/http.yml"
- "http/api/**"

invitations:
- ".github/workflows/api-tests.yml"
- "api/openapi/invitations.yml"
- "invitations/api/**"

provision:
- ".github/workflows/api-tests.yml"
- "api/openapi/provision.yml"
- "provision/api/**"

readers:
- ".github/workflows/api-tests.yml"
- "api/openapi/readers.yml"
- "readers/api/**"

things:
- ".github/workflows/api-tests.yml"
- "api/openapi/things.yml"
- "things/api/**"

twins:
- ".github/workflows/api-tests.yml"
- "api/openapi/twins.yml"
- "twins/api/**"

users:
- ".github/workflows/api-tests.yml"
- "api/openapi/users.yml"
- "users/api/**"

- name: Run Users API tests
if: steps.changes.outputs.users == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/users.yml
base-url: ${{ env.USERS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Things API tests
if: steps.changes.outputs.things == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/things.yml
base-url: ${{ env.THINGS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Invitations API tests
if: steps.changes.outputs.invitations == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/invitations.yml
base-url: ${{ env.INVITATIONS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Auth API tests
if: steps.changes.outputs.auth == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/auth.yml
base-url: ${{ env.AUTH_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Bootstrap API tests
if: steps.changes.outputs.bootstrap == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/bootstrap.yml
base-url: ${{ env.BOOTSTRAP_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Certs API tests
if: steps.changes.outputs.certs == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/certs.yml
base-url: ${{ env.CERTS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Stop containers
if: always()
run: make run down args="-v"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ tools/provision/mgconn.toml

# coverage files
coverage

# Schemathesis
.hypothesis
33 changes: 32 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ BUILD_DIR = build
SERVICES = auth users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \
mongodb-reader cassandra-writer cassandra-reader postgres-writer postgres-reader timescale-writer timescale-reader cli \
bootstrap opcua twins mqtt provision certs smtp-notifier smpp-notifier invitations
TEST_API_SERVICES = auth bootstrap certs http invitations notifiers provision readers things twins users
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
Expand Down Expand Up @@ -97,7 +99,7 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))

all: $(SERVICES)

.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs test_api

clean:
rm -rf ${BUILD_DIR}
Expand Down Expand Up @@ -129,6 +131,35 @@ test: mocks
done
go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|opcua\|cmd')

define test_api_service
$(eval svc=$(subst test_api_,,$(1)))
@which st > /dev/null || (echo "schemathesis not found, please install it from https://github.com/schemathesis/schemathesis#getting-started" && exit 1)

@if [ -z "$(USER_TOKEN)" ]; then \
echo "USER_TOKEN is not set"; \
echo "Please set it to a valid token"; \
exit 1; \
fi

st run api/openapi/$(svc).yml \
--checks all \
--base-url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
--contrib-unique-data --contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links
endef

test_api_users: TEST_API_URL := http://localhost:9002
test_api_things: TEST_API_URL := http://localhost:9000
test_api_invitations: TEST_API_URL := http://localhost:9020
test_api_auth: TEST_API_URL := http://localhost:8189
test_api_bootstrap: TEST_API_URL := http://localhost:9013
test_api_certs: TEST_API_URL := http://localhost:9019

$(TEST_API):
$(call test_api_service,$(@),$(TEST_API_URL))

proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./*.proto
Expand Down
24 changes: 21 additions & 3 deletions api/openapi/auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ info:
version: 0.14.0

servers:
- url: http://localhost:8180
- url: https://localhost:8180
- url: http://localhost:8189
- url: https://localhost:8189

tags:
- name: Auth
Expand Down Expand Up @@ -319,6 +319,7 @@ paths:
$ref: "#/components/responses/ServiceError"
/keys:
post:
operationId: issueKey
tags:
- Keys
summary: Issue API key
Expand All @@ -341,6 +342,7 @@ paths:

/keys/{keyID}:
get:
operationId: getKey
summary: Gets API key details.
description: |
Gets API key details for the given key.
Expand All @@ -355,10 +357,13 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"

delete:
operationId: revokeKey
summary: Revoke API key
description: |
Revoke API key identified by the given ID.
Expand All @@ -371,11 +376,14 @@ paths:
description: Key revoked.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"

/policies:
post:
operationId: addPolicies
summary: Creates new policies.
description: |
Creates new policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Expand All @@ -393,6 +401,8 @@ paths:
description: Missing or invalid access token provided.
"403":
description: Unauthorized access token provided.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing email address.
"415":
Expand All @@ -402,6 +412,7 @@ paths:

/policies/delete:
post:
operationId: deletePolicies
summary: Deletes policies.
description: |
Deletes policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Expand All @@ -415,6 +426,8 @@ paths:
description: Policies deleted.
"400":
description: Failed due to malformed JSON.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing email address.
"415":
Expand Down Expand Up @@ -867,11 +880,16 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Key"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id

HealthRes:
description: Service Health Check.
content:
application/json:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"

Expand Down
Loading
Loading