diff --git a/Makefile b/Makefile index 57d491bf..a9727e8b 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ build-kms-cli-binaries: @docker run -i --rm \ -v $(abspath .):/opt/workspace/kms \ --entrypoint "/opt/workspace/kms/scripts/build-cli.sh" \ - ghcr.io/gythialy/golang-cross:latest + ghcr.io/gythialy/golang-cross:go-1.18 .PHONY: extract-kms-cli-binaries extract-kms-cli-binaries: diff --git a/test/bdd/features/keystore_api.feature b/test/bdd/features/keystore_api.feature index 0467c42b..654e6673 100644 --- a/test/bdd/features/keystore_api.feature +++ b/test/bdd/features/keystore_api.feature @@ -9,7 +9,6 @@ Feature: Keystore management operations Scenario: User creates a keystore - Given Key Server is running on "localhost" port "4466" - And Hub Auth is running on "auth.trustbloc.local" port "8070" - When user makes an HTTP POST to "https://localhost:4466/v1/keystores" to create a keystore + Given Key Server is running on "localhost" port "8076" + When user makes an HTTP POST to "https://localhost:8076/v1/keystores" to create a keystore Then user gets a response with HTTP status "200 OK" and valid key store URL and root capabilities diff --git a/test/bdd/features/kms_api.feature b/test/bdd/features/kms_api.feature index 06769f0a..f3eb8422 100644 --- a/test/bdd/features/kms_api.feature +++ b/test/bdd/features/kms_api.feature @@ -8,37 +8,34 @@ @kms Feature: KMS and crypto operations Background: - Given Key Server is running on "localhost" port "4466" - And Hub Auth is running on "auth.trustbloc.local" port "8070" - And "Alice" has logged into auth server - And "Bob" has logged into auth server - And "Alice" has created a profile on auth server - And "Bob" has created a profile on auth server + Given Key Server is running on "localhost" port "8076" + And "Alice" has configured ZCAP authentication + And "Bob" has configured ZCAP authentication Scenario: User creates a key Given "Alice" has created an empty keystore on Key Server - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys" to create "ED25519" key + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys" to create "ED25519" key Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "key_url" Scenario: User creates multiple keys with parallel requests Given "Alice" has created an empty keystore on Key Server - When "Alice" makes parallel HTTP POST requests to "https://localhost:4466/v1/keystores/{keystoreID}/keys" to create "AES128GCM,ChaCha20Poly1305,XChaCha20Poly1305,ED25519,HMACSHA256Tag256,NISTP256ECDHKW,X25519ECDHKW,BLS12381G2" keys + When "Alice" makes parallel HTTP POST requests to "https://localhost:8076/v1/keystores/{keystoreID}/keys" to create "AES128GCM,ChaCha20Poly1305,XChaCha20Poly1305,ED25519,HMACSHA256Tag256,NISTP256ECDHKW,X25519ECDHKW,BLS12381G2" keys Then "Alice" gets a response with HTTP status "200 OK" for each request Scenario: User exports a public key Given "Bob" has created a keystore with "ED25519" key on Key Server - When "Bob" makes an HTTP GET to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/export" to export public key + When "Bob" makes an HTTP GET to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/export" to export public key Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with non-empty "public_key" Scenario: User creates and exports a key Given "Alice" has created an empty keystore on Key Server - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys" to create and export "ED25519" key + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys" to create and export "ED25519" key Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "key_url" And "Alice" gets a response with non-empty "public_key" @@ -46,52 +43,52 @@ Feature: KMS and crypto operations Scenario: User imports a private key Given "Bob" has created an empty keystore on Key Server - When "Bob" makes an HTTP PUT to "https://localhost:4466/v1/keystores/{keystoreID}/keys" to import a private key with ID "keyID" + When "Bob" makes an HTTP PUT to "https://localhost:8076/v1/keystores/{keystoreID}/keys" to import a private key with ID "keyID" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with "key_url" with value "https://kms.trustbloc.local:8076/v1/keystores/([^/]+)/keys/keyID" Scenario: User signs a message and verifies a signature Given "Alice" has created a keystore with "ED25519" key on Key Server - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/sign" to sign "test message" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/sign" to sign "test message" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "signature" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/verify" to verify "signature" for "test message" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/verify" to verify "signature" for "test message" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with no "errMessage" Scenario: User creates and rotates a key Given "Alice" has created a keystore with "AES256GCM" key on Key Server - And "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/encrypt" to encrypt "test message" + And "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/encrypt" to encrypt "test message" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/rotate" to rotate "AES256GCM" key + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/rotate" to rotate "AES256GCM" key Then "Alice" gets a response with HTTP status "200 OK" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/decrypt" to decrypt "ciphertext" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/decrypt" to decrypt "ciphertext" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with "plaintext" with value "test message" Scenario: User encrypts/decrypts a message Given "Bob" has created a keystore with "AES256GCM" key on Key Server - When "Bob" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/encrypt" to encrypt "test message" + When "Bob" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/encrypt" to encrypt "test message" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with non-empty "ciphertext" And "Bob" gets a response with non-empty "nonce" - When "Bob" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/decrypt" to decrypt "ciphertext" + When "Bob" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/decrypt" to decrypt "ciphertext" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with "plaintext" with value "test message" Scenario: User computes/verifies MAC for data Given "Alice" has created a keystore with "HMACSHA256Tag256" key on Key Server - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/computemac" to compute MAC for "test data" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/computemac" to compute MAC for "test data" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "mac" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/verifymac" to verify MAC "mac" for "test data" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/verifymac" to verify MAC "mac" for "test data" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with no "errMessage" @@ -100,11 +97,11 @@ Feature: KMS and crypto operations And "Bob" has created a keystore with "NISTP256ECDHKW" key on Key Server And "Alice" has a public key of "Bob" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/wrap" to wrap "testCEK" for "Bob" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/wrap" to wrap "testCEK" for "Bob" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "wrapped_key" - When "Bob" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to unwrap "wrapped_key" from "Alice" + When "Bob" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to unwrap "wrapped_key" from "Alice" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with content of "testCEK" key @@ -113,10 +110,10 @@ Feature: KMS and crypto operations And "Bob" has created a keystore with "X25519ECDHKW" key on Key Server And "Alice" has a public key of "Bob" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/wrap" to wrap "testCEK" for "Bob" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/wrap" to wrap "testCEK" for "Bob" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "wrapped_key" - When "Bob" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to unwrap "wrapped_key" from "Alice" + When "Bob" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to unwrap "wrapped_key" from "Alice" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with content of "testCEK" key diff --git a/test/bdd/features/kms_crypto_box_api.feature b/test/bdd/features/kms_crypto_box_api.feature index 9060c909..d1fe5dc1 100644 --- a/test/bdd/features/kms_crypto_box_api.feature +++ b/test/bdd/features/kms_crypto_box_api.feature @@ -8,12 +8,9 @@ @kms_crypto_box Feature: KMS CryptoBox operations Background: - Given Key Server is running on "localhost" port "4466" - And Hub Auth is running on "auth.trustbloc.local" port "8070" - And "Alice" has logged into auth server - And "Bob" has logged into auth server - And "Alice" has created a profile on auth server - And "Bob" has created a profile on auth server + Given Key Server is running on "localhost" port "8076" + And "Alice" has configured ZCAP authentication + And "Bob" has configured ZCAP authentication Scenario: User A anonymously encrypts (wrap as "easy") a payload for User B, User B decrypts (unwrap as "easy open") it Given "Alice" has created a keystore with "ED25519" key on Key Server @@ -21,13 +18,13 @@ Feature: KMS CryptoBox operations And "Alice" has a public key of "Bob" And "Bob" has a public key of "Alice" - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/wrap" to easy "test payload" for "Bob" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/wrap" to easy "test payload" for "Bob" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with non-empty "ciphertext" # since easyOpen now works like unwrap, adding `keys/{keyID}` below is necessary to follow the same pattern as unwrap even if # easyOpen does not use keyID (it uses keys found in the POST request instead) - When "Bob" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to easyOpen "ciphertext" from "Alice" + When "Bob" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to easyOpen "ciphertext" from "Alice" Then "Bob" gets a response with HTTP status "200 OK" And "Bob" gets a response with "plaintext" with value "test payload" @@ -39,6 +36,6 @@ Feature: KMS CryptoBox operations # since sealOpen now works like unwrap, adding `keys/{keyID}` below is necessary to follow the same pattern as unwrap even if # sealOpen does not use keyID (it uses keys found in the POST request instead) - When "Alice" makes an HTTP POST to "https://localhost:4466/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to sealOpen "ciphertext" from "Bob" + When "Alice" makes an HTTP POST to "https://localhost:8076/v1/keystores/{keystoreID}/keys/{keyID}/unwrap" to sealOpen "ciphertext" from "Bob" Then "Alice" gets a response with HTTP status "200 OK" And "Alice" gets a response with "plaintext" with value "test payload" diff --git a/test/bdd/fixtures/docker-compose.yml b/test/bdd/fixtures/docker-compose.yml index a82212a8..57070a2a 100644 --- a/test/bdd/fixtures/docker-compose.yml +++ b/test/bdd/fixtures/docker-compose.yml @@ -167,27 +167,6 @@ services: networks: - bdd_net - - oathkeeper-ops-keyserver.trustbloc.local: - container_name: oathkeeper-ops-keyserver.trustbloc.local - image: oryd/oathkeeper:v0.38.4-alpine - ports: - - 4466:4466 - command: /bin/sh -c "cp /etc/tls/ec-cacert.pem /usr/local/share/ca-certificates/;update-ca-certificates;oathkeeper serve proxy --config /oathkeeper/config.yaml" - user: root - entrypoint: "" - environment: - - LOG_LEVEL=debug - - PORT=4466 - - ISSUER_URL=https://oathkeeper-proxy.trustbloc.local - - SERVE_PROXY_TLS_KEY_PATH=/etc/tls/ec-key.pem - - SERVE_PROXY_TLS_CERT_PATH=/etc/tls/ec-pubCert.pem - volumes: - - ./oathkeeper-config/ops-keyserver:/oathkeeper - - ./keys/tls:/etc/tls - networks: - - bdd_net - auth.trustbloc.local: container_name: auth.trustbloc.local image: ${AUTH_REST_IMAGE}:${AUTH_REST_IMAGE_TAG} diff --git a/test/bdd/fixtures/oathkeeper-config/auth-keyserver/config.yaml b/test/bdd/fixtures/oathkeeper-config/auth-keyserver/config.yaml deleted file mode 100644 index 445b14ad..00000000 --- a/test/bdd/fixtures/oathkeeper-config/auth-keyserver/config.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright SecureKey Technologies Inc. All Rights Reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# - -serve: - proxy: - port: 4455 - api: - port: 4458 - -access_rules: - repositories: - - file:///oathkeeper/rules/resource-server.json - matching_strategy: glob - -authenticators: - oauth2_introspection: - enabled: true - config: - introspection_url: https://hydra.trustbloc.local:4445/oauth2/introspect - noop: - enabled: true - -authorizers: - allow: - enabled: true - -mutators: - header: - enabled: true - config: - headers: - AUTH-USER: '{{ print .Subject }}' - noop: - enabled: true diff --git a/test/bdd/fixtures/oathkeeper-config/auth-keyserver/rules/resource-server.json b/test/bdd/fixtures/oathkeeper-config/auth-keyserver/rules/resource-server.json deleted file mode 100644 index 175553cb..00000000 --- a/test/bdd/fixtures/oathkeeper-config/auth-keyserver/rules/resource-server.json +++ /dev/null @@ -1,73 +0,0 @@ -[ - { - "id": "auth-kms-create-keystore", - "upstream": { - "url": "https://authz-kms.trustbloc.local:8077" - }, - "match": { - "url": "https://localhost:4455/v1/keystores", - "methods": ["POST"] - }, - "authenticators": [{ - "handler": "oauth2_introspection" - }], - "mutators": [ - { - "handler": "header", - "config": { - "headers": { - "Auth-User": "{{ print .Subject }}" - } - } - } - ], - "authorizer": { - "handler": "allow" - } - }, - { - "id": "auth-kms-keystore-ops", - "upstream": { - "url": "https://authz-kms.trustbloc.local:8077" - }, - "match": { - "url": "https://localhost:4455/v1/keystores/<*>", - "methods": ["POST", "GET"] - }, - "authenticators": [{ - "handler": "oauth2_introspection" - }], - "mutators": [ - { - "handler": "header", - "config": { - "headers": { - "Auth-User": "{{ print .Subject }}" - } - } - } - ], - "authorizer": { - "handler": "allow" - } - }, - { - "id": "ops-kms-health", - "upstream": { - "url": "https://authz-kms.trustbloc.local:8077" - }, - "match": { - "url": "http://localhost:4466/healthcheck", - "methods": ["GET"] - }, - "authenticators": [{ - "handler": "noop" - }], - "mutators": [{ - "handler": "noop" - }], - "authorizer": { - "handler": "allow" - } - } -] diff --git a/test/bdd/fixtures/oathkeeper-config/ops-keyserver/config.yaml b/test/bdd/fixtures/oathkeeper-config/ops-keyserver/config.yaml deleted file mode 100644 index db155961..00000000 --- a/test/bdd/fixtures/oathkeeper-config/ops-keyserver/config.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright SecureKey Technologies Inc. All Rights Reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# - -serve: - proxy: - port: 4466 - api: - port: 4458 - -access_rules: - repositories: - - file:///oathkeeper/rules/resource-server.json - matching_strategy: glob - -authenticators: - oauth2_introspection: - enabled: true - config: - introspection_url: https://hydra.trustbloc.local:4445/oauth2/introspect - noop: - enabled: true - -authorizers: - allow: - enabled: true - -mutators: - header: - enabled: false - noop: - enabled: true diff --git a/test/bdd/fixtures/oathkeeper-config/ops-keyserver/rules/resource-server.json b/test/bdd/fixtures/oathkeeper-config/ops-keyserver/rules/resource-server.json deleted file mode 100644 index a201f356..00000000 --- a/test/bdd/fixtures/oathkeeper-config/ops-keyserver/rules/resource-server.json +++ /dev/null @@ -1,59 +0,0 @@ -[ - { - "id": "ops-kms-create-keystore", - "upstream": { - "url": "https://kms.trustbloc.local:8076" - }, - "match": { - "url": "https://localhost:4466/v1/keystores", - "methods": ["POST"] - }, - "authenticators": [{ - "handler": "oauth2_introspection" - }], - "mutators": [{ - "handler": "noop" - }], - "authorizer": { - "handler": "allow" - } - }, - { - "id": "ops-kms-keystore-ops", - "upstream": { - "url": "https://kms.trustbloc.local:8076" - }, - "match": { - "url": "https://localhost:4466/v1/keystores/<*>", - "methods": ["POST","PUT","GET"] - }, - "authenticators": [{ - "handler": "noop" - }], - "mutators": [{ - "handler": "noop" - }], - "authorizer": { - "handler": "allow" - } - }, - { - "id": "ops-kms-health", - "upstream": { - "url": "https://kms.trustbloc.local:8076" - }, - "match": { - "url": "http://localhost:4466/healthcheck", - "methods": ["GET"] - }, - "authenticators": [{ - "handler": "noop" - }], - "mutators": [{ - "handler": "noop" - }], - "authorizer": { - "handler": "allow" - } - } -] diff --git a/test/bdd/pkg/auth/login.go b/test/bdd/pkg/auth/login.go deleted file mode 100644 index 878740c8..00000000 --- a/test/bdd/pkg/auth/login.go +++ /dev/null @@ -1,271 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package auth - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/http/cookiejar" - "strings" - - "github.com/rs/xid" -) - -const ( - hubAuthHydraAdminURL = "https://localhost:4445" - hubAuthOIDCProviderURL = "https://localhost:4444/" - hubAuthOIDCProviderSelectionPath = "/ui" - hubAuthSelectOIDCProviderPath = "/oauth2/login" - mockLoginURL = "https://localhost:8099/mock/login" - mockAuthenticationURL = "https://localhost:8099/mock/authn" - mockConsentURL = "https://localhost:8099/mock/consent" - mockAuthorizationURL = "https://localhost:8099/mock/authz" - mockOIDCProviderName = "mockbank" // providers.yaml -) - -// LoginConfig sets services urls and names needed for auth login. -type LoginConfig struct { - HubAuthHydraAdminURL string - HubAuthOIDCProviderURL string - HubAuthOIDCProviderSelectionURL string - HubAuthSelectOIDCProviderURL string - LoginURL string - AuthenticationURL string - ConsentURL string - AuthorizationURL string - OIDCProviderName string -} - -// defines the payload expected by the login consent server's /authn endpoint. -type userAuthenticationConfig struct { - Sub string `json:"sub"` - Fail bool `json:"fail,omitempty"` -} - -type userAuthorizationConfig struct { - UserClaims *UserClaims `json:"user_claims,omitempty"` - Fail bool `json:"fail,omitempty"` -} - -// UserClaims can be configured by BDD tests. -type UserClaims struct { - Sub string `json:"sub"` - Name string `json:"name"` - GivenName string `json:"given_name"` - FamilyName string `json:"family_name"` - Email string `json:"email"` -} - -// AuthLogin used for wallet login. -type AuthLogin struct { //nolint:golint - browser *http.Client - tlsConfig *tls.Config - cfg *LoginConfig - wallet *MockWallet - expectedUserData *UserClaims -} - -// NewAuthLogin returns new instance of AuthLogin. -func NewAuthLogin(loginConfig *LoginConfig, tlsConfig *tls.Config) *AuthLogin { - return &AuthLogin{cfg: loginConfig, tlsConfig: tlsConfig} -} - -// WalletLogin logins and return a new MockWallet that is logged in. -func (a *AuthLogin) WalletLogin() (*MockWallet, string, error) { - err := a.registerWallet() - if err != nil { - return nil, "", err - } - - err = a.redirectUserToAuthenticate() - if err != nil { - return nil, "", err - } - - err = a.selectThirdPartyOIDCProvider() - if err != nil { - return nil, "", err - } - - err = a.authenticateUserAtThirdPartyProvider() - if err != nil { - return nil, "", err - } - - err = a.checkIsUserRedirectedBackToWallet() - if err != nil { - return nil, "", err - } - - return a.wallet, a.wallet.accessToken, a.checkIsUserAuthenticatedToTheWallet() -} - -func (a *AuthLogin) registerWallet() error { - err := a.initBrowser() - if err != nil { - return fmt.Errorf("failed to register auth: %w", err) - } - - a.wallet, err = NewMockWallet(a.cfg.HubAuthHydraAdminURL, a.cfg.HubAuthOIDCProviderURL, a.browser) - if err != nil { - return fmt.Errorf("failed to register auth: %w", err) - } - - return nil -} - -func (a *AuthLogin) redirectUserToAuthenticate() error { - result, err := a.wallet.RequestUserAuthentication() - if err != nil { - return fmt.Errorf("auth failed to redirect user for authentication: %w", err) - } - defer result.Body.Close() //nolint:errcheck - - if result.Request.URL.String() != a.cfg.HubAuthOIDCProviderSelectionURL { - return fmt.Errorf( - "the user ended up at the wrong login URL; expected %s got %s", - a.cfg.HubAuthOIDCProviderSelectionURL, result.Request.URL.String(), - ) - } - - return nil -} - -func (a *AuthLogin) selectThirdPartyOIDCProvider() error { - request := fmt.Sprintf("%s?provider=%s", a.cfg.HubAuthSelectOIDCProviderURL, a.cfg.OIDCProviderName) - - result, err := a.browser.Get(request) //nolint:noctx - if err != nil { - return fmt.Errorf("user failed to select OIDC provider using request %s: %w", request, err) - } - - defer result.Body.Close() //nolint:errcheck - - if !strings.HasPrefix(result.Request.URL.String(), a.cfg.LoginURL) { - return fmt.Errorf( - "user at wrong third party OIDC provider; expected %s got %s", - a.cfg.LoginURL, result.Request.URL.String(), - ) - } - - return nil -} - -func (a *AuthLogin) authenticateUserAtThirdPartyProvider() error { - a.expectedUserData = &UserClaims{ - Sub: xid.New().String(), - Name: "John Smith", - GivenName: "John", - FamilyName: "Smith", - Email: "john.smith@example.org", - } - - authn, err := json.Marshal(&userAuthenticationConfig{ - Sub: a.expectedUserData.Sub, - }) - if err != nil { - return fmt.Errorf("failed to marshal user authn config: %w", err) - } - - response, err := a.browser.Post(a.cfg.AuthenticationURL, "application/json", bytes.NewReader(authn)) //nolint:noctx - if err != nil { - return fmt.Errorf("user failed to send authentication data: %w", err) - } - - defer response.Body.Close() //nolint:errcheck - - if !strings.HasPrefix(response.Request.URL.String(), a.cfg.ConsentURL) { - return fmt.Errorf( - "user is at the wrong third party consent url; expected %s got %s", - a.cfg.ConsentURL, response.Request.URL.String(), - ) - } - - authz, err := json.Marshal(&userAuthorizationConfig{ - UserClaims: a.expectedUserData, - }) - if err != nil { - return fmt.Errorf("failed to marshal user authz config: %w", err) - } - - response, err = a.browser.Post(a.cfg.AuthorizationURL, "application/json", bytes.NewReader(authz)) //nolint:noctx - if err != nil { - return fmt.Errorf("user failed to send authorization data: %w, %s", err, a.cfg.AuthorizationURL) - } - - defer response.Body.Close() //nolint:errcheck - - if response.StatusCode != http.StatusOK { - msg, err := ioutil.ReadAll(response.Body) - if err != nil { - return fmt.Errorf("failed to read response body: %w", err) - } - - return fmt.Errorf( - "unexpected status code; expected %d got %d msg=%s", - http.StatusOK, response.StatusCode, msg, - ) - } - - return nil -} - -func (a *AuthLogin) checkIsUserRedirectedBackToWallet() error { - if !a.wallet.ReceivedCallback { - return fmt.Errorf("the auth has not received a callback") - } - - return nil -} - -func (a *AuthLogin) checkIsUserAuthenticatedToTheWallet() error { - if a.wallet.CallbackErr != nil { - return fmt.Errorf("auth failed to execute callback successfully: %w", a.wallet.CallbackErr) - } - - if a.wallet.UserData.Sub != a.expectedUserData.Sub { - return fmt.Errorf( - "auth received a different user idenfitier than expected; expected %s got %s", - a.expectedUserData.Sub, a.wallet.UserData.Sub, - ) - } - - return nil -} - -func (a *AuthLogin) initBrowser() error { - jar, err := cookiejar.New(nil) - if err != nil { - return fmt.Errorf("failed to init cookie jar: %w", err) - } - - a.browser = &http.Client{ - Jar: jar, - Transport: &http.Transport{TLSClientConfig: a.tlsConfig}, - } - - return nil -} - -// CreateDefaultConfig creates default login. -func CreateDefaultConfig(hubAuthURL string) *LoginConfig { - return &LoginConfig{ - HubAuthHydraAdminURL: hubAuthHydraAdminURL, - HubAuthOIDCProviderURL: hubAuthOIDCProviderURL, - HubAuthOIDCProviderSelectionURL: hubAuthURL + hubAuthOIDCProviderSelectionPath, - HubAuthSelectOIDCProviderURL: hubAuthURL + hubAuthSelectOIDCProviderPath, - LoginURL: mockLoginURL, - AuthenticationURL: mockAuthenticationURL, - ConsentURL: mockConsentURL, - AuthorizationURL: mockAuthorizationURL, - OIDCProviderName: mockOIDCProviderName, - } -} diff --git a/test/bdd/pkg/auth/mock_wallet.go b/test/bdd/pkg/auth/mock_wallet.go deleted file mode 100644 index c51be559..00000000 --- a/test/bdd/pkg/auth/mock_wallet.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package auth - -import ( - "context" - "errors" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" - - "github.com/coreos/go-oidc/v3/oidc" - "github.com/ory/hydra-client-go/client" - "github.com/ory/hydra-client-go/client/admin" - "github.com/ory/hydra-client-go/models" - "github.com/rs/xid" - "golang.org/x/oauth2" -) - -// MockWallet is a mock wallet. -type MockWallet struct { - oidcProvider *oidc.Provider - httpClient *http.Client - clientID string - clientSecret string - scope []string - server *httptest.Server - oauth2Config oauth2.Config - accessToken string - ReceivedCallback bool - UserData *UserClaims - CallbackErr error - Secret string -} - -// RequestUserAuthentication requests the user authentication from the OIDC provider. -func (m *MockWallet) RequestUserAuthentication() (*http.Response, error) { - m.oauth2Config = oauth2.Config{ - ClientID: m.clientID, - ClientSecret: m.clientSecret, - Endpoint: m.oidcProvider.Endpoint(), - RedirectURL: m.server.URL, - Scopes: m.scope, - } - - redirectURL := m.oauth2Config.AuthCodeURL("dont_care_about_state") - - response, err := m.httpClient.Get(redirectURL) //nolint:noctx - if err != nil { - return nil, fmt.Errorf("failed to send authentication request %s: %w", redirectURL, err) - } - - return response, nil -} - -// ServeHTTP serves HTTP requests for the wallet. -func (m *MockWallet) ServeHTTP(w http.ResponseWriter, r *http.Request) { - m.ReceivedCallback = true - - code := r.URL.Query().Get("code") - if code == "" { - m.CallbackErr = errors.New("did not get a code in the callback") - - return - } - - token, err := m.oauth2Config.Exchange( - context.WithValue(r.Context(), oauth2.HTTPClient, m.httpClient), - code, - ) - if err != nil { - m.CallbackErr = fmt.Errorf("failed to exchange code for token: %w", err) - - return - } - - m.accessToken = token.AccessToken - - rawIDToken, ok := token.Extra("id_token").(string) - if !ok { - m.CallbackErr = errors.New("missing id_token") - - return - } - - idToken, err := m.oidcProvider.Verifier(&oidc.Config{ClientID: m.clientID}).Verify(r.Context(), rawIDToken) - if err != nil { - m.CallbackErr = fmt.Errorf("failed to verify id_token: %w", err) - - return - } - - m.UserData = &UserClaims{} - - err = idToken.Claims(m.UserData) - if err != nil { - m.CallbackErr = fmt.Errorf("failed to extract claims from id_token: %w", err) - - return - } - - _, err = w.Write([]byte("mock auth authenticated the user!")) - if err != nil { - m.CallbackErr = fmt.Errorf("failed to render mock UI to the user: %w", err) - - return - } - - // store access token - m.accessToken = token.AccessToken -} - -// NewMockWallet returns a new instance of the mock wallet. -func NewMockWallet(clientRegistrationURL, oidcProviderURL string, httpClient *http.Client) (*MockWallet, error) { - oidcProvider, err := oidc.NewProvider( - oidc.ClientContext(context.Background(), httpClient), - oidcProviderURL, - ) - if err != nil { - return nil, fmt.Errorf("failed to init oidc provider: %w, %s", err, oidcProviderURL) - } - - wallet := &MockWallet{ - oidcProvider: oidcProvider, - httpClient: httpClient, - clientID: xid.New().String(), - clientSecret: xid.New().String(), - scope: []string{oidc.ScopeOpenID}, - } - wallet.server = httptest.NewServer(wallet) - - request := admin.NewCreateOAuth2ClientParams() - request.SetHTTPClient(wallet.httpClient) - request.SetBody(&models.OAuth2Client{ - ClientID: wallet.clientID, - ClientSecret: wallet.clientSecret, - GrantTypes: []string{"authorization_code", "refresh_token"}, - ResponseTypes: []string{"code", "id_token"}, - Scope: strings.Join(wallet.scope, " "), - RedirectUris: []string{wallet.server.URL}, - }) - - hydraAdminURL, err := url.Parse(clientRegistrationURL) - if err != nil { - return nil, fmt.Errorf("invalid hydra admin url: %s", clientRegistrationURL) - } - - hydraClient := client.NewHTTPClientWithConfig(nil, - &client.TransportConfig{ - Host: hydraAdminURL.Host, - BasePath: hydraAdminURL.Path, - Schemes: []string{hydraAdminURL.Scheme}, - }, - ).Admin - - _, err = hydraClient.CreateOAuth2Client(request) //nolint:errcheck - if err != nil { - return nil, fmt.Errorf("failed to register auth as an oidc client of hub auth: %w", err) - } - - return wallet, nil -} diff --git a/test/bdd/pkg/common/common_steps.go b/test/bdd/pkg/common/common_steps.go index 43a30b12..24c678a0 100644 --- a/test/bdd/pkg/common/common_steps.go +++ b/test/bdd/pkg/common/common_steps.go @@ -14,7 +14,6 @@ import ( "github.com/cucumber/godog" "github.com/trustbloc/edge-core/pkg/log" - "github.com/trustbloc/kms/test/bdd/pkg/auth" "github.com/trustbloc/kms/test/bdd/pkg/context" "github.com/trustbloc/kms/test/bdd/pkg/internal/bddutil" ) @@ -43,10 +42,7 @@ func (s *Steps) SetContext(ctx *context.BDDContext) { // RegisterSteps defines scenario steps. func (s *Steps) RegisterSteps(ctx *godog.ScenarioContext) { ctx.Step(`^Key Server is running on "([^"]*)" port "([^"]*)"$`, s.checkKeyServerIsRun) - ctx.Step(`^Hub Auth is running on "([^"]*)" port "([^"]*)"$`, s.checkHubAuthIsRun) - ctx.Step(`^Key Server is running on "([^"]*)" env$`, s.checkKeyServerIsRunEnv) - ctx.Step(`^Hub Auth is running on "([^"]*)" env$`, s.checkHubAuthIsRunEnv) } func (s *Steps) checkKeyServerIsRun(host string, port int) error { @@ -60,18 +56,6 @@ func (s *Steps) checkKeyServerIsRun(host string, port int) error { return nil } -func (s *Steps) checkHubAuthIsRun(host string, port int) error { - url, err := s.healthCheck(host, port) - if err != nil { - return err - } - - s.bddContext.HubAuthURL = url - s.bddContext.LoginConfig = auth.CreateDefaultConfig(url) - - return nil -} - func (s *Steps) checkKeyServerIsRunEnv(serverURLEnv string) error { url, err := getServerURL(serverURLEnv) if err != nil { diff --git a/test/bdd/pkg/context/context.go b/test/bdd/pkg/context/context.go index a69e0381..0cdf0df8 100644 --- a/test/bdd/pkg/context/context.go +++ b/test/bdd/pkg/context/context.go @@ -17,16 +17,12 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/secretlock" "github.com/hyperledger/aries-framework-go/pkg/secretlock/noop" tlsutils "github.com/trustbloc/edge-core/pkg/utils/tls" - - "github.com/trustbloc/kms/test/bdd/pkg/auth" ) // BDDContext is a global context shared between different test suites in bdd tests. type BDDContext struct { KeyServerURL string - AuthZKeyServerURL string HubAuthURL string - LoginConfig *auth.LoginConfig tlsConfig *tls.Config KeyManager kms.KeyManager Crypto cryptoapi.Crypto diff --git a/test/bdd/pkg/keystore/keystore_steps.go b/test/bdd/pkg/keystore/keystore_steps.go index 5f733b8f..aeda7ca6 100644 --- a/test/bdd/pkg/keystore/keystore_steps.go +++ b/test/bdd/pkg/keystore/keystore_steps.go @@ -20,7 +20,6 @@ import ( "github.com/trustbloc/edge-core/pkg/log" "github.com/trustbloc/edge-core/pkg/zcapld" - "github.com/trustbloc/kms/test/bdd/pkg/auth" "github.com/trustbloc/kms/test/bdd/pkg/context" "github.com/trustbloc/kms/test/bdd/pkg/internal/bddutil" ) @@ -63,19 +62,12 @@ func (s *Steps) RegisterSteps(ctx *godog.ScenarioContext) { } func (s *Steps) sendCreateKeystoreRequest(endpoint string) error { - login := auth.NewAuthLogin(s.bddContext.LoginConfig, s.bddContext.TLSConfig()) - - _, accessToken, err := login.WalletLogin() - if err != nil { - return fmt.Errorf("failed to login auth: %w", err) - } - body := bytes.NewBuffer([]byte(createKeystoreReq)) resp, err := bddutil.HTTPDo( http.MethodPost, endpoint, - headers(accessToken), + headers(), body, s.bddContext.TLSConfig(), ) if err != nil { @@ -145,9 +137,8 @@ func (s *Steps) checkResponse(status string) error { return nil } -func headers(token string) map[string]string { +func headers() map[string]string { return map[string]string{ "Content-Type": contentType, - "Authorization": fmt.Sprintf("Bearer %s", token), } } diff --git a/test/bdd/pkg/kms/auth_edv_steps.go b/test/bdd/pkg/kms/auth_edv_steps.go index c39e4492..1cc0873b 100644 --- a/test/bdd/pkg/kms/auth_edv_steps.go +++ b/test/bdd/pkg/kms/auth_edv_steps.go @@ -10,36 +10,16 @@ import ( "fmt" kmsapi "github.com/hyperledger/aries-framework-go/pkg/kms" "github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint" - - "github.com/trustbloc/kms/test/bdd/pkg/auth" ) -func (s *Steps) logIntoAuthServer(userName string) error { +func (s *Steps) configureZCAPAuth(userName string) error { u := &user{ name: userName, } s.users[userName] = u - login := auth.NewAuthLogin(s.bddContext.LoginConfig, s.bddContext.TLSConfig()) - - loggedWallet, accessToken, err := login.WalletLogin() - if err != nil { - return err - } - - u.subject = loggedWallet.UserData.Sub - u.accessToken = accessToken - - return nil -} - -func (s *Steps) createProfileOnAuthServer(userName string) error { - u := s.users[userName] - authUser := &user{ name: userName, - subject: u.subject, - accessToken: u.accessToken, } c, err := s.prepareAuthConfig(authUser) diff --git a/test/bdd/pkg/kms/kms_steps.go b/test/bdd/pkg/kms/kms_steps.go index 4ee21a9f..7dac9b00 100644 --- a/test/bdd/pkg/kms/kms_steps.go +++ b/test/bdd/pkg/kms/kms_steps.go @@ -75,9 +75,7 @@ func (s *Steps) SetContext(ctx *bddcontext.BDDContext) { func (s *Steps) RegisterSteps(ctx *godog.ScenarioContext) { // common creation steps ctx.Step(`^Create "([^"]*)" users$`, s.createUsers) - ctx.Step(`^"([^"]*)" has logged into auth server$`, s.logIntoAuthServer) - ctx.Step(`^"([^"]*)" has created a profile on auth server$`, s.createProfileOnAuthServer) - ctx.Step(`^"([^"]*)" users has created a profile on auth server$`, s.createProfileOnAuthServerForMultipleUsers) + ctx.Step(`^"([^"]*)" has configured ZCAP authentication$`, s.configureZCAPAuth) ctx.Step(`^"([^"]*)" has created an empty keystore on Key Server$`, s.createKeystore) ctx.Step(`^"([^"]*)" has created a keystore with "([^"]*)" key on Key Server$`, s.createKeystoreAndKey) ctx.Step(`^"([^"]*)" users request to create a keystore on "([^"]*)" with "([^"]*)" key and sign ([^"]*) times using "([^"]*)" concurrent requests$`, //nolint:lll @@ -145,8 +143,6 @@ func (s *Steps) createKeystoreReq(u *user, r *createKeystoreReq, endpoint string return err } - request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", u.accessToken)) - response, err := s.httpClient.Do(request) if err != nil { return fmt.Errorf("http do: %w", err) diff --git a/test/bdd/pkg/kms/stress_steps.go b/test/bdd/pkg/kms/stress_steps.go index e624f6e3..cb26dea9 100644 --- a/test/bdd/pkg/kms/stress_steps.go +++ b/test/bdd/pkg/kms/stress_steps.go @@ -48,21 +48,6 @@ func (s *Steps) createUsers(usersNumberEnv string) error { return nil } -func (s *Steps) createProfileOnAuthServerForMultipleUsers(usersNumberEnv string) error { - usersNumber, err := getUsersNumber(usersNumberEnv) - if err != nil { - return err - } - - for i := 0; i < usersNumber; i++ { - err = s.createProfileOnAuthServer(fmt.Sprintf(userNameTplt, i)) - if err != nil { - return err - } - } - - return nil -} //nolint:funlen,gocyclo func (s *Steps) stressTestForMultipleUsers( diff --git a/test/bdd/pkg/kms/user.go b/test/bdd/pkg/kms/user.go index 17ef7ca0..07aa6285 100644 --- a/test/bdd/pkg/kms/user.go +++ b/test/bdd/pkg/kms/user.go @@ -34,8 +34,6 @@ type user struct { keyID string vaultID string - subject string - recipientPubKeys map[string]*publicKeyData response *response data map[string]string @@ -46,7 +44,6 @@ type user struct { authCrypto crypto.Crypto kmsCapability *zcapld.Capability disableZCAP bool - accessToken string } type publicKeyData struct {