Merge pull request #2226 from murgatroid99/grpc-js_restrict_control_plane_status_codes

grpc-js: Restrict control-plane status codes
This commit is contained in:
Michael Lumish 2022-09-12 13:30:20 -07:00 committed by GitHub
commit b8c0cdc480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 32 additions and 15 deletions

View File

@ -68,6 +68,28 @@ function getNewCallNumber(): number {
return callNumber;
}
const INAPPROPRIATE_CONTROL_PLANE_CODES: Status[] = [
Status.OK,
Status.INVALID_ARGUMENT,
Status.NOT_FOUND,
Status.ALREADY_EXISTS,
Status.FAILED_PRECONDITION,
Status.ABORTED,
Status.OUT_OF_RANGE,
Status.DATA_LOSS
]
function restrictControlPlaneStatusCode(code: Status, details: string): {code: Status, details: string} {
if (INAPPROPRIATE_CONTROL_PLANE_CODES.includes(code)) {
return {
code: Status.INTERNAL,
details: `Invalid status from control plane: ${code} ${Status[code]} ${details}`
}
} else {
return {code, details};
}
}
/**
* An interface that represents a communication channel to a server specified
* by a given address.
@ -320,7 +342,7 @@ export class ChannelImplementation implements Channel {
this.trace('Name resolution failed with calls queued for config selection');
}
if (this.configSelector === null) {
this.currentResolutionError = status;
this.currentResolutionError = {...restrictControlPlaneStatusCode(status.code, status.details), metadata: status.metadata};
}
const localQueue = this.configSelectionQueue;
this.configSelectionQueue = [];
@ -534,10 +556,11 @@ export class ChannelImplementation implements Channel {
},
(error: Error & { code: number }) => {
// We assume the error code isn't 0 (Status.OK)
callStream.cancelWithStatus(
const {code, details} = restrictControlPlaneStatusCode(
typeof error.code === 'number' ? error.code : Status.UNKNOWN,
`Getting metadata from plugin failed with error: ${error.message}`
);
)
callStream.cancelWithStatus(code, details);
}
);
}
@ -549,17 +572,13 @@ export class ChannelImplementation implements Channel {
if (callMetadata.getOptions().waitForReady) {
this.pushPick(callStream, callMetadata, callConfig, dynamicFilters);
} else {
callStream.cancelWithStatus(
pickResult.status!.code,
pickResult.status!.details
);
const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
callStream.cancelWithStatus(code, details);
}
break;
case PickResultType.DROP:
callStream.cancelWithStatus(
pickResult.status!.code,
pickResult.status!.details
);
const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
callStream.cancelWithStatus(code, details);
break;
default:
throw new Error(
@ -668,10 +687,8 @@ export class ChannelImplementation implements Channel {
this.tryPick(stream, metadata, callConfig, []);
}
} else {
stream.cancelWithStatus(
callConfig.status,
'Failed to route call to method ' + stream.getMethod()
);
const {code, details} = restrictControlPlaneStatusCode(callConfig.status, 'Failed to route call to method ' + stream.getMethod());
stream.cancelWithStatus(code, details);
}
}
}