Skip to content

Commit

Permalink
General data validation on all IO boundaries including client and age…
Browse files Browse the repository at this point in the history
…nt service handlers and CLI bin parsers
  • Loading branch information
CMCDragonkai committed Feb 7, 2022
1 parent 0985f1d commit 134ad24
Show file tree
Hide file tree
Showing 107 changed files with 1,837 additions and 535 deletions.
10 changes: 6 additions & 4 deletions src/agent/service/nodesChainDataGet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ function nodesChainDataGet({ nodeManager }: { nodeManager: NodeManager }) {
call: grpc.ServerUnaryCall<utilsPB.EmptyMessage, nodesPB.ChainData>,
callback: grpc.sendUnaryData<nodesPB.ChainData>,
): Promise<void> => {
const response = new nodesPB.ChainData();
try {
const response = new nodesPB.ChainData();
const chainData = await nodeManager.getChainData();
// Iterate through each claim in the chain, and serialize for transport
for (const c in chainData) {
Expand All @@ -34,10 +34,12 @@ function nodesChainDataGet({ nodeManager }: { nodeManager: NodeManager }) {
// Add the serialized claim
response.getChainDataMap().set(claimId, claimMessage);
}
} catch (err) {
callback(grpcUtils.fromError(err), response);
callback(null, response);
return;
} catch (e) {
callback(grpcUtils.fromError(e));
return;
}
callback(null, response);
};
}

Expand Down
31 changes: 25 additions & 6 deletions src/agent/service/nodesClosestLocalNodesGet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type * as grpc from '@grpc/grpc-js';
import type { NodeManager } from '../../nodes';
import type { NodeId } from '../../nodes/types';
import { utils as grpcUtils } from '../../grpc';
import { utils as nodesUtils } from '../../nodes';
import { validateSync, utils as validationUtils } from '../../validation';
import { matchSync } from '../../utils';
import * as nodesPB from '../../proto/js/polykey/v1/nodes/nodes_pb';

/**
Expand All @@ -17,11 +20,25 @@ function nodesClosestLocalNodesGet({
call: grpc.ServerUnaryCall<nodesPB.Node, nodesPB.NodeTable>,
callback: grpc.sendUnaryData<nodesPB.NodeTable>,
): Promise<void> => {
const response = new nodesPB.NodeTable();
try {
const targetNodeId = nodesUtils.decodeNodeId(call.request.getNodeId());
const response = new nodesPB.NodeTable();
const {
nodeId,
}: {
nodeId: NodeId;
} = validateSync(
(keyPath, value) => {
return matchSync(keyPath)(
[['nodeId'], () => validationUtils.parseNodeId(value)],
() => value,
);
},
{
nodeId: call.request.getNodeId(),
},
);
// Get all local nodes that are closest to the target node from the request
const closestNodes = await nodeManager.getClosestLocalNodes(targetNodeId);
const closestNodes = await nodeManager.getClosestLocalNodes(nodeId);
for (const node of closestNodes) {
const addressMessage = new nodesPB.Address();
addressMessage.setHost(node.address.host);
Expand All @@ -31,10 +48,12 @@ function nodesClosestLocalNodesGet({
.getNodeTableMap()
.set(nodesUtils.encodeNodeId(node.id), addressMessage);
}
} catch (err) {
callback(grpcUtils.fromError(err), response);
callback(null, response);
return;
} catch (e) {
callback(grpcUtils.fromError(e));
return;
}
callback(null, response);
};
}

Expand Down
24 changes: 21 additions & 3 deletions src/agent/service/nodesCrossSignClaim.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type * as grpc from '@grpc/grpc-js';
import type { ClaimEncoded, ClaimIntermediary } from '../../claims/types';
import type { NodeManager } from '../../nodes';
import type { NodeId } from '../../nodes/types';
import type { Sigchain } from '../../sigchain';
import type { KeyManager } from '../../keys';
import type * as nodesPB from '../../proto/js/polykey/v1/nodes/nodes_pb';
import { utils as grpcUtils } from '../../grpc';
import { utils as claimsUtils, errors as claimsErrors } from '../../claims';
import { utils as nodesUtils } from '../../nodes';
import { validateSync, utils as validationUtils } from '../../validation';
import { matchSync } from '../../utils';

function nodesCrossSignClaim({
keyManager,
Expand Down Expand Up @@ -65,10 +68,23 @@ function nodesCrossSignClaim({
if (payloadData.type !== 'node') {
throw new claimsErrors.ErrorNodesClaimType();
}
// Verify the claim
const senderPublicKey = await nodeManager.getPublicKey(
nodesUtils.decodeNodeId(payloadData.node1),
const {
nodeId,
}: {
nodeId: NodeId;
} = validateSync(
(keyPath, value) => {
return matchSync(keyPath)(
[['nodeId'], () => validationUtils.parseNodeId(value)],
() => value,
);
},
{
nodeId: payloadData.node1,
},
);
// Verify the claim
const senderPublicKey = await nodeManager.getPublicKey(nodeId);
const verified = await claimsUtils.verifyClaimSignature(
constructedEncodedClaim,
senderPublicKey,
Expand Down Expand Up @@ -141,11 +157,13 @@ function nodesCrossSignClaim({
await sigchain.addExistingClaim(constructedDoublySignedClaim);
// Close the stream
await genClaims.next(null);
return;
});
} catch (e) {
await genClaims.throw(e);
// TODO: Handle the exception on this server - throw e?
// throw e;
return;
}
};
}
Expand Down
47 changes: 33 additions & 14 deletions src/agent/service/nodesHolePunchMessageSend.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type * as grpc from '@grpc/grpc-js';
import type { NodeManager } from '../../nodes';
import type { NodeId } from '../../nodes/types';
import type * as nodesPB from '../../proto/js/polykey/v1/nodes/nodes_pb';
import { utils as networkUtils } from '../../network';
import { utils as grpcUtils } from '../../grpc';
import { utils as nodesUtils } from '../../nodes';
import { validateSync, utils as validationUtils } from '../../validation';
import { matchSync } from '../../utils';
import * as utilsPB from '../../proto/js/polykey/v1/utils/utils_pb';

function nodesHolePunchMessageSend({
Expand All @@ -15,32 +17,49 @@ function nodesHolePunchMessageSend({
call: grpc.ServerUnaryCall<nodesPB.Relay, utilsPB.EmptyMessage>,
callback: grpc.sendUnaryData<utilsPB.EmptyMessage>,
): Promise<void> => {
const response = new utilsPB.EmptyMessage();
try {
const response = new utilsPB.EmptyMessage();
const {
targetId,
sourceId,
}: {
targetId: NodeId;
sourceId: NodeId;
} = validateSync(
(keyPath, value) => {
return matchSync(keyPath)(
[
['targetId'],
['sourceId'],
() => validationUtils.parseNodeId(value),
],
() => value,
);
},
{
targetId: call.request.getTargetId(),
sourceId: call.request.getSrcId(),
},
);
// Firstly, check if this node is the desired node
// If so, then we want to make this node start sending hole punching packets
// back to the source node.
if (
nodeManager.getNodeId() ===
nodesUtils.decodeNodeId(call.request.getTargetId())
) {
if (nodeManager.getNodeId() === targetId) {
const [host, port] = networkUtils.parseAddress(
call.request.getEgressAddress(),
);
await nodeManager.openConnection(host, port);
// Otherwise, find if node in table
// If so, ask the nodeManager to relay to the node
} else if (
await nodeManager.knowsNode(
nodesUtils.decodeNodeId(call.request.getSrcId()),
)
) {
} else if (await nodeManager.knowsNode(sourceId)) {
await nodeManager.relayHolePunchMessage(call.request);
}
} catch (err) {
callback(grpcUtils.fromError(err), response);
callback(null, response);
return;
} catch (e) {
callback(grpcUtils.fromError(e));
return;
}
callback(null, response);
};
}

Expand Down
19 changes: 7 additions & 12 deletions src/agent/service/notificationsSend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import type * as grpc from '@grpc/grpc-js';
import type { NotificationsManager } from '../../notifications';
import type * as notificationsPB from '../../proto/js/polykey/v1/notifications/notifications_pb';
import { utils as grpcUtils } from '../../grpc';
import {
utils as notificationsUtils,
errors as notificationsErrors,
} from '../../notifications';
import { utils as notificationsUtils } from '../../notifications';
import * as utilsPB from '../../proto/js/polykey/v1/utils/utils_pb';

function notificationsSend({
Expand All @@ -20,19 +17,17 @@ function notificationsSend({
>,
callback: grpc.sendUnaryData<utilsPB.EmptyMessage>,
): Promise<void> => {
const response = new utilsPB.EmptyMessage();
try {
const response = new utilsPB.EmptyMessage();
const jwt = call.request.getContent();
const notification = await notificationsUtils.verifyAndDecodeNotif(jwt);
await notificationsManager.receiveNotification(notification);
} catch (err) {
if (err instanceof notificationsErrors.ErrorNotifications) {
callback(grpcUtils.fromError(err), response);
} else {
throw err;
}
callback(null, response);
return;
} catch (e) {
callback(grpcUtils.fromError(e));
return;
}
callback(null, response);
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/agent/service/vaultsPermissionsCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ function vaultsPermissionsCheck(_) {
// response.setPermission(true);
// }
// callback(null, response);
} catch (err) {
callback(grpcUtils.fromError(err), null);
} catch (e) {
callback(grpcUtils.fromError(e));
}
};
}
Expand Down
11 changes: 6 additions & 5 deletions src/bin/identities/CommandAllow.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type PolykeyClient from '../../PolykeyClient';
import type { GestaltId } from '../../gestalts/types';
import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as parsers from '../utils/parsers';
import * as binParsers from '../utils/parsers';
import * as binProcessors from '../utils/processors';

class CommandAllow extends CommandPolykey {
Expand All @@ -12,14 +13,14 @@ class CommandAllow extends CommandPolykey {
this.description('Allow Permission for Identity');
this.argument(
'<gestaltId>',
'Node ID or `Provider Id:Identity Id`',
parsers.parseGestaltId,
'Node ID or `Provider ID:Identity ID`',
binParsers.parseGestaltId,
);
this.argument('<permissions>', 'permission to set');
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
this.action(async (gestaltId, permissions, options) => {
this.action(async (gestaltId: GestaltId, permissions, options) => {
const { default: PolykeyClient } = await import('../../PolykeyClient');
const identitiesPB = await import(
'../../proto/js/polykey/v1/identities/identities_pb'
Expand Down Expand Up @@ -54,7 +55,7 @@ class CommandAllow extends CommandPolykey {
});
const setActionMessage = new permissionsPB.ActionSet();
setActionMessage.setAction(permissions);
if (gestaltId.nodeId) {
if (gestaltId.type === 'node') {
// Setting by Node
const nodeMessage = new nodesPB.Node();
nodeMessage.setNodeId(gestaltId.nodeId);
Expand Down
7 changes: 4 additions & 3 deletions src/bin/identities/CommandDisallow.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type PolykeyClient from '../../PolykeyClient';
import type { GestaltId } from '../../gestalts/types';
import CommandPolykey from '../CommandPolykey';
import * as binOptions from '../utils/options';
import * as binUtils from '../utils';
Expand All @@ -19,7 +20,7 @@ class CommandDisallow extends CommandPolykey {
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
this.action(async (gestaltId, permissions, options) => {
this.action(async (gestaltId: GestaltId, permissions, options) => {
const { default: PolykeyClient } = await import('../../PolykeyClient');
const identitiesPB = await import(
'../../proto/js/polykey/v1/identities/identities_pb'
Expand Down Expand Up @@ -54,8 +55,8 @@ class CommandDisallow extends CommandPolykey {
});
const setActionMessage = new permissionsPB.ActionSet();
setActionMessage.setAction(permissions);
if (gestaltId.nodeId) {
// Setting by Node.
if (gestaltId.type === 'node') {
// Setting by Node
const nodeMessage = new nodesPB.Node();
nodeMessage.setNodeId(gestaltId.nodeId);
setActionMessage.setNode(nodeMessage);
Expand Down
9 changes: 5 additions & 4 deletions src/bin/identities/CommandDiscover.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type PolykeyClient from '../../PolykeyClient';
import type { GestaltId } from '../../gestalts/types';
import CommandPolykey from '../CommandPolykey';
import * as binOptions from '../utils/options';
import * as binUtils from '../utils';
Expand All @@ -14,13 +15,13 @@ class CommandDiscover extends CommandPolykey {
);
this.argument(
'<gestaltId>',
'Node ID or `Provider Id:Identity Id`',
'Node ID or `Provider ID:Identity ID`',
parsers.parseGestaltId,
);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
this.action(async (gestaltId, options) => {
this.action(async (gestaltId: GestaltId, options) => {
const { default: PolykeyClient } = await import('../../PolykeyClient');
const identitiesPB = await import(
'../../proto/js/polykey/v1/identities/identities_pb'
Expand Down Expand Up @@ -50,8 +51,8 @@ class CommandDiscover extends CommandPolykey {
port: clientOptions.clientPort,
logger: this.logger.getChild(PolykeyClient.name),
});
if (gestaltId.nodeId != null) {
// Discovery by Node.
if (gestaltId.type === 'node') {
// Discovery by Node
const nodeMessage = new nodesPB.Node();
nodeMessage.setNodeId(gestaltId.nodeId);
await binUtils.retryAuthentication(
Expand Down
11 changes: 6 additions & 5 deletions src/bin/identities/CommandGet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type gestaltsPB from '../../proto/js/polykey/v1/gestalts/gestalts_pb';
import type PolykeyClient from '../../PolykeyClient';
import type { GestaltId } from '../../gestalts/types';
import type gestaltsPB from '../../proto/js/polykey/v1/gestalts/gestalts_pb';
import CommandPolykey from '../CommandPolykey';
import * as binOptions from '../utils/options';
import * as binUtils from '../utils';
Expand All @@ -15,13 +16,13 @@ class CommandGet extends CommandPolykey {
);
this.argument(
'<gestaltId>',
'Node ID or `Provider Id:Identity Id`',
'Node ID or `Provider ID:Identity ID`',
parsers.parseGestaltId,
);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
this.action(async (gestaltId, options) => {
this.action(async (gestaltId: GestaltId, options) => {
const { default: PolykeyClient } = await import('../../PolykeyClient');
const identitiesPB = await import(
'../../proto/js/polykey/v1/identities/identities_pb'
Expand Down Expand Up @@ -52,8 +53,8 @@ class CommandGet extends CommandPolykey {
logger: this.logger.getChild(PolykeyClient.name),
});
let res: gestaltsPB.Graph;
if (gestaltId.nodeId) {
// Getting from node.
if (gestaltId.type === 'node') {
// Getting from node
const nodeMessage = new nodesPB.Node();
nodeMessage.setNodeId(gestaltId.nodeId);
res = await binUtils.retryAuthentication(
Expand Down
Loading

0 comments on commit 134ad24

Please sign in to comment.