Skip to content

Commit be0b7e8

Browse files
authored
Merge pull request #85 from DMTF/HTTP-hardening
HTTP hardening
2 parents ebe0e32 + 00cec83 commit be0b7e8

14 files changed

+339
-197
lines changed

redfish_protocol_validator/accounts.py

+12-14
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def get_user_names(sut: SystemUnderTest, session,
2929
if uri in responses:
3030
response = responses[uri]
3131
else:
32-
response = session.get(sut.rhost + uri)
32+
response = sut.get(uri, session=session)
3333
sut.add_response(uri, response,
3434
resource_type=ResourceType.MANAGER_ACCOUNT,
3535
request_type=request_type)
@@ -56,7 +56,7 @@ def get_available_roles(sut: SystemUnderTest, session,
5656
if uri in responses:
5757
response = responses[uri]
5858
else:
59-
response = session.get(sut.rhost + uri)
59+
response = sut.get(uri, session=session)
6060
sut.add_response(uri, response,
6161
resource_type=ResourceType.ROLE,
6262
request_type=request_type)
@@ -132,7 +132,7 @@ def find_empty_account_slot(sut: SystemUnderTest, session,
132132
if uri in responses:
133133
response = responses[uri]
134134
else:
135-
response = session.get(sut.rhost + uri)
135+
response = sut.get(uri, session=session)
136136
sut.add_response(uri, response,
137137
resource_type=ResourceType.MANAGER_ACCOUNT,
138138
request_type=request_type)
@@ -159,7 +159,7 @@ def add_account_via_patch(sut: SystemUnderTest, session, user, role, password,
159159
request_type=request_type)
160160
success = response.status_code == requests.codes.OK
161161
if success:
162-
response = session.get(sut.rhost + uri)
162+
response = sut.get(uri, session=session)
163163
if response.ok:
164164
# Enable the account if it not already enabled
165165
data = utils.get_response_json(response)
@@ -209,7 +209,7 @@ def add_account(sut: SystemUnderTest, session,
209209
new_acct_uri = urlparse(location).path
210210
else:
211211
new_acct_uri = utils.get_response_json(response).get('@odata.id')
212-
response = session.get(sut.rhost + new_acct_uri)
212+
response = sut.get(new_acct_uri, session=session)
213213
sut.add_response(new_acct_uri, response,
214214
resource_type=ResourceType.MANAGER_ACCOUNT,
215215
request_type=request_type)
@@ -353,28 +353,26 @@ def password_change_required(sut: SystemUnderTest, session, user, password,
353353
headers = {
354354
'OData-Version': '4.0'
355355
}
356-
response = requests.post(sut.rhost + sut.sessions_uri, json=payload,
357-
headers=headers, verify=sut.verify)
356+
response = sut.post(sut.sessions_uri, json=payload,
357+
headers=headers, no_session=True)
358358
sut.add_response(sut.sessions_uri, response,
359359
request_type=RequestType.PWD_CHANGE_REQUIRED)
360360
# GET the account
361-
response = requests.get(sut.rhost + uri, auth=(user, password),
362-
headers=headers, verify=sut.verify)
361+
response = sut.get(uri, auth=(user, password), headers=headers, no_session=True)
363362
etag = utils.get_response_etag(response)
364363
sut.add_response(uri, response, resource_type=ResourceType.MANAGER_ACCOUNT,
365364
request_type=RequestType.PWD_CHANGE_REQUIRED)
366365
# try to get protected resource
367-
response = requests.get(sut.rhost + sut.sessions_uri,
368-
auth=(user, password), headers=headers,
369-
verify=sut.verify)
366+
response = sut.get(sut.sessions_uri, auth=(user, password), headers=headers,
367+
no_session=True)
370368
sut.add_response(sut.sessions_uri, response,
371369
request_type=RequestType.PWD_CHANGE_REQUIRED)
372370
# change password
373371
payload = {'Password': new_password(sut)}
374372
if etag:
375373
headers['If-Match'] = etag
376-
response = requests.patch(sut.rhost + uri, auth=(user, password), json=payload,
377-
headers=headers, verify=sut.verify)
374+
response = sut.patch(uri, json=payload, headers=headers,
375+
no_session=True, auth=(user, password))
378376
sut.add_response(uri, response,
379377
resource_type=ResourceType.MANAGER_ACCOUNT,
380378
request_type=RequestType.PWD_CHANGE_REQUIRED)

redfish_protocol_validator/resources.py

+84-84
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ def set_mgr_net_proto_uri(sut: SystemUnderTest, data):
3333

3434

3535
def find_certificates(sut: SystemUnderTest, data):
36-
if 'NetworkProtocol' in data:
37-
uri = data['NetworkProtocol']['@odata.id']
38-
r = sut.session.get(sut.rhost + uri)
36+
uri = data.get('NetworkProtocol', {}).get('@odata.id')
37+
if uri:
38+
r = sut.get(uri)
3939
yield {'uri': uri, 'response': r}
4040
if r.ok:
4141
d = utils.get_response_json(r)
42-
if 'HTTPS' in d and 'Certificates' in d['HTTPS']:
43-
coll_uri = d['HTTPS']['Certificates']['@odata.id']
44-
r = sut.session.get(sut.rhost + coll_uri)
42+
coll_uri = d.get('HTTPS', {}).get('Certificates', {}).get('@odata.id')
43+
if coll_uri:
44+
r = sut.get(coll_uri)
4545
yield {'uri': coll_uri, 'response': r}
4646
if r.ok:
4747
d = utils.get_response_json(r)
48-
if 'Members' in d and len(d['Members']):
49-
for m in d['Members']:
50-
uri = m['@odata.id']
48+
for m in d.get('Members', []):
49+
uri = m.get('@odata.id')
50+
if uri:
5151
# uncomment next 2 lines if we need to read certs
52-
# r = session.get(sut.rhost + uri)
52+
# r = sut.get(uri)
5353
# yield {'uri': uri, 'response': r}
5454
sut.add_cert(coll_uri, uri)
5555

@@ -65,25 +65,24 @@ def get_default_resources(sut: SystemUnderTest, uri='/redfish/v1/',
6565
:return: dict elements containing the URI and `requests` response
6666
"""
6767
# do GETs on spec-defined URIs
68-
yield {'uri': '/redfish', 'response': sut.session.get(
69-
sut.rhost + '/redfish')}
68+
yield {'uri': '/redfish', 'response': sut.get('/redfish')}
7069
yield {'uri': '/redfish/v1/odata', 'response':
71-
sut.session.get(sut.rhost + '/redfish/v1/odata')}
70+
sut.get('/redfish/v1/odata')}
7271
yield {'uri': '/redfish/v1', 'response':
73-
sut.session.get(sut.rhost + '/redfish/v1')}
72+
sut.get('/redfish/v1')}
7473
yield {'uri': '/redfish/v1/$metadata', 'response':
75-
sut.session.get(sut.rhost + '/redfish/v1/$metadata',
76-
headers={'accept': 'application/xml'})}
74+
sut.get('/redfish/v1/$metadata',
75+
headers={'accept': 'application/xml'})}
7776
yield {'uri': '/redfish/v1/openapi.yaml',
7877
'request_type': RequestType.YAML,
79-
'response': sut.session.get(sut.rhost + '/redfish/v1/openapi.yaml',
80-
headers={'accept': 'application/yaml'})}
78+
'response': sut.get('/redfish/v1/openapi.yaml',
79+
headers={'accept': 'application/yaml'})}
8180

8281
# do HEAD on the service root
83-
r = sut.session.head(sut.rhost + uri)
82+
r = sut.head(uri)
8483
yield {'uri': uri, 'response': r}
8584
# do GET on the service root
86-
r = sut.session.get(sut.rhost + uri)
85+
r = sut.get(uri)
8786
yield {'uri': uri, 'response': r}
8887
root = utils.get_response_json(r) if r.status_code == requests.codes.OK else {}
8988

@@ -93,29 +92,30 @@ def get_default_resources(sut: SystemUnderTest, uri='/redfish/v1/',
9392
sut.set_supported_query_params(root.get('ProtocolFeaturesSupported', {}))
9493

9594
for prop in ['Systems', 'Chassis']:
96-
if prop in root:
97-
uri = root[prop]['@odata.id']
95+
uri = root.get(prop, {}).get('@odata.id')
96+
if uri:
9897
sut.set_nav_prop_uri(prop, uri)
99-
r = sut.session.get(sut.rhost + uri)
98+
r = sut.get(uri)
10099
yield {'uri': uri, 'response': r}
101100
if r.ok:
102101
data = utils.get_response_json(r)
103102
if 'Members' in data and len(data['Members']):
104-
uri = data['Members'][0]['@odata.id']
105-
r = sut.session.get(sut.rhost + uri)
106-
yield {'uri': uri, 'response': r}
103+
uri = data['Members'][0].get('@odata.id')
104+
if uri:
105+
r = sut.get(uri)
106+
yield {'uri': uri, 'response': r}
107107

108-
if 'Managers' in root:
109-
uri = root['Managers']['@odata.id']
108+
uri = root.get('Managers', {}).get('@odata.id')
109+
if uri:
110110
sut.set_nav_prop_uri('Managers', uri)
111-
r = sut.session.get(sut.rhost + uri)
111+
r = sut.get(uri)
112112
yield {'uri': uri, 'response': r}
113113
if r.ok:
114114
data = utils.get_response_json(r)
115-
if 'Members' in data and len(data['Members']):
116-
for m in data['Members']:
117-
uri = m['@odata.id']
118-
r = sut.session.get(sut.rhost + uri)
115+
for m in data.get('Members', []):
116+
uri = m.get('@odata.id')
117+
if uri:
118+
r = sut.get(uri)
119119
yield {'uri': uri, 'response': r}
120120
if r.ok:
121121
d = utils.get_response_json(r)
@@ -124,31 +124,31 @@ def get_default_resources(sut: SystemUnderTest, uri='/redfish/v1/',
124124
for c in find_certificates(sut, d):
125125
yield c
126126

127-
if 'AccountService' in root:
128-
uri = root['AccountService']['@odata.id']
127+
uri = root.get('AccountService', {}).get('@odata.id')
128+
if uri:
129129
sut.set_nav_prop_uri('AccountService', uri)
130-
r = sut.session.get(sut.rhost + uri)
130+
r = sut.get(uri)
131131
yield {'uri': uri, 'response': r}
132132
if r.ok:
133133
data = utils.get_response_json(r)
134-
if 'PrivilegeMap' in data:
135-
uri = data['PrivilegeMap']['@odata.id']
134+
uri = data.get('PrivilegeMap', {}).get('@odata.id')
135+
if uri:
136136
sut.set_nav_prop_uri('PrivilegeMap', uri)
137137
for prop in ['Accounts', 'Roles']:
138-
if prop in data:
139-
uri = data[prop]['@odata.id']
140-
r = sut.session.get(sut.rhost + uri)
138+
uri = data.get(prop, {}).get('@odata.id')
139+
if uri:
140+
r = sut.get(uri)
141141
yield {'uri': uri, 'response': r}
142142
sut.set_nav_prop_uri(prop, uri)
143143
if r.ok:
144144
d = utils.get_response_json(r)
145-
if 'Members' in d and len(d['Members']):
146-
if prop == 'Accounts':
147-
resource_type = ResourceType.MANAGER_ACCOUNT
148-
# get accounts up to sut.username
149-
for m in d['Members']:
150-
uri = m['@odata.id']
151-
r = sut.session.get(sut.rhost + uri)
145+
if prop == 'Accounts':
146+
resource_type = ResourceType.MANAGER_ACCOUNT
147+
# get accounts up to sut.username
148+
for m in d.get('Members', []):
149+
uri = m.get('@odata.id')
150+
if uri:
151+
r = sut.get(uri)
152152
yield {'uri': uri, 'response': r,
153153
'resource_type': resource_type}
154154
if r.ok:
@@ -157,46 +157,48 @@ def get_default_resources(sut: SystemUnderTest, uri='/redfish/v1/',
157157
== sut.username):
158158
break
159159

160-
else:
161-
resource_type = ResourceType.ROLE
162-
# get all the roles
163-
for m in d['Members']:
164-
uri = m['@odata.id']
165-
r = sut.session.get(sut.rhost + uri)
160+
else:
161+
resource_type = ResourceType.ROLE
162+
# get all the roles
163+
for m in d.get('Members', []):
164+
uri = m.get('@odata.id')
165+
if uri:
166+
r = sut.get(uri)
166167
yield {'uri': uri, 'response': r,
167168
'resource_type': resource_type}
168169
if r.ok:
169170
sut.add_role(utils.get_response_json(r))
170171

171-
if 'SessionService' in root:
172-
uri = root['SessionService']['@odata.id']
173-
r = sut.session.get(sut.rhost + uri)
172+
uri = root.get('SessionService', {}).get('@odata.id')
173+
if uri:
174+
r = sut.get(uri)
174175
yield {'uri': uri, 'response': r}
175176
if r.ok:
176177
data = utils.get_response_json(r)
177-
if 'Sessions' in data:
178-
uri = data['Sessions']['@odata.id']
179-
r = sut.session.get(sut.rhost + uri)
178+
uri = data.get('Sessions', {}).get('@odata.id')
179+
if uri:
180+
r = sut.get(uri)
180181
yield {'uri': uri, 'response': r}
181182
if r.ok:
182183
data = utils.get_response_json(r)
183184
if 'Members' in data and len(data['Members']):
184-
uri = data['Members'][0]['@odata.id']
185-
r = sut.session.get(sut.rhost + uri)
186-
yield {'uri': uri, 'response': r}
185+
uri = data['Members'][0].get('@odata.id')
186+
if uri:
187+
r = sut.get(uri)
188+
yield {'uri': uri, 'response': r}
187189

188-
if 'EventService' in root:
189-
uri = root['EventService']['@odata.id']
190+
uri = root.get('EventService', {}).get('@odata.id')
191+
if uri:
190192
sut.set_nav_prop_uri('EventService', uri)
191-
r = sut.session.get(sut.rhost + uri)
193+
r = sut.get(uri)
192194
yield {'uri': uri, 'response': r}
193195
if r.ok:
194196
data = utils.get_response_json(r)
195-
if 'Subscriptions' in data:
196-
sut.set_nav_prop_uri(
197-
'Subscriptions', data['Subscriptions']['@odata.id'])
198-
if 'ServerSentEventUri' in data:
199-
uri = data['ServerSentEventUri']
197+
uri = data.get('Subscriptions', {}).get('@odata.id')
198+
if uri:
199+
sut.set_nav_prop_uri('Subscriptions', uri)
200+
uri = data.get('ServerSentEventUri')
201+
if uri:
200202
sut.set_server_sent_event_uri(uri)
201203
r, event_dest_uri = utils.get_sse_stream(sut)
202204
if event_dest_uri:
@@ -205,10 +207,10 @@ def get_default_resources(sut: SystemUnderTest, uri='/redfish/v1/',
205207
yield {'uri': uri, 'response': r,
206208
'request_type': RequestType.STREAMING}
207209

208-
if 'CertificateService' in root:
209-
uri = root['CertificateService']['@odata.id']
210+
uri = root.get('CertificateService', {}).get('@odata.id')
211+
if uri:
210212
sut.set_nav_prop_uri('CertificateService', uri)
211-
r = sut.session.get(sut.rhost + uri)
213+
r = sut.get(uri)
212214
yield {'uri': uri, 'response': r}
213215

214216

@@ -286,7 +288,7 @@ def data_modification_requests(sut: SystemUnderTest):
286288
new_user, new_pwd, new_uri = create_account(
287289
sut, sut.session, request_type=RequestType.NORMAL)
288290
if new_uri:
289-
response = sut.session.get(sut.rhost + new_uri)
291+
response = sut.get(new_uri)
290292
sut.add_response(new_uri, response)
291293
if response.ok:
292294
etag = utils.get_response_etag(response)
@@ -344,7 +346,7 @@ def unsupported_requests(sut: SystemUnderTest):
344346
response = sut.post(uri, json={})
345347
sut.add_response(uri, response, request_type=RequestType.UNSUPPORTED_REQ)
346348
# Unsupported HTTP methods return HTTP 501
347-
response = sut.session.request('FAKEMETHODFORTEST', sut.rhost + uri)
349+
response = sut.request('FAKEMETHODFORTEST', uri)
348350
sut.add_response(uri, response, request_type=RequestType.UNSUPPORTED_REQ)
349351

350352

@@ -354,9 +356,8 @@ def basic_auth_requests(sut: SystemUnderTest):
354356
}
355357
uri = sut.sessions_uri
356358
# good request
357-
r = requests.get(sut.rhost + uri, headers=headers,
358-
auth=(sut.username, sut.password),
359-
verify=sut.verify)
359+
r = sut.get(uri, headers=headers, auth=(sut.username, sut.password),
360+
no_session=True)
360361
sut.add_response(uri, r, request_type=RequestType.BASIC_AUTH)
361362

362363

@@ -435,21 +436,20 @@ def bad_auth_requests(sut: SystemUnderTest):
435436
# IP will be blocked for 600 seconds."
436437
uri = sut.sessions_uri
437438
h = headers.copy()
438-
r = requests.get(sut.rhost + uri, headers=h,
439-
auth=(acct.new_username(set()), acct.new_password(sut)),
440-
verify=sut.verify)
439+
r = sut.get(uri, headers=h, auth=(acct.new_username(set()), acct.new_password(sut)),
440+
no_session=True)
441441
sut.add_response(uri, r, request_type=RequestType.BAD_AUTH)
442442
# request with bad auth token
443443
token = 'rfpv%012x' % random.randrange(2 ** 48) # ex: 'rfpv9e40b1f54c8a'
444444
sut.add_priv_info(token)
445445
uri = '/redfish/v1/RPVfoobar'
446446
h = headers.copy()
447447
h.update({'X-Auth-Token': token})
448-
r = requests.get(sut.rhost + uri, headers=h, verify=sut.verify)
448+
r = sut.get(uri, headers=h, no_session=True)
449449
sut.add_response(uri, r, request_type=RequestType.BAD_AUTH)
450450

451451

452452
def read_uris_no_auth(sut: SystemUnderTest, session):
453453
for uri in sut.get_all_uris():
454-
response = session.get(sut.rhost + uri)
454+
response = sut.get(uri, session=session)
455455
sut.add_response(uri, response, request_type=RequestType.NO_AUTH)

0 commit comments

Comments
 (0)