Mercurial > hg > orthanc-tests
annotate Tests/CheckDicomTls.py @ 574:ee71526e11ed
contributing
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 14 Aug 2023 10:19:50 +0200 |
parents | 933fe1bbce4f |
children | 8aa101e126d0 |
rev | line source |
---|---|
375 | 1 #!/usr/bin/python |
2 | |
3 # Orthanc - A Lightweight, RESTful DICOM Store | |
4 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
5 # Department, University Hospital of Liege, Belgium | |
511
933fe1bbce4f
upgrade to year 2023
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
449
diff
changeset
|
6 # Copyright (C) 2017-2023 Osimis S.A., Belgium |
933fe1bbce4f
upgrade to year 2023
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
449
diff
changeset
|
7 # Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
375 | 8 # |
9 # This program is free software: you can redistribute it and/or | |
10 # modify it under the terms of the GNU General Public License as | |
11 # published by the Free Software Foundation, either version 3 of the | |
12 # License, or (at your option) any later version. | |
13 # | |
14 # This program is distributed in the hope that it will be useful, but | |
15 # WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 # General Public License for more details. | |
18 # | |
19 # You should have received a copy of the GNU General Public License | |
20 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | |
22 | |
23 | |
24 import argparse | |
25 import os | |
26 import pprint | |
27 import re | |
28 import sys | |
29 import subprocess | |
30 import unittest | |
31 | |
32 from Toolbox import * | |
33 | |
34 | |
35 ## | |
36 ## Parse the command-line arguments | |
37 ## | |
38 | |
39 parser = argparse.ArgumentParser(description = 'Run the integration tests for DICOM TLS in Orthanc.') | |
40 | |
41 parser.add_argument('--server', | |
42 default = 'localhost', | |
43 help = 'Address of the Orthanc server to test') | |
44 parser.add_argument('--aet', | |
45 default = 'ORTHANC', | |
46 help = 'AET of the Orthanc instance to test') | |
47 parser.add_argument('--dicom', | |
48 type = int, | |
49 default = 4242, | |
50 help = 'DICOM port of the Orthanc instance to test') | |
51 parser.add_argument('--rest', | |
52 type = int, | |
53 default = 8042, | |
54 help = 'Port to the REST API') | |
55 parser.add_argument('--username', | |
56 default = 'alice', | |
57 help = 'Username to the REST API') | |
58 parser.add_argument('--password', | |
59 default = 'orthanctest', | |
60 help = 'Password to the REST API') | |
61 parser.add_argument('--force', help = 'Do not warn the user', | |
62 action = 'store_true') | |
63 parser.add_argument('--config', help = 'Create the configuration files for this test in the current folder', | |
64 action = 'store_true') | |
65 parser.add_argument('options', metavar = 'N', nargs = '*', | |
66 help='Arguments to Python unittest') | |
67 | |
68 args = parser.parse_args() | |
69 | |
70 | |
71 ## | |
72 ## Configure the testing context | |
73 ## | |
74 | |
75 | |
76 if args.config: | |
77 def CreateCertificate(name): | |
78 subprocess.check_call([ 'openssl', 'req', '-x509', '-nodes', '-days', '365', '-newkey', 'rsa:2048', | |
79 '-keyout', '%s.key' % name, | |
80 '-out', '%s.crt' % name, | |
81 '-subj', '/C=BE/CN=localhost' ]) | |
82 | |
83 print('Writing configuration to folder: %s' % args.config) | |
84 CreateCertificate('dicom-tls-a') | |
85 CreateCertificate('dicom-tls-b') | |
86 CreateCertificate('dicom-tls-c') # Not trusted by Orthanc | |
87 | |
88 with open('dicom-tls-trusted.crt', 'w') as f: | |
89 for i in [ 'dicom-tls-a.crt', 'dicom-tls-b.crt' ]: | |
90 with open(i, 'r') as g: | |
91 f.write(g.read()) | |
92 | |
93 with open('dicom-tls.json', 'w') as f: | |
94 f.write(json.dumps({ | |
95 'DicomTlsEnabled' : True, | |
96 'DicomTlsCertificate' : 'dicom-tls-a.crt', | |
97 'DicomTlsPrivateKey' : 'dicom-tls-a.key', | |
98 'DicomTlsTrustedCertificates' : 'dicom-tls-trusted.crt', | |
99 'ExecuteLuaEnabled' : True, | |
100 'RemoteAccessAllowed' : True, | |
101 'RegisteredUsers' : { | |
102 'alice' : 'orthanctest' | |
103 }, | |
400
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
104 'DicomTlsRemoteCertificateRequired' : False, # New in Orthanc 1.9.3 |
375 | 105 })) |
106 | |
107 exit(0) | |
108 | |
109 | |
110 if not args.force: | |
111 print(""" | |
112 WARNING: This test will remove all the content of your | |
113 Orthanc instance running on %s! | |
114 | |
115 Are you sure ["yes" to go on]?""" % args.server) | |
116 | |
117 if sys.stdin.readline().strip() != 'yes': | |
118 print('Aborting...') | |
119 exit(0) | |
120 | |
121 | |
122 ORTHANC = DefineOrthanc(server = args.server, | |
123 username = args.username, | |
124 password = args.password, | |
125 restPort = args.rest, | |
126 aet = args.aet, | |
127 dicomPort = args.dicom) | |
128 | |
129 | |
130 ## | |
131 ## The tests | |
132 ## | |
133 | |
134 | |
135 FNULL = open(os.devnull, 'w') # Emulates "subprocess.DEVNULL" on Python 2.7 | |
136 | |
137 | |
138 class Orthanc(unittest.TestCase): | |
139 def setUp(self): | |
140 if (sys.version_info >= (3, 0)): | |
141 # Remove annoying warnings about unclosed socket in Python 3 | |
142 import warnings | |
143 warnings.simplefilter('ignore', ResourceWarning) | |
144 | |
145 DropOrthanc(ORTHANC) | |
146 | |
147 | |
148 def test_incoming(self): | |
149 # No certificate | |
150 self.assertRaises(Exception, lambda: subprocess.check_call([ | |
151 FindExecutable('echoscu'), | |
152 ORTHANC['Server'], | |
153 str(ORTHANC['DicomPort']), | |
154 '-aec', 'ORTHANC', | |
155 ], stderr = FNULL)) | |
156 | |
157 subprocess.check_call([ | |
158 FindExecutable('echoscu'), | |
159 ORTHANC['Server'], | |
160 str(ORTHANC['DicomPort']), | |
161 '-aec', 'ORTHANC', | |
162 '+tls', 'dicom-tls-b.key', 'dicom-tls-b.crt', | |
163 '+cf', 'dicom-tls-a.crt', | |
164 ], stderr = FNULL) | |
165 | |
166 self.assertRaises(Exception, lambda: subprocess.check_call([ | |
167 FindExecutable('echoscu'), | |
168 ORTHANC['Server'], | |
169 str(ORTHANC['DicomPort']), | |
170 '-aec', 'ORTHANC', | |
171 '+tls', 'dicom-tls-c.key', 'dicom-tls-c.crt', # Not trusted by Orthanc | |
172 '+cf', 'dicom-tls-a.crt', | |
173 ], stderr = FNULL)) | |
174 | |
175 self.assertRaises(Exception, lambda: subprocess.check_call([ | |
176 FindExecutable('echoscu'), | |
177 ORTHANC['Server'], | |
178 str(ORTHANC['DicomPort']), | |
179 '-aec', 'ORTHANC', | |
180 '+tls', 'dicom-tls-b.key', 'dicom-tls-b.crt', | |
181 '+cf', 'dicom-tls-b.crt', # Not the certificate of Orthanc | |
182 ], stderr = FNULL)) | |
183 | |
184 | |
185 def test_outgoing_to_self(self): | |
186 u = UploadInstance(ORTHANC, 'DummyCT.dcm') ['ID'] | |
187 | |
188 # Error, as DICOM TLS is not enabled | |
189 DoPut(ORTHANC, '/modalities/self', { | |
190 'AET' : 'ORTHANC', | |
191 'Host' : ORTHANC['Server'], | |
192 'Port' : ORTHANC['DicomPort'], | |
193 }) | |
194 | |
195 self.assertRaises(Exception, lambda: DoPost(ORTHANC, '/modalities/self/store', u)) | |
196 | |
197 # Retry using DICOM TLS | |
198 DoPut(ORTHANC, '/modalities/self', { | |
199 'AET' : 'ORTHANC', | |
200 'Host' : ORTHANC['Server'], | |
201 'Port' : ORTHANC['DicomPort'], | |
202 'UseDicomTls' : True, | |
203 }) | |
204 | |
205 self.assertEqual(1, DoPost(ORTHANC, '/modalities/self/store', u) ['InstancesCount']) | |
206 | |
400
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
207 |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
208 def test_anonymous(self): |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
209 # Fails on Orthanc <= 1.9.2 |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
210 # https://book.orthanc-server.com/faq/dicom-tls.html#secure-tls-connections-without-certificate |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
211 subprocess.check_call([ |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
212 FindExecutable('echoscu'), |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
213 ORTHANC['Server'], |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
214 str(ORTHANC['DicomPort']), |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
215 '-aec', 'ORTHANC', |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
216 '--anonymous-tls', |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
217 '+cf', 'dicom-tls-a.crt', |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
218 ], stderr = FNULL) |
f454fe86061b
dicom tls: test_anonymous
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
375
diff
changeset
|
219 |
375 | 220 |
221 try: | |
222 print('\nStarting the tests...') | |
223 unittest.main(argv = [ sys.argv[0] ] + args.options) | |
224 | |
225 finally: | |
226 print('\nDone') |