mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] [Gateway] ArangoDB AuthIntegration (#1715)
This commit is contained in:
parent
81dfd87566
commit
fb2ac883ae
36 changed files with 792 additions and 47 deletions
|
@ -23,6 +23,7 @@
|
|||
- (Feature) Integration Service TLS
|
||||
- (Feature) (Gateway) SNI and Authz support
|
||||
- (Maintenance) Bump Examples to ArangoDB 3.12
|
||||
- (Feature) (Gateway) ArangoDB JWT Auth Integration
|
||||
|
||||
## [1.2.42](https://github.com/arangodb/kube-arangodb/tree/1.2.42) (2024-07-23)
|
||||
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -21,8 +21,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/version"
|
||||
|
@ -38,6 +36,5 @@ var cmdVersion = &cobra.Command{
|
|||
}
|
||||
|
||||
func versionRun(cmd *cobra.Command, args []string) {
|
||||
v := version.GetVersionV1()
|
||||
println(fmt.Sprintf("Version: %s %s, Build: %s, Go: %s, Build Date: %s", v.Edition.Title(), v.Version, v.Build, v.GoVersion, v.BuildDate))
|
||||
println(version.GetVersionV1().String())
|
||||
}
|
||||
|
|
|
@ -16,6 +16,12 @@ Deployment specifies the ArangoDeployment object name
|
|||
|
||||
***
|
||||
|
||||
### .spec.destination.authentication.type
|
||||
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_spec_destination_authentication.go#L28)</sup>
|
||||
|
||||
***
|
||||
|
||||
### .spec.destination.path
|
||||
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_spec_destination.go#L36)</sup>
|
||||
|
@ -131,6 +137,12 @@ UID keeps the information about object UID
|
|||
|
||||
***
|
||||
|
||||
### .status.target.authentication.type
|
||||
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_status_target_authentication.go#L26)</sup>
|
||||
|
||||
***
|
||||
|
||||
### .status.target.destinations\[int\].host
|
||||
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_status_target_destination.go#L38)</sup>
|
||||
|
@ -145,7 +157,7 @@ Type: `integer` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.
|
|||
|
||||
### .status.target.path
|
||||
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_status_target.go#L37)</sup>
|
||||
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.42/pkg/apis/networking/v1alpha1/route_status_target.go#L40)</sup>
|
||||
|
||||
Path specifies request path override
|
||||
|
||||
|
|
46
integrations/envoy/auth/v3/check.go
Normal file
46
integrations/envoy/auth/v3/check.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
)
|
||||
|
||||
type AuthResponse struct {
|
||||
Username string
|
||||
}
|
||||
|
||||
type AuthRequestFunc func(ctx context.Context, request *pbEnvoyAuthV3.CheckRequest, current *AuthResponse) (*AuthResponse, error)
|
||||
|
||||
func MergeAuthRequest(ctx context.Context, request *pbEnvoyAuthV3.CheckRequest, requests ...AuthRequestFunc) (*AuthResponse, error) {
|
||||
var resp *AuthResponse
|
||||
for _, r := range requests {
|
||||
if v, err := r(ctx, request, resp); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
resp = v
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
60
integrations/envoy/auth/v3/check_adb_jwt.go
Normal file
60
integrations/envoy/auth/v3/check_adb_jwt.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
|
||||
pbAuthenticationV1 "github.com/arangodb/kube-arangodb/integrations/authentication/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/strings"
|
||||
)
|
||||
|
||||
func (i *impl) checkADBJWT(ctx context.Context, request *pbEnvoyAuthV3.CheckRequest, current *AuthResponse) (*AuthResponse, error) {
|
||||
if current != nil {
|
||||
// Already authenticated
|
||||
return current, nil
|
||||
}
|
||||
if auth, ok := request.GetAttributes().GetRequest().GetHttp().GetHeaders()["authorization"]; ok {
|
||||
parts := strings.SplitN(auth, " ", 2)
|
||||
if len(parts) == 2 {
|
||||
if strings.ToLower(parts[0]) == "bearer" {
|
||||
resp, err := i.authClient.Validate(ctx, &pbAuthenticationV1.ValidateRequest{
|
||||
Token: parts[1],
|
||||
})
|
||||
if err != nil {
|
||||
logger.Err(err).Warn("Auth failure")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err == nil && resp.GetIsValid() {
|
||||
// All went fine!
|
||||
return &AuthResponse{
|
||||
Username: resp.GetDetails().GetUser(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
|
@ -22,4 +22,18 @@ package v3
|
|||
|
||||
const (
|
||||
Name = "envoy.auth.v3"
|
||||
|
||||
AuthConfigKeywordTrue = "true"
|
||||
AuthConfigKeywordFalse = "false"
|
||||
|
||||
AuthConfigNamespace = "platform.arangodb.com"
|
||||
AuthConfigAuthNamespace = "auth." + AuthConfigNamespace
|
||||
|
||||
AuthConfigTypeKey = AuthConfigNamespace + "/type"
|
||||
AuthConfigTypeValue = "ArangoDBPlatform"
|
||||
|
||||
AuthConfigAuthRequiredKey = AuthConfigAuthNamespace + "/required"
|
||||
|
||||
AuthUsernameHeader = "arangodb-platform-user"
|
||||
AuthAuthenticatedHeader = "arangodb-platform-authenticated"
|
||||
)
|
||||
|
|
|
@ -22,15 +22,23 @@ package v3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
pbAuthenticationV1 "github.com/arangodb/kube-arangodb/integrations/authentication/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors/panics"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
func New() svc.Handler {
|
||||
return &impl{}
|
||||
func New(authClient pbAuthenticationV1.AuthenticationV1Client) svc.Handler {
|
||||
return &impl{
|
||||
authClient: authClient,
|
||||
}
|
||||
}
|
||||
|
||||
var _ pbEnvoyAuthV3.AuthorizationServer = &impl{}
|
||||
|
@ -38,6 +46,8 @@ var _ svc.Handler = &impl{}
|
|||
|
||||
type impl struct {
|
||||
pbEnvoyAuthV3.UnimplementedAuthorizationServer
|
||||
|
||||
authClient pbAuthenticationV1.AuthenticationV1Client
|
||||
}
|
||||
|
||||
func (i *impl) Name() string {
|
||||
|
@ -53,10 +63,84 @@ func (i *impl) Register(registrar *grpc.Server) {
|
|||
}
|
||||
|
||||
func (i *impl) Check(ctx context.Context, request *pbEnvoyAuthV3.CheckRequest) (*pbEnvoyAuthV3.CheckResponse, error) {
|
||||
logger.Info("Request Received")
|
||||
resp, err := panics.RecoverO1(func() (*pbEnvoyAuthV3.CheckResponse, error) {
|
||||
return i.check(ctx, request)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
var v DeniedResponse
|
||||
if errors.As(err, &v) {
|
||||
return v.GetCheckResponse()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (i *impl) check(ctx context.Context, request *pbEnvoyAuthV3.CheckRequest) (*pbEnvoyAuthV3.CheckResponse, error) {
|
||||
ext := request.GetAttributes().GetContextExtensions()
|
||||
|
||||
if v, ok := ext[AuthConfigTypeKey]; !ok || v != AuthConfigTypeValue {
|
||||
return nil, DeniedResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: &DeniedMessage{
|
||||
Message: "Auth plugin is not enabled for this request",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
authenticated, err := MergeAuthRequest(ctx, request, i.checkADBJWT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if util.Optional(ext, AuthConfigAuthRequiredKey, AuthConfigKeywordFalse) == AuthConfigKeywordTrue && authenticated == nil {
|
||||
return nil, DeniedResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
Message: &DeniedMessage{
|
||||
Message: "Unauthorized",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if authenticated != nil {
|
||||
return &pbEnvoyAuthV3.CheckResponse{
|
||||
HttpResponse: &pbEnvoyAuthV3.CheckResponse_OkResponse{
|
||||
OkResponse: &pbEnvoyAuthV3.OkHttpResponse{},
|
||||
OkResponse: &pbEnvoyAuthV3.OkHttpResponse{
|
||||
Headers: []*corev3.HeaderValueOption{
|
||||
{
|
||||
Header: &corev3.HeaderValue{
|
||||
Key: AuthUsernameHeader,
|
||||
Value: authenticated.Username,
|
||||
},
|
||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||
},
|
||||
{
|
||||
Header: &corev3.HeaderValue{
|
||||
Key: AuthAuthenticatedHeader,
|
||||
Value: "true",
|
||||
},
|
||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pbEnvoyAuthV3.CheckResponse{
|
||||
HttpResponse: &pbEnvoyAuthV3.CheckResponse_OkResponse{
|
||||
OkResponse: &pbEnvoyAuthV3.OkHttpResponse{
|
||||
Headers: []*corev3.HeaderValueOption{
|
||||
{
|
||||
Header: &corev3.HeaderValue{
|
||||
Key: AuthAuthenticatedHeader,
|
||||
Value: "false",
|
||||
},
|
||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
85
integrations/envoy/auth/v3/response.go
Normal file
85
integrations/envoy/auth/v3/response.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||
status "google.golang.org/genproto/googleapis/rpc/status"
|
||||
)
|
||||
|
||||
type DeniedMessage struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type DeniedResponse struct {
|
||||
Code int32
|
||||
Headers map[string]string
|
||||
Message *DeniedMessage
|
||||
}
|
||||
|
||||
func (d DeniedResponse) Error() string {
|
||||
return fmt.Sprintf("Request denied with code: %d", d.Code)
|
||||
}
|
||||
|
||||
func (d DeniedResponse) GetCheckResponse() (*pbEnvoyAuthV3.CheckResponse, error) {
|
||||
var resp pbEnvoyAuthV3.DeniedHttpResponse
|
||||
|
||||
for k, v := range d.Headers {
|
||||
resp.Headers = append(resp.Headers, &corev3.HeaderValueOption{
|
||||
Header: &corev3.HeaderValue{
|
||||
Key: k,
|
||||
Value: v,
|
||||
},
|
||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||
})
|
||||
}
|
||||
|
||||
if data := d.Message; data != nil {
|
||||
z, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Body = string(z)
|
||||
resp.Headers = append(resp.Headers, &corev3.HeaderValueOption{
|
||||
Header: &corev3.HeaderValue{
|
||||
Key: "content/type",
|
||||
Value: "application/json",
|
||||
},
|
||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||
})
|
||||
}
|
||||
|
||||
resp.Status = &typev3.HttpStatus{
|
||||
Code: typev3.StatusCode(d.Code),
|
||||
}
|
||||
|
||||
return &pbEnvoyAuthV3.CheckResponse{
|
||||
HttpResponse: &pbEnvoyAuthV3.CheckResponse_DeniedResponse{DeniedResponse: &resp},
|
||||
Status: &status.Status{
|
||||
Code: d.Code,
|
||||
}}, nil
|
||||
}
|
|
@ -22,6 +22,7 @@ package v3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||
|
@ -35,7 +36,7 @@ import (
|
|||
func Client(t *testing.T, ctx context.Context) pbEnvoyAuthV3.AuthorizationClient {
|
||||
local := svc.NewService(svc.Configuration{
|
||||
Address: "127.0.0.1:0",
|
||||
}, New())
|
||||
}, New(nil))
|
||||
|
||||
start := local.Start(ctx)
|
||||
|
||||
|
@ -44,7 +45,7 @@ func Client(t *testing.T, ctx context.Context) pbEnvoyAuthV3.AuthorizationClient
|
|||
return client
|
||||
}
|
||||
|
||||
func Test_AllowAll(t *testing.T) {
|
||||
func Test_DenyHeader(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
|
@ -53,8 +54,28 @@ func Test_AllowAll(t *testing.T) {
|
|||
resp, err := client.Check(ctx, &pbEnvoyAuthV3.CheckRequest{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Validate())
|
||||
require.NotNil(t, resp.Status)
|
||||
require.NotNil(t, resp.HttpResponse)
|
||||
require.NotNil(t, tests.CastAs[*pbEnvoyAuthV3.CheckResponse_DeniedResponse](t, resp.GetHttpResponse()).DeniedResponse)
|
||||
require.EqualValues(t, http.StatusBadRequest, tests.CastAs[*pbEnvoyAuthV3.CheckResponse_DeniedResponse](t, resp.GetHttpResponse()).DeniedResponse.GetStatus().GetCode())
|
||||
}
|
||||
|
||||
func Test_AllowAll(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
client := Client(t, ctx)
|
||||
|
||||
resp, err := client.Check(ctx, &pbEnvoyAuthV3.CheckRequest{
|
||||
Attributes: &pbEnvoyAuthV3.AttributeContext{
|
||||
ContextExtensions: map[string]string{
|
||||
AuthConfigTypeKey: AuthConfigTypeValue,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Validate())
|
||||
require.Nil(t, resp.Status)
|
||||
require.NotNil(t, resp.HttpResponse)
|
||||
require.NotNil(t, tests.CastAs[*pbEnvoyAuthV3.CheckResponse_OkResponse](t, resp.GetHttpResponse()).OkResponse)
|
||||
require.Nil(t, resp.DynamicMetadata)
|
||||
}
|
||||
|
|
62
pkg/apis/networking/v1alpha1/route_spec_authentication.go
Normal file
62
pkg/apis/networking/v1alpha1/route_spec_authentication.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
)
|
||||
|
||||
type ArangoRouteSpecAuthenticationType string
|
||||
|
||||
const (
|
||||
ArangoRouteSpecAuthenticationTypeRequired ArangoRouteSpecAuthenticationType = "required"
|
||||
ArangoRouteSpecAuthenticationTypeOptional ArangoRouteSpecAuthenticationType = "optional"
|
||||
)
|
||||
|
||||
func (a *ArangoRouteSpecAuthenticationType) Get() ArangoRouteSpecAuthenticationType {
|
||||
if a == nil {
|
||||
return ArangoRouteSpecAuthenticationTypeOptional
|
||||
}
|
||||
switch v := *a; v {
|
||||
case ArangoRouteSpecAuthenticationTypeOptional, ArangoRouteSpecAuthenticationTypeRequired:
|
||||
return v
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecAuthenticationType) Validate() error {
|
||||
switch v := a.Get(); v {
|
||||
case ArangoRouteSpecAuthenticationTypeOptional, ArangoRouteSpecAuthenticationTypeRequired:
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("Invalid AuthType: %s", v)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecAuthenticationType) Hash() string {
|
||||
if a == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return util.SHA256FromString(string(*a))
|
||||
}
|
|
@ -34,6 +34,9 @@ type ArangoRouteSpecDestination struct {
|
|||
|
||||
// Path defines service path used for overrides
|
||||
Path *string `json:"path,omitempty"`
|
||||
|
||||
// Authentication defines auth methods
|
||||
Authentication *ArangoRouteSpecDestinationAuthentication `json:"authentication,omitempty"`
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecDestination) GetService() *ArangoRouteSpecDestinationService {
|
||||
|
@ -68,6 +71,14 @@ func (a *ArangoRouteSpecDestination) GetTLS() *ArangoRouteSpecDestinationTLS {
|
|||
return a.TLS
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecDestination) GetAuthentication() *ArangoRouteSpecDestinationAuthentication {
|
||||
if a == nil || a.Authentication == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return a.Authentication
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecDestination) Validate() error {
|
||||
if a == nil {
|
||||
a = &ArangoRouteSpecDestination{}
|
||||
|
@ -77,6 +88,7 @@ func (a *ArangoRouteSpecDestination) Validate() error {
|
|||
shared.ValidateOptionalInterfacePath("service", a.Service),
|
||||
shared.ValidateOptionalInterfacePath("schema", a.Schema),
|
||||
shared.ValidateOptionalInterfacePath("tls", a.TLS),
|
||||
shared.ValidateOptionalInterfacePath("authentication", a.Authentication),
|
||||
shared.PrefixResourceError("path", shared.ValidateAPIPath(a.GetPath())),
|
||||
); err != nil {
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
)
|
||||
|
||||
type ArangoRouteSpecDestinationAuthentication struct {
|
||||
Type *ArangoRouteSpecAuthenticationType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecDestinationAuthentication) GetType() ArangoRouteSpecAuthenticationType {
|
||||
if a == nil {
|
||||
return ArangoRouteSpecAuthenticationTypeOptional
|
||||
}
|
||||
|
||||
return a.Type.Get()
|
||||
}
|
||||
|
||||
func (a *ArangoRouteSpecDestinationAuthentication) Validate() error {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return shared.WithErrors(
|
||||
shared.ValidateOptionalInterfacePath("type", a.Type),
|
||||
)
|
||||
}
|
|
@ -33,6 +33,9 @@ type ArangoRouteStatusTarget struct {
|
|||
// TLS Keeps target TLS Settings (if not nil, TLS is enabled)
|
||||
TLS *ArangoRouteStatusTargetTLS `json:"TLS,omitempty"`
|
||||
|
||||
// Authentication specifies the authentication details
|
||||
Authentication ArangoRouteStatusTargetAuthentication `json:"authentication,omitempty"`
|
||||
|
||||
// Path specifies request path override
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
@ -61,5 +64,5 @@ func (a *ArangoRouteStatusTarget) Hash() string {
|
|||
if a == nil {
|
||||
return ""
|
||||
}
|
||||
return util.SHA256FromStringArray(a.Destinations.Hash(), a.TLS.Hash(), a.Path)
|
||||
return util.SHA256FromStringArray(a.Destinations.Hash(), a.TLS.Hash(), a.Path, a.Authentication.Hash())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import "github.com/arangodb/kube-arangodb/pkg/util"
|
||||
|
||||
type ArangoRouteStatusTargetAuthentication struct {
|
||||
Type ArangoRouteSpecAuthenticationType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (a *ArangoRouteStatusTargetAuthentication) Hash() string {
|
||||
if a == nil {
|
||||
return ""
|
||||
}
|
||||
return util.SHA256FromStringArray(a.Type.Hash())
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
v2alpha1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||
deploymentv1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||
v1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
intstr "k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
@ -147,6 +147,11 @@ func (in *ArangoRouteSpecDestination) DeepCopyInto(out *ArangoRouteSpecDestinati
|
|||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Authentication != nil {
|
||||
in, out := &in.Authentication, &out.Authentication
|
||||
*out = new(ArangoRouteSpecDestinationAuthentication)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -160,6 +165,27 @@ func (in *ArangoRouteSpecDestination) DeepCopy() *ArangoRouteSpecDestination {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ArangoRouteSpecDestinationAuthentication) DeepCopyInto(out *ArangoRouteSpecDestinationAuthentication) {
|
||||
*out = *in
|
||||
if in.Type != nil {
|
||||
in, out := &in.Type, &out.Type
|
||||
*out = new(ArangoRouteSpecAuthenticationType)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteSpecDestinationAuthentication.
|
||||
func (in *ArangoRouteSpecDestinationAuthentication) DeepCopy() *ArangoRouteSpecDestinationAuthentication {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ArangoRouteSpecDestinationAuthentication)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ArangoRouteSpecDestinationService) DeepCopyInto(out *ArangoRouteSpecDestinationService) {
|
||||
*out = *in
|
||||
|
@ -233,7 +259,7 @@ func (in *ArangoRouteStatus) DeepCopyInto(out *ArangoRouteStatus) {
|
|||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make(v2alpha1.ConditionList, len(*in))
|
||||
*out = make(deploymentv1.ConditionList, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
|
@ -274,6 +300,7 @@ func (in *ArangoRouteStatusTarget) DeepCopyInto(out *ArangoRouteStatusTarget) {
|
|||
*out = new(ArangoRouteStatusTargetTLS)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.Authentication = in.Authentication
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -287,6 +314,22 @@ func (in *ArangoRouteStatusTarget) DeepCopy() *ArangoRouteStatusTarget {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ArangoRouteStatusTargetAuthentication) DeepCopyInto(out *ArangoRouteStatusTargetAuthentication) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteStatusTargetAuthentication.
|
||||
func (in *ArangoRouteStatusTargetAuthentication) DeepCopy() *ArangoRouteStatusTargetAuthentication {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ArangoRouteStatusTargetAuthentication)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ArangoRouteStatusTargetDestination) DeepCopyInto(out *ArangoRouteStatusTargetDestination) {
|
||||
*out = *in
|
||||
|
|
|
@ -9,6 +9,12 @@ v1alpha1:
|
|||
destination:
|
||||
description: Destination defines the route destination
|
||||
properties:
|
||||
authentication:
|
||||
description: Authentication defines auth methods
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
path:
|
||||
description: Path defines service path used for overrides
|
||||
type: string
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3"
|
||||
networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1"
|
||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/gateway"
|
||||
|
@ -131,6 +132,7 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto
|
|||
Port: shared.ArangoPort,
|
||||
},
|
||||
},
|
||||
AuthExtension: &gateway.ConfigAuthZExtension{},
|
||||
}
|
||||
|
||||
if spec.TLS.IsSecure() {
|
||||
|
@ -193,6 +195,11 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto
|
|||
dest.Type = util.NewType(gateway.ConfigDestinationTypeHTTPS)
|
||||
}
|
||||
dest.Path = util.NewType(target.Path)
|
||||
dest.AuthExtension = &gateway.ConfigAuthZExtension{
|
||||
AuthZExtension: map[string]string{
|
||||
pbImplEnvoyAuthV3.AuthConfigAuthRequiredKey: util.BoolSwitch(target.Authentication.Type.Get() == networkingApi.ArangoRouteSpecAuthenticationTypeRequired, pbImplEnvoyAuthV3.AuthConfigKeywordTrue, pbImplEnvoyAuthV3.AuthConfigKeywordFalse),
|
||||
},
|
||||
}
|
||||
cfg.Destinations[at.Spec.GetRoute().GetPath()] = dest
|
||||
}
|
||||
|
||||
|
|
67
pkg/deployment/resources/gateway/gateway_authz_extension.go
Normal file
67
pkg/deployment/resources/gateway/gateway_authz_extension.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package gateway
|
||||
|
||||
import (
|
||||
httpFilterAuthzApi "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
)
|
||||
|
||||
type ConfigAuthZExtension struct {
|
||||
AuthZExtension map[string]string `json:"authZExtension,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ConfigAuthZExtension) RenderTypedFilterConfig() (util.KV[string, *anypb.Any], error) {
|
||||
if c == nil {
|
||||
return util.KV[string, *anypb.Any]{}, nil
|
||||
}
|
||||
|
||||
var data = map[string]string{}
|
||||
|
||||
for k, v := range c.AuthZExtension {
|
||||
data[k] = v
|
||||
}
|
||||
|
||||
data[pbImplEnvoyAuthV3.AuthConfigTypeKey] = pbImplEnvoyAuthV3.AuthConfigTypeValue
|
||||
|
||||
q, err := anypb.New(&httpFilterAuthzApi.ExtAuthzPerRoute{
|
||||
Override: &httpFilterAuthzApi.ExtAuthzPerRoute_CheckSettings{
|
||||
CheckSettings: &httpFilterAuthzApi.CheckSettings{
|
||||
ContextExtensions: data,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return util.KV[string, *anypb.Any]{}, err
|
||||
}
|
||||
|
||||
return util.KV[string, *anypb.Any]{
|
||||
K: IntegrationSidecarFilterName,
|
||||
V: q,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *ConfigAuthZExtension) Validate() error {
|
||||
return nil
|
||||
}
|
|
@ -26,7 +26,6 @@ import (
|
|||
clusterAPI "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||
endpointAPI "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
||||
routeAPI "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||
anypb "github.com/golang/protobuf/ptypes/any"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
|
@ -62,6 +61,8 @@ type ConfigDestination struct {
|
|||
Type *ConfigDestinationType `json:"type,omitempty"`
|
||||
|
||||
Path *string `json:"path,omitempty"`
|
||||
|
||||
AuthExtension *ConfigAuthZExtension `json:"authExtension,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ConfigDestination) Validate() error {
|
||||
|
@ -72,6 +73,7 @@ func (c *ConfigDestination) Validate() error {
|
|||
shared.PrefixResourceError("targets", c.Targets.Validate()),
|
||||
shared.PrefixResourceError("type", c.Type.Validate()),
|
||||
shared.PrefixResourceError("path", shared.ValidateAPIPath(c.GetPath())),
|
||||
shared.PrefixResourceError("authExtension", c.AuthExtension.Validate()),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -84,6 +86,16 @@ func (c *ConfigDestination) GetPath() string {
|
|||
}
|
||||
|
||||
func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, error) {
|
||||
var tcg []TypedFilterConfigGen
|
||||
|
||||
if c != nil && c.AuthExtension != nil {
|
||||
tcg = append(tcg, c.AuthExtension)
|
||||
}
|
||||
tc, err := NewTypedFilterConfig(tcg...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &routeAPI.Route{
|
||||
Match: &routeAPI.RouteMatch{
|
||||
PathSpecifier: &routeAPI.RouteMatch_Prefix{
|
||||
|
@ -98,7 +110,7 @@ func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, e
|
|||
PrefixRewrite: c.GetPath(),
|
||||
},
|
||||
},
|
||||
TypedPerFilterConfig: map[string]*anypb.Any{},
|
||||
TypedPerFilterConfig: tc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
58
pkg/deployment/resources/gateway/gateway_filter_extension.go
Normal file
58
pkg/deployment/resources/gateway/gateway_filter_extension.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
)
|
||||
|
||||
type TypedFilterConfigGen interface {
|
||||
RenderTypedFilterConfig() (util.KV[string, *anypb.Any], error)
|
||||
}
|
||||
|
||||
func NewTypedFilterConfig(gens ...TypedFilterConfigGen) (map[string]*anypb.Any, error) {
|
||||
generated := map[string]*anypb.Any{}
|
||||
|
||||
for _, g := range gens {
|
||||
if k, err := g.RenderTypedFilterConfig(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if _, ok := generated[k.K]; ok {
|
||||
return nil, errors.Errorf("Duplicated key: %s", k.K)
|
||||
}
|
||||
|
||||
if k.V == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
generated[k.K] = k.V
|
||||
}
|
||||
}
|
||||
|
||||
if len(generated) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return generated, nil
|
||||
}
|
|
@ -238,7 +238,11 @@ func (m *MemberGatewayPod) Labels() map[string]string {
|
|||
func (m *MemberGatewayPod) Profiles() (schedulerApi.ProfileTemplates, error) {
|
||||
integration, err := sidecar.NewIntegration(&schedulerContainerResourcesApi.Image{
|
||||
Image: util.NewType(m.resources.context.GetOperatorImage()),
|
||||
}, m.spec.Gateway.GetSidecar(), []string{shared.ServerContainerName}, sidecar.IntegrationEnvoyV3{
|
||||
}, m.spec.Gateway.GetSidecar(), []string{shared.ServerContainerName},
|
||||
sidecar.IntegrationEnvoyV3{
|
||||
Spec: m.spec,
|
||||
}, sidecar.IntegrationAuthenticationV1{
|
||||
DeploymentName: m.context.GetName(),
|
||||
Spec: m.spec,
|
||||
})
|
||||
|
||||
|
|
|
@ -121,6 +121,10 @@ func (h *handler) HandleArangoDestination(ctx context.Context, item operation.It
|
|||
|
||||
target.Path = dest.GetPath()
|
||||
|
||||
// Render Auth Settings
|
||||
|
||||
target.Authentication.Type = dest.GetAuthentication().GetType()
|
||||
|
||||
if dest.Schema.Get() == networkingApi.ArangoRouteSpecDestinationSchemaHTTPS {
|
||||
target.TLS = &networkingApi.ArangoRouteStatusTargetTLS{
|
||||
Insecure: util.NewType(extension.Spec.Destination.GetTLS().GetInsecure()),
|
||||
|
|
|
@ -56,7 +56,7 @@ func (a *authenticationV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *authenticationV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (a *authenticationV1) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
return pbImplAuthenticationV1.New(ctx, a.config)
|
||||
}
|
||||
|
||||
|
@ -67,3 +67,7 @@ func (a *authenticationV1) Name() string {
|
|||
func (a *authenticationV1) Description() string {
|
||||
return "Enable AuthenticationV1 Integration Service"
|
||||
}
|
||||
|
||||
func (*authenticationV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -51,6 +51,10 @@ func (a authorizationV0) Register(cmd *cobra.Command, arg ArgGen) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a authorizationV0) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (a authorizationV0) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
return pbImplAuthorizationV0.New(), nil
|
||||
}
|
||||
|
||||
func (a authorizationV0) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ func (a *configV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *configV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (a *configV1) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
var cfg pbImplConfigV1.Config
|
||||
|
||||
cfg.Modules = map[string]pbImplConfigV1.ModuleDefinition{}
|
||||
|
@ -75,3 +75,7 @@ func (a *configV1) Name() string {
|
|||
func (a *configV1) Description() string {
|
||||
return "Enable ConfigV1 Integration Service"
|
||||
}
|
||||
|
||||
func (*configV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
pbAuthenticationV1 "github.com/arangodb/kube-arangodb/integrations/authentication/v1/definition"
|
||||
pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
|
@ -42,14 +44,26 @@ func (a envoyAuthV3) Name() string {
|
|||
return pbImplEnvoyAuthV3.Name
|
||||
}
|
||||
|
||||
func (a envoyAuthV3) Description() string {
|
||||
func (a *envoyAuthV3) Description() string {
|
||||
return "Enable EnvoyAuthV3 Integration Service"
|
||||
}
|
||||
|
||||
func (a envoyAuthV3) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||
func (a *envoyAuthV3) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a envoyAuthV3) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
return pbImplEnvoyAuthV3.New(), nil
|
||||
func (a *envoyAuthV3) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
f := cmd.Flags()
|
||||
|
||||
v, err := f.GetString("services.address")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, _, err := util.NewGRPCClient(ctx, pbAuthenticationV1.NewAuthenticationV1Client, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pbImplEnvoyAuthV3.New(c), nil
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ type Integration interface {
|
|||
|
||||
Register(cmd *cobra.Command, arg ArgGen) error
|
||||
|
||||
Handler(ctx context.Context) (svc.Handler, error)
|
||||
Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error)
|
||||
}
|
||||
|
||||
type IntegrationEnablement interface {
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/shutdown"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
"github.com/arangodb/kube-arangodb/pkg/version"
|
||||
)
|
||||
|
||||
var registerer = util.NewRegisterer[string, Factory]()
|
||||
|
@ -171,6 +172,8 @@ func (c *configuration) run(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
|
||||
func (c *configuration) runWithContext(ctx context.Context, cancel context.CancelFunc, cmd *cobra.Command) error {
|
||||
println(version.GetVersionV1().String())
|
||||
|
||||
healthConfig, err := c.health.Config()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Unable to parse health config")
|
||||
|
@ -214,7 +217,7 @@ func (c *configuration) runWithContext(ctx context.Context, cancel context.Cance
|
|||
Info("Service discovered")
|
||||
|
||||
if ok && (internalEnabled || externalEnabled) {
|
||||
if svc, err := handler.Handler(ctx); err != nil {
|
||||
if svc, err := handler.Handler(ctx, cmd); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if internalEnabled {
|
||||
|
|
|
@ -59,7 +59,7 @@ func (b *schedulerV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *schedulerV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (b *schedulerV1) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
client, ok := kclient.GetDefaultFactory().Client()
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Unable to create Kubernetes Client")
|
||||
|
@ -67,3 +67,7 @@ func (b *schedulerV1) Handler(ctx context.Context) (svc.Handler, error) {
|
|||
|
||||
return pbImplSchedulerV1.New(ctx, client, b.Configuration)
|
||||
}
|
||||
|
||||
func (*schedulerV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ func init() {
|
|||
type shutdownV1 struct {
|
||||
}
|
||||
|
||||
func (s *shutdownV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (s *shutdownV1) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
return pbImplShutdownV1.New(shutdown.Stop), nil
|
||||
}
|
||||
|
||||
|
@ -55,3 +55,7 @@ func (s *shutdownV1) Description() string {
|
|||
func (s *shutdownV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*shutdownV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||
)
|
||||
|
||||
|
@ -34,7 +33,9 @@ var _ IntegrationVolumes = IntegrationAuthenticationV1{}
|
|||
|
||||
type IntegrationAuthenticationV1 struct {
|
||||
Core *Core
|
||||
Deployment *api.ArangoDeployment
|
||||
|
||||
DeploymentName string
|
||||
Spec api.DeploymentSpec
|
||||
}
|
||||
|
||||
func (i IntegrationAuthenticationV1) Name() []string {
|
||||
|
@ -42,10 +43,6 @@ func (i IntegrationAuthenticationV1) Name() []string {
|
|||
}
|
||||
|
||||
func (i IntegrationAuthenticationV1) Validate() error {
|
||||
if i.Deployment == nil {
|
||||
return errors.Errorf("Deployment is nil")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -53,7 +50,7 @@ func (i IntegrationAuthenticationV1) Args() (k8sutil.OptionPairs, error) {
|
|||
options := k8sutil.CreateOptionPairs()
|
||||
|
||||
options.Add("--integration.authentication.v1", true)
|
||||
options.Add("--integration.authentication.v1.enabled", i.Deployment.GetAcceptedSpec().IsAuthenticated())
|
||||
options.Add("--integration.authentication.v1.enabled", i.Spec.IsAuthenticated())
|
||||
options.Add("--integration.authentication.v1.path", shared.ClusterJWTSecretVolumeMountDir)
|
||||
|
||||
options.Merge(i.Core.Args(i))
|
||||
|
@ -62,13 +59,13 @@ func (i IntegrationAuthenticationV1) Args() (k8sutil.OptionPairs, error) {
|
|||
}
|
||||
|
||||
func (i IntegrationAuthenticationV1) Volumes() ([]core.Volume, []core.VolumeMount, error) {
|
||||
if i.Deployment.GetAcceptedSpec().IsAuthenticated() {
|
||||
if i.Spec.IsAuthenticated() {
|
||||
return []core.Volume{
|
||||
{
|
||||
Name: shared.ClusterJWTSecretVolumeName,
|
||||
VolumeSource: core.VolumeSource{
|
||||
Secret: &core.SecretVolumeSource{
|
||||
SecretName: pod.JWTSecretFolder(i.Deployment.GetName()),
|
||||
SecretName: pod.JWTSecretFolder(i.DeploymentName),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -64,6 +64,10 @@ func (b *storageV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *storageV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
func (b *storageV1) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||
return storage.NewService(ctx, b.Configuration)
|
||||
}
|
||||
|
||||
func (*storageV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ func Test_TLSCases(t *testing.T) {
|
|||
"--tls.enabled=false",
|
||||
"client",
|
||||
"health",
|
||||
"v1")).Code(t, codes.Unavailable).Errorf(t, "connection error: desc = \"error reading server preface: EOF\"")
|
||||
"v1")).Code(t, codes.Unavailable)
|
||||
})
|
||||
t.Run("external", func(t *testing.T) {
|
||||
tgrpc.AsGRPCError(t, executeSync(t, shutdown.Context(),
|
||||
|
@ -117,7 +117,7 @@ func Test_TLSCases(t *testing.T) {
|
|||
"--tls.enabled=false",
|
||||
"client",
|
||||
"health",
|
||||
"v1")).Code(t, codes.Unavailable).Errorf(t, "connection error: desc = \"error reading server preface: EOF\"")
|
||||
"v1")).Code(t, codes.Unavailable)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -115,3 +115,12 @@ func IterateSorted[V any](m map[string]V, cb func(string, V)) {
|
|||
cb(k, m[k])
|
||||
}
|
||||
}
|
||||
|
||||
func Optional[K comparable, V any](m map[K]V, key K, def V) V {
|
||||
v, ok := m[key]
|
||||
if ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -30,6 +30,20 @@ func recoverPanic(skipFrames int, in func() error) (err error) {
|
|||
return in()
|
||||
}
|
||||
|
||||
func recoverPanicO1[O1 any](skipFrames int, in func() (O1, error)) (o1 O1, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = newPanicError(r, GetStack(skipFrames))
|
||||
}
|
||||
}()
|
||||
|
||||
return in()
|
||||
}
|
||||
|
||||
func Recover(in func() error) (err error) {
|
||||
return recoverPanic(4, in)
|
||||
}
|
||||
|
||||
func RecoverO1[O1 any](in func() (O1, error)) (O1, error) {
|
||||
return recoverPanicO1(4, in)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -21,6 +21,7 @@
|
|||
package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
|
@ -58,6 +59,10 @@ func (i InfoV1) IsEnterprise() bool {
|
|||
return i.Edition == EnterpriseEdition
|
||||
}
|
||||
|
||||
func (i InfoV1) String() string {
|
||||
return fmt.Sprintf("Version: %s %s, Build: %s, Go: %s, Build Date: %s", i.Edition.Title(), i.Version, i.Build, i.GoVersion, i.BuildDate)
|
||||
}
|
||||
|
||||
func GetVersionV1() InfoV1 {
|
||||
return InfoV1{
|
||||
Version: driver.Version(version),
|
||||
|
|
Loading…
Reference in a new issue