Skip to content

Commit

Permalink
add allow routes by methods
Browse files Browse the repository at this point in the history
  • Loading branch information
fraidev committed Jan 18, 2024
1 parent 433f196 commit 0786ebc
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 85 deletions.
71 changes: 52 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,35 +42,65 @@ curl http://localhost:8080/chains/main/blocks/head/header
Here a default `tzproxy.yaml` file:

```yaml
allow_routes:
enabled: true
values:
- GET/chains/.*/blocks
- GET/chains/.*/chain_id
- GET/chains.*/checkpoint
- GET/chains/.*/invalid_blocks
- GET/chains.*/invalid_blocks.*
- GET/chains/.*/is_bootstrapped
- GET/chains.*/mempool/filter
- GET/chains/.*/mempool/monitor_operations
- GET/chains/.*/mempool/pending_operations
- GET/config/network/user_activated_protocol_overrides
- GET/config/network/user_activated_upgrades
- GET/config/network/dal
- GET/describe.*
- GET/errors
- GET/monitor.*
- GET/network/greylist/ips
- GET/network/greylist/peers
- GET/network/self
- GET/network/stat
- GET/network/version
- GET/network/versions
- GET/protocols
- GET/protocols.*
- GET/protocols.*/environment
- GET/version
- POST/chains/.*/blocks/.*/helpers
- POST/chains/.*/blocks/.*/script
- POST/chains/.*/blocks/.*/context/contracts.*/big_map_get
- POST/injection/operation
cache:
disabled_routes:
- /monitor/.*
- /chains/.*/mempool
- /chains/.*/blocks.*head
- GET/monitor/.*
- GET/chains/.*/mempool
- GET/chains/.*/blocks.*head
enabled: true
size_mb: 100
ttl: 5
cors:
enabled: true
deny_list:
deny_ips:
enabled: false
values: []
deny_routes:
enabled: true
values:
- /injection/block
- /injection/protocol
- /network.*
- /workers.*
- /worker.*
- /stats.*
- /config
- /chains/.*/blocks/.*/helpers/baking_rights
- /chains/.*/blocks/.*/helpers/endorsing_rights
- /helpers/baking_rights
- /helpers/endorsing_rights
- /chains/.*/blocks/.*/context/contracts(/?)$
- /chains/.*/blocks/.*/context/raw/bytes
- GET/workers.*
- GET/worker.*
- GET/stats.*
- GET/chains/.*/blocks/.*/helpers/baking_rights
- GET/chains/.*/blocks/.*/helpers/endorsing_rights
- GET/helpers/baking_rights
- GET/helpers/endorsing_rights
- GET/chains/.*/blocks/.*/context/contracts(/?)$
- GET/chains/.*/blocks/.*/context/raw/bytes
- POST/injection/block
- POST/injection/protocol
dev_mode: false
gc:
optimize_memory_store: true
Expand All @@ -96,6 +126,7 @@ redis:
host: ""
tezos_host:
- 127.0.0.1:8732
tezos_host_retry: ""
```
### Environment Variables
Expand All @@ -118,10 +149,12 @@ You can also configure or overwrite TzProxy with environment variables, using th
- `TZPROXY_RATE_LIMIT_ENABLED` is a flag to enable rate limiting.
- `TZPROXY_RATE_LIMIT_MINUTES` is the minutes of the period of rate limiting.
- `TZPROXY_RATE_LIMIT_MAX` is the max of requests permitted in a period.
- `TZPROXY_DENY_LIST_ENABLED` is a flag to block IP addresses.
- `TZPROXY_DENY_LIST_VALUES` is the IP Address that will be blocked on the proxy.
- `TZPROXY_DENY_IPS_ENABLED` is a flag to block IP addresses.
- `TZPROXY_DENY_IPS_VALUES` is the IP Address that will be blocked on the proxy.
- `TZPROXY_DENY_ROUTES_ENABLED` is a flag to block the Tezos node's routes.
- `TZPROXY_DENY_ROUTES_VALUES` is the Tezos nodes routes that will be blocked on the proxy.conf.
- `TZPROXY_ALLOW_ROUTES_ENABLED` is a flag to allow the Tezos node's routes.
- `TZPROXY_ALLOW_ROUTES_VALUES` is the Tezos nodes routes that will be allowed on the proxy.conf.
- `TZPROXY_METRICS_ENABLED` is the flag to enable metrics.
- `TZPROXY_METRICS_PPROF` is the flag to enable pprof.
- `TZPROXY_METRICS_HOST` is the host of the prometheus metrics and pprof (if enabled).
Expand Down
38 changes: 14 additions & 24 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"net/http"
"net/url"
"os"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -68,11 +67,16 @@ func NewConfig() *Config {
},
}

// Parse routes by http method
allowRegexRoutes := parseRegexRoutes(configFile.AllowRoutes.Values)
denyRegexRoutes := parseRegexRoutes(configFile.DenyRoutes.Values)
cacheDisableRegexRoutes := parseRegexRoutes(configFile.Cache.DisabledRoutes)

config := &Config{
ConfigFile: configFile,
DenyListTable: func() map[string]bool {
DenyIPsTable: func() map[string]bool {
table := make(map[string]bool)
for _, ip := range configFile.DenyList.Values {
for _, ip := range configFile.DenyIPs.Values {
table[ip] = true
}
return table
Expand All @@ -81,28 +85,14 @@ func NewConfig() *Config {
Period: time.Duration(configFile.RateLimit.Minutes) * time.Minute,
Limit: int64(configFile.RateLimit.Max),
},
Store: store,
CacheTTL: time.Duration(configFile.Cache.TTL) * (time.Second),
ProxyConfig: &proxyConfig,
Redis: redisClient,
}

for _, route := range config.ConfigFile.DenyRoutes.Values {
regex, err := regexp.Compile(route)
if err != nil {
log.Fatal().Err(err).Msg("unable to compile regex")
}
config.BlockRoutesRegex = append(config.BlockRoutesRegex, regex)
Store: store,
CacheTTL: time.Duration(configFile.Cache.TTL) * (time.Second),
ProxyConfig: &proxyConfig,
Redis: redisClient,
AllowRoutesRegex: allowRegexRoutes,
DenyRoutesRegex: denyRegexRoutes,
CacheDisabledRoutesRegex: cacheDisableRegexRoutes,
}

for _, route := range config.ConfigFile.Cache.DisabledRoutes {
regex, err := regexp.Compile(route)
if err != nil {
log.Fatal().Err(err).Msg("unable to compile regex")
}
config.CacheDisabledRoutesRegex = append(config.CacheDisabledRoutesRegex, regex)
}

config.Logger = logger

config.RequestLoggerConfig = &middleware.RequestLoggerConfig{
Expand Down
48 changes: 38 additions & 10 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,53 @@ var defaultConfig = &ConfigFile{
Enabled: true,
TTL: 5,
DisabledRoutes: []string{
"/monitor/.*",
"/chains/.*/mempool",
"/chains/.*/blocks.*head",
"GET/monitor/.*",
"GET/chains/.*/mempool",
"GET/chains/.*/blocks.*head",
},
SizeMB: 100,
},
DenyList: DenyList{
DenyIPs: DenyIPs{
Enabled: false,
Values: []string{},
},
AllowRoutes: AllowRoutes{
Enabled: true,
Values: []string{
"GET/chains/.*/blocks",
"GET/chains/.*/chain_id", "GET/chains.*/checkpoint",
"GET/chains/.*/invalid_blocks", "GET/chains.*/invalid_blocks.*",
"GET/chains/.*/is_bootstrapped", "GET/chains.*/mempool/filter",
"GET/chains/.*/mempool/monitor_operations",
"GET/chains/.*/mempool/pending_operations",
"GET/config/network/user_activated_protocol_overrides",
"GET/config/network/user_activated_upgrades",
"GET/config/network/dal", "GET/describe.*", "GET/errors",
"GET/monitor.*", "GET/network/greylist/ips",
"GET/network/greylist/peers", "GET/network/self",
"GET/network/stat", "GET/network/version", "GET/network/versions",
"GET/protocols", "GET/protocols.*", "GET/protocols.*/environment",
"GET/version",
"POST/chains/.*/blocks/.*/helpers",
"POST/chains/.*/blocks/.*/script",
"POST/chains/.*/blocks/.*/context/contracts.*/big_map_get",
"POST/injection/operation",
},
},
DenyRoutes: DenyRoutes{
Enabled: true,
Values: []string{
"/injection/block", "/injection/protocol", "/network.*", "/workers.*",
"/worker.*", "/stats.*", "/config", "/chains/.*/blocks/.*/helpers/baking_rights",
"/chains/.*/blocks/.*/helpers/endorsing_rights",
"/helpers/baking_rights", "/helpers/endorsing_rights",
"/chains/.*/blocks/.*/context/contracts(/?)$",
"/chains/.*/blocks/.*/context/raw/bytes",
"GET/workers.*",
"GET/worker.*",
"GET/stats.*",
"GET/chains/.*/blocks/.*/helpers/baking_rights",
"GET/chains/.*/blocks/.*/helpers/endorsing_rights",
"GET/helpers/baking_rights",
"GET/helpers/endorsing_rights",
"GET/chains/.*/blocks/.*/context/contracts(/?)$",
"GET/chains/.*/blocks/.*/context/raw/bytes",
"POST/injection/block",
"POST/injection/protocol",
},
},
Metrics: Metrics{
Expand Down
17 changes: 12 additions & 5 deletions config/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ type Config struct {
Level uint
HashBlock string
ConfigFile *ConfigFile
DenyListTable map[string]bool
Rate *limiter.Rate
CacheDisabledRoutesRegex []*regexp.Regexp
BlockRoutesRegex []*regexp.Regexp
DenyIPsTable map[string]bool
CacheDisabledRoutesRegex map[string][]*regexp.Regexp
DenyRoutesRegex map[string][]*regexp.Regexp
AllowRoutesRegex map[string][]*regexp.Regexp
Store echocache.Cache
CacheTTL time.Duration
RequestLoggerConfig *middleware.RequestLoggerConfig
Expand All @@ -45,7 +46,12 @@ type Cache struct {
SizeMB int `mapstructure:"size_mb"`
}

type DenyList struct {
type DenyIPs struct {
Enabled bool `mapstructure:"enabled"`
Values []string `mapstructure:"values"`
}

type AllowRoutes struct {
Enabled bool `mapstructure:"enabled"`
Values []string `mapstructure:"values"`
}
Expand Down Expand Up @@ -90,8 +96,9 @@ type ConfigFile struct {
Logger Logger `mapstructure:"logger"`
RateLimit RateLimit `mapstructure:"rate_limit"`
Cache Cache `mapstructure:"cache"`
DenyList DenyList `mapstructure:"deny_list"`
DenyIPs DenyIPs `mapstructure:"deny_ips"`
DenyRoutes DenyRoutes `mapstructure:"deny_routes"`
AllowRoutes AllowRoutes `mapstructure:"allow_routes"`
Metrics Metrics `mapstructure:"metrics"`
GC GC `mapstructure:"gc"`
CORS CORS `mapstructure:"cors"`
Expand Down
56 changes: 56 additions & 0 deletions config/regex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package config

import (
"net/http"
"regexp"
"strings"

"github.com/rs/zerolog/log"
)

func parseRegexRoutes(values []string) map[string][]*regexp.Regexp {
allMethods := []string{
http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete,
http.MethodPatch, http.MethodHead, http.MethodOptions,
}

regexRoutes := make(map[string][]*regexp.Regexp)
for _, route := range values {
if !containsPrefix(route, allMethods) {
for _, method := range allMethods {
regex, err := regexp.Compile(route)
if err != nil {
log.Fatal().Err(err).Msg("unable to compile regex")
}

regexRoutes[method] = append(regexRoutes[method], regex)
}
continue
}

for _, method := range allMethods {
if strings.HasPrefix(strings.ToUpper(route), method) {
url := strings.TrimPrefix(route, method)
regex, err := regexp.Compile(url)
if err != nil {
log.Fatal().Err(err).Msg("unable to compile regex")
}

regexRoutes[method] = append(regexRoutes[method], regex)
break
}
}
}

return regexRoutes
}

func containsPrefix(s string, prefixes []string) bool {
for _, prefix := range prefixes {
if strings.HasPrefix(s, prefix) {
return true
}
}

return false
}
6 changes: 4 additions & 2 deletions config/viper.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ func initViper() *ConfigFile {
viper.SetDefault("rate_limit.enabled", defaultConfig.RateLimit.Enabled)
viper.SetDefault("rate_limit.minutes", defaultConfig.RateLimit.Minutes)
viper.SetDefault("rate_limit.max", defaultConfig.RateLimit.Max)
viper.SetDefault("deny_list.enabled", defaultConfig.DenyList.Enabled)
viper.SetDefault("deny_list.values", defaultConfig.DenyList.Values)
viper.SetDefault("deny_ips.enabled", defaultConfig.DenyIPs.Enabled)
viper.SetDefault("deny_ips.values", defaultConfig.DenyIPs.Values)
viper.SetDefault("deny_routes.enabled", defaultConfig.DenyRoutes.Enabled)
viper.SetDefault("deny_routes.values", defaultConfig.DenyRoutes.Values)
viper.SetDefault("allow_routes.enabled", defaultConfig.AllowRoutes.Enabled)
viper.SetDefault("allow_routes.values", defaultConfig.AllowRoutes.Values)
viper.SetDefault("metrics.enabled", defaultConfig.Metrics.Enabled)
viper.SetDefault("metrics.pprof", defaultConfig.Metrics.Pprof)
viper.SetDefault("metrics.host", defaultConfig.Metrics.Host)
Expand Down
2 changes: 1 addition & 1 deletion flextesa.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
image=oxheadalpha/flextesa:latest
script=mumbaibox
script=nairobibox
docker run --rm --name my-sandbox --detach -p 8732:20000 \
-e block_time=3 \
"$image" "$script" start
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func main() {
e.Use(middleware.RequestLoggerWithConfig(*config.RequestLoggerConfig))
e.Use(middlewares.CORS(config))
e.Use(middlewares.RateLimit(config))
e.Use(middlewares.DenyIPs(config))
e.Use(middlewares.AllowRoutes(config))
e.Use(middlewares.DenyRoutes(config))
e.Use(middlewares.Cache(config))
e.Use(middlewares.Gzip(config))
Expand Down
Loading

0 comments on commit 0786ebc

Please sign in to comment.