udap_security_test_kit 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|