Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

relay-proxy: Support API Keys validation to limit the applications being able to use GO Feature Flag #649

Merged
merged 10 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/relayproxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Before starting your **relay proxy** you will need to create a minimal configura
# this is a minimal config containing only where your flag file is located
retriever:
kind: http
url: https://raw.githubusercontent.com/thomaspoignant/go-feature-flag/main/examples/file/flags.yaml
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalid url

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch 👍

url: https://raw.githubusercontent.com/thomaspoignant/go-feature-flag/main/examples/retriever_file/flags.yaml
```

After that you can launch the **relay proxy** by using this command:
Expand Down Expand Up @@ -77,12 +77,12 @@ But if you don't provide this option, the relay proxy will look in these folders
- `/goff/`
- `/etc/opt/goff/`

To learn how to configure the relay proxy, read [Configuration](docs/configuration.md).
To learn how to configure the relay proxy, read [Configuration](https://gofeatureflag.org/docs/relay_proxy/configure_relay_proxy).

## Exporting metrics and traces

To export the data you can use all the capabilities of `go-feature-flag` SDK.
To configure it please refer to the [type `exporter` section](docs/configuration.md#exporter) of the configuration.
To configure it please refer to the [type `exporter` section](https://gofeatureflag.org/docs/relay_proxy/configure_relay_proxy#exporter) of the configuration.


## Service endpoints
Expand Down
25 changes: 23 additions & 2 deletions cmd/relayproxy/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ package api

import (
"fmt"
"github.com/labstack/echo-contrib/prometheus"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"strings"
"time"

"github.com/brpaz/echozap"
"github.com/labstack/echo-contrib/prometheus"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
echoSwagger "github.com/swaggo/echo-swagger"
ffclient "github.com/thomaspoignant/go-feature-flag"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/config"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/controller"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/service"
"go.uber.org/zap"
)
Expand Down Expand Up @@ -61,6 +62,26 @@ func (s *Server) init() {
s.echoInstance.Use(middleware.TimeoutWithConfig(
middleware.TimeoutConfig{Timeout: time.Duration(s.config.RestAPITimeout) * time.Millisecond}),
)
if len(s.config.APIKeys) > 0 {
s.echoInstance.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
Skipper: func(c echo.Context) bool {
_, ok := map[string]struct{}{
"/health": {},
"/info": {},
"/metrics": {},
}[c.Path()]
return ok || strings.HasPrefix(c.Path(), "/swagger/")
},
Validator: func(key string, c echo.Context) (bool, error) {
for _, k := range s.config.APIKeys {
if k == key {
return true, nil
}
}
return false, nil
},
}))
}

// Init controllers
cHealth := controller.NewHealth(s.monitoringService)
Expand Down
10 changes: 7 additions & 3 deletions cmd/relayproxy/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package config

import (
"fmt"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"go.uber.org/zap"
"net/http"
"strings"
"time"

"github.com/spf13/pflag"
"github.com/spf13/viper"
"go.uber.org/zap"
)

var DefaultRetriever = struct {
Expand Down Expand Up @@ -137,6 +138,9 @@ type Config struct {

// Version is the version of the relay-proxy
Version string

// APIKeys list of API keys that authorized to use endpoints
APIKeys []string `mapstructure:"apiKeys"`
}

// IsValid contains all the validation of the configuration.
Expand Down
8 changes: 8 additions & 0 deletions cmd/relayproxy/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ func TestParseConfig_fileFromPflag(t *testing.T) {
RestAPITimeout: 5000,
Version: "1.X.X",
EnableSwagger: true,
APIKeys: []string{
"apikey1",
"apikey2",
},
},
wantErr: assert.NoError,
},
Expand Down Expand Up @@ -104,6 +108,10 @@ func TestParseConfig_fileFromFolder(t *testing.T) {
RestAPITimeout: 5000,
Version: "1.X.X",
EnableSwagger: true,
APIKeys: []string{
"apikey1",
"apikey2",
},
},
wantErr: assert.NoError,
},
Expand Down
3 changes: 2 additions & 1 deletion cmd/relayproxy/controller/all_flags.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package controller

import (
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"net/http"

"github.com/labstack/echo/v4"
ffclient "github.com/thomaspoignant/go-feature-flag"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/model"
)

Expand All @@ -26,6 +26,7 @@ func NewAllFlags(goFF *ffclient.GoFeatureFlag) Controller {
// @Description
// @Description To get a variation you should provide information about the user.
// @Description For that you should provide some user information in JSON in the request body.
// @Security ApiKeyAuth
// @Produce json
// @Accept json
// @Param data body model.AllFlagRequest true "Payload of the user we want to challenge against the flag."
Expand Down
4 changes: 3 additions & 1 deletion cmd/relayproxy/controller/collect_eval_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package controller

import (
"fmt"
"net/http"

"github.com/labstack/echo/v4"
ffclient "github.com/thomaspoignant/go-feature-flag"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/model"
"net/http"
)

type collectEvalData struct {
Expand All @@ -26,6 +27,7 @@ func NewCollectEvalData(goFF *ffclient.GoFeatureFlag) Controller {
// @Description
// @Description It is used by the different Open Feature providers to send in bulk all the cached events to avoid
// @Description to lose track of what happen when a cached flag is used.
// @Security ApiKeyAuth
// @Produce json
// @Accept json
// @Param data body model.CollectEvalDataRequest true "List of flag evaluation that be passed to the data exporter"
Expand Down
3 changes: 2 additions & 1 deletion cmd/relayproxy/controller/flag_eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package controller

import (
"fmt"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"net/http"

"github.com/labstack/echo/v4"
ffclient "github.com/thomaspoignant/go-feature-flag"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/model"
)

Expand All @@ -32,6 +32,7 @@ func NewFlagEval(goFF *ffclient.GoFeatureFlag) Controller {
// @Description Note that you will always have a usable value in the response, you can use the field `failed` to know if
// @Description an issue has occurred during the validation of the flag, in that case the value returned will be the
// @Description default value.
// @Security ApiKeyAuth
// @Produce json
// @Accept json
// @Param data body model.EvalFlagRequest true "Payload of the user we want to get all the flags from."
Expand Down
6 changes: 0 additions & 6 deletions cmd/relayproxy/docs/api.md

This file was deleted.

Loading