Add CORS support for the REST services

The added options work in opt-in fashion. If they are not specified,
the server will respond to all requests as if the CORS specification
doesn't exist. This will result in errors in CORS-enabled clients.

Please note that future versions may support more than one allowed
origin. The option names will stay the same, but the user will be
able to repeat them on the command line (similar to other options
such as --web3-url).

To be documented in the guide in a separate PR.
This commit is contained in:
Zahary Karadjov 2022-02-12 00:33:30 +02:00 committed by zah
parent e81e67fe65
commit 922a0d264c
4 changed files with 34 additions and 8 deletions

View File

@ -331,6 +331,11 @@ type
defaultValueDesc: "127.0.0.1"
name: "rest-address" }: ValidIpAddress
restAllowedOrigin* {.
desc: "Limit the access to the REST API to a particular hostname " &
"(for CORS-enabled clients such as browsers)"
name: "rest-allow-origin" }: Option[string]
restCacheSize* {.
defaultValue: 3
desc: "The maximum number of recently accessed states that are kept in " &
@ -377,6 +382,11 @@ type
defaultValueDesc: "127.0.0.1"
name: "keymanager-address" }: ValidIpAddress
keymanagerAllowedOrigin* {.
desc: "Limit the access to the Keymanager API to a particular hostname " &
"(for CORS-enabled clients such as browsers)"
name: "keymanager-allow-origin" }: Option[string]
keymanagerTokenFile* {.
desc: "A file specifying the authorizition token required for accessing the keymanager API"
name: "keymanager-token-file" }: Option[InputFile]

View File

@ -35,7 +35,9 @@ type
template init(T: type RpcHttpServer, ip: ValidIpAddress, port: Port): T =
newRpcHttpServer([initTAddress(ip, port)])
template init(T: type RestServerRef, ip: ValidIpAddress, port: Port,
template init(T: type RestServerRef,
ip: ValidIpAddress, port: Port,
allowedOrigin: Option[string],
config: BeaconNodeConf): T =
let address = initTAddress(ip, port)
let serverFlags = {HttpServerFlags.QueryCommaSeparatedArray,
@ -48,7 +50,8 @@ template init(T: type RestServerRef, ip: ValidIpAddress, port: Port,
seconds(int64(config.restRequestTimeout))
maxHeadersSize = config.restMaxRequestHeadersSize * 1024
maxRequestBodySize = config.restMaxRequestBodySize * 1024
let res = RestServerRef.new(getRouter(), address, serverFlags = serverFlags,
let res = RestServerRef.new(getRouter(allowedOrigin),
address, serverFlags = serverFlags,
httpHeadersTimeout = headersTimeout,
maxHeadersSize = maxHeadersSize,
maxRequestBodySize = maxRequestBodySize)
@ -372,7 +375,11 @@ proc init*(T: type BeaconNode,
nil
let restServer = if config.restEnabled:
RestServerRef.init(config.restAddress, config.restPort, config)
RestServerRef.init(
config.restAddress,
config.restPort,
config.restAllowedOrigin,
config)
else:
nil
@ -400,10 +407,19 @@ proc init*(T: type BeaconNode,
if restServer != nil and
config.restAddress == config.keymanagerAddress and
config.restPort == config.keymanagerPort:
if config.keymanagerAllowedOrigin.isSome and
config.restAllowedOrigin != config.keymanagerAllowedOrigin:
fatal "Please specify a separate port for the Keymanager API " &
"if you want to restrict the origin in a different way " &
"from the Beacon API"
quit 1
restServer
else:
RestServerRef.init(config.keymanagerAddress, config.keymanagerPort,
config)
RestServerRef.init(
config.keymanagerAddress,
config.keymanagerPort,
config.keymanagerAllowedOrigin,
config)
else:
nil

View File

@ -271,8 +271,8 @@ func keysToIndices*(cacheTable: var Table[ValidatorPubKey, ValidatorIndex],
indices[listIndex[]] = some(ValidatorIndex(validatorIndex))
indices
proc getRouter*(): RestRouter =
RestRouter.init(validate)
proc getRouter*(allowedOrigin: Option[string]): RestRouter =
RestRouter.init(validate, allowedOrigin = allowedOrigin)
const
jsonMediaType* = MediaType.init("application/json")

2
vendor/nim-presto vendored

@ -1 +1 @@
Subproject commit 668a2369f666e0753983ae34eaa88363a6dd823c
Subproject commit 1dba6dd6f466cd4e7b793b0e473c237ce453d82a