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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/lib/udap_security_test_kit/authorization_code_authentication_group.rb +44 -0
- data/lib/udap_security_test_kit/authorization_code_group.rb +103 -0
- data/lib/udap_security_test_kit/authorization_code_received_test.rb +31 -0
- data/lib/udap_security_test_kit/authorization_code_redirect_test.rb +74 -0
- data/lib/udap_security_test_kit/authorization_code_token_exchange_test.rb +103 -0
- data/lib/udap_security_test_kit/authorization_endpoint_field_test.rb +43 -0
- data/lib/udap_security_test_kit/certs/InfernoCA.key +52 -0
- data/lib/udap_security_test_kit/certs/InfernoCA.pem +35 -0
- data/lib/udap_security_test_kit/certs/TestClient.pem +32 -0
- data/lib/udap_security_test_kit/certs/TestClientPrivateKey.key +28 -0
- data/lib/udap_security_test_kit/client_credentials_authentication_group.rb +40 -0
- data/lib/udap_security_test_kit/client_credentials_group.rb +105 -0
- data/lib/udap_security_test_kit/client_credentials_token_exchange_test.rb +130 -0
- data/lib/udap_security_test_kit/common_assertions.rb +16 -0
- data/lib/udap_security_test_kit/default_cert_file_loader.rb +27 -0
- data/lib/udap_security_test_kit/discovery_group.rb +90 -0
- data/lib/udap_security_test_kit/dynamic_client_registration_group.rb +129 -0
- data/lib/udap_security_test_kit/generate_client_certs_test.rb +60 -0
- data/lib/udap_security_test_kit/grant_types_supported_field_test.rb +53 -0
- data/lib/udap_security_test_kit/reg_endpoint_jwt_signing_alg_values_supported_field_test.rb +29 -0
- data/lib/udap_security_test_kit/registration_endpoint_field_test.rb +30 -0
- data/lib/udap_security_test_kit/registration_failure_invalid_contents_test.rb +68 -0
- data/lib/udap_security_test_kit/registration_failure_invalid_jwt_signature_test.rb +70 -0
- data/lib/udap_security_test_kit/registration_success_contents_test.rb +64 -0
- data/lib/udap_security_test_kit/registration_success_test.rb +68 -0
- data/lib/udap_security_test_kit/scopes_supported_field_test.rb +26 -0
- data/lib/udap_security_test_kit/signed_metadata_contents_test.rb +89 -0
- data/lib/udap_security_test_kit/signed_metadata_field_test.rb +31 -0
- data/lib/udap_security_test_kit/signed_metadata_trust_verification_test.rb +54 -0
- data/lib/udap_security_test_kit/software_statement_builder.rb +32 -0
- data/lib/udap_security_test_kit/token_endpoint_auth_methods_supported_field_test.rb +22 -0
- data/lib/udap_security_test_kit/token_endpoint_auth_signing_alg_values_supported_field_test.rb +32 -0
- data/lib/udap_security_test_kit/token_endpoint_field_test.rb +30 -0
- data/lib/udap_security_test_kit/token_exchange_response_body_test.rb +30 -0
- data/lib/udap_security_test_kit/token_exchange_response_headers_test.rb +30 -0
- data/lib/udap_security_test_kit/udap_auth_extensions_required_field_test.rb +38 -0
- data/lib/udap_security_test_kit/udap_auth_extensions_supported_field_test.rb +31 -0
- data/lib/udap_security_test_kit/udap_certifications_required_field_test.rb +45 -0
- data/lib/udap_security_test_kit/udap_certifications_supported_field_test.rb +33 -0
- data/lib/udap_security_test_kit/udap_client_assertion_payload_builder.rb +15 -0
- data/lib/udap_security_test_kit/udap_jwt_builder.rb +30 -0
- data/lib/udap_security_test_kit/udap_jwt_validator.rb +71 -0
- data/lib/udap_security_test_kit/udap_profiles_supported_field_test.rb +47 -0
- data/lib/udap_security_test_kit/udap_request_builder.rb +43 -0
- data/lib/udap_security_test_kit/udap_versions_supported_field_test.rb +21 -0
- data/lib/udap_security_test_kit/udap_x509_certificate.rb +42 -0
- data/lib/udap_security_test_kit/version.rb +3 -0
- data/lib/udap_security_test_kit/well_known_endpoint_test.rb +31 -0
- data/lib/udap_security_test_kit.rb +63 -0
- 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
|