From 1b626c4a1384a352d5929fc189f1fb37c00e9ab6 Mon Sep 17 00:00:00 2001 From: George MacRorie Date: Mon, 7 Nov 2022 09:58:39 +0000 Subject: [PATCH] feat(auth): bootstrapping process for first token (#1114) fix: ensure authentication store is always instantiated refactor(storage): rename query params Validate or Normalize chore(rpc/auth): prefix method enum values with METHOD_ chore(sql/testing): use wait.ForSQL during mysql testcontainer boot chore(storage): increase list limit from 10 to 25 feat(openapi): add Authorization header security requirements feat(openapi): add security requirements --- cmd/flipt/main.go | 5 +- internal/server/auth/method/token/server.go | 2 +- internal/server/auth/middleware_test.go | 2 +- internal/storage/auth/bootstrap.go | 4 +- internal/storage/auth/memory/store.go | 6 +- internal/storage/auth/sql/store.go | 5 +- internal/storage/auth/sql/store_test.go | 46 +++--- internal/storage/storage.go | 11 +- internal/storage/testing/testing.go | 4 +- rpc/flipt/auth/auth.pb.go | 93 ++++++----- rpc/flipt/auth/auth.proto | 33 +++- rpc/flipt/flipt.pb.go | 22 ++- rpc/flipt/flipt.proto | 27 +++ swagger/auth/auth.swagger.json | 24 ++- swagger/flipt.swagger.json | 174 ++++++++++++++++++++ 15 files changed, 361 insertions(+), 97 deletions(-) diff --git a/cmd/flipt/main.go b/cmd/flipt/main.go index 93d58806c9..9b29a97d3b 100644 --- a/cmd/flipt/main.go +++ b/cmd/flipt/main.go @@ -488,13 +488,10 @@ func run(ctx context.Context, logger *zap.Logger) error { otelgrpc.UnaryServerInterceptor(), } - // authentication interceptor - var authenticationStore storage.AuthenticationStore + authenticationStore := authsql.NewStore(driver, sql.BuilderFor(db, driver), logger) // only enable enforcement middleware if authentication required if cfg.Authentication.Required { - authenticationStore = authsql.NewStore(driver, sql.BuilderFor(db, driver), logger) - interceptors = append(interceptors, auth.UnaryInterceptor(logger, authenticationStore)) logger.Info("authentication middleware enabled") diff --git a/internal/server/auth/method/token/server.go b/internal/server/auth/method/token/server.go index a7c92d3bc4..1f40325118 100644 --- a/internal/server/auth/method/token/server.go +++ b/internal/server/auth/method/token/server.go @@ -39,7 +39,7 @@ func NewServer(logger *zap.Logger, store storage.AuthenticationStore) *Server { // Along with the created Authentication, which includes it's identifier and associated timestamps. func (s *Server) CreateToken(ctx context.Context, req *auth.CreateTokenRequest) (*auth.CreateTokenResponse, error) { clientToken, authentication, err := s.store.CreateAuthentication(ctx, &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: auth.Method_METHOD_TOKEN, ExpiresAt: req.ExpiresAt, Metadata: map[string]string{ storageMetadataNameKey: req.GetName(), diff --git a/internal/server/auth/middleware_test.go b/internal/server/auth/middleware_test.go index 304bf36e18..f04504b179 100644 --- a/internal/server/auth/middleware_test.go +++ b/internal/server/auth/middleware_test.go @@ -17,7 +17,7 @@ func TestUnaryInterceptor(t *testing.T) { authenticator := memory.NewStore() clientToken, storedAuth, err := authenticator.CreateAuthentication( context.TODO(), - &storage.CreateAuthenticationRequest{Method: authrpc.Method_TOKEN}, + &storage.CreateAuthenticationRequest{Method: authrpc.Method_METHOD_TOKEN}, ) require.NoError(t, err) diff --git a/internal/storage/auth/bootstrap.go b/internal/storage/auth/bootstrap.go index 36149a0f60..ca8f2b24af 100644 --- a/internal/storage/auth/bootstrap.go +++ b/internal/storage/auth/bootstrap.go @@ -11,7 +11,7 @@ import ( // Bootstrap creates an initial static authentication of type token // if one does not already exist. func Bootstrap(ctx context.Context, store storage.AuthenticationStore) (string, error) { - req := storage.NewListRequest(ListWithMethod(rpcauth.Method_TOKEN)) + req := storage.NewListRequest(ListWithMethod(rpcauth.Method_METHOD_TOKEN)) set, err := store.ListAuthentications(ctx, req) if err != nil { return "", fmt.Errorf("bootstrapping authentication store: %w", err) @@ -23,7 +23,7 @@ func Bootstrap(ctx context.Context, store storage.AuthenticationStore) (string, } clientToken, _, err := store.CreateAuthentication(ctx, &storage.CreateAuthenticationRequest{ - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "initial_bootstrap_token", "io.flipt.auth.token.description": "Initial token created when bootstrapping authentication", diff --git a/internal/storage/auth/memory/store.go b/internal/storage/auth/memory/store.go index 9e99e15395..372e6b873b 100644 --- a/internal/storage/auth/memory/store.go +++ b/internal/storage/auth/memory/store.go @@ -130,9 +130,9 @@ func (s *Store) GetAuthenticationByClientToken(ctx context.Context, clientToken func (s *Store) ListAuthentications(ctx context.Context, req *storage.ListRequest[storage.ListAuthenticationsPredicate]) (storage.ResultSet[*rpcauth.Authentication], error) { var set storage.ResultSet[*rpcauth.Authentication] - if err := req.QueryParams.Validate(); err != nil { - return set, fmt.Errorf("listing authentications: %w", err) - } + + // adjust the query parameters within normal bounds + req.QueryParams.Normalize() // copy all auths into slice s.mu.Lock() diff --git a/internal/storage/auth/sql/store.go b/internal/storage/auth/sql/store.go index 9ae6482471..59aa16c3a9 100644 --- a/internal/storage/auth/sql/store.go +++ b/internal/storage/auth/sql/store.go @@ -182,9 +182,8 @@ func (s *Store) ListAuthentications(ctx context.Context, req *storage.ListReques } }() - if err = req.QueryParams.Validate(); err != nil { - return - } + // adjust the query parameters within normal bounds + req.QueryParams.Normalize() query := s.builder. Select( diff --git a/internal/storage/auth/sql/store_test.go b/internal/storage/auth/sql/store_test.go index 8775a89868..f8c284b9ff 100644 --- a/internal/storage/auth/sql/store_test.go +++ b/internal/storage/auth/sql/store_test.go @@ -43,7 +43,7 @@ func TestAuthenticationStoreHarness(t *testing.T) { func TestAuthentication_CreateAuthentication(t *testing.T) { // established a store factory with a single seeded auth entry - storeFn := newTestStore(t, createAuth("create_auth_id", "create_auth_token", rpcauth.Method_TOKEN)) + storeFn := newTestStore(t, createAuth("create_auth_id", "create_auth_token", rpcauth.Method_METHOD_TOKEN)) ctx := context.TODO() for _, test := range []struct { @@ -58,7 +58,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { name: "successfully creates authentication", opts: commonOpts, req: &storage.CreateAuthenticationRequest{ - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -68,7 +68,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { expectedToken: "token:TestAuthentication_CreateAuthentication/successfully_creates_authentication", expectedAuthentication: &rpcauth.Authentication{ Id: "id:TestAuthentication_CreateAuthentication/successfully_creates_authentication", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", @@ -82,7 +82,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { name: "successfully creates authentication (no expiration)", opts: commonOpts, req: &storage.CreateAuthenticationRequest{ - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", @@ -91,7 +91,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { expectedToken: "token:TestAuthentication_CreateAuthentication/successfully_creates_authentication_(no_expiration)", expectedAuthentication: &rpcauth.Authentication{ Id: "id:TestAuthentication_CreateAuthentication/successfully_creates_authentication_(no_expiration)", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", @@ -111,7 +111,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { } }, req: &storage.CreateAuthenticationRequest{ - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -131,7 +131,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { } }, req: &storage.CreateAuthenticationRequest{ - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -163,7 +163,7 @@ func TestAuthentication_GetAuthenticationByClientToken(t *testing.T) { ctx := context.TODO() // established a store factory with a single seeded auth entry - storeFn := newTestStore(t, createAuth("get_auth_id", "get_auth_token", rpcauth.Method_TOKEN)) + storeFn := newTestStore(t, createAuth("get_auth_id", "get_auth_token", rpcauth.Method_METHOD_TOKEN)) // run table tests for _, test := range []struct { @@ -182,7 +182,7 @@ func TestAuthentication_GetAuthenticationByClientToken(t *testing.T) { clientToken: "get_auth_token", expectedAuthentication: &rpcauth.Authentication{ Id: "get_auth_id", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -225,17 +225,17 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { } storeFn := newTestStore(t, - createAuth("none_id_one", "none_client_token_one", rpcauth.Method_NONE, withOpts(seedOpts)), - createAuth("none_id_two", "none_client_token_two", rpcauth.Method_NONE, withOpts(seedOpts)), - createAuth("none_id_three", "none_client_token_three", rpcauth.Method_NONE, withOpts(seedOpts)), - createAuth("token_id_one", "token_client_token_one", rpcauth.Method_TOKEN, withOpts(seedOpts)), - createAuth("token_id_two", "token_client_token_two", rpcauth.Method_TOKEN, withOpts(seedOpts)), - createAuth("token_id_three", "token_client_token_three", rpcauth.Method_TOKEN, withOpts(seedOpts)), + createAuth("none_id_one", "none_client_token_one", rpcauth.Method_METHOD_NONE, withOpts(seedOpts)), + createAuth("none_id_two", "none_client_token_two", rpcauth.Method_METHOD_NONE, withOpts(seedOpts)), + createAuth("none_id_three", "none_client_token_three", rpcauth.Method_METHOD_NONE, withOpts(seedOpts)), + createAuth("token_id_one", "token_client_token_one", rpcauth.Method_METHOD_TOKEN, withOpts(seedOpts)), + createAuth("token_id_two", "token_client_token_two", rpcauth.Method_METHOD_TOKEN, withOpts(seedOpts)), + createAuth("token_id_three", "token_client_token_three", rpcauth.Method_METHOD_TOKEN, withOpts(seedOpts)), ) t.Run("method == none", func(t *testing.T) { // list predicated with none auth method - req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_NONE)) + req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_METHOD_NONE)) noneMethod, err := storeFn().ListAuthentications(ctx, req) require.NoError(t, err) @@ -243,7 +243,7 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { Results: []*rpcauth.Authentication{ { Id: "none_id_one", - Method: rpcauth.Method_NONE, + Method: rpcauth.Method_METHOD_NONE, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -254,7 +254,7 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { }, { Id: "none_id_two", - Method: rpcauth.Method_NONE, + Method: rpcauth.Method_METHOD_NONE, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -265,7 +265,7 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { }, { Id: "none_id_three", - Method: rpcauth.Method_NONE, + Method: rpcauth.Method_METHOD_NONE, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -280,14 +280,14 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { t.Run("method == token", func(t *testing.T) { // list predicated with token auth method - req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_TOKEN)) + req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_METHOD_TOKEN)) tokenMethod, err := storeFn().ListAuthentications(ctx, req) require.NoError(t, err) assert.Equal(t, storage.ResultSet[*rpcauth.Authentication]{ Results: []*rpcauth.Authentication{ { Id: "token_id_one", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -298,7 +298,7 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { }, { Id: "token_id_two", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -309,7 +309,7 @@ func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { }, { Id: "token_id_three", - Method: rpcauth.Method_TOKEN, + Method: rpcauth.Method_METHOD_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 72cdfbf818..5e3531211b 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -11,7 +11,7 @@ import ( const ( // DefaultListLimit is the default limit applied to any list operation page size when one is not provided. - DefaultListLimit uint64 = 10 + DefaultListLimit uint64 = 25 // MaxListLimit is the upper limit applied to any list operation page size. MaxListLimit uint64 = 100 @@ -54,16 +54,17 @@ type QueryParams struct { Order Order // not exposed to the user yet } -func (q *QueryParams) Validate() error { +// Normalize adjusts query parameters within the enforced boundaries. +// For example, limit is adjusted to be in the range (0, max]. +// Given the limit is not supplied (0) it is set to the default limit. +func (q *QueryParams) Normalize() { if q.Limit == 0 { q.Limit = DefaultListLimit } if q.Limit > MaxListLimit { - return fmt.Errorf("maximum page size limit (%d) exceeded: %d", MaxListLimit, q.Limit) + q.Limit = MaxListLimit } - - return nil } type QueryOption func(p *QueryParams) diff --git a/internal/storage/testing/testing.go b/internal/storage/testing/testing.go index 6675338905..538bd08d21 100644 --- a/internal/storage/testing/testing.go +++ b/internal/storage/testing/testing.go @@ -24,9 +24,9 @@ func TestAuthenticationStoreHarness(t *testing.T, fn func(t *testing.T) storage. ) t.Run(fmt.Sprintf("Create %d authentications", authCount), func(t *testing.T) { - for i := 0; i < 100; i++ { + for i := 0; i < authCount; i++ { token, auth, err := store.CreateAuthentication(ctx, &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: auth.Method_METHOD_TOKEN, Metadata: map[string]string{ "name": fmt.Sprintf("foo_%d", i), "description": "bar", diff --git a/rpc/flipt/auth/auth.pb.go b/rpc/flipt/auth/auth.pb.go index 6ed53de6ac..972806126c 100644 --- a/rpc/flipt/auth/auth.pb.go +++ b/rpc/flipt/auth/auth.pb.go @@ -25,19 +25,19 @@ const ( type Method int32 const ( - Method_NONE Method = 0 - Method_TOKEN Method = 1 + Method_METHOD_NONE Method = 0 + Method_METHOD_TOKEN Method = 1 ) // Enum value maps for Method. var ( Method_name = map[int32]string{ - 0: "NONE", - 1: "TOKEN", + 0: "METHOD_NONE", + 1: "METHOD_TOKEN", } Method_value = map[string]int32{ - "NONE": 0, - "TOKEN": 1, + "METHOD_NONE": 0, + "METHOD_TOKEN": 1, } ) @@ -124,7 +124,7 @@ func (x *Authentication) GetMethod() Method { if x != nil { return x.Method } - return Method_NONE + return Method_METHOD_NONE } func (x *Authentication) GetExpiresAt() *timestamppb.Timestamp { @@ -325,41 +325,52 @@ var file_auth_auth_proto_rawDesc = []byte{ 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2a, 0x1d, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x08, 0x0a, - 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x4f, 0x4b, 0x45, 0x4e, - 0x10, 0x01, 0x32, 0xc9, 0x01, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa4, 0x01, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1e, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, - 0x61, 0x75, 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, - 0x61, 0x75, 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x92, 0x41, 0x51, 0x0a, 0x2a, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0xaa, - 0x02, 0x5a, 0x20, 0x67, 0x6f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, - 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x61, - 0x75, 0x74, 0x68, 0x92, 0x41, 0x84, 0x02, 0x12, 0xb0, 0x01, 0x0a, 0x19, 0x46, 0x6c, 0x69, 0x70, - 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x50, 0x49, 0x73, 0x22, 0x3d, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x54, - 0x65, 0x61, 0x6d, 0x12, 0x21, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2d, 0x69, 0x6f, - 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x1a, 0x0c, 0x64, 0x65, 0x76, 0x40, 0x66, 0x6c, 0x69, 0x70, - 0x74, 0x2e, 0x69, 0x6f, 0x2a, 0x4c, 0x0a, 0x0b, 0x4d, 0x49, 0x54, 0x20, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2d, 0x69, 0x6f, - 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, - 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, - 0x53, 0x45, 0x32, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, + 0x69, 0x6f, 0x6e, 0x2a, 0x2b, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0f, 0x0a, + 0x0b, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x10, + 0x0a, 0x0c, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x10, 0x01, + 0x32, 0xc9, 0x01, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa4, 0x01, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1e, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x61, 0x75, + 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x61, 0x75, + 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x92, 0x41, 0x51, 0x0a, 0x2a, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x2a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0xd4, 0x03, 0x5a, + 0x20, 0x67, 0x6f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, 0x6c, 0x69, + 0x70, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x61, 0x75, 0x74, + 0x68, 0x92, 0x41, 0xae, 0x03, 0x12, 0xb0, 0x01, 0x0a, 0x19, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x50, 0x49, 0x73, 0x22, 0x3d, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x54, 0x65, 0x61, + 0x6d, 0x12, 0x21, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2d, 0x69, 0x6f, 0x2f, 0x66, + 0x6c, 0x69, 0x70, 0x74, 0x1a, 0x0c, 0x64, 0x65, 0x76, 0x40, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, + 0x69, 0x6f, 0x2a, 0x4c, 0x0a, 0x0b, 0x4d, 0x49, 0x54, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, + 0x65, 0x12, 0x3d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2d, 0x69, 0x6f, 0x2f, 0x66, + 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x72, + 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, + 0x32, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, - 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, - 0x6f, 0x6e, 0x72, 0x27, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x44, 0x6f, 0x63, 0x73, - 0x12, 0x19, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x66, 0x6c, - 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x64, 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x52, 0x63, 0x0a, 0x03, 0x34, 0x30, 0x31, 0x12, 0x5c, 0x0a, 0x3d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x28, 0x61, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x29, 0x2e, 0x12, 0x1b, 0x0a, 0x19, 0x1a, 0x17, 0x23, 0x2f, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x70, 0x63, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x5a, 0x2a, 0x0a, 0x28, 0x0a, 0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x13, 0x08, 0x02, + 0x1a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x02, 0x62, 0x17, 0x0a, 0x15, 0x0a, 0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x00, 0x72, 0x27, 0x0a, 0x0a, 0x46, 0x6c, + 0x69, 0x70, 0x74, 0x20, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x19, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x64, + 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/flipt/auth/auth.proto b/rpc/flipt/auth/auth.proto index 65b941e939..739ee9d585 100644 --- a/rpc/flipt/auth/auth.proto +++ b/rpc/flipt/auth/auth.proto @@ -24,16 +24,43 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { external_docs: { url: "https://www.flipt.io/docs"; description: "Flipt Docs"; - } + }; schemes: HTTP; schemes: HTTPS; consumes: "application/json"; produces: "application/json"; + security_definitions: { + security: { + key: "ClientTokenBearer"; + value: { + type: TYPE_API_KEY; + in: IN_HEADER; + name: "Authorization"; + } + } + }; + security: { + security_requirement: { + key: "ClientTokenBearer"; + value: {}; + } + }; + responses: { + key: "401"; + value: { + description: "Request could not be authenticated (authentication required)."; + schema: { + json_schema: { + ref: "#/definitions/rpcStatus"; + }; + }; + }; + }; }; enum Method { - NONE = 0; - TOKEN = 1; + METHOD_NONE = 0; + METHOD_TOKEN = 1; } message Authentication { diff --git a/rpc/flipt/flipt.pb.go b/rpc/flipt/flipt.pb.go index 5205730ffe..2cc7e52933 100644 --- a/rpc/flipt/flipt.pb.go +++ b/rpc/flipt/flipt.pb.go @@ -3520,10 +3520,10 @@ var file_flipt_proto_rawDesc = []byte{ 0x6d, 0x70, 0x74, 0x79, 0x22, 0x35, 0x92, 0x41, 0x32, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x2a, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x42, 0x9b, 0x02, 0x5a, 0x21, + 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x42, 0xc5, 0x03, 0x5a, 0x21, 0x67, 0x6f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x66, 0x6c, 0x69, 0x70, - 0x74, 0x92, 0x41, 0xf4, 0x01, 0x12, 0xa0, 0x01, 0x0a, 0x09, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, + 0x74, 0x92, 0x41, 0x9e, 0x03, 0x12, 0xa0, 0x01, 0x0a, 0x09, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x41, 0x50, 0x49, 0x22, 0x3d, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x21, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2d, 0x69, 0x6f, 0x2f, 0x66, @@ -3536,10 +3536,20 @@ var file_flipt_proto_rawDesc = []byte{ 0x32, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, - 0x72, 0x27, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x70, 0x74, 0x20, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x19, - 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x70, - 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x64, 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x52, 0x63, 0x0a, 0x03, 0x34, 0x30, 0x31, 0x12, 0x5c, 0x0a, 0x3d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x28, 0x61, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x29, 0x2e, 0x12, 0x1b, 0x0a, 0x19, 0x1a, 0x17, 0x23, 0x2f, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x70, 0x63, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x5a, 0x2a, 0x0a, 0x28, 0x0a, 0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x13, 0x08, 0x02, + 0x1a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x02, 0x62, 0x17, 0x0a, 0x15, 0x0a, 0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x00, 0x72, 0x27, 0x0a, 0x0a, 0x46, 0x6c, + 0x69, 0x70, 0x74, 0x20, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x19, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x64, + 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/flipt/flipt.proto b/rpc/flipt/flipt.proto index d7b04c72bb..17c7a6666e 100644 --- a/rpc/flipt/flipt.proto +++ b/rpc/flipt/flipt.proto @@ -30,6 +30,33 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { schemes: HTTPS; consumes: "application/json"; produces: "application/json"; + security_definitions: { + security: { + key: "ClientTokenBearer"; + value: { + type: TYPE_API_KEY; + in: IN_HEADER; + name: "Authorization"; + } + } + }; + security: { + security_requirement: { + key: "ClientTokenBearer"; + value: {}; + } + }; + responses: { + key: "401"; + value: { + description: "Request could not be authenticated (authentication required)."; + schema: { + json_schema: { + ref: "#/definitions/rpcStatus"; + }; + }; + }; + }; }; message EvaluationRequest { diff --git a/swagger/auth/auth.swagger.json b/swagger/auth/auth.swagger.json index 39ef1ad9cd..a5d0861b43 100644 --- a/swagger/auth/auth.swagger.json +++ b/swagger/auth/auth.swagger.json @@ -40,6 +40,12 @@ "$ref": "#/definitions/authCreateTokenResponse" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -126,10 +132,10 @@ "authMethod": { "type": "string", "enum": [ - "NONE", - "TOKEN" + "METHOD_NONE", + "METHOD_TOKEN" ], - "default": "NONE" + "default": "METHOD_NONE" }, "protobufAny": { "type": "object", @@ -159,6 +165,18 @@ } } }, + "securityDefinitions": { + "ClientTokenBearer": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "security": [ + { + "ClientTokenBearer": [] + } + ], "externalDocs": { "description": "Flipt Docs", "url": "https://www.flipt.io/docs" diff --git a/swagger/flipt.swagger.json b/swagger/flipt.swagger.json index ba1abb447b..902eceed4b 100644 --- a/swagger/flipt.swagger.json +++ b/swagger/flipt.swagger.json @@ -40,6 +40,12 @@ "$ref": "#/definitions/fliptBatchEvaluationResponse" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -73,6 +79,12 @@ "$ref": "#/definitions/fliptEvaluationResponse" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -106,6 +118,12 @@ "$ref": "#/definitions/fliptFlagList" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -149,6 +167,12 @@ "$ref": "#/definitions/fliptFlag" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -182,6 +206,12 @@ "$ref": "#/definitions/fliptRuleList" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -231,6 +261,12 @@ "$ref": "#/definitions/fliptRule" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -284,6 +320,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -334,6 +376,12 @@ "$ref": "#/definitions/fliptRule" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -370,6 +418,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -405,6 +459,12 @@ "$ref": "#/definitions/fliptRule" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -458,6 +518,12 @@ "$ref": "#/definitions/fliptDistribution" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -517,6 +583,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -564,6 +636,12 @@ "$ref": "#/definitions/fliptDistribution" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -628,6 +706,12 @@ "$ref": "#/definitions/fliptVariant" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -685,6 +769,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -720,6 +810,12 @@ "$ref": "#/definitions/fliptVariant" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -782,6 +878,12 @@ "$ref": "#/definitions/fliptFlag" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -812,6 +914,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -841,6 +949,12 @@ "$ref": "#/definitions/fliptFlag" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -894,6 +1008,12 @@ "$ref": "#/definitions/fliptSegmentList" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -937,6 +1057,12 @@ "$ref": "#/definitions/fliptSegment" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -970,6 +1096,12 @@ "$ref": "#/definitions/fliptSegment" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1000,6 +1132,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1029,6 +1167,12 @@ "$ref": "#/definitions/fliptSegment" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1082,6 +1226,12 @@ "$ref": "#/definitions/fliptConstraint" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1141,6 +1291,12 @@ "properties": {} } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1176,6 +1332,12 @@ "$ref": "#/definitions/fliptConstraint" } }, + "401": { + "description": "Request could not be authenticated (authentication required).", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + }, "default": { "description": "An unexpected error response.", "schema": { @@ -1671,6 +1833,18 @@ } } }, + "securityDefinitions": { + "ClientTokenBearer": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "security": [ + { + "ClientTokenBearer": [] + } + ], "externalDocs": { "description": "Flipt Docs", "url": "https://www.flipt.io/docs"