diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..c14eafa --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contribution expectations + +The following expectations apply to each PR: + +1. The PR and branch are named for [automatic linking](https://support.atlassian.com/jira-cloud-administration/docs/use-the-github-for-jira-app/) to the most relevant JIRA issue (for example, `JRA-123 Adds foo` for PR title and `jra-123-adds-foo` for branch name). +2. Reviewers are selected to include people from all teams impacted by the changes in the PR. +3. The PR has been assigned to the people who will respond to reviews and merge when ready (usually the person filing the review, but can change when a PR is handed off to someone else). +4. The PR is reasonably limited in scope to ensure: + - It doesn't bunch together disparate features, fixes, refactorings, etc. + - There isn't too much of a burden on reviewers. + - Any problems it causes have a small blast radius. + - Changes will be easier to roll back if necessary. +5. The PR includes any required documentation changes, including `README` updates and changelog or release notes entries. +6. All new and modified code is appropriately commented to make the what and why of its design reasonably clear, even to those unfamiliar with the project. +7. Any incomplete work introduced by the PR is detailed in `TODO` comments which include a JIRA ticket ID for any items that require urgent attention. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c2a38dd..21ea69c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,24 +1,21 @@ ## 🎫 Ticket -https://jira.cms.gov/browse/BCDA-xxx +https://jira.cms.gov/browse/... ## 🛠 Changes -(What was added, updated, or removed in this PR.) + -## ℹ️ Context for reviewers +## ℹ️ Context -(Background context, more in-depth details of the implementation, and anything else you'd like to call out or ask reviewers.) + -## ✅ Acceptance Validation + -(How were the changes verified? Did you fully test the acceptance criteria in the ticket? Provide reproducible testing instructions and screenshots if applicable.) +## 🧪 Validation -## 🔒 Security Implications - -- [ ] This PR adds a new software dependency or dependencies. -- [ ] This PR modifies or invalidates one or more of our security controls. -- [ ] This PR stores or transmits data that was not stored or transmitted before. -- [ ] This PR requires additional review of its security implications for other reasons. - -If any security implications apply, add Jason Ashbaugh (GitHub username: StewGoin) as a reviewer and do not merge this PR without his approval. + diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index aa9e2e2..4788425 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -32,7 +32,7 @@ jobs: run: | make test - name: Archive code coverage results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: code-coverage-report path: ./test_results/latest/testcoverage.out @@ -41,9 +41,12 @@ jobs: name: Sonarqube Quality Gate needs: build runs-on: self-hosted + env: + # Workaround until https://jira.cms.gov/browse/PLT-338 is implemented. + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: "true" steps: - name: Download code coverage - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: code-coverage-report - name: Set env vars from AWS params diff --git a/.github/workflows/dbdocs.yml b/.github/workflows/dbdocs.yml new file mode 100644 index 0000000..37e98bb --- /dev/null +++ b/.github/workflows/dbdocs.yml @@ -0,0 +1,27 @@ +# This workflow generates database documentation and ERD files. +# +name: Generate dbdocs + +on: + pull_request: + paths: + - .github/workflows/dbdocs.yml + - db/migrations + +jobs: + generate-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.ref }} + + - name: Generate DB docs + run: make dbdocs + + - uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 + with: + add: dbdocs + message: "Generate dbdocs" + default_author: github_actions diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..5cbcbcf --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,9 @@ +title = "DASG Standard" + +[extend] + useDefault = true + +[[rules]] + id = "mbi-detection" + description = "Detects a potential MBI pattern based on https://www.cms.gov/medicare/new-medicare-card/understanding-the-mbi.pdf" + regex = '''\b((?i)[1-9][ACDEFGHJKMNPQRTUVWXY][ACDEFGHJKMNPQRTUVWXY\d]-?\d[ACDEFGHJKMNPQRTUVWXY][ACDEFGHJKMNPQRTUVWXY\d]\d-?[ACDEFGHJKMNPQRTUVWXY]{2}\d{2})\b''' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 443fe20..1d3562a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,10 @@ repos: - repo: https://github.com/gitleaks/gitleaks - rev: v8.16.1 + rev: v8.19.2 hooks: - id: gitleaks - repo: https://github.com/tekwizely/pre-commit-golang - rev: master + rev: v1.0.0-rc.1 hooks: - id: go-imports args: ['-w'] diff --git a/Dockerfiles/Dockerfile.package b/Dockerfiles/Dockerfile.package index 638d071..8db2478 100644 --- a/Dockerfiles/Dockerfile.package +++ b/Dockerfiles/Dockerfile.package @@ -1,4 +1,4 @@ -FROM golang:1.19-alpine3.15 +FROM golang:1.21.12-alpine3.20 ENV CGO_ENABLED=0 diff --git a/Dockerfiles/Dockerfile.ssas b/Dockerfiles/Dockerfile.ssas index 06b1073..9a9915c 100644 --- a/Dockerfiles/Dockerfile.ssas +++ b/Dockerfiles/Dockerfile.ssas @@ -1,18 +1,19 @@ -FROM golang:1.19-alpine3.15 AS documentation +FROM golang:1.21.12-alpine3.20 AS documentation RUN apk update upgrade -RUN apk add git build-base gcc +RUN apk add git build-base gcc binutils-gold WORKDIR /go/src/github.com/CMSgov/bcda-ssas-app COPY . . +ARG GO111MODULE=auto RUN dir=$(mktemp -d) && \ - git clone -b v0.28.0 https://github.com/go-swagger/go-swagger "$dir" && \ + git clone -b v0.31.0 https://github.com/go-swagger/go-swagger "$dir" && \ cd "$dir" && \ go install ./cmd/swagger WORKDIR /go/src/github.com/CMSgov/bcda-ssas-app/ssas/service/main RUN swagger generate spec -i ../../swaggerui/tags.yml -o ../../swaggerui/swagger.json -m -FROM golang:1.19-alpine3.15 AS builder +FROM golang:1.21.12-alpine3.20 AS builder ARG VERSION RUN apk update upgrade RUN apk add git @@ -22,7 +23,7 @@ WORKDIR /go/src/github.com/CMSgov/bcda-ssas-app/ssas COPY --from=documentation /go/src/github.com/CMSgov/bcda-ssas-app/ssas/swaggerui ./swaggerui RUN go build -ldflags "-X github.com/CMSgov/bcda-ssas-app/ssas/constants.Version=$VERSION" -o ssas ./service/main -FROM golang:1.19-alpine3.15 +FROM golang:1.21.12-alpine3.20 RUN apk update upgrade RUN apk --no-cache add ca-certificates aws-cli curl WORKDIR /go/src/github.com/CMSgov/bcda-ssas-app diff --git a/Dockerfiles/Dockerfile.tests b/Dockerfiles/Dockerfile.tests index 327bd88..05c2c06 100644 --- a/Dockerfiles/Dockerfile.tests +++ b/Dockerfiles/Dockerfile.tests @@ -1,4 +1,4 @@ -FROM golang:1.19-alpine3.15 +FROM golang:1.21.12-alpine3.20 RUN apk update upgrade @@ -6,9 +6,9 @@ RUN apk add bash build-base curl RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin -RUN GO111MODULE=on go install github.com/xo/usql@v0.11.0 -RUN go install github.com/securego/gosec/v2/cmd/gosec@v2.12.0 -RUN go install gotest.tools/gotestsum@v1.8.1 +RUN GO111MODULE=on go install github.com/xo/usql@v0.17.5 +RUN go install github.com/securego/gosec/v2/cmd/gosec@v2.20.0 +RUN go install gotest.tools/gotestsum@v1.12.0 RUN go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.15.2 WORKDIR /go/src/github.com/CMSgov/bcda-ssas-app diff --git a/Makefile b/Makefile index 351bcee..60a8641 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ package: # This target should be executed by passing in an argument representing the version of the artifacts we are packaging # For example: make package version=r1 - docker-compose run --rm documentation swagger generate spec -i ../../swaggerui/tags.yml -o ../../swaggerui/swagger.json -m + docker compose run --rm documentation swagger generate spec -i ../../swaggerui/tags.yml -o ../../swaggerui/swagger.json -m docker build -t packaging -f Dockerfiles/Dockerfile.package . docker run --rm \ -e BCDA_GPG_RPM_PASSPHRASE='${BCDA_GPG_RPM_PASSPHRASE}' \ @@ -12,26 +12,28 @@ package: -v ${PWD}:/go/src/github.com/CMSgov/bcda-ssas-app packaging $(version) lint: - docker-compose -f docker-compose.test.yml run --rm tests golangci-lint -e SA1029 -v run ./... - docker-compose -f docker-compose.test.yml run --rm tests gosec ./... + docker compose -f docker-compose.test.yml run --rm tests golangci-lint -e SA1029 --timeout 10m0s -v run ./... + docker compose -f docker-compose.test.yml run --rm tests gosec ./... # The following vars are available to tests needing SSAS admin credentials; currently they are used in smoke-test-ssas, postman-ssas, and unit-test-ssas # Note that these variables should only be used for smoke tests, must be set before the api starts, and cannot be changed after the api starts SSAS_ADMIN_CLIENT_ID ?= 31e029ef-0e97-47f8-873c-0e8b7e7f99bf -SSAS_ADMIN_CLIENT_SECRET := $(shell docker-compose run --rm ssas sh -c 'ssas --reset-secret --client-id=$(SSAS_ADMIN_CLIENT_ID)'|tail -n1) +SSAS_ADMIN_CLIENT_SECRET := $(shell docker compose run --rm ssas sh -c 'ssas --reset-secret --client-id=$(SSAS_ADMIN_CLIENT_ID)'|tail -n1) smoke-test: - docker-compose -f docker-compose.test.yml run --rm postman_test test/postman_test/SSAS_Smoke_Test.postman_collection.json -e test/postman_test/local.postman_environment.json --global-var "token=$(token)" --global-var adminClientId=$(SSAS_ADMIN_CLIENT_ID) --global-var adminClientSecret=$(SSAS_ADMIN_CLIENT_SECRET) --global-var ssas_client_assertion_aud=$(SASS_CLIENT_ASSERTION_AUD) + docker compose -f docker-compose.test.yml run --rm postman_test test/postman_test/SSAS_Smoke_Test.postman_collection.json -e test/postman_test/local.postman_environment.json --global-var "token=$(token)" --global-var adminClientId=$(SSAS_ADMIN_CLIENT_ID) --global-var adminClientSecret=$(SSAS_ADMIN_CLIENT_SECRET) --global-var ssas_client_assertion_aud=$(SASS_CLIENT_ASSERTION_AUD) postman: - docker-compose -f docker-compose.test.yml run --rm postman_test test/postman_test/SSAS.postman_collection.json -e test/postman_test/local.postman_environment.json --global-var adminClientId=$(SSAS_ADMIN_CLIENT_ID) --global-var adminClientSecret=$(SSAS_ADMIN_CLIENT_SECRET) --global-var ssas_client_assertion_aud=$(SASS_CLIENT_ASSERTION_AUD) + docker compose -f docker-compose.test.yml run --rm postman_test test/postman_test/SSAS.postman_collection.json -e test/postman_test/local.postman_environment.json --global-var adminClientId=$(SSAS_ADMIN_CLIENT_ID) --global-var adminClientSecret=$(SSAS_ADMIN_CLIENT_SECRET) --global-var ssas_client_assertion_aud=$(SASS_CLIENT_ASSERTION_AUD) migrations-test: - docker-compose -f docker-compose.test.yml run --rm tests bash ops/migrations_test.sh + docker compose -f docker-compose.test.yml run --rm tests bash ops/migrations_test.sh -unit-test: - docker-compose up -d db - docker-compose -f docker-compose.test.yml run --rm tests bash unit_test.sh +start-db: + docker compose up -d db + +unit-test: start-db + docker compose -f docker-compose.test.yml run --rm tests bash unit_test.sh test: $(MAKE) lint @@ -41,17 +43,20 @@ test: $(MAKE) migrations-test load-fixtures: - docker-compose -f docker-compose.migrate.yml run --rm migrate -database "postgres://postgres:toor@db:5432/bcda?sslmode=disable" -path /go/src/github.com/CMSgov/bcda-ssas-app/db/migrations up - docker-compose -f docker-compose.yml run ssas sh -c 'ssas --add-fixture-data' + docker compose -f docker-compose.migrate.yml run --rm migrate -database "postgres://postgres:toor@db:5432/bcda?sslmode=disable" -path /go/src/github.com/CMSgov/bcda-ssas-app/db/migrations up + docker compose -f docker-compose.yml run ssas sh -c 'ssas --add-fixture-data' docker-build: - docker-compose build --force-rm - docker-compose -f docker-compose.test.yml build --force-rm + docker compose build --force-rm + docker compose -f docker-compose.test.yml build --force-rm docker-bootstrap: $(MAKE) docker-build - docker-compose up -d + docker compose up -d sleep 40 $(MAKE) load-fixtures -.PHONY: docker-build docker-bootstrap load-fixtures test package release smoke-test postman unit-test lint migrations-test +dbdocs: start-db load-fixtures + docker run --rm -v $PWD:/work -w /work --network bcda-ssas-app_default ghcr.io/k1low/tbls doc --rm-dist "postgres://postgres:toor@db:5432/bcda?sslmode=disable" dbdocs/bcda + +.PHONY: docker-build docker-bootstrap load-fixtures test package release smoke-test postman unit-test lint migrations-test start-db dbdocs diff --git a/README.md b/README.md index 3639c3c..97de17e 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ The project uses [Go Modules](https://golang.org/ref/mod) allowing you to clone # Build -Build all the code and containers with `make docker-bootstrap`. Alternatively, `docker-compose up ssas` will build and run the SSAS by itself. Note that SSAS needs the db container to be running as well. +Build all the code and containers with `make docker-bootstrap`. Alternatively, `docker compose up ssas` will build and run the SSAS by itself. Note that SSAS needs the db container to be running as well. ## Bootstrapping CLI @@ -129,7 +129,7 @@ one of these test suites, follow the instructions at the top of the test file. ### **Running Single / Single-file Unit Tests** -This step assumes that the user has installed VSCode, the Go language extension available [here](https://marketplace.visualstudio.com/items?itemName=golang.Go), and has successfully imported test data to their local database. +This step assumes that the user has installed VSCode, the Go language extension available [here](https://marketplace.visualstudio.com/items?itemName=golang.Go), and has successfully imported test data to their local database. To run tests from within VSCode: In a FILENAME_test.go file, there will be a green arrow to the left of the method name, and clicking this arrow will run a single test locally. Tests should not be dependent upon other tests, but if a known-good test is failing, the user can run all tests in a given file by going to View -> Command Palette -> Go: Test Package, which will run all tests in a given file. Alternatively, in some instances, the init() method can be commented out to enable testing of single functions. @@ -138,13 +138,13 @@ In a FILENAME_test.go file, there will be a green arrow to the left of the metho To run postman tests locally: -Build and startup the required containers. Building with docker-compose up first will significantly improve the performance of the following steps. +Build and startup the required containers. Building with docker compose up first will significantly improve the performance of the following steps. ``` -docker-compose up -docker-compose stop -docker-compose up -d db -docker-compose up ssas +docker compose up +docker compose stop +docker compose up -d db +docker compose up ssas ``` If this is the first time you've started the containers, set up your database tables and seed them with sample group and systems: @@ -175,13 +175,13 @@ docker run --rm --network bcda-ssas-app_default -e PGPASSWORD=PASSHERE -it postg To reset a secret by client id (can be found in Makefile): ``` -docker-compose run --rm ssas sh -c 'ssas --reset-secret --client-id=[client_id]' +docker compose run --rm ssas sh -c 'ssas --reset-secret --client-id=[client_id]' ``` To list all active IPs from the connected database: ``` -docker-compose run --rm ssas sh -c 'ssas --list-ips' +docker compose run --rm ssas sh -c 'ssas --list-ips' ``` # Swagger Documentation @@ -190,11 +190,11 @@ The admin server has Swagger documentation. To access: 1. Make sure it's been built (the container will stop after a few seconds when the documentation is ready) - `docker-compose up documentation` + `docker compose up documentation` 1. Make sure the `ssas` container is running - `docker-compose up ssas` + `docker compose up ssas` 1. Access Swagger in your browser: http://localhost:3104/swagger diff --git a/db/migrations/README.md b/db/migrations/README.md index e5ad097..c4c84b3 100644 --- a/db/migrations/README.md +++ b/db/migrations/README.md @@ -4,7 +4,7 @@ * All database changes will be modeled in discrete schema migrations * Code to roll back a migration will be included unless highly impracticable * Migrations will receive unique sequential integer identifiers. - * Engineers should keep aware of identifier collisions (and in some instances required migration order), and adjust their migration ID’s before merging with master, if necessary. + * Engineers should keep aware of identifier collisions (and in some instances required migration order), and adjust their migration ID’s before merging with main, if necessary. * Migrations will be written with production environments in mind * If data changes are required (default values instead of nulls, compound fields broken apart, etc.), the migration will include commands for these transformations. * If the migration would break running instances, reasonable effort will be made to write multiple migrations. In the first migration, a non-breaking transition schema will be used that can support both the old and new code versions. After all instances have been upgraded, the final version of the schema can be introduced in a second migration. @@ -19,4 +19,4 @@ * Using the file format `######_schema_name.[up|down].sql` create separate scripts for each schema change, and for reversing the schema change. * Add tests for both scripts in `migrations_test.go` * Test migration scripts - * Run `make migrations-test` \ No newline at end of file + * Run `make migrations-test` diff --git a/dbdocs/bcda/README.md b/dbdocs/bcda/README.md new file mode 100644 index 0000000..b96bde2 --- /dev/null +++ b/dbdocs/bcda/README.md @@ -0,0 +1,23 @@ +# bcda + +## Tables + +| Name | Columns | Comment | Type | +| ---- | ------- | ------- | ---- | +| [public.schema_migrations](public.schema_migrations.md) | 2 | | BASE TABLE | +| [public.blacklist_entries](public.blacklist_entries.md) | 7 | | BASE TABLE | +| [public.encryption_keys](public.encryption_keys.md) | 7 | | BASE TABLE | +| [public.groups](public.groups.md) | 7 | | BASE TABLE | +| [public.secrets](public.secrets.md) | 6 | | BASE TABLE | +| [public.systems](public.systems.md) | 12 | | BASE TABLE | +| [public.ips](public.ips.md) | 6 | | BASE TABLE | +| [public.client_tokens](public.client_tokens.md) | 8 | | BASE TABLE | +| [public.root_keys](public.root_keys.md) | 8 | | BASE TABLE | + +## Relations + +![er](schema.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.blacklist_entries.md b/dbdocs/bcda/public.blacklist_entries.md new file mode 100644 index 0000000..bcd1637 --- /dev/null +++ b/dbdocs/bcda/public.blacklist_entries.md @@ -0,0 +1,36 @@ +# public.blacklist_entries + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('blacklist_entries_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| key | text | | false | | | | +| entry_date | bigint | | false | | | | +| cache_expiration | bigint | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| blacklist_entries_pkey | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| blacklist_entries_pkey | CREATE UNIQUE INDEX blacklist_entries_pkey ON public.blacklist_entries USING btree (id) | +| idx_blacklist_entries_deleted_at | CREATE INDEX idx_blacklist_entries_deleted_at ON public.blacklist_entries USING btree (deleted_at) | + +## Relations + +![er](public.blacklist_entries.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.blacklist_entries.svg b/dbdocs/bcda/public.blacklist_entries.svg new file mode 100644 index 0000000..ec658f1 --- /dev/null +++ b/dbdocs/bcda/public.blacklist_entries.svg @@ -0,0 +1,44 @@ + + + + + + +public.blacklist_entries + + + +public.blacklist_entries + + +public.blacklist_entries +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +key +[text] + +entry_date +[bigint] + +cache_expiration +[bigint] + + + + diff --git a/dbdocs/bcda/public.client_tokens.md b/dbdocs/bcda/public.client_tokens.md new file mode 100644 index 0000000..3c31d29 --- /dev/null +++ b/dbdocs/bcda/public.client_tokens.md @@ -0,0 +1,36 @@ +# public.client_tokens + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('client_tokens_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| label | text | | true | | | | +| uuid | text | | false | | | | +| system_id | integer | | true | | | | +| expires_at | timestamp with time zone | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| client_tokens_uuid_key | UNIQUE | UNIQUE (uuid) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| client_tokens_uuid_key | CREATE UNIQUE INDEX client_tokens_uuid_key ON public.client_tokens USING btree (uuid) | + +## Relations + +![er](public.client_tokens.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.client_tokens.svg b/dbdocs/bcda/public.client_tokens.svg new file mode 100644 index 0000000..2f746f3 --- /dev/null +++ b/dbdocs/bcda/public.client_tokens.svg @@ -0,0 +1,47 @@ + + + + + + +public.client_tokens + + + +public.client_tokens + + +public.client_tokens +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +label +[text] + +uuid +[text] + +system_id +[integer] + +expires_at +[timestamp with time zone] + + + + diff --git a/dbdocs/bcda/public.encryption_keys.md b/dbdocs/bcda/public.encryption_keys.md new file mode 100644 index 0000000..0b94a3e --- /dev/null +++ b/dbdocs/bcda/public.encryption_keys.md @@ -0,0 +1,37 @@ +# public.encryption_keys + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('encryption_keys_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| body | text | | true | | | | +| system_id | integer | | true | | [public.systems](public.systems.md) | | +| uuid | text | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| encryption_keys_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| encryption_keys_system_id_systems_id_foreign | FOREIGN KEY | FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| encryption_keys_pkey | CREATE UNIQUE INDEX encryption_keys_pkey ON public.encryption_keys USING btree (id) | +| idx_encryption_keys_deleted_at | CREATE INDEX idx_encryption_keys_deleted_at ON public.encryption_keys USING btree (deleted_at) | + +## Relations + +![er](public.encryption_keys.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.encryption_keys.svg b/dbdocs/bcda/public.encryption_keys.svg new file mode 100644 index 0000000..67b8655 --- /dev/null +++ b/dbdocs/bcda/public.encryption_keys.svg @@ -0,0 +1,96 @@ + + + + + + +public.encryption_keys + + + +public.encryption_keys + + +public.encryption_keys +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +body +[text] + +system_id +[integer] + +uuid +[text] + + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +client_id     +[text] + +software_id     +[text] + +client_name     +[text] + +api_scope     +[text] + +g_id     +[integer] + +last_token_at     +[timestamp with time zone] + +x_data     +[text] + + + +public.encryption_keys:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + diff --git a/dbdocs/bcda/public.groups.md b/dbdocs/bcda/public.groups.md new file mode 100644 index 0000000..8838e88 --- /dev/null +++ b/dbdocs/bcda/public.groups.md @@ -0,0 +1,37 @@ +# public.groups + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('groups_id_seq'::regclass) | false | [public.systems](public.systems.md) | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| group_id | text | | false | | | | +| x_data | text | | true | | | | +| data | jsonb | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| groups_pkey | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| groups_pkey | CREATE UNIQUE INDEX groups_pkey ON public.groups USING btree (id) | +| idx_groups_deleted_at | CREATE INDEX idx_groups_deleted_at ON public.groups USING btree (deleted_at) | +| groups_group_id_deleted_at_key | CREATE UNIQUE INDEX groups_group_id_deleted_at_key ON public.groups USING btree (group_id) WHERE (deleted_at IS NULL) | + +## Relations + +![er](public.groups.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.groups.svg b/dbdocs/bcda/public.groups.svg new file mode 100644 index 0000000..55cd159 --- /dev/null +++ b/dbdocs/bcda/public.groups.svg @@ -0,0 +1,96 @@ + + + + + + +public.groups + + + +public.groups + + +public.groups +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +group_id +[text] + +x_data +[text] + +data +[jsonb] + + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +client_id     +[text] + +software_id     +[text] + +client_name     +[text] + +api_scope     +[text] + +g_id     +[integer] + +last_token_at     +[timestamp with time zone] + +x_data     +[text] + + + +public.systems:g_id->public.groups:id + + +FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + diff --git a/dbdocs/bcda/public.ips.md b/dbdocs/bcda/public.ips.md new file mode 100644 index 0000000..499e06d --- /dev/null +++ b/dbdocs/bcda/public.ips.md @@ -0,0 +1,36 @@ +# public.ips + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('ips_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| address | inet | | false | | | | +| system_id | integer | | false | | [public.systems](public.systems.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| ips_system_id_systems_id_foreign | FOREIGN KEY | FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT | +| ips_pkey | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| ips_pkey | CREATE UNIQUE INDEX ips_pkey ON public.ips USING btree (id) | +| idx_ips_deleted_at | CREATE INDEX idx_ips_deleted_at ON public.ips USING btree (deleted_at) | + +## Relations + +![er](public.ips.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.ips.svg b/dbdocs/bcda/public.ips.svg new file mode 100644 index 0000000..9522d96 --- /dev/null +++ b/dbdocs/bcda/public.ips.svg @@ -0,0 +1,93 @@ + + + + + + +public.ips + + + +public.ips + + +public.ips +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +address +[inet] + +system_id +[integer] + + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +client_id     +[text] + +software_id     +[text] + +client_name     +[text] + +api_scope     +[text] + +g_id     +[integer] + +last_token_at     +[timestamp with time zone] + +x_data     +[text] + + + +public.ips:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + diff --git a/dbdocs/bcda/public.root_keys.md b/dbdocs/bcda/public.root_keys.md new file mode 100644 index 0000000..c241e6b --- /dev/null +++ b/dbdocs/bcda/public.root_keys.md @@ -0,0 +1,36 @@ +# public.root_keys + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('root_keys_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| expires_at | timestamp with time zone | | true | | | | +| uuid | text | | false | | | | +| key | text | | false | | | | +| system_id | integer | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| root_keys_uuid_system_id_key | UNIQUE | UNIQUE (uuid, system_id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| root_keys_uuid_system_id_key | CREATE UNIQUE INDEX root_keys_uuid_system_id_key ON public.root_keys USING btree (uuid, system_id) | + +## Relations + +![er](public.root_keys.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.root_keys.svg b/dbdocs/bcda/public.root_keys.svg new file mode 100644 index 0000000..828c595 --- /dev/null +++ b/dbdocs/bcda/public.root_keys.svg @@ -0,0 +1,47 @@ + + + + + + +public.root_keys + + + +public.root_keys + + +public.root_keys +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +expires_at +[timestamp with time zone] + +uuid +[text] + +key +[text] + +system_id +[integer] + + + + diff --git a/dbdocs/bcda/public.schema_migrations.md b/dbdocs/bcda/public.schema_migrations.md new file mode 100644 index 0000000..ce19fba --- /dev/null +++ b/dbdocs/bcda/public.schema_migrations.md @@ -0,0 +1,30 @@ +# public.schema_migrations + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| version | bigint | | false | | | | +| dirty | boolean | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| schema_migrations_pkey | PRIMARY KEY | PRIMARY KEY (version) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| schema_migrations_pkey | CREATE UNIQUE INDEX schema_migrations_pkey ON public.schema_migrations USING btree (version) | + +## Relations + +![er](public.schema_migrations.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.schema_migrations.svg b/dbdocs/bcda/public.schema_migrations.svg new file mode 100644 index 0000000..d757865 --- /dev/null +++ b/dbdocs/bcda/public.schema_migrations.svg @@ -0,0 +1,29 @@ + + + + + + +public.schema_migrations + + + +public.schema_migrations + + +public.schema_migrations +     +[BASE TABLE] + +version +[bigint] + +dirty +[boolean] + + + + diff --git a/dbdocs/bcda/public.secrets.md b/dbdocs/bcda/public.secrets.md new file mode 100644 index 0000000..3d98f7b --- /dev/null +++ b/dbdocs/bcda/public.secrets.md @@ -0,0 +1,36 @@ +# public.secrets + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('secrets_id_seq'::regclass) | false | | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| hash | text | | true | | | | +| system_id | integer | | true | | [public.systems](public.systems.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| secrets_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| secrets_system_id_systems_id_foreign | FOREIGN KEY | FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| secrets_pkey | CREATE UNIQUE INDEX secrets_pkey ON public.secrets USING btree (id) | +| idx_secrets_deleted_at | CREATE INDEX idx_secrets_deleted_at ON public.secrets USING btree (deleted_at) | + +## Relations + +![er](public.secrets.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.secrets.svg b/dbdocs/bcda/public.secrets.svg new file mode 100644 index 0000000..f9a5ab6 --- /dev/null +++ b/dbdocs/bcda/public.secrets.svg @@ -0,0 +1,93 @@ + + + + + + +public.secrets + + + +public.secrets + + +public.secrets +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +hash +[text] + +system_id +[integer] + + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +client_id     +[text] + +software_id     +[text] + +client_name     +[text] + +api_scope     +[text] + +g_id     +[integer] + +last_token_at     +[timestamp with time zone] + +x_data     +[text] + + + +public.secrets:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + diff --git a/dbdocs/bcda/public.systems.md b/dbdocs/bcda/public.systems.md new file mode 100644 index 0000000..e2de38e --- /dev/null +++ b/dbdocs/bcda/public.systems.md @@ -0,0 +1,43 @@ +# public.systems + +## Description + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | nextval('systems_id_seq'::regclass) | false | [public.encryption_keys](public.encryption_keys.md) [public.secrets](public.secrets.md) [public.ips](public.ips.md) | | | +| created_at | timestamp with time zone | | true | | | | +| updated_at | timestamp with time zone | | true | | | | +| deleted_at | timestamp with time zone | | true | | | | +| group_id | text | | true | | | | +| client_id | text | | true | | | | +| software_id | text | | true | | | | +| client_name | text | | true | | | | +| api_scope | text | | true | | | | +| g_id | integer | | true | | [public.groups](public.groups.md) | | +| last_token_at | timestamp with time zone | | true | | | | +| x_data | text | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| systems_g_id_groups_g_id_foreign | FOREIGN KEY | FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT | +| systems_pkey | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| systems_pkey | CREATE UNIQUE INDEX systems_pkey ON public.systems USING btree (id) | +| idx_systems_deleted_at | CREATE INDEX idx_systems_deleted_at ON public.systems USING btree (deleted_at) | +| idx_client | CREATE UNIQUE INDEX idx_client ON public.systems USING btree (client_id) | + +## Relations + +![er](public.systems.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/dbdocs/bcda/public.systems.svg b/dbdocs/bcda/public.systems.svg new file mode 100644 index 0000000..483a049 --- /dev/null +++ b/dbdocs/bcda/public.systems.svg @@ -0,0 +1,201 @@ + + + + + + +public.systems + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id +[integer] + +created_at +[timestamp with time zone] + +updated_at +[timestamp with time zone] + +deleted_at +[timestamp with time zone] + +group_id +[text] + +client_id +[text] + +software_id +[text] + +client_name +[text] + +api_scope +[text] + +g_id +[integer] + +last_token_at +[timestamp with time zone] + +x_data +[text] + + + + +public.groups + + +public.groups +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +x_data     +[text] + +data     +[jsonb] + + + +public.systems:g_id->public.groups:id + + +FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.encryption_keys + + +public.encryption_keys +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +body     +[text] + +system_id     +[integer] + +uuid     +[text] + + + +public.encryption_keys:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.secrets + + +public.secrets +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +hash     +[text] + +system_id     +[integer] + + + +public.secrets:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.ips + + +public.ips +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +address     +[inet] + +system_id     +[integer] + + + +public.ips:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + diff --git a/dbdocs/bcda/schema.json b/dbdocs/bcda/schema.json new file mode 100644 index 0000000..6b00399 --- /dev/null +++ b/dbdocs/bcda/schema.json @@ -0,0 +1 @@ +{"name":"bcda","desc":"","tables":[{"name":"public.schema_migrations","type":"BASE TABLE","comment":"","columns":[{"name":"version","type":"bigint","nullable":false,"default":null,"comment":""},{"name":"dirty","type":"boolean","nullable":false,"default":null,"comment":""}],"indexes":[{"name":"schema_migrations_pkey","def":"CREATE UNIQUE INDEX schema_migrations_pkey ON public.schema_migrations USING btree (version)","table":"public.schema_migrations","columns":["version"],"comment":""}],"constraints":[{"name":"schema_migrations_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (version)","table":"public.schema_migrations","referenced_table":"","columns":["version"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.blacklist_entries","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('blacklist_entries_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"key","type":"text","nullable":false,"default":null,"comment":""},{"name":"entry_date","type":"bigint","nullable":false,"default":null,"comment":""},{"name":"cache_expiration","type":"bigint","nullable":false,"default":null,"comment":""}],"indexes":[{"name":"blacklist_entries_pkey","def":"CREATE UNIQUE INDEX blacklist_entries_pkey ON public.blacklist_entries USING btree (id)","table":"public.blacklist_entries","columns":["id"],"comment":""},{"name":"idx_blacklist_entries_deleted_at","def":"CREATE INDEX idx_blacklist_entries_deleted_at ON public.blacklist_entries USING btree (deleted_at)","table":"public.blacklist_entries","columns":["deleted_at"],"comment":""}],"constraints":[{"name":"blacklist_entries_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.blacklist_entries","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.encryption_keys","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('encryption_keys_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"body","type":"text","nullable":true,"default":null,"comment":""},{"name":"system_id","type":"integer","nullable":true,"default":null,"comment":""},{"name":"uuid","type":"text","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"encryption_keys_pkey","def":"CREATE UNIQUE INDEX encryption_keys_pkey ON public.encryption_keys USING btree (id)","table":"public.encryption_keys","columns":["id"],"comment":""},{"name":"idx_encryption_keys_deleted_at","def":"CREATE INDEX idx_encryption_keys_deleted_at ON public.encryption_keys USING btree (deleted_at)","table":"public.encryption_keys","columns":["deleted_at"],"comment":""}],"constraints":[{"name":"encryption_keys_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.encryption_keys","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""},{"name":"encryption_keys_system_id_systems_id_foreign","type":"FOREIGN KEY","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","table":"public.encryption_keys","referenced_table":"systems","columns":["system_id"],"referenced_columns":["id"],"comment":""}],"triggers":[],"def":""},{"name":"public.groups","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('groups_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"group_id","type":"text","nullable":false,"default":null,"comment":""},{"name":"x_data","type":"text","nullable":true,"default":null,"comment":""},{"name":"data","type":"jsonb","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"groups_pkey","def":"CREATE UNIQUE INDEX groups_pkey ON public.groups USING btree (id)","table":"public.groups","columns":["id"],"comment":""},{"name":"idx_groups_deleted_at","def":"CREATE INDEX idx_groups_deleted_at ON public.groups USING btree (deleted_at)","table":"public.groups","columns":["deleted_at"],"comment":""},{"name":"groups_group_id_deleted_at_key","def":"CREATE UNIQUE INDEX groups_group_id_deleted_at_key ON public.groups USING btree (group_id) WHERE (deleted_at IS NULL)","table":"public.groups","columns":["group_id"],"comment":""}],"constraints":[{"name":"groups_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.groups","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.secrets","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('secrets_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"hash","type":"text","nullable":true,"default":null,"comment":""},{"name":"system_id","type":"integer","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"secrets_pkey","def":"CREATE UNIQUE INDEX secrets_pkey ON public.secrets USING btree (id)","table":"public.secrets","columns":["id"],"comment":""},{"name":"idx_secrets_deleted_at","def":"CREATE INDEX idx_secrets_deleted_at ON public.secrets USING btree (deleted_at)","table":"public.secrets","columns":["deleted_at"],"comment":""}],"constraints":[{"name":"secrets_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.secrets","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""},{"name":"secrets_system_id_systems_id_foreign","type":"FOREIGN KEY","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","table":"public.secrets","referenced_table":"systems","columns":["system_id"],"referenced_columns":["id"],"comment":""}],"triggers":[],"def":""},{"name":"public.systems","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('systems_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"group_id","type":"text","nullable":true,"default":null,"comment":""},{"name":"client_id","type":"text","nullable":true,"default":null,"comment":""},{"name":"software_id","type":"text","nullable":true,"default":null,"comment":""},{"name":"client_name","type":"text","nullable":true,"default":null,"comment":""},{"name":"api_scope","type":"text","nullable":true,"default":null,"comment":""},{"name":"g_id","type":"integer","nullable":true,"default":null,"comment":""},{"name":"last_token_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"x_data","type":"text","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"systems_pkey","def":"CREATE UNIQUE INDEX systems_pkey ON public.systems USING btree (id)","table":"public.systems","columns":["id"],"comment":""},{"name":"idx_systems_deleted_at","def":"CREATE INDEX idx_systems_deleted_at ON public.systems USING btree (deleted_at)","table":"public.systems","columns":["deleted_at"],"comment":""},{"name":"idx_client","def":"CREATE UNIQUE INDEX idx_client ON public.systems USING btree (client_id)","table":"public.systems","columns":["client_id"],"comment":""}],"constraints":[{"name":"systems_g_id_groups_g_id_foreign","type":"FOREIGN KEY","def":"FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT","table":"public.systems","referenced_table":"groups","columns":["g_id"],"referenced_columns":["id"],"comment":""},{"name":"systems_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.systems","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.ips","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('ips_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"address","type":"inet","nullable":false,"default":null,"comment":""},{"name":"system_id","type":"integer","nullable":false,"default":null,"comment":""}],"indexes":[{"name":"ips_pkey","def":"CREATE UNIQUE INDEX ips_pkey ON public.ips USING btree (id)","table":"public.ips","columns":["id"],"comment":""},{"name":"idx_ips_deleted_at","def":"CREATE INDEX idx_ips_deleted_at ON public.ips USING btree (deleted_at)","table":"public.ips","columns":["deleted_at"],"comment":""}],"constraints":[{"name":"ips_system_id_systems_id_foreign","type":"FOREIGN KEY","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","table":"public.ips","referenced_table":"systems","columns":["system_id"],"referenced_columns":["id"],"comment":""},{"name":"ips_pkey","type":"PRIMARY KEY","def":"PRIMARY KEY (id)","table":"public.ips","referenced_table":"","columns":["id"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.client_tokens","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('client_tokens_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"label","type":"text","nullable":true,"default":null,"comment":""},{"name":"uuid","type":"text","nullable":false,"default":null,"comment":""},{"name":"system_id","type":"integer","nullable":true,"default":null,"comment":""},{"name":"expires_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"client_tokens_uuid_key","def":"CREATE UNIQUE INDEX client_tokens_uuid_key ON public.client_tokens USING btree (uuid)","table":"public.client_tokens","columns":["uuid"],"comment":""}],"constraints":[{"name":"client_tokens_uuid_key","type":"UNIQUE","def":"UNIQUE (uuid)","table":"public.client_tokens","referenced_table":"","columns":["uuid"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""},{"name":"public.root_keys","type":"BASE TABLE","comment":"","columns":[{"name":"id","type":"integer","nullable":false,"default":"nextval('root_keys_id_seq'::regclass)","comment":""},{"name":"created_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"updated_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"deleted_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"expires_at","type":"timestamp with time zone","nullable":true,"default":null,"comment":""},{"name":"uuid","type":"text","nullable":false,"default":null,"comment":""},{"name":"key","type":"text","nullable":false,"default":null,"comment":""},{"name":"system_id","type":"integer","nullable":true,"default":null,"comment":""}],"indexes":[{"name":"root_keys_uuid_system_id_key","def":"CREATE UNIQUE INDEX root_keys_uuid_system_id_key ON public.root_keys USING btree (uuid, system_id)","table":"public.root_keys","columns":["system_id","uuid"],"comment":""}],"constraints":[{"name":"root_keys_uuid_system_id_key","type":"UNIQUE","def":"UNIQUE (uuid, system_id)","table":"public.root_keys","referenced_table":"","columns":["uuid","system_id"],"referenced_columns":[],"comment":""}],"triggers":[],"def":""}],"relations":[{"table":"public.encryption_keys","columns":["system_id"],"cardinality":"Zero or more","parent_table":"public.systems","parent_columns":["id"],"parent_cardinality":"Zero or one","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","virtual":false},{"table":"public.secrets","columns":["system_id"],"cardinality":"Zero or more","parent_table":"public.systems","parent_columns":["id"],"parent_cardinality":"Zero or one","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","virtual":false},{"table":"public.systems","columns":["g_id"],"cardinality":"Zero or more","parent_table":"public.groups","parent_columns":["id"],"parent_cardinality":"Zero or one","def":"FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT","virtual":false},{"table":"public.ips","columns":["system_id"],"cardinality":"Zero or more","parent_table":"public.systems","parent_columns":["id"],"parent_cardinality":"Exactly one","def":"FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT","virtual":false}],"functions":[],"driver":{"name":"postgres","database_version":"PostgreSQL 15.7 (Debian 15.7-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit","meta":{"current_schema":"public","search_paths":["postgres","public"],"dict":{"Functions":"Stored procedures and functions"}}}} diff --git a/dbdocs/bcda/schema.svg b/dbdocs/bcda/schema.svg new file mode 100644 index 0000000..3568642 --- /dev/null +++ b/dbdocs/bcda/schema.svg @@ -0,0 +1,311 @@ + + + + + + +bcda + + + +public.schema_migrations + + +public.schema_migrations +     +[BASE TABLE] + +version     +[bigint] + +dirty     +[boolean] + + + +public.blacklist_entries + + +public.blacklist_entries +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +key     +[text] + +entry_date     +[bigint] + +cache_expiration     +[bigint] + + + +public.encryption_keys + + +public.encryption_keys +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +body     +[text] + +system_id     +[integer] + +uuid     +[text] + + + +public.systems + + +public.systems +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +client_id     +[text] + +software_id     +[text] + +client_name     +[text] + +api_scope     +[text] + +g_id     +[integer] + +last_token_at     +[timestamp with time zone] + +x_data     +[text] + + + +public.encryption_keys:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.groups + + +public.groups +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +group_id     +[text] + +x_data     +[text] + +data     +[jsonb] + + + +public.secrets + + +public.secrets +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +hash     +[text] + +system_id     +[integer] + + + +public.secrets:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.systems:g_id->public.groups:id + + +FOREIGN KEY (g_id) REFERENCES groups(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.ips + + +public.ips +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +address     +[inet] + +system_id     +[integer] + + + +public.ips:system_id->public.systems:id + + +FOREIGN KEY (system_id) REFERENCES systems(id) ON UPDATE RESTRICT ON DELETE RESTRICT + + + +public.client_tokens + + +public.client_tokens +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +label     +[text] + +uuid     +[text] + +system_id     +[integer] + +expires_at     +[timestamp with time zone] + + + +public.root_keys + + +public.root_keys +     +[BASE TABLE] + +id     +[integer] + +created_at     +[timestamp with time zone] + +updated_at     +[timestamp with time zone] + +deleted_at     +[timestamp with time zone] + +expires_at     +[timestamp with time zone] + +uuid     +[text] + +key     +[text] + +system_id     +[integer] + + + diff --git a/docker-compose.yml b/docker-compose.yml index e13c50b..8510bc8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: db: - image: postgres:11 + image: postgres:15 environment: - POSTGRES_DB=bcda - POSTGRES_PASSWORD=toor diff --git a/go.mod b/go.mod index f32674e..f07a077 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/pborman/uuid v1.2.1 github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.1 - golang.org/x/crypto v0.17.0 + golang.org/x/crypto v0.23.0 gopkg.in/macaroon.v2 v2.1.0 gorm.io/driver/postgres v1.5.4 gorm.io/gorm v1.25.5 @@ -33,12 +33,12 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fbc0363..6cd9352 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -118,8 +118,8 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -133,11 +133,11 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -172,8 +172,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/macaroon.v2 v2.1.0 h1:HZcsjBCzq9t0eBPMKqTN/uSN6JOm78ZJ2INbqcBQOUI= diff --git a/ops/Jenkinsfile.build_trigger b/ops/Jenkinsfile.build_trigger index d6dd59e..cc4ca61 100644 --- a/ops/Jenkinsfile.build_trigger +++ b/ops/Jenkinsfile.build_trigger @@ -41,7 +41,7 @@ pipeline { ]] ]) script { - if (env.BRANCH_NAME == "master") { + if (env.BRANCH_NAME == "main") { DEPLOY='dev' } } @@ -51,7 +51,7 @@ pipeline { stage('Build and Package') { steps { build job: 'BCDA - Build and Package', - // Since this is being triggered by a code delivery to SSAS repo, it should always be built with BCDA master + // Since this is being triggered by a code delivery to SSAS repo, it should always be built with BCDA main parameters: [string(name: 'SSAS_GIT_VERSION', value: "${env.BRANCH_NAME}"), string(name: 'DEPLOY', value: "${DEPLOY}")], wait: true, propagate: true diff --git a/ops/migrations_test.sh b/ops/migrations_test.sh index ec21f95..38610e8 100644 --- a/ops/migrations_test.sh +++ b/ops/migrations_test.sh @@ -1,7 +1,7 @@ #!/bin/bash # # This script is intended to be run from within the Docker "tests" container -# The docker-compose file brings forward the env vars: DB +# The docker compose file brings forward the env vars: DB # set -e set -o pipefail diff --git a/ssas/groups.go b/ssas/groups.go index 45cc6db..3d05d73 100644 --- a/ssas/groups.go +++ b/ssas/groups.go @@ -106,8 +106,7 @@ func ListGroups(ctx context.Context) (list GroupList, err error) { func UpdateGroup(ctx context.Context, id string, gd GroupData) (Group, error) { g, err := GetGroupByID(ctx, id) if err != nil { - errString := fmt.Sprintf("record not found for id=%s", id) - err := fmt.Errorf(errString) + err := fmt.Errorf("record not found for id=%s", id) return Group{}, err } gd.GroupID = g.Data.GroupID diff --git a/ssas/service/admin/api.go b/ssas/service/admin/api.go index 70ebfbc..29c4af5 100644 --- a/ssas/service/admin/api.go +++ b/ssas/service/admin/api.go @@ -149,7 +149,7 @@ func updateGroup(w http.ResponseWriter, r *http.Request) { gd := ssas.GroupData{} err := json.Unmarshal(body, &gd) if err != nil { - logger.Error("failed to marshal JSON: ", err) + logger.Error("failed to unmarshal JSON: ", err) service.JSONError(w, http.StatusBadRequest, "invalid request body", "") return } @@ -272,7 +272,7 @@ func updateSystem(w http.ResponseWriter, r *http.Request) { _, err = ssas.UpdateSystem(r.Context(), id, v) if err != nil { logger.Errorf("failed to update system; %s", err) - service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "failed to update system") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "failed to update system") return } @@ -308,7 +308,7 @@ func deleteGroup(w http.ResponseWriter, r *http.Request) { err := ssas.DeleteGroup(r.Context(), id) if err != nil { logger.Errorf("failed to delete group; %s", err) - service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "failed to delete group") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "failed to delete group") return } @@ -565,6 +565,12 @@ func deactivateSystemCredentials(w http.ResponseWriter, r *http.Request) { */ func revokeToken(w http.ResponseWriter, r *http.Request) { tokenID := chi.URLParam(r, "tokenID") + + if tokenID == "" { + service.JSONError(w, http.StatusBadRequest, "Missing tokenID", "") + return + } + ssas.SetCtxEntry(r, "Op", "TokenBlacklist") logger := ssas.GetCtxLogger(r.Context()) logger.Infof("Operation Called: admin.revokeToken()") @@ -592,7 +598,7 @@ func registerIP(w http.ResponseWriter, r *http.Request) { system, err := ssas.GetSystemByID(r.Context(), systemID) if err != nil { logger.Errorf("failed to retrieve system; %s", err) - service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusBadRequest), "Invalid system ID") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "Invalid system ID") return } @@ -653,7 +659,7 @@ func getSystemIPs(w http.ResponseWriter, r *http.Request) { ips, err := system.GetIps(r.Context()) if err != nil { logger.Error("Could not retrieve system ips", err) - service.JSONError(w, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), "") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "") return } @@ -711,7 +717,7 @@ func deleteSystemIP(w http.ResponseWriter, r *http.Request) { err = system.DeleteIP(r.Context(), ipID) if err != nil { logger.Errorf("failed to delete IP: %s", err) - service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "failed to delete IP") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "failed to delete IP") return } @@ -742,13 +748,13 @@ func createToken(w http.ResponseWriter, r *http.Request) { b, err := io.ReadAll(r.Body) if err != nil { logger.Error(err) - service.JSONError(w, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), "") + service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "") return } if err := json.Unmarshal(b, &body); err != nil { logger.Error("unable to marshal JSON: ", err) - service.JSONError(w, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), "") + service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "") return } @@ -828,6 +834,12 @@ func createKey(w http.ResponseWriter, r *http.Request) { return } + if pk.PublicKey == "" || pk.Signature == "" { + logger.Error("failed to receive PublicKey and/or Signature") + service.JSONError(w, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), "") + return + } + key, err := system.AddAdditionalPublicKey(strings.NewReader(pk.PublicKey), pk.Signature) if err != nil { logger.Error("failed to add additional public key: ", err) @@ -849,7 +861,7 @@ func deleteKey(w http.ResponseWriter, r *http.Request) { system, err := ssas.GetSystemByID(r.Context(), systemID) if err != nil { logger.Error("failed to get system: ", err) - service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusInternalServerError), "Invalid system ID") + service.JSONError(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), "Invalid system ID") return } diff --git a/ssas/service/admin/api_test.go b/ssas/service/admin/api_test.go index d944e51..9b00767 100644 --- a/ssas/service/admin/api_test.go +++ b/ssas/service/admin/api_test.go @@ -266,7 +266,7 @@ func (s *APITestSuite) TestRevokeTokenNoToken() { handler.ServeHTTP(rr, req) // TODO(BCDA-7212): Handle gracefully - assert.Equal(s.T(), http.StatusInternalServerError, rr.Result().StatusCode) + assert.Equal(s.T(), http.StatusBadRequest, rr.Result().StatusCode) } func (s *APITestSuite) TestDeleteGroup() { @@ -949,7 +949,7 @@ func (s *APITestSuite) TestDeleteIPIPNotFound() { rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) - assert.Equal(s.T(), http.StatusBadRequest, rr.Result().StatusCode) + assert.Equal(s.T(), http.StatusNotFound, rr.Result().StatusCode) _ = ssas.CleanDatabase(group) } @@ -1064,7 +1064,7 @@ func (s *APITestSuite) TestUpdateNonExistingSystem() { handler := http.HandlerFunc(updateSystem) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) - assert.Equal(s.T(), http.StatusBadRequest, rr.Result().StatusCode) + assert.Equal(s.T(), http.StatusNotFound, rr.Result().StatusCode) assert.Contains(s.T(), rr.Body.String(), "failed to update system") } @@ -1363,7 +1363,7 @@ func (s *APITestSuite) TestCreateV2SystemTokenNonJson() { handler.ServeHTTP(rr, req) // TODO(BCDA-7212): Handle gracefully - assert.Equal(s.T(), http.StatusInternalServerError, rr.Result().StatusCode) + assert.Equal(s.T(), http.StatusBadRequest, rr.Result().StatusCode) } func (s *APITestSuite) TestCreateV2SystemTokenMissingLabel() { @@ -1504,7 +1504,7 @@ func (s *APITestSuite) TestCreatePublicKeyMissingFields() { handler.ServeHTTP(rr, req) // TODO(BCDA-7212): Handle gracefully - assert.Equal(s.T(), http.StatusInternalServerError, rr.Result().StatusCode) + assert.Equal(s.T(), http.StatusBadRequest, rr.Result().StatusCode) } func (s *APITestSuite) TestDeletePublicKeySystemNotFound() { diff --git a/ssas/service/admin/router_test.go b/ssas/service/admin/router_test.go index 2a8f8d9..5dec5c9 100644 --- a/ssas/service/admin/router_test.go +++ b/ssas/service/admin/router_test.go @@ -109,7 +109,7 @@ func (s *RouterTestSuite) TestDeleteGroup() { rr := httptest.NewRecorder() s.router.ServeHTTP(rr, req) res := rr.Result() - assert.Equal(s.T(), http.StatusBadRequest, res.StatusCode) + assert.Equal(s.T(), http.StatusNotFound, res.StatusCode) } func (s *RouterTestSuite) TestPostSystem() { diff --git a/ssas/service/main/main.go b/ssas/service/main/main.go index 2bb6503..e4d9432 100644 --- a/ssas/service/main/main.go +++ b/ssas/service/main/main.go @@ -5,13 +5,13 @@ For more details see our repository readme and Postman tests: - https://github.com/CMSgov/bcda-ssas-app - - https://github.com/CMSgov/bcda-ssas-app/tree/master/test/postman_test + - https://github.com/CMSgov/bcda-ssas-app/tree/main/test/postman_test If you have a Client ID and Secret you can use this page to explore the API. To do this, click the green "Authorize" button below and enter your Client ID and secret in the Basic Authentication username and password boxes. Until you click logout your token will be presented with every request made. To make requests click on the "Try it out" button for the desired endpoint. Version: 1.0.0 - License: Public Domain https://github.com/CMSgov/bcda-ssas-app/blob/master/LICENSE.md + License: Public Domain https://github.com/CMSgov/bcda-ssas-app/blob/main/LICENSE.md Contact: bcapi@cms.hhs.gov Produces: diff --git a/ssas/service/public/api_test.go b/ssas/service/public/api_test.go index 0111717..07839d3 100644 --- a/ssas/service/public/api_test.go +++ b/ssas/service/public/api_test.go @@ -1254,7 +1254,7 @@ func (s *APITestSuite) TestGetTokenInfo() { rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) assert.Equal(s.T(), http.StatusOK, rr.Result().StatusCode) - assert.Equal(s.T(), "application/json; charset=utf-8", rr.Result().Header.Get("Content-Type")) + assert.Contains(s.T(), rr.Result().Header.Get("Content-Type"), "application/json") var result map[string]interface{} _ = json.Unmarshal(rr.Body.Bytes(), &result) assert.NotEmpty(s.T(), result["data"]) diff --git a/ssas/service/server.go b/ssas/service/server.go index 9c3631e..793ddbe 100644 --- a/ssas/service/server.go +++ b/ssas/service/server.go @@ -58,7 +58,7 @@ func ChooseSigningKey(signingKeyPath, signingKey string) (*rsa.PrivateKey, error if err != nil { msg := fmt.Sprintf("bad signing key; path %s; %v", signingKeyPath, err) ssas.Logger.Error(msg) - error = fmt.Errorf(msg) + error = errors.New(msg) } key = sk } else if signingKey != "" && signingKeyPath == "" { @@ -66,17 +66,17 @@ func ChooseSigningKey(signingKeyPath, signingKey string) (*rsa.PrivateKey, error if err != nil { msg := fmt.Sprintf("bad inline signing key; %v", err) ssas.Logger.Error(msg) - error = fmt.Errorf(msg) + error = errors.New(msg) } key = sk } else if signingKey == "" && signingKeyPath == "" { msg := "inline key and path are both empty strings" ssas.Logger.Error(msg) - error = fmt.Errorf(msg) + error = errors.New(msg) } else { msg := "inline key or path must be set, but not both" ssas.Logger.Error(msg) - error = fmt.Errorf(msg) + error = errors.New(msg) } return key, error @@ -481,7 +481,7 @@ func (s *Server) CheckRequiredClaims(claims *CommonClaims, requiredTokenType str } if requiredTokenType != claims.TokenType { - return fmt.Errorf(fmt.Sprintf("wrong token type: %s; required type: %s", claims.TokenType, requiredTokenType)) + return fmt.Errorf("wrong token type: %s; required type: %s", claims.TokenType, requiredTokenType) } return nil } diff --git a/ssas/service/tokenblacklist.go b/ssas/service/tokenblacklist.go index 8ad700b..5b35de5 100644 --- a/ssas/service/tokenblacklist.go +++ b/ssas/service/tokenblacklist.go @@ -70,7 +70,7 @@ func (t *Blacklist) BlacklistToken(ctx context.Context, tokenID string, blacklis entryDate := time.Now() expirationDate := entryDate.Add(blacklistExpiration) if _, err := ssas.CreateBlacklistEntry(ctx, tokenID, entryDate, expirationDate); err != nil { - return fmt.Errorf(fmt.Sprintf("unable to blacklist token id %s: %s", tokenID, err.Error())) + return fmt.Errorf("unable to blacklist token id %s: %s", tokenID, err.Error()) } // Add to cache only after token is blacklisted in database diff --git a/ssas/systems.go b/ssas/systems.go index 5b37968..8d6e018 100644 --- a/ssas/systems.go +++ b/ssas/systems.go @@ -238,7 +238,7 @@ func (system *System) RevokeSecret(ctx context.Context, systemID string) error { err = system.deactivateSecrets(ctx) if err != nil { - return fmt.Errorf("unable to revoke credentials for clientID " + system.ClientID) + return fmt.Errorf("unable to revoke credentials for clientID %s", system.ClientID) } return nil } diff --git a/test/postman_test/SSAS.postman_collection.json b/test/postman_test/SSAS.postman_collection.json index 79618d7..e3e19ec 100644 --- a/test/postman_test/SSAS.postman_collection.json +++ b/test/postman_test/SSAS.postman_collection.json @@ -293,16 +293,16 @@ "response": [] }, { - "name": "admin delete group, 400", + "name": "admin delete group, 404", "event": [ { "listen": "test", "script": { "id": "95ce3470-8202-4e9f-b4f6-4fe36a09cb0d", "exec": [ - "pm.test(\"response is 400 and record not found\", function () {", - " pm.response.to.have.status(400);", - " pm.response.to.have.body('{\"error\":\"Bad Request\",\"error_description\":\"failed to delete group\"}',)", + "pm.test(\"response is 404 and not found\", function () {", + " pm.response.to.have.status(404);", + " pm.response.to.have.body('{\"error\":\"Not Found\",\"error_description\":\"failed to delete group\"}',)", "});" ], "type": "text/javascript" diff --git a/unit_test.sh b/unit_test.sh index 7d99de3..ce172f6 100755 --- a/unit_test.sh +++ b/unit_test.sh @@ -1,7 +1,7 @@ #!/bin/bash # # This script is intended to be run from within the Docker "unit_test" container -# The docker-compose file brings forward the env vars: DB +# The docker compose file brings forward the env vars: DB # set -e set -o pipefail