Skip to content

Commit

Permalink
Expose /env and /config for Configuration reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
letzya committed Oct 18, 2024
1 parent cf5aeb0 commit 5e8d5d7
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 0 deletions.
24 changes: 24 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,28 @@ type SecurityConfig struct {
Certificates CertificatesConfig `json:"certificates"`
}

type ConfigurationReportingCfg struct {

// Enable controls the availability of HTTP endpoints for monitoring and debugging Tyk Gateway.
// These endpoints provide critical system information and are disabled by default for security reasons.
// Access to these endpoints requires a secret, defined in the `security.secret` configuration field.
// Available endpoints include:
// * /config - a read-only HTTP endpoint that returns the current config keys and values in JSON notation.
// * /env - a read-only HTTP endpoint that returns the current config keys and values in an environment variable
// format
Enable bool `json:"enable"`

// Ensure the Gateway configuration port is set
// The Configuration API runs on a separate port, so you can secure this port behind a firewall.
APIPort int `json:"api_port"`

// This should be changed as soon as Tyk is installed on your system.
// This value is used in when using Tyk Gateway Config APIs. It should be passed along as the X-Tyk-Authorization
// header in any requests made. Tyk assumes that you are sensible enough not to expose the management endpoints
// publicly and to keep this configuration value to yourself.
APIKey string `json:"api_key" structviewer:"obfuscate"`
}

type NewRelicConfig struct {
// New Relic Application name
AppName string `json:"app_name"`
Expand Down Expand Up @@ -680,6 +702,8 @@ type Config struct {
// Set to run your Gateway Control API on a separate port, and protect it behind a firewall if needed. Please make sure you follow this guide when setting the control port https://tyk.io/docs/planning-for-production/#change-your-control-port.
ControlAPIPort int `json:"control_api_port"`

ConfigurationReporting ConfigurationReportingCfg `json:"configuration_reporting"`

// This should be changed as soon as Tyk is installed on your system.
// This value is used in every interaction with the Tyk Gateway API. It should be passed along as the X-Tyk-Authorization header in any requests made.
// Tyk assumes that you are sensible enough not to expose the management endpoints publicly and to keep this configuration value to yourself.
Expand Down
82 changes: 82 additions & 0 deletions gateway/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/TykTechnologies/structviewer"
htmltemplate "html/template"
"io/ioutil"
stdlog "log"
Expand Down Expand Up @@ -1940,6 +1941,9 @@ func (gw *Gateway) startServer() {
muxer := &proxyMux{}

router := mux.NewRouter()

gw.loadConfigurationAPI()

gw.loadControlAPIEndpoints(router)

muxer.setRouter(gw.GetConfig().ControlAPIPort, "", router, gw.GetConfig())
Expand Down Expand Up @@ -1977,3 +1981,81 @@ func (gw *Gateway) SetConfig(conf config.Config, skipReload ...bool) {
gw.config.Store(conf)
gw.configMu.Unlock()
}

func (gw *Gateway) loadConfigurationAPI() error {

config := gw.GetConfig()

// Check if enabled
if config.ConfigurationReporting.Enable != true {
mainLog.Info("configuration Reporting API is disabled in the configuration. Please enable it if you need to use it")
}
mainLog.Info("configuration Reporting API is enabled")

port := strconv.Itoa(config.ConfigurationReporting.APIPort)
// Check the port
if port == "" {
return fmt.Errorf("configuration Reporting API port is not set. Please set it in order to use it")
}
mainLog.Info("configuration Reporting API Port is set to", port)

// Check the API key
if config.ConfigurationReporting.APIKey == "" {
return fmt.Errorf("configuration Reporting API port is not set. Please set it in order to use it")
}

var structviewerCfg = &structviewer.Config{
Object: config,
ParseComments: false,
}
const GW_ENV_PREFIX = "TYK_GW_"
v, err := structviewer.New(structviewerCfg, GW_ENV_PREFIX)
if err != nil {
return err
}

// Create a new router for the Configuration reporting API server
router := mux.NewRouter()

// Define routes and middleware specific to the Config API
router.Handle("/config", authConfigurationAPI(http.HandlerFunc(v.ConfigHandler), config.ConfigurationReporting.APIKey))
router.Handle("/env", authConfigurationAPI(http.HandlerFunc(v.EnvsHandler), config.ConfigurationReporting.APIKey))

// muxer := &proxyMux{}
// muxer.setRouter(apiPort, "", router, gw.GetConfig())

log.Printf("Starting Configuration Reporting API on addr=%q", config.ConfigurationReporting.APIPort)

var apiPort = ":" + port
if err := http.ListenAndServe(apiPort, router); err != nil {
fmt.Println("Error starting server:", err)
}
mainLog.Info("--> Configuration Reporting API is on - Listening on port: ", apiPort)

return nil
}

// authConfigurationAPI will ensure that the accessor of the HTTP API has the
// correct security credentials - this is a shared secret between the
// client and the owner and is set in the settings. This should
// never be made public!
func authConfigurationAPI(next http.Handler, apiKey string) http.Handler {

authorizationHeader := "X-Tyk-Authorization"
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tykAuthKey := r.Header.Get(authorizationHeader)
if tykAuthKey != apiKey {
log.Warning("Attempted administrative access with invalid or missing key!")

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
err := json.NewEncoder(w).Encode(map[string]string{"error": "Attempted administrative access with invalid or missing key!"})
if err != nil {
log.WithError(err).Error("Failed to write error response in authAdminMiddleware middleware")
}

return
}
next.ServeHTTP(w, r)
})
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ require (
github.com/TykTechnologies/graphql-go-tools/v2 v2.0.0-20240509085643-e95cdc317e1d
github.com/TykTechnologies/kin-openapi v0.90.0
github.com/TykTechnologies/opentelemetry v0.0.21
github.com/TykTechnologies/structviewer v1.1.1
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/go-redis/redismock/v9 v9.2.0
github.com/goccy/go-json v0.10.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ github.com/TykTechnologies/opentelemetry v0.0.21 h1:/ew4NET0nbLKmsNKmuEavTU+Zp3L
github.com/TykTechnologies/opentelemetry v0.0.21/go.mod h1:5LkNDN08FYVhSTH0gC3hwk6cH6jP3F8cc5mv2asUHyA=
github.com/TykTechnologies/storage v1.2.2 h1:NfBIpnMu9cPMrLxFrKIVzQHtTsvXte7/VdmFC0QrSfw=
github.com/TykTechnologies/storage v1.2.2/go.mod h1:x4/SA+yiTmYkOyhQy18eNLgGJR4G6/kxX6qXBpzFmtw=
github.com/TykTechnologies/structviewer v1.1.1 h1:9/++875RSRc/8rmUgAbrVuQIziVsM1sm2/MsDiG7g8A=
github.com/TykTechnologies/structviewer v1.1.1/go.mod h1:jrG78SYN2mxqbjDwSk6z5KIEwMWaZLiRV0yaxt5p2dg=
github.com/TykTechnologies/tyk-pump v1.10.0 h1:mc2sRUlY6pPN8cdOUzswi8Ukjgtoxo5YMSh1XUTinwQ=
github.com/TykTechnologies/tyk-pump v1.10.0/go.mod h1:dN4jBt2NlveiWalfTBgmyhkdRFL5kbCA02BwBBvAl2g=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
Expand Down

0 comments on commit 5e8d5d7

Please sign in to comment.