Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,4 @@ typescript
!.gitattributes
!.gitignore
!.gitkeep
.envrc
9 changes: 7 additions & 2 deletions src/pds/ingress/authorizer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ exports.handler = async(event, _context, callback) => {
return;
}

if (groups.includes(request_group)) {
// The UserGroup header may contain multiple comma-separated group names (e.g. for SBN which
// has two orgs). Authorize if the user belongs to ANY of the permitted groups for the node.
let permitted_groups = request_group.split(',').map(g => g.trim());
let authorized = permitted_groups.some(g => groups.includes(g));

if (authorized) {
console.log("VALID TOKEN, ALLOW!!");
callback(null, generatePolicy('user', 'Allow', event.methodArn));
} else {
console.log(`Invalid request group. User belongs to: [${groups}], but requested: ${request_group}`);
console.log(`Invalid request group. User belongs to: [${groups}], but requested: [${permitted_groups}]`);
callback("Unauthorized");
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/pds/ingress/client/pds_ingress_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ def request_batch_for_ingress(request_batch, batch_index, node_id, force_overwri
params = {"node": node_id, "node_name": NodeUtil.node_id_to_long_name[node_id]}
headers = {
"Authorization": BEARER_TOKEN,
"UserGroup": NodeUtil.node_id_to_group_name(node_id),
"UserGroup": ",".join(NodeUtil.node_id_to_group_names(node_id)),
"ForceOverwrite": str(int(force_overwrite)),
"ClientVersion": __version__,
"content-type": "application/json",
Expand Down
4 changes: 2 additions & 2 deletions src/pds/ingress/client/pds_status_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def main(args):
params = {"node": args.node, "node_name": NodeUtil.node_id_to_long_name[args.node]}
headers = {
"Authorization": bearer_token,
"UserGroup": NodeUtil.node_id_to_group_name(args.node),
"UserGroup": ",".join(NodeUtil.node_id_to_group_names(args.node)),
"ForceOverwrite": "1", # Likely we'll repeat requests using same manifest file names, so always overwrite
"ClientVersion": __version__,
"content-type": "application/json",
Expand Down Expand Up @@ -184,7 +184,7 @@ def main(args):

headers = {
"Authorization": bearer_token,
"UserGroup": NodeUtil.node_id_to_group_name(args.node),
"UserGroup": ",".join(NodeUtil.node_id_to_group_names(args.node)),
"ClientVersion": __version__,
"content-type": "application/json",
"x-amz-docs-region": api_gateway_region,
Expand Down
4 changes: 2 additions & 2 deletions src/pds/ingress/util/log_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ def send_log_events_to_cloud_watch(self, log_events):

headers = {
"Authorization": self.bearer_token,
"UserGroup": NodeUtil.node_id_to_group_name(self.node_id),
"UserGroup": ",".join(NodeUtil.node_id_to_group_names(self.node_id)),
"content-type": "application/json",
"x-amz-docs-region": api_gateway_region,
}
Expand All @@ -522,7 +522,7 @@ def send_log_events_to_cloud_watch(self, log_events):
payload["logEvents"] = log_events
headers = {
"Authorization": self.bearer_token,
"UserGroup": NodeUtil.node_id_to_group_name(self.node_id),
"UserGroup": ",".join(NodeUtil.node_id_to_group_names(self.node_id)),
"content-type": "application/json",
"x-amz-docs-region": api_gateway_region,
}
Expand Down
21 changes: 17 additions & 4 deletions src/pds/ingress/util/node_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,28 @@ class NodeUtil:
"sbn": "Small Bodies",
}

node_id_to_cognito_groups = {
"atm": ["PDS_ATM_USERS"],
"eng": ["PDS_ENG_USERS"],
"geo": ["PDS_GEO_USERS"],
"img": ["PDS_IMG_USERS"],
"naif": ["PDS_NAIF_USERS"],
"ppi": ["PDS_PPI_USERS"],
"rs": ["PDS_RS_USERS"],
"rms": ["PDS_RMS_USERS"],
"sbn": ["PDS_SBN_USERS", "PDS_SBNUMD_USERS"],
}

@classmethod
def permissible_node_ids(cls):
"""Returns a list of the Node IDs accepted by the Ingress client"""
return cls.node_id_to_long_name.keys()

@classmethod
def node_id_to_group_name(cls, node_id):
"""Returns the Cognito group name for the given node ID"""
if node_id.lower() not in cls.node_id_to_long_name.keys():
def node_id_to_group_names(cls, node_id):
"""Returns all Cognito group names permitted for the given node ID"""
if node_id.lower() not in cls.node_id_to_cognito_groups:
raise ValueError(f'Unknown node ID "{node_id}"')

return f"PDS_{node_id.upper()}_USERS"
return cls.node_id_to_cognito_groups[node_id.lower()]

2 changes: 1 addition & 1 deletion tests/pds/ingress/util/test_log_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def requests_post_patch(url, data=None, json=None, **kwargs):
self.assertIn("Authorization", headers)
self.assertIn("UserGroup", headers)
self.assertEqual(headers["Authorization"], "Bearer faketoken")
self.assertEqual(headers["UserGroup"], NodeUtil.node_id_to_group_name("eng"))
self.assertEqual(headers["UserGroup"], ",".join(NodeUtil.node_id_to_group_names("eng")))

response = requests.Response()
response.status_code = HTTPStatus.OK
Expand Down
Loading