From d2e0ac07f12884c7a569ad07b9e5f48305792a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Fri, 6 Sep 2024 15:47:57 +0300 Subject: [PATCH] chore(tests): use a coverage server binary (#8407) # Which Problems Are Solved Use a single server instance for API integration tests. This optimizes the time taken for the integration test pipeline, because it allows running tests on multiple packages in parallel. Also, it saves time by not start and stopping a zitadel server for every package. # How the Problems Are Solved - Build a binary with `go build -race -cover ....` - Integration tests only construct clients. The server remains running in the background. - The integration package and tested packages now fully utilize the API. No more direct database access trough `query` and `command` packages. - Use Makefile recipes to setup, start and stop the server in the background. - The binary has the race detector enabled - Init and setup jobs are configured to halt immediately on race condition - Because the server runs in the background, races are only logged. When the server is stopped and race logs exist, the Makefile recipe will throw an error and print the logs. - Makefile recipes include logic to print logs and convert coverage reports after the server is stopped. - Some tests need a downstream HTTP server to make requests, like quota and milestones. A new `integration/sink` package creates an HTTP server and uses websockets to forward HTTP request back to the test packages. The package API uses Go channels for abstraction and easy usage. # Additional Changes - Integration test files already used the `//go:build integration` directive. In order to properly split integration from unit tests, integration test files need to be in a `integration_test` subdirectory of their package. - `UseIsolatedInstance` used to overwrite the `Tester.Client` for each instance. Now a `Instance` object is returned with a gRPC client that is connected to the isolated instance's hostname. - The `Tester` type is now `Instance`. The object is created for the first instance, used by default in any test. Isolated instances are also `Instance` objects and therefore benefit from the same methods and values. The first instance and any other us capable of creating an isolated instance over the system API. - All test packages run in an Isolated instance by calling `NewInstance()` - Individual tests that use an isolated instance use `t.Parallel()` # Additional Context - Closes #6684 - https://go.dev/doc/articles/race_detector - https://go.dev/doc/build-cover --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com> --- .github/workflows/build.yml | 16 +- ...ore-test.yml => core-integration-test.yml} | 7 +- .github/workflows/core-unit-test.yml | 76 +++ CONTRIBUTING.md | 46 +- Makefile | 59 ++- cmd/start/start.go | 5 + go.mod | 3 +- go.sum | 1 + .../iam_member_test.go} | 52 +- .../iam_settings_test.go} | 47 +- .../import_test.go} | 0 .../information_test.go} | 2 +- ...ns_allow_public_org_registrations_test.go} | 46 +- .../restrictions_allowed_languages_test.go} | 75 +-- .../server_test.go} | 19 +- .../feature_test.go} | 20 +- .../feature_test.go} | 228 +-------- internal/api/grpc/fields.go | 14 +- .../query_test.go} | 8 +- .../idp/v2/integration_test/server_test.go | 36 ++ .../grpc/idp/v2/server_integration_test.go | 40 -- .../org_test.go} | 44 +- .../server_test.go} | 12 +- .../user_test.go} | 10 +- .../oidc_test.go} | 51 +- .../oidc_test.go} | 51 +- .../org_test.go} | 31 +- .../query_test.go} | 76 +-- .../org_test.go} | 25 +- .../execution_target_test.go} | 67 +-- .../execution_test.go} | 108 +++-- .../query_test.go} | 142 +++--- .../v3alpha/integration_test/server_test.go | 70 +++ .../target_test.go} | 100 ++-- .../action/v3alpha/server_integration_test.go | 68 --- .../server_test.go} | 23 +- .../user_test.go} | 20 +- .../query_test.go} | 14 +- .../server_test.go} | 21 +- .../userschema_test.go} | 54 +-- .../webkey_integration_test.go | 80 ++-- internal/api/grpc/server/server.go | 1 + .../session_test.go} | 135 +++--- .../session_test.go} | 133 +++--- .../server_test.go} | 11 +- .../settings_test.go} | 35 +- .../server_test.go} | 11 +- .../settings_test.go} | 35 +- .../instance_test.go} | 15 +- .../limits_auditlogretention_test.go} | 96 ++-- .../limits_block_test.go} | 67 +-- .../limits_bulk_test.go} | 4 +- .../quotas_enabled/quota_test.go} | 82 ++-- .../quotas_enabled/server_test.go | 23 + .../system/integration_test/server_test.go | 24 + .../quotas_enabled/server_integration_test.go | 37 -- .../grpc/system/server_integration_test.go | 32 -- .../email_test.go} | 27 +- .../idp_link_test.go} | 73 +-- .../otp_test.go} | 115 +++-- .../passkey_test.go} | 41 +- .../password_test.go} | 23 +- .../phone_test.go} | 41 +- .../query_test.go} | 39 +- .../totp_test.go} | 63 ++- .../u2f_test.go} | 45 +- .../user_test.go} | 275 ++++++----- .../email_test.go} | 24 +- .../otp_test.go} | 96 ++-- .../passkey_test.go} | 28 +- .../password_test.go} | 20 +- .../phone_test.go} | 38 +- .../query_test.go} | 32 +- .../totp_test.go} | 71 +-- .../u2f_test.go} | 34 +- .../user_test.go} | 290 ++++++----- .../idp_test.go} | 42 +- .../auth_request_test.go} | 182 ++++--- .../client_test.go} | 62 +-- .../keys_test.go} | 30 +- .../oidc_test.go} | 165 +++---- .../server_test.go} | 6 +- .../token_client_credentials_test.go} | 32 +- .../token_exchange_test.go} | 42 +- .../token_jwt_profile_test.go} | 32 +- .../userinfo_test.go} | 73 ++- internal/api/oidc/server_test.go | 3 +- internal/command/org_idp_test.go | 2 +- internal/integration/assert.go | 12 +- internal/integration/client.go | 450 ++++++++---------- internal/integration/config.go | 53 +++ internal/integration/config/client.yaml | 10 + .../integration/config/docker-compose.yaml | 2 +- internal/integration/config/postgres.yaml | 6 +- internal/integration/config/steps.yaml | 13 + internal/integration/config/zitadel.yaml | 17 +- internal/integration/instance.go | 354 ++++++++++++++ internal/integration/integration.go | 449 ----------------- internal/integration/integration_test.go | 16 - internal/integration/oidc.go | 119 ++--- internal/integration/sink/channel.go | 9 + internal/integration/sink/channel_enumer.go | 78 +++ internal/integration/sink/server.go | 167 +++++++ internal/integration/sink/sink.go | 4 + internal/integration/sink/stub.go | 9 + internal/integration/sink/subscription.go | 90 ++++ internal/integration/system.go | 59 +++ internal/integration/user.go | 10 +- internal/integration/usertype_enumer.go | 86 ++++ internal/integration/usertype_string.go | 27 -- .../handlers/handlers_integration_test.go | 36 -- .../integration_test/handlers_test.go | 23 + .../telemetry_pusher_test.go} | 68 +-- .../handlers/quota_notifier_test.go | 155 ------ internal/webauthn/webauthn.go | 4 +- 115 files changed, 3632 insertions(+), 3348 deletions(-) rename .github/workflows/{core-test.yml => core-integration-test.yml} (95%) create mode 100644 .github/workflows/core-unit-test.yml rename internal/api/grpc/admin/{iam_member_integration_test.go => integration_test/iam_member_test.go} (82%) rename internal/api/grpc/admin/{iam_settings_integration_test.go => integration_test/iam_settings_test.go} (79%) rename internal/api/grpc/admin/{import_integration_test.go => integration_test/import_test.go} (100%) rename internal/api/grpc/admin/{information_integration_test.go => integration_test/information_test.go} (81%) rename internal/api/grpc/admin/{restrictions_integration_allow_public_org_registrations_test.go => integration_test/restrictions_allow_public_org_registrations_test.go} (64%) rename internal/api/grpc/admin/{restrictions_integration_allowed_languages_test.go => integration_test/restrictions_allowed_languages_test.go} (67%) rename internal/api/grpc/admin/{server_integration_test.go => integration_test/server_test.go} (70%) rename internal/api/grpc/feature/v2/{feature_integration_test.go => integration_test/feature_test.go} (96%) rename internal/api/grpc/feature/v2beta/{feature_integration_test.go => integration_test/feature_test.go} (56%) rename internal/api/grpc/idp/v2/{query_integration_test.go => integration_test/query_test.go} (96%) create mode 100644 internal/api/grpc/idp/v2/integration_test/server_test.go delete mode 100644 internal/api/grpc/idp/v2/server_integration_test.go rename internal/api/grpc/management/{org_integration_test.go => integration_test/org_test.go} (85%) rename internal/api/grpc/management/{server_integration_test.go => integration_test/server_test.go} (60%) rename internal/api/grpc/management/{user_integration_test.go => integration_test/user_test.go} (93%) rename internal/api/grpc/oidc/v2/{oidc_integration_test.go => integration_test/oidc_test.go} (73%) rename internal/api/grpc/oidc/v2beta/{oidc_integration_test.go => integration_test/oidc_test.go} (73%) rename internal/api/grpc/org/v2/{org_integration_test.go => integration_test/org_test.go} (85%) rename internal/api/grpc/org/v2/{query_integration_test.go => integration_test/query_test.go} (81%) rename internal/api/grpc/org/v2beta/{org_integration_test.go => integration_test/org_test.go} (89%) rename internal/api/grpc/resources/action/v3alpha/{execution_target_integration_test.go => integration_test/execution_target_test.go} (76%) rename internal/api/grpc/resources/action/v3alpha/{execution_integration_test.go => integration_test/execution_test.go} (85%) rename internal/api/grpc/resources/action/v3alpha/{query_integration_test.go => integration_test/query_test.go} (85%) create mode 100644 internal/api/grpc/resources/action/v3alpha/integration_test/server_test.go rename internal/api/grpc/resources/action/v3alpha/{target_integration_test.go => integration_test/target_test.go} (75%) delete mode 100644 internal/api/grpc/resources/action/v3alpha/server_integration_test.go rename internal/api/grpc/resources/user/v3alpha/{server_integration_test.go => integration_test/server_test.go} (63%) rename internal/api/grpc/resources/user/v3alpha/{user_integration_test.go => integration_test/user_test.go} (89%) rename internal/api/grpc/resources/userschema/v3alpha/{query_integration_test.go => integration_test/query_test.go} (93%) rename internal/api/grpc/resources/userschema/v3alpha/{server_integration_test.go => integration_test/server_test.go} (65%) rename internal/api/grpc/resources/userschema/v3alpha/{userschema_integration_test.go => integration_test/userschema_test.go} (91%) rename internal/api/grpc/resources/webkey/v3/{ => integration_test}/webkey_integration_test.go (71%) rename internal/api/grpc/session/v2/{session_integration_test.go => integration_test/session_test.go} (86%) rename internal/api/grpc/session/v2beta/{session_integration_test.go => integration_test/session_test.go} (86%) rename internal/api/grpc/settings/v2/{server_integration_test.go => integration_test/server_test.go} (59%) rename internal/api/grpc/settings/v2/{settings_integration_test.go => integration_test/settings_test.go} (78%) rename internal/api/grpc/settings/v2beta/{server_integration_test.go => integration_test/server_test.go} (59%) rename internal/api/grpc/settings/v2beta/{settings_integration_test.go => integration_test/settings_test.go} (78%) rename internal/api/grpc/system/{instance_integration_test.go => integration_test/instance_test.go} (87%) rename internal/api/grpc/system/{limits_integration_auditlogretention_test.go => integration_test/limits_auditlogretention_test.go} (57%) rename internal/api/grpc/system/{limits_integration_block_test.go => integration_test/limits_block_test.go} (79%) rename internal/api/grpc/system/{limits_integration_bulk_test.go => integration_test/limits_bulk_test.go} (95%) rename internal/api/grpc/system/{quotas_enabled/quota_integration_test.go => integration_test/quotas_enabled/quota_test.go} (61%) create mode 100644 internal/api/grpc/system/integration_test/quotas_enabled/server_test.go create mode 100644 internal/api/grpc/system/integration_test/server_test.go delete mode 100644 internal/api/grpc/system/quotas_enabled/server_integration_test.go delete mode 100644 internal/api/grpc/system/server_integration_test.go rename internal/api/grpc/user/v2/{email_integration_test.go => integration_test/email_test.go} (90%) rename internal/api/grpc/user/v2/{idp_link_integration_test.go => integration_test/idp_link_test.go} (67%) rename internal/api/grpc/user/v2/{otp_integration_test.go => integration_test/otp_test.go} (59%) rename internal/api/grpc/user/v2/{passkey_integration_test.go => integration_test/passkey_test.go} (92%) rename internal/api/grpc/user/v2/{password_integration_test.go => integration_test/password_test.go} (91%) rename internal/api/grpc/user/v2/{phone_integration_test.go => integration_test/phone_test.go} (87%) rename internal/api/grpc/user/v2/{query_integration_test.go => integration_test/query_test.go} (93%) rename internal/api/grpc/user/v2/{totp_integration_test.go => integration_test/totp_test.go} (72%) rename internal/api/grpc/user/v2/{u2f_integration_test.go => integration_test/u2f_test.go} (82%) rename internal/api/grpc/user/v2/{user_integration_test.go => integration_test/user_test.go} (88%) rename internal/api/grpc/user/v2beta/{email_integration_test.go => integration_test/email_test.go} (90%) rename internal/api/grpc/user/v2beta/{otp_integration_test.go => integration_test/otp_test.go} (66%) rename internal/api/grpc/user/v2beta/{passkey_integration_test.go => integration_test/passkey_test.go} (89%) rename internal/api/grpc/user/v2beta/{password_integration_test.go => integration_test/password_test.go} (91%) rename internal/api/grpc/user/v2beta/{phone_integration_test.go => integration_test/phone_test.go} (87%) rename internal/api/grpc/user/v2beta/{query_integration_test.go => integration_test/query_test.go} (94%) rename internal/api/grpc/user/v2beta/{totp_integration_test.go => integration_test/totp_test.go} (70%) rename internal/api/grpc/user/v2beta/{u2f_integration_test.go => integration_test/u2f_test.go} (76%) rename internal/api/grpc/user/v2beta/{user_integration_test.go => integration_test/user_test.go} (88%) rename internal/api/idp/{idp_integration_test.go => integration_test/idp_test.go} (90%) rename internal/api/oidc/{auth_request_integration_test.go => integration_test/auth_request_test.go} (68%) rename internal/api/oidc/{client_integration_test.go => integration_test/client_test.go} (81%) rename internal/api/oidc/{keys_integration_test.go => integration_test/keys_test.go} (66%) rename internal/api/oidc/{oidc_integration_test.go => integration_test/oidc_test.go} (59%) rename internal/api/oidc/{server_integration_test.go => integration_test/server_test.go} (92%) rename internal/api/oidc/{token_client_credentials_integration_test.go => integration_test/token_client_credentials_test.go} (80%) rename internal/api/oidc/{token_exchange_integration_test.go => integration_test/token_exchange_test.go} (91%) rename internal/api/oidc/{token_jwt_profile_integration_test.go => integration_test/token_jwt_profile_test.go} (76%) rename internal/api/oidc/{userinfo_integration_test.go => integration_test/userinfo_test.go} (82%) create mode 100644 internal/integration/config.go create mode 100644 internal/integration/config/client.yaml create mode 100644 internal/integration/config/steps.yaml create mode 100644 internal/integration/instance.go delete mode 100644 internal/integration/integration.go delete mode 100644 internal/integration/integration_test.go create mode 100644 internal/integration/sink/channel.go create mode 100644 internal/integration/sink/channel_enumer.go create mode 100644 internal/integration/sink/server.go create mode 100644 internal/integration/sink/sink.go create mode 100644 internal/integration/sink/stub.go create mode 100644 internal/integration/sink/subscription.go create mode 100644 internal/integration/system.go create mode 100644 internal/integration/usertype_enumer.go delete mode 100644 internal/integration/usertype_string.go delete mode 100644 internal/notification/handlers/handlers_integration_test.go create mode 100644 internal/notification/handlers/integration_test/handlers_test.go rename internal/notification/handlers/{telemetry_pusher_integration_test.go => integration_test/telemetry_pusher_test.go} (53%) delete mode 100644 internal/notification/handlers/quota_notifier_test.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8f673c2e8..ac7d909589 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,9 +50,19 @@ jobs: console_cache_path: ${{ needs.console.outputs.cache_path }} version: ${{ needs.version.outputs.version }} - core-test: + core-unit-test: needs: core - uses: ./.github/workflows/core-test.yml + uses: ./.github/workflows/core-unit-test.yml + with: + go_version: "1.22" + core_cache_key: ${{ needs.core.outputs.cache_key }} + core_cache_path: ${{ needs.core.outputs.cache_path }} + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + core-integration-test: + needs: core + uses: ./.github/workflows/core-integration-test.yml with: go_version: "1.22" core_cache_key: ${{ needs.core.outputs.cache_key }} @@ -93,7 +103,7 @@ jobs: issues: write pull-requests: write needs: - [version, core-test, lint, container, e2e] + [version, core-unit-test, core-integration-test, lint, container, e2e] if: ${{ github.event_name == 'workflow_dispatch' }} secrets: GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }} diff --git a/.github/workflows/core-test.yml b/.github/workflows/core-integration-test.yml similarity index 95% rename from .github/workflows/core-test.yml rename to .github/workflows/core-integration-test.yml index 4d8d978b60..b790db01d7 100644 --- a/.github/workflows/core-test.yml +++ b/.github/workflows/core-integration-test.yml @@ -18,11 +18,8 @@ on: jobs: postgres: - runs-on: ubuntu-latest - # TODO: use runner group as soon as integration tests run in parallel - # Currently it only consumes time and adds no value - # runs-on: - # group: zitadel-public + runs-on: + group: zitadel-public services: postgres: image: postgres diff --git a/.github/workflows/core-unit-test.yml b/.github/workflows/core-unit-test.yml new file mode 100644 index 0000000000..0b1467ff5d --- /dev/null +++ b/.github/workflows/core-unit-test.yml @@ -0,0 +1,76 @@ +name: Unit test core + +on: + workflow_call: + inputs: + go_version: + required: true + type: string + core_cache_key: + required: true + type: string + core_cache_path: + required: true + type: string + crdb_version: + required: false + type: string + secrets: + CODECOV_TOKEN: + required: true + +jobs: + test: + runs-on: + group: zitadel-public + steps: + - + uses: actions/checkout@v3 + - + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go_version }} + - + uses: actions/cache/restore@v4 + timeout-minutes: 1 + name: restore core + id: restore-core + with: + path: ${{ inputs.core_cache_path }} + key: ${{ inputs.core_cache_key }} + fail-on-cache-miss: true + - + id: go-cache-path + name: set cache path + run: echo "GO_CACHE_PATH=$(go env GOCACHE)" >> $GITHUB_OUTPUT + - + uses: actions/cache/restore@v4 + id: cache + timeout-minutes: 1 + continue-on-error: true + name: restore previous results + with: + key: unit-test-${{ inputs.core_cache_key }} + restore-keys: | + unit-test-core- + path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }} + - + name: test + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + run: make core_unit_test + - + name: publish coverage + uses: codecov/codecov-action@v4.3.0 + with: + file: profile.cov + name: core-unit-tests + flags: core-unit-tests + token: ${{ secrets.CODECOV_TOKEN }} + - + uses: actions/cache/save@v4 + name: cache results + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + with: + key: unit-test-${{ inputs.core_cache_key }} + path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }} + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d58908786..e56ca307d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -205,16 +205,50 @@ make core_unit_test #### Run Local Integration Tests -To test the database-connected gRPC API, run PostgreSQL and CockroachDB, set up a ZITADEL instance and run the tests including integration tests: +Integration tests are run as gRPC clients against a running ZITADEL server binary. +The server binary is typically [build with coverage enabled](https://go.dev/doc/build-cover). +It is also possible to run a ZITADEL sever in a debugger and run the integrations tests like that. In order to run the server, a database is required. + +The database flavor can **optionally** be set in the environment to `cockroach` or `postgres`. The default is `postgres`. ```bash -export INTEGRATION_DB_FLAVOR="cockroach" ZITADEL_MASTERKEY="MasterkeyNeedsToHave32Characters" -docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait ${INTEGRATION_DB_FLAVOR} -make core_integration_test -docker compose -f internal/integration/config/docker-compose.yaml down +export INTEGRATION_DB_FLAVOR="cockroach" ``` -Repeat the above with `INTEGRATION_DB_FLAVOR="postgres"`. +In order to prepare the local system, the following will bring up the database, builds a coverage binary, initializes the database and starts the sever. + +```bash +make core_integration_db_up core_integration_server_start +``` + +When this job is finished, you can run individual package integration test through your IDE or command-line. The actual integration test clients reside in the `integration_test` subdirectory of the package they aim to test. Integration test files use the `integration` build tag, in order to be excluded from regular unit tests. +Because of the server-client split, Go is usually unaware of changes in server code and tends to cache test results. Pas `-count 1` to disable test caching. + +Example command to run a single package integration test: + +```bash +go test -count 1 -tags integration ./internal/api/grpc/management/integration_test +``` + +To run all available integration tests: + +```bash +make core_integration_test_packages +``` + +When you change any ZITADEL server code, be sure to rebuild and restart the server before the next test run. + +```bash +make core_integration_server_stop core_integration_server_start +``` + +To cleanup after testing (deletes the database!): + +```bash +make core_integration_server_stop core_integration_db_down +``` + +The test binary has the race detector enabled. `core_core_integration_server_stop` checks for any race logs reported by Go and will print them along a `66` exit code when found. Note that the actual race condition may have happened anywhere during the server lifetime, including start, stop or serving gRPC requests during tests. #### Run Local End-to-End Tests diff --git a/Makefile b/Makefile index 8ef48623f6..56788e9f34 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,12 @@ VERSION ?= development-$(now) COMMIT_SHA ?= $(shell git rev-parse HEAD) ZITADEL_IMAGE ?= zitadel:local +GOCOVERDIR = tmp/coverage +INTEGRATION_DB_FLAVOR ?= postgres +ZITADEL_MASTERKEY ?= MasterkeyNeedsToHave32Characters + +export GOCOVERDIR INTEGRATION_DB_FLAVOR ZITADEL_MASTERKEY + .PHONY: compile compile: core_build console_build compile_pipeline @@ -99,25 +105,56 @@ clean: $(RM) -r .artifacts/grpc $(RM) $(gen_authopt_path) $(RM) $(gen_zitadel_path) + $(RM) -r tmp/ .PHONY: core_unit_test core_unit_test: - go test -race -coverprofile=profile.cov ./... + go test -race -coverprofile=profile.cov -coverpkg=./internal/... ./... + +.PHONY: core_integration_db_up +core_integration_db_up: + docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait $${INTEGRATION_DB_FLAVOR} + +.PHONY: core_integration_db_down +core_integration_db_down: + docker compose -f internal/integration/config/docker-compose.yaml down .PHONY: core_integration_setup core_integration_setup: - go build -o zitadel main.go - ./zitadel init --config internal/integration/config/zitadel.yaml --config internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml - ./zitadel setup --masterkeyFromEnv --init-projections --config internal/integration/config/zitadel.yaml --config internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml --steps internal/integration/config/zitadel.yaml --steps internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml - $(RM) zitadel + go build -cover -race -tags integration -o zitadel.test main.go + mkdir -p $${GOCOVERDIR} + GORACE="halt_on_error=1" ./zitadel.test init --config internal/integration/config/zitadel.yaml --config internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml + GORACE="halt_on_error=1" ./zitadel.test setup --masterkeyFromEnv --init-projections --config internal/integration/config/zitadel.yaml --config internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml --steps internal/integration/config/steps.yaml + +.PHONY: core_integration_server_start +core_integration_server_start: core_integration_setup + GORACE="log_path=tmp/race.log" \ + ./zitadel.test start --masterkeyFromEnv --config internal/integration/config/zitadel.yaml --config internal/integration/config/${INTEGRATION_DB_FLAVOR}.yaml \ + > tmp/zitadel.log 2>&1 \ + & printf $$! > tmp/zitadel.pid + +.PHONY: core_integration_test_packages +core_integration_test_packages: + go test -count 1 -tags integration -timeout 30m $$(go list -tags integration ./... | grep "integration_test") + +.PHONY: core_integration_server_stop +core_integration_server_stop: + pid=$$(cat tmp/zitadel.pid); \ + $(RM) tmp/zitadel.pid; \ + kill $$pid; \ + if [ -s tmp/race.log.$$pid ]; then \ + cat tmp/race.log.$$pid; \ + exit 66; \ + fi + +.PHONY: core_integration_reports +core_integration_reports: + go tool covdata textfmt -i=tmp/coverage -pkg=github.com/zitadel/zitadel/internal/...,github.com/zitadel/zitadel/cmd/... -o profile.cov + $(RM) -r tmp/coverage + cat tmp/zitadel.log .PHONY: core_integration_test -core_integration_test: core_integration_setup - go test -tags=integration -race -p 1 -coverprofile=profile.cov -coverpkg=./internal/...,./cmd/... ./... - -.PHONY: core_integration_test_fast -core_integration_test_fast: core_integration_setup - go test -tags=integration -p 1 ./... +core_integration_test: core_integration_server_start core_integration_test_packages core_integration_server_stop core_integration_reports .PHONY: console_lint console_lint: diff --git a/cmd/start/start.go b/cmd/start/start.go index 47bc33ca42..594e16776b 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -79,6 +79,7 @@ import ( new_es "github.com/zitadel/zitadel/internal/eventstore/v3" "github.com/zitadel/zitadel/internal/i18n" "github.com/zitadel/zitadel/internal/id" + "github.com/zitadel/zitadel/internal/integration/sink" "github.com/zitadel/zitadel/internal/logstore" "github.com/zitadel/zitadel/internal/logstore/emitters/access" "github.com/zitadel/zitadel/internal/logstore/emitters/execution" @@ -138,6 +139,10 @@ type Server struct { func startZitadel(ctx context.Context, config *Config, masterKey string, server chan<- *Server) error { showBasicInformation(config) + // sink Server is stubbed out in production builds, see function's godoc. + closeSink := sink.StartServer() + defer closeSink() + i18n.MustLoadSupportedLanguagesFromDir() queryDBClient, err := database.Connect(config.Database, false, dialect.DBPurposeQuery) diff --git a/go.mod b/go.mod index 61d1d711d1..0137251400 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.0.4 github.com/fatih/color v1.17.0 github.com/gabriel-vasile/mimetype v1.4.4 + github.com/go-chi/chi/v5 v5.1.0 github.com/go-jose/go-jose/v4 v4.0.4 github.com/go-ldap/ldap/v3 v3.4.8 github.com/go-webauthn/webauthn v0.10.2 @@ -30,6 +31,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/gorilla/schema v1.4.1 github.com/gorilla/securecookie v1.1.2 + github.com/gorilla/websocket v1.4.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 @@ -95,7 +97,6 @@ require ( github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.0 // indirect github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/crewjam/httperr v0.2.0 // indirect - github.com/go-chi/chi/v5 v5.1.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index 82ef92c3a7..de6c80d513 100644 --- a/go.sum +++ b/go.sum @@ -346,6 +346,7 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= diff --git a/internal/api/grpc/admin/iam_member_integration_test.go b/internal/api/grpc/admin/integration_test/iam_member_test.go similarity index 82% rename from internal/api/grpc/admin/iam_member_integration_test.go rename to internal/api/grpc/admin/integration_test/iam_member_test.go index 06a8acb914..c65ede3d26 100644 --- a/internal/api/grpc/admin/iam_member_integration_test.go +++ b/internal/api/grpc/admin/integration_test/iam_member_test.go @@ -5,6 +5,7 @@ package admin_test import ( "context" "testing" + "time" "github.com/brianvoe/gofakeit/v6" "github.com/stretchr/testify/assert" @@ -33,7 +34,7 @@ func TestServer_ListIAMMemberRoles(t *testing.T) { } func TestServer_ListIAMMembers(t *testing.T) { - user := Tester.CreateHumanUserVerified(AdminCTX, Tester.Organisation.ID, gofakeit.Email()) + user := Instance.CreateHumanUserVerified(AdminCTX, Instance.DefaultOrg.Id, gofakeit.Email()) _, err := Client.AddIAMMember(AdminCTX, &admin_pb.AddIAMMemberRequest{ UserId: user.GetUserId(), Roles: iamRoles, @@ -52,7 +53,7 @@ func TestServer_ListIAMMembers(t *testing.T) { { name: "permission error", args: args{ - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: Instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), req: &admin_pb.ListIAMMembersRequest{ Query: &object.ListQuery{}, Queries: []*member.SearchQuery{{ @@ -91,26 +92,29 @@ func TestServer_ListIAMMembers(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Client.ListIAMMembers(tt.args.ctx, tt.args.req) - if tt.wantErr { - assert.Error(t, err) - return - } - require.NoError(t, err) - wantResult := tt.want.GetResult() - gotResult := got.GetResult() + assert.EventuallyWithT(t, func(ct *assert.CollectT) { + got, err := Client.ListIAMMembers(tt.args.ctx, tt.args.req) + if tt.wantErr { + assert.Error(ct, err) + return + } + require.NoError(ct, err) + wantResult := tt.want.GetResult() + gotResult := got.GetResult() - require.Len(t, gotResult, len(wantResult)) - for i, want := range wantResult { - assert.Equal(t, want.GetUserId(), gotResult[i].GetUserId()) - assert.ElementsMatch(t, want.GetRoles(), gotResult[i].GetRoles()) - } + if assert.Len(ct, gotResult, len(wantResult)) { + for i, want := range wantResult { + assert.Equal(ct, want.GetUserId(), gotResult[i].GetUserId()) + assert.ElementsMatch(ct, want.GetRoles(), gotResult[i].GetRoles()) + } + } + }, time.Minute, time.Second) }) } } func TestServer_AddIAMMember(t *testing.T) { - user := Tester.CreateHumanUserVerified(AdminCTX, Tester.Organisation.ID, gofakeit.Email()) + user := Instance.CreateHumanUserVerified(AdminCTX, Instance.DefaultOrg.Id, gofakeit.Email()) type args struct { ctx context.Context req *admin_pb.AddIAMMemberRequest @@ -124,7 +128,7 @@ func TestServer_AddIAMMember(t *testing.T) { { name: "permission error", args: args{ - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: Instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), req: &admin_pb.AddIAMMemberRequest{ UserId: user.GetUserId(), Roles: iamRoles, @@ -143,7 +147,7 @@ func TestServer_AddIAMMember(t *testing.T) { }, want: &admin_pb.AddIAMMemberResponse{ Details: &object.ObjectDetails{ - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, }, }, @@ -184,7 +188,7 @@ func TestServer_AddIAMMember(t *testing.T) { } func TestServer_UpdateIAMMember(t *testing.T) { - user := Tester.CreateHumanUserVerified(AdminCTX, Tester.Organisation.ID, gofakeit.Email()) + user := Instance.CreateHumanUserVerified(AdminCTX, Instance.DefaultOrg.Id, gofakeit.Email()) _, err := Client.AddIAMMember(AdminCTX, &admin_pb.AddIAMMemberRequest{ UserId: user.GetUserId(), Roles: []string{"IAM_OWNER"}, @@ -204,7 +208,7 @@ func TestServer_UpdateIAMMember(t *testing.T) { { name: "permission error", args: args{ - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: Instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), req: &admin_pb.UpdateIAMMemberRequest{ UserId: user.GetUserId(), Roles: iamRoles, @@ -223,7 +227,7 @@ func TestServer_UpdateIAMMember(t *testing.T) { }, want: &admin_pb.UpdateIAMMemberResponse{ Details: &object.ObjectDetails{ - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), ChangeDate: timestamppb.Now(), }, }, @@ -265,7 +269,7 @@ func TestServer_UpdateIAMMember(t *testing.T) { } func TestServer_RemoveIAMMember(t *testing.T) { - user := Tester.CreateHumanUserVerified(AdminCTX, Tester.Organisation.ID, gofakeit.Email()) + user := Instance.CreateHumanUserVerified(AdminCTX, Instance.DefaultOrg.Id, gofakeit.Email()) _, err := Client.AddIAMMember(AdminCTX, &admin_pb.AddIAMMemberRequest{ UserId: user.GetUserId(), Roles: []string{"IAM_OWNER"}, @@ -285,7 +289,7 @@ func TestServer_RemoveIAMMember(t *testing.T) { { name: "permission error", args: args{ - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: Instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), req: &admin_pb.RemoveIAMMemberRequest{ UserId: user.GetUserId(), }, @@ -302,7 +306,7 @@ func TestServer_RemoveIAMMember(t *testing.T) { }, want: &admin_pb.RemoveIAMMemberResponse{ Details: &object.ObjectDetails{ - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), ChangeDate: timestamppb.Now(), }, }, diff --git a/internal/api/grpc/admin/iam_settings_integration_test.go b/internal/api/grpc/admin/integration_test/iam_settings_test.go similarity index 79% rename from internal/api/grpc/admin/iam_settings_integration_test.go rename to internal/api/grpc/admin/integration_test/iam_settings_test.go index 6d39abb747..2787f94755 100644 --- a/internal/api/grpc/admin/iam_settings_integration_test.go +++ b/internal/api/grpc/admin/integration_test/iam_settings_test.go @@ -17,21 +17,17 @@ import ( ) func TestServer_GetSecurityPolicy(t *testing.T) { - _, err := Client.SetSecurityPolicy(AdminCTX, &admin_pb.SetSecurityPolicyRequest{ + t.Parallel() + + instance := integration.NewInstance(CTX) + adminCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + + _, err := instance.Client.Admin.SetSecurityPolicy(adminCtx, &admin_pb.SetSecurityPolicyRequest{ EnableIframeEmbedding: true, AllowedOrigins: []string{"foo.com", "bar.com"}, EnableImpersonation: true, }) require.NoError(t, err) - t.Cleanup(func() { - _, err := Client.SetSecurityPolicy(AdminCTX, &admin_pb.SetSecurityPolicyRequest{ - EnableIframeEmbedding: false, - AllowedOrigins: []string{}, - EnableImpersonation: false, - }) - require.NoError(t, err) - }) - tests := []struct { name string ctx context.Context @@ -40,12 +36,12 @@ func TestServer_GetSecurityPolicy(t *testing.T) { }{ { name: "permission error", - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), wantErr: true, }, { name: "success", - ctx: AdminCTX, + ctx: adminCtx, want: &admin_pb.GetSecurityPolicyResponse{ Policy: &settings.SecurityPolicy{ EnableIframeEmbedding: true, @@ -57,7 +53,7 @@ func TestServer_GetSecurityPolicy(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - resp, err := Client.GetSecurityPolicy(tt.ctx, &admin_pb.GetSecurityPolicyRequest{}) + resp, err := instance.Client.Admin.GetSecurityPolicy(tt.ctx, &admin_pb.GetSecurityPolicyRequest{}) if tt.wantErr { assert.Error(t, err) return @@ -72,6 +68,11 @@ func TestServer_GetSecurityPolicy(t *testing.T) { } func TestServer_SetSecurityPolicy(t *testing.T) { + t.Parallel() + + instance := integration.NewInstance(CTX) + adminCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + type args struct { ctx context.Context req *admin_pb.SetSecurityPolicyRequest @@ -85,7 +86,7 @@ func TestServer_SetSecurityPolicy(t *testing.T) { { name: "permission error", args: args{ - ctx: Tester.WithAuthorization(CTX, integration.OrgOwner), + ctx: instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), req: &admin_pb.SetSecurityPolicyRequest{ EnableIframeEmbedding: true, AllowedOrigins: []string{"foo.com", "bar.com"}, @@ -97,7 +98,7 @@ func TestServer_SetSecurityPolicy(t *testing.T) { { name: "success allowed origins", args: args{ - ctx: AdminCTX, + ctx: adminCtx, req: &admin_pb.SetSecurityPolicyRequest{ AllowedOrigins: []string{"foo.com", "bar.com"}, }, @@ -105,14 +106,14 @@ func TestServer_SetSecurityPolicy(t *testing.T) { want: &admin_pb.SetSecurityPolicyResponse{ Details: &object.ObjectDetails{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: instance.ID(), }, }, }, { name: "success iframe embedding", args: args{ - ctx: AdminCTX, + ctx: adminCtx, req: &admin_pb.SetSecurityPolicyRequest{ EnableIframeEmbedding: true, }, @@ -120,14 +121,14 @@ func TestServer_SetSecurityPolicy(t *testing.T) { want: &admin_pb.SetSecurityPolicyResponse{ Details: &object.ObjectDetails{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: instance.ID(), }, }, }, { name: "success impersonation", args: args{ - ctx: AdminCTX, + ctx: adminCtx, req: &admin_pb.SetSecurityPolicyRequest{ EnableImpersonation: true, }, @@ -135,14 +136,14 @@ func TestServer_SetSecurityPolicy(t *testing.T) { want: &admin_pb.SetSecurityPolicyResponse{ Details: &object.ObjectDetails{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: instance.ID(), }, }, }, { name: "success all", args: args{ - ctx: AdminCTX, + ctx: adminCtx, req: &admin_pb.SetSecurityPolicyRequest{ EnableIframeEmbedding: true, AllowedOrigins: []string{"foo.com", "bar.com"}, @@ -152,14 +153,14 @@ func TestServer_SetSecurityPolicy(t *testing.T) { want: &admin_pb.SetSecurityPolicyResponse{ Details: &object.ObjectDetails{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: instance.ID(), }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Client.SetSecurityPolicy(tt.args.ctx, tt.args.req) + got, err := instance.Client.Admin.SetSecurityPolicy(tt.args.ctx, tt.args.req) if tt.wantErr { assert.Error(t, err) return diff --git a/internal/api/grpc/admin/import_integration_test.go b/internal/api/grpc/admin/integration_test/import_test.go similarity index 100% rename from internal/api/grpc/admin/import_integration_test.go rename to internal/api/grpc/admin/integration_test/import_test.go diff --git a/internal/api/grpc/admin/information_integration_test.go b/internal/api/grpc/admin/integration_test/information_test.go similarity index 81% rename from internal/api/grpc/admin/information_integration_test.go rename to internal/api/grpc/admin/integration_test/information_test.go index 7c324fc27a..9072bc80eb 100644 --- a/internal/api/grpc/admin/information_integration_test.go +++ b/internal/api/grpc/admin/integration_test/information_test.go @@ -15,6 +15,6 @@ import ( func TestServer_Healthz(t *testing.T) { ctx, cancel := context.WithTimeout(AdminCTX, time.Minute) defer cancel() - _, err := Tester.Client.Admin.Healthz(ctx, &admin.HealthzRequest{}) + _, err := Instance.Client.Admin.Healthz(ctx, &admin.HealthzRequest{}) require.NoError(t, err) } diff --git a/internal/api/grpc/admin/restrictions_integration_allow_public_org_registrations_test.go b/internal/api/grpc/admin/integration_test/restrictions_allow_public_org_registrations_test.go similarity index 64% rename from internal/api/grpc/admin/restrictions_integration_allow_public_org_registrations_test.go rename to internal/api/grpc/admin/integration_test/restrictions_allow_public_org_registrations_test.go index 5b29de19bb..3663fec4dd 100644 --- a/internal/api/grpc/admin/restrictions_integration_allow_public_org_registrations_test.go +++ b/internal/api/grpc/admin/integration_test/restrictions_allow_public_org_registrations_test.go @@ -10,20 +10,20 @@ import ( "net/http/cookiejar" "net/url" "testing" - "time" "github.com/muhlemmer/gu" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/admin" ) func TestServer_Restrictions_DisallowPublicOrgRegistration(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) - defer cancel() - domain, _, _, iamOwnerCtx := Tester.UseIsolatedInstance(t, ctx, SystemCTX) - regOrgUrl, err := url.Parse("http://" + domain + ":8080/ui/login/register/org") + t.Parallel() + + instance := integration.NewInstance(CTX) + regOrgUrl, err := url.Parse("http://" + instance.Domain + ":8080/ui/login/register/org") require.NoError(t, err) // The CSRF cookie must be sent with every request. // We can simulate a browser session using a cookie jar. @@ -31,36 +31,38 @@ func TestServer_Restrictions_DisallowPublicOrgRegistration(t *testing.T) { require.NoError(t, err) browserSession := &http.Client{Jar: jar} var csrfToken string - t.Run("public org registration is allowed by default", func(*testing.T) { - csrfToken = awaitPubOrgRegAllowed(t, iamOwnerCtx, browserSession, regOrgUrl) + iamOwnerCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + + t.Run("public org registration is allowed by default", func(tt *testing.T) { + csrfToken = awaitPubOrgRegAllowed(tt, iamOwnerCtx, instance.Client, browserSession, regOrgUrl) }) - t.Run("disallowing public org registration disables the endpoints", func(*testing.T) { - _, err = Tester.Client.Admin.SetRestrictions(iamOwnerCtx, &admin.SetRestrictionsRequest{DisallowPublicOrgRegistration: gu.Ptr(true)}) - require.NoError(t, err) - awaitPubOrgRegDisallowed(t, iamOwnerCtx, browserSession, regOrgUrl, csrfToken) + t.Run("disallowing public org registration disables the endpoints", func(tt *testing.T) { + _, err = instance.Client.Admin.SetRestrictions(iamOwnerCtx, &admin.SetRestrictionsRequest{DisallowPublicOrgRegistration: gu.Ptr(true)}) + require.NoError(tt, err) + awaitPubOrgRegDisallowed(tt, iamOwnerCtx, instance.Client, browserSession, regOrgUrl, csrfToken) }) - t.Run("allowing public org registration again re-enables the endpoints", func(*testing.T) { - _, err = Tester.Client.Admin.SetRestrictions(iamOwnerCtx, &admin.SetRestrictionsRequest{DisallowPublicOrgRegistration: gu.Ptr(false)}) - require.NoError(t, err) - awaitPubOrgRegAllowed(t, iamOwnerCtx, browserSession, regOrgUrl) + t.Run("allowing public org registration again re-enables the endpoints", func(tt *testing.T) { + _, err = instance.Client.Admin.SetRestrictions(iamOwnerCtx, &admin.SetRestrictionsRequest{DisallowPublicOrgRegistration: gu.Ptr(false)}) + require.NoError(tt, err) + awaitPubOrgRegAllowed(tt, iamOwnerCtx, instance.Client, browserSession, regOrgUrl) }) } // awaitPubOrgRegAllowed doesn't accept a CSRF token, as we expected it to always produce a new one -func awaitPubOrgRegAllowed(t *testing.T, ctx context.Context, client *http.Client, parsedURL *url.URL) string { +func awaitPubOrgRegAllowed(t *testing.T, ctx context.Context, cc *integration.Client, client *http.Client, parsedURL *url.URL) string { csrfToken := awaitGetSSRGetResponse(t, ctx, client, parsedURL, http.StatusOK) awaitPostFormResponse(t, ctx, client, parsedURL, http.StatusOK, csrfToken) - restrictions, err := Tester.Client.Admin.GetRestrictions(ctx, &admin.GetRestrictionsRequest{}) + restrictions, err := cc.Admin.GetRestrictions(ctx, &admin.GetRestrictionsRequest{}) require.NoError(t, err) require.False(t, restrictions.DisallowPublicOrgRegistration) return csrfToken } // awaitPubOrgRegDisallowed accepts an old CSRF token, as we don't expect to get a CSRF token from the GET request anymore -func awaitPubOrgRegDisallowed(t *testing.T, ctx context.Context, client *http.Client, parsedURL *url.URL, reuseOldCSRFToken string) { +func awaitPubOrgRegDisallowed(t *testing.T, ctx context.Context, cc *integration.Client, client *http.Client, parsedURL *url.URL, reuseOldCSRFToken string) { awaitGetSSRGetResponse(t, ctx, client, parsedURL, http.StatusNotFound) awaitPostFormResponse(t, ctx, client, parsedURL, http.StatusConflict, reuseOldCSRFToken) - restrictions, err := Tester.Client.Admin.GetRestrictions(ctx, &admin.GetRestrictionsRequest{}) + restrictions, err := cc.Admin.GetRestrictions(ctx, &admin.GetRestrictionsRequest{}) require.NoError(t, err) require.True(t, restrictions.DisallowPublicOrgRegistration) } @@ -70,9 +72,9 @@ func awaitGetSSRGetResponse(t *testing.T, ctx context.Context, client *http.Clie var csrfToken []byte await(t, ctx, func(tt *assert.CollectT) { resp, err := client.Get(parsedURL.String()) - require.NoError(t, err) + require.NoError(tt, err) body, err := io.ReadAll(resp.Body) - require.NoError(t, err) + require.NoError(tt, err) searchField := ` 0", assert.Greater, zeroCounts) }, "wait for seeded event assertions to pass") - produceEvents(iamOwnerCtx, t, userID, appID, projectID, projectGrantID) - addedCount := requireEventually(t, iamOwnerCtx, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { + produceEvents(iamOwnerCtx, t, isoInstance.Client, userID, appID, projectID, projectGrantID) + addedCount := requireEventually(t, iamOwnerCtx, isoInstance.Client, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { counts.assertAll(t, c, "added events are > seeded events", assert.Greater, seededCount) }, "wait for added event assertions to pass") - _, err := Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{ - InstanceId: instanceID, + _, err := integration.SystemClient().SetLimits(CTX, &system.SetLimitsRequest{ + InstanceId: isoInstance.ID(), AuditLogRetention: durationpb.New(time.Now().Sub(beforeTime)), }) require.NoError(t, err) var limitedCounts *eventCounts - requireEventually(t, iamOwnerCtx, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { + requireEventually(t, iamOwnerCtx, isoInstance.Client, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { counts.assertAll(t, c, "limited events < added events", assert.Less, addedCount) counts.assertAll(t, c, "limited events > 0", assert.Greater, zeroCounts) limitedCounts = counts }, "wait for limited event assertions to pass") - listedEvents, err := Tester.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_From{ + listedEvents, err := isoInstance.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_From{ From: farPast, }}) require.NoError(t, err) assert.LessOrEqual(t, len(listedEvents.GetEvents()), limitedCounts.all, "ListEvents with from query older than retention doesn't return more events") - listedEvents, err = Tester.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_Range{Range: &admin.ListEventsRequestCreationDateRange{ + listedEvents, err = isoInstance.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_Range{Range: &admin.ListEventsRequestCreationDateRange{ Since: farPast, }}}) require.NoError(t, err) assert.LessOrEqual(t, len(listedEvents.GetEvents()), limitedCounts.all, "ListEvents with since query older than retention doesn't return more events") - _, err = Tester.Client.System.ResetLimits(SystemCTX, &system.ResetLimitsRequest{ - InstanceId: instanceID, + _, err = integration.SystemClient().ResetLimits(CTX, &system.ResetLimitsRequest{ + InstanceId: isoInstance.ID(), }) require.NoError(t, err) - requireEventually(t, iamOwnerCtx, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { + requireEventually(t, iamOwnerCtx, isoInstance.Client, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) { counts.assertAll(t, c, "with reset limit, added events are > seeded events", assert.Greater, seededCount) }, "wait for reset event assertions to pass") } @@ -66,6 +70,7 @@ func TestServer_Limits_AuditLogRetention(t *testing.T) { func requireEventually( t *testing.T, ctx context.Context, + cc *integration.Client, userID, projectID, appID, projectGrantID string, assertCounts func(assert.TestingT, *eventCounts), msg string, @@ -75,7 +80,7 @@ func requireEventually( countCtx, cancel := context.WithTimeout(ctx, countTimeout) defer cancel() require.EventuallyWithT(t, func(c *assert.CollectT) { - counts = countEvents(countCtx, t, userID, projectID, appID, projectGrantID) + counts = countEvents(countCtx, c, cc, userID, projectID, appID, projectGrantID) assertCounts(c, counts) }, assertTimeout, time.Second, msg) return counts @@ -91,68 +96,68 @@ func randomString(resourceType string, n int) string { return "test" + resourceType + "-" + string(b) } -func seedObjects(ctx context.Context, t *testing.T) (string, string, string, string) { +func seedObjects(ctx context.Context, t *testing.T, cc *integration.Client) (string, string, string, string) { t.Helper() - project, err := Tester.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ + project, err := cc.Mgmt.AddProject(ctx, &management.AddProjectRequest{ Name: randomString("project", 5), }) require.NoError(t, err) - app, err := Tester.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ + app, err := cc.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ Name: randomString("app", 5), ProjectId: project.GetId(), }) - org, err := Tester.Client.Mgmt.AddOrg(ctx, &management.AddOrgRequest{ + org, err := cc.Mgmt.AddOrg(ctx, &management.AddOrgRequest{ Name: randomString("org", 5), }) require.NoError(t, err) role := randomString("role", 5) require.NoError(t, err) - _, err = Tester.Client.Mgmt.AddProjectRole(ctx, &management.AddProjectRoleRequest{ + _, err = cc.Mgmt.AddProjectRole(ctx, &management.AddProjectRoleRequest{ ProjectId: project.GetId(), RoleKey: role, DisplayName: role, }) require.NoError(t, err) - projectGrant, err := Tester.Client.Mgmt.AddProjectGrant(ctx, &management.AddProjectGrantRequest{ + projectGrant, err := cc.Mgmt.AddProjectGrant(ctx, &management.AddProjectGrantRequest{ ProjectId: project.GetId(), GrantedOrgId: org.GetId(), RoleKeys: []string{role}, }) require.NoError(t, err) - user, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + user, err := cc.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) userID := user.GetUser().GetId() - requireUserEvent(ctx, t, userID) + requireUserEvent(ctx, t, cc, userID) return userID, project.GetId(), app.GetAppId(), projectGrant.GetGrantId() } -func produceEvents(ctx context.Context, t *testing.T, machineID, appID, projectID, grantID string) { +func produceEvents(ctx context.Context, t *testing.T, cc *integration.Client, machineID, appID, projectID, grantID string) { t.Helper() - _, err := Tester.Client.Mgmt.UpdateOrg(ctx, &management.UpdateOrgRequest{ + _, err := cc.Mgmt.UpdateOrg(ctx, &management.UpdateOrgRequest{ Name: randomString("org", 5), }) require.NoError(t, err) - _, err = Tester.Client.Mgmt.UpdateProject(ctx, &management.UpdateProjectRequest{ + _, err = cc.Mgmt.UpdateProject(ctx, &management.UpdateProjectRequest{ Id: projectID, Name: randomString("project", 5), }) require.NoError(t, err) - _, err = Tester.Client.Mgmt.UpdateApp(ctx, &management.UpdateAppRequest{ + _, err = cc.Mgmt.UpdateApp(ctx, &management.UpdateAppRequest{ AppId: appID, ProjectId: projectID, Name: randomString("app", 5), }) require.NoError(t, err) - requireUserEvent(ctx, t, machineID) - _, err = Tester.Client.Mgmt.UpdateProjectGrant(ctx, &management.UpdateProjectGrantRequest{ + requireUserEvent(ctx, t, cc, machineID) + _, err = cc.Mgmt.UpdateProjectGrant(ctx, &management.UpdateProjectGrantRequest{ ProjectId: projectID, GrantId: grantID, }) require.NoError(t, err) } -func requireUserEvent(ctx context.Context, t *testing.T, machineID string) { - _, err := Tester.Client.Mgmt.UpdateMachine(ctx, &management.UpdateMachineRequest{ +func requireUserEvent(ctx context.Context, t *testing.T, cc *integration.Client, machineID string) { + _, err := cc.Mgmt.UpdateMachine(ctx, &management.UpdateMachineRequest{ UserId: machineID, Name: randomString("machine", 5), }) @@ -175,51 +180,50 @@ func (e *eventCounts) assertAll(t *testing.T, c assert.TestingT, name string, co }) } -func countEvents(ctx context.Context, t *testing.T, userID, projectID, appID, grantID string) *eventCounts { - t.Helper() +func countEvents(ctx context.Context, t assert.TestingT, cc *integration.Client, userID, projectID, appID, grantID string) *eventCounts { counts := new(eventCounts) var wg sync.WaitGroup wg.Add(7) go func() { defer wg.Done() - result, err := Tester.Client.Admin.ListEvents(ctx, &admin.ListEventsRequest{}) - require.NoError(t, err) + result, err := cc.Admin.ListEvents(ctx, &admin.ListEventsRequest{}) + assert.NoError(t, err) counts.all = len(result.GetEvents()) }() go func() { defer wg.Done() - result, err := Tester.Client.Auth.ListMyUserChanges(ctx, &auth.ListMyUserChangesRequest{}) - require.NoError(t, err) + result, err := cc.Auth.ListMyUserChanges(ctx, &auth.ListMyUserChangesRequest{}) + assert.NoError(t, err) counts.myUser = len(result.GetResult()) }() go func() { defer wg.Done() - result, err := Tester.Client.Mgmt.ListUserChanges(ctx, &management.ListUserChangesRequest{UserId: userID}) - require.NoError(t, err) + result, err := cc.Mgmt.ListUserChanges(ctx, &management.ListUserChangesRequest{UserId: userID}) + assert.NoError(t, err) counts.aUser = len(result.GetResult()) }() go func() { defer wg.Done() - result, err := Tester.Client.Mgmt.ListAppChanges(ctx, &management.ListAppChangesRequest{ProjectId: projectID, AppId: appID}) - require.NoError(t, err) + result, err := cc.Mgmt.ListAppChanges(ctx, &management.ListAppChangesRequest{ProjectId: projectID, AppId: appID}) + assert.NoError(t, err) counts.app = len(result.GetResult()) }() go func() { defer wg.Done() - result, err := Tester.Client.Mgmt.ListOrgChanges(ctx, &management.ListOrgChangesRequest{}) - require.NoError(t, err) + result, err := cc.Mgmt.ListOrgChanges(ctx, &management.ListOrgChangesRequest{}) + assert.NoError(t, err) counts.org = len(result.GetResult()) }() go func() { defer wg.Done() - result, err := Tester.Client.Mgmt.ListProjectChanges(ctx, &management.ListProjectChangesRequest{ProjectId: projectID}) - require.NoError(t, err) + result, err := cc.Mgmt.ListProjectChanges(ctx, &management.ListProjectChangesRequest{ProjectId: projectID}) + assert.NoError(t, err) counts.project = len(result.GetResult()) }() go func() { defer wg.Done() - result, err := Tester.Client.Mgmt.ListProjectGrantChanges(ctx, &management.ListProjectGrantChangesRequest{ProjectId: projectID, GrantId: grantID}) - require.NoError(t, err) + result, err := cc.Mgmt.ListProjectGrantChanges(ctx, &management.ListProjectGrantChangesRequest{ProjectId: projectID, GrantId: grantID}) + assert.NoError(t, err) counts.grant = len(result.GetResult()) }() wg.Wait() diff --git a/internal/api/grpc/system/limits_integration_block_test.go b/internal/api/grpc/system/integration_test/limits_block_test.go similarity index 79% rename from internal/api/grpc/system/limits_integration_block_test.go rename to internal/api/grpc/system/integration_test/limits_block_test.go index 68426dd05e..b8d17a1167 100644 --- a/internal/api/grpc/system/limits_integration_block_test.go +++ b/internal/api/grpc/system/integration_test/limits_block_test.go @@ -20,41 +20,35 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/durationpb" - "github.com/zitadel/zitadel/internal/api/authz" - "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/admin" "github.com/zitadel/zitadel/pkg/grpc/system" ) func TestServer_Limits_Block(t *testing.T) { - domain, instanceID, _, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX) + t.Parallel() + + isoInstance := integration.NewInstance(CTX) + iamOwnerCtx := isoInstance.WithAuthorization(CTX, integration.UserTypeIAMOwner) tests := []*test{ - publicAPIBlockingTest(domain), + publicAPIBlockingTest(isoInstance.Domain), { name: "mutating API", testGrpc: func(tt assert.TestingT, expectBlocked bool) { randomGrpcIdpName := randomString("idp-grpc", 5) - _, err := Tester.Client.Admin.AddGitHubProvider(iamOwnerCtx, &admin.AddGitHubProviderRequest{ + _, err := isoInstance.Client.Admin.AddGitHubProvider(iamOwnerCtx, &admin.AddGitHubProviderRequest{ Name: randomGrpcIdpName, ClientId: "client-id", ClientSecret: "client-secret", }) assertGrpcError(tt, err, expectBlocked) - //nolint:contextcheck - idpExists := idpExistsCondition(tt, instanceID, randomGrpcIdpName) - if expectBlocked { - // We ensure that the idp really is not created - assert.Neverf(tt, idpExists, 5*time.Second, 1*time.Second, "idp should never be created") - } else { - assert.Eventuallyf(tt, idpExists, 5*time.Second, 1*time.Second, "idp should be created") - } }, testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) { randomHttpIdpName := randomString("idp-http", 5) req, err := http.NewRequestWithContext( CTX, "POST", - fmt.Sprintf("http://%s/admin/v1/idps/github", net.JoinHostPort(domain, "8080")), + fmt.Sprintf("http://%s/admin/v1/idps/github", net.JoinHostPort(isoInstance.Domain, "8080")), strings.NewReader(`{ "name": "`+randomHttpIdpName+`", "clientId": "client-id", @@ -64,7 +58,7 @@ func TestServer_Limits_Block(t *testing.T) { if err != nil { return nil, err, nil } - req.Header.Set("Authorization", Tester.BearerToken(iamOwnerCtx)) + req.Header.Set("Authorization", isoInstance.BearerToken(iamOwnerCtx)) return req, nil, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) { assertLimitResponse(ttt, response, expectBlocked) assertSetLimitingCookie(ttt, response, expectBlocked) @@ -76,7 +70,7 @@ func TestServer_Limits_Block(t *testing.T) { req, err := http.NewRequestWithContext( CTX, "GET", - fmt.Sprintf("http://%s/.well-known/openid-configuration", net.JoinHostPort(domain, "8080")), + fmt.Sprintf("http://%s/.well-known/openid-configuration", net.JoinHostPort(isoInstance.Domain, "8080")), nil, ) return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) { @@ -90,7 +84,7 @@ func TestServer_Limits_Block(t *testing.T) { req, err := http.NewRequestWithContext( CTX, "GET", - fmt.Sprintf("http://%s/ui/login/login/externalidp/callback", net.JoinHostPort(domain, "8080")), + fmt.Sprintf("http://%s/ui/login/login/externalidp/callback", net.JoinHostPort(isoInstance.Domain, "8080")), nil, ) return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) { @@ -109,7 +103,7 @@ func TestServer_Limits_Block(t *testing.T) { req, err := http.NewRequestWithContext( CTX, "GET", - fmt.Sprintf("http://%s/ui/console/", net.JoinHostPort(domain, "8080")), + fmt.Sprintf("http://%s/ui/console/", net.JoinHostPort(isoInstance.Domain, "8080")), nil, ) return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) { @@ -125,7 +119,7 @@ func TestServer_Limits_Block(t *testing.T) { req, err := http.NewRequestWithContext( CTX, "GET", - fmt.Sprintf("http://%s/ui/console/assets/environment.json", net.JoinHostPort(domain, "8080")), + fmt.Sprintf("http://%s/ui/console/assets/environment.json", net.JoinHostPort(isoInstance.Domain, "8080")), nil, ) return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) { @@ -142,14 +136,14 @@ func TestServer_Limits_Block(t *testing.T) { } }, }} - _, err := Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{ - InstanceId: instanceID, + _, err := integration.SystemClient().SetLimits(CTX, &system.SetLimitsRequest{ + InstanceId: isoInstance.ID(), Block: gu.Ptr(true), }) require.NoError(t, err) // The following call ensures that an undefined bool is not deserialized to false - _, err = Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{ - InstanceId: instanceID, + _, err = integration.SystemClient().SetLimits(CTX, &system.SetLimitsRequest{ + InstanceId: isoInstance.ID(), AuditLogRetention: durationpb.New(time.Hour), }) require.NoError(t, err) @@ -160,8 +154,8 @@ func TestServer_Limits_Block(t *testing.T) { testBlockingAPI(t, tt, true, isFirst) }) } - _, err = Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{ - InstanceId: instanceID, + _, err = integration.SystemClient().SetLimits(CTX, &system.SetLimitsRequest{ + InstanceId: isoInstance.ID(), Block: gu.Ptr(false), }) require.NoError(t, err) @@ -183,7 +177,7 @@ type test struct { func testBlockingAPI(t *testing.T, tt *test, expectBlocked bool, isFirst bool) { req, err, assertResponse := tt.testHttp(t) require.NoError(t, err) - testHTTP := func(tt assert.TestingT) { + testHTTP := func(t require.TestingT) { resp, err := (&http.Client{ // Don't follow redirects CheckRedirect: func(req *http.Request, via []*http.Request) error { @@ -200,7 +194,7 @@ func testBlockingAPI(t *testing.T, tt *test, expectBlocked bool, isFirst bool) { // limits are eventually consistent, so we need to wait for the blocking to be set on the first test assert.EventuallyWithT(t, func(c *assert.CollectT) { testHTTP(c) - }, 15*time.Second, time.Second, "wait for blocking to be set") + }, time.Minute, time.Second, "wait for blocking to be set") } else { testHTTP(t) } @@ -249,7 +243,7 @@ func assertSetLimitingCookie(t assert.TestingT, response *http.Response, expectS return } } - assert.FailNow(t, "cookie not found") + assert.Fail(t, "cookie not found") } func assertGrpcError(t assert.TestingT, err error, expectBlocked bool) { @@ -268,20 +262,3 @@ func assertLimitResponse(t assert.TestingT, response *http.Response, expectBlock assert.GreaterOrEqual(t, response.StatusCode, 200) assert.Less(t, response.StatusCode, 300) } - -func idpExistsCondition(t assert.TestingT, instanceID, idpName string) func() bool { - return func() bool { - nameQuery, err := query.NewIDPTemplateNameSearchQuery(query.TextEquals, idpName) - assert.NoError(t, err) - instanceQuery, err := query.NewIDPTemplateResourceOwnerSearchQuery(instanceID) - assert.NoError(t, err) - idps, err := Tester.Queries.IDPTemplates(authz.WithInstanceID(CTX, instanceID), &query.IDPTemplateSearchQueries{ - Queries: []query.SearchQuery{ - instanceQuery, - nameQuery, - }, - }, false) - assert.NoError(t, err) - return len(idps.Templates) > 0 - } -} diff --git a/internal/api/grpc/system/limits_integration_bulk_test.go b/internal/api/grpc/system/integration_test/limits_bulk_test.go similarity index 95% rename from internal/api/grpc/system/limits_integration_bulk_test.go rename to internal/api/grpc/system/integration_test/limits_bulk_test.go index 0cdb37f5c3..b81c5c68ff 100644 --- a/internal/api/grpc/system/limits_integration_bulk_test.go +++ b/internal/api/grpc/system/integration_test/limits_bulk_test.go @@ -18,7 +18,7 @@ func TestServer_Limits_Bulk(t *testing.T) { instances := make([]*instance, len) for i := 0; i < len; i++ { domain := integration.RandString(5) + ".integration.localhost" - resp, err := Tester.Client.System.CreateInstance(SystemCTX, &system.CreateInstanceRequest{ + resp, err := integration.SystemClient().CreateInstance(CTX, &system.CreateInstanceRequest{ InstanceName: "testinstance", CustomDomain: domain, Owner: &system.CreateInstanceRequest_Machine_{ @@ -31,7 +31,7 @@ func TestServer_Limits_Bulk(t *testing.T) { require.NoError(t, err) instances[i] = &instance{domain, resp.GetInstanceId()} } - resp, err := Tester.Client.System.BulkSetLimits(SystemCTX, &system.BulkSetLimitsRequest{ + resp, err := integration.SystemClient().BulkSetLimits(CTX, &system.BulkSetLimitsRequest{ Limits: []*system.SetLimitsRequest{{ InstanceId: instances[0].id, Block: gu.Ptr(true), diff --git a/internal/api/grpc/system/quotas_enabled/quota_integration_test.go b/internal/api/grpc/system/integration_test/quotas_enabled/quota_test.go similarity index 61% rename from internal/api/grpc/system/quotas_enabled/quota_integration_test.go rename to internal/api/grpc/system/integration_test/quotas_enabled/quota_test.go index 225b4a2daa..09c42eeb97 100644 --- a/internal/api/grpc/system/quotas_enabled/quota_integration_test.go +++ b/internal/api/grpc/system/integration_test/quotas_enabled/quota_test.go @@ -14,21 +14,25 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/zitadel/zitadel/internal/integration" + "github.com/zitadel/zitadel/internal/integration/sink" "github.com/zitadel/zitadel/internal/repository/quota" "github.com/zitadel/zitadel/pkg/grpc/admin" quota_pb "github.com/zitadel/zitadel/pkg/grpc/quota" "github.com/zitadel/zitadel/pkg/grpc/system" ) -var callURL = "http://localhost:" + integration.PortQuotaServer +var callURL = sink.CallURL(sink.ChannelQuota) func TestServer_QuotaNotification_Limit(t *testing.T) { + instance := integration.NewInstance(CTX) + iamCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + amount := 10 percent := 50 percentAmount := amount * percent / 100 - _, err := Tester.Client.System.SetQuota(SystemCTX, &system.SetQuotaRequest{ - InstanceId: Tester.Instance.InstanceID(), + _, err := integration.SystemClient().SetQuota(CTX, &system.SetQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, From: timestamppb.Now(), ResetInterval: durationpb.New(time.Minute * 5), @@ -49,30 +53,35 @@ func TestServer_QuotaNotification_Limit(t *testing.T) { }) require.NoError(t, err) + sub := sink.Subscribe(CTX, sink.ChannelQuota) + defer sub.Close() + for i := 0; i < percentAmount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, err := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount) } - awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent) + awaitNotification(t, sub, quota.RequestsAllAuthenticated, percent) for i := 0; i < (amount - percentAmount); i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, err := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount) } - awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100) + awaitNotification(t, sub, quota.RequestsAllAuthenticated, 100) - _, limitErr := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, limitErr := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.Error(t, limitErr) } func TestServer_QuotaNotification_NoLimit(t *testing.T) { - _, instanceID, _, IAMOwnerCTX := Tester.UseIsolatedInstance(t, CTX, SystemCTX) + instance := integration.NewInstance(CTX) + iamCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + amount := 10 percent := 50 percentAmount := amount * percent / 100 - _, err := Tester.Client.System.SetQuota(SystemCTX, &system.SetQuotaRequest{ - InstanceId: instanceID, + _, err := integration.SystemClient().SetQuota(CTX, &system.SetQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, From: timestamppb.Now(), ResetInterval: durationpb.New(time.Minute * 5), @@ -93,34 +102,39 @@ func TestServer_QuotaNotification_NoLimit(t *testing.T) { }) require.NoError(t, err) + sub := sink.Subscribe(CTX, sink.ChannelQuota) + defer sub.Close() + for i := 0; i < percentAmount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, err := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount) } - awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent) + awaitNotification(t, sub, quota.RequestsAllAuthenticated, percent) for i := 0; i < (amount - percentAmount); i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, err := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount) } - awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100) + awaitNotification(t, sub, quota.RequestsAllAuthenticated, 100) for i := 0; i < amount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, err := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount) } - awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 200) + awaitNotification(t, sub, quota.RequestsAllAuthenticated, 200) - _, limitErr := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{}) + _, limitErr := instance.Client.Admin.GetDefaultOrg(iamCTX, &admin.GetDefaultOrgRequest{}) require.NoError(t, limitErr) } -func awaitNotification(t *testing.T, bodies chan []byte, unit quota.Unit, percent int) { +func awaitNotification(t *testing.T, sub *sink.Subscription, unit quota.Unit, percent int) { for { select { - case body := <-bodies: + case req, ok := <-sub.Recv(): + require.True(t, ok, "channel closed") + plain := new(bytes.Buffer) - if err := json.Indent(plain, body, "", " "); err != nil { + if err := json.Indent(plain, req.Body, "", " "); err != nil { t.Fatal(err) } t.Log("received notificationDueEvent", plain.String()) @@ -132,7 +146,7 @@ func awaitNotification(t *testing.T, bodies chan []byte, unit quota.Unit, percen Threshold uint16 `json:"threshold"` Usage uint64 `json:"usage"` }{} - if err := json.Unmarshal(body, &event); err != nil { + if err := json.Unmarshal(req.Body, &event); err != nil { t.Error(err) } if event.ID == "" { @@ -148,10 +162,10 @@ func awaitNotification(t *testing.T, bodies chan []byte, unit quota.Unit, percen } func TestServer_AddAndRemoveQuota(t *testing.T) { - _, instanceID, _, _ := Tester.UseIsolatedInstance(t, CTX, SystemCTX) + instance := integration.NewInstance(CTX) - got, err := Tester.Client.System.SetQuota(SystemCTX, &system.SetQuotaRequest{ - InstanceId: instanceID, + got, err := integration.SystemClient().SetQuota(CTX, &system.SetQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, From: timestamppb.Now(), ResetInterval: durationpb.New(time.Minute), @@ -166,10 +180,10 @@ func TestServer_AddAndRemoveQuota(t *testing.T) { }, }) require.NoError(t, err) - require.Equal(t, got.Details.ResourceOwner, instanceID) + require.Equal(t, got.Details.ResourceOwner, instance.Instance.Id) - gotAlreadyExisting, errAlreadyExisting := Tester.Client.System.SetQuota(SystemCTX, &system.SetQuotaRequest{ - InstanceId: instanceID, + gotAlreadyExisting, errAlreadyExisting := integration.SystemClient().SetQuota(CTX, &system.SetQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, From: timestamppb.Now(), ResetInterval: durationpb.New(time.Minute), @@ -184,17 +198,17 @@ func TestServer_AddAndRemoveQuota(t *testing.T) { }, }) require.Nil(t, errAlreadyExisting) - require.Equal(t, gotAlreadyExisting.Details.ResourceOwner, instanceID) + require.Equal(t, gotAlreadyExisting.Details.ResourceOwner, instance.Instance.Id) - gotRemove, errRemove := Tester.Client.System.RemoveQuota(SystemCTX, &system.RemoveQuotaRequest{ - InstanceId: instanceID, + gotRemove, errRemove := integration.SystemClient().RemoveQuota(CTX, &system.RemoveQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, }) require.NoError(t, errRemove) - require.Equal(t, gotRemove.Details.ResourceOwner, instanceID) + require.Equal(t, gotRemove.Details.ResourceOwner, instance.Instance.Id) - gotRemoveAlready, errRemoveAlready := Tester.Client.System.RemoveQuota(SystemCTX, &system.RemoveQuotaRequest{ - InstanceId: instanceID, + gotRemoveAlready, errRemoveAlready := integration.SystemClient().RemoveQuota(CTX, &system.RemoveQuotaRequest{ + InstanceId: instance.Instance.Id, Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, }) require.Error(t, errRemoveAlready) diff --git a/internal/api/grpc/system/integration_test/quotas_enabled/server_test.go b/internal/api/grpc/system/integration_test/quotas_enabled/server_test.go new file mode 100644 index 0000000000..0780575dd6 --- /dev/null +++ b/internal/api/grpc/system/integration_test/quotas_enabled/server_test.go @@ -0,0 +1,23 @@ +//go:build integration + +package quotas_enabled_test + +import ( + "context" + "os" + "testing" + "time" +) + +var ( + CTX context.Context +) + +func TestMain(m *testing.M) { + os.Exit(func() int { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + CTX = ctx + return m.Run() + }()) +} diff --git a/internal/api/grpc/system/integration_test/server_test.go b/internal/api/grpc/system/integration_test/server_test.go new file mode 100644 index 0000000000..f21ec5a9de --- /dev/null +++ b/internal/api/grpc/system/integration_test/server_test.go @@ -0,0 +1,24 @@ +//go:build integration + +package system_test + +import ( + "context" + "os" + "testing" + "time" +) + +var ( + CTX context.Context +) + +func TestMain(m *testing.M) { + os.Exit(func() int { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + + CTX = ctx + return m.Run() + }()) +} diff --git a/internal/api/grpc/system/quotas_enabled/server_integration_test.go b/internal/api/grpc/system/quotas_enabled/server_integration_test.go deleted file mode 100644 index c552049e44..0000000000 --- a/internal/api/grpc/system/quotas_enabled/server_integration_test.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build integration - -package quotas_enabled_test - -import ( - "context" - "os" - "testing" - "time" - - "github.com/zitadel/zitadel/internal/integration" -) - -var ( - CTX context.Context - SystemCTX context.Context - IAMOwnerCTX context.Context - Tester *integration.Tester -) - -func TestMain(m *testing.M) { - os.Exit(func() int { - ctx, _, cancel := integration.Contexts(5 * time.Minute) - defer cancel() - CTX = ctx - - Tester = integration.NewTester(ctx, ` -Quotas: - Access: - Enabled: true -`) - defer Tester.Done() - SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser) - IAMOwnerCTX = Tester.WithAuthorization(ctx, integration.IAMOwner) - return m.Run() - }()) -} diff --git a/internal/api/grpc/system/server_integration_test.go b/internal/api/grpc/system/server_integration_test.go deleted file mode 100644 index f36972993f..0000000000 --- a/internal/api/grpc/system/server_integration_test.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build integration - -package system_test - -import ( - "context" - "os" - "testing" - "time" - - "github.com/zitadel/zitadel/internal/integration" -) - -var ( - CTX context.Context - SystemCTX context.Context - Tester *integration.Tester -) - -func TestMain(m *testing.M) { - os.Exit(func() int { - ctx, _, cancel := integration.Contexts(5 * time.Minute) - defer cancel() - CTX = ctx - - Tester = integration.NewTester(ctx) - defer Tester.Done() - - SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser) - return m.Run() - }()) -} diff --git a/internal/api/grpc/user/v2/email_integration_test.go b/internal/api/grpc/user/v2/integration_test/email_test.go similarity index 90% rename from internal/api/grpc/user/v2/email_integration_test.go rename to internal/api/grpc/user/v2/integration_test/email_test.go index 2264934f25..c15e2c0bf3 100644 --- a/internal/api/grpc/user/v2/email_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/email_test.go @@ -12,14 +12,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" object "github.com/zitadel/zitadel/pkg/grpc/object/v2" user "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_SetEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -45,7 +44,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -64,7 +63,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -94,7 +93,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -112,7 +111,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -145,8 +144,8 @@ func TestServer_SetEmail(t *testing.T) { } func TestServer_ResendEmailCode(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - verifiedUserID := Tester.CreateHumanUserVerified(CTX, Tester.Organisation.ID, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() tests := []struct { name string @@ -177,7 +176,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -195,7 +194,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -223,7 +222,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -246,7 +245,7 @@ func TestServer_ResendEmailCode(t *testing.T) { } func TestServer_VerifyEmail(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) tests := []struct { name string req *user.VerifyEmailRequest @@ -279,7 +278,7 @@ func TestServer_VerifyEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2/idp_link_integration_test.go b/internal/api/grpc/user/v2/integration_test/idp_link_test.go similarity index 67% rename from internal/api/grpc/user/v2/idp_link_integration_test.go rename to internal/api/grpc/user/v2/integration_test/idp_link_test.go index 99658b3024..2daa42b91a 100644 --- a/internal/api/grpc/user/v2/idp_link_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/idp_link_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/timestamppb" "github.com/zitadel/zitadel/internal/integration" @@ -18,7 +19,7 @@ import ( ) func TestServer_AddIDPLink(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context req *user.AddIDPLinkRequest @@ -36,7 +37,7 @@ func TestServer_AddIDPLink(t *testing.T) { &user.AddIDPLinkRequest{ UserId: "userID", IdpLink: &user.IDPLink{ - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -50,7 +51,7 @@ func TestServer_AddIDPLink(t *testing.T) { args: args{ CTX, &user.AddIDPLinkRequest{ - UserId: Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, + UserId: Instance.Users.Get(integration.UserTypeOrgOwner).ID, IdpLink: &user.IDPLink{ IdpId: "idpID", UserId: "userID", @@ -66,9 +67,9 @@ func TestServer_AddIDPLink(t *testing.T) { args: args{ CTX, &user.AddIDPLinkRequest{ - UserId: Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, + UserId: Instance.Users.Get(integration.UserTypeOrgOwner).ID, IdpLink: &user.IDPLink{ - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -77,7 +78,7 @@ func TestServer_AddIDPLink(t *testing.T) { want: &user.AddIDPLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, wantErr: false, @@ -98,19 +99,24 @@ func TestServer_AddIDPLink(t *testing.T) { } func TestServer_ListIDPLinks(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - instanceIdpID := Tester.AddGenericOAuthProvider(t, IamCTX) - userInstanceResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) - Tester.CreateUserIDPlink(IamCTX, userInstanceResp.GetUserId(), "external_instance", instanceIdpID, "externalUsername_instance") + instanceIdpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) + userInstanceResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + _, err := Instance.CreateUserIDPlink(IamCTX, userInstanceResp.GetUserId(), "external_instance", instanceIdpResp.Id, "externalUsername_instance") + require.NoError(t, err) - orgIdpID := Tester.AddOrgGenericOAuthProvider(t, IamCTX, orgResp.OrganizationId) - userOrgResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) - Tester.CreateUserIDPlink(IamCTX, userOrgResp.GetUserId(), "external_org", orgIdpID, "externalUsername_org") + ctxOrg := metadata.AppendToOutgoingContext(IamCTX, "x-zitadel-orgid", orgResp.GetOrganizationId()) + orgIdpResp := Instance.AddOrgGenericOAuthProvider(ctxOrg, orgResp.OrganizationId) + userOrgResp := Instance.CreateHumanUserVerified(ctxOrg, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + _, err = Instance.CreateUserIDPlink(ctxOrg, userOrgResp.GetUserId(), "external_org", orgIdpResp.Id, "externalUsername_org") + require.NoError(t, err) - userMultipleResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) - Tester.CreateUserIDPlink(IamCTX, userMultipleResp.GetUserId(), "external_multi", instanceIdpID, "externalUsername_multi") - Tester.CreateUserIDPlink(IamCTX, userMultipleResp.GetUserId(), "external_multi", orgIdpID, "externalUsername_multi") + userMultipleResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + _, err = Instance.CreateUserIDPlink(IamCTX, userMultipleResp.GetUserId(), "external_multi", instanceIdpResp.Id, "externalUsername_multi") + require.NoError(t, err) + _, err = Instance.CreateUserIDPlink(ctxOrg, userMultipleResp.GetUserId(), "external_multi", orgIdpResp.Id, "externalUsername_multi") + require.NoError(t, err) type args struct { ctx context.Context @@ -167,7 +173,7 @@ func TestServer_ListIDPLinks(t *testing.T) { }, Result: []*user.IDPLink{ { - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, UserId: "external_org", UserName: "externalUsername_org", }, @@ -189,7 +195,7 @@ func TestServer_ListIDPLinks(t *testing.T) { }, Result: []*user.IDPLink{ { - IdpId: instanceIdpID, + IdpId: instanceIdpResp.Id, UserId: "external_instance", UserName: "externalUsername_instance", }, @@ -211,12 +217,12 @@ func TestServer_ListIDPLinks(t *testing.T) { }, Result: []*user.IDPLink{ { - IdpId: instanceIdpID, + IdpId: instanceIdpResp.Id, UserId: "external_multi", UserName: "externalUsername_multi", }, { - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, UserId: "external_multi", UserName: "externalUsername_multi", }, @@ -252,17 +258,20 @@ func TestServer_ListIDPLinks(t *testing.T) { } func TestServer_RemoveIDPLink(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - instanceIdpID := Tester.AddGenericOAuthProvider(t, IamCTX) - userInstanceResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) - Tester.CreateUserIDPlink(IamCTX, userInstanceResp.GetUserId(), "external_instance", instanceIdpID, "externalUsername_instance") + instanceIdpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) + userInstanceResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + _, err := Instance.CreateUserIDPlink(IamCTX, userInstanceResp.GetUserId(), "external_instance", instanceIdpResp.Id, "externalUsername_instance") + require.NoError(t, err) - orgIdpID := Tester.AddOrgGenericOAuthProvider(t, IamCTX, orgResp.OrganizationId) - userOrgResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) - Tester.CreateUserIDPlink(IamCTX, userOrgResp.GetUserId(), "external_org", orgIdpID, "externalUsername_org") + ctxOrg := metadata.AppendToOutgoingContext(IamCTX, "x-zitadel-orgid", orgResp.GetOrganizationId()) + orgIdpResp := Instance.AddOrgGenericOAuthProvider(ctxOrg, orgResp.OrganizationId) + userOrgResp := Instance.CreateHumanUserVerified(ctxOrg, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + _, err = Instance.CreateUserIDPlink(ctxOrg, userOrgResp.GetUserId(), "external_org", orgIdpResp.Id, "externalUsername_org") + require.NoError(t, err) - userNoLinkResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) + userNoLinkResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listidplinks.com", time.Now().UnixNano())) type args struct { ctx context.Context @@ -280,7 +289,7 @@ func TestServer_RemoveIDPLink(t *testing.T) { UserCTX, &user.RemoveIDPLinkRequest{ UserId: userOrgResp.GetUserId(), - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, LinkedUserId: "external_org", }, }, @@ -292,7 +301,7 @@ func TestServer_RemoveIDPLink(t *testing.T) { CTX, &user.RemoveIDPLinkRequest{ UserId: userOrgResp.GetUserId(), - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, LinkedUserId: "external_org", }, }, @@ -304,7 +313,7 @@ func TestServer_RemoveIDPLink(t *testing.T) { IamCTX, &user.RemoveIDPLinkRequest{ UserId: userOrgResp.GetUserId(), - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, LinkedUserId: "external_org", }, }, @@ -321,7 +330,7 @@ func TestServer_RemoveIDPLink(t *testing.T) { IamCTX, &user.RemoveIDPLinkRequest{ UserId: userInstanceResp.GetUserId(), - IdpId: instanceIdpID, + IdpId: instanceIdpResp.Id, LinkedUserId: "external_instance", }, }, diff --git a/internal/api/grpc/user/v2/otp_integration_test.go b/internal/api/grpc/user/v2/integration_test/otp_test.go similarity index 59% rename from internal/api/grpc/user/v2/otp_integration_test.go rename to internal/api/grpc/user/v2/integration_test/otp_test.go index 52b30fbd38..ae7c040427 100644 --- a/internal/api/grpc/user/v2/otp_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/otp_test.go @@ -9,32 +9,31 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/object/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_AddOTPSMS(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - userVerified := Tester.CreateHumanUser(CTX) - _, err := Tester.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{ + userVerified := Instance.CreateHumanUser(CTX) + _, err := Instance.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), }) require.NoError(t, err) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerified2 := Tester.CreateHumanUser(CTX) - _, err = Tester.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{ + userVerified2 := Instance.CreateHumanUser(CTX) + _, err = Instance.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{ UserId: userVerified2.GetUserId(), VerificationCode: userVerified2.GetPhoneCode(), }) @@ -61,7 +60,7 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "user mismatch", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), req: &user.AddOTPSMSRequest{ UserId: userID, }, @@ -71,7 +70,7 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "phone not verified", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.AddOTPSMSRequest{ UserId: userID, }, @@ -81,14 +80,14 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "add success", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenVerified), req: &user.AddOTPSMSRequest{ UserId: userVerified.GetUserId(), }, }, want: &user.AddOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -102,7 +101,7 @@ func TestServer_AddOTPSMS(t *testing.T) { }, want: &user.AddOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -122,20 +121,20 @@ func TestServer_AddOTPSMS(t *testing.T) { } func TestServer_RemoveOTPSMS(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) - _, err := Tester.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) + _, err := Instance.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), }) require.NoError(t, err) - _, err = Tester.Client.UserV2.AddOTPSMS(userVerifiedCtx, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()}) + _, err = Instance.Client.UserV2.AddOTPSMS(userVerifiedCtx, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()}) require.NoError(t, err) type args struct { @@ -151,7 +150,7 @@ func TestServer_RemoveOTPSMS(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveOTPSMSRequest{ UserId: userID, }, @@ -168,7 +167,7 @@ func TestServer_RemoveOTPSMS(t *testing.T) { }, want: &user.RemoveOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -188,25 +187,25 @@ func TestServer_RemoveOTPSMS(t *testing.T) { } func TestServer_AddOTPEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - userVerified := Tester.CreateHumanUser(CTX) - _, err := Tester.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{ + userVerified := Instance.CreateHumanUser(CTX) + _, err := Instance.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetEmailCode(), }) require.NoError(t, err) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerified2 := Tester.CreateHumanUser(CTX) - _, err = Tester.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{ + userVerified2 := Instance.CreateHumanUser(CTX) + _, err = Instance.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{ UserId: userVerified2.GetUserId(), VerificationCode: userVerified2.GetEmailCode(), }) @@ -233,7 +232,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "user mismatch", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), req: &user.AddOTPEmailRequest{ UserId: userID, }, @@ -243,7 +242,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "email not verified", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.AddOTPEmailRequest{ UserId: userID, }, @@ -253,7 +252,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "add success", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenVerified), req: &user.AddOTPEmailRequest{ UserId: userVerified.GetUserId(), }, @@ -261,7 +260,7 @@ func TestServer_AddOTPEmail(t *testing.T) { want: &user.AddOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -276,7 +275,7 @@ func TestServer_AddOTPEmail(t *testing.T) { want: &user.AddOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -296,20 +295,20 @@ func TestServer_AddOTPEmail(t *testing.T) { } func TestServer_RemoveOTPEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) - _, err := Tester.Client.UserV2.VerifyEmail(userVerifiedCtx, &user.VerifyEmailRequest{ + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) + _, err := Instance.Client.UserV2.VerifyEmail(userVerifiedCtx, &user.VerifyEmailRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetEmailCode(), }) require.NoError(t, err) - _, err = Tester.Client.UserV2.AddOTPEmail(userVerifiedCtx, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()}) + _, err = Instance.Client.UserV2.AddOTPEmail(userVerifiedCtx, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()}) require.NoError(t, err) type args struct { @@ -325,7 +324,7 @@ func TestServer_RemoveOTPEmail(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveOTPEmailRequest{ UserId: userID, }, @@ -343,7 +342,7 @@ func TestServer_RemoveOTPEmail(t *testing.T) { want: &user.RemoveOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, diff --git a/internal/api/grpc/user/v2/passkey_integration_test.go b/internal/api/grpc/user/v2/integration_test/passkey_test.go similarity index 92% rename from internal/api/grpc/user/v2/passkey_integration_test.go rename to internal/api/grpc/user/v2/integration_test/passkey_test.go index 12d3a6622b..6041e5e409 100644 --- a/internal/api/grpc/user/v2/passkey_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/passkey_test.go @@ -13,14 +13,13 @@ import ( "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/object/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_RegisterPasskey(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{ UserId: userID, Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{}, @@ -28,8 +27,8 @@ func TestServer_RegisterPasskey(t *testing.T) { require.NoError(t, err) // We also need a user session - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) type args struct { ctx context.Context @@ -62,7 +61,7 @@ func TestServer_RegisterPasskey(t *testing.T) { want: &user.RegisterPasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -106,7 +105,7 @@ func TestServer_RegisterPasskey(t *testing.T) { { name: "user setting its own passkey", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionToken), + ctx: integration.WithAuthorizationToken(CTX, sessionToken), req: &user.RegisterPasskeyRequest{ UserId: userID, }, @@ -114,7 +113,7 @@ func TestServer_RegisterPasskey(t *testing.T) { want: &user.RegisterPasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -132,7 +131,7 @@ func TestServer_RegisterPasskey(t *testing.T) { if tt.want != nil { assert.NotEmpty(t, got.GetPasskeyId()) assert.NotEmpty(t, got.GetPublicKeyCredentialCreationOptions()) - _, err = Tester.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) + _, err = Instance.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) } }) @@ -142,7 +141,7 @@ func TestServer_RegisterPasskey(t *testing.T) { func TestServer_VerifyPasskeyRegistration(t *testing.T) { userID, pkr := userWithPasskeyRegistered(t) - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) type args struct { @@ -181,7 +180,7 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) { want: &user.VerifyPasskeyRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -216,7 +215,7 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) { } func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() type args struct { ctx context.Context @@ -248,7 +247,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -268,7 +267,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -284,7 +283,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, wantCode: true, @@ -309,7 +308,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { } func userWithPasskeyRegistered(t *testing.T) (string, *user.RegisterPasskeyResponse) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() return userID, passkeyRegister(t, userID) } @@ -335,7 +334,7 @@ func passkeyRegister(t *testing.T, userID string) *user.RegisterPasskeyResponse } func passkeyVerify(t *testing.T, userID string, pkr *user.RegisterPasskeyResponse) string { - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) _, err = Client.VerifyPasskeyRegistration(CTX, &user.VerifyPasskeyRegistrationRequest{ @@ -349,7 +348,7 @@ func passkeyVerify(t *testing.T, userID string, pkr *user.RegisterPasskeyRespons } func TestServer_RemovePasskey(t *testing.T) { - userIDWithout := Tester.CreateHumanUser(CTX).GetUserId() + userIDWithout := Instance.CreateHumanUser(CTX).GetUserId() userIDRegistered, pkrRegistered := userWithPasskeyRegistered(t) userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t) userIDVerifiedPermission, passkeyIDVerifiedPermission := userWithPasskeyVerified(t) @@ -396,7 +395,7 @@ func TestServer_RemovePasskey(t *testing.T) { want: &user.RemovePasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -423,7 +422,7 @@ func TestServer_RemovePasskey(t *testing.T) { want: &user.RemovePasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -454,7 +453,7 @@ func TestServer_RemovePasskey(t *testing.T) { } func TestServer_ListPasskeys(t *testing.T) { - userIDWithout := Tester.CreateHumanUser(CTX).GetUserId() + userIDWithout := Instance.CreateHumanUser(CTX).GetUserId() userIDRegistered, _ := userWithPasskeyRegistered(t) userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t) diff --git a/internal/api/grpc/user/v2/password_integration_test.go b/internal/api/grpc/user/v2/integration_test/password_test.go similarity index 91% rename from internal/api/grpc/user/v2/password_integration_test.go rename to internal/api/grpc/user/v2/integration_test/password_test.go index f97d0467d7..a316b40df5 100644 --- a/internal/api/grpc/user/v2/password_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/password_test.go @@ -11,14 +11,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" object "github.com/zitadel/zitadel/pkg/grpc/object/v2" user "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_RequestPasswordReset(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -35,7 +34,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -54,7 +53,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -82,7 +81,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -130,7 +129,7 @@ func TestServer_SetPassword(t *testing.T) { { name: "set successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -145,14 +144,14 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID _, err := Client.SetPassword(CTX, &user.SetPasswordRequest{ UserId: userID, @@ -176,14 +175,14 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "set with code successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -210,7 +209,7 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2/phone_integration_test.go b/internal/api/grpc/user/v2/integration_test/phone_test.go similarity index 87% rename from internal/api/grpc/user/v2/phone_integration_test.go rename to internal/api/grpc/user/v2/integration_test/phone_test.go index ab88268ee1..456b77231d 100644 --- a/internal/api/grpc/user/v2/phone_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/phone_test.go @@ -13,14 +13,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" object "github.com/zitadel/zitadel/pkg/grpc/object/v2" user "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_SetPhone(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -38,7 +37,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -55,7 +54,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -72,7 +71,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -90,7 +89,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -123,8 +122,8 @@ func TestServer_SetPhone(t *testing.T) { } func TestServer_ResendPhoneCode(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - verifiedUserID := Tester.CreateHumanUserVerified(CTX, Tester.Organisation.ID, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() tests := []struct { name string @@ -158,7 +157,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -174,7 +173,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -197,7 +196,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { } func TestServer_VerifyPhone(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) tests := []struct { name string req *user.VerifyPhoneRequest @@ -230,7 +229,7 @@ func TestServer_VerifyPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -249,13 +248,13 @@ func TestServer_VerifyPhone(t *testing.T) { } func TestServer_RemovePhone(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) - failResp := Tester.CreateHumanUserNoPhone(CTX) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - doubleRemoveUser := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) + failResp := Instance.CreateHumanUserNoPhone(CTX) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + doubleRemoveUser := Instance.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) tests := []struct { name string @@ -275,7 +274,7 @@ func TestServer_RemovePhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) { @@ -317,7 +316,7 @@ func TestServer_RemovePhone(t *testing.T) { }, { name: "other user, no permission", - ctx: Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(CTX, sessionTokenOtherUser), req: &user.RemovePhoneRequest{ UserId: userResp.GetUserId(), }, diff --git a/internal/api/grpc/user/v2/query_integration_test.go b/internal/api/grpc/user/v2/integration_test/query_test.go similarity index 93% rename from internal/api/grpc/user/v2/query_integration_test.go rename to internal/api/grpc/user/v2/integration_test/query_test.go index 7509a9d430..5d0835d9ae 100644 --- a/internal/api/grpc/user/v2/query_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/query_test.go @@ -13,14 +13,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/object/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_GetUserByID(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) type args struct { ctx context.Context req *user.GetUserByIDRequest @@ -64,7 +63,7 @@ func TestServer_GetUserByID(t *testing.T) { IamCTX, &user.GetUserByIDRequest{}, func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() return &userAttr{resp.GetUserId(), username, nil, resp.GetDetails()}, nil }, @@ -108,9 +107,9 @@ func TestServer_GetUserByID(t *testing.T) { IamCTX, &user.GetUserByIDRequest{}, func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() - details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + details := Instance.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) return &userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()}, nil }, }, @@ -181,7 +180,7 @@ func TestServer_GetUserByID(t *testing.T) { } } assert.Equal(ttt, tt.want.User, got.User) - integration.AssertDetails(t, tt.want, got) + integration.AssertDetails(ttt, tt.want, got) }, retryDuration, time.Second) }) } @@ -190,7 +189,7 @@ func TestServer_GetUserByID(t *testing.T) { func TestServer_GetUserByID_Permission(t *testing.T) { timeNow := time.Now().UTC() newOrgOwnerEmail := fmt.Sprintf("%d@permission.get.com", timeNow.UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) newUserID := newOrg.CreatedAdmins[0].GetUserId() type args struct { ctx context.Context @@ -330,8 +329,8 @@ type userAttr struct { } func TestServer_ListUsers(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - userResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + userResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano())) type args struct { ctx context.Context count int @@ -378,7 +377,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } @@ -432,9 +431,9 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + details := Instance.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) infos[i] = userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()} } request.Queries = append(request.Queries, InUserIDsQuery(userIDs)) @@ -489,7 +488,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } @@ -585,7 +584,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} request.Queries = append(request.Queries, UsernameQuery(username)) @@ -638,7 +637,7 @@ func TestServer_ListUsers(t *testing.T) { func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) @@ -690,7 +689,7 @@ func TestServer_ListUsers(t *testing.T) { func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) @@ -801,11 +800,11 @@ func TestServer_ListUsers(t *testing.T) { 3, &user.ListUsersRequest{}, func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { - orgResp := Tester.CreateOrganization(ctx, fmt.Sprintf("ListUsersResourceowner%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(ctx, fmt.Sprintf("ListUsersResourceowner%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId)) @@ -935,7 +934,7 @@ func TestServer_ListUsers(t *testing.T) { for i := range tt.want.Result { assert.Contains(ttt, got.Result, tt.want.Result[i]) } - integration.AssertListDetails(t, tt.want, got) + integration.AssertListDetails(ttt, tt.want, got) }, retryDuration, time.Millisecond*100, "timeout waiting for expected user result") }) } diff --git a/internal/api/grpc/user/v2/totp_integration_test.go b/internal/api/grpc/user/v2/integration_test/totp_test.go similarity index 72% rename from internal/api/grpc/user/v2/totp_integration_test.go rename to internal/api/grpc/user/v2/integration_test/totp_test.go index 474aed95b8..e65756c1c1 100644 --- a/internal/api/grpc/user/v2/totp_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/totp_test.go @@ -12,22 +12,21 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/object/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_RegisterTOTP(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - ctxOtherUser := Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + ctxOtherUser := integration.WithAuthorizationToken(CTX, sessionTokenOtherUser) type args struct { ctx context.Context @@ -68,7 +67,7 @@ func TestServer_RegisterTOTP(t *testing.T) { want: &user.RegisterTOTPResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -83,7 +82,7 @@ func TestServer_RegisterTOTP(t *testing.T) { want: &user.RegisterTOTPResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -105,10 +104,10 @@ func TestServer_RegisterTOTP(t *testing.T) { } func TestServer_VerifyTOTPRegistration(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) reg, err := Client.RegisterTOTP(ctx, &user.RegisterTOTPRequest{ UserId: userID, @@ -117,10 +116,10 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { code, err := totp.GenerateCode(reg.Secret, time.Now()) require.NoError(t, err) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - ctxOtherUser := Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + ctxOtherUser := integration.WithAuthorizationToken(CTX, sessionTokenOtherUser) regOtherUser, err := Client.RegisterTOTP(CTX, &user.RegisterTOTPRequest{ UserId: otherUser, @@ -172,7 +171,7 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { want: &user.VerifyTOTPRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -188,7 +187,7 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { want: &user.VerifyTOTPRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -208,15 +207,15 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { } func TestServer_RemoveTOTP(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) - _, err := Tester.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) + _, err := Instance.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), }) @@ -248,7 +247,7 @@ func TestServer_RemoveTOTP(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveTOTPRequest{ UserId: userID, }, @@ -265,7 +264,7 @@ func TestServer_RemoveTOTP(t *testing.T) { }, want: &user.RemoveTOTPResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, diff --git a/internal/api/grpc/user/v2/u2f_integration_test.go b/internal/api/grpc/user/v2/integration_test/u2f_test.go similarity index 82% rename from internal/api/grpc/user/v2/u2f_integration_test.go rename to internal/api/grpc/user/v2/integration_test/u2f_test.go index c4d4c33071..b8af753f85 100644 --- a/internal/api/grpc/user/v2/u2f_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/u2f_test.go @@ -11,21 +11,20 @@ import ( "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/object/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/integration" ) func TestServer_RegisterU2F(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - otherUser := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + otherUser := Instance.CreateHumanUser(CTX).GetUserId() // We also need a user session - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) type args struct { ctx context.Context @@ -56,14 +55,14 @@ func TestServer_RegisterU2F(t *testing.T) { want: &user.RegisterU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "other user, no permission", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(CTX, sessionTokenOtherUser), req: &user.RegisterU2FRequest{ UserId: userID, }, @@ -73,7 +72,7 @@ func TestServer_RegisterU2F(t *testing.T) { { name: "user setting its own passkey", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionToken), + ctx: integration.WithAuthorizationToken(CTX, sessionToken), req: &user.RegisterU2FRequest{ UserId: userID, }, @@ -81,7 +80,7 @@ func TestServer_RegisterU2F(t *testing.T) { want: &user.RegisterU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -99,7 +98,7 @@ func TestServer_RegisterU2F(t *testing.T) { if tt.want != nil { assert.NotEmpty(t, got.GetU2FId()) assert.NotEmpty(t, got.GetPublicKeyCredentialCreationOptions()) - _, err = Tester.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) + _, err = Instance.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) } }) @@ -109,7 +108,7 @@ func TestServer_RegisterU2F(t *testing.T) { func TestServer_VerifyU2FRegistration(t *testing.T) { ctx, userID, pkr := ctxFromNewUserWithRegisteredU2F(t) - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) type args struct { @@ -147,7 +146,7 @@ func TestServer_VerifyU2FRegistration(t *testing.T) { want: &user.VerifyU2FRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -182,10 +181,10 @@ func TestServer_VerifyU2FRegistration(t *testing.T) { } func ctxFromNewUserWithRegisteredU2F(t *testing.T) (context.Context, string, *user.RegisterU2FResponse) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) pkr, err := Client.RegisterU2F(ctx, &user.RegisterU2FRequest{ UserId: userID, @@ -198,7 +197,7 @@ func ctxFromNewUserWithRegisteredU2F(t *testing.T) (context.Context, string, *us func ctxFromNewUserWithVerifiedU2F(t *testing.T) (context.Context, string, string) { ctx, userID, pkr := ctxFromNewUserWithRegisteredU2F(t) - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) _, err = Client.VerifyU2FRegistration(ctx, &user.VerifyU2FRegistrationRequest{ @@ -212,7 +211,7 @@ func ctxFromNewUserWithVerifiedU2F(t *testing.T) (context.Context, string, strin } func TestServer_RemoveU2F(t *testing.T) { - userIDWithout := Tester.CreateHumanUser(CTX).GetUserId() + userIDWithout := Instance.CreateHumanUser(CTX).GetUserId() ctxRegistered, userIDRegistered, pkrRegistered := ctxFromNewUserWithRegisteredU2F(t) _, userIDVerified, u2fVerified := ctxFromNewUserWithVerifiedU2F(t) _, userIDVerifiedPermission, u2fVerifiedPermission := ctxFromNewUserWithVerifiedU2F(t) @@ -259,7 +258,7 @@ func TestServer_RemoveU2F(t *testing.T) { want: &user.RemoveU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -286,7 +285,7 @@ func TestServer_RemoveU2F(t *testing.T) { want: &user.RemoveU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2/user_integration_test.go b/internal/api/grpc/user/v2/integration_test/user_test.go similarity index 88% rename from internal/api/grpc/user/v2/user_integration_test.go rename to internal/api/grpc/user/v2/integration_test/user_test.go index e762c10181..cab073c616 100644 --- a/internal/api/grpc/user/v2/user_integration_test.go +++ b/internal/api/grpc/user/v2/integration_test/user_test.go @@ -15,16 +15,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" - "github.com/zitadel/zitadel/pkg/grpc/object/v2" - "github.com/zitadel/zitadel/pkg/grpc/user/v2" - - "github.com/zitadel/zitadel/internal/api/grpc" "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/idp" mgmt "github.com/zitadel/zitadel/pkg/grpc/management" + "github.com/zitadel/zitadel/pkg/grpc/object/v2" + "github.com/zitadel/zitadel/pkg/grpc/user/v2" ) var ( @@ -32,30 +29,28 @@ var ( IamCTX context.Context UserCTX context.Context SystemCTX context.Context - ErrCTX context.Context - Tester *integration.Tester + Instance *integration.Instance Client user.UserServiceClient ) func TestMain(m *testing.M) { os.Exit(func() int { - ctx, errCtx, cancel := integration.Contexts(time.Hour) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer cancel() - Tester = integration.NewTester(ctx) - defer Tester.Done() + Instance = integration.NewInstance(ctx) - UserCTX = Tester.WithAuthorization(ctx, integration.Login) - IamCTX = Tester.WithAuthorization(ctx, integration.IAMOwner) - SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser) - CTX, ErrCTX = Tester.WithAuthorization(ctx, integration.OrgOwner), errCtx - Client = Tester.Client.UserV2 + UserCTX = Instance.WithAuthorization(ctx, integration.UserTypeLogin) + IamCTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner) + SystemCTX = integration.WithSystemAuthorization(ctx) + CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner) + Client = Instance.Client.UserV2 return m.Run() }()) } func TestServer_AddHumanUser(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context req *user.AddHumanUserRequest @@ -73,7 +68,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -103,7 +98,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -114,7 +109,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -147,7 +142,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, EmailCode: gu.Ptr("something"), }, @@ -159,7 +154,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -194,7 +189,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -205,7 +200,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -240,7 +235,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, PhoneCode: gu.Ptr("something"), }, @@ -252,7 +247,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -293,7 +288,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Email: &user.SetHumanEmail{ @@ -324,7 +319,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -358,7 +353,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -405,7 +400,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -436,7 +431,7 @@ func TestServer_AddHumanUser(t *testing.T) { }, IdpLinks: []*user.IDPLink{ { - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -446,7 +441,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -457,7 +452,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -492,7 +487,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -503,7 +498,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -537,7 +532,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -565,7 +560,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -576,7 +571,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -637,7 +632,7 @@ func TestServer_AddHumanUser(t *testing.T) { func TestServer_AddHumanUser_Permission(t *testing.T) { newOrgOwnerEmail := fmt.Sprintf("%d@permission.com", time.Now().UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) type args struct { ctx context.Context req *user.AddHumanUserRequest @@ -857,7 +852,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change username, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -870,14 +865,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change profile, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -897,14 +892,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change email, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -920,14 +915,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change email, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -943,7 +938,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, EmailCode: gu.Ptr("something"), }, @@ -951,7 +946,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change phone, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -967,14 +962,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change phone, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -990,7 +985,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, PhoneCode: gu.Ptr("something"), }, @@ -998,7 +993,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change password, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1030,14 +1025,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change hashed password, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1068,14 +1063,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change hashed password, code, not supported", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1110,7 +1105,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change password, old password, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ @@ -1157,7 +1152,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1186,7 +1181,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { func TestServer_UpdateHumanUser_Permission(t *testing.T) { newOrgOwnerEmail := fmt.Sprintf("%d@permission.update.com", time.Now().UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) newUserID := newOrg.CreatedAdmins[0].GetUserId() type args struct { ctx context.Context @@ -1296,7 +1291,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1304,7 +1299,7 @@ func TestServer_LockUser(t *testing.T) { want: &user.LockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1314,7 +1309,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1322,7 +1317,7 @@ func TestServer_LockUser(t *testing.T) { want: &user.LockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1332,7 +1327,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1348,7 +1343,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1404,7 +1399,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1417,7 +1412,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1430,7 +1425,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1441,7 +1436,7 @@ func TestServer_UnLockUser(t *testing.T) { want: &user.UnlockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1451,7 +1446,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1462,7 +1457,7 @@ func TestServer_UnLockUser(t *testing.T) { want: &user.UnlockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1512,7 +1507,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1520,7 +1515,7 @@ func TestServer_DeactivateUser(t *testing.T) { want: &user.DeactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1530,7 +1525,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1538,7 +1533,7 @@ func TestServer_DeactivateUser(t *testing.T) { want: &user.DeactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1548,7 +1543,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1564,7 +1559,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1620,7 +1615,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1633,7 +1628,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1646,7 +1641,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1657,7 +1652,7 @@ func TestServer_ReactivateUser(t *testing.T) { want: &user.ReactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1667,7 +1662,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1678,7 +1673,7 @@ func TestServer_ReactivateUser(t *testing.T) { want: &user.ReactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1700,7 +1695,7 @@ func TestServer_ReactivateUser(t *testing.T) { } func TestServer_DeleteUser(t *testing.T) { - projectResp, err := Tester.CreateProject(CTX) + projectResp, err := Instance.CreateProject(CTX) require.NoError(t, err) type args struct { ctx context.Context @@ -1730,7 +1725,7 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return err }, @@ -1738,7 +1733,7 @@ func TestServer_DeleteUser(t *testing.T) { want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1748,7 +1743,7 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return err }, @@ -1756,7 +1751,7 @@ func TestServer_DeleteUser(t *testing.T) { want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1766,18 +1761,18 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() - Tester.CreateProjectUserGrant(t, CTX, projectResp.GetId(), request.UserId) - Tester.CreateProjectMembership(t, CTX, projectResp.GetId(), request.UserId) - Tester.CreateOrgMembership(t, CTX, request.UserId) + Instance.CreateProjectUserGrant(t, CTX, projectResp.GetId(), request.UserId) + Instance.CreateProjectMembership(t, CTX, projectResp.GetId(), request.UserId) + Instance.CreateOrgMembership(t, CTX, request.UserId) return err }, }, want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1799,13 +1794,13 @@ func TestServer_DeleteUser(t *testing.T) { } func TestServer_StartIdentityProviderIntent(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) - orgIdpID := Tester.AddOrgGenericOAuthProvider(t, CTX, Tester.Organisation.ID) - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - notDefaultOrgIdpID := Tester.AddOrgGenericOAuthProvider(t, CTX, orgResp.OrganizationId) - samlIdpID := Tester.AddSAMLProvider(t, CTX) - samlRedirectIdpID := Tester.AddSAMLRedirectProvider(t, CTX, "") - samlPostIdpID := Tester.AddSAMLPostProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) + orgIdpResp := Instance.AddOrgGenericOAuthProvider(CTX, Instance.DefaultOrg.Id) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + notDefaultOrgIdpResp := Instance.AddOrgGenericOAuthProvider(IamCTX, orgResp.OrganizationId) + samlIdpID := Instance.AddSAMLProvider(IamCTX) + samlRedirectIdpID := Instance.AddSAMLRedirectProvider(IamCTX, "") + samlPostIdpID := Instance.AddSAMLPostProvider(IamCTX) type args struct { ctx context.Context req *user.StartIdentityProviderIntentRequest @@ -1828,7 +1823,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: idpID, + IdpId: idpResp.Id, }, }, wantErr: true, @@ -1838,7 +1833,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: idpID, + IdpId: idpResp.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1850,13 +1845,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1869,7 +1864,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1881,13 +1876,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1900,7 +1895,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: notDefaultOrgIdpID, + IdpId: notDefaultOrgIdpResp.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1912,13 +1907,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1931,7 +1926,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: orgIdpID, + IdpId: orgIdpResp.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1943,13 +1938,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1974,9 +1969,9 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, - url: "http://" + Tester.Config.ExternalDomain + ":8000/sso", + url: "http://" + Instance.Domain + ":8000/sso", parametersExisting: []string{"RelayState", "SAMLRequest"}, }, wantErr: false, @@ -1998,9 +1993,9 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, - url: "http://" + Tester.Config.ExternalDomain + ":8000/sso", + url: "http://" + Instance.Domain + ":8000/sso", parametersExisting: []string{"RelayState", "SAMLRequest"}, }, wantErr: false, @@ -2022,7 +2017,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, postForm: true, }, @@ -2061,14 +2056,15 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { } } +/* func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) - intentID := Tester.CreateIntent(t, CTX, idpID) - successfulID, token, changeDate, sequence := Tester.CreateSuccessfulOAuthIntent(t, CTX, idpID, "", "id") - successfulWithUserID, withUsertoken, withUserchangeDate, withUsersequence := Tester.CreateSuccessfulOAuthIntent(t, CTX, idpID, "user", "id") - ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence := Tester.CreateSuccessfulLDAPIntent(t, CTX, idpID, "", "id") - ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence := Tester.CreateSuccessfulLDAPIntent(t, CTX, idpID, "user", "id") - samlSuccessfulID, samlToken, samlChangeDate, samlSequence := Tester.CreateSuccessfulSAMLIntent(t, CTX, idpID, "", "id") + idpID := Instance.AddGenericOAuthProvider(t, CTX) + intentID := Instance.CreateIntent(t, CTX, idpID) + successfulID, token, changeDate, sequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID, "", "id") + successfulWithUserID, withUsertoken, withUserchangeDate, withUsersequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID, "user", "id") + ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence := Instance.CreateSuccessfulLDAPIntent(t, CTX, idpID, "", "id") + ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence := Instance.CreateSuccessfulLDAPIntent(t, CTX, idpID, "user", "id") + samlSuccessfulID, samlToken, samlChangeDate, samlSequence := Instance.CreateSuccessfulSAMLIntent(t, CTX, idpID, "", "id") type args struct { ctx context.Context req *user.RetrieveIdentityProviderIntentRequest @@ -2113,7 +2109,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(changeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: sequence, }, IdpInformation: &user.IDPInformation{ @@ -2150,7 +2146,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(withUserchangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: withUsersequence, }, UserId: "user", @@ -2188,7 +2184,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(ldapChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: ldapSequence, }, IdpInformation: &user.IDPInformation{ @@ -2233,7 +2229,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(ldapWithUserChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: ldapWithUserSequence, }, UserId: "user", @@ -2279,7 +2275,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(samlChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: samlSequence, }, IdpInformation: &user.IDPInformation{ @@ -2319,40 +2315,41 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { }) } } +*/ func TestServer_ListAuthenticationMethodTypes(t *testing.T) { - userIDWithoutAuth := Tester.CreateHumanUser(CTX).GetUserId() + userIDWithoutAuth := Instance.CreateHumanUser(CTX).GetUserId() - userIDWithPasskey := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userIDWithPasskey) + userIDWithPasskey := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userIDWithPasskey) - userMultipleAuth := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userMultipleAuth) - provider, err := Tester.Client.Mgmt.AddGenericOIDCProvider(CTX, &mgmt.AddGenericOIDCProviderRequest{ + userMultipleAuth := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userMultipleAuth) + provider, err := Instance.Client.Mgmt.AddGenericOIDCProvider(CTX, &mgmt.AddGenericOIDCProviderRequest{ Name: "ListAuthenticationMethodTypes", Issuer: "https://example.com", ClientId: "client_id", ClientSecret: "client_secret", }) require.NoError(t, err) - _, err = Tester.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{}) + _, err = Instance.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{}) require.Condition(t, func() bool { code := status.Convert(err).Code() return code == codes.AlreadyExists || code == codes.OK }) - _, err = Tester.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{ + _, err = Instance.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{ IdpId: provider.GetId(), OwnerType: idp.IDPOwnerType_IDP_OWNER_TYPE_ORG, }) require.NoError(t, err) - idpLink, err := Tester.Client.UserV2.AddIDPLink(CTX, &user.AddIDPLinkRequest{UserId: userMultipleAuth, IdpLink: &user.IDPLink{ + idpLink, err := Instance.Client.UserV2.AddIDPLink(CTX, &user.AddIDPLinkRequest{UserId: userMultipleAuth, IdpLink: &user.IDPLink{ IdpId: provider.GetId(), UserId: "external-id", UserName: "displayName", }}) require.NoError(t, err) // This should not remove the user IDP links - _, err = Tester.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{ + _, err = Instance.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{ IdpId: provider.GetId(), }) require.NoError(t, err) diff --git a/internal/api/grpc/user/v2beta/email_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/email_test.go similarity index 90% rename from internal/api/grpc/user/v2beta/email_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/email_test.go index 4034a5e7da..71d411fdbb 100644 --- a/internal/api/grpc/user/v2beta/email_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/email_test.go @@ -18,7 +18,7 @@ import ( ) func TestServer_SetEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -44,7 +44,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -63,7 +63,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -93,7 +93,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -111,7 +111,7 @@ func TestServer_SetEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -144,8 +144,8 @@ func TestServer_SetEmail(t *testing.T) { } func TestServer_ResendEmailCode(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - verifiedUserID := Tester.CreateHumanUserVerified(CTX, Tester.Organisation.ID, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() tests := []struct { name string @@ -176,7 +176,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -194,7 +194,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -222,7 +222,7 @@ func TestServer_ResendEmailCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -245,7 +245,7 @@ func TestServer_ResendEmailCode(t *testing.T) { } func TestServer_VerifyEmail(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) tests := []struct { name string req *user.VerifyEmailRequest @@ -278,7 +278,7 @@ func TestServer_VerifyEmail(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2beta/otp_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/otp_test.go similarity index 66% rename from internal/api/grpc/user/v2beta/otp_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/otp_test.go index a6d671c645..6d6e2eff3e 100644 --- a/internal/api/grpc/user/v2beta/otp_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/otp_test.go @@ -15,24 +15,24 @@ import ( ) func TestServer_AddOTPSMS(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - userVerified := Tester.CreateHumanUser(CTX) + userVerified := Instance.CreateHumanUser(CTX) _, err := Client.VerifyPhone(CTX, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), }) require.NoError(t, err) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerified2 := Tester.CreateHumanUser(CTX) + userVerified2 := Instance.CreateHumanUser(CTX) _, err = Client.VerifyPhone(CTX, &user.VerifyPhoneRequest{ UserId: userVerified2.GetUserId(), VerificationCode: userVerified2.GetPhoneCode(), @@ -60,7 +60,7 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "user mismatch", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), req: &user.AddOTPSMSRequest{ UserId: userID, }, @@ -70,7 +70,7 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "phone not verified", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.AddOTPSMSRequest{ UserId: userID, }, @@ -80,14 +80,14 @@ func TestServer_AddOTPSMS(t *testing.T) { { name: "add success", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenVerified), req: &user.AddOTPSMSRequest{ UserId: userVerified.GetUserId(), }, }, want: &user.AddOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -101,7 +101,7 @@ func TestServer_AddOTPSMS(t *testing.T) { }, want: &user.AddOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -121,14 +121,14 @@ func TestServer_AddOTPSMS(t *testing.T) { } func TestServer_RemoveOTPSMS(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) _, err := Client.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), @@ -150,7 +150,7 @@ func TestServer_RemoveOTPSMS(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveOTPSMSRequest{ UserId: userID, }, @@ -167,7 +167,7 @@ func TestServer_RemoveOTPSMS(t *testing.T) { }, want: &user.RemoveOTPSMSResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -187,24 +187,24 @@ func TestServer_RemoveOTPSMS(t *testing.T) { } func TestServer_AddOTPEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - userVerified := Tester.CreateHumanUser(CTX) + userVerified := Instance.CreateHumanUser(CTX) _, err := Client.VerifyEmail(CTX, &user.VerifyEmailRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetEmailCode(), }) require.NoError(t, err) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerified2 := Tester.CreateHumanUser(CTX) + userVerified2 := Instance.CreateHumanUser(CTX) _, err = Client.VerifyEmail(CTX, &user.VerifyEmailRequest{ UserId: userVerified2.GetUserId(), VerificationCode: userVerified2.GetEmailCode(), @@ -232,7 +232,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "user mismatch", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser), req: &user.AddOTPEmailRequest{ UserId: userID, }, @@ -242,7 +242,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "email not verified", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.AddOTPEmailRequest{ UserId: userID, }, @@ -252,7 +252,7 @@ func TestServer_AddOTPEmail(t *testing.T) { { name: "add success", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified), + ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenVerified), req: &user.AddOTPEmailRequest{ UserId: userVerified.GetUserId(), }, @@ -260,7 +260,7 @@ func TestServer_AddOTPEmail(t *testing.T) { want: &user.AddOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -275,7 +275,7 @@ func TestServer_AddOTPEmail(t *testing.T) { want: &user.AddOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -295,14 +295,14 @@ func TestServer_AddOTPEmail(t *testing.T) { } func TestServer_RemoveOTPEmail(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) _, err := Client.VerifyEmail(userVerifiedCtx, &user.VerifyEmailRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetEmailCode(), @@ -324,7 +324,7 @@ func TestServer_RemoveOTPEmail(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveOTPEmailRequest{ UserId: userID, }, @@ -342,7 +342,7 @@ func TestServer_RemoveOTPEmail(t *testing.T) { want: &user.RemoveOTPEmailResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, diff --git a/internal/api/grpc/user/v2beta/passkey_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/passkey_test.go similarity index 89% rename from internal/api/grpc/user/v2beta/passkey_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/passkey_test.go index 230a744a64..acca01885c 100644 --- a/internal/api/grpc/user/v2beta/passkey_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/passkey_test.go @@ -18,7 +18,7 @@ import ( ) func TestServer_RegisterPasskey(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{ UserId: userID, Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{}, @@ -26,8 +26,8 @@ func TestServer_RegisterPasskey(t *testing.T) { require.NoError(t, err) // We also need a user session - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) type args struct { ctx context.Context @@ -60,7 +60,7 @@ func TestServer_RegisterPasskey(t *testing.T) { want: &user.RegisterPasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -104,7 +104,7 @@ func TestServer_RegisterPasskey(t *testing.T) { { name: "user setting its own passkey", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionToken), + ctx: integration.WithAuthorizationToken(CTX, sessionToken), req: &user.RegisterPasskeyRequest{ UserId: userID, }, @@ -112,7 +112,7 @@ func TestServer_RegisterPasskey(t *testing.T) { want: &user.RegisterPasskeyResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -130,7 +130,7 @@ func TestServer_RegisterPasskey(t *testing.T) { if tt.want != nil { assert.NotEmpty(t, got.GetPasskeyId()) assert.NotEmpty(t, got.GetPublicKeyCredentialCreationOptions()) - _, err = Tester.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) + _, err = Instance.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) } }) @@ -138,7 +138,7 @@ func TestServer_RegisterPasskey(t *testing.T) { } func TestServer_VerifyPasskeyRegistration(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{ UserId: userID, Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{}, @@ -152,7 +152,7 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) { require.NotEmpty(t, pkr.GetPasskeyId()) require.NotEmpty(t, pkr.GetPublicKeyCredentialCreationOptions()) - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) type args struct { @@ -191,7 +191,7 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) { want: &user.VerifyPasskeyRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -226,7 +226,7 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) { } func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() type args struct { ctx context.Context @@ -258,7 +258,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -278,7 +278,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -294,7 +294,7 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) { want: &user.CreatePasskeyRegistrationLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, wantCode: true, diff --git a/internal/api/grpc/user/v2beta/password_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/password_test.go similarity index 91% rename from internal/api/grpc/user/v2beta/password_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/password_test.go index 03b18a5fa7..7dd71edbba 100644 --- a/internal/api/grpc/user/v2beta/password_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/password_test.go @@ -17,7 +17,7 @@ import ( ) func TestServer_RequestPasswordReset(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -34,7 +34,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -53,7 +53,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -81,7 +81,7 @@ func TestServer_RequestPasswordReset(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -129,7 +129,7 @@ func TestServer_SetPassword(t *testing.T) { { name: "set successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -144,14 +144,14 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID _, err := Client.SetPassword(CTX, &user.SetPasswordRequest{ UserId: userID, @@ -175,14 +175,14 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "set with code successful", prepare: func(request *user.SetPasswordRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -209,7 +209,7 @@ func TestServer_SetPassword(t *testing.T) { want: &user.SetPasswordResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2beta/phone_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/phone_test.go similarity index 87% rename from internal/api/grpc/user/v2beta/phone_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/phone_test.go index 692f7af5f7..baa7b0f895 100644 --- a/internal/api/grpc/user/v2beta/phone_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/phone_test.go @@ -19,7 +19,7 @@ import ( ) func TestServer_SetPhone(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() tests := []struct { name string @@ -37,7 +37,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -54,7 +54,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -71,7 +71,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -89,7 +89,7 @@ func TestServer_SetPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -122,8 +122,8 @@ func TestServer_SetPhone(t *testing.T) { } func TestServer_ResendPhoneCode(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - verifiedUserID := Tester.CreateHumanUserVerified(CTX, Tester.Organisation.ID, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId() tests := []struct { name string @@ -157,7 +157,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -173,7 +173,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, VerificationCode: gu.Ptr("xxx"), }, @@ -196,7 +196,7 @@ func TestServer_ResendPhoneCode(t *testing.T) { } func TestServer_VerifyPhone(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) tests := []struct { name string req *user.VerifyPhoneRequest @@ -229,7 +229,7 @@ func TestServer_VerifyPhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -248,13 +248,13 @@ func TestServer_VerifyPhone(t *testing.T) { } func TestServer_RemovePhone(t *testing.T) { - userResp := Tester.CreateHumanUser(CTX) - failResp := Tester.CreateHumanUserNoPhone(CTX) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - doubleRemoveUser := Tester.CreateHumanUser(CTX) + userResp := Instance.CreateHumanUser(CTX) + failResp := Instance.CreateHumanUserNoPhone(CTX) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + doubleRemoveUser := Instance.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) tests := []struct { name string @@ -274,7 +274,7 @@ func TestServer_RemovePhone(t *testing.T) { Details: &object.Details{ Sequence: 1, ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) { @@ -316,7 +316,7 @@ func TestServer_RemovePhone(t *testing.T) { }, { name: "other user, no permission", - ctx: Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(CTX, sessionTokenOtherUser), req: &user.RemovePhoneRequest{ UserId: userResp.GetUserId(), }, diff --git a/internal/api/grpc/user/v2beta/query_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/query_test.go similarity index 94% rename from internal/api/grpc/user/v2beta/query_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/query_test.go index 1b375e4091..f78a54d049 100644 --- a/internal/api/grpc/user/v2beta/query_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/query_test.go @@ -28,7 +28,7 @@ func detailsV2ToV2beta(obj *object.Details) *object_v2beta.Details { } func TestServer_GetUserByID(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) type args struct { ctx context.Context req *user.GetUserByIDRequest @@ -72,7 +72,7 @@ func TestServer_GetUserByID(t *testing.T) { IamCTX, &user.GetUserByIDRequest{}, func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() return &userAttr{resp.GetUserId(), username, nil, resp.GetDetails()}, nil }, @@ -116,9 +116,9 @@ func TestServer_GetUserByID(t *testing.T) { IamCTX, &user.GetUserByIDRequest{}, func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() - details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + details := Instance.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) return &userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()}, nil }, }, @@ -198,7 +198,7 @@ func TestServer_GetUserByID(t *testing.T) { func TestServer_GetUserByID_Permission(t *testing.T) { timeNow := time.Now().UTC() newOrgOwnerEmail := fmt.Sprintf("%d@permission.get.com", timeNow.UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) newUserID := newOrg.CreatedAdmins[0].GetUserId() type args struct { ctx context.Context @@ -338,8 +338,8 @@ type userAttr struct { } func TestServer_ListUsers(t *testing.T) { - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - userResp := Tester.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + userResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano())) type args struct { ctx context.Context count int @@ -386,7 +386,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } @@ -440,9 +440,9 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + details := Instance.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) infos[i] = userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()} } request.Queries = append(request.Queries, InUserIDsQuery(userIDs)) @@ -497,7 +497,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } @@ -593,7 +593,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) userIDs := make([]string, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} request.Queries = append(request.Queries, UsernameQuery(username)) @@ -646,7 +646,7 @@ func TestServer_ListUsers(t *testing.T) { func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) @@ -698,7 +698,7 @@ func TestServer_ListUsers(t *testing.T) { func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) @@ -809,11 +809,11 @@ func TestServer_ListUsers(t *testing.T) { 3, &user.ListUsersRequest{}, func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) { - orgResp := Tester.CreateOrganization(ctx, fmt.Sprintf("ListUsersResourceowner%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + orgResp := Instance.CreateOrganization(ctx, fmt.Sprintf("ListUsersResourceowner%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) infos := make([]userAttr, len(usernames)) for i, username := range usernames { - resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) + resp := Instance.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId)) diff --git a/internal/api/grpc/user/v2beta/totp_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/totp_test.go similarity index 70% rename from internal/api/grpc/user/v2beta/totp_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/totp_test.go index 47b2952afd..4afe5e1f31 100644 --- a/internal/api/grpc/user/v2beta/totp_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/totp_test.go @@ -18,15 +18,15 @@ import ( ) func TestServer_RegisterTOTP(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - ctxOtherUser := Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + ctxOtherUser := integration.WithAuthorizationToken(CTX, sessionTokenOtherUser) type args struct { ctx context.Context @@ -67,7 +67,7 @@ func TestServer_RegisterTOTP(t *testing.T) { want: &user.RegisterTOTPResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -82,7 +82,7 @@ func TestServer_RegisterTOTP(t *testing.T) { want: &user.RegisterTOTPResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -104,22 +104,27 @@ func TestServer_RegisterTOTP(t *testing.T) { } func TestServer_VerifyTOTPRegistration(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) + + var reg *user.RegisterTOTPResponse + assert.EventuallyWithT(t, func(ct *assert.CollectT) { + var err error + reg, err = Client.RegisterTOTP(ctx, &user.RegisterTOTPRequest{ + UserId: userID, + }) + assert.NoError(ct, err) + }, time.Minute, time.Second/10) - reg, err := Client.RegisterTOTP(ctx, &user.RegisterTOTPRequest{ - UserId: userID, - }) - require.NoError(t, err) code, err := totp.GenerateCode(reg.Secret, time.Now()) require.NoError(t, err) - otherUser := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) - ctxOtherUser := Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser) + otherUser := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + ctxOtherUser := integration.WithAuthorizationToken(CTX, sessionTokenOtherUser) regOtherUser, err := Client.RegisterTOTP(CTX, &user.RegisterTOTPRequest{ UserId: otherUser, @@ -171,7 +176,7 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { want: &user.VerifyTOTPRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -187,7 +192,7 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { want: &user.VerifyTOTPRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, @@ -207,14 +212,14 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { } func TestServer_RemoveTOTP(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) - userVerified := Tester.CreateHumanUser(CTX) - Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) - _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) - userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) + userVerified := Instance.CreateHumanUser(CTX) + Instance.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified) _, err := Client.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ UserId: userVerified.GetUserId(), VerificationCode: userVerified.GetPhoneCode(), @@ -247,7 +252,7 @@ func TestServer_RemoveTOTP(t *testing.T) { { name: "not added", args: args{ - ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + ctx: integration.WithAuthorizationToken(context.Background(), sessionToken), req: &user.RemoveTOTPRequest{ UserId: userID, }, @@ -264,7 +269,7 @@ func TestServer_RemoveTOTP(t *testing.T) { }, want: &user.RemoveTOTPResponse{ Details: &object.Details{ - ResourceOwner: Tester.Organisation.ResourceOwner, + ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner, }, }, }, diff --git a/internal/api/grpc/user/v2beta/u2f_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/u2f_test.go similarity index 76% rename from internal/api/grpc/user/v2beta/u2f_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/u2f_test.go index 3b7fbd293c..6e47cbbb99 100644 --- a/internal/api/grpc/user/v2beta/u2f_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/u2f_test.go @@ -17,14 +17,14 @@ import ( ) func TestServer_RegisterU2F(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - otherUser := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() + otherUser := Instance.CreateHumanUser(CTX).GetUserId() // We also need a user session - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - Tester.RegisterUserPasskey(CTX, otherUser) - _, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser) + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + Instance.RegisterUserPasskey(CTX, otherUser) + _, sessionTokenOtherUser, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, otherUser) type args struct { ctx context.Context @@ -55,14 +55,14 @@ func TestServer_RegisterU2F(t *testing.T) { want: &user.RegisterU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "other user, no permission", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser), + ctx: integration.WithAuthorizationToken(CTX, sessionTokenOtherUser), req: &user.RegisterU2FRequest{ UserId: userID, }, @@ -72,7 +72,7 @@ func TestServer_RegisterU2F(t *testing.T) { { name: "user setting its own passkey", args: args{ - ctx: Tester.WithAuthorizationToken(CTX, sessionToken), + ctx: integration.WithAuthorizationToken(CTX, sessionToken), req: &user.RegisterU2FRequest{ UserId: userID, }, @@ -80,7 +80,7 @@ func TestServer_RegisterU2F(t *testing.T) { want: &user.RegisterU2FResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -98,7 +98,7 @@ func TestServer_RegisterU2F(t *testing.T) { if tt.want != nil { assert.NotEmpty(t, got.GetU2FId()) assert.NotEmpty(t, got.GetPublicKeyCredentialCreationOptions()) - _, err = Tester.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) + _, err = Instance.WebAuthN.CreateAttestationResponse(got.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) } }) @@ -106,10 +106,10 @@ func TestServer_RegisterU2F(t *testing.T) { } func TestServer_VerifyU2FRegistration(t *testing.T) { - userID := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userID) - _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) - ctx := Tester.WithAuthorizationToken(CTX, sessionToken) + userID := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID) + ctx := integration.WithAuthorizationToken(CTX, sessionToken) pkr, err := Client.RegisterU2F(ctx, &user.RegisterU2FRequest{ UserId: userID, @@ -117,7 +117,7 @@ func TestServer_VerifyU2FRegistration(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, pkr.GetPublicKeyCredentialCreationOptions()) - attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) require.NoError(t, err) type args struct { @@ -155,7 +155,7 @@ func TestServer_VerifyU2FRegistration(t *testing.T) { want: &user.VerifyU2FRegistrationResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, diff --git a/internal/api/grpc/user/v2beta/user_integration_test.go b/internal/api/grpc/user/v2beta/integration_test/user_test.go similarity index 88% rename from internal/api/grpc/user/v2beta/user_integration_test.go rename to internal/api/grpc/user/v2beta/integration_test/user_test.go index d808e46c5f..bf93b67c93 100644 --- a/internal/api/grpc/user/v2beta/user_integration_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/user_test.go @@ -15,10 +15,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" - "github.com/zitadel/zitadel/internal/api/grpc" "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/idp" mgmt "github.com/zitadel/zitadel/pkg/grpc/management" @@ -31,30 +29,28 @@ var ( IamCTX context.Context UserCTX context.Context SystemCTX context.Context - ErrCTX context.Context - Tester *integration.Tester + Instance *integration.Instance Client user.UserServiceClient ) func TestMain(m *testing.M) { os.Exit(func() int { - ctx, errCtx, cancel := integration.Contexts(time.Hour) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer cancel() - Tester = integration.NewTester(ctx) - defer Tester.Done() + Instance = integration.NewInstance(ctx) - UserCTX = Tester.WithAuthorization(ctx, integration.Login) - IamCTX = Tester.WithAuthorization(ctx, integration.IAMOwner) - SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser) - CTX, ErrCTX = Tester.WithAuthorization(ctx, integration.OrgOwner), errCtx - Client = Tester.Client.UserV2beta + UserCTX = Instance.WithAuthorization(ctx, integration.UserTypeLogin) + IamCTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner) + SystemCTX = integration.WithSystemAuthorization(ctx) + CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner) + Client = Instance.Client.UserV2beta return m.Run() }()) } func TestServer_AddHumanUser(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context req *user.AddHumanUserRequest @@ -72,7 +68,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -102,7 +98,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -113,7 +109,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -146,7 +142,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, EmailCode: gu.Ptr("something"), }, @@ -158,7 +154,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -193,7 +189,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -204,7 +200,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -239,7 +235,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, PhoneCode: gu.Ptr("something"), }, @@ -251,7 +247,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -292,7 +288,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Email: &user.SetHumanEmail{ @@ -323,7 +319,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -357,7 +353,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -404,7 +400,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -435,7 +431,7 @@ func TestServer_AddHumanUser(t *testing.T) { }, IdpLinks: []*user.IDPLink{ { - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -445,7 +441,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -456,7 +452,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -491,7 +487,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -502,7 +498,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -536,7 +532,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -564,7 +560,7 @@ func TestServer_AddHumanUser(t *testing.T) { want: &user.AddHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -575,7 +571,7 @@ func TestServer_AddHumanUser(t *testing.T) { &user.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: Tester.Organisation.ID, + OrgId: Instance.DefaultOrg.Id, }, }, Profile: &user.SetHumanProfile{ @@ -636,7 +632,7 @@ func TestServer_AddHumanUser(t *testing.T) { func TestServer_AddHumanUser_Permission(t *testing.T) { newOrgOwnerEmail := fmt.Sprintf("%d@permission.com", time.Now().UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) type args struct { ctx context.Context req *user.AddHumanUserRequest @@ -856,7 +852,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change username, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -869,14 +865,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change profile, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -896,14 +892,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change email, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -919,14 +915,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change email, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -942,7 +938,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, EmailCode: gu.Ptr("something"), }, @@ -950,7 +946,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change phone, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -966,14 +962,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change phone, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID return nil }, @@ -989,7 +985,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, PhoneCode: gu.Ptr("something"), }, @@ -997,7 +993,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change password, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1029,14 +1025,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change hashed password, code, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1067,14 +1063,14 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, { name: "change hashed password, code, not supported", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ UserId: userID, @@ -1109,7 +1105,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { { name: "change password, old password, ok", prepare: func(request *user.UpdateHumanUserRequest) error { - userID := Tester.CreateHumanUser(CTX).GetUserId() + userID := Instance.CreateHumanUser(CTX).GetUserId() request.UserId = userID resp, err := Client.PasswordReset(CTX, &user.PasswordResetRequest{ @@ -1156,7 +1152,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { want: &user.UpdateHumanUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1185,7 +1181,7 @@ func TestServer_UpdateHumanUser(t *testing.T) { func TestServer_UpdateHumanUser_Permission(t *testing.T) { newOrgOwnerEmail := fmt.Sprintf("%d@permission.update.com", time.Now().UnixNano()) - newOrg := Tester.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) + newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail) newUserID := newOrg.CreatedAdmins[0].GetUserId() type args struct { ctx context.Context @@ -1295,7 +1291,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1303,7 +1299,7 @@ func TestServer_LockUser(t *testing.T) { want: &user.LockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1313,7 +1309,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1321,7 +1317,7 @@ func TestServer_LockUser(t *testing.T) { want: &user.LockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1331,7 +1327,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1347,7 +1343,7 @@ func TestServer_LockUser(t *testing.T) { CTX, &user.LockUserRequest{}, func(request *user.LockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1403,7 +1399,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1416,7 +1412,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1429,7 +1425,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1440,7 +1436,7 @@ func TestServer_UnLockUser(t *testing.T) { want: &user.UnlockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1450,7 +1446,7 @@ func TestServer_UnLockUser(t *testing.T) { ctx: CTX, req: &user.UnlockUserRequest{}, prepare: func(request *user.UnlockUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.LockUser(CTX, &user.LockUserRequest{ UserId: resp.GetUserId(), @@ -1461,7 +1457,7 @@ func TestServer_UnLockUser(t *testing.T) { want: &user.UnlockUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1511,7 +1507,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1519,7 +1515,7 @@ func TestServer_DeactivateUser(t *testing.T) { want: &user.DeactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1529,7 +1525,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1537,7 +1533,7 @@ func TestServer_DeactivateUser(t *testing.T) { want: &user.DeactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1547,7 +1543,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1563,7 +1559,7 @@ func TestServer_DeactivateUser(t *testing.T) { CTX, &user.DeactivateUserRequest{}, func(request *user.DeactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1619,7 +1615,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1632,7 +1628,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return nil }, @@ -1645,7 +1641,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1656,7 +1652,7 @@ func TestServer_ReactivateUser(t *testing.T) { want: &user.ReactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1666,7 +1662,7 @@ func TestServer_ReactivateUser(t *testing.T) { ctx: CTX, req: &user.ReactivateUserRequest{}, prepare: func(request *user.ReactivateUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() _, err := Client.DeactivateUser(CTX, &user.DeactivateUserRequest{ UserId: resp.GetUserId(), @@ -1677,7 +1673,7 @@ func TestServer_ReactivateUser(t *testing.T) { want: &user.ReactivateUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1699,7 +1695,7 @@ func TestServer_ReactivateUser(t *testing.T) { } func TestServer_DeleteUser(t *testing.T) { - projectResp, err := Tester.CreateProject(CTX) + projectResp, err := Instance.CreateProject(CTX) require.NoError(t, err) type args struct { ctx context.Context @@ -1729,7 +1725,7 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() return err }, @@ -1737,7 +1733,7 @@ func TestServer_DeleteUser(t *testing.T) { want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1747,7 +1743,7 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateMachineUser(CTX) + resp := Instance.CreateMachineUser(CTX) request.UserId = resp.GetUserId() return err }, @@ -1755,7 +1751,7 @@ func TestServer_DeleteUser(t *testing.T) { want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1765,18 +1761,18 @@ func TestServer_DeleteUser(t *testing.T) { ctx: CTX, req: &user.DeleteUserRequest{}, prepare: func(request *user.DeleteUserRequest) error { - resp := Tester.CreateHumanUser(CTX) + resp := Instance.CreateHumanUser(CTX) request.UserId = resp.GetUserId() - Tester.CreateProjectUserGrant(t, CTX, projectResp.GetId(), request.UserId) - Tester.CreateProjectMembership(t, CTX, projectResp.GetId(), request.UserId) - Tester.CreateOrgMembership(t, CTX, request.UserId) + Instance.CreateProjectUserGrant(t, CTX, projectResp.GetId(), request.UserId) + Instance.CreateProjectMembership(t, CTX, projectResp.GetId(), request.UserId) + Instance.CreateOrgMembership(t, CTX, request.UserId) return err }, }, want: &user.DeleteUserResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, }, @@ -1798,7 +1794,7 @@ func TestServer_DeleteUser(t *testing.T) { } func TestServer_AddIDPLink(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context req *user.AddIDPLinkRequest @@ -1816,7 +1812,7 @@ func TestServer_AddIDPLink(t *testing.T) { &user.AddIDPLinkRequest{ UserId: "userID", IdpLink: &user.IDPLink{ - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -1830,7 +1826,7 @@ func TestServer_AddIDPLink(t *testing.T) { args: args{ CTX, &user.AddIDPLinkRequest{ - UserId: Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, + UserId: Instance.Users.Get(integration.UserTypeOrgOwner).ID, IdpLink: &user.IDPLink{ IdpId: "idpID", UserId: "userID", @@ -1846,9 +1842,9 @@ func TestServer_AddIDPLink(t *testing.T) { args: args{ CTX, &user.AddIDPLinkRequest{ - UserId: Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, + UserId: Instance.Users.Get(integration.UserTypeOrgOwner).ID, IdpLink: &user.IDPLink{ - IdpId: idpID, + IdpId: idpResp.Id, UserId: "userID", UserName: "username", }, @@ -1857,7 +1853,7 @@ func TestServer_AddIDPLink(t *testing.T) { want: &user.AddIDPLinkResponse{ Details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Organisation.ID, + ResourceOwner: Instance.DefaultOrg.Id, }, }, wantErr: false, @@ -1878,13 +1874,13 @@ func TestServer_AddIDPLink(t *testing.T) { } func TestServer_StartIdentityProviderIntent(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) - orgIdpID := Tester.AddOrgGenericOAuthProvider(t, CTX, Tester.Organisation.ID) - orgResp := Tester.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - notDefaultOrgIdpID := Tester.AddOrgGenericOAuthProvider(t, CTX, orgResp.OrganizationId) - samlIdpID := Tester.AddSAMLProvider(t, CTX) - samlRedirectIdpID := Tester.AddSAMLRedirectProvider(t, CTX, "") - samlPostIdpID := Tester.AddSAMLPostProvider(t, CTX) + idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id) + orgIdpID := Instance.AddOrgGenericOAuthProvider(CTX, Instance.DefaultOrg.Id) + orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + notDefaultOrgIdpID := Instance.AddOrgGenericOAuthProvider(IamCTX, orgResp.OrganizationId) + samlIdpID := Instance.AddSAMLProvider(IamCTX) + samlRedirectIdpID := Instance.AddSAMLRedirectProvider(IamCTX, "") + samlPostIdpID := Instance.AddSAMLPostProvider(IamCTX) type args struct { ctx context.Context req *user.StartIdentityProviderIntentRequest @@ -1907,7 +1903,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: idpID, + IdpId: idpResp.Id, }, }, wantErr: true, @@ -1917,7 +1913,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: idpID, + IdpId: idpResp.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1929,13 +1925,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1948,7 +1944,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: orgIdpID, + IdpId: orgIdpID.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1960,13 +1956,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -1979,7 +1975,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: notDefaultOrgIdpID, + IdpId: notDefaultOrgIdpID.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -1991,13 +1987,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -2010,7 +2006,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { args: args{ CTX, &user.StartIdentityProviderIntentRequest{ - IdpId: orgIdpID, + IdpId: orgIdpID.Id, Content: &user.StartIdentityProviderIntentRequest_Urls{ Urls: &user.RedirectURLs{ SuccessUrl: "https://example.com/success", @@ -2022,13 +2018,13 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, url: "https://example.com/oauth/v2/authorize", parametersEqual: map[string]string{ "client_id": "clientID", "prompt": "select_account", - "redirect_uri": "http://" + Tester.Config.ExternalDomain + ":8080/idps/callback", + "redirect_uri": "http://" + Instance.Domain + ":8080/idps/callback", "response_type": "code", "scope": "openid profile email", }, @@ -2053,9 +2049,9 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, - url: "http://" + Tester.Config.ExternalDomain + ":8000/sso", + url: "http://" + Instance.Domain + ":8000/sso", parametersExisting: []string{"RelayState", "SAMLRequest"}, }, wantErr: false, @@ -2077,9 +2073,9 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, - url: "http://" + Tester.Config.ExternalDomain + ":8000/sso", + url: "http://" + Instance.Domain + ":8000/sso", parametersExisting: []string{"RelayState", "SAMLRequest"}, }, wantErr: false, @@ -2101,7 +2097,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { want: want{ details: &object.Details{ ChangeDate: timestamppb.Now(), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), }, postForm: true, }, @@ -2140,14 +2136,15 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) { } } +/* func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { - idpID := Tester.AddGenericOAuthProvider(t, CTX) - intentID := Tester.CreateIntent(t, CTX, idpID) - successfulID, token, changeDate, sequence := Tester.CreateSuccessfulOAuthIntent(t, CTX, idpID, "", "id") - successfulWithUserID, withUsertoken, withUserchangeDate, withUsersequence := Tester.CreateSuccessfulOAuthIntent(t, CTX, idpID, "user", "id") - ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence := Tester.CreateSuccessfulLDAPIntent(t, CTX, idpID, "", "id") - ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence := Tester.CreateSuccessfulLDAPIntent(t, CTX, idpID, "user", "id") - samlSuccessfulID, samlToken, samlChangeDate, samlSequence := Tester.CreateSuccessfulSAMLIntent(t, CTX, idpID, "", "id") + idpID := Instance.AddGenericOAuthProvider(t, CTX) + intentID := Instance.CreateIntent(t, CTX, idpID) + successfulID, token, changeDate, sequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID.Id, "", "id") + successfulWithUserID, withUsertoken, withUserchangeDate, withUsersequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID.Id, "user", "id") + ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence := Instance.CreateSuccessfulLDAPIntent(t, CTX, idpID.Id, "", "id") + ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence := Instance.CreateSuccessfulLDAPIntent(t, CTX, idpID.Id, "user", "id") + samlSuccessfulID, samlToken, samlChangeDate, samlSequence := Instance.CreateSuccessfulSAMLIntent(t, CTX, idpID.Id, "", "id") type args struct { ctx context.Context req *user.RetrieveIdentityProviderIntentRequest @@ -2192,7 +2189,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(changeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: sequence, }, IdpInformation: &user.IDPInformation{ @@ -2202,7 +2199,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdToken: gu.Ptr("idToken"), }, }, - IdpId: idpID, + IdpId: idpID.Id, UserId: "id", UserName: "username", RawInformation: func() *structpb.Struct { @@ -2229,7 +2226,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(withUserchangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: withUsersequence, }, UserId: "user", @@ -2240,7 +2237,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdToken: gu.Ptr("idToken"), }, }, - IdpId: idpID, + IdpId: idpID.Id, UserId: "id", UserName: "username", RawInformation: func() *structpb.Struct { @@ -2267,7 +2264,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(ldapChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: ldapSequence, }, IdpInformation: &user.IDPInformation{ @@ -2284,7 +2281,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { }(), }, }, - IdpId: idpID, + IdpId: idpID.Id, UserId: "id", UserName: "username", RawInformation: func() *structpb.Struct { @@ -2312,7 +2309,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(ldapWithUserChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: ldapWithUserSequence, }, UserId: "user", @@ -2330,7 +2327,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { }(), }, }, - IdpId: idpID, + IdpId: idpID.Id, UserId: "id", UserName: "username", RawInformation: func() *structpb.Struct { @@ -2358,7 +2355,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { want: &user.RetrieveIdentityProviderIntentResponse{ Details: &object.Details{ ChangeDate: timestamppb.New(samlChangeDate), - ResourceOwner: Tester.Instance.InstanceID(), + ResourceOwner: Instance.ID(), Sequence: samlSequence, }, IdpInformation: &user.IDPInformation{ @@ -2367,7 +2364,7 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { Assertion: []byte(""), }, }, - IdpId: idpID, + IdpId: idpID.Id, UserId: "id", UserName: "", RawInformation: func() *structpb.Struct { @@ -2398,28 +2395,29 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { }) } } +*/ func TestServer_ListAuthenticationMethodTypes(t *testing.T) { - userIDWithoutAuth := Tester.CreateHumanUser(CTX).GetUserId() + userIDWithoutAuth := Instance.CreateHumanUser(CTX).GetUserId() - userIDWithPasskey := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userIDWithPasskey) + userIDWithPasskey := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userIDWithPasskey) - userMultipleAuth := Tester.CreateHumanUser(CTX).GetUserId() - Tester.RegisterUserPasskey(CTX, userMultipleAuth) - provider, err := Tester.Client.Mgmt.AddGenericOIDCProvider(CTX, &mgmt.AddGenericOIDCProviderRequest{ + userMultipleAuth := Instance.CreateHumanUser(CTX).GetUserId() + Instance.RegisterUserPasskey(CTX, userMultipleAuth) + provider, err := Instance.Client.Mgmt.AddGenericOIDCProvider(CTX, &mgmt.AddGenericOIDCProviderRequest{ Name: "ListAuthenticationMethodTypes", Issuer: "https://example.com", ClientId: "client_id", ClientSecret: "client_secret", }) require.NoError(t, err) - _, err = Tester.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{}) + _, err = Instance.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{}) require.Condition(t, func() bool { code := status.Convert(err).Code() return code == codes.AlreadyExists || code == codes.OK }) - _, err = Tester.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{ + _, err = Instance.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{ IdpId: provider.GetId(), OwnerType: idp.IDPOwnerType_IDP_OWNER_TYPE_ORG, }) @@ -2431,7 +2429,7 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) { }}) require.NoError(t, err) // This should not remove the user IDP links - _, err = Tester.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{ + _, err = Instance.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{ IdpId: provider.GetId(), }) require.NoError(t, err) diff --git a/internal/api/idp/idp_integration_test.go b/internal/api/idp/integration_test/idp_test.go similarity index 90% rename from internal/api/idp/idp_integration_test.go rename to internal/api/idp/integration_test/idp_test.go index 51d9bbfeea..609b98262b 100644 --- a/internal/api/idp/idp_integration_test.go +++ b/internal/api/idp/integration_test/idp_test.go @@ -31,29 +31,27 @@ import ( ) var ( - CTX context.Context - ErrCTX context.Context - Tester *integration.Tester - Client user.UserServiceClient + CTX context.Context + Instance *integration.Instance + Client user.UserServiceClient ) func TestMain(m *testing.M) { os.Exit(func() int { - ctx, errCtx, cancel := integration.Contexts(time.Hour) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer cancel() - Tester = integration.NewTester(ctx) - defer Tester.Done() + Instance = integration.NewInstance(ctx) - CTX, ErrCTX = Tester.WithAuthorization(ctx, integration.OrgOwner), errCtx - Client = Tester.Client.UserV2 + CTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner) + Client = Instance.Client.UserV2 return m.Run() }()) } func TestServer_SAMLCertificate(t *testing.T) { - samlRedirectIdpID := Tester.AddSAMLRedirectProvider(t, CTX, "") - oauthIdpID := Tester.AddGenericOAuthProvider(t, CTX) + samlRedirectIdpID := Instance.AddSAMLRedirectProvider(CTX, "") + oauthIdpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context @@ -76,7 +74,7 @@ func TestServer_SAMLCertificate(t *testing.T) { name: "saml certificate, invalid idp type", args: args{ ctx: CTX, - idpID: oauthIdpID, + idpID: oauthIdpResp.Id, }, want: http.StatusBadRequest, }, @@ -91,7 +89,7 @@ func TestServer_SAMLCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - certificateURL := http_util.BuildOrigin(Tester.Host(), Tester.Server.Config.ExternalSecure) + "/idps/" + tt.args.idpID + "/saml/certificate" + certificateURL := http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + tt.args.idpID + "/saml/certificate" resp, err := http.Get(certificateURL) assert.NoError(t, err) assert.Equal(t, tt.want, resp.StatusCode) @@ -109,8 +107,8 @@ func TestServer_SAMLCertificate(t *testing.T) { } func TestServer_SAMLMetadata(t *testing.T) { - samlRedirectIdpID := Tester.AddSAMLRedirectProvider(t, CTX, "") - oauthIdpID := Tester.AddGenericOAuthProvider(t, CTX) + samlRedirectIdpID := Instance.AddSAMLRedirectProvider(CTX, "") + oauthIdpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id) type args struct { ctx context.Context @@ -133,7 +131,7 @@ func TestServer_SAMLMetadata(t *testing.T) { name: "saml metadata, invalid idp type", args: args{ ctx: CTX, - idpID: oauthIdpID, + idpID: oauthIdpResp.Id, }, want: http.StatusBadRequest, }, @@ -148,7 +146,7 @@ func TestServer_SAMLMetadata(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - metadataURL := http_util.BuildOrigin(Tester.Host(), Tester.Server.Config.ExternalSecure) + "/idps/" + tt.args.idpID + "/saml/metadata" + metadataURL := http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + tt.args.idpID + "/saml/metadata" resp, err := http.Get(metadataURL) assert.NoError(t, err) assert.Equal(t, tt.want, resp.StatusCode) @@ -166,13 +164,13 @@ func TestServer_SAMLMetadata(t *testing.T) { } func TestServer_SAMLACS(t *testing.T) { - userHuman := Tester.CreateHumanUser(CTX) - samlRedirectIdpID := Tester.AddSAMLRedirectProvider(t, CTX, "urn:oid:0.9.2342.19200300.100.1.1") // the username is set in urn:oid:0.9.2342.19200300.100.1.1 + userHuman := Instance.CreateHumanUser(CTX) + samlRedirectIdpID := Instance.AddSAMLRedirectProvider(CTX, "urn:oid:0.9.2342.19200300.100.1.1") // the username is set in urn:oid:0.9.2342.19200300.100.1.1 externalUserID := "test1" linkedExternalUserID := "test2" - Tester.CreateUserIDPlink(CTX, userHuman.UserId, linkedExternalUserID, samlRedirectIdpID, linkedExternalUserID) + Instance.CreateUserIDPlink(CTX, userHuman.UserId, linkedExternalUserID, samlRedirectIdpID, linkedExternalUserID) idp, err := getIDP( - http_util.BuildOrigin(Tester.Host(), Tester.Server.Config.ExternalSecure), + http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure), []string{samlRedirectIdpID}, externalUserID, linkedExternalUserID, @@ -328,7 +326,7 @@ func TestServer_SAMLACS(t *testing.T) { if tt.args.intentID != "" { relayState = tt.args.intentID } - callbackURL := http_util.BuildOrigin(Tester.Host(), Tester.Server.Config.ExternalSecure) + "/idps/" + tt.args.idpID + "/saml/acs" + callbackURL := http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + tt.args.idpID + "/saml/acs" response := createResponse(t, idp, samlRequest, tt.args.nameID, tt.args.nameIDFormat, tt.args.username) //test purposes, use defined response if tt.args.response != "" { diff --git a/internal/api/oidc/auth_request_integration_test.go b/internal/api/oidc/integration_test/auth_request_test.go similarity index 68% rename from internal/api/oidc/auth_request_integration_test.go rename to internal/api/oidc/integration_test/auth_request_test.go index faa5126676..bd9142a3f6 100644 --- a/internal/api/oidc/auth_request_integration_test.go +++ b/internal/api/oidc/integration_test/auth_request_test.go @@ -28,17 +28,21 @@ var ( ) func TestOPStorage_CreateAuthRequest(t *testing.T) { - clientID, _ := createClient(t) + t.Parallel() - id := createAuthRequest(t, clientID, redirectURI) + clientID, _ := createClient(t, Instance) + + id := createAuthRequest(t, Instance, clientID, redirectURI) require.Contains(t, id, command.IDPrefixV2) } func TestOPStorage_CreateAccessToken_code(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + t.Parallel() + + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -51,13 +55,13 @@ func TestOPStorage_CreateAccessToken_code(t *testing.T) { // test code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) // callback on a succeeded request must fail - linkResp, err = Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + linkResp, err = Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -69,15 +73,17 @@ func TestOPStorage_CreateAccessToken_code(t *testing.T) { require.Error(t, err) // exchange with a used code must fail - _, err = exchangeTokens(t, clientID, code, redirectURI) + _, err = exchangeTokens(t, Instance, clientID, code, redirectURI) require.Error(t, err) } func TestOPStorage_CreateAccessToken_implicit(t *testing.T) { + t.Parallel() + clientID := createImplicitClient(t) authRequestID := createAuthRequestImplicit(t, clientID, redirectURIImplicit) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -104,14 +110,14 @@ func TestOPStorage_CreateAccessToken_implicit(t *testing.T) { assert.Equal(t, "state", values.Get("state")) // check id_token / claims - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURIImplicit) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURIImplicit) require.NoError(t, err) claims, err := rp.VerifyTokens[*oidc.IDTokenClaims](context.Background(), accessToken, idToken, provider.IDTokenVerifier()) require.NoError(t, err) assertIDTokenClaims(t, claims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) // callback on a succeeded request must fail - linkResp, err = Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + linkResp, err = Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -124,10 +130,12 @@ func TestOPStorage_CreateAccessToken_implicit(t *testing.T) { } func TestOPStorage_CreateAccessAndRefreshTokens_code(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + t.Parallel() + + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -140,19 +148,21 @@ func TestOPStorage_CreateAccessAndRefreshTokens_code(t *testing.T) { // test code exchange (expect refresh token to be returned) code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) } func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -165,7 +175,7 @@ func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -183,12 +193,14 @@ func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) { } func TestOPStorage_RevokeToken_access_token(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -201,7 +213,7 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -226,12 +238,14 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) { } func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -244,7 +258,7 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -263,12 +277,14 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T } func TestOPStorage_RevokeToken_refresh_token(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -281,7 +297,7 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -306,12 +322,14 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) { } func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -324,7 +342,7 @@ func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing. // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -343,10 +361,12 @@ func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing. } func TestOPStorage_RevokeToken_invalid_client(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + t.Parallel() + + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -359,26 +379,28 @@ func TestOPStorage_RevokeToken_invalid_client(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) // simulate second client (not part of the audience) trying to revoke the token - otherClientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, otherClientID, redirectURI) + otherClientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, otherClientID, redirectURI) require.NoError(t, err) err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "") require.Error(t, err) } func TestOPStorage_TerminateSession(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -391,7 +413,7 @@ func TestOPStorage_TerminateSession(t *testing.T) { // test code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -410,12 +432,14 @@ func TestOPStorage_TerminateSession(t *testing.T) { } func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -428,7 +452,7 @@ func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) { // test code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -454,12 +478,14 @@ func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) { } func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -472,21 +498,21 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) { // test code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) postLogoutRedirect, err := rp.EndSession(CTX, provider, "", logoutRedirectURI, "state") require.NoError(t, err) - assert.Equal(t, http_utils.BuildOrigin(Tester.Host(), Tester.Config.ExternalSecure)+Tester.Config.OIDC.DefaultLogoutURLV2+logoutRedirectURI+"?state=state", postLogoutRedirect.String()) + assert.Equal(t, http_utils.BuildOrigin(Instance.Host(), Instance.Config.Secure)+Instance.Config.LogoutURLV2+logoutRedirectURI+"?state=state", postLogoutRedirect.String()) // userinfo must not fail until login UI terminated session _, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider) require.NoError(t, err) // simulate termination by login UI - _, err = Tester.Client.SessionV2.DeleteSession(CTXLOGIN, &session.DeleteSessionRequest{ + _, err = Instance.Client.SessionV2.DeleteSession(CTXLOGIN, &session.DeleteSessionRequest{ SessionId: sessionID, SessionToken: gu.Ptr(sessionToken), }) @@ -497,15 +523,15 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) { require.Error(t, err) } -func exchangeTokens(t testing.TB, clientID, code, redirectURI string) (*oidc.Tokens[*oidc.IDTokenClaims], error) { - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) +func exchangeTokens(t testing.TB, instance *integration.Instance, clientID, code, redirectURI string) (*oidc.Tokens[*oidc.IDTokenClaims], error) { + provider, err := instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) return rp.CodeExchange[*oidc.IDTokenClaims](context.Background(), code, provider, rp.WithCodeVerifier(integration.CodeVerifier)) } func refreshTokens(t testing.TB, clientID, refreshToken string) (*oidc.Tokens[*oidc.IDTokenClaims], error) { - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) return rp.RefreshTokens[*oidc.IDTokenClaims](CTX, provider, refreshToken, "", "") diff --git a/internal/api/oidc/client_integration_test.go b/internal/api/oidc/integration_test/client_test.go similarity index 81% rename from internal/api/oidc/client_integration_test.go rename to internal/api/oidc/integration_test/client_test.go index 9ff0b104d9..7e9f15ffac 100644 --- a/internal/api/oidc/client_integration_test.go +++ b/internal/api/oidc/integration_test/client_test.go @@ -24,9 +24,11 @@ import ( ) func TestServer_Introspect(t *testing.T) { - project, err := Tester.CreateProject(CTX) + t.Parallel() + + project, err := Instance.CreateProject(CTX) require.NoError(t, err) - app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false) + app, err := Instance.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false) require.NoError(t, err) wantAudience := []string{app.GetClientId(), project.GetId()} @@ -39,16 +41,16 @@ func TestServer_Introspect(t *testing.T) { { name: "client assertion", api: func(t *testing.T) (string, rs.ResourceServer) { - api, err := Tester.CreateAPIClientJWT(CTX, project.GetId()) + api, err := Instance.CreateAPIClientJWT(CTX, project.GetId()) require.NoError(t, err) - keyResp, err := Tester.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{ + keyResp, err := Instance.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{ ProjectId: project.GetId(), AppId: api.GetAppId(), Type: authn.KeyType_KEY_TYPE_JSON, ExpirationDate: nil, }) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyResp.GetKeyDetails()) + resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyResp.GetKeyDetails()) require.NoError(t, err) return api.GetClientId(), resourceServer }, @@ -56,9 +58,9 @@ func TestServer_Introspect(t *testing.T) { { name: "client credentials", api: func(t *testing.T) (string, rs.ResourceServer) { - api, err := Tester.CreateAPIClientBasic(CTX, project.GetId()) + api, err := Instance.CreateAPIClientBasic(CTX, project.GetId()) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), api.GetClientSecret()) + resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), api.GetClientSecret()) require.NoError(t, err) return api.GetClientId(), resourceServer }, @@ -66,9 +68,9 @@ func TestServer_Introspect(t *testing.T) { { name: "client invalid id, error", api: func(t *testing.T) (string, rs.ResourceServer) { - api, err := Tester.CreateAPIClientBasic(CTX, project.GetId()) + api, err := Instance.CreateAPIClientBasic(CTX, project.GetId()) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, "xxxxx", api.GetClientSecret()) + resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, "xxxxx", api.GetClientSecret()) require.NoError(t, err) return api.GetClientId(), resourceServer }, @@ -77,9 +79,9 @@ func TestServer_Introspect(t *testing.T) { { name: "client invalid secret, error", api: func(t *testing.T) (string, rs.ResourceServer) { - api, err := Tester.CreateAPIClientBasic(CTX, project.GetId()) + api, err := Instance.CreateAPIClientBasic(CTX, project.GetId()) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx") + resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx") require.NoError(t, err) return api.GetClientId(), resourceServer }, @@ -88,9 +90,9 @@ func TestServer_Introspect(t *testing.T) { { name: "client credentials on jwt client, error", api: func(t *testing.T) (string, rs.ResourceServer) { - api, err := Tester.CreateAPIClientJWT(CTX, project.GetId()) + api, err := Instance.CreateAPIClientJWT(CTX, project.GetId()) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx") + resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx") require.NoError(t, err) return api.GetClientId(), resourceServer }, @@ -104,9 +106,9 @@ func TestServer_Introspect(t *testing.T) { wantAudience = append(wantAudience, apiID) scope := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess, oidc_api.ScopeResourceOwner} - authRequestID := createAuthRequest(t, app.GetClientId(), redirectURI, scope...) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, app.GetClientId(), redirectURI, scope...) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -119,7 +121,7 @@ func TestServer_Introspect(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, app.GetClientId(), code, redirectURI) + tokens, err := exchangeTokens(t, Instance, app.GetClientId(), code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) @@ -133,7 +135,7 @@ func TestServer_Introspect(t *testing.T) { require.NoError(t, err) assertIntrospection(t, introspection, - Tester.OIDCIssuer(), app.GetClientId(), + Instance.OIDCIssuer(), app.GetClientId(), scope, wantAudience, tokens.Expiry, tokens.Expiry.Add(-12*time.Hour)) }) @@ -141,9 +143,11 @@ func TestServer_Introspect(t *testing.T) { } func TestServer_Introspect_invalid_auth_invalid_token(t *testing.T) { + t.Parallel() + // ensure that when an invalid authentication and token is sent, the authentication error is returned // https://github.com/zitadel/zitadel/pull/8133 - resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, "xxxxx", "xxxxx") + resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, "xxxxx", "xxxxx") require.NoError(t, err) _, err = rs.Introspect[*oidc.IntrospectionResponse](context.Background(), resourceServer, "xxxxx") require.Error(t, err) @@ -187,17 +191,19 @@ func assertIntrospection( // TestServer_VerifyClient tests verification by running code flow tests // with clients that have different authentication methods. func TestServer_VerifyClient(t *testing.T) { - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - project, err := Tester.CreateProject(CTX) + t.Parallel() + + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + project, err := Instance.CreateProject(CTX) require.NoError(t, err) - inactiveClient, err := Tester.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) + inactiveClient, err := Instance.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) require.NoError(t, err) - nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false) + nativeClient, err := Instance.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false) require.NoError(t, err) - basicWebClient, err := Tester.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId()) + basicWebClient, err := Instance.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId()) require.NoError(t, err) - jwtWebClient, keyData, err := Tester.CreateOIDCWebClientJWT(CTX, redirectURI, logoutRedirectURI, project.GetId()) + jwtWebClient, keyData, err := Instance.CreateOIDCWebClientJWT(CTX, redirectURI, logoutRedirectURI, project.GetId()) require.NoError(t, err) type clientDetails struct { @@ -295,9 +301,9 @@ func TestServer_VerifyClient(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, tt.client.authReqClientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, oidc.ScopeOpenID) + authRequestID, err := Instance.CreateOIDCAuthRequest(CTX, tt.client.authReqClientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID) require.NoError(t, err) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -313,7 +319,7 @@ func TestServer_VerifyClient(t *testing.T) { if tt.client.keyData != nil { options = append(options, rp.WithJWTProfile(rp.SignerFromKeyFile(tt.client.keyData))) } - provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), tt.client.clientID, tt.client.clientSecret, redirectURI, []string{oidc.ScopeOpenID}, options...) + provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), tt.client.clientID, tt.client.clientSecret, redirectURI, []string{oidc.ScopeOpenID}, options...) require.NoError(t, err) // test code exchange diff --git a/internal/api/oidc/keys_integration_test.go b/internal/api/oidc/integration_test/keys_test.go similarity index 66% rename from internal/api/oidc/keys_integration_test.go rename to internal/api/oidc/integration_test/keys_test.go index a78e4fc1b8..e8160017a5 100644 --- a/internal/api/oidc/keys_integration_test.go +++ b/internal/api/oidc/integration_test/keys_test.go @@ -18,17 +18,23 @@ import ( http_util "github.com/zitadel/zitadel/internal/api/http" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/feature/v2" oidc_pb "github.com/zitadel/zitadel/pkg/grpc/oidc/v2" ) func TestServer_Keys(t *testing.T) { - // TODO: isolated instance + t.Parallel() - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) - sessionID, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + instance := integration.NewInstance(CTX) + ctxLogin := instance.WithAuthorization(CTX, integration.UserTypeLogin) + + clientID, _ := createClient(t, instance) + authRequestID := createAuthRequest(t, instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) + + instance.RegisterUserPasskey(instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), instance.AdminUserID) + sessionID, sessionToken, _, _ := instance.CreateVerifiedWebAuthNSession(t, ctxLogin, instance.AdminUserID) + linkResp, err := instance.Client.OIDCv2.CreateCallback(ctxLogin, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -41,10 +47,10 @@ func TestServer_Keys(t *testing.T) { // code exchange so we are sure there is 1 legacy key pair. code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - _, err = exchangeTokens(t, clientID, code, redirectURI) + _, err = exchangeTokens(t, instance, clientID, code, redirectURI) require.NoError(t, err) - issuer := http_util.BuildHTTP(Tester.Config.ExternalDomain, Tester.Config.Port, Tester.Config.ExternalSecure) + issuer := http_util.BuildHTTP(instance.Domain, instance.Config.Port, instance.Config.Secure) discovery, err := client.Discover(CTX, issuer, http.DefaultClient) require.NoError(t, err) @@ -66,7 +72,7 @@ func TestServer_Keys(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ensureWebKeyFeature(t, tt.webKeyFeature) + ensureWebKeyFeature(t, instance, tt.webKeyFeature) assert.EventuallyWithT(t, func(ttt *assert.CollectT) { resp, err := http.Get(discovery.JwksURI) @@ -100,14 +106,16 @@ func TestServer_Keys(t *testing.T) { } } -func ensureWebKeyFeature(t *testing.T, set bool) { - _, err := Tester.Client.FeatureV2.SetInstanceFeatures(CTXIAM, &feature.SetInstanceFeaturesRequest{ +func ensureWebKeyFeature(t *testing.T, instance *integration.Instance, set bool) { + ctxIam := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + + _, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{ WebKey: proto.Bool(set), }) require.NoError(t, err) t.Cleanup(func() { - _, err := Tester.Client.FeatureV2.SetInstanceFeatures(CTXIAM, &feature.SetInstanceFeaturesRequest{ + _, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{ WebKey: proto.Bool(false), }) require.NoError(t, err) diff --git a/internal/api/oidc/oidc_integration_test.go b/internal/api/oidc/integration_test/oidc_test.go similarity index 59% rename from internal/api/oidc/oidc_integration_test.go rename to internal/api/oidc/integration_test/oidc_test.go index 1f7f615809..016745cf56 100644 --- a/internal/api/oidc/oidc_integration_test.go +++ b/internal/api/oidc/integration_test/oidc_test.go @@ -28,7 +28,7 @@ var ( CTX context.Context CTXLOGIN context.Context CTXIAM context.Context - Tester *integration.Tester + Instance *integration.Instance User *user.AddHumanUserResponse ) @@ -41,27 +41,26 @@ const ( func TestMain(m *testing.M) { os.Exit(func() int { - ctx, _, cancel := integration.Contexts(10 * time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer cancel() - Tester = integration.NewTester(ctx) - defer Tester.Done() + Instance = integration.NewInstance(ctx) - CTX = Tester.WithAuthorization(ctx, integration.OrgOwner) - User = Tester.CreateHumanUser(CTX) - Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false) - Tester.RegisterUserPasskey(CTX, User.GetUserId()) - CTXLOGIN = Tester.WithAuthorization(ctx, integration.Login) - CTXIAM = Tester.WithAuthorization(ctx, integration.IAMOwner) + CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner) + User = Instance.CreateHumanUser(CTX) + Instance.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false) + Instance.RegisterUserPasskey(CTX, User.GetUserId()) + CTXLOGIN = Instance.WithAuthorization(ctx, integration.UserTypeLogin) + CTXIAM = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner) return m.Run() }()) } func Test_ZITADEL_API_missing_audience_scope(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -74,22 +73,22 @@ func Test_ZITADEL_API_missing_audience_scope(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) } func Test_ZITADEL_API_missing_authentication(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) - createResp, err := Tester.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{ + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) + createResp, err := Instance.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{ Checks: &session.Checks{ User: &session.CheckUser{ Search: &session.CheckUser_UserId{UserId: User.GetUserId()}, @@ -97,7 +96,7 @@ func Test_ZITADEL_API_missing_authentication(t *testing.T) { }, }) require.NoError(t, err) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -110,24 +109,24 @@ func Test_ZITADEL_API_missing_authentication(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) } func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) { - clientID, _ := createClient(t) - org := Tester.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_API_MISSING_MFA_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + clientID, _ := createClient(t, Instance) + org := Instance.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_API_MISSING_MFA_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) userID := org.CreatedAdmins[0].GetUserId() - Tester.SetUserPassword(CTXIAM, userID, integration.UserPassword, false) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreatePasswordSession(t, CTXLOGIN, userID, integration.UserPassword) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + Instance.SetUserPassword(CTXIAM, userID, integration.UserPassword, false) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreatePasswordSession(t, CTXLOGIN, userID, integration.UserPassword) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -140,20 +139,20 @@ func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertIDTokenClaims(t, tokens.IDTokenClaims, userID, armPassword, startTime, changeTime, sessionID) ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) // pre check if request would succeed - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, userID, myUserResp.GetUser().GetId()) // require MFA ctxOrg := metadata.AppendToOutgoingContext(CTXIAM, "x-zitadel-orgid", org.GetOrganizationId()) - _, err = Tester.Client.Mgmt.AddCustomLoginPolicy(ctxOrg, &mgmt.AddCustomLoginPolicyRequest{ + _, err = Instance.Client.Mgmt.AddCustomLoginPolicy(ctxOrg, &mgmt.AddCustomLoginPolicyRequest{ ForceMfa: true, }) require.NoError(t, err) @@ -164,23 +163,23 @@ func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) { retryDuration = time.Until(ctxDeadline) } require.EventuallyWithT(t, func(ttt *assert.CollectT) { - got, getErr := Tester.Client.Mgmt.GetLoginPolicy(ctxOrg, &mgmt.GetLoginPolicyRequest{}) + got, getErr := Instance.Client.Mgmt.GetLoginPolicy(ctxOrg, &mgmt.GetLoginPolicyRequest{}) assert.NoError(ttt, getErr) assert.False(ttt, got.GetPolicy().IsDefault) }, retryDuration, time.Millisecond*100, "timeout waiting for login policy") // now it must fail - myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) } func Test_ZITADEL_API_success(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -193,28 +192,28 @@ func Test_ZITADEL_API_success(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId()) } func Test_ZITADEL_API_glob_redirects(t *testing.T) { const redirectURI = "https://my-org-1yfnjl2xj-my-app.vercel.app/api/auth/callback/zitadel" - clientID, _ := createClientWithOpts(t, clientOpts{ + clientID, _ := createClientWithOpts(t, Instance, clientOpts{ redirectURI: "https://my-org-*-my-app.vercel.app/api/auth/callback/zitadel", logoutURI: "https://my-org-*-my-app.vercel.app/", devMode: true, }) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -227,23 +226,23 @@ func Test_ZITADEL_API_glob_redirects(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, false) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId()) } func Test_ZITADEL_API_inactive_access_token(t *testing.T) { - clientID, _ := createClient(t) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + clientID, _ := createClient(t, Instance) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -256,14 +255,14 @@ func Test_ZITADEL_API_inactive_access_token(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) // make sure token works ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId()) @@ -274,18 +273,18 @@ func Test_ZITADEL_API_inactive_access_token(t *testing.T) { // use invalidated token ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) } func Test_ZITADEL_API_terminated_session(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -298,14 +297,14 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) // make sure token works ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId()) @@ -316,13 +315,13 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) { // use token from terminated session ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) } func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) { - clientID, _ := createClient(t) + clientID, _ := createClient(t, Instance) tests := []struct { name string disable func(userID string) error @@ -330,32 +329,32 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) { { name: "deactivated", disable: func(userID string) error { - _, err := Tester.Client.UserV2.DeactivateUser(CTX, &user.DeactivateUserRequest{UserId: userID}) + _, err := Instance.Client.UserV2.DeactivateUser(CTX, &user.DeactivateUserRequest{UserId: userID}) return err }, }, { name: "locked", disable: func(userID string) error { - _, err := Tester.Client.UserV2.LockUser(CTX, &user.LockUserRequest{UserId: userID}) + _, err := Instance.Client.UserV2.LockUser(CTX, &user.LockUserRequest{UserId: userID}) return err }, }, { name: "deleted", disable: func(userID string) error { - _, err := Tester.Client.UserV2.DeleteUser(CTX, &user.DeleteUserRequest{UserId: userID}) + _, err := Instance.Client.UserV2.DeleteUser(CTX, &user.DeleteUserRequest{UserId: userID}) return err }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - disabledUser := Tester.CreateHumanUser(CTX) - Tester.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword, false) - authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) - sessionID, sessionToken, startTime, changeTime := Tester.CreatePasswordSession(t, CTXLOGIN, disabledUser.GetUserId(), integration.UserPassword) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + disabledUser := Instance.CreateHumanUser(CTX) + Instance.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword, false) + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) + sessionID, sessionToken, startTime, changeTime := Instance.CreatePasswordSession(t, CTXLOGIN, disabledUser.GetUserId(), integration.UserPassword) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -368,14 +367,14 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) { // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, disabledUser.GetUserId(), armPassword, startTime, changeTime, sessionID) // make sure token works ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.NoError(t, err) require.Equal(t, disabledUser.GetUserId(), myUserResp.GetUser().GetId()) @@ -385,15 +384,15 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) { // use token from deactivated user ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)) - myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) + myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{}) require.Error(t, err) require.Nil(t, myUserResp) }) } } -func createClient(t testing.TB) (clientID, projectID string) { - return createClientWithOpts(t, clientOpts{ +func createClient(t testing.TB, instance *integration.Instance) (clientID, projectID string) { + return createClientWithOpts(t, instance, clientOpts{ redirectURI: redirectURI, logoutURI: logoutRedirectURI, devMode: false, @@ -406,28 +405,30 @@ type clientOpts struct { devMode bool } -func createClientWithOpts(t testing.TB, opts clientOpts) (clientID, projectID string) { - project, err := Tester.CreateProject(CTX) +func createClientWithOpts(t testing.TB, instance *integration.Instance, opts clientOpts) (clientID, projectID string) { + ctx := instance.WithAuthorization(CTX, integration.UserTypeOrgOwner) + + project, err := instance.CreateProject(ctx) require.NoError(t, err) - app, err := Tester.CreateOIDCNativeClient(CTX, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode) + app, err := instance.CreateOIDCNativeClient(ctx, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode) require.NoError(t, err) return app.GetClientId(), project.GetId() } func createImplicitClient(t testing.TB) string { - app, err := Tester.CreateOIDCImplicitFlowClient(CTX, redirectURIImplicit) + app, err := Instance.CreateOIDCImplicitFlowClient(CTX, redirectURIImplicit) require.NoError(t, err) return app.GetClientId() } -func createAuthRequest(t testing.TB, clientID, redirectURI string, scope ...string) string { - redURL, err := Tester.CreateOIDCAuthRequest(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...) +func createAuthRequest(t testing.TB, instance *integration.Instance, clientID, redirectURI string, scope ...string) string { + redURL, err := instance.CreateOIDCAuthRequest(CTX, clientID, instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, scope...) require.NoError(t, err) return redURL } func createAuthRequestImplicit(t testing.TB, clientID, redirectURI string, scope ...string) string { - redURL, err := Tester.CreateOIDCAuthRequestImplicit(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...) + redURL, err := Instance.CreateOIDCAuthRequestImplicit(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, scope...) require.NoError(t, err) return redURL } @@ -437,5 +438,5 @@ func assertOIDCTime(t *testing.T, actual oidc.Time, expected time.Time) { } func assertOIDCTimeRange(t *testing.T, actual oidc.Time, expectedStart, expectedEnd time.Time) { - assert.WithinRange(t, actual.AsTime(), expectedStart.Add(-1*time.Second), expectedEnd.Add(1*time.Second)) + assert.WithinRange(t, actual.AsTime(), expectedStart.Add(-10*time.Second), expectedEnd.Add(10*time.Second)) } diff --git a/internal/api/oidc/server_integration_test.go b/internal/api/oidc/integration_test/server_test.go similarity index 92% rename from internal/api/oidc/server_integration_test.go rename to internal/api/oidc/integration_test/server_test.go index 8a0c8796fa..fcf9bfb65e 100644 --- a/internal/api/oidc/server_integration_test.go +++ b/internal/api/oidc/integration_test/server_test.go @@ -18,8 +18,10 @@ import ( ) func TestServer_RefreshToken_Status(t *testing.T) { - clientID, _ := createClient(t) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + t.Parallel() + + clientID, _ := createClient(t, Instance) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) tests := []struct { diff --git a/internal/api/oidc/token_client_credentials_integration_test.go b/internal/api/oidc/integration_test/token_client_credentials_test.go similarity index 80% rename from internal/api/oidc/token_client_credentials_integration_test.go rename to internal/api/oidc/integration_test/token_client_credentials_test.go index 21a1c4de75..5316202e31 100644 --- a/internal/api/oidc/token_client_credentials_integration_test.go +++ b/internal/api/oidc/integration_test/token_client_credentials_test.go @@ -19,7 +19,9 @@ import ( ) func TestServer_ClientCredentialsExchange(t *testing.T) { - machine, name, clientID, clientSecret, err := Tester.CreateOIDCCredentialsClient(CTX) + t.Parallel() + + machine, name, clientID, clientSecret, err := Instance.CreateOIDCCredentialsClient(CTX) require.NoError(t, err) type claims struct { @@ -57,7 +59,7 @@ func TestServer_ClientCredentialsExchange(t *testing.T) { name: "machine user without secret error", clientID: func() string { name := gofakeit.Username() - _, err := Tester.Client.Mgmt.AddMachineUser(CTX, &management.AddMachineUserRequest{ + _, err := Instance.Client.Mgmt.AddMachineUser(CTX, &management.AddMachineUserRequest{ Name: name, UserName: name, AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, @@ -99,14 +101,14 @@ func TestServer_ClientCredentialsExchange(t *testing.T) { clientSecret: clientSecret, scope: []string{ oidc.ScopeOpenID, - domain.OrgIDScope + Tester.Organisation.ID, - domain.OrgDomainPrimaryScope + Tester.Organisation.Domain, + domain.OrgIDScope + Instance.DefaultOrg.Id, + domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain, }, wantClaims: claims{ - resourceOwnerID: Tester.Organisation.ID, - resourceOwnerName: Tester.Organisation.Name, - resourceOwnerPrimaryDomain: Tester.Organisation.Domain, - orgDomain: Tester.Organisation.Domain, + resourceOwnerID: Instance.DefaultOrg.Id, + resourceOwnerName: Instance.DefaultOrg.Name, + resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain, + orgDomain: Instance.DefaultOrg.PrimaryDomain, }, }, { @@ -115,10 +117,10 @@ func TestServer_ClientCredentialsExchange(t *testing.T) { clientSecret: clientSecret, scope: []string{ oidc.ScopeOpenID, - domain.OrgDomainPrimaryScope + Tester.Organisation.Domain, + domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain, domain.OrgDomainPrimaryScope + "foo"}, wantClaims: claims{ - orgDomain: Tester.Organisation.Domain, + orgDomain: Instance.DefaultOrg.PrimaryDomain, }, }, { @@ -126,19 +128,19 @@ func TestServer_ClientCredentialsExchange(t *testing.T) { clientID: clientID, clientSecret: clientSecret, scope: []string{oidc.ScopeOpenID, - domain.OrgIDScope + Tester.Organisation.ID, + domain.OrgIDScope + Instance.DefaultOrg.Id, domain.OrgIDScope + "foo", }, wantClaims: claims{ - resourceOwnerID: Tester.Organisation.ID, - resourceOwnerName: Tester.Organisation.Name, - resourceOwnerPrimaryDomain: Tester.Organisation.Domain, + resourceOwnerID: Instance.DefaultOrg.Id, + resourceOwnerName: Instance.DefaultOrg.Name, + resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), tt.clientID, tt.clientSecret, redirectURI, tt.scope) + provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), tt.clientID, tt.clientSecret, redirectURI, tt.scope) require.NoError(t, err) tokens, err := rp.ClientCredentials(CTX, provider, nil) if tt.wantErr { diff --git a/internal/api/oidc/token_exchange_integration_test.go b/internal/api/oidc/integration_test/token_exchange_test.go similarity index 91% rename from internal/api/oidc/token_exchange_integration_test.go rename to internal/api/oidc/integration_test/token_exchange_test.go index b8b4b0bbfe..26c4475024 100644 --- a/internal/api/oidc/token_exchange_integration_test.go +++ b/internal/api/oidc/integration_test/token_exchange_test.go @@ -26,9 +26,9 @@ import ( ) func setTokenExchangeFeature(t *testing.T, value bool) { - iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner) + iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) - _, err := Tester.Client.FeatureV2.SetInstanceFeatures(iamCTX, &feature.SetInstanceFeaturesRequest{ + _, err := Instance.Client.FeatureV2.SetInstanceFeatures(iamCTX, &feature.SetInstanceFeaturesRequest{ OidcTokenExchange: proto.Bool(value), }) require.NoError(t, err) @@ -36,19 +36,19 @@ func setTokenExchangeFeature(t *testing.T, value bool) { } func resetFeatures(t *testing.T) { - iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner) - _, err := Tester.Client.FeatureV2.ResetInstanceFeatures(iamCTX, &feature.ResetInstanceFeaturesRequest{}) + iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + _, err := Instance.Client.FeatureV2.ResetInstanceFeatures(iamCTX, &feature.ResetInstanceFeaturesRequest{}) require.NoError(t, err) time.Sleep(time.Second) } func setImpersonationPolicy(t *testing.T, value bool) { - iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner) + iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) - policy, err := Tester.Client.Admin.GetSecurityPolicy(iamCTX, &admin.GetSecurityPolicyRequest{}) + policy, err := Instance.Client.Admin.GetSecurityPolicy(iamCTX, &admin.GetSecurityPolicyRequest{}) require.NoError(t, err) if policy.GetPolicy().GetEnableImpersonation() != value { - _, err = Tester.Client.Admin.SetSecurityPolicy(iamCTX, &admin.SetSecurityPolicyRequest{ + _, err = Instance.Client.Admin.SetSecurityPolicy(iamCTX, &admin.SetSecurityPolicyRequest{ EnableImpersonation: value, }) require.NoError(t, err) @@ -57,8 +57,8 @@ func setImpersonationPolicy(t *testing.T, value bool) { } func createMachineUserPATWithMembership(t *testing.T, roles ...string) (userID, pat string) { - iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner) - userID, pat, err := Tester.CreateMachineUserPATWithMembership(iamCTX, roles...) + iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + userID, pat, err := Instance.CreateMachineUserPATWithMembership(iamCTX, roles...) require.NoError(t, err) return userID, pat } @@ -112,16 +112,18 @@ func refreshTokenVerifier(ctx context.Context, provider rp.RelyingParty, subject } func TestServer_TokenExchange(t *testing.T) { + t.Parallel() + t.Cleanup(func() { resetFeatures(t) setImpersonationPolicy(t, false) }) - client, keyData, err := Tester.CreateOIDCTokenExchangeClient(CTX) + client, keyData, err := Instance.CreateOIDCTokenExchangeClient(CTX) require.NoError(t, err) signer, err := rp.SignerFromKeyFile(keyData)() require.NoError(t, err) - exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Tester.OIDCIssuer(), client.GetClientId(), signer) + exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Instance.OIDCIssuer(), client.GetClientId(), signer) require.NoError(t, err) time.Sleep(time.Second) @@ -137,9 +139,9 @@ func TestServer_TokenExchange(t *testing.T) { patScopes := oidc.SpaceDelimitedArray{"openid", "profile", "urn:zitadel:iam:user:metadata", "urn:zitadel:iam:user:resourceowner"} - relyingParty, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), client.GetClientId(), "", "", []string{"openid"}, rp.WithJWTProfile(rp.SignerFromKeyFile(keyData))) + relyingParty, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), client.GetClientId(), "", "", []string{"openid"}, rp.WithJWTProfile(rp.SignerFromKeyFile(keyData))) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyData) + resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyData) require.NoError(t, err) type settings struct { @@ -481,7 +483,7 @@ func TestServer_TokenExchange(t *testing.T) { token, err := crypto.Sign(&oidc.JWTTokenRequest{ Issuer: client.GetClientId(), Subject: User.GetUserId(), - Audience: oidc.Audience{Tester.OIDCIssuer()}, + Audience: oidc.Audience{Instance.OIDCIssuer()}, ExpiresAt: oidc.FromTime(time.Now().Add(time.Hour)), IssuedAt: oidc.FromTime(time.Now().Add(-time.Second)), }, signer) @@ -559,13 +561,13 @@ func TestServer_TokenExchange(t *testing.T) { // This test tries to call the zitadel API with an impersonated token, // which should fail. func TestImpersonation_API_Call(t *testing.T) { - client, keyData, err := Tester.CreateOIDCTokenExchangeClient(CTX) + client, keyData, err := Instance.CreateOIDCTokenExchangeClient(CTX) require.NoError(t, err) signer, err := rp.SignerFromKeyFile(keyData)() require.NoError(t, err) - exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Tester.OIDCIssuer(), client.GetClientId(), signer) + exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Instance.OIDCIssuer(), client.GetClientId(), signer) require.NoError(t, err) - resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyData) + resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyData) require.NoError(t, err) setTokenExchangeFeature(t, true) @@ -576,15 +578,15 @@ func TestImpersonation_API_Call(t *testing.T) { }) iamUserID, iamImpersonatorPAT := createMachineUserPATWithMembership(t, "IAM_ADMIN_IMPERSONATOR") - iamOwner := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.IAMOwner) + iamOwner := Instance.Users.Get(integration.UserTypeIAMOwner) // impersonating the IAM owner! resp, err := tokenexchange.ExchangeToken(CTX, exchanger, iamOwner.Token, oidc.AccessTokenType, iamImpersonatorPAT, oidc.AccessTokenType, nil, nil, nil, oidc.AccessTokenType) require.NoError(t, err) accessTokenVerifier(CTX, resourceServer, iamOwner.ID, iamUserID) - impersonatedCTX := Tester.WithAuthorizationToken(CTX, resp.AccessToken) - _, err = Tester.Client.Admin.GetAllowedLanguages(impersonatedCTX, &admin.GetAllowedLanguagesRequest{}) + impersonatedCTX := integration.WithAuthorizationToken(CTX, resp.AccessToken) + _, err = Instance.Client.Admin.GetAllowedLanguages(impersonatedCTX, &admin.GetAllowedLanguagesRequest{}) status := status.Convert(err) assert.Equal(t, codes.PermissionDenied, status.Code()) assert.Equal(t, "Errors.TokenExchange.Token.NotForAPI (APP-Shi0J)", status.Message()) diff --git a/internal/api/oidc/token_jwt_profile_integration_test.go b/internal/api/oidc/integration_test/token_jwt_profile_test.go similarity index 76% rename from internal/api/oidc/token_jwt_profile_integration_test.go rename to internal/api/oidc/integration_test/token_jwt_profile_test.go index 0ad8d76da2..24fad41a2b 100644 --- a/internal/api/oidc/token_jwt_profile_integration_test.go +++ b/internal/api/oidc/integration_test/token_jwt_profile_test.go @@ -17,7 +17,9 @@ import ( ) func TestServer_JWTProfile(t *testing.T) { - user, name, keyData, err := Tester.CreateOIDCJWTProfileClient(CTX) + t.Parallel() + + user, name, keyData, err := Instance.CreateOIDCJWTProfileClient(CTX) require.NoError(t, err) type claims struct { @@ -56,14 +58,14 @@ func TestServer_JWTProfile(t *testing.T) { keyData: keyData, scope: []string{ oidc.ScopeOpenID, - domain.OrgIDScope + Tester.Organisation.ID, - domain.OrgDomainPrimaryScope + Tester.Organisation.Domain, + domain.OrgIDScope + Instance.DefaultOrg.Id, + domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain, }, wantClaims: claims{ - resourceOwnerID: Tester.Organisation.ID, - resourceOwnerName: Tester.Organisation.Name, - resourceOwnerPrimaryDomain: Tester.Organisation.Domain, - orgDomain: Tester.Organisation.Domain, + resourceOwnerID: Instance.DefaultOrg.Id, + resourceOwnerName: Instance.DefaultOrg.Name, + resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain, + orgDomain: Instance.DefaultOrg.PrimaryDomain, }, }, { @@ -71,29 +73,29 @@ func TestServer_JWTProfile(t *testing.T) { keyData: keyData, scope: []string{ oidc.ScopeOpenID, - domain.OrgDomainPrimaryScope + Tester.Organisation.Domain, + domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain, domain.OrgDomainPrimaryScope + "foo"}, wantClaims: claims{ - orgDomain: Tester.Organisation.Domain, + orgDomain: Instance.DefaultOrg.PrimaryDomain, }, }, { name: "invalid org id filtered", keyData: keyData, scope: []string{oidc.ScopeOpenID, - domain.OrgIDScope + Tester.Organisation.ID, + domain.OrgIDScope + Instance.DefaultOrg.Id, domain.OrgIDScope + "foo", }, wantClaims: claims{ - resourceOwnerID: Tester.Organisation.ID, - resourceOwnerName: Tester.Organisation.Name, - resourceOwnerPrimaryDomain: Tester.Organisation.Domain, + resourceOwnerID: Instance.DefaultOrg.Id, + resourceOwnerName: Instance.DefaultOrg.Name, + resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tokenSource, err := profile.NewJWTProfileTokenSourceFromKeyFileData(CTX, Tester.OIDCIssuer(), tt.keyData, tt.scope) + tokenSource, err := profile.NewJWTProfileTokenSourceFromKeyFileData(CTX, Instance.OIDCIssuer(), tt.keyData, tt.scope) require.NoError(t, err) tokens, err := tokenSource.TokenCtx(CTX) @@ -104,7 +106,7 @@ func TestServer_JWTProfile(t *testing.T) { require.NoError(t, err) require.NotNil(t, tokens) - provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), "", "", redirectURI, tt.scope) + provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), "", "", redirectURI, tt.scope) require.NoError(t, err) userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, oidc.BearerToken, user.GetUserId(), provider) require.NoError(t, err) diff --git a/internal/api/oidc/userinfo_integration_test.go b/internal/api/oidc/integration_test/userinfo_test.go similarity index 82% rename from internal/api/oidc/userinfo_integration_test.go rename to internal/api/oidc/integration_test/userinfo_test.go index e938078078..c2ad3be3ec 100644 --- a/internal/api/oidc/userinfo_integration_test.go +++ b/internal/api/oidc/integration_test/userinfo_test.go @@ -27,9 +27,9 @@ import ( // userinfo integration test against a matrix of different feature flags. // This ensure that the response of the different implementations remains the same. func TestServer_UserInfo(t *testing.T) { - iamOwnerCTX := Tester.WithAuthorization(CTX, integration.IAMOwner) + iamOwnerCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) t.Cleanup(func() { - _, err := Tester.Client.FeatureV2.ResetInstanceFeatures(iamOwnerCTX, &feature.ResetInstanceFeaturesRequest{}) + _, err := Instance.Client.FeatureV2.ResetInstanceFeatures(iamOwnerCTX, &feature.ResetInstanceFeaturesRequest{}) require.NoError(t, err) }) tests := []struct { @@ -67,7 +67,7 @@ func TestServer_UserInfo(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := Tester.Client.FeatureV2.SetInstanceFeatures(iamOwnerCTX, &feature.SetInstanceFeaturesRequest{ + _, err := Instance.Client.FeatureV2.SetInstanceFeatures(iamOwnerCTX, &feature.SetInstanceFeaturesRequest{ OidcLegacyIntrospection: &tt.legacy, OidcTriggerIntrospectionProjections: &tt.trigger, WebKey: &tt.webKey, @@ -86,7 +86,7 @@ func testServer_UserInfo(t *testing.T) { roleBar = "bar" ) - clientID, projectID := createClient(t) + clientID, projectID := createClient(t, Instance) addProjectRolesGrants(t, User.GetUserId(), projectID, roleFoo, roleBar) tests := []struct { @@ -133,21 +133,21 @@ func testServer_UserInfo(t *testing.T) { { name: "project role assertion", prepare: func(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] { - _, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ + _, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ Id: projectID, Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), ProjectRoleAssertion: true, }) require.NoError(t, err) t.Cleanup(func() { - _, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ + _, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ Id: projectID, Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), ProjectRoleAssertion: false, }) require.NoError(t, err) }) - resp, err := Tester.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID}) + resp, err := Instance.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID}) require.NoError(t, err) require.True(t, resp.GetProject().GetProjectRoleAssertion(), "project role assertion") @@ -157,7 +157,7 @@ func testServer_UserInfo(t *testing.T) { assertions: []func(*testing.T, *oidc.UserInfo){ assertUserinfo, func(t *testing.T, ui *oidc.UserInfo) { - assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo, roleBar}, []string{Tester.Organisation.ID}) + assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo, roleBar}, []string{Instance.DefaultOrg.Id}) }, }, }, @@ -170,7 +170,7 @@ func testServer_UserInfo(t *testing.T) { assertions: []func(*testing.T, *oidc.UserInfo){ assertUserinfo, func(t *testing.T, ui *oidc.UserInfo) { - assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Tester.Organisation.ID}) + assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Instance.DefaultOrg.Id}) }, }, }, @@ -184,14 +184,14 @@ func testServer_UserInfo(t *testing.T) { assertions: []func(*testing.T, *oidc.UserInfo){ assertUserinfo, func(t *testing.T, ui *oidc.UserInfo) { - assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Tester.Organisation.ID}) + assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Instance.DefaultOrg.Id}) }, }, }, { name: "PAT", prepare: func(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] { - user := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.OrgOwner) + user := Instance.Users.Get(integration.UserTypeOrgOwner) return &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ AccessToken: user.Token, @@ -206,11 +206,8 @@ func testServer_UserInfo(t *testing.T) { }, assertions: []func(*testing.T, *oidc.UserInfo){ func(t *testing.T, ui *oidc.UserInfo) { - user := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.OrgOwner) + user := Instance.Users.Get(integration.UserTypeOrgOwner) assert.Equal(t, user.ID, ui.Subject) - assert.Equal(t, user.PreferredLoginName, ui.PreferredUsername) - assert.Equal(t, user.Machine.Name, ui.Name) - assert.Equal(t, user.ResourceOwner, ui.Claims[oidc_api.ClaimResourceOwnerID]) assert.NotEmpty(t, ui.Claims[oidc_api.ClaimResourceOwnerName]) assert.NotEmpty(t, ui.Claims[oidc_api.ClaimResourceOwnerPrimaryDomain]) }, @@ -220,7 +217,7 @@ func testServer_UserInfo(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tokens := tt.prepare(t, clientID, tt.scope) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider) if tt.wantErr { @@ -242,17 +239,17 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) { roleFoo = "foo" roleBar = "bar" ) - clientID, projectID := createClient(t) + clientID, projectID := createClient(t, Instance) addProjectRolesGrants(t, User.GetUserId(), projectID, roleFoo, roleBar) grantedOrgID := addProjectOrgGrant(t, User.GetUserId(), projectID, roleFoo, roleBar) - _, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ + _, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{ Id: projectID, Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), ProjectRoleAssertion: true, }) require.NoError(t, err) - resp, err := Tester.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID}) + resp, err := Instance.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID}) require.NoError(t, err) require.True(t, resp.GetProject().GetProjectRoleAssertion(), "project role assertion") @@ -266,7 +263,7 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) { scope: []string{ oidc.ScopeOpenID, oidc.ScopeOfflineAccess, }, - wantRoleOrgIDs: []string{Tester.Organisation.ID, grantedOrgID}, + wantRoleOrgIDs: []string{Instance.DefaultOrg.Id, grantedOrgID}, }, { name: "only granted org", @@ -279,24 +276,24 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) { name: "only own org", scope: []string{ oidc.ScopeOpenID, oidc.ScopeOfflineAccess, - domain.OrgRoleIDScope + Tester.Organisation.ID, + domain.OrgRoleIDScope + Instance.DefaultOrg.Id, }, - wantRoleOrgIDs: []string{Tester.Organisation.ID}, + wantRoleOrgIDs: []string{Instance.DefaultOrg.Id}, }, { name: "request both orgs", scope: []string{ oidc.ScopeOpenID, oidc.ScopeOfflineAccess, - domain.OrgRoleIDScope + Tester.Organisation.ID, + domain.OrgRoleIDScope + Instance.DefaultOrg.Id, domain.OrgRoleIDScope + grantedOrgID, }, - wantRoleOrgIDs: []string{Tester.Organisation.ID, grantedOrgID}, + wantRoleOrgIDs: []string{Instance.DefaultOrg.Id, grantedOrgID}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tokens := getTokens(t, clientID, tt.scope) - provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI) + provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI) require.NoError(t, err) userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider) require.NoError(t, err) @@ -312,10 +309,10 @@ func TestServer_UserInfo_Issue6662(t *testing.T) { roleBar = "bar" ) - project, err := Tester.CreateProject(CTX) + project, err := Instance.CreateProject(CTX) projectID := project.GetId() require.NoError(t, err) - user, _, clientID, clientSecret, err := Tester.CreateOIDCCredentialsClient(CTX) + user, _, clientID, clientSecret, err := Instance.CreateOIDCCredentialsClient(CTX) require.NoError(t, err) addProjectRolesGrants(t, user.GetUserId(), projectID, roleFoo, roleBar) @@ -324,14 +321,14 @@ func TestServer_UserInfo_Issue6662(t *testing.T) { domain.ProjectIDScope + projectID + domain.AudSuffix, } - provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), clientID, clientSecret, redirectURI, scope) + provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), clientID, clientSecret, redirectURI, scope) require.NoError(t, err) tokens, err := rp.ClientCredentials(CTX, provider, nil) require.NoError(t, err) userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, user.GetUserId(), provider) require.NoError(t, err) - assertProjectRoleClaims(t, projectID, userinfo.Claims, false, []string{roleFoo}, []string{Tester.Organisation.ID}) + assertProjectRoleClaims(t, projectID, userinfo.Claims, false, []string{roleFoo}, []string{Instance.DefaultOrg.Id}) } func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...string) { @@ -343,12 +340,12 @@ func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...stri DisplayName: role, } } - _, err := Tester.Client.Mgmt.BulkAddProjectRoles(CTX, &management.BulkAddProjectRolesRequest{ + _, err := Instance.Client.Mgmt.BulkAddProjectRoles(CTX, &management.BulkAddProjectRolesRequest{ ProjectId: projectID, Roles: bulkRoles, }) require.NoError(t, err) - _, err = Tester.Client.Mgmt.AddUserGrant(CTX, &management.AddUserGrantRequest{ + _, err = Instance.Client.Mgmt.AddUserGrant(CTX, &management.AddUserGrantRequest{ UserId: userID, ProjectId: projectID, RoleKeys: roles, @@ -359,8 +356,8 @@ func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...stri // addProjectOrgGrant adds a new organization which will be granted on the projectID with the specified roles. // The userID will be granted in the new organization to the project with the same roles. func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string) (grantedOrgID string) { - grantedOrg := Tester.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_GRANTED_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) - projectGrant, err := Tester.Client.Mgmt.AddProjectGrant(CTX, &management.AddProjectGrantRequest{ + grantedOrg := Instance.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_GRANTED_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())) + projectGrant, err := Instance.Client.Mgmt.AddProjectGrant(CTX, &management.AddProjectGrantRequest{ ProjectId: projectID, GrantedOrgId: grantedOrg.GetOrganizationId(), RoleKeys: roles, @@ -368,7 +365,7 @@ func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string) require.NoError(t, err) ctxOrg := metadata.AppendToOutgoingContext(CTXIAM, "x-zitadel-orgid", grantedOrg.GetOrganizationId()) - _, err = Tester.Client.Mgmt.AddUserGrant(ctxOrg, &management.AddUserGrantRequest{ + _, err = Instance.Client.Mgmt.AddUserGrant(ctxOrg, &management.AddUserGrantRequest{ UserId: userID, ProjectId: projectID, ProjectGrantId: projectGrant.GetGrantId(), @@ -379,9 +376,9 @@ func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string) } func getTokens(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] { - authRequestID := createAuthRequest(t, clientID, redirectURI, scope...) - sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) - linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ + authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, scope...) + sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId()) + linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_pb.CreateCallbackRequest_Session{ Session: &oidc_pb.Session{ @@ -394,7 +391,7 @@ func getTokens(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc // code exchange code := assertCodeResponse(t, linkResp.GetCallbackUrl()) - tokens, err := exchangeTokens(t, clientID, code, redirectURI) + tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI) require.NoError(t, err) assertTokens(t, tokens, true) assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID) diff --git a/internal/api/oidc/server_test.go b/internal/api/oidc/server_test.go index 47f24fcdee..76d073151a 100644 --- a/internal/api/oidc/server_test.go +++ b/internal/api/oidc/server_test.go @@ -7,9 +7,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/oidc/v3/pkg/op" + "golang.org/x/text/language" + "github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/feature" - "golang.org/x/text/language" ) func TestServer_createDiscoveryConfig(t *testing.T) { diff --git a/internal/command/org_idp_test.go b/internal/command/org_idp_test.go index e1fa43e879..b2b4632cf6 100644 --- a/internal/command/org_idp_test.go +++ b/internal/command/org_idp_test.go @@ -21,7 +21,7 @@ import ( "github.com/zitadel/zitadel/internal/zerrors" ) -func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) { +func TestCommandSide_AddOrgGenericOAuthProvider(t *testing.T) { type fields struct { eventstore func(*testing.T) *eventstore.Eventstore idGenerator id.Generator diff --git a/internal/integration/assert.go b/internal/integration/assert.go index b3e63fd29e..3c5fadb373 100644 --- a/internal/integration/assert.go +++ b/internal/integration/assert.go @@ -50,7 +50,7 @@ type ResourceListDetailsMsg interface { // If the change date is populated, it is checked with a tolerance of 1 minute around Now. // // The resource owner is compared with expected. -func AssertDetails[D Details, M DetailsMsg[D]](t testing.TB, expected, actual M) { +func AssertDetails[D Details, M DetailsMsg[D]](t assert.TestingT, expected, actual M) { wantDetails, gotDetails := expected.GetDetails(), actual.GetDetails() var nilDetails D if wantDetails == nilDetails { @@ -69,7 +69,7 @@ func AssertDetails[D Details, M DetailsMsg[D]](t testing.TB, expected, actual M) assert.Equal(t, wantDetails.GetResourceOwner(), gotDetails.GetResourceOwner()) } -func AssertResourceDetails(t testing.TB, expected *resources_object.Details, actual *resources_object.Details) { +func AssertResourceDetails(t assert.TestingT, expected *resources_object.Details, actual *resources_object.Details) { if expected.GetChanged() != nil { wantChangeDate := time.Now() gotChangeDate := actual.GetChanged().AsTime() @@ -87,7 +87,7 @@ func AssertResourceDetails(t testing.TB, expected *resources_object.Details, act } } -func AssertListDetails[L ListDetails, D ListDetailsMsg[L]](t testing.TB, expected, actual D) { +func AssertListDetails[L ListDetails, D ListDetailsMsg[L]](t assert.TestingT, expected, actual D) { wantDetails, gotDetails := expected.GetDetails(), actual.GetDetails() var nilDetails L if wantDetails == nilDetails { @@ -99,11 +99,11 @@ func AssertListDetails[L ListDetails, D ListDetailsMsg[L]](t testing.TB, expecte if wantDetails.GetTimestamp() != nil { gotCD := gotDetails.GetTimestamp().AsTime() wantCD := time.Now() - assert.WithinRange(t, gotCD, wantCD.Add(-time.Minute), wantCD.Add(time.Minute)) + assert.WithinRange(t, gotCD, wantCD.Add(-10*time.Minute), wantCD.Add(time.Minute)) } } -func AssertResourceListDetails[D ResourceListDetailsMsg](t testing.TB, expected, actual D) { +func AssertResourceListDetails[D ResourceListDetailsMsg](t assert.TestingT, expected, actual D) { wantDetails, gotDetails := expected.GetDetails(), actual.GetDetails() if wantDetails == nil { assert.Nil(t, gotDetails) @@ -116,7 +116,7 @@ func AssertResourceListDetails[D ResourceListDetailsMsg](t testing.TB, expected, if wantDetails.GetTimestamp() != nil { gotCD := gotDetails.GetTimestamp().AsTime() wantCD := time.Now() - assert.WithinRange(t, gotCD, wantCD.Add(-time.Minute), wantCD.Add(time.Minute)) + assert.WithinRange(t, gotCD, wantCD.Add(-10*time.Minute), wantCD.Add(time.Minute)) } } diff --git a/internal/integration/client.go b/internal/integration/client.go index ed5f0620c4..404ec0162b 100644 --- a/internal/integration/client.go +++ b/internal/integration/client.go @@ -6,26 +6,17 @@ import ( "testing" "time" - crewjam_saml "github.com/crewjam/saml" + "github.com/brianvoe/gofakeit/v6" "github.com/muhlemmer/gu" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/zitadel/logging" - "github.com/zitadel/oidc/v3/pkg/oidc" - "golang.org/x/oauth2" - "golang.org/x/text/language" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/structpb" - "github.com/zitadel/zitadel/internal/api/authz" - "github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/domain" - "github.com/zitadel/zitadel/internal/idp/providers/ldap" - openid "github.com/zitadel/zitadel/internal/idp/providers/oidc" - "github.com/zitadel/zitadel/internal/idp/providers/saml" - idp_rp "github.com/zitadel/zitadel/internal/repository/idp" "github.com/zitadel/zitadel/pkg/grpc/admin" "github.com/zitadel/zitadel/pkg/grpc/auth" "github.com/zitadel/zitadel/pkg/grpc/feature/v2" @@ -37,7 +28,7 @@ import ( object_v3alpha "github.com/zitadel/zitadel/pkg/grpc/object/v3alpha" oidc_pb "github.com/zitadel/zitadel/pkg/grpc/oidc/v2" oidc_pb_v2beta "github.com/zitadel/zitadel/pkg/grpc/oidc/v2beta" - "github.com/zitadel/zitadel/pkg/grpc/org/v2" + org "github.com/zitadel/zitadel/pkg/grpc/org/v2" org_v2beta "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" action "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha" user_v3alpha "github.com/zitadel/zitadel/pkg/grpc/resources/user/v3alpha" @@ -47,7 +38,6 @@ import ( session_v2beta "github.com/zitadel/zitadel/pkg/grpc/session/v2beta" "github.com/zitadel/zitadel/pkg/grpc/settings/v2" settings_v2beta "github.com/zitadel/zitadel/pkg/grpc/settings/v2beta" - "github.com/zitadel/zitadel/pkg/grpc/system" user_pb "github.com/zitadel/zitadel/pkg/grpc/user" user_v2 "github.com/zitadel/zitadel/pkg/grpc/user/v2" user_v2beta "github.com/zitadel/zitadel/pkg/grpc/user/v2beta" @@ -68,7 +58,6 @@ type Client struct { OIDCv2 oidc_pb.OIDCServiceClient OrgV2beta org_v2beta.OrganizationServiceClient OrgV2 org.OrganizationServiceClient - System system.SystemServiceClient ActionV3Alpha action.ZITADELActionsClient FeatureV2beta feature_v2beta.FeatureServiceClient FeatureV2 feature.FeatureServiceClient @@ -78,8 +67,14 @@ type Client struct { UserV3Alpha user_v3alpha.ZITADELUsersClient } -func newClient(cc *grpc.ClientConn) Client { - return Client{ +func newClient(ctx context.Context, target string) (*Client, error) { + cc, err := grpc.NewClient(target, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + if err != nil { + return nil, err + } + client := &Client{ CC: cc, Admin: admin.NewAdminServiceClient(cc), Mgmt: mgmt.NewManagementServiceClient(cc), @@ -94,7 +89,6 @@ func newClient(cc *grpc.ClientConn) Client { OIDCv2: oidc_pb.NewOIDCServiceClient(cc), OrgV2beta: org_v2beta.NewOrganizationServiceClient(cc), OrgV2: org.NewOrganizationServiceClient(cc), - System: system.NewSystemServiceClient(cc), ActionV3Alpha: action.NewZITADELActionsClient(cc), FeatureV2beta: feature_v2beta.NewFeatureServiceClient(cc), FeatureV2: feature.NewFeatureServiceClient(cc), @@ -103,60 +97,38 @@ func newClient(cc *grpc.ClientConn) Client { IDPv2: idp_pb.NewIdentityProviderServiceClient(cc), UserV3Alpha: user_v3alpha.NewZITADELUsersClient(cc), } + return client, client.pollHealth(ctx) } -func (t *Tester) UseIsolatedInstance(tt *testing.T, iamOwnerCtx, systemCtx context.Context) (primaryDomain, instanceId, adminID string, authenticatedIamOwnerCtx context.Context) { - primaryDomain = RandString(5) + ".integration.localhost" - instance, err := t.Client.System.CreateInstance(systemCtx, &system.CreateInstanceRequest{ - InstanceName: "testinstance", - CustomDomain: primaryDomain, - Owner: &system.CreateInstanceRequest_Machine_{ - Machine: &system.CreateInstanceRequest_Machine{ - UserName: "owner", - Name: "owner", - PersonalAccessToken: &system.CreateInstanceRequest_PersonalAccessToken{}, - }, - }, - }) - require.NoError(tt, err) - t.createClientConn(iamOwnerCtx, fmt.Sprintf("%s:%d", primaryDomain, t.Config.Port)) - instanceId = instance.GetInstanceId() - owner, err := t.Queries.GetUserByLoginName(authz.WithInstanceID(iamOwnerCtx, instanceId), true, "owner@"+primaryDomain) - require.NoError(tt, err) - t.Users.Set(instanceId, IAMOwner, &User{ - User: owner, - Token: instance.GetPat(), - }) - newCtx := t.WithInstanceAuthorization(iamOwnerCtx, IAMOwner, instanceId) - var adminUser *mgmt.ImportHumanUserResponse - // the following serves two purposes: - // 1. it ensures that the instance is ready to be used - // 2. it enables a normal login with the default admin user credentials - require.EventuallyWithT(tt, func(collectT *assert.CollectT) { - var importErr error - adminUser, importErr = t.Client.Mgmt.ImportHumanUser(newCtx, &mgmt.ImportHumanUserRequest{ - UserName: "zitadel-admin@zitadel.localhost", - Email: &mgmt.ImportHumanUserRequest_Email{ - Email: "zitadel-admin@zitadel.localhost", - IsEmailVerified: true, - }, - Password: "Password1!", - Profile: &mgmt.ImportHumanUserRequest_Profile{ - FirstName: "hodor", - LastName: "hodor", - NickName: "hodor", - }, - }) - assert.NoError(collectT, importErr) - }, 2*time.Minute, 100*time.Millisecond, "instance not ready") - return primaryDomain, instanceId, adminUser.GetUserId(), t.updateInstanceAndOrg(newCtx, fmt.Sprintf("%s:%d", primaryDomain, t.Config.ExternalPort)) +// pollHealth waits until a healthy status is reported. +func (c *Client) pollHealth(ctx context.Context) (err error) { + for { + err = func(ctx context.Context) error { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := c.Admin.Healthz(ctx, &admin.HealthzRequest{}) + return err + }(ctx) + if err == nil { + return nil + } + logging.WithError(err).Debug("poll healthz") + + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(time.Second): + continue + } + } } -func (s *Tester) CreateHumanUser(ctx context.Context) *user_v2.AddHumanUserResponse { - resp, err := s.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ +func (i *Instance) CreateHumanUser(ctx context.Context) *user_v2.AddHumanUserResponse { + resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: s.Organisation.ID, + OrgId: i.DefaultOrg.GetId(), }, }, Profile: &user_v2.SetHumanProfile{ @@ -178,15 +150,15 @@ func (s *Tester) CreateHumanUser(ctx context.Context) *user_v2.AddHumanUserRespo }, }, }) - logging.OnError(err).Fatal("create human user") + logging.OnError(err).Panic("create human user") return resp } -func (s *Tester) CreateHumanUserNoPhone(ctx context.Context) *user_v2.AddHumanUserResponse { - resp, err := s.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ +func (i *Instance) CreateHumanUserNoPhone(ctx context.Context) *user_v2.AddHumanUserResponse { + resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: s.Organisation.ID, + OrgId: i.DefaultOrg.GetId(), }, }, Profile: &user_v2.SetHumanProfile{ @@ -202,15 +174,15 @@ func (s *Tester) CreateHumanUserNoPhone(ctx context.Context) *user_v2.AddHumanUs }, }, }) - logging.OnError(err).Fatal("create human user") + logging.OnError(err).Panic("create human user") return resp } -func (s *Tester) CreateHumanUserWithTOTP(ctx context.Context, secret string) *user_v2.AddHumanUserResponse { - resp, err := s.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ +func (i *Instance) CreateHumanUserWithTOTP(ctx context.Context, secret string) *user_v2.AddHumanUserResponse { + resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ - OrgId: s.Organisation.ID, + OrgId: i.DefaultOrg.GetId(), }, }, Profile: &user_v2.SetHumanProfile{ @@ -233,12 +205,12 @@ func (s *Tester) CreateHumanUserWithTOTP(ctx context.Context, secret string) *us }, TotpSecret: gu.Ptr(secret), }) - logging.OnError(err).Fatal("create human user") + logging.OnError(err).Panic("create human user") return resp } -func (s *Tester) CreateOrganization(ctx context.Context, name, adminEmail string) *org.AddOrganizationResponse { - resp, err := s.Client.OrgV2.AddOrganization(ctx, &org.AddOrganizationRequest{ +func (i *Instance) CreateOrganization(ctx context.Context, name, adminEmail string) *org.AddOrganizationResponse { + resp, err := i.Client.OrgV2.AddOrganization(ctx, &org.AddOrganizationRequest{ Name: name, Admins: []*org.AddOrganizationRequest_Admin{ { @@ -259,12 +231,12 @@ func (s *Tester) CreateOrganization(ctx context.Context, name, adminEmail string }, }, }) - logging.OnError(err).Fatal("create org") + logging.OnError(err).Panic("create org") return resp } -func (s *Tester) DeactivateOrganization(ctx context.Context, orgID string) *mgmt.DeactivateOrgResponse { - resp, err := s.Client.Mgmt.DeactivateOrg( +func (i *Instance) DeactivateOrganization(ctx context.Context, orgID string) *mgmt.DeactivateOrgResponse { + resp, err := i.Client.Mgmt.DeactivateOrg( SetOrgID(ctx, orgID), &mgmt.DeactivateOrgRequest{}, ) @@ -281,8 +253,8 @@ func SetOrgID(ctx context.Context, orgID string) context.Context { return metadata.NewOutgoingContext(ctx, md) } -func (s *Tester) CreateOrganizationWithUserID(ctx context.Context, name, userID string) *org.AddOrganizationResponse { - resp, err := s.Client.OrgV2.AddOrganization(ctx, &org.AddOrganizationRequest{ +func (i *Instance) CreateOrganizationWithUserID(ctx context.Context, name, userID string) *org.AddOrganizationResponse { + resp, err := i.Client.OrgV2.AddOrganization(ctx, &org.AddOrganizationRequest{ Name: name, Admins: []*org.AddOrganizationRequest_Admin{ { @@ -296,8 +268,8 @@ func (s *Tester) CreateOrganizationWithUserID(ctx context.Context, name, userID return resp } -func (s *Tester) CreateHumanUserVerified(ctx context.Context, org, email string) *user_v2.AddHumanUserResponse { - resp, err := s.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ +func (i *Instance) CreateHumanUserVerified(ctx context.Context, org, email string) *user_v2.AddHumanUserResponse { + resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ Organization: &object.Organization{ Org: &object.Organization_OrgId{ OrgId: org, @@ -323,23 +295,23 @@ func (s *Tester) CreateHumanUserVerified(ctx context.Context, org, email string) }, }, }) - logging.OnError(err).Fatal("create human user") + logging.OnError(err).Panic("create human user") return resp } -func (s *Tester) CreateMachineUser(ctx context.Context) *mgmt.AddMachineUserResponse { - resp, err := s.Client.Mgmt.AddMachineUser(ctx, &mgmt.AddMachineUserRequest{ +func (i *Instance) CreateMachineUser(ctx context.Context) *mgmt.AddMachineUserResponse { + resp, err := i.Client.Mgmt.AddMachineUser(ctx, &mgmt.AddMachineUserRequest{ UserName: fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()), Name: "Mickey", Description: "Mickey Mouse", AccessTokenType: user_pb.AccessTokenType_ACCESS_TOKEN_TYPE_BEARER, }) - logging.OnError(err).Fatal("create human user") + logging.OnError(err).Panic("create human user") return resp } -func (s *Tester) CreateUserIDPlink(ctx context.Context, userID, externalID, idpID, username string) *user_v2.AddIDPLinkResponse { - resp, err := s.Client.UserV2.AddIDPLink( +func (i *Instance) CreateUserIDPlink(ctx context.Context, userID, externalID, idpID, username string) (*user_v2.AddIDPLinkResponse, error) { + return i.Client.UserV2.AddIDPLink( ctx, &user_v2.AddIDPLinkRequest{ UserId: userID, @@ -350,67 +322,65 @@ func (s *Tester) CreateUserIDPlink(ctx context.Context, userID, externalID, idpI }, }, ) - logging.OnError(err).Fatal("create human user link") - return resp } -func (s *Tester) RegisterUserPasskey(ctx context.Context, userID string) { - reg, err := s.Client.UserV2.CreatePasskeyRegistrationLink(ctx, &user_v2.CreatePasskeyRegistrationLinkRequest{ +func (i *Instance) RegisterUserPasskey(ctx context.Context, userID string) { + reg, err := i.Client.UserV2.CreatePasskeyRegistrationLink(ctx, &user_v2.CreatePasskeyRegistrationLinkRequest{ UserId: userID, Medium: &user_v2.CreatePasskeyRegistrationLinkRequest_ReturnCode{}, }) - logging.OnError(err).Fatal("create user passkey") + logging.OnError(err).Panic("create user passkey") - pkr, err := s.Client.UserV2.RegisterPasskey(ctx, &user_v2.RegisterPasskeyRequest{ + pkr, err := i.Client.UserV2.RegisterPasskey(ctx, &user_v2.RegisterPasskeyRequest{ UserId: userID, Code: reg.GetCode(), - Domain: s.Config.ExternalDomain, + Domain: i.Domain, }) - logging.OnError(err).Fatal("create user passkey") - attestationResponse, err := s.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) - logging.OnError(err).Fatal("create user passkey") + logging.OnError(err).Panic("create user passkey") + attestationResponse, err := i.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + logging.OnError(err).Panic("create user passkey") - _, err = s.Client.UserV2.VerifyPasskeyRegistration(ctx, &user_v2.VerifyPasskeyRegistrationRequest{ + _, err = i.Client.UserV2.VerifyPasskeyRegistration(ctx, &user_v2.VerifyPasskeyRegistrationRequest{ UserId: userID, PasskeyId: pkr.GetPasskeyId(), PublicKeyCredential: attestationResponse, PasskeyName: "nice name", }) - logging.OnError(err).Fatal("create user passkey") + logging.OnError(err).Panic("create user passkey") } -func (s *Tester) RegisterUserU2F(ctx context.Context, userID string) { - pkr, err := s.Client.UserV2.RegisterU2F(ctx, &user_v2.RegisterU2FRequest{ +func (i *Instance) RegisterUserU2F(ctx context.Context, userID string) { + pkr, err := i.Client.UserV2.RegisterU2F(ctx, &user_v2.RegisterU2FRequest{ UserId: userID, - Domain: s.Config.ExternalDomain, + Domain: i.Domain, }) - logging.OnError(err).Fatal("create user u2f") - attestationResponse, err := s.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) - logging.OnError(err).Fatal("create user u2f") + logging.OnError(err).Panic("create user u2f") + attestationResponse, err := i.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions()) + logging.OnError(err).Panic("create user u2f") - _, err = s.Client.UserV2.VerifyU2FRegistration(ctx, &user_v2.VerifyU2FRegistrationRequest{ + _, err = i.Client.UserV2.VerifyU2FRegistration(ctx, &user_v2.VerifyU2FRegistrationRequest{ UserId: userID, U2FId: pkr.GetU2FId(), PublicKeyCredential: attestationResponse, TokenName: "nice name", }) - logging.OnError(err).Fatal("create user u2f") + logging.OnError(err).Panic("create user u2f") } -func (s *Tester) SetUserPassword(ctx context.Context, userID, password string, changeRequired bool) *object.Details { - resp, err := s.Client.UserV2.SetPassword(ctx, &user_v2.SetPasswordRequest{ +func (i *Instance) SetUserPassword(ctx context.Context, userID, password string, changeRequired bool) *object.Details { + resp, err := i.Client.UserV2.SetPassword(ctx, &user_v2.SetPasswordRequest{ UserId: userID, NewPassword: &user_v2.Password{ Password: password, ChangeRequired: changeRequired, }, }) - logging.OnError(err).Fatal("set user password") + logging.OnError(err).Panic("set user password") return resp.GetDetails() } -func (s *Tester) AddGenericOAuthIDP(ctx context.Context, name string) *admin.AddGenericOAuthProviderResponse { - resp, err := s.Client.Admin.AddGenericOAuthProvider(ctx, &admin.AddGenericOAuthProviderRequest{ +func (i *Instance) AddGenericOAuthProvider(ctx context.Context, name string) *admin.AddGenericOAuthProviderResponse { + resp, err := i.Client.Admin.AddGenericOAuthProvider(ctx, &admin.AddGenericOAuthProviderRequest{ Name: name, ClientId: "clientID", ClientSecret: "clientSecret", @@ -427,136 +397,126 @@ func (s *Tester) AddGenericOAuthIDP(ctx context.Context, name string) *admin.Add AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME, }, }) - logging.OnError(err).Fatal("create generic OAuth idp") - return resp -} + logging.OnError(err).Panic("create generic OAuth idp") -func (s *Tester) AddGenericOAuthProvider(t *testing.T, ctx context.Context) string { - ctx = authz.WithInstance(ctx, s.Instance) - id, _, err := s.Commands.AddInstanceGenericOAuthProvider(ctx, command.GenericOAuthProvider{ - Name: "idp", - ClientID: "clientID", - ClientSecret: "clientSecret", - AuthorizationEndpoint: "https://example.com/oauth/v2/authorize", - TokenEndpoint: "https://example.com/oauth/v2/token", - UserEndpoint: "https://api.example.com/user", - Scopes: []string{"openid", "profile", "email"}, - IDAttribute: "id", - IDPOptions: idp_rp.Options{ - IsLinkingAllowed: true, - IsCreationAllowed: true, - IsAutoCreation: true, - IsAutoUpdate: true, - }, - }) - require.NoError(t, err) - return id -} - -func (s *Tester) AddOrgGenericOAuthIDP(ctx context.Context, name string) *mgmt.AddGenericOAuthProviderResponse { - resp, err := s.Client.Mgmt.AddGenericOAuthProvider(ctx, &mgmt.AddGenericOAuthProviderRequest{ - Name: name, - ClientId: "clientID", - ClientSecret: "clientSecret", - AuthorizationEndpoint: "https://example.com/oauth/v2/authorize", - TokenEndpoint: "https://example.com/oauth/v2/token", - UserEndpoint: "https://api.example.com/user", - Scopes: []string{"openid", "profile", "email"}, - IdAttribute: "id", - ProviderOptions: &idp.Options{ - IsLinkingAllowed: true, - IsCreationAllowed: true, - IsAutoCreation: true, - IsAutoUpdate: true, - AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME, - }, - }) - logging.OnError(err).Fatal("create generic OAuth idp") - return resp -} - -func (s *Tester) AddOrgGenericOAuthProvider(t *testing.T, ctx context.Context, orgID string) string { - ctx = authz.WithInstance(ctx, s.Instance) - id, _, err := s.Commands.AddOrgGenericOAuthProvider(ctx, orgID, - command.GenericOAuthProvider{ - Name: "idp", - ClientID: "clientID", - ClientSecret: "clientSecret", - AuthorizationEndpoint: "https://example.com/oauth/v2/authorize", - TokenEndpoint: "https://example.com/oauth/v2/token", - UserEndpoint: "https://api.example.com/user", - Scopes: []string{"openid", "profile", "email"}, - IDAttribute: "id", - IDPOptions: idp_rp.Options{ - IsLinkingAllowed: true, - IsCreationAllowed: true, - IsAutoCreation: true, - IsAutoUpdate: true, - }, + mustAwait(func() error { + _, err := i.Client.Admin.GetProviderByID(ctx, &admin.GetProviderByIDRequest{ + Id: resp.GetId(), }) - require.NoError(t, err) - return id + return err + }) + + return resp } -func (s *Tester) AddSAMLProvider(t *testing.T, ctx context.Context) string { - ctx = authz.WithInstance(ctx, s.Instance) - id, _, err := s.Server.Commands.AddInstanceSAMLProvider(ctx, command.SAMLProvider{ - Name: "saml-idp", - Metadata: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n \n"), - IDPOptions: idp_rp.Options{ +func (i *Instance) AddOrgGenericOAuthProvider(ctx context.Context, name string) *mgmt.AddGenericOAuthProviderResponse { + resp, err := i.Client.Mgmt.AddGenericOAuthProvider(ctx, &mgmt.AddGenericOAuthProviderRequest{ + Name: name, + ClientId: "clientID", + ClientSecret: "clientSecret", + AuthorizationEndpoint: "https://example.com/oauth/v2/authorize", + TokenEndpoint: "https://example.com/oauth/v2/token", + UserEndpoint: "https://api.example.com/user", + Scopes: []string{"openid", "profile", "email"}, + IdAttribute: "id", + ProviderOptions: &idp.Options{ + IsLinkingAllowed: true, + IsCreationAllowed: true, + IsAutoCreation: true, + IsAutoUpdate: true, + AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME, + }, + }) + logging.OnError(err).Panic("create generic OAuth idp") + /* + mustAwait(func() error { + _, err := i.Client.Mgmt.GetProviderByID(ctx, &mgmt.GetProviderByIDRequest{ + Id: resp.GetId(), + }) + return err + }) + */ + return resp +} + +func (i *Instance) AddSAMLProvider(ctx context.Context) string { + resp, err := i.Client.Admin.AddSAMLProvider(ctx, &admin.AddSAMLProviderRequest{ + Name: "saml-idp", + Metadata: &admin.AddSAMLProviderRequest_MetadataXml{ + MetadataXml: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n \n"), + }, + ProviderOptions: &idp.Options{ IsLinkingAllowed: true, IsCreationAllowed: true, IsAutoCreation: true, IsAutoUpdate: true, }, }) - require.NoError(t, err) - return id + logging.OnError(err).Panic("create saml idp") + return resp.GetId() } -func (s *Tester) AddSAMLRedirectProvider(t *testing.T, ctx context.Context, transientMappingAttributeName string) string { - ctx = authz.WithInstance(ctx, s.Instance) - id, _, err := s.Server.Commands.AddInstanceSAMLProvider(ctx, command.SAMLProvider{ - Name: "saml-idp-redirect", - Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", - Metadata: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n"), - TransientMappingAttributeName: transientMappingAttributeName, - IDPOptions: idp_rp.Options{ +func (i *Instance) AddSAMLRedirectProvider(ctx context.Context, transientMappingAttributeName string) string { + resp, err := i.Client.Admin.AddSAMLProvider(ctx, &admin.AddSAMLProviderRequest{ + Name: "saml-idp-redirect", + Binding: idp.SAMLBinding_SAML_BINDING_REDIRECT, + Metadata: &admin.AddSAMLProviderRequest_MetadataXml{ + MetadataXml: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n"), + }, + TransientMappingAttributeName: &transientMappingAttributeName, + ProviderOptions: &idp.Options{ IsLinkingAllowed: true, IsCreationAllowed: true, IsAutoCreation: true, IsAutoUpdate: true, }, }) - require.NoError(t, err) - return id + logging.OnError(err).Panic("create saml idp") + return resp.GetId() } -func (s *Tester) AddSAMLPostProvider(t *testing.T, ctx context.Context) string { - ctx = authz.WithInstance(ctx, s.Instance) - id, _, err := s.Server.Commands.AddInstanceSAMLProvider(ctx, command.SAMLProvider{ - Name: "saml-idp-post", - Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", - Metadata: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n"), - IDPOptions: idp_rp.Options{ +func (i *Instance) AddSAMLPostProvider(ctx context.Context) string { + resp, err := i.Client.Admin.AddSAMLProvider(ctx, &admin.AddSAMLProviderRequest{ + Name: "saml-idp-post", + Binding: idp.SAMLBinding_SAML_BINDING_POST, + Metadata: &admin.AddSAMLProviderRequest_MetadataXml{ + MetadataXml: []byte("\n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8Ahs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+aucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWxm+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURNB2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0OBBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uvNONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEfy/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsbGFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTLUzreO96WzlBBMtY=\n \n \n \n \n \n \n \n urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n \n \n"), + }, + ProviderOptions: &idp.Options{ IsLinkingAllowed: true, IsCreationAllowed: true, IsAutoCreation: true, IsAutoUpdate: true, }, }) - require.NoError(t, err) - return id + logging.OnError(err).Panic("create saml idp") + return resp.GetId() } -func (s *Tester) CreateIntent(t *testing.T, ctx context.Context, idpID string) string { +/* +func (s *Instance) CreateIntent(t *testing.T, ctx context.Context, idpID string) string { + resp, err := i.Client.UserV2.StartIdentityProviderIntent(ctx, &user.StartIdentityProviderIntentRequest{ + IdpId: idpID, + Content: &user.StartIdentityProviderIntentRequest_Urls{ + Urls: &user.RedirectURLs{ + SuccessUrl: "https://example.com/success", + FailureUrl: "https://example.com/failure", + }, + AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME, + }, + }) + logging.OnError(err).Fatal("create generic OAuth idp") + return resp +} + +func (i *Instance) CreateIntent(t *testing.T, ctx context.Context, idpID string) string { ctx = authz.WithInstance(context.WithoutCancel(ctx), s.Instance) writeModel, _, err := s.Commands.CreateIntent(ctx, idpID, "https://example.com/success", "https://example.com/failure", s.Instance.InstanceID()) require.NoError(t, err) return writeModel.AggregateID } -func (s *Tester) CreateSuccessfulOAuthIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { +func (i *Instance) CreateSuccessfulOAuthIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { ctx = authz.WithInstance(context.WithoutCancel(ctx), s.Instance) intentID := s.CreateIntent(t, ctx, idpID) writeModel, err := s.Commands.GetIntentWriteModel(ctx, intentID, s.Instance.InstanceID()) @@ -582,7 +542,7 @@ func (s *Tester) CreateSuccessfulOAuthIntent(t *testing.T, ctx context.Context, return intentID, token, writeModel.ChangeDate, writeModel.ProcessedSequence } -func (s *Tester) CreateSuccessfulLDAPIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { +func (s *Instance) CreateSuccessfulLDAPIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { ctx = authz.WithInstance(context.WithoutCancel(ctx), s.Instance) intentID := s.CreateIntent(t, ctx, idpID) writeModel, err := s.Commands.GetIntentWriteModel(ctx, intentID, s.Instance.InstanceID()) @@ -610,7 +570,7 @@ func (s *Tester) CreateSuccessfulLDAPIntent(t *testing.T, ctx context.Context, i return intentID, token, writeModel.ChangeDate, writeModel.ProcessedSequence } -func (s *Tester) CreateSuccessfulSAMLIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { +func (s *Instance) CreateSuccessfulSAMLIntent(t *testing.T, ctx context.Context, idpID, userID, idpUserID string) (string, string, time.Time, uint64) { ctx = authz.WithInstance(context.WithoutCancel(ctx), s.Instance) intentID := s.CreateIntent(t, ctx, idpID) writeModel, err := s.Server.Commands.GetIntentWriteModel(ctx, intentID, s.Instance.InstanceID()) @@ -626,17 +586,18 @@ func (s *Tester) CreateSuccessfulSAMLIntent(t *testing.T, ctx context.Context, i require.NoError(t, err) return intentID, token, writeModel.ChangeDate, writeModel.ProcessedSequence } +*/ -func (s *Tester) CreateVerifiedWebAuthNSession(t *testing.T, ctx context.Context, userID string) (id, token string, start, change time.Time) { - return s.CreateVerifiedWebAuthNSessionWithLifetime(t, ctx, userID, 0) +func (i *Instance) CreateVerifiedWebAuthNSession(t *testing.T, ctx context.Context, userID string) (id, token string, start, change time.Time) { + return i.CreateVerifiedWebAuthNSessionWithLifetime(t, ctx, userID, 0) } -func (s *Tester) CreateVerifiedWebAuthNSessionWithLifetime(t *testing.T, ctx context.Context, userID string, lifetime time.Duration) (id, token string, start, change time.Time) { +func (i *Instance) CreateVerifiedWebAuthNSessionWithLifetime(t *testing.T, ctx context.Context, userID string, lifetime time.Duration) (id, token string, start, change time.Time) { var sessionLifetime *durationpb.Duration if lifetime > 0 { sessionLifetime = durationpb.New(lifetime) } - createResp, err := s.Client.SessionV2.CreateSession(ctx, &session.CreateSessionRequest{ + createResp, err := i.Client.SessionV2.CreateSession(ctx, &session.CreateSessionRequest{ Checks: &session.Checks{ User: &session.CheckUser{ Search: &session.CheckUser_UserId{UserId: userID}, @@ -644,7 +605,7 @@ func (s *Tester) CreateVerifiedWebAuthNSessionWithLifetime(t *testing.T, ctx con }, Challenges: &session.RequestChallenges{ WebAuthN: &session.RequestChallenges_WebAuthN{ - Domain: s.Config.ExternalDomain, + Domain: i.Domain, UserVerificationRequirement: session.UserVerificationRequirement_USER_VERIFICATION_REQUIREMENT_REQUIRED, }, }, @@ -652,10 +613,10 @@ func (s *Tester) CreateVerifiedWebAuthNSessionWithLifetime(t *testing.T, ctx con }) require.NoError(t, err) - assertion, err := s.WebAuthN.CreateAssertionResponse(createResp.GetChallenges().GetWebAuthN().GetPublicKeyCredentialRequestOptions(), true) + assertion, err := i.WebAuthN.CreateAssertionResponse(createResp.GetChallenges().GetWebAuthN().GetPublicKeyCredentialRequestOptions(), true) require.NoError(t, err) - updateResp, err := s.Client.SessionV2.SetSession(ctx, &session.SetSessionRequest{ + updateResp, err := i.Client.SessionV2.SetSession(ctx, &session.SetSessionRequest{ SessionId: createResp.GetSessionId(), Checks: &session.Checks{ WebAuthN: &session.CheckWebAuthN{ @@ -668,8 +629,8 @@ func (s *Tester) CreateVerifiedWebAuthNSessionWithLifetime(t *testing.T, ctx con createResp.GetDetails().GetChangeDate().AsTime(), updateResp.GetDetails().GetChangeDate().AsTime() } -func (s *Tester) CreatePasswordSession(t *testing.T, ctx context.Context, userID, password string) (id, token string, start, change time.Time) { - createResp, err := s.Client.SessionV2.CreateSession(ctx, &session.CreateSessionRequest{ +func (i *Instance) CreatePasswordSession(t *testing.T, ctx context.Context, userID, password string) (id, token string, start, change time.Time) { + createResp, err := i.Client.SessionV2.CreateSession(ctx, &session.CreateSessionRequest{ Checks: &session.Checks{ User: &session.CheckUser{ Search: &session.CheckUser_UserId{UserId: userID}, @@ -684,8 +645,8 @@ func (s *Tester) CreatePasswordSession(t *testing.T, ctx context.Context, userID createResp.GetDetails().GetChangeDate().AsTime(), createResp.GetDetails().GetChangeDate().AsTime() } -func (s *Tester) CreateProjectUserGrant(t *testing.T, ctx context.Context, projectID, userID string) string { - resp, err := s.Client.Mgmt.AddUserGrant(ctx, &mgmt.AddUserGrantRequest{ +func (i *Instance) CreateProjectUserGrant(t *testing.T, ctx context.Context, projectID, userID string) string { + resp, err := i.Client.Mgmt.AddUserGrant(ctx, &mgmt.AddUserGrantRequest{ UserId: userID, ProjectId: projectID, }) @@ -693,16 +654,16 @@ func (s *Tester) CreateProjectUserGrant(t *testing.T, ctx context.Context, proje return resp.GetUserGrantId() } -func (s *Tester) CreateOrgMembership(t *testing.T, ctx context.Context, userID string) { - _, err := s.Client.Mgmt.AddOrgMember(ctx, &mgmt.AddOrgMemberRequest{ +func (i *Instance) CreateOrgMembership(t *testing.T, ctx context.Context, userID string) { + _, err := i.Client.Mgmt.AddOrgMember(ctx, &mgmt.AddOrgMemberRequest{ UserId: userID, Roles: []string{domain.RoleOrgOwner}, }) require.NoError(t, err) } -func (s *Tester) CreateProjectMembership(t *testing.T, ctx context.Context, projectID, userID string) { - _, err := s.Client.Mgmt.AddProjectMember(ctx, &mgmt.AddProjectMemberRequest{ +func (i *Instance) CreateProjectMembership(t *testing.T, ctx context.Context, projectID, userID string) { + _, err := i.Client.Mgmt.AddProjectMember(ctx, &mgmt.AddProjectMemberRequest{ ProjectId: projectID, UserId: userID, Roles: []string{domain.RoleProjectOwner}, @@ -710,13 +671,12 @@ func (s *Tester) CreateProjectMembership(t *testing.T, ctx context.Context, proj require.NoError(t, err) } -func (s *Tester) CreateTarget(ctx context.Context, t *testing.T, name, endpoint string, ty domain.TargetType, interrupt bool) *action.CreateTargetResponse { - nameSet := fmt.Sprint(time.Now().UnixNano() + 1) - if name != "" { - nameSet = name +func (i *Instance) CreateTarget(ctx context.Context, t *testing.T, name, endpoint string, ty domain.TargetType, interrupt bool) *action.CreateTargetResponse { + if name == "" { + name = gofakeit.Name() } reqTarget := &action.Target{ - Name: nameSet, + Name: name, Endpoint: endpoint, Timeout: durationpb.New(10 * time.Second), } @@ -738,20 +698,20 @@ func (s *Tester) CreateTarget(ctx context.Context, t *testing.T, name, endpoint RestAsync: &action.SetRESTAsync{}, } } - target, err := s.Client.ActionV3Alpha.CreateTarget(ctx, &action.CreateTargetRequest{Target: reqTarget}) + target, err := i.Client.ActionV3Alpha.CreateTarget(ctx, &action.CreateTargetRequest{Target: reqTarget}) require.NoError(t, err) return target } -func (s *Tester) DeleteExecution(ctx context.Context, t *testing.T, cond *action.Condition) { - _, err := s.Client.ActionV3Alpha.SetExecution(ctx, &action.SetExecutionRequest{ +func (i *Instance) DeleteExecution(ctx context.Context, t *testing.T, cond *action.Condition) { + _, err := i.Client.ActionV3Alpha.SetExecution(ctx, &action.SetExecutionRequest{ Condition: cond, }) require.NoError(t, err) } -func (s *Tester) SetExecution(ctx context.Context, t *testing.T, cond *action.Condition, targets []*action.ExecutionTargetType) *action.SetExecutionResponse { - target, err := s.Client.ActionV3Alpha.SetExecution(ctx, &action.SetExecutionRequest{ +func (i *Instance) SetExecution(ctx context.Context, t *testing.T, cond *action.Condition, targets []*action.ExecutionTargetType) *action.SetExecutionResponse { + target, err := i.Client.ActionV3Alpha.SetExecution(ctx, &action.SetExecutionRequest{ Condition: cond, Execution: &action.Execution{ Targets: targets, @@ -761,15 +721,15 @@ func (s *Tester) SetExecution(ctx context.Context, t *testing.T, cond *action.Co return target } -func (s *Tester) CreateUserSchemaEmpty(ctx context.Context) *userschema_v3alpha.CreateUserSchemaResponse { - return s.CreateUserSchemaEmptyWithType(ctx, fmt.Sprint(time.Now().UnixNano()+1)) +func (i *Instance) CreateUserSchemaEmpty(ctx context.Context) *userschema_v3alpha.CreateUserSchemaResponse { + return i.CreateUserSchemaEmptyWithType(ctx, fmt.Sprint(time.Now().UnixNano()+1)) } -func (s *Tester) CreateUserSchema(ctx context.Context, schemaData []byte) *userschema_v3alpha.CreateUserSchemaResponse { +func (i *Instance) CreateUserSchema(ctx context.Context, schemaData []byte) *userschema_v3alpha.CreateUserSchemaResponse { userSchema := new(structpb.Struct) err := userSchema.UnmarshalJSON(schemaData) logging.OnError(err).Fatal("create userschema unmarshal") - schema, err := s.Client.UserSchemaV3.CreateUserSchema(ctx, &userschema_v3alpha.CreateUserSchemaRequest{ + schema, err := i.Client.UserSchemaV3.CreateUserSchema(ctx, &userschema_v3alpha.CreateUserSchemaRequest{ UserSchema: &userschema_v3alpha.UserSchema{ Type: fmt.Sprint(time.Now().UnixNano() + 1), DataType: &userschema_v3alpha.UserSchema_Schema{ @@ -781,7 +741,7 @@ func (s *Tester) CreateUserSchema(ctx context.Context, schemaData []byte) *users return schema } -func (s *Tester) CreateUserSchemaEmptyWithType(ctx context.Context, schemaType string) *userschema_v3alpha.CreateUserSchemaResponse { +func (i *Instance) CreateUserSchemaEmptyWithType(ctx context.Context, schemaType string) *userschema_v3alpha.CreateUserSchemaResponse { userSchema := new(structpb.Struct) err := userSchema.UnmarshalJSON([]byte(`{ "$schema": "urn:zitadel:schema:v1", @@ -789,7 +749,7 @@ func (s *Tester) CreateUserSchemaEmptyWithType(ctx context.Context, schemaType s "properties": {} }`)) logging.OnError(err).Fatal("create userschema unmarshal") - schema, err := s.Client.UserSchemaV3.CreateUserSchema(ctx, &userschema_v3alpha.CreateUserSchemaRequest{ + schema, err := i.Client.UserSchemaV3.CreateUserSchema(ctx, &userschema_v3alpha.CreateUserSchemaRequest{ UserSchema: &userschema_v3alpha.UserSchema{ Type: schemaType, DataType: &userschema_v3alpha.UserSchema_Schema{ @@ -801,11 +761,11 @@ func (s *Tester) CreateUserSchemaEmptyWithType(ctx context.Context, schemaType s return schema } -func (s *Tester) CreateSchemaUser(ctx context.Context, orgID string, schemaID string, data []byte) *user_v3alpha.CreateUserResponse { +func (i *Instance) CreateSchemaUser(ctx context.Context, orgID string, schemaID string, data []byte) *user_v3alpha.CreateUserResponse { userData := new(structpb.Struct) err := userData.UnmarshalJSON(data) logging.OnError(err).Fatal("create user unmarshal") - user, err := s.Client.UserV3Alpha.CreateUser(ctx, &user_v3alpha.CreateUserRequest{ + user, err := i.Client.UserV3Alpha.CreateUser(ctx, &user_v3alpha.CreateUserRequest{ Organization: &object_v3alpha.Organization{Property: &object_v3alpha.Organization_OrgId{OrgId: orgID}}, User: &user_v3alpha.CreateUser{ SchemaId: schemaID, diff --git a/internal/integration/config.go b/internal/integration/config.go new file mode 100644 index 0000000000..5aea740752 --- /dev/null +++ b/internal/integration/config.go @@ -0,0 +1,53 @@ +package integration + +import ( + "bytes" + _ "embed" + "os/exec" + "path/filepath" + + "github.com/zitadel/logging" + "sigs.k8s.io/yaml" +) + +type Config struct { + Log *logging.Config + Hostname string + Port uint16 + Secure bool + LoginURLV2 string + LogoutURLV2 string + WebAuthNName string +} + +var ( + //go:embed config/client.yaml + clientYAML []byte +) + +var ( + tmpDir string + loadedConfig Config +) + +// TmpDir returns the absolute path to the projects's temp directory. +func TmpDir() string { + return tmpDir +} + +func init() { + cmd := exec.Command("git", "rev-parse", "--show-toplevel") + out, err := cmd.Output() + if err != nil { + panic(err) + } + tmpDir = filepath.Join(string(bytes.TrimSpace(out)), "tmp") + + if err := yaml.Unmarshal(clientYAML, &loadedConfig); err != nil { + panic(err) + } + if err := loadedConfig.Log.SetLogger(); err != nil { + panic(err) + } + SystemToken = systemUserToken() +} diff --git a/internal/integration/config/client.yaml b/internal/integration/config/client.yaml new file mode 100644 index 0000000000..43e417d4d6 --- /dev/null +++ b/internal/integration/config/client.yaml @@ -0,0 +1,10 @@ +Log: + Level: info + Formatter: + Format: text +Hostname: localhost +Port: 8080 +Secure: false +LoginURLV2: "/login?authRequest=" +LogoutURLV2: "/logout?post_logout_redirect=" +WebAuthNName: ZITADEL diff --git a/internal/integration/config/docker-compose.yaml b/internal/integration/config/docker-compose.yaml index b7f065fad7..1749b9f0ab 100644 --- a/internal/integration/config/docker-compose.yaml +++ b/internal/integration/config/docker-compose.yaml @@ -14,7 +14,7 @@ services: - PGUSER=zitadel - POSTGRES_DB=zitadel - POSTGRES_HOST_AUTH_METHOD=trust - command: postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all + command: postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all -c shared_buffers=1GB -c work_mem=16MB -c effective_io_concurrency=100 -c wal_level=minimal -c archive_mode=off -c max_wal_senders=0 healthcheck: test: ["CMD-SHELL", "pg_isready"] interval: '10s' diff --git a/internal/integration/config/postgres.yaml b/internal/integration/config/postgres.yaml index c75187d7fb..9cabb440c0 100644 --- a/internal/integration/config/postgres.yaml +++ b/internal/integration/config/postgres.yaml @@ -1,10 +1,12 @@ Database: + EventPushConnRatio: 0.2 # 4 + ProjectionSpoolerConnRatio: 0.3 # 6 postgres: Host: localhost Port: 5432 Database: zitadel - MaxOpenConns: 15 - MaxIdleConns: 10 + MaxOpenConns: 20 + MaxIdleConns: 20 User: Username: zitadel SSL: diff --git a/internal/integration/config/steps.yaml b/internal/integration/config/steps.yaml new file mode 100644 index 0000000000..fea8441e2b --- /dev/null +++ b/internal/integration/config/steps.yaml @@ -0,0 +1,13 @@ +FirstInstance: + Skip: false + PatPath: tmp/admin-pat.txt + InstanceName: ZITADEL + DefaultLanguage: en + Org: + Name: ZITADEL + Machine: + Machine: + Username: boss + Name: boss + Pat: + ExpirationDate: 2099-01-01T00:00:00Z diff --git a/internal/integration/config/zitadel.yaml b/internal/integration/config/zitadel.yaml index d58529b7a8..68e0b43f9c 100644 --- a/internal/integration/config/zitadel.yaml +++ b/internal/integration/config/zitadel.yaml @@ -1,15 +1,19 @@ Log: - Level: debug + Level: info ExternalSecure: false TLS: Enabled: false +Quotas: + Access: + Enabled: true + Telemetry: Enabled: true Endpoints: - - http://localhost:8081 + - http://localhost:8081/milestone Headers: single-value: "single-value" multi-value: @@ -27,14 +31,15 @@ LogStore: Enabled: true Projections: - HandleActiveInstances: 60s + HandleActiveInstances: 30m + RequeueEvery: 5s + TransactionDuration: 1m Customizations: NotificationsQuotas: RequeueEvery: 1s + telemetry: HandleActiveInstances: 60s - Telemetry: - RequeueEvery: 5s - HandleActiveInstances: 60s + RequeueEvery: 1s DefaultInstance: LoginPolicy: diff --git a/internal/integration/instance.go b/internal/integration/instance.go new file mode 100644 index 0000000000..c6e0b9737c --- /dev/null +++ b/internal/integration/instance.go @@ -0,0 +1,354 @@ +// Package integration provides helpers for integration testing. +package integration + +import ( + "bytes" + "context" + _ "embed" + "errors" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/brianvoe/gofakeit/v6" + "github.com/zitadel/logging" + "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/proto" + + http_util "github.com/zitadel/zitadel/internal/api/http" + "github.com/zitadel/zitadel/internal/webauthn" + "github.com/zitadel/zitadel/pkg/grpc/admin" + "github.com/zitadel/zitadel/pkg/grpc/auth" + "github.com/zitadel/zitadel/pkg/grpc/instance" + "github.com/zitadel/zitadel/pkg/grpc/management" + "github.com/zitadel/zitadel/pkg/grpc/org" + "github.com/zitadel/zitadel/pkg/grpc/system" + "github.com/zitadel/zitadel/pkg/grpc/user" + user_v2 "github.com/zitadel/zitadel/pkg/grpc/user/v2" +) + +// NotEmpty can be used as placeholder, when the returned values is unknown. +// It can be used in tests to assert whether a value should be empty or not. +const NotEmpty = "not empty" + +const ( + adminPATFile = "admin-pat.txt" +) + +// UserType provides constants that give +// a short explanation with the purpose +// a service user. +// This allows to pre-create users with +// different permissions and reuse them. +type UserType int + +//go:generate enumer -type UserType -transform snake -trimprefix UserType +const ( + UserTypeUnspecified UserType = iota + UserTypeIAMOwner + UserTypeOrgOwner + UserTypeLogin +) + +const ( + UserPassword = "VeryS3cret!" +) + +const ( + PortMilestoneServer = "8081" + PortQuotaServer = "8082" +) + +// User information with a Personal Access Token. +type User struct { + ID string + Username string + Token string +} + +type UserMap map[UserType]*User + +func (m UserMap) Set(typ UserType, user *User) { + m[typ] = user +} + +func (m UserMap) Get(typ UserType) *User { + return m[typ] +} + +// Host returns the primary host of zitadel, on which the first instance is served. +// http://localhost:8080 by default +func (c *Config) Host() string { + return fmt.Sprintf("%s:%d", c.Hostname, c.Port) +} + +// Instance is a Zitadel server and client with all resources available for testing. +type Instance struct { + Config Config + Domain string + Instance *instance.InstanceDetail + DefaultOrg *org.Org + Users UserMap + AdminUserID string // First human user for password login + + Client *Client + WebAuthN *webauthn.Client +} + +// GetFirstInstance returns the default instance and org information, +// with authorized machine users. +// Using the first instance is not recommended as parallel test might +// interfere with each other. +// It is recommended to use [NewInstance] instead. +func GetFirstInstance(ctx context.Context) *Instance { + i := &Instance{ + Config: loadedConfig, + Domain: loadedConfig.Hostname, + } + token := loadInstanceOwnerPAT() + i.setClient(ctx) + i.setupInstance(ctx, token) + return i +} + +// NewInstance returns a new instance that can be used for integration tests. +// The instance contains a gRPC client connected to the domain of this instance. +// The included users are the IAM_OWNER, ORG_OWNER of the default org and +// a Login client user. +// +// The instance is isolated and is safe for parallel testing. +func NewInstance(ctx context.Context) *Instance { + primaryDomain := RandString(5) + ".integration.localhost" + + ctx = WithSystemAuthorization(ctx) + resp, err := SystemClient().CreateInstance(ctx, &system.CreateInstanceRequest{ + InstanceName: "testinstance", + CustomDomain: primaryDomain, + Owner: &system.CreateInstanceRequest_Machine_{ + Machine: &system.CreateInstanceRequest_Machine{ + UserName: "owner", + Name: "owner", + PersonalAccessToken: &system.CreateInstanceRequest_PersonalAccessToken{}, + }, + }, + }) + if err != nil { + panic(err) + } + i := &Instance{ + Config: loadedConfig, + Domain: primaryDomain, + } + i.setClient(ctx) + i.awaitFirstUser(WithAuthorizationToken(ctx, resp.GetPat())) + i.setupInstance(ctx, resp.GetPat()) + return i +} + +func (i *Instance) ID() string { + return i.Instance.GetId() +} + +func (i *Instance) awaitFirstUser(ctx context.Context) { + var allErrs []error + for { + resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{ + Username: proto.String("zitadel-admin@zitadel.localhost"), + Profile: &user_v2.SetHumanProfile{ + GivenName: "hodor", + FamilyName: "hodor", + NickName: proto.String("hodor"), + }, + Email: &user_v2.SetHumanEmail{ + Email: "zitadel-admin@zitadel.localhost", + Verification: &user_v2.SetHumanEmail_IsVerified{ + IsVerified: true, + }, + }, + PasswordType: &user_v2.AddHumanUserRequest_Password{ + Password: &user_v2.Password{ + Password: "Password1!", + ChangeRequired: false, + }, + }, + }) + if err == nil { + i.AdminUserID = resp.GetUserId() + return + } + logging.WithError(err).Debug("await first instance user") + allErrs = append(allErrs, err) + select { + case <-ctx.Done(): + panic(errors.Join(append(allErrs, ctx.Err())...)) + case <-time.After(time.Second): + continue + } + } +} + +func (i *Instance) setupInstance(ctx context.Context, token string) { + i.Users = make(UserMap) + ctx = WithAuthorizationToken(ctx, token) + i.setInstance(ctx) + i.setOrganization(ctx) + i.createMachineUserInstanceOwner(ctx, token) + i.createMachineUserOrgOwner(ctx) + i.createLoginClient(ctx) + i.createWebAuthNClient() +} + +// Host returns the primary Domain of the instance with the port. +func (i *Instance) Host() string { + return fmt.Sprintf("%s:%d", i.Domain, i.Config.Port) +} + +func loadInstanceOwnerPAT() string { + data, err := os.ReadFile(filepath.Join(tmpDir, adminPATFile)) + if err != nil { + panic(err) + } + return string(bytes.TrimSpace(data)) +} + +func (i *Instance) createMachineUserInstanceOwner(ctx context.Context, token string) { + mustAwait(func() error { + user, err := i.Client.Auth.GetMyUser(WithAuthorizationToken(ctx, token), &auth.GetMyUserRequest{}) + if err != nil { + return err + } + i.Users.Set(UserTypeIAMOwner, &User{ + ID: user.GetUser().GetId(), + Username: user.GetUser().GetUserName(), + Token: token, + }) + return nil + }) +} + +func (i *Instance) createMachineUserOrgOwner(ctx context.Context) { + _, err := i.Client.Mgmt.AddOrgMember(ctx, &management.AddOrgMemberRequest{ + UserId: i.createMachineUser(ctx, UserTypeOrgOwner), + Roles: []string{"ORG_OWNER"}, + }) + if err != nil { + panic(err) + } +} + +func (i *Instance) createLoginClient(ctx context.Context) { + i.createMachineUser(ctx, UserTypeLogin) +} + +func (i *Instance) setClient(ctx context.Context) { + client, err := newClient(ctx, i.Host()) + if err != nil { + panic(err) + } + i.Client = client +} + +func (i *Instance) setInstance(ctx context.Context) { + mustAwait(func() error { + instance, err := i.Client.Admin.GetMyInstance(ctx, &admin.GetMyInstanceRequest{}) + i.Instance = instance.GetInstance() + return err + }) +} + +func (i *Instance) setOrganization(ctx context.Context) { + mustAwait(func() error { + resp, err := i.Client.Mgmt.GetMyOrg(ctx, &management.GetMyOrgRequest{}) + i.DefaultOrg = resp.GetOrg() + return err + }) +} + +func (i *Instance) createMachineUser(ctx context.Context, userType UserType) (userID string) { + mustAwait(func() error { + username := gofakeit.Username() + userResp, err := i.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{ + UserName: username, + Name: username, + Description: userType.String(), + AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, + }) + if err != nil { + return err + } + userID = userResp.GetUserId() + patResp, err := i.Client.Mgmt.AddPersonalAccessToken(ctx, &management.AddPersonalAccessTokenRequest{ + UserId: userID, + }) + if err != nil { + return err + } + i.Users.Set(userType, &User{ + ID: userID, + Username: username, + Token: patResp.GetToken(), + }) + return nil + }) + return userID +} + +func (i *Instance) createWebAuthNClient() { + i.WebAuthN = webauthn.NewClient(i.Config.WebAuthNName, i.Domain, http_util.BuildOrigin(i.Host(), i.Config.Secure)) +} + +func (i *Instance) WithAuthorization(ctx context.Context, u UserType) context.Context { + return i.WithInstanceAuthorization(ctx, u) +} + +func (i *Instance) WithInstanceAuthorization(ctx context.Context, u UserType) context.Context { + return WithAuthorizationToken(ctx, i.Users.Get(u).Token) +} + +func (i *Instance) GetUserID(u UserType) string { + return i.Users.Get(u).ID +} + +func WithAuthorizationToken(ctx context.Context, token string) context.Context { + md, ok := metadata.FromOutgoingContext(ctx) + if !ok { + md = make(metadata.MD) + } + md.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + return metadata.NewOutgoingContext(ctx, md) +} + +func (i *Instance) BearerToken(ctx context.Context) string { + md, ok := metadata.FromOutgoingContext(ctx) + if !ok { + return "" + } + return md.Get("Authorization")[0] +} + +func (i *Instance) WithSystemAuthorizationHTTP(u UserType) map[string]string { + return map[string]string{"Authorization": fmt.Sprintf("Bearer %s", i.Users.Get(u).Token)} +} + +func await(af func() error) error { + maxTimer := time.NewTimer(15 * time.Minute) + for { + err := af() + if err == nil { + return nil + } + select { + case <-maxTimer.C: + return err + case <-time.After(time.Second): + continue + } + } +} + +func mustAwait(af func() error) { + if err := await(af); err != nil { + panic(err) + } +} diff --git a/internal/integration/integration.go b/internal/integration/integration.go deleted file mode 100644 index 20af65993b..0000000000 --- a/internal/integration/integration.go +++ /dev/null @@ -1,449 +0,0 @@ -// Package integration provides helpers for integration testing. -package integration - -import ( - "bytes" - "context" - "database/sql" - _ "embed" - "errors" - "fmt" - "io" - "net/http" - "net/http/httptest" - "os" - "reflect" - "strings" - "sync" - "time" - - "github.com/spf13/viper" - "github.com/zitadel/logging" - "github.com/zitadel/oidc/v3/pkg/client" - "github.com/zitadel/oidc/v3/pkg/oidc" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/metadata" - - "github.com/zitadel/zitadel/cmd" - "github.com/zitadel/zitadel/cmd/start" - "github.com/zitadel/zitadel/internal/api/authz" - http_util "github.com/zitadel/zitadel/internal/api/http" - z_oidc "github.com/zitadel/zitadel/internal/api/oidc" - "github.com/zitadel/zitadel/internal/command" - "github.com/zitadel/zitadel/internal/domain" - "github.com/zitadel/zitadel/internal/eventstore/v1/models" - "github.com/zitadel/zitadel/internal/net" - "github.com/zitadel/zitadel/internal/query" - "github.com/zitadel/zitadel/internal/webauthn" - "github.com/zitadel/zitadel/internal/zerrors" - "github.com/zitadel/zitadel/pkg/grpc/admin" -) - -var ( - //go:embed config/zitadel.yaml - zitadelYAML []byte - //go:embed config/cockroach.yaml - cockroachYAML []byte - //go:embed config/postgres.yaml - postgresYAML []byte - //go:embed config/system-user-key.pem - systemUserKey []byte -) - -// NotEmpty can be used as placeholder, when the returned values is unknown. -// It can be used in tests to assert whether a value should be empty or not. -const NotEmpty = "not empty" - -// UserType provides constants that give -// a short explinanation with the purpose -// a serverice user. -// This allows to pre-create users with -// different permissions and reuse them. -type UserType int - -//go:generate stringer -type=UserType -const ( - Unspecified UserType = iota - OrgOwner - Login - IAMOwner - SystemUser // SystemUser is a user with access to the system service. -) - -const ( - FirstInstanceUsersKey = "first" - UserPassword = "VeryS3cret!" -) - -const ( - PortMilestoneServer = "8081" - PortQuotaServer = "8082" -) - -// User information with a Personal Access Token. -type User struct { - *query.User - Token string -} - -type InstanceUserMap map[string]map[UserType]*User - -func (m InstanceUserMap) Set(instanceID string, typ UserType, user *User) { - if m[instanceID] == nil { - m[instanceID] = make(map[UserType]*User) - } - m[instanceID][typ] = user -} - -func (m InstanceUserMap) Get(instanceID string, typ UserType) *User { - if users, ok := m[instanceID]; ok { - return users[typ] - } - return nil -} - -// Tester is a Zitadel server and client with all resources available for testing. -type Tester struct { - *start.Server - - Instance authz.Instance - Organisation *query.Org - Users InstanceUserMap - - MilestoneChan chan []byte - milestoneServer *httptest.Server - QuotaNotificationChan chan []byte - quotaNotificationServer *httptest.Server - - Client Client - WebAuthN *webauthn.Client - wg sync.WaitGroup // used for shutdown -} - -const commandLine = `start --masterkeyFromEnv` - -func (s *Tester) Host() string { - return fmt.Sprintf("%s:%d", s.Config.ExternalDomain, s.Config.Port) -} - -func (s *Tester) createClientConn(ctx context.Context, target string) { - cc, err := grpc.DialContext(ctx, target, - grpc.WithBlock(), - grpc.WithTransportCredentials(insecure.NewCredentials()), - ) - if err != nil { - s.Shutdown <- os.Interrupt - s.wg.Wait() - } - logging.OnError(err).Fatal("integration tester client dial") - logging.New().WithField("target", target).Info("finished dialing grpc client conn") - - s.Client = newClient(cc) - err = s.pollHealth(ctx) - logging.OnError(err).Fatal("integration tester health") -} - -// pollHealth waits until a healthy status is reported. -// TODO: remove when we make the setup blocking on all -// projections completed. -func (s *Tester) pollHealth(ctx context.Context) (err error) { - for { - err = func(ctx context.Context) error { - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := s.Client.Admin.Healthz(ctx, &admin.HealthzRequest{}) - return err - }(ctx) - if err == nil { - return nil - } - logging.WithError(err).Info("poll healthz") - - select { - case <-ctx.Done(): - return ctx.Err() - case <-time.After(time.Second): - continue - } - } -} - -const ( - LoginUser = "loginClient" - MachineUserOrgOwner = "integrationOrgOwner" - MachineUserInstanceOwner = "integrationInstanceOwner" -) - -func (s *Tester) createMachineUserOrgOwner(ctx context.Context) { - var err error - - ctx, user := s.createMachineUser(ctx, MachineUserOrgOwner, OrgOwner) - _, err = s.Commands.AddOrgMember(ctx, user.ResourceOwner, user.ID, "ORG_OWNER") - target := new(zerrors.AlreadyExistsError) - if !errors.As(err, &target) { - logging.OnError(err).Fatal("add org member") - } -} - -func (s *Tester) createMachineUserInstanceOwner(ctx context.Context) { - var err error - - ctx, user := s.createMachineUser(ctx, MachineUserInstanceOwner, IAMOwner) - _, err = s.Commands.AddInstanceMember(ctx, user.ID, "IAM_OWNER") - target := new(zerrors.AlreadyExistsError) - if !errors.As(err, &target) { - logging.OnError(err).Fatal("add instance member") - } -} - -func (s *Tester) createLoginClient(ctx context.Context) { - s.createMachineUser(ctx, LoginUser, Login) -} - -func (s *Tester) createMachineUser(ctx context.Context, username string, userType UserType) (context.Context, *query.User) { - var err error - ctx = s.updateInstanceAndOrg(ctx, s.Host()) - usernameQuery, err := query.NewUserUsernameSearchQuery(username, query.TextEquals) - logging.OnError(err).Fatal("user query") - user, err := s.Queries.GetUser(ctx, true, usernameQuery) - if errors.Is(err, sql.ErrNoRows) { - _, err = s.Commands.AddMachine(ctx, &command.Machine{ - ObjectRoot: models.ObjectRoot{ - ResourceOwner: s.Organisation.ID, - }, - Username: username, - Name: username, - Description: "who cares?", - AccessTokenType: domain.OIDCTokenTypeJWT, - }) - logging.WithFields("username", username).OnError(err).Fatal("add machine user") - user, err = s.Queries.GetUser(ctx, true, usernameQuery) - } - logging.WithFields("username", username).OnError(err).Fatal("get user") - - scopes := []string{oidc.ScopeOpenID, oidc.ScopeProfile, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner} - pat := command.NewPersonalAccessToken(user.ResourceOwner, user.ID, time.Now().Add(time.Hour), scopes, domain.UserTypeMachine) - _, err = s.Commands.AddPersonalAccessToken(ctx, pat) - logging.WithFields("username", SystemUser).OnError(err).Fatal("add pat") - s.Users.Set(FirstInstanceUsersKey, userType, &User{ - User: user, - Token: pat.Token, - }) - return ctx, user -} - -func (s *Tester) WithAuthorization(ctx context.Context, u UserType) context.Context { - return s.WithInstanceAuthorization(ctx, u, FirstInstanceUsersKey) -} - -func (s *Tester) WithInstanceAuthorization(ctx context.Context, u UserType, instanceID string) context.Context { - if u == SystemUser { - s.ensureSystemUser() - } - return s.WithAuthorizationToken(ctx, s.Users.Get(instanceID, u).Token) -} - -func (s *Tester) GetUserID(u UserType) string { - if u == SystemUser { - s.ensureSystemUser() - } - return s.Users.Get(FirstInstanceUsersKey, u).ID -} - -func (s *Tester) WithAuthorizationToken(ctx context.Context, token string) context.Context { - md, ok := metadata.FromOutgoingContext(ctx) - if !ok { - md = make(metadata.MD) - } - md.Set("Authorization", fmt.Sprintf("Bearer %s", token)) - return metadata.NewOutgoingContext(ctx, md) -} - -func (s *Tester) BearerToken(ctx context.Context) string { - md, ok := metadata.FromOutgoingContext(ctx) - if !ok { - return "" - } - return md.Get("Authorization")[0] -} - -func (s *Tester) ensureSystemUser() { - const ISSUER = "tester" - if s.Users.Get(FirstInstanceUsersKey, SystemUser) != nil { - return - } - audience := http_util.BuildOrigin(s.Host(), s.Server.Config.ExternalSecure) - signer, err := client.NewSignerFromPrivateKeyByte(systemUserKey, "") - logging.OnError(err).Fatal("system key signer") - jwt, err := client.SignedJWTProfileAssertion(ISSUER, []string{audience}, time.Hour, signer) - logging.OnError(err).Fatal("system key jwt") - s.Users.Set(FirstInstanceUsersKey, SystemUser, &User{Token: jwt}) -} - -func (s *Tester) WithSystemAuthorizationHTTP(u UserType) map[string]string { - return map[string]string{"Authorization": fmt.Sprintf("Bearer %s", s.Users.Get(FirstInstanceUsersKey, u).Token)} -} - -// Done send an interrupt signal to cleanly shutdown the server. -func (s *Tester) Done() { - err := s.Client.CC.Close() - logging.OnError(err).Error("integration tester client close") - - s.Shutdown <- os.Interrupt - s.wg.Wait() - s.milestoneServer.Close() - s.quotaNotificationServer.Close() -} - -// NewTester start a new Zitadel server by passing the default commandline. -// The server will listen on the configured port. -// The database configuration that will be used can be set by the -// INTEGRATION_DB_FLAVOR environment variable and can have the values "cockroach" -// or "postgres". Defaults to "cockroach". -// -// The default Instance and Organisation are read from the DB and system -// users are created as needed. -// -// After the server is started, a [grpc.ClientConn] will be created and -// the server is polled for it's health status. -// -// Note: the database must already be setup and initialized before -// using NewTester. See the CONTRIBUTING.md document for details. - -func NewTester(ctx context.Context, zitadelConfigYAML ...string) *Tester { - args := strings.Split(commandLine, " ") - - sc := make(chan *start.Server) - //nolint:contextcheck - cmd := cmd.New(os.Stdout, os.Stdin, args, sc) - cmd.SetArgs(args) - for _, yaml := range append([]string{string(zitadelYAML)}, zitadelConfigYAML...) { - err := viper.MergeConfig(bytes.NewBuffer([]byte(yaml))) - logging.OnError(err).Fatal() - } - var err error - flavor := os.Getenv("INTEGRATION_DB_FLAVOR") - switch flavor { - case "cockroach", "": - err = viper.MergeConfig(bytes.NewBuffer(cockroachYAML)) - case "postgres": - err = viper.MergeConfig(bytes.NewBuffer(postgresYAML)) - default: - logging.New().WithField("flavor", flavor).Fatal("unknown db flavor set in INTEGRATION_DB_FLAVOR") - } - logging.OnError(err).Fatal() - - tester := Tester{ - Users: make(InstanceUserMap), - } - tester.MilestoneChan = make(chan []byte, 100) - tester.milestoneServer, err = runMilestoneServer(ctx, tester.MilestoneChan) - logging.OnError(err).Fatal() - tester.QuotaNotificationChan = make(chan []byte, 100) - tester.quotaNotificationServer, err = runQuotaServer(ctx, tester.QuotaNotificationChan) - logging.OnError(err).Fatal() - - tester.wg.Add(1) - go func(wg *sync.WaitGroup) { - logging.OnError(cmd.Execute()).Fatal() - wg.Done() - }(&tester.wg) - - select { - case tester.Server = <-sc: - case <-ctx.Done(): - logging.OnError(ctx.Err()).Fatal("waiting for integration tester server") - } - host := tester.Host() - tester.createClientConn(ctx, host) - tester.createLoginClient(ctx) - tester.WebAuthN = webauthn.NewClient(tester.Config.WebAuthNName, tester.Config.ExternalDomain, http_util.BuildOrigin(host, tester.Config.ExternalSecure)) - tester.createMachineUserOrgOwner(ctx) - tester.createMachineUserInstanceOwner(ctx) - tester.WebAuthN = webauthn.NewClient(tester.Config.WebAuthNName, tester.Config.ExternalDomain, "https://"+tester.Host()) - return &tester -} - -func Contexts(timeout time.Duration) (ctx, errCtx context.Context, cancel context.CancelFunc) { - errCtx, cancel = context.WithCancel(context.Background()) - cancel() - ctx, cancel = context.WithTimeout(context.Background(), timeout) - return ctx, errCtx, cancel -} - -func runMilestoneServer(ctx context.Context, bodies chan []byte) (*httptest.Server, error) { - mockServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if r.Header.Get("single-value") != "single-value" { - http.Error(w, "single-value header not set", http.StatusInternalServerError) - return - } - if reflect.DeepEqual(r.Header.Get("multi-value"), "multi-value-1,multi-value-2") { - http.Error(w, "single-value header not set", http.StatusInternalServerError) - return - } - bodies <- body - w.WriteHeader(http.StatusOK) - })) - config := net.ListenConfig() - listener, err := config.Listen(ctx, "tcp", ":"+PortMilestoneServer) - if err != nil { - return nil, err - } - mockServer.Listener = listener - mockServer.Start() - return mockServer, nil -} - -func runQuotaServer(ctx context.Context, bodies chan []byte) (*httptest.Server, error) { - mockServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - bodies <- body - w.WriteHeader(http.StatusOK) - })) - config := net.ListenConfig() - listener, err := config.Listen(ctx, "tcp", ":"+PortQuotaServer) - if err != nil { - return nil, err - } - mockServer.Listener = listener - mockServer.Start() - return mockServer, nil -} - -func (s *Tester) updateInstanceAndOrg(ctx context.Context, domain string) context.Context { - var err error - s.Instance, err = s.Queries.InstanceByHost(ctx, domain, "") - logging.OnError(err).Fatal("query instance") - ctx = authz.WithInstance(ctx, s.Instance) - - s.Organisation, err = s.Queries.OrgByID(ctx, true, s.Instance.DefaultOrganisationID()) - logging.OnError(err).Fatal("query organisation") - return ctx -} - -func await(af func() error) error { - maxTimer := time.NewTimer(15 * time.Minute) - for { - err := af() - if err == nil { - return nil - } - select { - case <-maxTimer.C: - return err - case <-time.After(time.Second / 10): - continue - } - } -} diff --git a/internal/integration/integration_test.go b/internal/integration/integration_test.go deleted file mode 100644 index 416602ea25..0000000000 --- a/internal/integration/integration_test.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build integration - -package integration - -import ( - "testing" - "time" -) - -func TestNewTester(t *testing.T) { - ctx, _, cancel := Contexts(time.Hour) - defer cancel() - - s := NewTester(ctx) - defer s.Done() -} diff --git a/internal/integration/oidc.go b/internal/integration/oidc.go index 1d15d25f29..9f394e2c2c 100644 --- a/internal/integration/oidc.go +++ b/internal/integration/oidc.go @@ -24,11 +24,11 @@ import ( "github.com/zitadel/zitadel/pkg/grpc/user" ) -func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType, devMode bool, grantTypes ...app.OIDCGrantType) (*management.AddOIDCAppResponse, error) { +func (i *Instance) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType, devMode bool, grantTypes ...app.OIDCGrantType) (*management.AddOIDCAppResponse, error) { if len(grantTypes) == 0 { grantTypes = []app.OIDCGrantType{app.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE, app.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN} } - resp, err := s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ + resp, err := i.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ ProjectId: projectID, Name: fmt.Sprintf("app-%d", time.Now().UnixNano()), RedirectUris: []string{redirectURI}, @@ -51,7 +51,7 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire return nil, err } return resp, await(func() error { - _, err := s.Client.Mgmt.GetAppByID(ctx, &management.GetAppByIDRequest{ + _, err := i.Client.Mgmt.GetAppByID(ctx, &management.GetAppByIDRequest{ ProjectId: projectID, AppId: resp.GetAppId(), }) @@ -59,20 +59,20 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire }) } -func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, devMode bool) (*management.AddOIDCAppResponse, error) { - return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE, devMode) +func (i *Instance) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, devMode bool) (*management.AddOIDCAppResponse, error) { + return i.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE, devMode) } -func (s *Tester) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { - return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC, false) +func (i *Instance) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { + return i.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC, false) } -func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, grantTypes ...app.OIDCGrantType) (client *management.AddOIDCAppResponse, keyData []byte, err error) { - client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT, false, grantTypes...) +func (i *Instance) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, grantTypes ...app.OIDCGrantType) (client *management.AddOIDCAppResponse, keyData []byte, err error) { + client, err = i.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT, false, grantTypes...) if err != nil { return nil, nil, err } - key, err := s.Client.Mgmt.AddAppKey(ctx, &management.AddAppKeyRequest{ + key, err := i.Client.Mgmt.AddAppKey(ctx, &management.AddAppKeyRequest{ ProjectId: projectID, AppId: client.GetAppId(), Type: authn.KeyType_KEY_TYPE_JSON, @@ -81,15 +81,23 @@ func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logout if err != nil { return nil, nil, err } + mustAwait(func() error { + _, err := i.Client.Mgmt.GetAppByID(ctx, &management.GetAppByIDRequest{ + ProjectId: projectID, + AppId: client.GetAppId(), + }) + return err + }) + return client, key.GetKeyDetails(), nil } -func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { - client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID, false) +func (i *Instance) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { + client, err := i.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID, false) if err != nil { return nil, err } - _, err = s.Client.Mgmt.DeactivateApp(ctx, &management.DeactivateAppRequest{ + _, err = i.Client.Mgmt.DeactivateApp(ctx, &management.DeactivateAppRequest{ ProjectId: projectID, AppId: client.GetAppId(), }) @@ -99,14 +107,14 @@ func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, lo return client, err } -func (s *Tester) CreateOIDCImplicitFlowClient(ctx context.Context, redirectURI string) (*management.AddOIDCAppResponse, error) { - project, err := s.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ +func (i *Instance) CreateOIDCImplicitFlowClient(ctx context.Context, redirectURI string) (*management.AddOIDCAppResponse, error) { + project, err := i.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), }) if err != nil { return nil, err } - resp, err := s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ + resp, err := i.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ ProjectId: project.GetId(), Name: fmt.Sprintf("app-%d", time.Now().UnixNano()), RedirectUris: []string{redirectURI}, @@ -129,7 +137,7 @@ func (s *Tester) CreateOIDCImplicitFlowClient(ctx context.Context, redirectURI s return nil, err } return resp, await(func() error { - _, err := s.Client.Mgmt.GetAppByID(ctx, &management.GetAppByIDRequest{ + _, err := i.Client.Mgmt.GetAppByID(ctx, &management.GetAppByIDRequest{ ProjectId: project.GetId(), AppId: resp.GetAppId(), }) @@ -137,32 +145,32 @@ func (s *Tester) CreateOIDCImplicitFlowClient(ctx context.Context, redirectURI s }) } -func (s *Tester) CreateOIDCTokenExchangeClient(ctx context.Context) (client *management.AddOIDCAppResponse, keyData []byte, err error) { - project, err := s.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ +func (i *Instance) CreateOIDCTokenExchangeClient(ctx context.Context) (client *management.AddOIDCAppResponse, keyData []byte, err error) { + project, err := i.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), }) if err != nil { return nil, nil, err } - return s.CreateOIDCWebClientJWT(ctx, "", "", project.GetId(), app.OIDCGrantType_OIDC_GRANT_TYPE_TOKEN_EXCHANGE, app.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE, app.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN) + return i.CreateOIDCWebClientJWT(ctx, "", "", project.GetId(), app.OIDCGrantType_OIDC_GRANT_TYPE_TOKEN_EXCHANGE, app.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE, app.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN) } -func (s *Tester) CreateProject(ctx context.Context) (*management.AddProjectResponse, error) { - return s.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ +func (i *Instance) CreateProject(ctx context.Context) (*management.AddProjectResponse, error) { + return i.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{ Name: fmt.Sprintf("project-%d", time.Now().UnixNano()), }) } -func (s *Tester) CreateAPIClientJWT(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) { - return s.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{ +func (i *Instance) CreateAPIClientJWT(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) { + return i.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{ ProjectId: projectID, Name: fmt.Sprintf("api-%d", time.Now().UnixNano()), AuthMethodType: app.APIAuthMethodType_API_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT, }) } -func (s *Tester) CreateAPIClientBasic(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) { - return s.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{ +func (i *Instance) CreateAPIClientBasic(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) { + return i.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{ ProjectId: projectID, Name: fmt.Sprintf("api-%d", time.Now().UnixNano()), AuthMethodType: app.APIAuthMethodType_API_AUTH_METHOD_TYPE_BASIC, @@ -171,36 +179,36 @@ func (s *Tester) CreateAPIClientBasic(ctx context.Context, projectID string) (*m const CodeVerifier = "codeVerifier" -func (s *Tester) CreateOIDCAuthRequest(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { - return s.CreateOIDCAuthRequestWithDomain(ctx, s.Config.ExternalDomain, clientID, loginClient, redirectURI, scope...) +func (i *Instance) CreateOIDCAuthRequest(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { + return i.CreateOIDCAuthRequestWithDomain(ctx, i.Domain, clientID, loginClient, redirectURI, scope...) } -func (s *Tester) CreateOIDCAuthRequestWithDomain(ctx context.Context, domain, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { - provider, err := s.CreateRelyingPartyForDomain(ctx, domain, clientID, redirectURI, scope...) +func (i *Instance) CreateOIDCAuthRequestWithDomain(ctx context.Context, domain, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { + provider, err := i.CreateRelyingPartyForDomain(ctx, domain, clientID, redirectURI, scope...) if err != nil { - return "", err + return "", fmt.Errorf("create relying party: %w", err) } codeChallenge := oidc.NewSHACodeChallenge(CodeVerifier) authURL := rp.AuthURL("state", provider, rp.WithCodeChallenge(codeChallenge)) req, err := GetRequest(authURL, map[string]string{oidc_internal.LoginClientHeader: loginClient}) if err != nil { - return "", err + return "", fmt.Errorf("get request: %w", err) } loc, err := CheckRedirect(req) if err != nil { - return "", err + return "", fmt.Errorf("check redirect: %w", err) } - prefixWithHost := provider.Issuer() + s.Config.OIDC.DefaultLoginURLV2 + prefixWithHost := provider.Issuer() + i.Config.LoginURLV2 if !strings.HasPrefix(loc.String(), prefixWithHost) { return "", fmt.Errorf("login location has not prefix %s, but is %s", prefixWithHost, loc.String()) } return strings.TrimPrefix(loc.String(), prefixWithHost), nil } -func (s *Tester) CreateOIDCAuthRequestImplicit(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { - provider, err := s.CreateRelyingParty(ctx, clientID, redirectURI, scope...) +func (i *Instance) CreateOIDCAuthRequestImplicit(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) { + provider, err := i.CreateRelyingParty(ctx, clientID, redirectURI, scope...) if err != nil { return "", err } @@ -224,48 +232,49 @@ func (s *Tester) CreateOIDCAuthRequestImplicit(ctx context.Context, clientID, lo return "", err } - prefixWithHost := provider.Issuer() + s.Config.OIDC.DefaultLoginURLV2 + prefixWithHost := provider.Issuer() + i.Config.LoginURLV2 if !strings.HasPrefix(loc.String(), prefixWithHost) { return "", fmt.Errorf("login location has not prefix %s, but is %s", prefixWithHost, loc.String()) } return strings.TrimPrefix(loc.String(), prefixWithHost), nil } -func (s *Tester) OIDCIssuer() string { - return http_util.BuildHTTP(s.Config.ExternalDomain, s.Config.Port, s.Config.ExternalSecure) +func (i *Instance) OIDCIssuer() string { + return http_util.BuildHTTP(i.Domain, i.Config.Port, i.Config.Secure) } -func (s *Tester) CreateRelyingParty(ctx context.Context, clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) { - return s.CreateRelyingPartyForDomain(ctx, s.Config.ExternalDomain, clientID, redirectURI, scope...) +func (i *Instance) CreateRelyingParty(ctx context.Context, clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) { + return i.CreateRelyingPartyForDomain(ctx, i.Domain, clientID, redirectURI, scope...) } -func (s *Tester) CreateRelyingPartyForDomain(ctx context.Context, domain, clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) { +func (i *Instance) CreateRelyingPartyForDomain(ctx context.Context, domain, clientID, redirectURI string, scope ...string) (rp.RelyingParty, error) { if len(scope) == 0 { scope = []string{oidc.ScopeOpenID} } - loginClient := &http.Client{Transport: &loginRoundTripper{http.DefaultTransport}} - return rp.NewRelyingPartyOIDC(ctx, http_util.BuildHTTP(domain, s.Config.Port, s.Config.ExternalSecure), clientID, "", redirectURI, scope, rp.WithHTTPClient(loginClient)) + loginClient := &http.Client{Transport: &loginRoundTripper{http.DefaultTransport, i.Users.Get(UserTypeLogin).Username}} + return rp.NewRelyingPartyOIDC(ctx, http_util.BuildHTTP(domain, i.Config.Port, i.Config.Secure), clientID, "", redirectURI, scope, rp.WithHTTPClient(loginClient)) } type loginRoundTripper struct { http.RoundTripper + loginUsername string } func (c *loginRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - req.Header.Set(oidc_internal.LoginClientHeader, LoginUser) + req.Header.Set(oidc_internal.LoginClientHeader, c.loginUsername) return c.RoundTripper.RoundTrip(req) } -func (s *Tester) CreateResourceServerJWTProfile(ctx context.Context, keyFileData []byte) (rs.ResourceServer, error) { +func (i *Instance) CreateResourceServerJWTProfile(ctx context.Context, keyFileData []byte) (rs.ResourceServer, error) { keyFile, err := client.ConfigFromKeyFileData(keyFileData) if err != nil { return nil, err } - return rs.NewResourceServerJWTProfile(ctx, s.OIDCIssuer(), keyFile.ClientID, keyFile.KeyID, []byte(keyFile.Key)) + return rs.NewResourceServerJWTProfile(ctx, i.OIDCIssuer(), keyFile.ClientID, keyFile.KeyID, []byte(keyFile.Key)) } -func (s *Tester) CreateResourceServerClientCredentials(ctx context.Context, clientID, clientSecret string) (rs.ResourceServer, error) { - return rs.NewResourceServerClientCredentials(ctx, s.OIDCIssuer(), clientID, clientSecret) +func (i *Instance) CreateResourceServerClientCredentials(ctx context.Context, clientID, clientSecret string) (rs.ResourceServer, error) { + return rs.NewResourceServerClientCredentials(ctx, i.OIDCIssuer(), clientID, clientSecret) } func GetRequest(url string, headers map[string]string) (*http.Request, error) { @@ -313,9 +322,9 @@ func CheckRedirect(req *http.Request) (*url.URL, error) { return resp.Location() } -func (s *Tester) CreateOIDCCredentialsClient(ctx context.Context) (machine *management.AddMachineUserResponse, name, clientID, clientSecret string, err error) { +func (i *Instance) CreateOIDCCredentialsClient(ctx context.Context) (machine *management.AddMachineUserResponse, name, clientID, clientSecret string, err error) { name = gofakeit.Username() - machine, err = s.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{ + machine, err = i.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{ Name: name, UserName: name, AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, @@ -323,7 +332,7 @@ func (s *Tester) CreateOIDCCredentialsClient(ctx context.Context) (machine *mana if err != nil { return nil, "", "", "", err } - secret, err := s.Client.Mgmt.GenerateMachineSecret(ctx, &management.GenerateMachineSecretRequest{ + secret, err := i.Client.Mgmt.GenerateMachineSecret(ctx, &management.GenerateMachineSecretRequest{ UserId: machine.GetUserId(), }) if err != nil { @@ -332,9 +341,9 @@ func (s *Tester) CreateOIDCCredentialsClient(ctx context.Context) (machine *mana return machine, name, secret.GetClientId(), secret.GetClientSecret(), nil } -func (s *Tester) CreateOIDCJWTProfileClient(ctx context.Context) (machine *management.AddMachineUserResponse, name string, keyData []byte, err error) { +func (i *Instance) CreateOIDCJWTProfileClient(ctx context.Context) (machine *management.AddMachineUserResponse, name string, keyData []byte, err error) { name = gofakeit.Username() - machine, err = s.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{ + machine, err = i.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{ Name: name, UserName: name, AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, @@ -342,7 +351,7 @@ func (s *Tester) CreateOIDCJWTProfileClient(ctx context.Context) (machine *manag if err != nil { return nil, "", nil, err } - keyResp, err := s.Client.Mgmt.AddMachineKey(ctx, &management.AddMachineKeyRequest{ + keyResp, err := i.Client.Mgmt.AddMachineKey(ctx, &management.AddMachineKeyRequest{ UserId: machine.GetUserId(), Type: authn.KeyType_KEY_TYPE_JSON, ExpirationDate: timestamppb.New(time.Now().Add(time.Hour)), diff --git a/internal/integration/sink/channel.go b/internal/integration/sink/channel.go new file mode 100644 index 0000000000..e25ae4d70c --- /dev/null +++ b/internal/integration/sink/channel.go @@ -0,0 +1,9 @@ +package sink + +//go:generate enumer -type Channel -trimprefix Channel -transform snake +type Channel int + +const ( + ChannelMilestone Channel = iota + ChannelQuota +) diff --git a/internal/integration/sink/channel_enumer.go b/internal/integration/sink/channel_enumer.go new file mode 100644 index 0000000000..85792ffec7 --- /dev/null +++ b/internal/integration/sink/channel_enumer.go @@ -0,0 +1,78 @@ +// Code generated by "enumer -type Channel -trimprefix Channel -transform snake"; DO NOT EDIT. + +package sink + +import ( + "fmt" + "strings" +) + +const _ChannelName = "milestonequota" + +var _ChannelIndex = [...]uint8{0, 9, 14} + +const _ChannelLowerName = "milestonequota" + +func (i Channel) String() string { + if i < 0 || i >= Channel(len(_ChannelIndex)-1) { + return fmt.Sprintf("Channel(%d)", i) + } + return _ChannelName[_ChannelIndex[i]:_ChannelIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _ChannelNoOp() { + var x [1]struct{} + _ = x[ChannelMilestone-(0)] + _ = x[ChannelQuota-(1)] +} + +var _ChannelValues = []Channel{ChannelMilestone, ChannelQuota} + +var _ChannelNameToValueMap = map[string]Channel{ + _ChannelName[0:9]: ChannelMilestone, + _ChannelLowerName[0:9]: ChannelMilestone, + _ChannelName[9:14]: ChannelQuota, + _ChannelLowerName[9:14]: ChannelQuota, +} + +var _ChannelNames = []string{ + _ChannelName[0:9], + _ChannelName[9:14], +} + +// ChannelString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func ChannelString(s string) (Channel, error) { + if val, ok := _ChannelNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _ChannelNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to Channel values", s) +} + +// ChannelValues returns all values of the enum +func ChannelValues() []Channel { + return _ChannelValues +} + +// ChannelStrings returns a slice of all String values of the enum +func ChannelStrings() []string { + strs := make([]string, len(_ChannelNames)) + copy(strs, _ChannelNames) + return strs +} + +// IsAChannel returns "true" if the value is listed in the enum definition. "false" otherwise +func (i Channel) IsAChannel() bool { + for _, v := range _ChannelValues { + if i == v { + return true + } + } + return false +} diff --git a/internal/integration/sink/server.go b/internal/integration/sink/server.go new file mode 100644 index 0000000000..959353ae5f --- /dev/null +++ b/internal/integration/sink/server.go @@ -0,0 +1,167 @@ +//go:build integration + +package sink + +import ( + "errors" + "io" + "net/http" + "net/url" + "path" + "sync" + "sync/atomic" + + "github.com/go-chi/chi/v5" + "github.com/gorilla/websocket" + "github.com/sirupsen/logrus" + "github.com/zitadel/logging" +) + +const ( + port = "8081" + listenAddr = "127.0.0.1:" + port + host = "localhost:" + port +) + +// CallURL returns the full URL to the handler of a [Channel]. +func CallURL(ch Channel) string { + u := url.URL{ + Scheme: "http", + Host: host, + Path: rootPath(ch), + } + return u.String() +} + +// StartServer starts a simple HTTP server on localhost:8081 +// ZITADEL can use the server to send HTTP requests which can be +// used to validate tests through [Subscribe]rs. +// For each [Channel] a route is registered on http://localhost:8081/. +// The route must be used to send the HTTP request to be validated. +// [CallURL] can be used to obtain the full URL for a given Channel. +// +// This function is only active when the `integration` build tag is enabled +func StartServer() (close func()) { + router := chi.NewRouter() + for _, ch := range ChannelValues() { + fwd := &forwarder{ + channelID: ch, + subscribers: make(map[int64]chan<- *Request), + } + router.HandleFunc(rootPath(ch), fwd.receiveHandler) + router.HandleFunc(subscribePath(ch), fwd.subscriptionHandler) + } + s := &http.Server{ + Addr: listenAddr, + Handler: router, + } + + logging.WithFields("listen_addr", listenAddr).Warn("!!!! A sink server is started which may expose sensitive data on a public endpoint. Make sure the `integration` build tag is disabled for production builds. !!!!") + go func() { + err := s.ListenAndServe() + if !errors.Is(err, http.ErrServerClosed) { + logging.WithError(err).Fatal("sink server") + } + }() + return func() { + logging.OnError(s.Close()).Error("sink server") + } +} + +func rootPath(c Channel) string { + return path.Join("/", c.String()) +} + +func subscribePath(c Channel) string { + return path.Join("/", c.String(), "subscribe") +} + +// forwarder handles incoming HTTP requests from ZITADEL and +// forwards them to all subscribed web sockets. +type forwarder struct { + channelID Channel + id atomic.Int64 + mtx sync.RWMutex + subscribers map[int64]chan<- *Request + upgrader websocket.Upgrader +} + +// receiveHandler receives a simple HTTP for a single [Channel] +// and forwards them on all active subscribers of that Channel. +func (c *forwarder) receiveHandler(w http.ResponseWriter, r *http.Request) { + req := &Request{ + Header: r.Header.Clone(), + } + var err error + req.Body, err = io.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + } + + c.mtx.RLock() + for _, reqChan := range c.subscribers { + reqChan <- req + } + c.mtx.RUnlock() + w.WriteHeader(http.StatusOK) +} + +// subscriptionHandler upgrades HTTP request to a websocket connection for subscribers. +// All received HTTP requests on a subscriber's channel are send on the websocket to the client. +func (c *forwarder) subscriptionHandler(w http.ResponseWriter, r *http.Request) { + ws, err := c.upgrader.Upgrade(w, r, nil) + logging.OnError(err).Error("websocket upgrade") + if err != nil { + return + } + done := readLoop(ws) + + id := c.id.Add(1) + reqChannel := make(chan *Request, 100) + + c.mtx.Lock() + c.subscribers[id] = reqChannel + c.mtx.Unlock() + + logging.WithFields("id", id, "channel", c.channelID).Info("websocket opened") + + defer func() { + c.mtx.Lock() + delete(c.subscribers, id) + c.mtx.Unlock() + + ws.Close() + close(reqChannel) + }() + + for { + select { + case err := <-done: + logging.WithError(err).WithFields(logrus.Fields{"id": id, "channel": c.channelID}).Info("websocket closed") + return + case req := <-reqChannel: + if err := ws.WriteJSON(req); err != nil { + logging.WithError(err).WithFields(logrus.Fields{"id": id, "channel": c.channelID}).Error("websocket write json") + return + } + } + } +} + +// readLoop makes sure we can receive close messages +func readLoop(ws *websocket.Conn) (done chan error) { + done = make(chan error, 1) + + go func(done chan<- error) { + for { + _, _, err := ws.NextReader() + if err != nil { + done <- err + break + } + } + close(done) + }(done) + + return done +} diff --git a/internal/integration/sink/sink.go b/internal/integration/sink/sink.go new file mode 100644 index 0000000000..fa339e4763 --- /dev/null +++ b/internal/integration/sink/sink.go @@ -0,0 +1,4 @@ +// Package sink provides a simple HTTP server where Zitadel can send HTTP based messages, +// which are then possible to be observed using observers on websockets. +// The contents of this package become available when the `integration` build tag is enabled. +package sink diff --git a/internal/integration/sink/stub.go b/internal/integration/sink/stub.go new file mode 100644 index 0000000000..01d1047f34 --- /dev/null +++ b/internal/integration/sink/stub.go @@ -0,0 +1,9 @@ +//go:build !integration + +package sink + +// StartServer and its returned close function are a no-op +// when the `integration` build tag is disabled. +func StartServer() (close func()) { + return func() {} +} diff --git a/internal/integration/sink/subscription.go b/internal/integration/sink/subscription.go new file mode 100644 index 0000000000..7d5ca36e91 --- /dev/null +++ b/internal/integration/sink/subscription.go @@ -0,0 +1,90 @@ +//go:build integration + +package sink + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "net/http" + "net/url" + "sync/atomic" + + "github.com/gorilla/websocket" + "github.com/zitadel/logging" +) + +// Request is a message forwarded from the handler to [Subscription]s. +type Request struct { + Header http.Header + Body json.RawMessage +} + +// Subscription is a websocket client to which [Request]s are forwarded by the server. +type Subscription struct { + conn *websocket.Conn + closed atomic.Bool + reqChannel chan *Request +} + +// Subscribe to a channel. +// The subscription forwards all requests it received on the channel's +// handler, after Subscribe has returned. +// Multiple subscription may be active on a single channel. +// Each request is always forwarded to each Subscription. +// Close must be called to cleanup up the Subscription's channel and go routine. +func Subscribe(ctx context.Context, ch Channel) *Subscription { + u := url.URL{ + Scheme: "ws", + Host: listenAddr, + Path: subscribePath(ch), + } + conn, resp, err := websocket.DefaultDialer.DialContext(ctx, u.String(), nil) + if err != nil { + if resp != nil { + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + err = fmt.Errorf("subscribe: %w, status: %s, body: %s", err, resp.Status, body) + } + panic(err) + } + + sub := &Subscription{ + conn: conn, + reqChannel: make(chan *Request, 10), + } + go sub.readToChan() + return sub +} + +func (s *Subscription) readToChan() { + for { + if s.closed.Load() { + break + } + req := new(Request) + if err := s.conn.ReadJSON(req); err != nil { + opErr := new(net.OpError) + if errors.As(err, &opErr) { + break + } + logging.WithError(err).Error("subscription read") + break + } + s.reqChannel <- req + } + close(s.reqChannel) +} + +// Recv returns the channel over which [Request]s are send. +func (s *Subscription) Recv() <-chan *Request { + return s.reqChannel +} + +func (s *Subscription) Close() error { + s.closed.Store(true) + return s.conn.Close() +} diff --git a/internal/integration/system.go b/internal/integration/system.go new file mode 100644 index 0000000000..a9673a40ae --- /dev/null +++ b/internal/integration/system.go @@ -0,0 +1,59 @@ +package integration + +import ( + "context" + _ "embed" + "sync" + "time" + + "github.com/zitadel/oidc/v3/pkg/client" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + http_util "github.com/zitadel/zitadel/internal/api/http" + "github.com/zitadel/zitadel/pkg/grpc/system" +) + +var ( + //go:embed config/system-user-key.pem + systemUserKey []byte +) + +var ( + // SystemClient creates a system connection once and reuses it on every use. + // Each client call automatically gets the authorization context for the system user. + SystemClient = sync.OnceValue[system.SystemServiceClient](systemClient) + SystemToken string +) + +func systemClient() system.SystemServiceClient { + cc, err := grpc.NewClient(loadedConfig.Host(), + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithChainUnaryInterceptor(func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + ctx = WithSystemAuthorization(ctx) + return invoker(ctx, method, req, reply, cc, opts...) + }), + ) + if err != nil { + panic(err) + } + return system.NewSystemServiceClient(cc) +} + +func systemUserToken() string { + const ISSUER = "tester" + audience := http_util.BuildOrigin(loadedConfig.Host(), loadedConfig.Secure) + signer, err := client.NewSignerFromPrivateKeyByte(systemUserKey, "") + if err != nil { + panic(err) + } + token, err := client.SignedJWTProfileAssertion(ISSUER, []string{audience}, time.Hour, signer) + if err != nil { + panic(err) + } + return token +} + +func WithSystemAuthorization(ctx context.Context) context.Context { + return WithAuthorizationToken(ctx, SystemToken) +} diff --git a/internal/integration/user.go b/internal/integration/user.go index 60a6e41318..6eb26fa5a7 100644 --- a/internal/integration/user.go +++ b/internal/integration/user.go @@ -11,10 +11,10 @@ import ( "github.com/zitadel/zitadel/pkg/grpc/management" ) -func (s *Tester) CreateMachineUserPATWithMembership(ctx context.Context, roles ...string) (id, pat string, err error) { - user := s.CreateMachineUser(ctx) +func (i *Instance) CreateMachineUserPATWithMembership(ctx context.Context, roles ...string) (id, pat string, err error) { + user := i.CreateMachineUser(ctx) - patResp, err := s.Client.Mgmt.AddPersonalAccessToken(ctx, &management.AddPersonalAccessTokenRequest{ + patResp, err := i.Client.Mgmt.AddPersonalAccessToken(ctx, &management.AddPersonalAccessTokenRequest{ UserId: user.GetUserId(), ExpirationDate: timestamppb.New(time.Now().Add(24 * time.Hour)), }) @@ -35,7 +35,7 @@ func (s *Tester) CreateMachineUserPATWithMembership(ctx context.Context, roles . } if len(orgRoles) > 0 { - _, err := s.Client.Mgmt.AddOrgMember(ctx, &management.AddOrgMemberRequest{ + _, err := i.Client.Mgmt.AddOrgMember(ctx, &management.AddOrgMemberRequest{ UserId: user.GetUserId(), Roles: orgRoles, }) @@ -44,7 +44,7 @@ func (s *Tester) CreateMachineUserPATWithMembership(ctx context.Context, roles . } } if len(iamRoles) > 0 { - _, err := s.Client.Admin.AddIAMMember(ctx, &admin.AddIAMMemberRequest{ + _, err := i.Client.Admin.AddIAMMember(ctx, &admin.AddIAMMemberRequest{ UserId: user.GetUserId(), Roles: iamRoles, }) diff --git a/internal/integration/usertype_enumer.go b/internal/integration/usertype_enumer.go new file mode 100644 index 0000000000..66d49ced4d --- /dev/null +++ b/internal/integration/usertype_enumer.go @@ -0,0 +1,86 @@ +// Code generated by "enumer -type UserType -transform snake -trimprefix UserType"; DO NOT EDIT. + +package integration + +import ( + "fmt" + "strings" +) + +const _UserTypeName = "unspecifiediam_ownerorg_ownerlogin" + +var _UserTypeIndex = [...]uint8{0, 11, 20, 29, 34} + +const _UserTypeLowerName = "unspecifiediam_ownerorg_ownerlogin" + +func (i UserType) String() string { + if i < 0 || i >= UserType(len(_UserTypeIndex)-1) { + return fmt.Sprintf("UserType(%d)", i) + } + return _UserTypeName[_UserTypeIndex[i]:_UserTypeIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _UserTypeNoOp() { + var x [1]struct{} + _ = x[UserTypeUnspecified-(0)] + _ = x[UserTypeIAMOwner-(1)] + _ = x[UserTypeOrgOwner-(2)] + _ = x[UserTypeLogin-(3)] +} + +var _UserTypeValues = []UserType{UserTypeUnspecified, UserTypeIAMOwner, UserTypeOrgOwner, UserTypeLogin} + +var _UserTypeNameToValueMap = map[string]UserType{ + _UserTypeName[0:11]: UserTypeUnspecified, + _UserTypeLowerName[0:11]: UserTypeUnspecified, + _UserTypeName[11:20]: UserTypeIAMOwner, + _UserTypeLowerName[11:20]: UserTypeIAMOwner, + _UserTypeName[20:29]: UserTypeOrgOwner, + _UserTypeLowerName[20:29]: UserTypeOrgOwner, + _UserTypeName[29:34]: UserTypeLogin, + _UserTypeLowerName[29:34]: UserTypeLogin, +} + +var _UserTypeNames = []string{ + _UserTypeName[0:11], + _UserTypeName[11:20], + _UserTypeName[20:29], + _UserTypeName[29:34], +} + +// UserTypeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func UserTypeString(s string) (UserType, error) { + if val, ok := _UserTypeNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _UserTypeNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to UserType values", s) +} + +// UserTypeValues returns all values of the enum +func UserTypeValues() []UserType { + return _UserTypeValues +} + +// UserTypeStrings returns a slice of all String values of the enum +func UserTypeStrings() []string { + strs := make([]string, len(_UserTypeNames)) + copy(strs, _UserTypeNames) + return strs +} + +// IsAUserType returns "true" if the value is listed in the enum definition. "false" otherwise +func (i UserType) IsAUserType() bool { + for _, v := range _UserTypeValues { + if i == v { + return true + } + } + return false +} diff --git a/internal/integration/usertype_string.go b/internal/integration/usertype_string.go deleted file mode 100644 index 6477630986..0000000000 --- a/internal/integration/usertype_string.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by "stringer -type=UserType"; DO NOT EDIT. - -package integration - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[Unspecified-0] - _ = x[OrgOwner-1] - _ = x[Login-2] - _ = x[IAMOwner-3] - _ = x[SystemUser-4] -} - -const _UserType_name = "UnspecifiedOrgOwnerLoginIAMOwnerSystemUser" - -var _UserType_index = [...]uint8{0, 11, 19, 24, 32, 42} - -func (i UserType) String() string { - if i < 0 || i >= UserType(len(_UserType_index)-1) { - return "UserType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _UserType_name[_UserType_index[i]:_UserType_index[i+1]] -} diff --git a/internal/notification/handlers/handlers_integration_test.go b/internal/notification/handlers/handlers_integration_test.go deleted file mode 100644 index 329bba1310..0000000000 --- a/internal/notification/handlers/handlers_integration_test.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build integration - -package handlers_test - -import ( - "context" - "os" - "testing" - "time" - - "github.com/zitadel/zitadel/internal/integration" -) - -var ( - CTX context.Context - SystemCTX context.Context - Tester *integration.Tester -) - -func TestMain(m *testing.M) { - os.Exit(func() int { - ctx, _, cancel := integration.Contexts(5 * time.Minute) - defer cancel() - CTX = ctx - - Tester = integration.NewTester(ctx, ` -Quotas: - Access: - Enabled: true -`) - defer Tester.Done() - - SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser) - return m.Run() - }()) -} diff --git a/internal/notification/handlers/integration_test/handlers_test.go b/internal/notification/handlers/integration_test/handlers_test.go new file mode 100644 index 0000000000..3b2dfe2406 --- /dev/null +++ b/internal/notification/handlers/integration_test/handlers_test.go @@ -0,0 +1,23 @@ +//go:build integration + +package handlers_test + +import ( + "context" + "os" + "testing" + "time" +) + +var ( + CTX context.Context +) + +func TestMain(m *testing.M) { + os.Exit(func() int { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + CTX = ctx + return m.Run() + }()) +} diff --git a/internal/notification/handlers/telemetry_pusher_integration_test.go b/internal/notification/handlers/integration_test/telemetry_pusher_test.go similarity index 53% rename from internal/notification/handlers/telemetry_pusher_integration_test.go rename to internal/notification/handlers/integration_test/telemetry_pusher_test.go index 8f207b9de3..c12ab64f35 100644 --- a/internal/notification/handlers/telemetry_pusher_integration_test.go +++ b/internal/notification/handlers/integration_test/telemetry_pusher_test.go @@ -4,7 +4,6 @@ package handlers_test import ( "bytes" - "context" "encoding/json" "net/url" "testing" @@ -16,6 +15,7 @@ import ( "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel/internal/integration" + "github.com/zitadel/zitadel/internal/integration/sink" "github.com/zitadel/zitadel/pkg/grpc/app" "github.com/zitadel/zitadel/pkg/grpc/management" "github.com/zitadel/zitadel/pkg/grpc/object" @@ -25,16 +25,20 @@ import ( ) func TestServer_TelemetryPushMilestones(t *testing.T) { - primaryDomain, instanceID, adminID, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX) - t.Log("testing against instance with primary domain", primaryDomain) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "InstanceCreated") + sub := sink.Subscribe(CTX, sink.ChannelMilestone) + defer sub.Close() - projectAdded, err := Tester.Client.Mgmt.AddProject(iamOwnerCtx, &management.AddProjectRequest{Name: "integration"}) + instance := integration.NewInstance(CTX) + iamOwnerCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + t.Log("testing against instance with primary domain", instance.Domain) + awaitMilestone(t, sub, instance.Domain, "InstanceCreated") + + projectAdded, err := instance.Client.Mgmt.AddProject(iamOwnerCtx, &management.AddProjectRequest{Name: "integration"}) require.NoError(t, err) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "ProjectCreated") + awaitMilestone(t, sub, instance.Domain, "ProjectCreated") redirectURI := "http://localhost:8888" - application, err := Tester.Client.Mgmt.AddOIDCApp(iamOwnerCtx, &management.AddOIDCAppRequest{ + application, err := instance.Client.Mgmt.AddOIDCApp(iamOwnerCtx, &management.AddOIDCAppRequest{ ProjectId: projectAdded.GetId(), Name: "integration", RedirectUris: []string{redirectURI}, @@ -46,35 +50,37 @@ func TestServer_TelemetryPushMilestones(t *testing.T) { AccessTokenType: app.OIDCTokenType_OIDC_TOKEN_TYPE_JWT, }) require.NoError(t, err) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "ApplicationCreated") + awaitMilestone(t, sub, instance.Domain, "ApplicationCreated") // create the session to be used for the authN of the clients - sessionID, sessionToken, _, _ := Tester.CreatePasswordSession(t, iamOwnerCtx, adminID, "Password1!") + sessionID, sessionToken, _, _ := instance.CreatePasswordSession(t, iamOwnerCtx, instance.AdminUserID, "Password1!") - console := consoleOIDCConfig(iamOwnerCtx, t) - loginToClient(iamOwnerCtx, t, primaryDomain, console.GetClientId(), instanceID, console.GetRedirectUris()[0], sessionID, sessionToken) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "AuthenticationSucceededOnInstance") + console := consoleOIDCConfig(t, instance) + loginToClient(t, instance, console.GetClientId(), console.GetRedirectUris()[0], sessionID, sessionToken) + awaitMilestone(t, sub, instance.Domain, "AuthenticationSucceededOnInstance") // make sure the client has been projected require.EventuallyWithT(t, func(collectT *assert.CollectT) { - _, err := Tester.Client.Mgmt.GetAppByID(iamOwnerCtx, &management.GetAppByIDRequest{ + _, err := instance.Client.Mgmt.GetAppByID(iamOwnerCtx, &management.GetAppByIDRequest{ ProjectId: projectAdded.GetId(), AppId: application.GetAppId(), }) assert.NoError(collectT, err) - }, 1*time.Minute, 100*time.Millisecond, "app not found") - loginToClient(iamOwnerCtx, t, primaryDomain, application.GetClientId(), instanceID, redirectURI, sessionID, sessionToken) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "AuthenticationSucceededOnApplication") + }, time.Minute, time.Second, "app not found") + loginToClient(t, instance, application.GetClientId(), redirectURI, sessionID, sessionToken) + awaitMilestone(t, sub, instance.Domain, "AuthenticationSucceededOnApplication") - _, err = Tester.Client.System.RemoveInstance(SystemCTX, &system.RemoveInstanceRequest{InstanceId: instanceID}) + _, err = integration.SystemClient().RemoveInstance(CTX, &system.RemoveInstanceRequest{InstanceId: instance.ID()}) require.NoError(t, err) - awaitMilestone(t, Tester.MilestoneChan, primaryDomain, "InstanceDeleted") + awaitMilestone(t, sub, instance.Domain, "InstanceDeleted") } -func loginToClient(iamOwnerCtx context.Context, t *testing.T, primaryDomain, clientID, instanceID, redirectURI, sessionID, sessionToken string) { - authRequestID, err := Tester.CreateOIDCAuthRequestWithDomain(iamOwnerCtx, primaryDomain, clientID, Tester.Users.Get(instanceID, integration.IAMOwner).ID, redirectURI, "openid") +func loginToClient(t *testing.T, instance *integration.Instance, clientID, redirectURI, sessionID, sessionToken string) { + iamOwnerCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + + authRequestID, err := instance.CreateOIDCAuthRequestWithDomain(iamOwnerCtx, instance.Domain, clientID, instance.Users.Get(integration.UserTypeIAMOwner).ID, redirectURI, "openid") require.NoError(t, err) - callback, err := Tester.Client.OIDCv2.CreateCallback(iamOwnerCtx, &oidc_v2.CreateCallbackRequest{ + callback, err := instance.Client.OIDCv2.CreateCallback(iamOwnerCtx, &oidc_v2.CreateCallbackRequest{ AuthRequestId: authRequestID, CallbackKind: &oidc_v2.CreateCallbackRequest_Session{Session: &oidc_v2.Session{ SessionId: sessionID, @@ -82,7 +88,7 @@ func loginToClient(iamOwnerCtx context.Context, t *testing.T, primaryDomain, cli }}, }) require.NoError(t, err) - provider, err := Tester.CreateRelyingPartyForDomain(iamOwnerCtx, primaryDomain, clientID, redirectURI) + provider, err := instance.CreateRelyingPartyForDomain(iamOwnerCtx, instance.Domain, clientID, redirectURI) require.NoError(t, err) callbackURL, err := url.Parse(callback.GetCallbackUrl()) require.NoError(t, err) @@ -91,8 +97,10 @@ func loginToClient(iamOwnerCtx context.Context, t *testing.T, primaryDomain, cli require.NoError(t, err) } -func consoleOIDCConfig(iamOwnerCtx context.Context, t *testing.T) *app.OIDCConfig { - projects, err := Tester.Client.Mgmt.ListProjects(iamOwnerCtx, &management.ListProjectsRequest{ +func consoleOIDCConfig(t *testing.T, instance *integration.Instance) *app.OIDCConfig { + iamOwnerCtx := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner) + + projects, err := instance.Client.Mgmt.ListProjects(iamOwnerCtx, &management.ListProjectsRequest{ Queries: []*project.ProjectQuery{ { Query: &project.ProjectQuery_NameQuery{ @@ -106,7 +114,7 @@ func consoleOIDCConfig(iamOwnerCtx context.Context, t *testing.T) *app.OIDCConfi }) require.NoError(t, err) require.Len(t, projects.GetResult(), 1) - apps, err := Tester.Client.Mgmt.ListApps(iamOwnerCtx, &management.ListAppsRequest{ + apps, err := instance.Client.Mgmt.ListApps(iamOwnerCtx, &management.ListAppsRequest{ ProjectId: projects.GetResult()[0].GetId(), Queries: []*app.AppQuery{ { @@ -124,12 +132,12 @@ func consoleOIDCConfig(iamOwnerCtx context.Context, t *testing.T) *app.OIDCConfi return apps.GetResult()[0].GetOidcConfig() } -func awaitMilestone(t *testing.T, bodies chan []byte, primaryDomain, expectMilestoneType string) { +func awaitMilestone(t *testing.T, sub *sink.Subscription, primaryDomain, expectMilestoneType string) { for { select { - case body := <-bodies: + case req := <-sub.Recv(): plain := new(bytes.Buffer) - if err := json.Indent(plain, body, "", " "); err != nil { + if err := json.Indent(plain, req.Body, "", " "); err != nil { t.Fatal(err) } t.Log("received milestone", plain.String()) @@ -137,13 +145,13 @@ func awaitMilestone(t *testing.T, bodies chan []byte, primaryDomain, expectMiles Type string `json:"type"` PrimaryDomain string `json:"primaryDomain"` }{} - if err := json.Unmarshal(body, &milestone); err != nil { + if err := json.Unmarshal(req.Body, &milestone); err != nil { t.Error(err) } if milestone.Type == expectMilestoneType && milestone.PrimaryDomain == primaryDomain { return } - case <-time.After(60 * time.Second): + case <-time.After(2 * time.Minute): // why does it take so long to get a milestone !? t.Fatalf("timed out waiting for milestone %s in domain %s", expectMilestoneType, primaryDomain) } } diff --git a/internal/notification/handlers/quota_notifier_test.go b/internal/notification/handlers/quota_notifier_test.go deleted file mode 100644 index 14de4e369c..0000000000 --- a/internal/notification/handlers/quota_notifier_test.go +++ /dev/null @@ -1,155 +0,0 @@ -//go:build integration - -package handlers_test - -import ( - "bytes" - "encoding/json" - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/timestamppb" - - "github.com/zitadel/zitadel/internal/repository/quota" - "github.com/zitadel/zitadel/pkg/grpc/admin" - quota_pb "github.com/zitadel/zitadel/pkg/grpc/quota" - "github.com/zitadel/zitadel/pkg/grpc/system" -) - -func TestServer_QuotaNotification_Limit(t *testing.T) { - _, instanceID, _, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX) - amount := 10 - percent := 50 - percentAmount := amount * percent / 100 - - _, err := Tester.Client.System.AddQuota(SystemCTX, &system.AddQuotaRequest{ - InstanceId: instanceID, - Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, - From: timestamppb.Now(), - ResetInterval: durationpb.New(time.Minute * 5), - Amount: uint64(amount), - Limit: true, - Notifications: []*quota_pb.Notification{ - { - Percent: uint32(percent), - Repeat: true, - CallUrl: "http://localhost:8082", - }, - { - Percent: 100, - Repeat: true, - CallUrl: "http://localhost:8082", - }, - }, - }) - require.NoError(t, err) - - for i := 0; i < percentAmount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - if err != nil { - require.NoError(t, fmt.Errorf("error in %d call of %d: %f", i, percentAmount, err)) - } - } - awaitNotification(t, time.Now(), Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent) - - for i := 0; i < (amount - percentAmount); i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - require.NoError(t, err) - } - awaitNotification(t, time.Now(), Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100) - - _, limitErr := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - require.Error(t, limitErr) -} - -func TestServer_QuotaNotification_NoLimit(t *testing.T) { - _, instanceID, _, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX) - amount := 10 - percent := 50 - percentAmount := amount * percent / 100 - - _, err := Tester.Client.System.AddQuota(SystemCTX, &system.AddQuotaRequest{ - InstanceId: instanceID, - Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED, - From: timestamppb.Now(), - ResetInterval: durationpb.New(time.Minute * 5), - Amount: uint64(amount), - Limit: false, - Notifications: []*quota_pb.Notification{ - { - Percent: uint32(percent), - Repeat: false, - CallUrl: "http://localhost:8082", - }, - { - Percent: 100, - Repeat: true, - CallUrl: "http://localhost:8082", - }, - }, - }) - require.NoError(t, err) - - for i := 0; i < percentAmount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - if err != nil { - require.NoError(t, fmt.Errorf("error in %d call of %d: %f", i, percentAmount, err)) - } - } - awaitNotification(t, time.Now(), Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent) - - for i := 0; i < (amount - percentAmount); i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - if err != nil { - require.NoError(t, fmt.Errorf("error in %d call of %d: %f", percentAmount+i, amount, err)) - } - } - awaitNotification(t, time.Now(), Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100) - - for i := 0; i < amount; i++ { - _, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - if err != nil { - require.NoError(t, fmt.Errorf("error in %d call of %d over limit: %f", i, amount, err)) - } - } - awaitNotification(t, time.Now(), Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 200) - - _, limitErr := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{}) - require.NoError(t, limitErr) -} - -func awaitNotification(t *testing.T, start time.Time, bodies chan []byte, unit quota.Unit, percent int) { - for { - select { - case body := <-bodies: - plain := new(bytes.Buffer) - if err := json.Indent(plain, body, "", " "); err != nil { - t.Fatal(err) - } - t.Log("received notificationDueEvent", plain.String()) - event := struct { - Unit quota.Unit `json:"unit"` - ID string `json:"id"` - CallURL string `json:"callURL"` - PeriodStart time.Time `json:"periodStart"` - Threshold uint16 `json:"threshold"` - Usage uint64 `json:"usage"` - }{} - if err := json.Unmarshal(body, &event); err != nil { - t.Error(err) - } - if event.ID == "" { - continue - } - if event.Unit == unit && event.Threshold == uint16(percent) { - return - } - case <-time.After(20 * time.Second): - t.Fatalf("start %s stop %s timed out waiting for unit %s and percent %d", start.Format(time.RFC3339), time.Now().Format(time.RFC3339), strconv.Itoa(int(unit)), percent) - } - } -} diff --git a/internal/webauthn/webauthn.go b/internal/webauthn/webauthn.go index 5938f885bc..998c013a3c 100644 --- a/internal/webauthn/webauthn.go +++ b/internal/webauthn/webauthn.go @@ -100,7 +100,7 @@ func (w *Config) FinishRegistration(ctx context.Context, user *domain.Human, web } credentialData, err := protocol.ParseCredentialCreationResponseBody(bytes.NewReader(credData)) if err != nil { - logging.WithFields("error", tryExtractProtocolErrMsg(err)).Debug("webauthn credential could not be parsed") + logging.WithFields("error", tryExtractProtocolErrMsg(err), "err_id", "WEBAU-sEr8c").Debug("webauthn credential could not be parsed") return nil, zerrors.ThrowInternal(err, "WEBAU-sEr8c", "Errors.User.WebAuthN.ErrorOnParseCredential") } sessionData := WebAuthNToSessionData(webAuthN) @@ -115,7 +115,7 @@ func (w *Config) FinishRegistration(ctx context.Context, user *domain.Human, web sessionData, credentialData) if err != nil { - logging.WithFields("error", tryExtractProtocolErrMsg(err)).Debug("webauthn credential could not be created") + logging.WithFields("error", tryExtractProtocolErrMsg(err), "err_id", "WEBAU-3Vb9s").Debug("webauthn credential could not be created") return nil, zerrors.ThrowInternal(err, "WEBAU-3Vb9s", "Errors.User.WebAuthN.CreateCredentialFailed") }