checkpoint: working OPA ext-authz

pull/17980/head
Chris Thain 2023-06-05 12:08:54 -07:00
parent 0b1299c28d
commit 6699b17313
5 changed files with 181 additions and 6 deletions

View File

@ -46,11 +46,11 @@ type Agent interface {
type Config struct {
// NodeName is set for the consul agent name and container name
// Equivalent to the -node command-line flag.
// If empty, a randam name will be generated
// If empty, a random name will be generated
NodeName string
// NodeID is used to configure node_id in agent config file
// Equivalent to the -node-id command-line flag.
// If empty, a randam name will be generated
// If empty, a random name will be generated
NodeID string
// ExternalDataDir is data directory to copy consul data from, if set.
@ -83,10 +83,7 @@ func (c *Config) DockerImage() string {
func (c Config) Clone() Config {
c2 := c
if c.Cmd != nil {
c2.Cmd = make([]string, len(c.Cmd))
for i, v := range c.Cmd {
c2.Cmd[i] = v
}
copy(c2.Cmd, c.Cmd)
}
return c2
}

View File

@ -6,7 +6,9 @@ package utils
import (
"encoding/json"
"fmt"
"os"
"strings"
"time"
"github.com/itchyny/gojq"
"github.com/teris-io/shortid"
@ -66,3 +68,14 @@ func BoolToPointer(b bool) *bool {
func StringToPointer(s string) *string {
return &s
}
func Wait() {
for {
_, err := os.Stat("continue")
if err == nil {
_ = os.Remove("continue")
break
}
time.Sleep(time.Second)
}
}

View File

@ -0,0 +1,153 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package envoyextensions
import (
"context"
"fmt"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/hashicorp/consul/api"
libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert"
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service"
"github.com/hashicorp/consul/test/integration/consul-container/libs/topology"
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
)
// TestExtAuthz Summary
// This test makes sure two services in the same datacenter have connectivity.
// A simulated client (a direct HTTP call) talks to it's upstream proxy through the
//
// Steps:
// - Create a single agent cluster.
// - Create the example static-server and sidecar containers, then register them both with Consul
// - Create an example static-client sidecar, then register both the service and sidecar with Consul
// - Make sure a call to the client sidecar local bind port returns a response from the upstream, static-server
func TestExtAuthz(t *testing.T) {
t.Parallel()
cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{
NumServers: 1,
NumClients: 1,
ApplyDefaultProxySettings: true,
BuildOpts: &libcluster.BuildOptions{
Datacenter: "dc1",
InjectAutoEncryption: true,
InjectGossipEncryption: true,
},
})
createLocalAuthzService(t, cluster)
clientService := createServices(t, cluster)
_, port := clientService.GetAddr()
_, adminPort := clientService.GetAdminAddr()
libassert.AssertUpstreamEndpointStatus(t, adminPort, "static-server.default", "HEALTHY", 1)
libassert.GetEnvoyListenerTCPFilters(t, adminPort)
libassert.AssertContainerState(t, clientService, "running")
libassert.HTTPServiceEchoes(t, "localhost", port, "")
libassert.AssertFortioName(t, fmt.Sprintf("http://localhost:%d", port), "static-server", "")
// wire up ext-authz envoy extension
consul := cluster.APIClient(0)
defaults := api.ServiceConfigEntry{
Kind: api.ServiceDefaults,
Name: "static-server",
Protocol: "http",
EnvoyExtensions: []api.EnvoyExtension{{
Name: "builtin/ext-authz",
Arguments: map[string]any{
"Config": map[string]any{
"GrpcService": map[string]any{
"Target": map[string]any{"URI": "127.0.0.1:9191"},
},
},
},
}},
}
consul.ConfigEntries().Set(&defaults, nil)
utils.Wait()
}
func createServices(t *testing.T, cluster *libcluster.Cluster) libservice.Service {
node := cluster.Agents[0]
client := node.GetClient()
// Create a service and proxy instance
serviceOpts := &libservice.ServiceOpts{
Name: libservice.StaticServerServiceName,
ID: "static-server",
HTTPPort: 8080,
GRPCPort: 8079,
}
// Create a service and proxy instance
_, _, err := libservice.CreateAndRegisterStaticServerAndSidecar(node, serviceOpts)
require.NoError(t, err)
libassert.CatalogServiceExists(t, client, "static-server-sidecar-proxy", nil)
libassert.CatalogServiceExists(t, client, libservice.StaticServerServiceName, nil)
// Create a client proxy instance with the server as an upstream
clientConnectProxy, err := libservice.CreateAndRegisterStaticClientSidecar(node, "", false, false)
require.NoError(t, err)
libassert.CatalogServiceExists(t, client, "static-client-sidecar-proxy", nil)
return clientConnectProxy
}
func createLocalAuthzService(t *testing.T, cluster *libcluster.Cluster) {
node := cluster.Agents[0]
//client := node.GetClient()
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
req := testcontainers.ContainerRequest{
Image: "openpolicyagent/opa:0.53.0-envoy-3",
AutoRemove: true,
Name: "ext-authz",
Env: make(map[string]string),
Cmd: []string{
"run",
"--server",
"--addr=localhost:8181",
"--diagnostic-addr=0.0.0.0:8282",
"--set=plugins.envoy_ext_authz_grpc.addr=:9191",
"--set=plugins.envoy_ext_authz_grpc.path=envoy/authz/allow",
"--set=decision_logs.console=true",
"--set=status.console=true",
"--ignore=.*",
"/testdata/policies/bundle.tar.gz",
},
Mounts: []testcontainers.ContainerMount{{
Source: testcontainers.DockerBindMountSource{
HostPath: fmt.Sprintf("%s/testdata", cwd),
},
Target: "/testdata",
ReadOnly: true,
}},
}
ctx := context.Background()
exposedPorts := []string{}
info, err := libcluster.LaunchContainerOnNode(ctx, node, req, exposedPorts)
if err != nil {
t.Fatal(err)
}
fmt.Printf("\n!!! ext-authz info = %#v\n\n", *info)
}

View File

@ -0,0 +1,12 @@
package envoy.authz
import future.keywords
import input.attributes.request.http as http_request
default allow := false
allow if {
http_request.method == "GET"
glob.match("/allow", ["/"], http_request.path)
}