udap_security_test_kit 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/udap_security_test_kit/authorization_code_authentication_group.rb +44 -0
  4. data/lib/udap_security_test_kit/authorization_code_group.rb +103 -0
  5. data/lib/udap_security_test_kit/authorization_code_received_test.rb +31 -0
  6. data/lib/udap_security_test_kit/authorization_code_redirect_test.rb +74 -0
  7. data/lib/udap_security_test_kit/authorization_code_token_exchange_test.rb +103 -0
  8. data/lib/udap_security_test_kit/authorization_endpoint_field_test.rb +43 -0
  9. data/lib/udap_security_test_kit/certs/InfernoCA.key +52 -0
  10. data/lib/udap_security_test_kit/certs/InfernoCA.pem +35 -0
  11. data/lib/udap_security_test_kit/certs/TestClient.pem +32 -0
  12. data/lib/udap_security_test_kit/certs/TestClientPrivateKey.key +28 -0
  13. data/lib/udap_security_test_kit/client_credentials_authentication_group.rb +40 -0
  14. data/lib/udap_security_test_kit/client_credentials_group.rb +105 -0
  15. data/lib/udap_security_test_kit/client_credentials_token_exchange_test.rb +130 -0
  16. data/lib/udap_security_test_kit/common_assertions.rb +16 -0
  17. data/lib/udap_security_test_kit/default_cert_file_loader.rb +27 -0
  18. data/lib/udap_security_test_kit/discovery_group.rb +90 -0
  19. data/lib/udap_security_test_kit/dynamic_client_registration_group.rb +129 -0
  20. data/lib/udap_security_test_kit/generate_client_certs_test.rb +60 -0
  21. data/lib/udap_security_test_kit/grant_types_supported_field_test.rb +53 -0
  22. data/lib/udap_security_test_kit/reg_endpoint_jwt_signing_alg_values_supported_field_test.rb +29 -0
  23. data/lib/udap_security_test_kit/registration_endpoint_field_test.rb +30 -0
  24. data/lib/udap_security_test_kit/registration_failure_invalid_contents_test.rb +68 -0
  25. data/lib/udap_security_test_kit/registration_failure_invalid_jwt_signature_test.rb +70 -0
  26. data/lib/udap_security_test_kit/registration_success_contents_test.rb +64 -0
  27. data/lib/udap_security_test_kit/registration_success_test.rb +68 -0
  28. data/lib/udap_security_test_kit/scopes_supported_field_test.rb +26 -0
  29. data/lib/udap_security_test_kit/signed_metadata_contents_test.rb +89 -0
  30. data/lib/udap_security_test_kit/signed_metadata_field_test.rb +31 -0
  31. data/lib/udap_security_test_kit/signed_metadata_trust_verification_test.rb +54 -0
  32. data/lib/udap_security_test_kit/software_statement_builder.rb +32 -0
  33. data/lib/udap_security_test_kit/token_endpoint_auth_methods_supported_field_test.rb +22 -0
  34. data/lib/udap_security_test_kit/token_endpoint_auth_signing_alg_values_supported_field_test.rb +32 -0
  35. data/lib/udap_security_test_kit/token_endpoint_field_test.rb +30 -0
  36. data/lib/udap_security_test_kit/token_exchange_response_body_test.rb +30 -0
  37. data/lib/udap_security_test_kit/token_exchange_response_headers_test.rb +30 -0
  38. data/lib/udap_security_test_kit/udap_auth_extensions_required_field_test.rb +38 -0
  39. data/lib/udap_security_test_kit/udap_auth_extensions_supported_field_test.rb +31 -0
  40. data/lib/udap_security_test_kit/udap_certifications_required_field_test.rb +45 -0
  41. data/lib/udap_security_test_kit/udap_certifications_supported_field_test.rb +33 -0
  42. data/lib/udap_security_test_kit/udap_client_assertion_payload_builder.rb +15 -0
  43. data/lib/udap_security_test_kit/udap_jwt_builder.rb +30 -0
  44. data/lib/udap_security_test_kit/udap_jwt_validator.rb +71 -0
  45. data/lib/udap_security_test_kit/udap_profiles_supported_field_test.rb +47 -0
  46. data/lib/udap_security_test_kit/udap_request_builder.rb +43 -0
  47. data/lib/udap_security_test_kit/udap_versions_supported_field_test.rb +21 -0
  48. data/lib/udap_security_test_kit/udap_x509_certificate.rb +42 -0
  49. data/lib/udap_security_test_kit/version.rb +3 -0
  50. data/lib/udap_security_test_kit/well_known_endpoint_test.rb +31 -0
  51. data/lib/udap_security_test_kit.rb +63 -0
  52. metadata +124 -0
@@ -0,0 +1,35 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
34
+ tsGvVZ6GCrAl5XejmwQBzyZQQw==
35
+ -----END CERTIFICATE-----
@@ -0,0 +1,32 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFcjCCA1qgAwIBAgIUbdCfB3IJ9bdOPGQVtxJHhMxUWv0wDQYJKoZIhvcNAQEL
3
+ BQAwgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEQMA4GA1UEBwwHQmVkZm9y
4
+ ZDEQMA4GA1UECgwHSW5mZXJubzEdMBsGA1UEAwwUSW5mZXJuby1VREFQLVJvb3Qt
5
+ Q0ExJzAlBgkqhkiG9w0BCQEWGGluZmVybm9AZ3JvdXBzLm1pdHJlLm9yZzAeFw0y
6
+ NDA4MTIyMzU4MTBaFw0zNDA4MTAyMzU4MTBaMGExCzAJBgNVBAYTAlVTMQswCQYD
7
+ VQQIDAJNQTEQMA4GA1UEBwwHQmVkZm9yZDEQMA4GA1UECgwHSW5mZXJubzEhMB8G
8
+ A1UEAwwYVURBUCBFeGFtcGxlIFRlc3QgQ2xpZW50MIIBIjANBgkqhkiG9w0BAQEF
9
+ AAOCAQ8AMIIBCgKCAQEAnfqzJCyeFNRhlcsrUPiO2LQtudObDHUKj4Q7fkYPUf9X
10
+ ecTMckfPKd8UJ7x8Vb5o1zmR3hsMoo1A7IkwBkmK2BXvxq243cCGO1q4w/jdL/EG
11
+ DiIZjTr7qvkawyeh9cAaApOrBlD4gnOxB05GjingDZgiT7GqBwrpEB2XJ4tw4idS
12
+ B3W9Rv0ynbgqPKgGw9hnEef+uNAvFIvSbfdz1n4xHNP0GuMuAX+edFCyxYFmDe74
13
+ 8pl3TH9dxkoM945r5tHmuJS9n1pXkTB9L5RVbqH77dIyOBobehHHpT4D3zjdSFmh
14
+ fta5NnDi5/iqRcFz7FVO79jJIoAqN+mWBlVH0yyfYQIDAQABo4H7MIH4MC8GA1Ud
15
+ EQQoMCaGJGh0dHBzOi8vaW5mZXJuby5jb20vdWRhcF9zZWN1cml0eS9hYzAxBgNV
16
+ HSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBDA6
17
+ BgNVHR8EMzAxMC+gLaArhilodHRwczovL2luZmVybm8uY29tL21vY2tfY3JsX2Vu
18
+ ZHBvaW50LmNybDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU6Eo2
19
+ HE37gpSaW9zBGf0t7XfYnfIwHwYDVR0jBBgwFoAUNOqoPKju4u9y9JAuAfnSAcFb
20
+ NKAwDQYJKoZIhvcNAQELBQADggIBACh2uQ1Krkw6F3Gq0HG3ohCm2j1ynmLSJwGE
21
+ HvPlkiBcs8RBPxZzJOZJBMxGmjTPga2Kt6zsBlmjLg++C7C5/8JruwrMtrBuTtHx
22
+ Kky0Qw+YJm81IgATeDIU/qkJB8LcnHgkQbu3nyoyeKocx9XSW8nlEm4FkyREXxfC
23
+ rSVCoc70GGg2vSnSkRikNjxwKGnHvmEDUOW2bBbbzvTGKlTKSIF50NiNPM3Fi7vF
24
+ bOfi1aZh6m8IKVaI2KUXVFHco1qB3QDK5BUEimko+EyaWSZPvP83PE2+TIdapRrw
25
+ HxQQJEr774GUNH1/hdW0qlP4u3CMMMAjS2H4dOsRYOOmgC6iEewFEBQqTRLkEfgP
26
+ pMxYhGAVAmrglLLr4t+ZF9KOmifvB6f18qF352Bj1D0TMB+oLy67kFw3s2ah21la
27
+ 3Xm6hQt+M5mZ/EYZIOUPxMHtqVt5DSJdMENHO2cjcRARyeD/BGYnJqnf6yA1LL2V
28
+ TK+jhC/C/Dcv0hHQnVWlUGlwoFMOOzfsr2K3mXYezAuHASP8LIAyjodPpd6cLQu2
29
+ SZTVVobSebaNmZ2UeX8Bc9bcobM2bbVb2c3UeezEJWOpt5cSOeEScEiwkaktxD5p
30
+ ix1K3KkIg2yDP176ILlVqBBA0X2FqTSSvFbTa5us3XIwkDfARJBpLnA7OfmsO61+
31
+ Ij5io7+X
32
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCd+rMkLJ4U1GGV
3
+ yytQ+I7YtC2505sMdQqPhDt+Rg9R/1d5xMxyR88p3xQnvHxVvmjXOZHeGwyijUDs
4
+ iTAGSYrYFe/GrbjdwIY7WrjD+N0v8QYOIhmNOvuq+RrDJ6H1wBoCk6sGUPiCc7EH
5
+ TkaOKeANmCJPsaoHCukQHZcni3DiJ1IHdb1G/TKduCo8qAbD2GcR5/640C8Ui9Jt
6
+ 93PWfjEc0/Qa4y4Bf550ULLFgWYN7vjymXdMf13GSgz3jmvm0ea4lL2fWleRMH0v
7
+ lFVuofvt0jI4Ght6EcelPgPfON1IWaF+1rk2cOLn+KpFwXPsVU7v2MkigCo36ZYG
8
+ VUfTLJ9hAgMBAAECggEAApTpPosYHkEGQztpvs4BD5uKL8I8g2yaOpQvoLWmZHGm
9
+ zU+hA7EWuplxq+CRq5kL/5BqSNXqU/G5AOSRC1lCUpuxKm8GWWFfEDNAV7uGadUn
10
+ gy2de0heeoHNpSjNpcV451fgcJ78IK2hU/w8fPBEQBSfYuwFWk4cVu4U3UmTE68I
11
+ O7PpCdTjk70IOsLT8uBagAOw92Fj0mGU7agCdWfJ+LjPRUtg+PhVvODatL3taG+l
12
+ FAParsomiRqKGINyn8vALXNISuBYHVDUzv93P10gG5rA2sJ7953/+++Hr9DoLpmL
13
+ SH/q/LebFzPJ2u6KzLc6bam1YX0w/MSNTJVIxA5V/QKBgQDU+iFXdShLwvEXGVtb
14
+ FdZuRk3XsN+yfkFyM9SZrmaLF2VBALkC5pd+rYkXSaTA/cbs623VOYpoJhVmjL8d
15
+ VvTlN/G+8TzfdsmOlAXiOSiUn3VKM/Othu5l9k0AgylU8aXBWTUv5FzmV8gMn+/s
16
+ 9oOucAVFa60LdkR2d609y/tKnwKBgQC95Gviall3E/+7drT05KxPPGDKRUjhCLBe
17
+ BNj2+ttSt4+v+E5v3K+LSd11VfGkvLkDvkhjiJlVamf+XgLne3TLrEThAKq8ySUr
18
+ XKBRi+nfmisUHSrMGljHw500Rx+MR/LEpfEERMosLQWTrOTz5VG2RueVHbWbD622
19
+ Witr8tnV/wKBgGDYUNr9GlLBFXJEhIc5ueUxMOp4sm/u+4Gb0fwEEvsCq3dQhdCs
20
+ 3IytCp69TR65B4DqWWpRHP/Y+XhFXg5QYVHuC46hEeYnlOWxp69EAJD8pZAVaaQp
21
+ rDRPOJqYCe5nZ9Ew6H+bnybbGcur2qTtP9nNdIgpu2lv4RfhubRVEjLPAoGAXqzb
22
+ SSii8GbNMwcNU6gLbPn6e/6tRl1RqZ6bGhCadxREFIUlfko2T6kFPDIcZ3kceYxO
23
+ hSme4WJK9RykMAtygPWj5daySauz13m4CNBMS4qO/dlI9DgSmY6i+2SWixd4J6lg
24
+ kDNH5VyREj66bAuigNG7NrJ4UBYyEt/EFG8hQrsCgYEAyLwk7f2Wgu9ykdwSrrQE
25
+ TBK0iOVUcwPhxj1UbFyDxPdO0EspyKtIFD5w/sbBtQbJGSUFd7ZPoCsYkT2yAsDp
26
+ 3cI/ubRxA+/GaqUo84QxvJ4Uqdu8YS8C0FCEnhXGjA60Y5HFzufJF5EqfzwNctCr
27
+ G0cRyX/4Ut4BNUcir/CRVL0=
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,40 @@
1
+ require_relative 'client_credentials_token_exchange_test'
2
+ require_relative 'token_exchange_response_body_test'
3
+ require_relative 'token_exchange_response_headers_test'
4
+
5
+ module UDAPSecurityTestKit
6
+ class ClientCredentialsAuthenticationGroup < Inferno::TestGroup
7
+ title 'UDAP Client Credentials Authorization & Authentication'
8
+ description %(
9
+ This group tests the use of the client_credentials grant type to authenticate to an authorization server and
10
+ receive an access token, as described
11
+ in the [business-to-business (B2B) profile requirements](https://hl7.org/fhir/us/udap-security/STU1/b2b.html).
12
+ )
13
+ id :udap_client_credentials_authentication_group
14
+
15
+ test from: :udap_client_credentials_token_exchange,
16
+ config: {
17
+ requests: {
18
+ token_exchange: {
19
+ name: :client_credentials_token_exchange
20
+ }
21
+ }
22
+ }
23
+ test from: :udap_token_exchange_response_body,
24
+ config: {
25
+ inputs: {
26
+ token_response_body: {
27
+ name: :client_credentials_token_response_body
28
+ }
29
+ }
30
+ }
31
+ test from: :udap_token_exchange_response_headers,
32
+ config: {
33
+ requests: {
34
+ token_exchange: {
35
+ name: :client_credentials_token_exchange
36
+ }
37
+ }
38
+ }
39
+ end
40
+ end
@@ -0,0 +1,105 @@
1
+ require_relative 'dynamic_client_registration_group'
2
+ require_relative 'discovery_group'
3
+ require_relative 'client_credentials_authentication_group'
4
+
5
+ module UDAPSecurityTestKit
6
+ class ClientCredentialsGroup < Inferno::TestGroup
7
+ title 'UDAP Client Credentials Flow'
8
+ description %(
9
+ This group tests UDAP servers that support JWT authentication using an OAuth2.0 client_credentials grant flow and
10
+ includes the following sub-groups.
11
+
12
+ 1. Discovery Group
13
+ 2. Dynamic Client Registration
14
+ 3. Authorization and Authentication - supports only the [Business-to-Business (B2B)](https://hl7.org/fhir/us/udap-security/STU1/b2b.html)
15
+ profile in the UDAP IG
16
+ )
17
+ id :udap_client_credentials_group
18
+
19
+ input_instructions %(
20
+ **Discovery Tests**
21
+
22
+ #{DiscoveryGroup.discovery_group_input_instructions}
23
+
24
+ **Dynamic Client Registration Tests**
25
+
26
+ #{DynamicClientRegistrationGroup.dynamic_client_registration_input_instructions}
27
+ )
28
+
29
+ group from: :udap_discovery_group,
30
+ id: :auth_code_discovery_group,
31
+ run_as_group: true,
32
+ config: {
33
+ inputs: {
34
+ required_flow_type: {
35
+ name: :flow_type_client_creds,
36
+ title: 'Required OAuth2.0 Flow Type for Client Credentials Workflow',
37
+ optional: 'false',
38
+ default: ['client_credentials'],
39
+ locked: true
40
+ }
41
+ }
42
+ }
43
+
44
+ group from: :udap_dynamic_client_registration_group,
45
+ id: :client_creds_dcr_group,
46
+ run_as_group: true,
47
+ config: {
48
+ inputs: {
49
+ udap_registration_grant_type: {
50
+ name: :reg_grant_type_client_creds,
51
+ default: 'client_credentials',
52
+ locked: true
53
+ },
54
+ udap_client_cert_pem: {
55
+ name: :udap_client_cert_pem_client_creds_flow,
56
+ title: 'Client Credentials Client Certificate(s) (PEM Format)'
57
+ },
58
+ udap_client_private_key_pem: {
59
+ name: :udap_client_private_key_client_creds_flow,
60
+ title: 'Client Credentials Client Private Key (PEM Format)'
61
+ },
62
+ udap_cert_iss: {
63
+ name: :udap_cert_iss_client_creds_flow,
64
+ title: 'Client Credentials JWT Issuer (iss) Claim'
65
+ },
66
+ udap_registration_requested_scope: {
67
+ name: :udap_registration_scope_client_creds_flow,
68
+ title: 'Client Credentials Registration Requested Scope(s)',
69
+ description: %(
70
+ String containing a space delimited list of scopes requested by the client application for use in
71
+ subsequent requests. The Authorization Server MAY consider this list when deciding the scopes that it
72
+ will allow the application to subsequently request. Apps requesting the "client_credentials" grant
73
+ type SHOULD request system scopes.
74
+ )
75
+ },
76
+ udap_registration_certifications: {
77
+ name: :udap_registration_certifications_client_creds_flow,
78
+ title: 'Client Credentials UDAP Registration Certifications'
79
+ }
80
+ },
81
+ outputs: {
82
+ udap_client_cert_pem: {
83
+ name: :udap_client_cert_pem_client_creds_flow
84
+ },
85
+ udap_client_private_key_pem: {
86
+ name: :udap_client_private_key_client_creds_flow
87
+ },
88
+ udap_cert_iss: {
89
+ name: :udap_cert_iss_client_creds_flow
90
+ }
91
+ }
92
+ } do
93
+ input_order :udap_registration_endpoint,
94
+ :reg_grant_type_client_creds,
95
+ :udap_client_cert_pem_client_creds_flow,
96
+ :udap_client_private_key_client_creds_flow,
97
+ :udap_cert_iss_client_creds_flow,
98
+ :udap_registration_scope_client_creds_flow,
99
+ :udap_jwt_signing_alg, :udap_registration_certifications_client_creds_flow
100
+ end
101
+
102
+ group from: :udap_client_credentials_authentication_group,
103
+ run_as_group: true
104
+ end
105
+ end
@@ -0,0 +1,130 @@
1
+ require_relative 'udap_client_assertion_payload_builder'
2
+
3
+ module UDAPSecurityTestKit
4
+ class ClientCredentialsTokenExchangeTest < Inferno::Test
5
+ title 'OAuth token exchange request succeeds when supplied correct information'
6
+ description %(
7
+ The [UDAP Security IG Section 5.2 on Obtaining an Access Token](https://hl7.org/fhir/us/udap-security/STU1/b2b.html#obtaining-an-access-token)
8
+ states the following:
9
+ - The client SHALL use its private key to sign an Authentication
10
+ Token ... and include this JWT in the
11
+ client_assertion parameter of its token request
12
+ - Client applications using the client credentials grant and
13
+ authenticating with a private key and
14
+ Authentication Token as per Section 5.2.1 SHALL submit a POST request to the Authorization Server’s token
15
+ endpoint
16
+ - An Authorization Server receiving token requests containin
17
+ Authentication Tokens as above SHALL validate and
18
+ respond to the request as per Sections 6 and 7 of UDAP JWT-Based Client Authentication.
19
+
20
+ Furthermore, the inclusion of an `extensions` claim in the Authentication JWT is required for B2B client apps
21
+ using the client credentials flow. Inferno provides an extensions object with the following information:
22
+ - `'version'`: `'1'`
23
+ - `'subject_name'`: `'UDAP Test Kit'`
24
+ - `'organization_name'`: `'Inferno Framework'`
25
+ - `'organization_id'`: `'https://inferno-framework.github.io/'`
26
+ - `'purpose_of_use'`: `['SYSDEV']`
27
+
28
+ This test creates an authentication JWT, POSTs a token request to the server's token endpoint, and expects a 200
29
+ response.
30
+ )
31
+ id :udap_client_credentials_token_exchange
32
+
33
+ input :udap_client_id,
34
+ title: 'Client ID',
35
+ description: 'Client ID as registered with the authorization server.'
36
+
37
+ input :udap_token_endpoint,
38
+ title: 'Token Endpoint',
39
+ description: 'The full URL from which Inferno will request an access token'
40
+
41
+ input :udap_client_cert_pem_client_creds_flow,
42
+ title: 'X.509 Client Certificate(s) (PEM Format)',
43
+ type: 'textarea',
44
+ description: %(
45
+ A list of one or more X.509 certificates in PEM format separated by a newline. The first (leaf) certificate
46
+ MUST represent the client entity Inferno registered as,
47
+ and the trust chain that will be built from the provided certificate(s) must resolve to a CA trusted by the
48
+ authorization server under test.
49
+ )
50
+
51
+ input :udap_client_private_key_client_creds_flow,
52
+ type: 'textarea',
53
+ title: 'Client Private Key (PEM Format)',
54
+ description: 'The private key corresponding to the X.509 client certificate'
55
+
56
+ input :udap_jwt_signing_alg,
57
+ title: 'JWT Signing Algorithm',
58
+ description: %(
59
+ Algorithm used to sign UDAP JSON Web Tokens (JWTs). UDAP Implementations SHALL support
60
+ RS256.
61
+ ),
62
+ type: 'radio',
63
+ options: {
64
+ list_options: [
65
+ {
66
+ label: 'RS256',
67
+ value: 'RS256'
68
+ }
69
+ ]
70
+ },
71
+ default: 'RS256',
72
+ locked: true
73
+
74
+ output :token_retrieval_time
75
+ output :client_credentials_token_response_body
76
+ makes_request :token_exchange
77
+
78
+ run do
79
+ # SYSDEV purpose of use definition:
80
+ # "To perform one or more operations on information to design, develop
81
+ # implement, test, or deploy a healthcare system or application."
82
+ # See https://terminology.hl7.org/5.5.0/ValueSet-v3-PurposeOfUse.html
83
+ extensions = {
84
+ 'hl7-b2b' => {
85
+ 'version' => '1',
86
+ 'subject_name' => 'UDAP Test Kit',
87
+ 'organization_name' => 'Inferno Framework',
88
+ 'organization_id' => 'https://inferno-framework.github.io/',
89
+ 'purpose_of_use' => ['SYSDEV']
90
+ }
91
+ }
92
+
93
+ client_assertion_payload = UDAPClientAssertionPayloadBuilder.build(
94
+ udap_client_id,
95
+ udap_token_endpoint,
96
+ extensions.to_json
97
+ )
98
+
99
+ x5c_certs = UDAPJWTBuilder.split_user_input_cert_string(
100
+ udap_client_cert_pem_client_creds_flow
101
+ )
102
+
103
+ client_assertion_jwt = UDAPJWTBuilder.encode_jwt_with_x5c_header(
104
+ client_assertion_payload,
105
+ udap_client_private_key_client_creds_flow,
106
+ udap_jwt_signing_alg,
107
+ x5c_certs
108
+ )
109
+
110
+ token_exchange_headers, token_exchange_body = UDAPRequestBuilder.build_token_exchange_request(
111
+ client_assertion_jwt,
112
+ 'client_credentials',
113
+ nil,
114
+ nil
115
+ )
116
+
117
+ post(udap_token_endpoint,
118
+ body: token_exchange_body,
119
+ name: :token_exchange,
120
+ headers: token_exchange_headers)
121
+
122
+ assert_response_status(200)
123
+ assert_valid_json(request.response_body)
124
+
125
+ output token_retrieval_time: Time.now.iso8601
126
+
127
+ output client_credentials_token_response_body: request.response_body
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,16 @@
1
+ # Module for assertion methods that are used across multiple tests
2
+ module CommonAssertions
3
+ extend Inferno::DSL::Assertions
4
+
5
+ def self.assert_array_of_strings(config, field)
6
+ values = config[field]
7
+
8
+ assert values.is_a?(Array), "`#{field}` should be an Array, but found #{values.class.name}"
9
+
10
+ non_string_values = values.reject { |value| value.is_a?(String) }
11
+
12
+ assert non_string_values.blank?,
13
+ "`#{field}` should be an Array of strings, but found
14
+ #{non_string_values.map(&:class).map(&:name).join(', ')}"
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module UDAPSecurityTestKit
2
+ class DefaultCertFileLoader
3
+ def self.load_default_ca_pem_file
4
+ raw_cert = File.read(File.join(File.dirname(__FILE__), 'certs/InfernoCA.pem'))
5
+ cert = OpenSSL::X509::Certificate.new raw_cert
6
+ cert.to_pem
7
+ end
8
+
9
+ def self.load_default_ca_private_key_file
10
+ raw_key = File.read(File.join(File.dirname(__FILE__), 'certs/InfernoCA.key'))
11
+ private_key = OpenSSL::PKey::RSA.new raw_key
12
+ private_key.to_pem
13
+ end
14
+
15
+ def self.load_test_client_cert_pem_file
16
+ raw_cert = File.read(File.join(File.dirname(__FILE__), 'certs/TestClient.pem'))
17
+ cert = OpenSSL::X509::Certificate.new raw_cert
18
+ cert.to_pem
19
+ end
20
+
21
+ def self.load_test_client_private_key_file
22
+ raw_key = File.read(File.join(File.dirname(__FILE__), 'certs/TestClientPrivateKey.key'))
23
+ key = OpenSSL::PKey::RSA.new raw_key
24
+ key.to_pem
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ require 'jwt'
2
+ require_relative 'authorization_endpoint_field_test'
3
+ require_relative 'grant_types_supported_field_test'
4
+ require_relative 'reg_endpoint_jwt_signing_alg_values_supported_field_test'
5
+ require_relative 'registration_endpoint_field_test'
6
+ require_relative 'scopes_supported_field_test'
7
+ require_relative 'signed_metadata_contents_test'
8
+ require_relative 'signed_metadata_field_test'
9
+ require_relative 'token_endpoint_auth_methods_supported_field_test'
10
+ require_relative 'token_endpoint_auth_signing_alg_values_supported_field_test'
11
+ require_relative 'token_endpoint_field_test'
12
+ require_relative 'udap_auth_extensions_required_field_test'
13
+ require_relative 'udap_auth_extensions_supported_field_test'
14
+ require_relative 'udap_certifications_required_field_test'
15
+ require_relative 'udap_certifications_supported_field_test'
16
+ require_relative 'udap_profiles_supported_field_test'
17
+ require_relative 'udap_versions_supported_field_test'
18
+ require_relative 'well_known_endpoint_test'
19
+ require_relative 'signed_metadata_trust_verification_test'
20
+ module UDAPSecurityTestKit
21
+ class DiscoveryGroup < Inferno::TestGroup
22
+ include Inferno::DSL::Assertions
23
+
24
+ title 'UDAP Discovery'
25
+ description %(
26
+ Verify that server configuration is made available and conforms with [the
27
+ discovery
28
+ requirements](https://hl7.org/fhir/us/udap-security/STU1/discovery.html).
29
+ )
30
+ id :udap_discovery_group
31
+
32
+ input :required_flow_type,
33
+ title: 'Required Supported OAuth2.0 Grant Type(s)',
34
+ description: 'Which grant type(s) must be supported per the returned Discovery metadata',
35
+ type: 'checkbox',
36
+ optional: 'true',
37
+ options: {
38
+ list_options: [
39
+ {
40
+ label: 'Authorization Code',
41
+ value: 'authorization_code'
42
+ },
43
+ {
44
+ label: 'Client Credentials',
45
+ value: 'client_credentials'
46
+ }
47
+ ]
48
+ }
49
+
50
+ def self.discovery_group_input_instructions
51
+ %(
52
+ Inferno currently does not support the use of the Authority Information Access (AIA) extension to access issuing
53
+ certificates. As such, Inferno must be provided any intermediate server certificates needed to establish a
54
+ trust chain. If the intermediate CAs are not included in the x5c header of the server's signed metadata JWT,
55
+ testers may include them along with the root CA as a trust anchor input.
56
+ )
57
+ end
58
+ input_instructions discovery_group_input_instructions
59
+
60
+ output :udap_registration_certficiations_required
61
+ output :udap_registration_endpoint
62
+ output :udap_registration_grant_type
63
+
64
+ test from: :udap_well_known_endpoint
65
+ test from: :udap_versions_supported_field
66
+ test from: :udap_grant_types_supported_field
67
+ test from: :udap_profiles_supported_field
68
+ test from: :udap_auth_extensions_supported_field
69
+ test from: :udap_auth_extensions_required_field
70
+ test from: :udap_certifications_supported_field
71
+ test from: :udap_certifications_required_field
72
+ test from: :udap_scopes_supported_field
73
+ test from: :udap_authorization_endpoint_field
74
+ test from: :udap_token_endpoint_field
75
+ test from: :udap_token_endpoint_auth_methods_supported_field
76
+ test from: :udap_token_endpoint_auth_signing_alg_values_supported_field
77
+ test from: :udap_registration_endpoint_field
78
+ test from: :udap_reg_endpoint_jwt_signing_alg_values_supported_field
79
+ test from: :udap_signed_metadata_field
80
+ test from: :udap_signed_metadata_contents
81
+ test from: :udap_signed_metadata_trust_verification, optional: true,
82
+ config: {
83
+ inputs: {
84
+ udap_server_trust_anchor_certs: {
85
+ optional: true
86
+ }
87
+ }
88
+ }
89
+ end
90
+ end
@@ -0,0 +1,129 @@
1
+ require_relative 'registration_failure_invalid_contents_test'
2
+ require_relative 'registration_failure_invalid_jwt_signature_test'
3
+ require_relative 'registration_success_test'
4
+ require_relative 'registration_success_contents_test'
5
+
6
+ module UDAPSecurityTestKit
7
+ class DynamicClientRegistrationGroup < Inferno::TestGroup
8
+ title 'UDAP Dynamic Client Registration'
9
+ description %(
10
+ Generate and sign a software statement to register the client with the authorization server as described in the
11
+ [dynamic client registration requirements](https://hl7.org/fhir/us/udap-security/STU1/registration.html).
12
+ )
13
+ id :udap_dynamic_client_registration_group
14
+
15
+ def self.dynamic_client_registration_input_instructions
16
+ %(
17
+ Testers must provide a client certificate and any additional CAs needed for the authorization server under test to
18
+ establish a trust chain.
19
+
20
+ Cancelling a UDAP client's registration is not a required server capability and as such the Inferno client has no
21
+ way of resetting state on the authorization server after a successful registration attempt. Testers wishing to
22
+ run the Dynamic Client Registration tests more than once must do one of the following:
23
+ - Remove the Inferno test client's registration out-of-band before re-running tests, to register the original
24
+ client URI anew
25
+ - Specifiy a different client URI as the issuer input (if the client cert has more than one Subject Alternative
26
+ Name (SAN) URI entry), to register a different logical client with the original certificate
27
+ - Provide a different client certificate and its associated URI to register a new logical client
28
+ )
29
+ end
30
+
31
+ input_instructions dynamic_client_registration_input_instructions
32
+
33
+ input :udap_registration_endpoint,
34
+ title: 'UDAP Dynamic Client Registration Endpoint',
35
+ description: %(
36
+ The absolute URL of the dynamic client registration endpoint.
37
+ )
38
+
39
+ input :udap_registration_grant_type,
40
+ title: 'Client Registration Grant Type',
41
+ description: %(
42
+ The OAuth2.0 grant type for which this client will register itself. A given client may register as either
43
+ option, but not both.
44
+ ),
45
+ type: 'radio',
46
+ options: {
47
+ list_options: [
48
+ {
49
+ label: 'Authorization Code',
50
+ value: 'authorization_code'
51
+ },
52
+ {
53
+ label: 'Client Credentials',
54
+ value: 'client_credentials'
55
+ }
56
+ ]
57
+ }
58
+
59
+ input :udap_client_cert_pem,
60
+ title: 'X.509 Client Certificate(s) (PEM Format)',
61
+ description: %(
62
+ A list of one or more X.509 certificates in PEM format separated by a newline. The first (leaf) certificate
63
+ MUST represent the client entity Inferno will register as,
64
+ and the trust chain that will be built from the provided certificate(s) must resolve to a CA trusted by the
65
+ authorization server under test.
66
+ ),
67
+ type: 'textarea',
68
+ optional: false
69
+
70
+ input :udap_client_private_key_pem,
71
+ title: 'Client Private Key (PEM Format)',
72
+ description: %(
73
+ The private key corresponding to the client certificate used for registration, in PEM format. Used to sign
74
+ registration and/or authentication JWTs.
75
+ ),
76
+ type: 'textarea',
77
+ optional: false
78
+
79
+ input :udap_cert_iss,
80
+ title: 'JWT Issuer (iss) Claim',
81
+ description: %(
82
+ MUST correspond to a unique URI entry in the Subject Alternative Name (SAN) extension of the client
83
+ certificate used for registration.
84
+ ),
85
+ optional: false
86
+
87
+ input :udap_jwt_signing_alg,
88
+ title: 'JWT Signing Algorithm',
89
+ description: %(
90
+ Algorithm used to sign UDAP JSON Web Tokens (JWTs). UDAP Implementations SHALL support
91
+ RS256.
92
+ ),
93
+ type: 'radio',
94
+ options: {
95
+ list_options: [
96
+ {
97
+ label: 'RS256',
98
+ value: 'RS256'
99
+ }
100
+ ]
101
+ },
102
+ default: 'RS256',
103
+ locked: true
104
+
105
+ input :udap_registration_requested_scope,
106
+ title: 'Scope(s) Requested',
107
+ description: %(
108
+ String containing a space delimited list of scopes requested by the client application for use in
109
+ subsequent requests. The Authorization Server MAY consider this list when deciding the scopes that it will
110
+ allow the application to subsequently request. Apps requesting the "client_credentials" grant type SHOULD
111
+ request system scopes; apps requesting
112
+ the "authorization_code" grant type SHOULD request user or patient scopes.
113
+ )
114
+
115
+ input :udap_registration_certifications,
116
+ title: 'UDAP Certifications',
117
+ description: %(
118
+ Additional UDAP certifications to include in registration request, if required by the authorization server.
119
+ Include a space separated list of strings representing a Base64-encoded, signed JWT.
120
+ ),
121
+ type: 'textarea',
122
+ optional: true
123
+
124
+ test from: :udap_registration_failure_invalid_contents
125
+ test from: :udap_registration_failure_invalid_jwt_signature
126
+ test from: :udap_registration_success
127
+ test from: :udap_registration_success_contents
128
+ end
129
+ end