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) Integration Service TLS
|
||||||
- (Feature) (Gateway) SNI and Authz support
|
- (Feature) (Gateway) SNI and Authz support
|
||||||
- (Maintenance) Bump Examples to ArangoDB 3.12
|
- (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)
|
## [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
|
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// DISCLAIMER
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,8 +21,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/version"
|
"github.com/arangodb/kube-arangodb/pkg/version"
|
||||||
|
@ -38,6 +36,5 @@ var cmdVersion = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func versionRun(cmd *cobra.Command, args []string) {
|
func versionRun(cmd *cobra.Command, args []string) {
|
||||||
v := version.GetVersionV1()
|
println(version.GetVersionV1().String())
|
||||||
println(fmt.Sprintf("Version: %s %s, Build: %s, Go: %s, Build Date: %s", v.Edition.Title(), v.Version, v.Build, v.GoVersion, v.BuildDate))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
### .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>
|
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
|
### .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>
|
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
|
### .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
|
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 (
|
const (
|
||||||
Name = "envoy.auth.v3"
|
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 (
|
import (
|
||||||
"context"
|
"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"
|
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||||
"google.golang.org/grpc"
|
"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"
|
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New() svc.Handler {
|
func New(authClient pbAuthenticationV1.AuthenticationV1Client) svc.Handler {
|
||||||
return &impl{}
|
return &impl{
|
||||||
|
authClient: authClient,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ pbEnvoyAuthV3.AuthorizationServer = &impl{}
|
var _ pbEnvoyAuthV3.AuthorizationServer = &impl{}
|
||||||
|
@ -38,6 +46,8 @@ var _ svc.Handler = &impl{}
|
||||||
|
|
||||||
type impl struct {
|
type impl struct {
|
||||||
pbEnvoyAuthV3.UnimplementedAuthorizationServer
|
pbEnvoyAuthV3.UnimplementedAuthorizationServer
|
||||||
|
|
||||||
|
authClient pbAuthenticationV1.AuthenticationV1Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *impl) Name() string {
|
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) {
|
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{
|
||||||
|
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{
|
return &pbEnvoyAuthV3.CheckResponse{
|
||||||
HttpResponse: &pbEnvoyAuthV3.CheckResponse_OkResponse{
|
HttpResponse: &pbEnvoyAuthV3.CheckResponse_OkResponse{
|
||||||
OkResponse: &pbEnvoyAuthV3.OkHttpResponse{},
|
OkResponse: &pbEnvoyAuthV3.OkHttpResponse{
|
||||||
|
Headers: []*corev3.HeaderValueOption{
|
||||||
|
{
|
||||||
|
Header: &corev3.HeaderValue{
|
||||||
|
Key: AuthAuthenticatedHeader,
|
||||||
|
Value: "false",
|
||||||
|
},
|
||||||
|
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, 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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
pbEnvoyAuthV3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
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 {
|
func Client(t *testing.T, ctx context.Context) pbEnvoyAuthV3.AuthorizationClient {
|
||||||
local := svc.NewService(svc.Configuration{
|
local := svc.NewService(svc.Configuration{
|
||||||
Address: "127.0.0.1:0",
|
Address: "127.0.0.1:0",
|
||||||
}, New())
|
}, New(nil))
|
||||||
|
|
||||||
start := local.Start(ctx)
|
start := local.Start(ctx)
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ func Client(t *testing.T, ctx context.Context) pbEnvoyAuthV3.AuthorizationClient
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_AllowAll(t *testing.T) {
|
func Test_DenyHeader(t *testing.T) {
|
||||||
ctx, c := context.WithCancel(context.Background())
|
ctx, c := context.WithCancel(context.Background())
|
||||||
defer c()
|
defer c()
|
||||||
|
|
||||||
|
@ -53,8 +54,28 @@ func Test_AllowAll(t *testing.T) {
|
||||||
resp, err := client.Check(ctx, &pbEnvoyAuthV3.CheckRequest{})
|
resp, err := client.Check(ctx, &pbEnvoyAuthV3.CheckRequest{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, resp.Validate())
|
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.Nil(t, resp.Status)
|
||||||
require.NotNil(t, resp.HttpResponse)
|
require.NotNil(t, resp.HttpResponse)
|
||||||
require.NotNil(t, tests.CastAs[*pbEnvoyAuthV3.CheckResponse_OkResponse](t, resp.GetHttpResponse()).OkResponse)
|
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 defines service path used for overrides
|
||||||
Path *string `json:"path,omitempty"`
|
Path *string `json:"path,omitempty"`
|
||||||
|
|
||||||
|
// Authentication defines auth methods
|
||||||
|
Authentication *ArangoRouteSpecDestinationAuthentication `json:"authentication,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArangoRouteSpecDestination) GetService() *ArangoRouteSpecDestinationService {
|
func (a *ArangoRouteSpecDestination) GetService() *ArangoRouteSpecDestinationService {
|
||||||
|
@ -68,6 +71,14 @@ func (a *ArangoRouteSpecDestination) GetTLS() *ArangoRouteSpecDestinationTLS {
|
||||||
return a.TLS
|
return a.TLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ArangoRouteSpecDestination) GetAuthentication() *ArangoRouteSpecDestinationAuthentication {
|
||||||
|
if a == nil || a.Authentication == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Authentication
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ArangoRouteSpecDestination) Validate() error {
|
func (a *ArangoRouteSpecDestination) Validate() error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
a = &ArangoRouteSpecDestination{}
|
a = &ArangoRouteSpecDestination{}
|
||||||
|
@ -77,6 +88,7 @@ func (a *ArangoRouteSpecDestination) Validate() error {
|
||||||
shared.ValidateOptionalInterfacePath("service", a.Service),
|
shared.ValidateOptionalInterfacePath("service", a.Service),
|
||||||
shared.ValidateOptionalInterfacePath("schema", a.Schema),
|
shared.ValidateOptionalInterfacePath("schema", a.Schema),
|
||||||
shared.ValidateOptionalInterfacePath("tls", a.TLS),
|
shared.ValidateOptionalInterfacePath("tls", a.TLS),
|
||||||
|
shared.ValidateOptionalInterfacePath("authentication", a.Authentication),
|
||||||
shared.PrefixResourceError("path", shared.ValidateAPIPath(a.GetPath())),
|
shared.PrefixResourceError("path", shared.ValidateAPIPath(a.GetPath())),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
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 Keeps target TLS Settings (if not nil, TLS is enabled)
|
||||||
TLS *ArangoRouteStatusTargetTLS `json:"TLS,omitempty"`
|
TLS *ArangoRouteStatusTargetTLS `json:"TLS,omitempty"`
|
||||||
|
|
||||||
|
// Authentication specifies the authentication details
|
||||||
|
Authentication ArangoRouteStatusTargetAuthentication `json:"authentication,omitempty"`
|
||||||
|
|
||||||
// Path specifies request path override
|
// Path specifies request path override
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -61,5 +64,5 @@ func (a *ArangoRouteStatusTarget) Hash() string {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return ""
|
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
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
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"
|
v1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
intstr "k8s.io/apimachinery/pkg/util/intstr"
|
intstr "k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
@ -147,6 +147,11 @@ func (in *ArangoRouteSpecDestination) DeepCopyInto(out *ArangoRouteSpecDestinati
|
||||||
*out = new(string)
|
*out = new(string)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.Authentication != nil {
|
||||||
|
in, out := &in.Authentication, &out.Authentication
|
||||||
|
*out = new(ArangoRouteSpecDestinationAuthentication)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +165,27 @@ func (in *ArangoRouteSpecDestination) DeepCopy() *ArangoRouteSpecDestination {
|
||||||
return out
|
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.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ArangoRouteSpecDestinationService) DeepCopyInto(out *ArangoRouteSpecDestinationService) {
|
func (in *ArangoRouteSpecDestinationService) DeepCopyInto(out *ArangoRouteSpecDestinationService) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -233,7 +259,7 @@ func (in *ArangoRouteStatus) DeepCopyInto(out *ArangoRouteStatus) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make(v2alpha1.ConditionList, len(*in))
|
*out = make(deploymentv1.ConditionList, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -274,6 +300,7 @@ func (in *ArangoRouteStatusTarget) DeepCopyInto(out *ArangoRouteStatusTarget) {
|
||||||
*out = new(ArangoRouteStatusTargetTLS)
|
*out = new(ArangoRouteStatusTargetTLS)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
|
out.Authentication = in.Authentication
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +314,22 @@ func (in *ArangoRouteStatusTarget) DeepCopy() *ArangoRouteStatusTarget {
|
||||||
return out
|
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.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ArangoRouteStatusTargetDestination) DeepCopyInto(out *ArangoRouteStatusTargetDestination) {
|
func (in *ArangoRouteStatusTargetDestination) DeepCopyInto(out *ArangoRouteStatusTargetDestination) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
|
@ -9,6 +9,12 @@ v1alpha1:
|
||||||
destination:
|
destination:
|
||||||
description: Destination defines the route destination
|
description: Destination defines the route destination
|
||||||
properties:
|
properties:
|
||||||
|
authentication:
|
||||||
|
description: Authentication defines auth methods
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
path:
|
path:
|
||||||
description: Path defines service path used for overrides
|
description: Path defines service path used for overrides
|
||||||
type: string
|
type: string
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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"
|
networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1"
|
||||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/gateway"
|
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/gateway"
|
||||||
|
@ -131,6 +132,7 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto
|
||||||
Port: shared.ArangoPort,
|
Port: shared.ArangoPort,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AuthExtension: &gateway.ConfigAuthZExtension{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.TLS.IsSecure() {
|
if spec.TLS.IsSecure() {
|
||||||
|
@ -193,6 +195,11 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto
|
||||||
dest.Type = util.NewType(gateway.ConfigDestinationTypeHTTPS)
|
dest.Type = util.NewType(gateway.ConfigDestinationTypeHTTPS)
|
||||||
}
|
}
|
||||||
dest.Path = util.NewType(target.Path)
|
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
|
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"
|
clusterAPI "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||||
endpointAPI "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
endpointAPI "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
||||||
routeAPI "github.com/envoyproxy/go-control-plane/envoy/config/route/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"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
|
||||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||||
|
@ -62,6 +61,8 @@ type ConfigDestination struct {
|
||||||
Type *ConfigDestinationType `json:"type,omitempty"`
|
Type *ConfigDestinationType `json:"type,omitempty"`
|
||||||
|
|
||||||
Path *string `json:"path,omitempty"`
|
Path *string `json:"path,omitempty"`
|
||||||
|
|
||||||
|
AuthExtension *ConfigAuthZExtension `json:"authExtension,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfigDestination) Validate() error {
|
func (c *ConfigDestination) Validate() error {
|
||||||
|
@ -72,6 +73,7 @@ func (c *ConfigDestination) Validate() error {
|
||||||
shared.PrefixResourceError("targets", c.Targets.Validate()),
|
shared.PrefixResourceError("targets", c.Targets.Validate()),
|
||||||
shared.PrefixResourceError("type", c.Type.Validate()),
|
shared.PrefixResourceError("type", c.Type.Validate()),
|
||||||
shared.PrefixResourceError("path", shared.ValidateAPIPath(c.GetPath())),
|
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) {
|
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{
|
return &routeAPI.Route{
|
||||||
Match: &routeAPI.RouteMatch{
|
Match: &routeAPI.RouteMatch{
|
||||||
PathSpecifier: &routeAPI.RouteMatch_Prefix{
|
PathSpecifier: &routeAPI.RouteMatch_Prefix{
|
||||||
|
@ -98,7 +110,7 @@ func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, e
|
||||||
PrefixRewrite: c.GetPath(),
|
PrefixRewrite: c.GetPath(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TypedPerFilterConfig: map[string]*anypb.Any{},
|
TypedPerFilterConfig: tc,
|
||||||
}, nil
|
}, 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,9 +238,13 @@ func (m *MemberGatewayPod) Labels() map[string]string {
|
||||||
func (m *MemberGatewayPod) Profiles() (schedulerApi.ProfileTemplates, error) {
|
func (m *MemberGatewayPod) Profiles() (schedulerApi.ProfileTemplates, error) {
|
||||||
integration, err := sidecar.NewIntegration(&schedulerContainerResourcesApi.Image{
|
integration, err := sidecar.NewIntegration(&schedulerContainerResourcesApi.Image{
|
||||||
Image: util.NewType(m.resources.context.GetOperatorImage()),
|
Image: util.NewType(m.resources.context.GetOperatorImage()),
|
||||||
}, m.spec.Gateway.GetSidecar(), []string{shared.ServerContainerName}, sidecar.IntegrationEnvoyV3{
|
}, m.spec.Gateway.GetSidecar(), []string{shared.ServerContainerName},
|
||||||
Spec: m.spec,
|
sidecar.IntegrationEnvoyV3{
|
||||||
})
|
Spec: m.spec,
|
||||||
|
}, sidecar.IntegrationAuthenticationV1{
|
||||||
|
DeploymentName: m.context.GetName(),
|
||||||
|
Spec: m.spec,
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -121,6 +121,10 @@ func (h *handler) HandleArangoDestination(ctx context.Context, item operation.It
|
||||||
|
|
||||||
target.Path = dest.GetPath()
|
target.Path = dest.GetPath()
|
||||||
|
|
||||||
|
// Render Auth Settings
|
||||||
|
|
||||||
|
target.Authentication.Type = dest.GetAuthentication().GetType()
|
||||||
|
|
||||||
if dest.Schema.Get() == networkingApi.ArangoRouteSpecDestinationSchemaHTTPS {
|
if dest.Schema.Get() == networkingApi.ArangoRouteSpecDestinationSchemaHTTPS {
|
||||||
target.TLS = &networkingApi.ArangoRouteStatusTargetTLS{
|
target.TLS = &networkingApi.ArangoRouteStatusTargetTLS{
|
||||||
Insecure: util.NewType(extension.Spec.Destination.GetTLS().GetInsecure()),
|
Insecure: util.NewType(extension.Spec.Destination.GetTLS().GetInsecure()),
|
||||||
|
|
|
@ -56,7 +56,7 @@ func (a *authenticationV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||||
return nil
|
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)
|
return pbImplAuthenticationV1.New(ctx, a.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,3 +67,7 @@ func (a *authenticationV1) Name() string {
|
||||||
func (a *authenticationV1) Description() string {
|
func (a *authenticationV1) Description() string {
|
||||||
return "Enable AuthenticationV1 Integration Service"
|
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
|
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
|
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
|
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
|
var cfg pbImplConfigV1.Config
|
||||||
|
|
||||||
cfg.Modules = map[string]pbImplConfigV1.ModuleDefinition{}
|
cfg.Modules = map[string]pbImplConfigV1.ModuleDefinition{}
|
||||||
|
@ -75,3 +75,7 @@ func (a *configV1) Name() string {
|
||||||
func (a *configV1) Description() string {
|
func (a *configV1) Description() string {
|
||||||
return "Enable ConfigV1 Integration Service"
|
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"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
pbAuthenticationV1 "github.com/arangodb/kube-arangodb/integrations/authentication/v1/definition"
|
||||||
pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3"
|
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"
|
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,14 +44,26 @@ func (a envoyAuthV3) Name() string {
|
||||||
return pbImplEnvoyAuthV3.Name
|
return pbImplEnvoyAuthV3.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a envoyAuthV3) Description() string {
|
func (a *envoyAuthV3) Description() string {
|
||||||
return "Enable EnvoyAuthV3 Integration Service"
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a envoyAuthV3) Handler(ctx context.Context) (svc.Handler, error) {
|
func (a *envoyAuthV3) Handler(ctx context.Context, cmd *cobra.Command) (svc.Handler, error) {
|
||||||
return pbImplEnvoyAuthV3.New(), nil
|
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
|
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 {
|
type IntegrationEnablement interface {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/shutdown"
|
"github.com/arangodb/kube-arangodb/pkg/util/shutdown"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var registerer = util.NewRegisterer[string, Factory]()
|
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 {
|
func (c *configuration) runWithContext(ctx context.Context, cancel context.CancelFunc, cmd *cobra.Command) error {
|
||||||
|
println(version.GetVersionV1().String())
|
||||||
|
|
||||||
healthConfig, err := c.health.Config()
|
healthConfig, err := c.health.Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "Unable to parse health config")
|
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")
|
Info("Service discovered")
|
||||||
|
|
||||||
if ok && (internalEnabled || externalEnabled) {
|
if ok && (internalEnabled || externalEnabled) {
|
||||||
if svc, err := handler.Handler(ctx); err != nil {
|
if svc, err := handler.Handler(ctx, cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
if internalEnabled {
|
if internalEnabled {
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (b *schedulerV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||||
return nil
|
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()
|
client, ok := kclient.GetDefaultFactory().Client()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.Errorf("Unable to create Kubernetes Client")
|
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)
|
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 {
|
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
|
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 {
|
func (s *shutdownV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*shutdownV1) Init(ctx context.Context, cmd *cobra.Command) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -26,15 +26,16 @@ import (
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
|
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ IntegrationVolumes = IntegrationAuthenticationV1{}
|
var _ IntegrationVolumes = IntegrationAuthenticationV1{}
|
||||||
|
|
||||||
type IntegrationAuthenticationV1 struct {
|
type IntegrationAuthenticationV1 struct {
|
||||||
Core *Core
|
Core *Core
|
||||||
Deployment *api.ArangoDeployment
|
|
||||||
|
DeploymentName string
|
||||||
|
Spec api.DeploymentSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i IntegrationAuthenticationV1) Name() []string {
|
func (i IntegrationAuthenticationV1) Name() []string {
|
||||||
|
@ -42,10 +43,6 @@ func (i IntegrationAuthenticationV1) Name() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i IntegrationAuthenticationV1) Validate() error {
|
func (i IntegrationAuthenticationV1) Validate() error {
|
||||||
if i.Deployment == nil {
|
|
||||||
return errors.Errorf("Deployment is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +50,7 @@ func (i IntegrationAuthenticationV1) Args() (k8sutil.OptionPairs, error) {
|
||||||
options := k8sutil.CreateOptionPairs()
|
options := k8sutil.CreateOptionPairs()
|
||||||
|
|
||||||
options.Add("--integration.authentication.v1", true)
|
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.Add("--integration.authentication.v1.path", shared.ClusterJWTSecretVolumeMountDir)
|
||||||
|
|
||||||
options.Merge(i.Core.Args(i))
|
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) {
|
func (i IntegrationAuthenticationV1) Volumes() ([]core.Volume, []core.VolumeMount, error) {
|
||||||
if i.Deployment.GetAcceptedSpec().IsAuthenticated() {
|
if i.Spec.IsAuthenticated() {
|
||||||
return []core.Volume{
|
return []core.Volume{
|
||||||
{
|
{
|
||||||
Name: shared.ClusterJWTSecretVolumeName,
|
Name: shared.ClusterJWTSecretVolumeName,
|
||||||
VolumeSource: core.VolumeSource{
|
VolumeSource: core.VolumeSource{
|
||||||
Secret: &core.SecretVolumeSource{
|
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
|
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)
|
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",
|
"--tls.enabled=false",
|
||||||
"client",
|
"client",
|
||||||
"health",
|
"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) {
|
t.Run("external", func(t *testing.T) {
|
||||||
tgrpc.AsGRPCError(t, executeSync(t, shutdown.Context(),
|
tgrpc.AsGRPCError(t, executeSync(t, shutdown.Context(),
|
||||||
|
@ -117,7 +117,7 @@ func Test_TLSCases(t *testing.T) {
|
||||||
"--tls.enabled=false",
|
"--tls.enabled=false",
|
||||||
"client",
|
"client",
|
||||||
"health",
|
"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])
|
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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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()
|
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) {
|
func Recover(in func() error) (err error) {
|
||||||
return recoverPanic(4, in)
|
return recoverPanic(4, in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RecoverO1[O1 any](in func() (O1, error)) (O1, error) {
|
||||||
|
return recoverPanicO1(4, in)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// DISCLAIMER
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
package version
|
package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
|
@ -58,6 +59,10 @@ func (i InfoV1) IsEnterprise() bool {
|
||||||
return i.Edition == EnterpriseEdition
|
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 {
|
func GetVersionV1() InfoV1 {
|
||||||
return InfoV1{
|
return InfoV1{
|
||||||
Version: driver.Version(version),
|
Version: driver.Version(version),
|
||||||
|
|
Loading…
Reference in a new issue