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; 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 * An interface that represents a communication channel to a server specified
* by a given address. * by a given address.
@ -320,7 +342,7 @@ export class ChannelImplementation implements Channel {
this.trace('Name resolution failed with calls queued for config selection'); this.trace('Name resolution failed with calls queued for config selection');
} }
if (this.configSelector === null) { if (this.configSelector === null) {
this.currentResolutionError = status; this.currentResolutionError = {...restrictControlPlaneStatusCode(status.code, status.details), metadata: status.metadata};
} }
const localQueue = this.configSelectionQueue; const localQueue = this.configSelectionQueue;
this.configSelectionQueue = []; this.configSelectionQueue = [];
@ -534,10 +556,11 @@ export class ChannelImplementation implements Channel {
}, },
(error: Error & { code: number }) => { (error: Error & { code: number }) => {
// We assume the error code isn't 0 (Status.OK) // We assume the error code isn't 0 (Status.OK)
callStream.cancelWithStatus( const {code, details} = restrictControlPlaneStatusCode(
typeof error.code === 'number' ? error.code : Status.UNKNOWN, typeof error.code === 'number' ? error.code : Status.UNKNOWN,
`Getting metadata from plugin failed with error: ${error.message}` `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) { if (callMetadata.getOptions().waitForReady) {
this.pushPick(callStream, callMetadata, callConfig, dynamicFilters); this.pushPick(callStream, callMetadata, callConfig, dynamicFilters);
} else { } else {
callStream.cancelWithStatus( const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
pickResult.status!.code, callStream.cancelWithStatus(code, details);
pickResult.status!.details
);
} }
break; break;
case PickResultType.DROP: case PickResultType.DROP:
callStream.cancelWithStatus( const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details);
pickResult.status!.code, callStream.cancelWithStatus(code, details);
pickResult.status!.details
);
break; break;
default: default:
throw new Error( throw new Error(
@ -668,10 +687,8 @@ export class ChannelImplementation implements Channel {
this.tryPick(stream, metadata, callConfig, []); this.tryPick(stream, metadata, callConfig, []);
} }
} else { } else {
stream.cancelWithStatus( const {code, details} = restrictControlPlaneStatusCode(callConfig.status, 'Failed to route call to method ' + stream.getMethod());
callConfig.status, stream.cancelWithStatus(code, details);
'Failed to route call to method ' + stream.getMethod()
);
} }
} }
} }