// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package extauthz import ( "testing" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/stretchr/testify/require" ) func TestConstructor(t *testing.T) { t.Parallel() cases := map[string]struct { extName string args map[string]any errMsg string }{ "invalid name": { extName: "invalid", errMsg: `expected extension name "builtin/ext-authz"`, }, "invalid proxy type": { args: map[string]any{"ProxyType": "invalid"}, errMsg: `unsupported ProxyType`, }, "no service type": { args: map[string]any{"ProxyType": "connect-proxy"}, errMsg: `exactly one of GrpcService or HttpService must be set`, }, "both service types": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "localhost:9191", }, }, "HttpService": map[string]any{ "Target": map[string]any{ "URI": "localhost:9191", }, }, }, }, errMsg: `exactly one of GrpcService or HttpService must be set`, }, "non-loopback address hostname": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "foo.bar.com:9191", }, }, }, }, errMsg: `invalid host for Target.URI "foo.bar.com:9191": expected "localhost", "127.0.0.1", or "::1"`, }, "non-loopback address": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "10.0.0.1:9191", }, }, }, }, errMsg: `invalid host for Target.URI "10.0.0.1:9191": expected "localhost", "127.0.0.1", or "::1"`, }, "invalid target port": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "localhost:zero", }, }, }, }, errMsg: `invalid format for Target.URI "localhost:zero": expected host:port`, }, "invalid target timeout": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "localhost:9191", "Timeout": "one", }, }, }, }, errMsg: `failed to parse Target.Timeout "one" as a duration`, }, "no uri or service target": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "HttpService": map[string]any{ "Target": map[string]any{ "Timeout": "1s", }, }, }, }, errMsg: `exactly one of Target.Service or Target.URI must be set`, }, "uri and service target": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "10.0.0.1:9191", "Service": map[string]any{ "Name": "test-service", }, }, }, }, }, errMsg: `exactly one of Target.Service or Target.URI must be set`, }, "invalid status on error": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "StatusOnError": 1, "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "10.0.0.1:9191", "Service": map[string]any{ "Name": "test-service", }, }, }, }, }, errMsg: `failed to validate Config.StatusOnError`, }, "valid grpc service": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "GrpcService": map[string]any{ "Target": map[string]any{ "URI": "localhost:9191", }, }, }, }, }, "valid http service": { args: map[string]any{ "ProxyType": "connect-proxy", "Config": map[string]any{ "HttpService": map[string]any{ "Target": map[string]any{ "URI": "127.0.0.1:9191", }, }, }, }, }, } for name, c := range cases { c := c t.Run(name, func(t *testing.T) { extName := api.BuiltinExtAuthzExtension if c.extName != "" { extName = c.extName } ext, err := newExtAuthz(api.EnvoyExtension{Name: extName, Arguments: c.args}) if c.errMsg == "" { require.NoError(t, err) httpFilter, err := ext.Config.toEnvoyHttpFilter(&extensioncommon.RuntimeConfig{}) require.NoError(t, err) require.NotNil(t, httpFilter) if ext.Config.isGRPC() { netFilter, err := ext.Config.toEnvoyNetworkFilter(&extensioncommon.RuntimeConfig{}) require.NoError(t, err) require.NotNil(t, netFilter) } } else { require.Error(t, err) require.Contains(t, err.Error(), c.errMsg) } }) } }