Skip to content

Commit 9269f3a

Browse files
committed
grpc-js: Restrict control-plane status codes
1 parent b8da460 commit 9269f3a

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

packages/grpc-js/src/channel.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,28 @@ function getNewCallNumber(): number {
6868
return callNumber;
6969
}
7070

71+
const INAPPPROPRIATE_CONTROL_PLANE_CODES: Status[] = [
72+
Status.OK,
73+
Status.INVALID_ARGUMENT,
74+
Status.NOT_FOUND,
75+
Status.ALREADY_EXISTS,
76+
Status.FAILED_PRECONDITION,
77+
Status.ABORTED,
78+
Status.OUT_OF_RANGE,
79+
Status.DATA_LOSS
80+
]
81+
82+
function restrictControlPlaneStatusCode(code: Status, details: string): {code: Status, details: string} {
83+
if (INAPPPROPRIATE_CONTROL_PLANE_CODES.includes(code)) {
84+
return {
85+
code: Status.INTERNAL,
86+
details: `Invalid status from control plane: ${code} ${Status[code]} ${details}`
87+
}
88+
} else {
89+
return {code, details};
90+
}
91+
}
92+
7193
/**
7294
* An interface that represents a communication channel to a server specified
7395
* by a given address.
@@ -320,7 +342,7 @@ export class ChannelImplementation implements Channel {
320342
this.trace('Name resolution failed with calls queued for config selection');
321343
}
322344
if (this.configSelector === null) {
323-
this.currentResolutionError = status;
345+
this.currentResolutionError = {...restrictControlPlaneStatusCode(status.code, status.details), metadata: status.metadata};
324346
}
325347
const localQueue = this.configSelectionQueue;
326348
this.configSelectionQueue = [];
@@ -534,10 +556,11 @@ export class ChannelImplementation implements Channel {
534556
},
535557
(error: Error & { code: number }) => {
536558
// We assume the error code isn't 0 (Status.OK)
537-
callStream.cancelWithStatus(
559+
const {code, details} = restrictControlPlaneStatusCode(
538560
typeof error.code === 'number' ? error.code : Status.UNKNOWN,
539561
`Getting metadata from plugin failed with error: ${error.message}`
540-
);
562+
)
563+
callStream.cancelWithStatus(code, details);
541564
}
542565
);
543566
}
@@ -549,17 +572,13 @@ export class ChannelImplementation implements Channel {
549572
if (callMetadata.getOptions().waitForReady) {
550573
this.pushPick(callStream, callMetadata, callConfig, dynamicFilters);
551574
} else {
552-
callStream.cancelWithStatus(
553-
pickResult.status!.code,
554-
pickResult.status!.details
555-
);
575+
const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
576+
callStream.cancelWithStatus(code, details);
556577
}
557578
break;
558579
case PickResultType.DROP:
559-
callStream.cancelWithStatus(
560-
pickResult.status!.code,
561-
pickResult.status!.details
562-
);
580+
const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
581+
callStream.cancelWithStatus(code, details);
563582
break;
564583
default:
565584
throw new Error(
@@ -668,10 +687,8 @@ export class ChannelImplementation implements Channel {
668687
this.tryPick(stream, metadata, callConfig, []);
669688
}
670689
} else {
671-
stream.cancelWithStatus(
672-
callConfig.status,
673-
'Failed to route call to method ' + stream.getMethod()
674-
);
690+
const {code, details} = restrictControlPlaneStatusCode(callConfig.status, 'Failed to route call to method ' + stream.getMethod());
691+
stream.cancelWithStatus(code, details);
675692
}
676693
}
677694
}

0 commit comments

Comments
 (0)