Skip to content

Commit

Permalink
feat(metadata): authenticate /meta endpoints (#1250)
Browse files Browse the repository at this point in the history
* feat(metadata): authenticate /meta endpoints

* refactor(metadata): simplify marshal json

* fix(test): update meta endpoints to require authenticated
  • Loading branch information
GeorgeMac committed Jan 3, 2023
1 parent d00b9aa commit b3fc4b1
Show file tree
Hide file tree
Showing 12 changed files with 661 additions and 12 deletions.
2 changes: 1 addition & 1 deletion cmd/flipt/main.go
Expand Up @@ -328,7 +328,7 @@ func run(ctx context.Context, logger *zap.Logger) error {

migrator.Close()

grpcServer, err := cmd.NewGRPCServer(ctx, logger, cfg)
grpcServer, err := cmd.NewGRPCServer(ctx, logger, cfg, info)
if err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions internal/cmd/grpc.go
Expand Up @@ -9,10 +9,12 @@ import (
"time"

"go.flipt.io/flipt/internal/config"
"go.flipt.io/flipt/internal/info"
fliptserver "go.flipt.io/flipt/internal/server"
"go.flipt.io/flipt/internal/server/cache"
"go.flipt.io/flipt/internal/server/cache/memory"
"go.flipt.io/flipt/internal/server/cache/redis"
"go.flipt.io/flipt/internal/server/metadata"
middlewaregrpc "go.flipt.io/flipt/internal/server/middleware/grpc"
"go.flipt.io/flipt/internal/storage"
authsql "go.flipt.io/flipt/internal/storage/auth/sql"
Expand Down Expand Up @@ -81,6 +83,7 @@ func NewGRPCServer(
ctx context.Context,
logger *zap.Logger,
cfg *config.Config,
info info.Flipt,
) (*GRPCServer, error) {
logger = logger.With(zap.String("server", "grpc"))
server := &GRPCServer{
Expand Down Expand Up @@ -245,6 +248,7 @@ func NewGRPCServer(

// initialize server
register.Add(fliptserver.New(logger, store))
register.Add(metadata.NewServer(cfg, info))

// initialize grpc server
server.Server = grpc.NewServer(grpcOpts...)
Expand Down
17 changes: 12 additions & 5 deletions internal/cmd/http.go
Expand Up @@ -14,11 +14,13 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.flipt.io/flipt/internal/config"
"go.flipt.io/flipt/internal/gateway"
"go.flipt.io/flipt/internal/info"
"go.flipt.io/flipt/rpc/flipt"
"go.flipt.io/flipt/rpc/flipt/meta"
"go.flipt.io/flipt/ui"
"go.uber.org/zap"
"google.golang.org/grpc"
Expand Down Expand Up @@ -101,11 +103,16 @@ func NewHTTPServer(
// to the chi router.
authenticationHTTPMount(ctx, cfg.Authentication, r, conn)

r.Route("/meta", func(r chi.Router) {
r.Use(middleware.SetHeader("Content-Type", "application/json"))
r.Handle("/info", info)
r.Handle("/config", cfg)
})
// mount the metadata service to the chi router under /meta.
r.Mount("/meta", runtime.NewServeMux(
runtime.WithMarshalerOption("application/json", &runtime.HTTPBodyMarshaler{}),
runtime.WithMarshalerOption("application/json+pretty", &runtime.HTTPBodyMarshaler{}),
registerFunc(
ctx,
conn,
meta.RegisterMetadataServiceHandler,
),
))

if cfg.UI.Enabled {
u, err := fs.Sub(ui.UI, "dist")
Expand Down
68 changes: 68 additions & 0 deletions internal/server/metadata/server.go
@@ -0,0 +1,68 @@
package metadata

import (
"context"
"encoding/json"

"go.flipt.io/flipt/internal/config"
"go.flipt.io/flipt/internal/info"
"go.flipt.io/flipt/rpc/flipt/meta"
"google.golang.org/genproto/googleapis/api/httpbody"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/types/known/emptypb"
)

type Server struct {
cfg *config.Config
info info.Flipt

meta.UnimplementedMetadataServiceServer
}

func NewServer(cfg *config.Config, info info.Flipt) *Server {
return &Server{
cfg: cfg,
info: info,
}
}

// RegisterGRPC registers the server on the provided gRPC server instance.
func (s *Server) RegisterGRPC(server *grpc.Server) {
meta.RegisterMetadataServiceServer(server, s)
}

// GetConfiguration returns a HttpBody instance containing the Flipt instance's
// configuration structure marshalled as JSON.
func (s *Server) GetConfiguration(ctx context.Context, _ *emptypb.Empty) (*httpbody.HttpBody, error) {
return response(ctx, s.cfg)
}

// GetInfo returns a HttpBody instance containing the Flipt instance's
// runtime information marshalled as JSON.
func (s *Server) GetInfo(ctx context.Context, _ *emptypb.Empty) (*httpbody.HttpBody, error) {
return response(ctx, s.info)
}

func response(ctx context.Context, v any) (*httpbody.HttpBody, error) {
data, err := marshal(ctx, v)
if err != nil {
return nil, err
}

return &httpbody.HttpBody{
ContentType: "application/json",
Data: data,
}, nil
}

func marshal(ctx context.Context, v any) ([]byte, error) {
if md, ok := metadata.FromIncomingContext(ctx); ok {
accept := md.Get("grpcgateway-accept")
if len(accept) > 0 && accept[0] == "application/json+pretty" {
return json.MarshalIndent(v, "", " ")
}
}

return json.Marshal(v)
}
4 changes: 2 additions & 2 deletions rpc/flipt/auth/auth.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions rpc/flipt/flipt.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions rpc/flipt/flipt.yaml
Expand Up @@ -73,6 +73,11 @@ http:
body: "*"
- selector: flipt.Flipt.DeleteConstraint
delete: /api/v1/segments/{segment_key}/constraints/{id}
# metadata
- selector: flipt.meta.MetadataService.GetConfiguration
get: /meta/config
- selector: flipt.meta.MetadataService.GetInfo
get: /meta/info
# authentication public routes
- selector: flipt.auth.PublicAuthenticationService.ListAuthenticationMethods
get: /auth/v1/method
Expand Down
123 changes: 123 additions & 0 deletions rpc/flipt/meta/meta.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b3fc4b1

Please sign in to comment.