pytest-nhsd-apim 3.3.15__py3-none-any.whl → 3.4.0__py3-none-any.whl
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.
Potentially problematic release.
This version of pytest-nhsd-apim might be problematic. Click here for more details.
- pytest_nhsd_apim/apigee_apis.py +211 -4
- pytest_nhsd_apim/apigee_edge.py +11 -0
- pytest_nhsd_apim/pytest_nhsd_apim.py +2 -1
- {pytest_nhsd_apim-3.3.15.dist-info → pytest_nhsd_apim-3.4.0.dist-info}/METADATA +2 -1
- pytest_nhsd_apim-3.4.0.dist-info/RECORD +16 -0
- pytest_nhsd_apim-3.3.15.dist-info/RECORD +0 -16
- {pytest_nhsd_apim-3.3.15.dist-info → pytest_nhsd_apim-3.4.0.dist-info}/WHEEL +0 -0
- {pytest_nhsd_apim-3.3.15.dist-info → pytest_nhsd_apim-3.4.0.dist-info}/entry_points.txt +0 -0
- {pytest_nhsd_apim-3.3.15.dist-info → pytest_nhsd_apim-3.4.0.dist-info}/top_level.txt +0 -0
pytest_nhsd_apim/apigee_apis.py
CHANGED
|
@@ -476,7 +476,7 @@ class DeveloperAppsAPI:
|
|
|
476
476
|
resp = self.client.delete(url=url)
|
|
477
477
|
if resp.status_code != 200:
|
|
478
478
|
raise Exception(
|
|
479
|
-
f"
|
|
479
|
+
f"DELETE request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
480
480
|
)
|
|
481
481
|
return resp.json()
|
|
482
482
|
|
|
@@ -1241,11 +1241,218 @@ class UserRolesAPI:
|
|
|
1241
1241
|
|
|
1242
1242
|
|
|
1243
1243
|
class AppKeysAPI:
|
|
1244
|
+
"""
|
|
1245
|
+
Manage consumer credentials for apps associated with individual developers.
|
|
1246
|
+
|
|
1247
|
+
Credential pairs consisting of consumer key and consumer secret are provisioned
|
|
1248
|
+
by Apigee Edge to apps for specific API products. Apigee Edge maintains the
|
|
1249
|
+
relationship between consumer keys and API products, enabling API products to be
|
|
1250
|
+
added to and removed from consumer keys. A single consumer key can be used to
|
|
1251
|
+
access multiple API products. Keys may be manually or automatically approved for
|
|
1252
|
+
API products--how they are issued depends on the API product configuration. A key
|
|
1253
|
+
must approved and approved for an API product to be capable of accessing any of
|
|
1254
|
+
the URIs defined in the API product.
|
|
1255
|
+
"""
|
|
1256
|
+
|
|
1244
1257
|
def __init__(self, client: RestClient) -> None:
|
|
1245
1258
|
self.client = client
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1259
|
+
|
|
1260
|
+
def create_app_key(self, email: str, app_name: str, body: dict) -> "dict":
|
|
1261
|
+
"""
|
|
1262
|
+
Creates a custom consumer key and secret for a developer app.
|
|
1263
|
+
This is particularly useful if you want to migrate existing consumer
|
|
1264
|
+
keys/secrets to Edge from another system.
|
|
1265
|
+
|
|
1266
|
+
After creating the consumer key and secret, associate the key with an
|
|
1267
|
+
API product, as described in Add API Product to Key.
|
|
1268
|
+
|
|
1269
|
+
Consumer keys and secrets can contain letters, numbers, underscores,
|
|
1270
|
+
and hyphens. No other special characters are allowed.
|
|
1271
|
+
|
|
1272
|
+
Note: Be aware of the following size limits on API keys. By staying
|
|
1273
|
+
within these limits, you help avoid service disruptions.
|
|
1274
|
+
|
|
1275
|
+
- Consumer key (API key) size: 2 KB
|
|
1276
|
+
|
|
1277
|
+
- Consumer secret size: 2 KB
|
|
1278
|
+
|
|
1279
|
+
If a consumer key and secret already exist, you can either keep them
|
|
1280
|
+
or delete them, as described in Delete Key for a Developer App.
|
|
1281
|
+
|
|
1282
|
+
In addition, you can use this API if you have existing API keys and
|
|
1283
|
+
secrets that you want to copy into Edge from another system. For more
|
|
1284
|
+
information, see Import existing consumer keys and secrets.
|
|
1285
|
+
"""
|
|
1286
|
+
|
|
1287
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/create"
|
|
1288
|
+
url = f"{self.client.base_url}{resource}"
|
|
1289
|
+
resp = self.client.post(url=url, json=body)
|
|
1290
|
+
if resp.status_code != 201:
|
|
1291
|
+
raise Exception(
|
|
1292
|
+
f"POST request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1293
|
+
)
|
|
1294
|
+
return resp.json()
|
|
1295
|
+
|
|
1296
|
+
def delete_app_key(self, email: str, app_name: str, app_key: str) -> None:
|
|
1297
|
+
"""
|
|
1298
|
+
Deletes a consumer key that belongs to an app, and removes all API products
|
|
1299
|
+
associated with the app. Once deleted, the consumer key cannot be used
|
|
1300
|
+
to access any APIs.
|
|
1301
|
+
|
|
1302
|
+
After you delete a consumer key, you may want to:
|
|
1303
|
+
|
|
1304
|
+
- Create a new consumer key and secret for the developer app, and
|
|
1305
|
+
subsequently add an API product to the key.
|
|
1306
|
+
|
|
1307
|
+
- Delete the developer app, if it is no longer required.
|
|
1308
|
+
"""
|
|
1309
|
+
|
|
1310
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{app_key}"
|
|
1311
|
+
url = f"{self.client.base_url}{resource}"
|
|
1312
|
+
resp = self.client.delete(url=url)
|
|
1313
|
+
if resp.status_code != 200:
|
|
1314
|
+
raise Exception(
|
|
1315
|
+
f"DELETE request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1316
|
+
)
|
|
1317
|
+
return resp.json()
|
|
1318
|
+
|
|
1319
|
+
def get_app_key(self, email: str, app_name: str, key: str, **query_params) -> "list[str]":
|
|
1320
|
+
"""
|
|
1321
|
+
Gets details for a consumer key for a developer app, including the key
|
|
1322
|
+
and secret value, associated API products, and other information.
|
|
1323
|
+
"""
|
|
1324
|
+
|
|
1325
|
+
params = query_params
|
|
1326
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{key}"
|
|
1327
|
+
url = f"{self.client.base_url}{resource}"
|
|
1328
|
+
resp = self.client.get(url=url, params=params)
|
|
1329
|
+
if resp.status_code != 200:
|
|
1330
|
+
raise Exception(
|
|
1331
|
+
f"GET request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1332
|
+
)
|
|
1333
|
+
return resp.json()
|
|
1334
|
+
|
|
1335
|
+
def post_app_key(self, email: str, app_name: str, key: str, body: dict, **query_params) -> "dict":
|
|
1336
|
+
"""
|
|
1337
|
+
Enables you to perform one of the following tasks:
|
|
1338
|
+
|
|
1339
|
+
- Add an API product to a developer app key, enabling the app that holds
|
|
1340
|
+
the key to access the API resources bundled in the API product. You can
|
|
1341
|
+
also use this API to add attributes to the key. You must include all existing
|
|
1342
|
+
attributes, whether or not you are updating them, as well as any new attributes
|
|
1343
|
+
that you are adding. After adding the API product, you can use the same key
|
|
1344
|
+
to access all API products associated with the app.
|
|
1345
|
+
|
|
1346
|
+
- Approve or revoke a specific consumer key for an app. Call the API with the
|
|
1347
|
+
action query parameter set to approve or revoke (with no request body) and
|
|
1348
|
+
set the Content-type header to application/octet-stream. If successful, the HTTP
|
|
1349
|
+
status code for success is: 204 No Content
|
|
1350
|
+
|
|
1351
|
+
- You can approve a consumer key that is currently revoked or pending. Once
|
|
1352
|
+
approved, the app can use the consumer key to access APIs. Revoking a consumer
|
|
1353
|
+
key renders it unusable for the app to use to access an API.
|
|
1354
|
+
|
|
1355
|
+
- Note: Any access tokens associated with a revoked app key will remain active.
|
|
1356
|
+
However, Apigee Edge checks the status of the app key and if set to revoked it
|
|
1357
|
+
will not allow API calls to go through.
|
|
1358
|
+
"""
|
|
1359
|
+
|
|
1360
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{key}"
|
|
1361
|
+
url = f"{self.client.base_url}{resource}"
|
|
1362
|
+
resp = self.client.post(url=url, json=body, params=query_params)
|
|
1363
|
+
if resp.status_code != 200 and resp.status_code != 204:
|
|
1364
|
+
raise Exception(
|
|
1365
|
+
f"POST request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1366
|
+
)
|
|
1367
|
+
if resp.status_code == 204:
|
|
1368
|
+
return resp
|
|
1369
|
+
else:
|
|
1370
|
+
return resp.json()
|
|
1371
|
+
|
|
1372
|
+
def put_app_key(self, email: str, app_name: str, key: str, body: dict) -> "dict":
|
|
1373
|
+
"""
|
|
1374
|
+
Updates the allowed OAuth scopes associated with an app.
|
|
1375
|
+
|
|
1376
|
+
Note: Specify the complete list of scopes to apply. The specified list replaces
|
|
1377
|
+
the existing scopes on the app. Therefore, to add a scope, you must specify all
|
|
1378
|
+
of the existing scopes along with the added scope.
|
|
1379
|
+
|
|
1380
|
+
This API does not change the list of scopes in the API product(s) included in
|
|
1381
|
+
the app; rather, it sets allowed list of scopes in the scopes element under the
|
|
1382
|
+
apiProducts element in the attributes of the app.
|
|
1383
|
+
|
|
1384
|
+
Important: The specified scopes must already exist on the API product(s)
|
|
1385
|
+
associated with the app. You can't arbitrarily add a scope that does not already
|
|
1386
|
+
exist in an API product. For example, if the app has one API product with these
|
|
1387
|
+
scopes: READ, WRITE. You can't use this API to add a new scope, such as DELETE
|
|
1388
|
+
(unless the app has another product with that scope). If you do this, you'll get
|
|
1389
|
+
a 400 Bad Request error. For example:
|
|
1390
|
+
|
|
1391
|
+
{
|
|
1392
|
+
"code": "keymanagement.service.InvalidScopes",
|
|
1393
|
+
"message": "Invalid scopes. Scopes must be contained in [READ, WRITE]",
|
|
1394
|
+
"contexts": []
|
|
1395
|
+
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
It would be allowed to remove one or both of the existing scopes, and later add
|
|
1399
|
+
one or both back.
|
|
1400
|
+
"""
|
|
1401
|
+
|
|
1402
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{key}"
|
|
1403
|
+
url = f"{self.client.base_url}{resource}"
|
|
1404
|
+
resp = self.client.put(url=url, json=body)
|
|
1405
|
+
if resp.status_code != 200:
|
|
1406
|
+
raise Exception(
|
|
1407
|
+
f"PUT request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1408
|
+
)
|
|
1409
|
+
return resp.json()
|
|
1410
|
+
|
|
1411
|
+
def delete_product_app_key_association(self, email: str, app_name: str, app_key: str, apiproduct_name: str) -> None:
|
|
1412
|
+
"""
|
|
1413
|
+
Removes an API product from an app's consumer key, and thereby renders the app
|
|
1414
|
+
unable to access the API resources defined in that API product.
|
|
1415
|
+
|
|
1416
|
+
Note that the consumer key itself still exists after this call. Only the
|
|
1417
|
+
association of the key with the API product is removed.
|
|
1418
|
+
"""
|
|
1419
|
+
|
|
1420
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{app_key}/apiproducts/{apiproduct_name}"
|
|
1421
|
+
url = f"{self.client.base_url}{resource}"
|
|
1422
|
+
resp = self.client.delete(url=url)
|
|
1423
|
+
if resp.status_code != 200:
|
|
1424
|
+
raise Exception(
|
|
1425
|
+
f"DELETE request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1426
|
+
)
|
|
1427
|
+
return resp.json()
|
|
1428
|
+
|
|
1429
|
+
def post_product_app_key_association(self, email: str, app_name: str, key: str, apiproduct_name: str, **query_params) -> "dict":
|
|
1430
|
+
"""
|
|
1431
|
+
Approves or revokes an API product for an API key. Call the API with the action
|
|
1432
|
+
query parameter set to approve or revoke (with no request body) and set the
|
|
1433
|
+
Content-type header to application/octet-stream. If successful, the HTTP status
|
|
1434
|
+
code for success is: 204 No Content
|
|
1435
|
+
|
|
1436
|
+
To consume API resources defined in an API product, an app's consumer key must
|
|
1437
|
+
be approved and it must also be approved for that specific API product.
|
|
1438
|
+
|
|
1439
|
+
Notes:
|
|
1440
|
+
|
|
1441
|
+
- The API product must already be associated with the app.
|
|
1442
|
+
|
|
1443
|
+
- Any access tokens associated with a revoked app key will remain active. However,
|
|
1444
|
+
Apigee Edge checks the status of the app key and if set to revoked it will not
|
|
1445
|
+
allow API calls to go through.
|
|
1446
|
+
"""
|
|
1447
|
+
|
|
1448
|
+
resource = f"/developers/{email}/apps/{app_name}/keys/{key}/apiproducts/{apiproduct_name}"
|
|
1449
|
+
url = f"{self.client.base_url}{resource}"
|
|
1450
|
+
resp = self.client.post(url=url, params=query_params)
|
|
1451
|
+
if resp.status_code != 204:
|
|
1452
|
+
raise Exception(
|
|
1453
|
+
f"POST request to {resp.url} failed with status_code: {resp.status_code}, Reason: {resp.reason} and Content: {resp.text}"
|
|
1454
|
+
)
|
|
1455
|
+
return resp
|
|
1249
1456
|
|
|
1250
1457
|
|
|
1251
1458
|
class UsersAPI:
|
pytest_nhsd_apim/apigee_edge.py
CHANGED
|
@@ -18,6 +18,7 @@ from .log import log, log_method
|
|
|
18
18
|
from .apigee_apis import (
|
|
19
19
|
ApigeeNonProdCredentials,
|
|
20
20
|
ApigeeClient,
|
|
21
|
+
AppKeysAPI,
|
|
21
22
|
DebugSessionsAPI,
|
|
22
23
|
AccessTokensAPI,
|
|
23
24
|
ApiProductsAPI,
|
|
@@ -583,3 +584,13 @@ def developer_apps_api():
|
|
|
583
584
|
config = ApigeeNonProdCredentials()
|
|
584
585
|
client = ApigeeClient(config=config)
|
|
585
586
|
return DeveloperAppsAPI(client=client)
|
|
587
|
+
|
|
588
|
+
@pytest.fixture(scope="session")
|
|
589
|
+
@log_method
|
|
590
|
+
def developer_app_keys_api():
|
|
591
|
+
"""
|
|
592
|
+
Authenitcated wrapper for Apigee's developer app keys API
|
|
593
|
+
"""
|
|
594
|
+
config = ApigeeNonProdCredentials()
|
|
595
|
+
client = ApigeeClient(config=config)
|
|
596
|
+
return AppKeysAPI(client=client)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pytest-nhsd-apim
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Pytest plugin accessing NHSDigital's APIM proxies
|
|
5
5
|
Home-page: https://github.com/NHSDigital/pytest-nhsd-apim
|
|
6
6
|
Author: Adrian Ciobanita
|
|
@@ -99,6 +99,7 @@ The APIs we offer at the moment are:
|
|
|
99
99
|
| ApiProductsAPI | [here](/src/pytest_nhsd_apim/apigee_apis.py#L575) |[Overview](https://apidocs.apigee.com/docs/api-products/1/overview)|
|
|
100
100
|
| DebugSessionsAPI | [here](/src/pytest_nhsd_apim/apigee_apis.py#L844) |[Overview](https://apidocs.apigee.com/docs/debug-sessions/1/overview)|
|
|
101
101
|
| AccessTokensAPI | [here](/src/pytest_nhsd_apim/apigee_apis.py#L983) |[Overview](https://apidocs.apigee.com/docs/oauth-20-access-tokens/1/overview)|
|
|
102
|
+
| AppKeysAPI | [here](/src/pytest_nhsd_apim/apigee_apis.py#L1243) |[Overview](https://apidocs.apigee.com/docs/developer-app-keys/1/overview)|
|
|
102
103
|
|
|
103
104
|
For a more detailed implementation of the available APIs please refer to the tests [here](/tests/test_apigee_apis.py).
|
|
104
105
|
We will keep adding APIs with time, if you are looking for a particular APIs not listed above please feel free to open a pull request and send it to us.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
pytest_nhsd_apim/__init__.py,sha256=CRwQfUDrbXIqvJX6OfTR4jGdhlU9kjGmBAptJasRg7E,72
|
|
2
|
+
pytest_nhsd_apim/apigee_apis.py,sha256=tcAo254Mvx__qAX7Focb-6855eTLWL2TUsna1vT6Eow,67284
|
|
3
|
+
pytest_nhsd_apim/apigee_edge.py,sha256=NQrW8PeA_-X4zt2torTmBOaFIzRKjh6pT1ksolNjpmA,19065
|
|
4
|
+
pytest_nhsd_apim/auth_journey.py,sha256=UovbLXhokUnikrMOaXIhjV8t5aRrcxinAbS96nfZWcY,5154
|
|
5
|
+
pytest_nhsd_apim/config.py,sha256=ScKfV8iURqDXX2ajgGsRDcVn9RZy2DxLoEU2QQt9lmA,4246
|
|
6
|
+
pytest_nhsd_apim/identity_service.py,sha256=HrXfSm0dIFg51LBng_nf2iIGlOcwzV_J1vA4agm_Ne4,19766
|
|
7
|
+
pytest_nhsd_apim/log.py,sha256=8gYHqzlQM546FB2XvFmLTk1YfZRNeNhIwLmOy0GScr8,2685
|
|
8
|
+
pytest_nhsd_apim/nhsd_apim_authorization.py,sha256=TE_6YnoM7kpRReiZP6-Z52rRs9bUuax1mpXqkbzg8zQ,3505
|
|
9
|
+
pytest_nhsd_apim/pytest_nhsd_apim.py,sha256=ZCItUqcM23CCmcRyGU8bEwI3vJnNcGdoOlbSfvYILR8,5242
|
|
10
|
+
pytest_nhsd_apim/secrets.py,sha256=yIYwOZwpliIomtqSJGIYRbAE2HYvLvQU4W2kOa9TnXo,2354
|
|
11
|
+
pytest_nhsd_apim/token_cache.py,sha256=6L08taTlSyRsx2NCb0LSGsHdWx_wmqwlFtcF7pZMhUg,3540
|
|
12
|
+
pytest_nhsd_apim-3.4.0.dist-info/METADATA,sha256=rjU6W_oeYnoU9RZz-l07XiP6LF1l0LQ_yt1_s-UiWms,4661
|
|
13
|
+
pytest_nhsd_apim-3.4.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
14
|
+
pytest_nhsd_apim-3.4.0.dist-info/entry_points.txt,sha256=XWicT3meTpqLXnZcXNoAd2IfXspFPlNgMgLBMy4nqwQ,57
|
|
15
|
+
pytest_nhsd_apim-3.4.0.dist-info/top_level.txt,sha256=ZK5GZP-g_K8gNfm4a58T9JCRb0i1X267ngvNelCGgfQ,17
|
|
16
|
+
pytest_nhsd_apim-3.4.0.dist-info/RECORD,,
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
pytest_nhsd_apim/__init__.py,sha256=CRwQfUDrbXIqvJX6OfTR4jGdhlU9kjGmBAptJasRg7E,72
|
|
2
|
-
pytest_nhsd_apim/apigee_apis.py,sha256=nVarxYSD1TIjCduBQyW8LIODyPk76xpELXD2lhyWLHc,57427
|
|
3
|
-
pytest_nhsd_apim/apigee_edge.py,sha256=sIITiwkyKoNVDJ9OmnxV3mipF6LJR0w2qpmvT5Mwr1M,18777
|
|
4
|
-
pytest_nhsd_apim/auth_journey.py,sha256=UovbLXhokUnikrMOaXIhjV8t5aRrcxinAbS96nfZWcY,5154
|
|
5
|
-
pytest_nhsd_apim/config.py,sha256=ScKfV8iURqDXX2ajgGsRDcVn9RZy2DxLoEU2QQt9lmA,4246
|
|
6
|
-
pytest_nhsd_apim/identity_service.py,sha256=HrXfSm0dIFg51LBng_nf2iIGlOcwzV_J1vA4agm_Ne4,19766
|
|
7
|
-
pytest_nhsd_apim/log.py,sha256=8gYHqzlQM546FB2XvFmLTk1YfZRNeNhIwLmOy0GScr8,2685
|
|
8
|
-
pytest_nhsd_apim/nhsd_apim_authorization.py,sha256=TE_6YnoM7kpRReiZP6-Z52rRs9bUuax1mpXqkbzg8zQ,3505
|
|
9
|
-
pytest_nhsd_apim/pytest_nhsd_apim.py,sha256=_snJGTUVsHA70FGrKNNXjx9yNc_UjO1Ffhw0SLQtYUs,5214
|
|
10
|
-
pytest_nhsd_apim/secrets.py,sha256=yIYwOZwpliIomtqSJGIYRbAE2HYvLvQU4W2kOa9TnXo,2354
|
|
11
|
-
pytest_nhsd_apim/token_cache.py,sha256=6L08taTlSyRsx2NCb0LSGsHdWx_wmqwlFtcF7pZMhUg,3540
|
|
12
|
-
pytest_nhsd_apim-3.3.15.dist-info/METADATA,sha256=y8LIwibo_Ulh9ouBI3RFahR7U7k1xIHnd9h7v_DvDI8,4518
|
|
13
|
-
pytest_nhsd_apim-3.3.15.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
14
|
-
pytest_nhsd_apim-3.3.15.dist-info/entry_points.txt,sha256=XWicT3meTpqLXnZcXNoAd2IfXspFPlNgMgLBMy4nqwQ,57
|
|
15
|
-
pytest_nhsd_apim-3.3.15.dist-info/top_level.txt,sha256=ZK5GZP-g_K8gNfm4a58T9JCRb0i1X267ngvNelCGgfQ,17
|
|
16
|
-
pytest_nhsd_apim-3.3.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|