From 14091a20f6e7527a5fd5153e4abc7d0f16ca543e Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Thu, 12 Dec 2024 16:31:36 -0800 Subject: [PATCH 1/6] Create client_registration_status input in test, groups --- .../authorization_code_group.rb | 4 ++++ .../client_credentials_group.rb | 4 ++++ .../dynamic_client_registration_group.rb | 21 +++++++++++++++++++ .../registration_success_test.rb | 1 + 4 files changed, 30 insertions(+) diff --git a/lib/udap_security_test_kit/authorization_code_group.rb b/lib/udap_security_test_kit/authorization_code_group.rb index 979dcc9..507220a 100644 --- a/lib/udap_security_test_kit/authorization_code_group.rb +++ b/lib/udap_security_test_kit/authorization_code_group.rb @@ -49,6 +49,9 @@ class AuthorizationCodeGroup < Inferno::TestGroup default: 'authorization_code', locked: true }, + udap_client_registration_status: { + name: :udap_auth_code_flow_client_registration_status + }, udap_client_cert_pem: { name: :udap_auth_code_flow_client_cert_pem, title: 'Authorization Code Client Certificate(s) (PEM Format)' @@ -90,6 +93,7 @@ class AuthorizationCodeGroup < Inferno::TestGroup } do input_order :udap_registration_endpoint, :udap_auth_code_flow_registration_grant_type, + :udap_auth_code_flow_client_registration_status, :udap_auth_code_flow_client_cert_pem, :udap_auth_code_flow_client_private_key, :udap_auth_code_flow_cert_iss, diff --git a/lib/udap_security_test_kit/client_credentials_group.rb b/lib/udap_security_test_kit/client_credentials_group.rb index 723e60b..74a07f9 100644 --- a/lib/udap_security_test_kit/client_credentials_group.rb +++ b/lib/udap_security_test_kit/client_credentials_group.rb @@ -51,6 +51,9 @@ class ClientCredentialsGroup < Inferno::TestGroup default: 'client_credentials', locked: true }, + udap_client_registration_status: { + name: :udap_client_credentials_flow_client_registration_status + }, udap_client_cert_pem: { name: :udap_client_credentials_flow_client_cert_pem, title: 'Client Credentials Client Certificate(s) (PEM Format)' @@ -92,6 +95,7 @@ class ClientCredentialsGroup < Inferno::TestGroup } do input_order :udap_registration_endpoint, :udap_client_credentials_flow_registration_grant_type, + :udap_client_credentials_flow_client_registration_status, :udap_client_credentials_flow_client_cert_pem, :udap_client_credentials_flow_client_private_key, :udap_cert_iss_client_creds_flow, diff --git a/lib/udap_security_test_kit/dynamic_client_registration_group.rb b/lib/udap_security_test_kit/dynamic_client_registration_group.rb index c20bc11..f0beb5c 100644 --- a/lib/udap_security_test_kit/dynamic_client_registration_group.rb +++ b/lib/udap_security_test_kit/dynamic_client_registration_group.rb @@ -57,6 +57,27 @@ def self.dynamic_client_registration_input_instructions ] } + input :udap_client_registration_status, + title: 'Client Registration Status', + description: %( + If the client's iss and certificate combination has already been registered with the authorization server + prior to this test run, select 'Update'. + ), + type: 'radio', + options: { + list_options: [ + { + label: 'New Registration (201 Response Code Expected)', + value: 'new' + }, + { + label: 'Update Registration (200 Response Code Expected)', + value: 'update' + } + ] + }, + default: 'new' + input :udap_client_cert_pem, title: 'X.509 Client Certificate(s) (PEM Format)', description: %( diff --git a/lib/udap_security_test_kit/registration_success_test.rb b/lib/udap_security_test_kit/registration_success_test.rb index d17cd26..36722fb 100644 --- a/lib/udap_security_test_kit/registration_success_test.rb +++ b/lib/udap_security_test_kit/registration_success_test.rb @@ -20,6 +20,7 @@ class RegistrationSuccessTest < Inferno::Test input :udap_cert_iss input :udap_registration_endpoint + input :udap_client_registration_status input :udap_jwt_signing_alg input :udap_registration_requested_scope input :udap_registration_grant_type From 0e0e6053cb5e723bf3182656dc01ea2b5f866d8a Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Thu, 12 Dec 2024 16:34:15 -0800 Subject: [PATCH 2/6] Update registration success test to check input for expected response code --- lib/udap_security_test_kit/registration_success_test.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/udap_security_test_kit/registration_success_test.rb b/lib/udap_security_test_kit/registration_success_test.rb index 36722fb..9f21b11 100644 --- a/lib/udap_security_test_kit/registration_success_test.rb +++ b/lib/udap_security_test_kit/registration_success_test.rb @@ -61,7 +61,12 @@ class RegistrationSuccessTest < Inferno::Test post(udap_registration_endpoint, body: reg_body, headers: reg_headers) - assert_response_status(201) + if udap_client_registration_status == 'new' + assert_response_status(201) + elsif udap_client_registration_status == 'update' + assert_response_status(200) + end + assert_valid_json(response[:body]) output udap_registration_response: response[:body] end From 83a12559c871b74cf005e1d283c0412f03a9f77a Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Thu, 12 Dec 2024 16:44:10 -0800 Subject: [PATCH 3/6] Update registration success spec tests to check for 200 vs 201 response type --- .../registration_success_test_spec.rb | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/spec/udap_security_test_kit/registration_success_test_spec.rb b/spec/udap_security_test_kit/registration_success_test_spec.rb index 4743ad8..af61c7a 100644 --- a/spec/udap_security_test_kit/registration_success_test_spec.rb +++ b/spec/udap_security_test_kit/registration_success_test_spec.rb @@ -21,6 +21,7 @@ let(:udap_registration_requested_scope) { 'system/*' } let(:udap_registration_grant_type) { 'client_credentials' } let(:udap_registration_certifications) { '' } + let(:udap_client_registration_status) { 'new' } let(:input) do { udap_client_cert_pem:, @@ -30,7 +31,8 @@ udap_jwt_signing_alg:, udap_registration_requested_scope:, udap_registration_grant_type:, - udap_registration_certifications: + udap_registration_certifications:, + udap_client_registration_status: } end @@ -48,21 +50,45 @@ def run(runnable, inputs = {}) Inferno::TestRunner.new(test_session:, test_run:).run(runnable) end - it 'fails if response status is not 201' do - stub_request(:post, udap_registration_endpoint) - .to_return(status: 400, body: {}.to_json) + context 'when new client is being registered' do + it 'fails if response status is not 201' do + stub_request(:post, udap_registration_endpoint) + .to_return(status: 200, body: {}.to_json) - result = run(runnable, input) + result = run(runnable, input) - expect(result.result).to eq('fail') + expect(result.result).to eq('fail') + end + + it 'passes when response status is 201' do + stub_request(:post, udap_registration_endpoint) + .to_return(status: 201, body: {}.to_json) + + result = run(runnable, input) + + expect(result.result).to eq('pass') + end end - it 'passes when response status is 201' do - stub_request(:post, udap_registration_endpoint) - .to_return(status: 201, body: {}.to_json) + context 'when existing client is updating its registration data' do + it 'fails if response status is not 200' do + stub_request(:post, udap_registration_endpoint) + .to_return(status: 201, body: {}.to_json) - result = run(runnable, input) + input[:udap_client_registration_status] = 'update' + result = run(runnable, input) - expect(result.result).to eq('pass') + expect(result.result).to eq('fail') + end + + it 'passes when response status is 200' do + stub_request(:post, udap_registration_endpoint) + .to_return(status: 200, body: {}.to_json) + + input[:udap_client_registration_status] = 'update' + result = run(runnable, input) + + expect(result.result).to eq('pass') + end end end From 3297c87679af1538fa343c3b6149983ee0322396 Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Tue, 17 Dec 2024 16:28:22 -0800 Subject: [PATCH 4/6] Update input instructions and test descriptions --- .../dynamic_client_registration_group.rb | 12 +++++------- .../registration_success_test.rb | 6 ++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/udap_security_test_kit/dynamic_client_registration_group.rb b/lib/udap_security_test_kit/dynamic_client_registration_group.rb index f0beb5c..d73e80f 100644 --- a/lib/udap_security_test_kit/dynamic_client_registration_group.rb +++ b/lib/udap_security_test_kit/dynamic_client_registration_group.rb @@ -19,13 +19,11 @@ def self.dynamic_client_registration_input_instructions establish a trust chain. Cancelling a UDAP client's registration is not a required server capability and as such the Inferno client has no - way of resetting state on the authorization server after a successful registration attempt. Testers wishing to - run the Dynamic Client Registration tests more than once must do one of the following: - - Remove the Inferno test client's registration out-of-band before re-running tests, to register the original - client URI anew - - Specifiy a different client URI as the issuer input (if the client cert has more than one Subject Alternative - Name (SAN) URI entry), to register a different logical client with the original certificate - - Provide a different client certificate and its associated URI to register a new logical client + way of resetting state on the authorization server after a successful registration attempt. If a given + certificate and issuer URI identity combination has already been registered with the authorization server, testers + may select the "Update Registration" option under Client Registration Status. This option will expect a `200 OK` + return status that indicates a registration modification, instead of the + `201 Created` return status required for a new registration entry. ) end diff --git a/lib/udap_security_test_kit/registration_success_test.rb b/lib/udap_security_test_kit/registration_success_test.rb index 9f21b11..7985a8d 100644 --- a/lib/udap_security_test_kit/registration_success_test.rb +++ b/lib/udap_security_test_kit/registration_success_test.rb @@ -13,6 +13,12 @@ class RegistrationSuccessTest < Inferno::Test The [UDAP IG Section 3.2.3](https://hl7.org/fhir/us/udap-security/STU1/registration.html#request-body) states: > If a new registration is successful, the Authorization Server SHALL return a registration response with a 201 > Created HTTP response code as per Section 5.1 of UDAP Dynamic Client Registration + + If the tester indicated this registration attempt represents a modification of an existing registration entry, + this test will expect a 200 response code instead, as indicated in + the [UDAP IG Section 3.4](https://hl7.org/fhir/us/udap-security/STU1/registration.html#modifying-and-cancelling-registrations): + > If the Authorization Server returns the same client_id in the registration response for a modification request, + > it SHOULD also return a 200 OK HTTP response code. ) input :udap_client_cert_pem From 486e4f158f4390acdc5b59f0644b3293a989590a Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Thu, 19 Dec 2024 11:28:05 -0800 Subject: [PATCH 5/6] Accept 200 or 201 response status for successful updated registration requests --- .../registration_success_test.rb | 2 +- .../registration_success_test_spec.rb | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/udap_security_test_kit/registration_success_test.rb b/lib/udap_security_test_kit/registration_success_test.rb index 7985a8d..8360e71 100644 --- a/lib/udap_security_test_kit/registration_success_test.rb +++ b/lib/udap_security_test_kit/registration_success_test.rb @@ -70,7 +70,7 @@ class RegistrationSuccessTest < Inferno::Test if udap_client_registration_status == 'new' assert_response_status(201) elsif udap_client_registration_status == 'update' - assert_response_status(200) + assert_response_status([200, 201]) end assert_valid_json(response[:body]) diff --git a/spec/udap_security_test_kit/registration_success_test_spec.rb b/spec/udap_security_test_kit/registration_success_test_spec.rb index af61c7a..ffbdee1 100644 --- a/spec/udap_security_test_kit/registration_success_test_spec.rb +++ b/spec/udap_security_test_kit/registration_success_test_spec.rb @@ -71,9 +71,9 @@ def run(runnable, inputs = {}) end context 'when existing client is updating its registration data' do - it 'fails if response status is not 200' do + it 'fails if response status is not 200 or 201' do stub_request(:post, udap_registration_endpoint) - .to_return(status: 201, body: {}.to_json) + .to_return(status: 401, body: {}.to_json) input[:udap_client_registration_status] = 'update' result = run(runnable, input) @@ -90,5 +90,15 @@ def run(runnable, inputs = {}) expect(result.result).to eq('pass') end + + it 'passes when response status is 201' do + stub_request(:post, udap_registration_endpoint) + .to_return(status: 201, body: {}.to_json) + + input[:udap_client_registration_status] = 'update' + result = run(runnable, input) + + expect(result.result).to eq('pass') + end end end From 8505a068cba786dca8693f5ec7547b8449ed579f Mon Sep 17 00:00:00 2001 From: Alisa Wallace Date: Thu, 19 Dec 2024 11:54:13 -0800 Subject: [PATCH 6/6] Update input instructions and test descriptions --- .../dynamic_client_registration_group.rb | 9 +++++---- lib/udap_security_test_kit/registration_success_test.rb | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/udap_security_test_kit/dynamic_client_registration_group.rb b/lib/udap_security_test_kit/dynamic_client_registration_group.rb index d73e80f..66cd828 100644 --- a/lib/udap_security_test_kit/dynamic_client_registration_group.rb +++ b/lib/udap_security_test_kit/dynamic_client_registration_group.rb @@ -21,9 +21,10 @@ def self.dynamic_client_registration_input_instructions Cancelling a UDAP client's registration is not a required server capability and as such the Inferno client has no way of resetting state on the authorization server after a successful registration attempt. If a given certificate and issuer URI identity combination has already been registered with the authorization server, testers - may select the "Update Registration" option under Client Registration Status. This option will expect a `200 OK` - return status that indicates a registration modification, instead of the - `201 Created` return status required for a new registration entry. + whose systems support registration modifications + may select the "Update Registration" option under Client Registration Status. This option will accept either a + `200 OK` or `201 Created` return status. Registration attempts for a new client may only return `201 Created`, + per the [IG](https://hl7.org/fhir/us/udap-security/STU1/registration.html#request-body). ) end @@ -69,7 +70,7 @@ def self.dynamic_client_registration_input_instructions value: 'new' }, { - label: 'Update Registration (200 Response Code Expected)', + label: 'Update Registration (200 or 201 Response Code Expected)', value: 'update' } ] diff --git a/lib/udap_security_test_kit/registration_success_test.rb b/lib/udap_security_test_kit/registration_success_test.rb index 8360e71..9ca60e5 100644 --- a/lib/udap_security_test_kit/registration_success_test.rb +++ b/lib/udap_security_test_kit/registration_success_test.rb @@ -15,10 +15,12 @@ class RegistrationSuccessTest < Inferno::Test > Created HTTP response code as per Section 5.1 of UDAP Dynamic Client Registration If the tester indicated this registration attempt represents a modification of an existing registration entry, - this test will expect a 200 response code instead, as indicated in - the [UDAP IG Section 3.4](https://hl7.org/fhir/us/udap-security/STU1/registration.html#modifying-and-cancelling-registrations): + the [UDAP IG Section 3.4](https://hl7.org/fhir/us/udap-security/STU1/registration.html#modifying-and-cancelling-registrations) + states: > If the Authorization Server returns the same client_id in the registration response for a modification request, > it SHOULD also return a 200 OK HTTP response code. + + In this case, the test will require either a 201 or 200 response code to pass. ) input :udap_client_cert_pem