@@ -3,7 +3,7 @@ import * as protoLoader from '@grpc/proto-loader';
33import * as promClient from 'prom-client' ;
44import { GrpcPlugin } from '../../node-plugin' ;
55import { Logger } from '../../logger' ;
6- import { PluginConfig } from '../../config' ;
6+ import { PluginConfig , SecurityConfig } from '../../config' ;
77import { createBrowser , Browser } from '../../browser' ;
88import { HTTPHeaders , ImageRenderOptions , RenderOptions } from '../../types' ;
99import {
@@ -21,6 +21,7 @@ import {
2121} from './types' ;
2222import { createSanitizer , Sanitizer } from '../../sanitizer/Sanitizer' ;
2323import { SanitizeRequest } from '../../sanitizer/types' ;
24+ import { Status } from '@grpc/grpc-js/build/src/constants' ;
2425
2526const rendererV2PackageDef = protoLoader . loadSync ( __dirname + '/../../../proto/rendererv2.proto' , {
2627 keepCase : true ,
@@ -58,7 +59,7 @@ export class RenderGRPCPluginV2 implements GrpcPlugin {
5859 async grpcServer ( server : grpc . Server ) {
5960 const metrics = setupMetrics ( ) ;
6061 const browser = createBrowser ( this . config . rendering , this . log , metrics ) ;
61- const pluginService = new PluginGRPCServer ( browser , this . log , createSanitizer ( ) ) ;
62+ const pluginService = new PluginGRPCServer ( browser , this . log , createSanitizer ( ) , this . config . plugin . security ) ;
6263
6364 const rendererServiceDef = rendererV2ProtoDescriptor [ 'pluginextensionv2' ] [ 'Renderer' ] [ 'service' ] ;
6465 server . addService ( rendererServiceDef , pluginService as any ) ;
@@ -92,7 +93,7 @@ export class RenderGRPCPluginV2 implements GrpcPlugin {
9293class PluginGRPCServer {
9394 private browserVersion : string | undefined ;
9495
95- constructor ( private browser : Browser , private log : Logger , private sanitizer : Sanitizer ) { }
96+ constructor ( private browser : Browser , private log : Logger , private sanitizer : Sanitizer , private securityCfg : SecurityConfig ) { }
9697
9798 async start ( browserVersion ?: string ) {
9899 this . browserVersion = browserVersion ;
@@ -104,7 +105,16 @@ class PluginGRPCServer {
104105 const headers : HTTPHeaders = { } ;
105106
106107 if ( ! req ) {
107- throw new Error ( 'Request cannot be null' ) ;
108+ return callback ( { code : Status . INVALID_ARGUMENT , details : 'Request cannot be null' } ) ;
109+ }
110+
111+ const configToken = this . securityCfg . authToken || '' ;
112+ if ( ! req . authToken || req . authToken !== configToken ) {
113+ return callback ( { code : Status . UNAUTHENTICATED , details : 'Unauthorized request' } ) ;
114+ }
115+
116+ if ( req . url && ! ( req . url . startsWith ( 'http://' ) || req . url . startsWith ( 'https://' ) ) ) {
117+ return callback ( { code : Status . INVALID_ARGUMENT , details : 'Forbidden query url protocol' } ) ;
108118 }
109119
110120 if ( req . headers ) {
@@ -145,7 +155,16 @@ class PluginGRPCServer {
145155 const headers : HTTPHeaders = { } ;
146156
147157 if ( ! req ) {
148- throw new Error ( 'Request cannot be null' ) ;
158+ return callback ( { code : Status . INVALID_ARGUMENT , details : 'Request cannot be null' } ) ;
159+ }
160+
161+ const configToken = this . securityCfg . authToken || '' ;
162+ if ( ! req . authToken || req . authToken !== configToken ) {
163+ return callback ( { code : Status . UNAUTHENTICATED , details : 'Unauthorized request' } ) ;
164+ }
165+
166+ if ( req . url && ! ( req . url . startsWith ( 'http://' ) || req . url . startsWith ( 'https://' ) ) ) {
167+ return callback ( { code : Status . INVALID_ARGUMENT , details : 'Forbidden query url protocol' } ) ;
149168 }
150169
151170 if ( req . headers ) {
@@ -198,6 +217,11 @@ class PluginGRPCServer {
198217 async sanitize ( call : grpc . ServerUnaryCall < GRPCSanitizeRequest , any > , callback : grpc . sendUnaryData < GRPCSanitizeResponse > ) {
199218 const grpcReq = call . request ;
200219
220+ const configToken = this . securityCfg . authToken || '' ;
221+ if ( ! grpcReq . authToken || grpcReq . authToken !== configToken ) {
222+ return callback ( { code : Status . UNAUTHENTICATED , details : 'Unauthorized request' } ) ;
223+ }
224+
201225 const req : SanitizeRequest = {
202226 content : grpcReq . content ,
203227 config : JSON . parse ( grpcReq . config . toString ( ) ) ,
@@ -294,6 +318,10 @@ const populateConfigFromEnv = (config: PluginConfig) => {
294318 if ( env [ 'GF_PLUGIN_RENDERING_DUMPIO' ] ) {
295319 config . rendering . dumpio = env [ 'GF_PLUGIN_RENDERING_DUMPIO' ] === 'true' ;
296320 }
321+
322+ if ( env [ 'GF_PLUGIN_AUTH_TOKEN' ] ) {
323+ config . plugin . security . authToken = env [ 'GF_PLUGIN_AUTH_TOKEN' ] ;
324+ }
297325} ;
298326
299327interface PluginMetrics {
0 commit comments