2023-03-28 18:39:22 +00:00
// Copyright (c) HashiCorp, Inc.
2023-08-11 13:12:13 +00:00
// SPDX-License-Identifier: BUSL-1.1
2023-03-28 18:39:22 +00:00
2014-01-06 21:21:48 +00:00
package agent
import (
2016-12-13 06:09:35 +00:00
"bytes"
2020-01-28 23:50:41 +00:00
"context"
2018-04-30 21:23:49 +00:00
"crypto/tls"
2018-03-21 17:55:39 +00:00
"crypto/x509"
2018-09-27 13:33:12 +00:00
"encoding/json"
2014-01-06 21:21:48 +00:00
"fmt"
2016-11-16 21:45:26 +00:00
"io"
2014-01-06 21:21:48 +00:00
"net/http"
2015-01-15 09:17:35 +00:00
"net/http/httptest"
2019-04-16 16:00:15 +00:00
"net/url"
2020-05-20 10:38:29 +00:00
"os"
2019-09-26 16:54:14 +00:00
"strconv"
2016-03-03 01:08:06 +00:00
"strings"
2014-01-06 21:21:48 +00:00
"testing"
"time"
2015-05-11 23:48:10 +00:00
2021-07-15 23:04:24 +00:00
"github.com/armon/go-metrics"
2021-07-26 21:12:29 +00:00
"github.com/mitchellh/hashstructure"
2020-11-30 17:53:46 +00:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/time/rate"
2024-09-05 14:50:46 +00:00
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/serf/serf"
2017-08-23 14:52:48 +00:00
"github.com/hashicorp/consul/acl"
2022-06-17 09:24:43 +00:00
"github.com/hashicorp/consul/acl/resolver"
2017-09-25 18:40:42 +00:00
"github.com/hashicorp/consul/agent/config"
2018-03-21 17:20:35 +00:00
"github.com/hashicorp/consul/agent/connect"
2021-02-08 19:18:51 +00:00
"github.com/hashicorp/consul/agent/connect/ca"
2020-09-16 17:29:59 +00:00
"github.com/hashicorp/consul/agent/consul"
2018-10-17 20:20:35 +00:00
"github.com/hashicorp/consul/agent/debug"
2018-09-27 13:33:12 +00:00
"github.com/hashicorp/consul/agent/local"
2017-07-06 10:34:00 +00:00
"github.com/hashicorp/consul/agent/structs"
2019-10-04 18:37:34 +00:00
"github.com/hashicorp/consul/agent/token"
2019-02-27 19:28:31 +00:00
tokenStore "github.com/hashicorp/consul/agent/token"
2023-06-09 16:30:56 +00:00
"github.com/hashicorp/consul/api"
2023-02-06 17:14:35 +00:00
"github.com/hashicorp/consul/envoyextensions/xdscommon"
2022-05-19 20:03:46 +00:00
"github.com/hashicorp/consul/lib"
2019-12-06 19:01:34 +00:00
"github.com/hashicorp/consul/sdk/testutil"
2019-03-27 12:54:56 +00:00
"github.com/hashicorp/consul/sdk/testutil/retry"
2019-04-16 16:00:15 +00:00
"github.com/hashicorp/consul/testrpc"
2016-06-07 20:24:51 +00:00
"github.com/hashicorp/consul/types"
2023-06-09 16:30:56 +00:00
"github.com/hashicorp/consul/version"
2014-01-06 21:21:48 +00:00
)
2021-07-20 21:52:34 +00:00
func createACLTokenWithAgentReadPolicy ( t * testing . T , srv * HTTPHandlers ) string {
policyReq := & structs . ACLPolicy {
Name : "agent-read" ,
Rules : ` agent_prefix "" { policy = "read" } ` ,
2016-12-14 17:33:57 +00:00
}
2021-07-20 21:52:34 +00:00
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonReader ( policyReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2016-12-14 17:33:57 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2021-07-20 21:52:34 +00:00
tokenReq := & structs . ACLToken {
Description : "agent-read-token-for-test" ,
Policies : [ ] structs . ACLTokenPolicyLink { { Name : "agent-read" } } ,
2016-12-14 17:33:57 +00:00
}
2021-07-20 21:52:34 +00:00
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/token" , jsonReader ( tokenReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-07-20 21:52:34 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
svcToken := & structs . ACLToken { }
dec := json . NewDecoder ( resp . Body )
err := dec . Decode ( svcToken )
2021-07-20 21:52:34 +00:00
require . NoError ( t , err )
return svcToken . SecretID
2016-12-14 17:33:57 +00:00
}
func TestAgent_Services ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2014-01-21 01:06:44 +00:00
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-21 01:06:44 +00:00
srv1 := & structs . NodeService {
ID : "mysql" ,
Service : "mysql" ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2018-05-12 10:27:44 +00:00
Meta : map [ string ] string {
"foo" : "bar" ,
} ,
Port : 5000 ,
2014-01-21 01:06:44 +00:00
}
2023-01-10 16:24:02 +00:00
require . NoError ( t , a . State . AddServiceWithChecks ( srv1 , nil , "" , false ) )
2018-04-20 13:24:24 +00:00
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-11-03 15:12:36 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
decoder := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := decoder . Decode ( & val )
require . NoError ( t , err )
assert . Lenf ( t , val , 1 , "bad services: %v" , val )
2018-04-20 13:24:24 +00:00
assert . Equal ( t , 5000 , val [ "mysql" ] . Port )
2018-05-12 10:27:44 +00:00
assert . Equal ( t , srv1 . Meta , val [ "mysql" ] . Meta )
2014-01-21 01:06:44 +00:00
}
2019-04-16 16:00:15 +00:00
func TestAgent_ServicesFiltered ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-04-16 16:00:15 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-04-16 16:00:15 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
srv1 := & structs . NodeService {
ID : "mysql" ,
Service : "mysql" ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2019-04-16 16:00:15 +00:00
Meta : map [ string ] string {
"foo" : "bar" ,
} ,
Port : 5000 ,
}
2023-01-10 16:24:02 +00:00
require . NoError ( t , a . State . AddServiceWithChecks ( srv1 , nil , "" , false ) )
2019-04-16 16:00:15 +00:00
// Add another service
srv2 := & structs . NodeService {
ID : "redis" ,
Service : "redis" ,
Tags : [ ] string { "kv" } ,
Meta : map [ string ] string {
"foo" : "bar" ,
} ,
Port : 1234 ,
}
2023-01-10 16:24:02 +00:00
require . NoError ( t , a . State . AddServiceWithChecks ( srv2 , nil , "" , false ) )
2019-04-16 16:00:15 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services?filter=" + url . QueryEscape ( "foo in Meta" ) , nil )
2021-11-03 15:12:36 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
decoder := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := decoder . Decode ( & val )
2019-04-16 16:00:15 +00:00
require . NoError ( t , err )
require . Len ( t , val , 2 )
req , _ = http . NewRequest ( "GET" , "/v1/agent/services?filter=" + url . QueryEscape ( "kv in Tags" ) , nil )
2021-11-03 15:12:36 +00:00
resp = httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
decoder = json . NewDecoder ( resp . Body )
val = make ( map [ string ] * api . AgentService )
err = decoder . Decode ( & val )
2019-04-16 16:00:15 +00:00
require . NoError ( t , err )
require . Len ( t , val , 1 )
}
2018-03-12 20:05:06 +00:00
// This tests that the agent services endpoint (/v1/agent/services) returns
// Connect proxies.
2018-04-20 13:24:24 +00:00
func TestAgent_Services_ExternalConnectProxy ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-08 18:54:05 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-08 18:54:05 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-08 18:54:05 +00:00
srv1 := & structs . NodeService {
2018-09-12 16:07:47 +00:00
Kind : structs . ServiceKindConnectProxy ,
ID : "db-proxy" ,
Service : "db-proxy" ,
Port : 5000 ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "db" ,
2023-03-22 18:56:18 +00:00
Upstreams : structs . TestUpstreams ( t , false ) ,
2018-09-12 16:07:47 +00:00
} ,
2014-01-21 01:06:44 +00:00
}
2023-01-10 16:24:02 +00:00
a . State . AddServiceWithChecks ( srv1 , nil , "" , false )
2018-03-08 18:54:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-11-03 15:12:36 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
decoder := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := decoder . Decode ( & val )
require . NoError ( t , err )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Len ( t , val , 1 )
2018-03-11 16:31:31 +00:00
actual := val [ "db-proxy" ]
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , api . ServiceKindConnectProxy , actual . Kind )
assert . Equal ( t , srv1 . Proxy . ToAPI ( ) , actual . Proxy )
2014-01-21 01:06:44 +00:00
}
2018-09-27 13:33:12 +00:00
// Thie tests that a sidecar-registered service is returned as expected.
func TestAgent_Services_Sidecar ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-09-27 13:33:12 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-09-27 13:33:12 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
srv1 := & structs . NodeService {
Kind : structs . ServiceKindConnectProxy ,
ID : "db-sidecar-proxy" ,
Service : "db-sidecar-proxy" ,
Port : 5000 ,
// Set this internal state that we expect sidecar registrations to have.
LocallyRegisteredAsSidecar : true ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "db" ,
2023-03-22 18:56:18 +00:00
Upstreams : structs . TestUpstreams ( t , false ) ,
2021-04-12 15:35:14 +00:00
Mode : structs . ProxyModeTransparent ,
TransparentProxy : structs . TransparentProxyConfig {
OutboundListenerPort : 10101 ,
} ,
2018-09-27 13:33:12 +00:00
} ,
}
2023-01-10 16:24:02 +00:00
a . State . AddServiceWithChecks ( srv1 , nil , "" , false )
2018-09-27 13:33:12 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-11-03 15:12:36 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
decoder := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := decoder . Decode ( & val )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2021-11-03 15:12:36 +00:00
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Len ( t , val , 1 )
2018-09-27 13:33:12 +00:00
actual := val [ "db-sidecar-proxy" ]
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NotNil ( t , actual )
assert . Equal ( t , api . ServiceKindConnectProxy , actual . Kind )
assert . Equal ( t , srv1 . Proxy . ToAPI ( ) , actual . Proxy )
2018-09-27 13:33:12 +00:00
// Sanity check that LocalRegisteredAsSidecar is not in the output (assuming
2018-11-02 17:00:39 +00:00
// JSON encoding). Right now this is not the case because the services
2018-09-27 13:33:12 +00:00
// endpoint happens to use the api struct which doesn't include that field,
// but this test serves as a regression test incase we change the endpoint to
// return the internal struct later and accidentally expose some "internal"
// state.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . NotContains ( t , resp . Body . String ( ) , "LocallyRegisteredAsSidecar" )
assert . NotContains ( t , resp . Body . String ( ) , "locally_registered_as_sidecar" )
2018-09-27 13:33:12 +00:00
}
2020-03-26 16:20:56 +00:00
// This tests that a mesh gateway service is returned as expected.
2019-06-18 00:52:01 +00:00
func TestAgent_Services_MeshGateway ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-06-18 00:52:01 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-06-18 00:52:01 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
srv1 := & structs . NodeService {
Kind : structs . ServiceKindMeshGateway ,
ID : "mg-dc1-01" ,
Service : "mg-dc1" ,
Port : 8443 ,
Proxy : structs . ConnectProxyConfig {
Config : map [ string ] interface { } {
"foo" : "bar" ,
} ,
} ,
}
2023-01-10 16:24:02 +00:00
a . State . AddServiceWithChecks ( srv1 , nil , "" , false )
2019-06-18 00:52:01 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
2019-06-18 00:52:01 +00:00
require . NoError ( t , err )
2021-12-07 14:44:03 +00:00
2019-06-18 00:52:01 +00:00
require . Len ( t , val , 1 )
actual := val [ "mg-dc1-01" ]
require . NotNil ( t , actual )
require . Equal ( t , api . ServiceKindMeshGateway , actual . Kind )
2021-12-07 14:44:03 +00:00
// Proxy.ToAPI() creates an empty Upstream list instead of keeping nil so do the same with actual.
if actual . Proxy . Upstreams == nil {
actual . Proxy . Upstreams = make ( [ ] api . Upstream , 0 )
}
2019-06-18 00:52:01 +00:00
require . Equal ( t , srv1 . Proxy . ToAPI ( ) , actual . Proxy )
}
2020-03-26 16:20:56 +00:00
// This tests that a terminating gateway service is returned as expected.
func TestAgent_Services_TerminatingGateway ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-03-26 16:20:56 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2020-03-26 16:20:56 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
srv1 := & structs . NodeService {
Kind : structs . ServiceKindTerminatingGateway ,
ID : "tg-dc1-01" ,
Service : "tg-dc1" ,
Port : 8443 ,
Proxy : structs . ConnectProxyConfig {
Config : map [ string ] interface { } {
"foo" : "bar" ,
} ,
} ,
}
2023-01-10 16:24:02 +00:00
require . NoError ( t , a . State . AddServiceWithChecks ( srv1 , nil , "" , false ) )
2020-03-26 16:20:56 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
2020-03-26 16:20:56 +00:00
require . NoError ( t , err )
2021-12-07 14:44:03 +00:00
2020-03-26 16:20:56 +00:00
require . Len ( t , val , 1 )
actual := val [ "tg-dc1-01" ]
require . NotNil ( t , actual )
require . Equal ( t , api . ServiceKindTerminatingGateway , actual . Kind )
2021-12-07 14:44:03 +00:00
// Proxy.ToAPI() creates an empty Upstream list instead of keeping nil so do the same with actual.
if actual . Proxy . Upstreams == nil {
actual . Proxy . Upstreams = make ( [ ] api . Upstream , 0 )
}
2020-03-26 16:20:56 +00:00
require . Equal ( t , srv1 . Proxy . ToAPI ( ) , actual . Proxy )
}
2016-12-14 22:16:46 +00:00
func TestAgent_Services_ACLFilter ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2016-12-14 22:16:46 +00:00
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2021-12-03 20:36:28 +00:00
services := [ ] * structs . NodeService {
{
ID : "web" ,
Service : "web" ,
Port : 5000 ,
} ,
{
ID : "api" ,
Service : "api" ,
Port : 6000 ,
} ,
}
for _ , s := range services {
2023-01-10 16:24:02 +00:00
a . State . AddServiceWithChecks ( s , nil , "" , false )
2017-07-14 05:33:47 +00:00
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2021-12-07 14:44:03 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
if len ( val ) != 0 {
t . Fatalf ( "bad: %v" , val )
}
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2021-12-03 20:36:28 +00:00
} )
t . Run ( "limited token" , func ( t * testing . T ) {
token := testCreateToken ( t , a , `
service "web" {
policy = "read"
}
` )
2023-01-24 16:21:41 +00:00
req := httptest . NewRequest ( "GET" , "/v1/agent/services" , nil )
req . Header . Add ( "X-Consul-Token" , token )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 2 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2024-11-20 23:26:12 +00:00
// ensure ACL filtering occurs before bexpr filtering.
const bexprMatchingUserTokenPermissions = "Service matches `web.*`"
const bexprNotMatchingUserTokenPermissions = "Service matches `api.*`"
tokenWithWebRead := testCreateToken ( t , a , `
service "web" {
policy = "read"
}
` )
t . Run ( "request with filter that matches token permissions returns 1 result and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/services?filter=" + url . QueryEscape ( bexprMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithWebRead )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that does not match token permissions returns 0 results and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/services?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithWebRead )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that would normally match but without any token returns zero results and ResultsFilteredByACLs equal to false" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/services?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ string ] * api . AgentService
err := dec . Decode ( & val )
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
2016-12-14 22:16:46 +00:00
}
2018-09-27 14:00:51 +00:00
func TestAgent_Service ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-09-27 14:00:51 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) + `
2018-09-27 14:00:51 +00:00
services {
name = "web"
port = 8181
2019-08-10 13:15:19 +00:00
tagged_addresses {
wan {
address = "198.18.0.1"
port = 1818
}
}
2018-09-27 14:00:51 +00:00
}
` )
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
proxy := structs . TestConnectProxyConfig ( t )
proxy . DestinationServiceID = "web1"
// Define a valid local sidecar proxy service
sidecarProxy := & structs . ServiceDefinition {
Kind : structs . ServiceKindConnectProxy ,
Name : "web-sidecar-proxy" ,
Check : structs . CheckType {
TCP : "127.0.0.1:8000" ,
Interval : 10 * time . Second ,
} ,
Port : 8000 ,
Proxy : & proxy ,
2018-10-04 13:08:12 +00:00
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2018-09-27 14:00:51 +00:00
}
// Define an updated version. Be careful to copy it.
updatedProxy := * sidecarProxy
updatedProxy . Port = 9999
// Mangle the proxy config/upstreams into the expected for with defaults and
// API struct types.
expectProxy := proxy
expectProxy . Upstreams =
2021-07-26 21:12:29 +00:00
structs . TestAddDefaultsToUpstreams ( t , sidecarProxy . Proxy . Upstreams , * structs . DefaultEnterpriseMetaInDefaultPartition ( ) )
2018-09-27 14:00:51 +00:00
expectedResponse := & api . AgentService {
2021-07-26 21:12:29 +00:00
Kind : api . ServiceKindConnectProxy ,
ID : "web-sidecar-proxy" ,
Service : "web-sidecar-proxy" ,
Port : 8000 ,
Proxy : expectProxy . ToAPI ( ) ,
2018-10-04 13:08:12 +00:00
Weights : api . AgentWeights {
Passing : 1 ,
Warning : 1 ,
} ,
2020-11-19 21:27:31 +00:00
Meta : map [ string ] string { } ,
Tags : [ ] string { } ,
Datacenter : "dc1" ,
2018-09-27 14:00:51 +00:00
}
2021-07-22 18:20:45 +00:00
fillAgentServiceEnterpriseMeta ( expectedResponse , structs . DefaultEnterpriseMetaInDefaultPartition ( ) )
2021-07-26 21:12:29 +00:00
hash1 , err := hashstructure . Hash ( expectedResponse , nil )
2021-07-27 21:09:59 +00:00
require . NoError ( t , err , "failed to generate hash" )
2021-07-26 21:12:29 +00:00
expectedResponse . ContentHash = fmt . Sprintf ( "%x" , hash1 )
2018-09-27 14:00:51 +00:00
// Copy and modify
updatedResponse := * expectedResponse
updatedResponse . Port = 9999
2021-07-27 21:09:59 +00:00
updatedResponse . ContentHash = "" // clear field before hashing
2021-07-26 21:12:29 +00:00
hash2 , err := hashstructure . Hash ( updatedResponse , nil )
2021-07-27 21:09:59 +00:00
require . NoError ( t , err , "failed to generate hash" )
2021-07-26 21:12:29 +00:00
updatedResponse . ContentHash = fmt . Sprintf ( "%x" , hash2 )
2018-09-27 14:00:51 +00:00
2018-10-04 13:08:12 +00:00
// Simple response for non-proxy service registered in TestAgent config
2018-09-27 14:00:51 +00:00
expectWebResponse := & api . AgentService {
2021-07-27 21:09:59 +00:00
ID : "web" ,
Service : "web" ,
Port : 8181 ,
2018-10-04 13:08:12 +00:00
Weights : api . AgentWeights {
Passing : 1 ,
Warning : 1 ,
} ,
2019-08-10 13:15:19 +00:00
TaggedAddresses : map [ string ] api . ServiceAddress {
2020-06-16 17:19:31 +00:00
"wan" : {
2019-08-10 13:15:19 +00:00
Address : "198.18.0.1" ,
Port : 1818 ,
} ,
} ,
2020-11-19 21:27:31 +00:00
Meta : map [ string ] string { } ,
Tags : [ ] string { } ,
Datacenter : "dc1" ,
2018-09-27 14:00:51 +00:00
}
2021-07-22 18:20:45 +00:00
fillAgentServiceEnterpriseMeta ( expectWebResponse , structs . DefaultEnterpriseMetaInDefaultPartition ( ) )
2021-07-27 21:09:59 +00:00
hash3 , err := hashstructure . Hash ( expectWebResponse , nil )
require . NoError ( t , err , "failed to generate hash" )
expectWebResponse . ContentHash = fmt . Sprintf ( "%x" , hash3 )
2018-09-27 14:00:51 +00:00
tests := [ ] struct {
name string
2023-02-06 15:35:52 +00:00
policies string
2018-09-27 14:00:51 +00:00
url string
updateFunc func ( )
wantWait time . Duration
wantCode int
wantErr string
wantResp * api . AgentService
} {
{
name : "simple fetch - proxy" ,
url : "/v1/agent/service/web-sidecar-proxy" ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
{
name : "simple fetch - non-proxy" ,
url : "/v1/agent/service/web" ,
wantCode : 200 ,
wantResp : expectWebResponse ,
} ,
{
name : "blocking fetch timeout, no change" ,
url : "/v1/agent/service/web-sidecar-proxy?hash=" + expectedResponse . ContentHash + "&wait=100ms" ,
wantWait : 100 * time . Millisecond ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
{
name : "blocking fetch old hash should return immediately" ,
url : "/v1/agent/service/web-sidecar-proxy?hash=123456789abcd&wait=10m" ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
{
name : "blocking fetch returns change" ,
url : "/v1/agent/service/web-sidecar-proxy?hash=" + expectedResponse . ContentHash ,
updateFunc : func ( ) {
time . Sleep ( 100 * time . Millisecond )
// Re-register with new proxy config, make sure we copy the struct so we
// don't alter it and affect later test cases.
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( updatedProxy ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-09-27 14:00:51 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-09-27 14:00:51 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
} ,
wantWait : 100 * time . Millisecond ,
wantCode : 200 ,
wantResp : & updatedResponse ,
} ,
{
// This test exercises a case that caused a busy loop to eat CPU for the
// entire duration of the blocking query. If a service gets re-registered
// wth same proxy config then the old proxy config chan is closed causing
// blocked watchset.Watch to return false indicating a change. But since
// the hash is the same when the blocking fn is re-called we should just
// keep blocking on the next iteration. The bug hit was that the WatchSet
// ws was not being reset in the loop and so when you try to `Watch` it
// the second time it just returns immediately making the blocking loop
// into a busy-poll!
//
// This test though doesn't catch that because busy poll still has the
2019-03-06 17:13:28 +00:00
// correct external behavior. I don't want to instrument the loop to
2018-09-27 14:00:51 +00:00
// assert it's not executing too fast here as I can't think of a clean way
// and the issue is fixed now so this test doesn't actually catch the
2019-03-06 17:13:28 +00:00
// error, but does provide an easy way to verify the behavior by hand:
2018-09-27 14:00:51 +00:00
// 1. Make this test fail e.g. change wantErr to true
// 2. Add a log.Println or similar into the blocking loop/function
// 3. See whether it's called just once or many times in a tight loop.
name : "blocking fetch interrupted with no change (same hash)" ,
url : "/v1/agent/service/web-sidecar-proxy?wait=200ms&hash=" + expectedResponse . ContentHash ,
updateFunc : func ( ) {
time . Sleep ( 100 * time . Millisecond )
// Re-register with _same_ proxy config
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( sidecarProxy ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-09-27 14:00:51 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-09-27 14:00:51 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
} ,
wantWait : 200 * time . Millisecond ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
{
// When we reload config, the agent pauses Anti-entropy, then clears all
// services (which causes their watch chans to be closed) before loading
// state from config/snapshot again). If we do that naively then we don't
// just get a spurios wakeup on the watch if the service didn't change,
// but we get it wakeup and then race with the reload and probably see no
2020-01-27 13:00:33 +00:00
// services and return a 404 error which is gross. This test exercises
2018-09-27 14:00:51 +00:00
// that - even though the registrations were from API not config, they are
// persisted and cleared/reloaded from snapshot which has same effect.
//
// The fix for this test is to allow the same mechanism that pauses
// Anti-entropy during reload to also pause the hash blocking loop so we
// don't resume until the state is reloaded and we get a chance to see if
// it actually changed or not.
name : "blocking fetch interrupted by reload shouldn't 404 - no change" ,
url : "/v1/agent/service/web-sidecar-proxy?wait=200ms&hash=" + expectedResponse . ContentHash ,
updateFunc : func ( ) {
time . Sleep ( 100 * time . Millisecond )
// Reload
2020-06-10 20:47:35 +00:00
require . NoError ( t , a . reloadConfigInternal ( a . Config ) )
2018-09-27 14:00:51 +00:00
} ,
// Should eventually timeout since there is no actual change
wantWait : 200 * time . Millisecond ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
{
// As above but test actually altering the service with the config reload.
// This simulates the API registration being overridden by a different one
// on disk during reload.
name : "blocking fetch interrupted by reload shouldn't 404 - changes" ,
url : "/v1/agent/service/web-sidecar-proxy?wait=10m&hash=" + expectedResponse . ContentHash ,
updateFunc : func ( ) {
time . Sleep ( 100 * time . Millisecond )
// Reload
newConfig := * a . Config
newConfig . Services = append ( newConfig . Services , & updatedProxy )
2020-06-10 20:47:35 +00:00
require . NoError ( t , a . reloadConfigInternal ( & newConfig ) )
2018-09-27 14:00:51 +00:00
} ,
wantWait : 100 * time . Millisecond ,
wantCode : 200 ,
wantResp : & updatedResponse ,
} ,
{
2022-01-05 17:11:03 +00:00
name : "err: non-existent proxy" ,
url : "/v1/agent/service/nope" ,
2022-01-05 20:18:08 +00:00
wantErr : fmt . Sprintf ( "unknown service ID: %s" , structs . NewServiceID ( "nope" , nil ) ) ,
2018-09-27 14:00:51 +00:00
} ,
{
name : "err: bad ACL for service" ,
url : "/v1/agent/service/web-sidecar-proxy" ,
// Limited token doesn't grant read to the service
2023-02-06 15:35:52 +00:00
policies : `
2018-09-27 14:00:51 +00:00
key "" {
policy = "read"
}
` ,
// Note that because we return ErrPermissionDenied and handle writing
// status at a higher level helper this actually gets a 200 in this test
// case so just assert that it was an error.
wantErr : "Permission denied" ,
} ,
{
name : "good ACL for service" ,
url : "/v1/agent/service/web-sidecar-proxy" ,
// Limited token doesn't grant read to the service
2023-02-06 15:35:52 +00:00
policies : `
2018-09-27 14:00:51 +00:00
service "web-sidecar-proxy" {
policy = "read"
}
` ,
wantCode : 200 ,
wantResp : expectedResponse ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
// Register the basic service to ensure it's in a known state to start.
{
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( sidecarProxy ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-09-27 14:00:51 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
2018-09-27 14:00:51 +00:00
}
req , _ := http . NewRequest ( "GET" , tt . url , nil )
// Inject the root token for tests that don't care about ACL
2021-08-20 16:57:45 +00:00
token := "root"
2023-02-06 15:35:52 +00:00
if tt . policies != "" {
2018-09-27 14:00:51 +00:00
// Create new token and use that.
2023-02-06 15:35:52 +00:00
token = testCreateToken ( t , a , tt . policies )
2018-09-27 14:00:51 +00:00
}
req . Header . Set ( "X-Consul-Token" , token )
resp := httptest . NewRecorder ( )
if tt . updateFunc != nil {
go tt . updateFunc ( )
}
start := time . Now ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2019-07-20 13:37:19 +00:00
elapsed := time . Since ( start )
2018-09-27 14:00:51 +00:00
if tt . wantErr != "" {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Contains ( t , strings . ToLower ( resp . Body . String ( ) ) , strings . ToLower ( tt . wantErr ) )
2018-09-27 14:00:51 +00:00
}
if tt . wantCode != 0 {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , tt . wantCode , resp . Code , "body: %s" , resp . Body . String ( ) )
2018-09-27 14:00:51 +00:00
}
if tt . wantWait != 0 {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , elapsed >= tt . wantWait , "should have waited at least %s, " +
2018-09-27 14:00:51 +00:00
"took %s" , tt . wantWait , elapsed )
}
if tt . wantResp != nil {
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := & api . AgentService { }
err := dec . Decode ( & val )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2021-12-07 14:44:03 +00:00
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , tt . wantResp , val )
assert . Equal ( t , tt . wantResp . ContentHash , resp . Header ( ) . Get ( "X-Consul-ContentHash" ) )
2018-09-27 14:00:51 +00:00
}
} )
}
}
2016-12-14 17:33:57 +00:00
func TestAgent_Checks ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2014-01-21 01:06:44 +00:00
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-21 01:06:44 +00:00
chk1 := & structs . HealthCheck {
2021-08-03 22:26:49 +00:00
Node : a . Config . NodeName ,
CheckID : "mysql" ,
Name : "mysql" ,
Interval : "30s" ,
Timeout : "5s" ,
Status : api . HealthPassing ,
2014-01-21 01:06:44 +00:00
}
2023-01-10 16:24:02 +00:00
a . State . AddCheck ( chk1 , "" , false )
2014-01-21 01:06:44 +00:00
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ types . CheckID ] * structs . HealthCheck
err := dec . Decode ( & val )
2014-01-21 01:06:44 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
2021-12-07 14:44:03 +00:00
2014-01-21 01:06:44 +00:00
if len ( val ) != 1 {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad checks: %v" , val )
2014-01-21 01:06:44 +00:00
}
2017-04-19 23:00:11 +00:00
if val [ "mysql" ] . Status != api . HealthPassing {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad check: %v" , val )
2014-01-21 01:06:44 +00:00
}
2021-08-03 22:26:49 +00:00
if val [ "mysql" ] . Node != chk1 . Node {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad check: %v" , val )
2021-08-03 22:26:49 +00:00
}
if val [ "mysql" ] . Interval != chk1 . Interval {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad check: %v" , val )
2021-08-03 22:26:49 +00:00
}
if val [ "mysql" ] . Timeout != chk1 . Timeout {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad check: %v" , val )
2021-08-03 22:26:49 +00:00
}
2014-01-21 01:06:44 +00:00
}
2019-04-16 16:00:15 +00:00
func TestAgent_ChecksWithFilter ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-04-16 16:00:15 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-04-16 16:00:15 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
chk1 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql" ,
Name : "mysql" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
a . State . AddCheck ( chk1 , "" , false )
2019-04-16 16:00:15 +00:00
chk2 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "redis" ,
Name : "redis" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
a . State . AddCheck ( chk2 , "" , false )
2019-04-16 16:00:15 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks?filter=" + url . QueryEscape ( "Name == `redis`" ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ types . CheckID ] * structs . HealthCheck
err := dec . Decode ( & val )
2019-04-16 16:00:15 +00:00
require . NoError ( t , err )
2021-12-07 14:44:03 +00:00
2019-04-16 16:00:15 +00:00
require . Len ( t , val , 1 )
_ , ok := val [ "redis" ]
require . True ( t , ok )
}
2019-01-07 14:39:23 +00:00
func TestAgent_HealthServiceByID ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-01-07 14:39:23 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-01-07 14:39:23 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
service := & structs . NodeService {
ID : "mysql" ,
Service : "mysql" ,
}
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : service ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
}
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "mysql2" ,
Service : "mysql2" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "mysql3" ,
Service : "mysql3" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
chk1 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql" ,
Name : "mysql" ,
ServiceID : "mysql" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err := a . State . AddCheck ( chk1 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk2 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql" ,
Name : "mysql" ,
ServiceID : "mysql" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk2 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk3 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql2" ,
Name : "mysql2" ,
ServiceID : "mysql2" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk3 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk4 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql2" ,
Name : "mysql2" ,
ServiceID : "mysql2" ,
Status : api . HealthWarning ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk4 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk5 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql3" ,
Name : "mysql3" ,
ServiceID : "mysql3" ,
Status : api . HealthMaint ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk5 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk6 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql3" ,
Name : "mysql3" ,
ServiceID : "mysql3" ,
Status : api . HealthCritical ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk6 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
eval := func ( t * testing . T , url string , expectedCode int , expected string ) {
t . Helper ( )
t . Run ( "format=text" , func ( t * testing . T ) {
t . Helper ( )
req , _ := http . NewRequest ( "GET" , url + "?format=text" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
body := resp . Body . String ( )
if got , want := resp . Code , expectedCode ; got != want {
t . Fatalf ( "returned bad status: expected %d, but had: %d" , expectedCode , resp . Code )
2019-01-07 14:39:23 +00:00
}
if got , want := body , expected ; got != want {
t . Fatalf ( "got body %q want %q" , got , want )
}
} )
t . Run ( "format=json" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , url , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if got , want := resp . Code , expectedCode ; got != want {
t . Fatalf ( "returned bad status: expected %d, but had: %d" , expectedCode , resp . Code )
2019-01-07 14:39:23 +00:00
}
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
data := & api . AgentServiceChecksInfo { }
if err := dec . Decode ( data ) ; err != nil {
t . Fatalf ( "Cannot convert result from JSON: %v" , err )
2019-01-07 14:39:23 +00:00
}
2021-12-07 14:44:03 +00:00
if resp . Code != http . StatusNotFound {
2019-01-07 14:39:23 +00:00
if data != nil && data . AggregatedStatus != expected {
t . Fatalf ( "got body %v want %v" , data , expected )
}
}
} )
}
t . Run ( "passing checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/id/mysql" , http . StatusOK , "passing" )
} )
t . Run ( "warning checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/id/mysql2" , http . StatusTooManyRequests , "warning" )
} )
t . Run ( "critical checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/id/mysql3" , http . StatusServiceUnavailable , "critical" )
} )
t . Run ( "unknown serviceid" , func ( t * testing . T ) {
2019-12-10 02:26:41 +00:00
eval ( t , "/v1/agent/health/service/id/mysql1" , http . StatusNotFound , fmt . Sprintf ( "ServiceId %s not found" , structs . ServiceIDString ( "mysql1" , nil ) ) )
2019-01-07 14:39:23 +00:00
} )
nodeCheck := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "diskCheck" ,
Name : "diskCheck" ,
Status : api . HealthCritical ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( nodeCheck , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
t . Run ( "critical check on node" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/id/mysql" , http . StatusServiceUnavailable , "critical" )
} )
2019-12-10 02:26:41 +00:00
err = a . State . RemoveCheck ( nodeCheck . CompoundCheckID ( ) )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
nodeCheck = & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "_node_maintenance" ,
Name : "_node_maintenance" ,
Status : api . HealthMaint ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( nodeCheck , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
t . Run ( "maintenance check on node" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/id/mysql" , http . StatusServiceUnavailable , "maintenance" )
} )
}
func TestAgent_HealthServiceByName ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-01-07 14:39:23 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-01-07 14:39:23 +00:00
defer a . Shutdown ( )
service := & structs . NodeService {
ID : "mysql1" ,
Service : "mysql-pool-r" ,
}
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : service ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
}
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "mysql2" ,
Service : "mysql-pool-r" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "mysql3" ,
Service : "mysql-pool-rw" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "mysql4" ,
Service : "mysql-pool-rw" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "httpd1" ,
Service : "httpd" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2019-01-07 14:39:23 +00:00
ID : "httpd2" ,
Service : "httpd" ,
}
2021-12-07 14:44:03 +00:00
if err := a . AddService ( serviceReq ) ; err != nil {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "err: %v" , err )
}
chk1 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql1" ,
Name : "mysql1" ,
ServiceID : "mysql1" ,
ServiceName : "mysql-pool-r" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err := a . State . AddCheck ( chk1 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk2 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql1" ,
Name : "mysql1" ,
ServiceID : "mysql1" ,
ServiceName : "mysql-pool-r" ,
Status : api . HealthWarning ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk2 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk3 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql2" ,
Name : "mysql2" ,
ServiceID : "mysql2" ,
ServiceName : "mysql-pool-r" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk3 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk4 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql2" ,
Name : "mysql2" ,
ServiceID : "mysql2" ,
ServiceName : "mysql-pool-r" ,
Status : api . HealthCritical ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk4 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk5 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql3" ,
Name : "mysql3" ,
ServiceID : "mysql3" ,
ServiceName : "mysql-pool-rw" ,
Status : api . HealthWarning ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk5 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk6 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "mysql4" ,
Name : "mysql4" ,
ServiceID : "mysql4" ,
ServiceName : "mysql-pool-rw" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk6 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk7 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "httpd1" ,
Name : "httpd1" ,
ServiceID : "httpd1" ,
ServiceName : "httpd" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk7 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
chk8 := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "httpd2" ,
Name : "httpd2" ,
ServiceID : "httpd2" ,
ServiceName : "httpd" ,
Status : api . HealthPassing ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( chk8 , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
eval := func ( t * testing . T , url string , expectedCode int , expected string ) {
t . Helper ( )
t . Run ( "format=text" , func ( t * testing . T ) {
t . Helper ( )
req , _ := http . NewRequest ( "GET" , url + "?format=text" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if got , want := resp . Code , expectedCode ; got != want {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "returned bad status: %d. Body: %q" , resp . Code , resp . Body . String ( ) )
}
2021-12-07 14:44:03 +00:00
if got , want := resp . Body . String ( ) , expected ; got != want {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "got body %q want %q" , got , want )
}
} )
t . Run ( "format=json" , func ( t * testing . T ) {
t . Helper ( )
req , _ := http . NewRequest ( "GET" , url , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
data := make ( [ ] * api . AgentServiceChecksInfo , 0 )
if err := dec . Decode ( & data ) ; err != nil {
t . Fatalf ( "Cannot convert result from JSON: %v" , err )
2019-01-07 14:39:23 +00:00
}
2021-12-07 14:44:03 +00:00
if got , want := resp . Code , expectedCode ; got != want {
2019-01-07 14:39:23 +00:00
t . Fatalf ( "returned bad code: %d. Body: %#v" , resp . Code , data )
}
if resp . Code != http . StatusNotFound {
2021-12-07 14:44:03 +00:00
matched := false
for _ , d := range data {
if d . AggregatedStatus == expected {
matched = true
break
}
}
if ! matched {
t . Fatalf ( "got wrong status, wanted %#v" , expected )
2019-01-07 14:39:23 +00:00
}
}
} )
}
t . Run ( "passing checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/httpd" , http . StatusOK , "passing" )
} )
t . Run ( "warning checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/mysql-pool-rw" , http . StatusTooManyRequests , "warning" )
} )
t . Run ( "critical checks" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/mysql-pool-r" , http . StatusServiceUnavailable , "critical" )
} )
t . Run ( "unknown serviceName" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/test" , http . StatusNotFound , "ServiceName test Not Found" )
} )
nodeCheck := & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "diskCheck" ,
Name : "diskCheck" ,
Status : api . HealthCritical ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( nodeCheck , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
t . Run ( "critical check on node" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/mysql-pool-r" , http . StatusServiceUnavailable , "critical" )
} )
2019-12-10 02:26:41 +00:00
err = a . State . RemoveCheck ( nodeCheck . CompoundCheckID ( ) )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
nodeCheck = & structs . HealthCheck {
Node : a . Config . NodeName ,
CheckID : "_node_maintenance" ,
Name : "_node_maintenance" ,
Status : api . HealthMaint ,
}
2023-01-10 16:24:02 +00:00
err = a . State . AddCheck ( nodeCheck , "" , false )
2019-01-07 14:39:23 +00:00
if err != nil {
t . Fatalf ( "Err: %v" , err )
}
t . Run ( "maintenance check on node" , func ( t * testing . T ) {
eval ( t , "/v1/agent/health/service/name/mysql-pool-r" , http . StatusServiceUnavailable , "maintenance" )
} )
}
2020-01-31 14:57:38 +00:00
func TestAgent_HealthServicesACLEnforcement ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-01-31 14:57:38 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfigWithParams ( nil ) )
2020-01-31 14:57:38 +00:00
defer a . Shutdown ( )
service := & structs . NodeService {
ID : "mysql1" ,
Service : "mysql" ,
}
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : service ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
}
require . NoError ( t , a . AddService ( serviceReq ) )
2020-01-31 14:57:38 +00:00
2021-12-07 14:44:03 +00:00
serviceReq . Service = & structs . NodeService {
2020-01-31 14:57:38 +00:00
ID : "foo1" ,
Service : "foo" ,
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2020-01-31 14:57:38 +00:00
// no token
t . Run ( "no-token-health-by-id" , func ( t * testing . T ) {
req , err := http . NewRequest ( "GET" , "/v1/agent/health/service/id/mysql1" , nil )
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2020-01-31 14:57:38 +00:00
} )
t . Run ( "no-token-health-by-name" , func ( t * testing . T ) {
req , err := http . NewRequest ( "GET" , "/v1/agent/health/service/name/mysql" , nil )
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2020-01-31 14:57:38 +00:00
} )
t . Run ( "root-token-health-by-id" , func ( t * testing . T ) {
req , err := http . NewRequest ( "GET" , "/v1/agent/health/service/id/foo1" , nil )
require . NoError ( t , err )
2021-12-07 12:48:50 +00:00
req . Header . Add ( "X-Consul-Token" , TestDefaultInitialManagementToken )
2020-01-31 14:57:38 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2020-01-31 14:57:38 +00:00
} )
t . Run ( "root-token-health-by-name" , func ( t * testing . T ) {
req , err := http . NewRequest ( "GET" , "/v1/agent/health/service/name/foo" , nil )
require . NoError ( t , err )
2021-12-07 12:48:50 +00:00
req . Header . Add ( "X-Consul-Token" , TestDefaultInitialManagementToken )
2020-01-31 14:57:38 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2020-01-31 14:57:38 +00:00
} )
}
2016-12-14 22:16:46 +00:00
func TestAgent_Checks_ACLFilter ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2016-12-14 22:16:46 +00:00
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2021-12-03 20:36:28 +00:00
checks := structs . HealthChecks {
{
Node : a . Config . NodeName ,
CheckID : "web" ,
ServiceName : "web" ,
Status : api . HealthPassing ,
} ,
{
Node : a . Config . NodeName ,
CheckID : "api" ,
ServiceName : "api" ,
Status : api . HealthPassing ,
} ,
}
for _ , c := range checks {
2023-01-10 16:24:02 +00:00
a . State . AddCheck ( c , "" , false )
2016-12-14 22:16:46 +00:00
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2021-12-07 14:44:03 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := make ( map [ types . CheckID ] * structs . HealthCheck )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2021-12-03 20:36:28 +00:00
} )
t . Run ( "limited token" , func ( t * testing . T ) {
token := testCreateToken ( t , a , fmt . Sprintf ( `
service "web" {
policy = "read"
}
node "%s" {
policy = "read"
}
` , a . Config . NodeName ) )
2023-01-24 16:21:41 +00:00
req := httptest . NewRequest ( "GET" , "/v1/agent/checks" , nil )
req . Header . Add ( "X-Consul-Token" , token )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
var val map [ types . CheckID ] * structs . HealthCheck
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := make ( map [ types . CheckID ] * structs . HealthCheck )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 2 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2024-11-20 23:26:12 +00:00
// ensure ACL filtering occurs before bexpr filtering.
const bexprMatchingUserTokenPermissions = "ServiceName matches `web.*`"
const bexprNotMatchingUserTokenPermissions = "ServiceName matches `api.*`"
tokenWithWebRead := testCreateToken ( t , a , `
service "web" {
policy = "read"
}
` )
t . Run ( "request with filter that matches token permissions returns 1 result and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks?filter=" + url . QueryEscape ( bexprMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithWebRead )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( map [ types . CheckID ] * structs . HealthCheck )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that does not match token permissions returns 0 results and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithWebRead )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( map [ types . CheckID ] * structs . HealthCheck )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that would normally match but without any token returns zero results and ResultsFilteredByACLs equal to false" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/checks?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( map [ types . CheckID ] * structs . HealthCheck )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Self ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2014-05-25 23:59:48 +00:00
2020-08-26 15:04:11 +00:00
cases := map [ string ] struct {
hcl string
expectXDS bool
2022-08-19 17:07:22 +00:00
grpcTLS bool
2020-08-26 15:04:11 +00:00
} {
2022-08-19 17:07:22 +00:00
"no grpc" : {
2020-08-26 15:04:11 +00:00
hcl : `
node_meta {
somekey = "somevalue"
}
2022-08-19 17:07:22 +00:00
ports = {
grpc = - 1
2022-09-29 03:27:11 +00:00
grpc_tls = - 1
} ` ,
2022-08-19 17:07:22 +00:00
expectXDS : false ,
grpcTLS : false ,
2020-08-26 15:04:11 +00:00
} ,
2022-08-19 17:07:22 +00:00
"plaintext grpc" : {
2020-08-26 15:04:11 +00:00
hcl : `
node_meta {
somekey = "somevalue"
}
2022-09-29 03:27:11 +00:00
ports = {
grpc_tls = - 1
} ` ,
2022-08-19 17:07:22 +00:00
expectXDS : true ,
grpcTLS : false ,
} ,
"tls grpc" : {
hcl : `
node_meta {
somekey = "somevalue"
2022-09-29 03:27:11 +00:00
} ` ,
2022-08-19 17:07:22 +00:00
expectXDS : true ,
grpcTLS : true ,
2020-08-26 15:04:11 +00:00
} ,
2014-05-25 23:59:48 +00:00
}
2020-08-26 15:04:11 +00:00
for name , tc := range cases {
tc := tc
t . Run ( name , func ( t * testing . T ) {
2022-08-19 17:07:22 +00:00
a := StartTestAgent ( t , TestAgent {
HCL : tc . hcl ,
UseGRPCTLS : tc . grpcTLS ,
} )
2020-08-26 15:04:11 +00:00
defer a . Shutdown ( )
2014-05-27 22:09:28 +00:00
2020-08-26 15:04:11 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
req , _ := http . NewRequest ( "GET" , "/v1/agent/self" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := & Self { }
require . NoError ( t , dec . Decode ( val ) )
2015-07-30 19:02:37 +00:00
2020-08-26 15:04:11 +00:00
require . Equal ( t , a . Config . SerfPortLAN , int ( val . Member . Port ) )
2021-12-07 14:44:03 +00:00
require . Equal ( t , a . Config . SerfPortLAN , int ( val . DebugConfig [ "SerfPortLAN" ] . ( float64 ) ) )
2020-08-26 15:04:11 +00:00
cs , err := a . GetLANCoordinate ( )
require . NoError ( t , err )
require . Equal ( t , cs [ a . config . SegmentName ] , val . Coord )
2023-07-12 19:34:39 +00:00
delete ( val . Meta , structs . MetaSegmentKey ) // Added later, not in config.
delete ( val . Meta , structs . MetaConsulVersion ) // Added later, not in config.
2020-08-26 15:04:11 +00:00
require . Equal ( t , a . config . NodeMeta , val . Meta )
if tc . expectXDS {
require . NotNil ( t , val . XDS , "xds component missing when gRPC is enabled" )
require . Equal ( t ,
2023-02-06 17:14:35 +00:00
map [ string ] [ ] string { "envoy" : xdscommon . EnvoyVersions } ,
2020-08-26 15:04:11 +00:00
val . XDS . SupportedProxies ,
)
2022-09-01 17:32:11 +00:00
require . Equal ( t , a . Config . GRPCTLSPort , val . XDS . Ports . TLS )
require . Equal ( t , a . Config . GRPCPort , val . XDS . Ports . Plaintext )
2022-08-19 17:07:22 +00:00
if tc . grpcTLS {
require . Equal ( t , a . Config . GRPCTLSPort , val . XDS . Port )
} else {
require . Equal ( t , a . Config . GRPCPort , val . XDS . Port )
}
2020-08-26 15:04:11 +00:00
} else {
require . Nil ( t , val . XDS , "xds component should be missing when gRPC is disabled" )
}
} )
2016-12-13 06:09:35 +00:00
}
2014-05-25 23:59:48 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Self_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2016-12-14 17:33:57 +00:00
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/self" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2022-01-20 12:47:50 +00:00
t . Run ( "agent recovery token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/self" , nil )
req . Header . Add ( "X-Consul-Token" , "towel" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/self" , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
}
2017-08-08 20:05:38 +00:00
func TestAgent_Metrics_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-08-08 20:05:38 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-08-08 20:05:38 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2017-08-08 20:05:38 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/metrics" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-08-08 20:05:38 +00:00
} )
2022-01-20 12:47:50 +00:00
t . Run ( "agent recovery token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/metrics" , nil )
req . Header . Add ( "X-Consul-Token" , "towel" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-08-08 20:05:38 +00:00
} )
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/metrics" , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-08-08 20:05:38 +00:00
} )
}
2023-08-04 18:27:48 +00:00
func newDefaultBaseDeps ( t * testing . T ) BaseDeps {
dataDir := testutil . TempDir ( t , "acl-agent" )
logBuffer := testutil . NewLogBuffer ( t )
logger := hclog . NewInterceptLogger ( nil )
loader := func ( source config . Source ) ( config . LoadResult , error ) {
dataDir := fmt . Sprintf ( ` data_dir = "%s" ` , dataDir )
opts := config . LoadOpts {
HCL : [ ] string { TestConfigHCL ( NodeID ( ) ) , "" , dataDir } ,
DefaultConfig : source ,
}
result , err := config . Load ( opts )
if result . RuntimeConfig != nil {
result . RuntimeConfig . Telemetry . Disable = true
}
return result , err
}
bd , err := NewBaseDeps ( loader , logBuffer , logger )
require . NoError ( t , err )
return bd
}
2021-07-15 23:04:24 +00:00
func TestHTTPHandlers_AgentMetricsStream_ACLDeny ( t * testing . T ) {
2024-09-05 14:50:46 +00:00
t . Skip ( "this test panics without a license manager in enterprise" )
2023-08-04 18:27:48 +00:00
bd := newDefaultBaseDeps ( t )
2021-07-15 23:04:24 +00:00
bd . Tokens = new ( tokenStore . Store )
sink := metrics . NewInmemSink ( 30 * time . Millisecond , time . Second )
2022-05-19 20:03:46 +00:00
bd . MetricsConfig = & lib . MetricsConfig {
Handler : sink ,
}
2023-08-09 16:36:58 +00:00
mockDelegate := delegateMock { }
mockDelegate . On ( "LicenseCheck" ) . Return ( )
d := fakeResolveTokenDelegate { delegate : & mockDelegate , authorizer : acl . DenyAll ( ) }
2021-07-15 23:04:24 +00:00
agent := & Agent {
baseDeps : bd ,
delegate : d ,
tokens : bd . Tokens ,
config : & config . RuntimeConfig { NodeName : "the-node" } ,
logger : hclog . NewInterceptLogger ( nil ) ,
}
h := HTTPHandlers { agent : agent , denylist : NewDenylist ( nil ) }
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
resp := httptest . NewRecorder ( )
req , err := http . NewRequestWithContext ( ctx , http . MethodGet , "/v1/agent/metrics/stream" , nil )
require . NoError ( t , err )
2023-06-30 03:00:29 +00:00
handle := h . handler ( )
2021-07-15 23:04:24 +00:00
handle . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
require . Contains ( t , resp . Body . String ( ) , "Permission denied" )
}
func TestHTTPHandlers_AgentMetricsStream ( t * testing . T ) {
2024-09-05 14:50:46 +00:00
t . Skip ( "this test panics without a license manager in enterprise" )
2023-08-04 18:27:48 +00:00
bd := newDefaultBaseDeps ( t )
2021-07-15 23:04:24 +00:00
bd . Tokens = new ( tokenStore . Store )
sink := metrics . NewInmemSink ( 20 * time . Millisecond , time . Second )
2022-05-19 20:03:46 +00:00
bd . MetricsConfig = & lib . MetricsConfig {
Handler : sink ,
}
2023-08-09 16:36:58 +00:00
mockDelegate := delegateMock { }
mockDelegate . On ( "LicenseCheck" ) . Return ( )
d := fakeResolveTokenDelegate { delegate : & mockDelegate , authorizer : acl . ManageAll ( ) }
2021-07-15 23:04:24 +00:00
agent := & Agent {
baseDeps : bd ,
delegate : d ,
tokens : bd . Tokens ,
config : & config . RuntimeConfig { NodeName : "the-node" } ,
logger : hclog . NewInterceptLogger ( nil ) ,
}
h := HTTPHandlers { agent : agent , denylist : NewDenylist ( nil ) }
ctx , cancel := context . WithTimeout ( context . Background ( ) , 60 * time . Millisecond )
defer cancel ( )
// produce some metrics
go func ( ) {
for ctx . Err ( ) == nil {
sink . SetGauge ( [ ] string { "the-key" } , 12 )
time . Sleep ( 5 * time . Millisecond )
}
} ( )
resp := httptest . NewRecorder ( )
req , err := http . NewRequestWithContext ( ctx , http . MethodGet , "/v1/agent/metrics/stream" , nil )
require . NoError ( t , err )
2023-06-30 03:00:29 +00:00
handle := h . handler ( )
2021-07-15 23:04:24 +00:00
handle . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
decoder := json . NewDecoder ( resp . Body )
var summary metrics . MetricsSummary
err = decoder . Decode ( & summary )
require . NoError ( t , err )
expected := [ ] metrics . GaugeValue {
{ Name : "the-key" , Value : 12 , DisplayLabels : map [ string ] string { } } ,
}
require . Equal ( t , expected , summary . Gauges )
// There should be at least two intervals worth of metrics
err = decoder . Decode ( & summary )
require . NoError ( t , err )
require . Equal ( t , expected , summary . Gauges )
}
type fakeResolveTokenDelegate struct {
delegate
authorizer acl . Authorizer
}
2022-06-17 09:24:43 +00:00
func ( f fakeResolveTokenDelegate ) ResolveTokenAndDefaultMeta ( _ string , _ * acl . EnterpriseMeta , _ * acl . AuthorizerContext ) ( resolver . Result , error ) {
return resolver . Result { Authorizer : f . authorizer } , nil
2021-07-15 23:04:24 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Reload ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-08-06 23:46:09 +00:00
dc1 := "dc1"
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2017-09-25 18:40:42 +00:00
services = [
{
name = "redis"
}
]
watches = [
{
2018-08-06 23:46:09 +00:00
datacenter = "`+dc1+`"
2017-09-25 18:40:42 +00:00
type = "key"
key = "test"
handler = "true"
}
]
2018-04-08 10:57:01 +00:00
limits = {
rpc_rate = 1
rpc_max_burst = 100
}
2017-09-25 18:40:42 +00:00
` )
2017-06-03 19:22:47 +00:00
defer a . Shutdown ( )
2016-11-30 18:29:42 +00:00
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , dc1 )
2019-12-10 02:26:41 +00:00
if a . State . Service ( structs . NewServiceID ( "redis" , nil ) ) == nil {
2017-08-28 12:17:13 +00:00
t . Fatal ( "missing redis service" )
2016-11-30 18:29:42 +00:00
}
2020-08-10 16:46:28 +00:00
cfg2 := TestConfig ( testutil . Logger ( t ) , config . FileSource {
2017-09-25 18:40:42 +00:00
Name : "reload" ,
Format : "hcl" ,
Data : `
data_dir = "` + a.Config.DataDir + `"
node_id = "` + string(a.Config.NodeID) + `"
node_name = "` + a.Config.NodeName + `"
services = [
{
name = "redis-reloaded"
}
]
2018-04-08 10:57:01 +00:00
limits = {
rpc_rate = 2
rpc_max_burst = 200
}
2017-09-25 18:40:42 +00:00
` ,
} )
2016-11-30 18:29:42 +00:00
2020-09-16 17:29:59 +00:00
shim := & delegateConfigReloadShim { delegate : a . delegate }
2022-05-25 19:33:00 +00:00
// NOTE: this may require refactoring to remove a potential test race
2020-09-16 17:29:59 +00:00
a . delegate = shim
2020-06-10 20:47:35 +00:00
if err := a . reloadConfigInternal ( cfg2 ) ; err != nil {
2017-06-03 19:22:47 +00:00
t . Fatalf ( "got error %v want nil" , err )
2016-11-30 18:29:42 +00:00
}
2019-12-10 02:26:41 +00:00
if a . State . Service ( structs . NewServiceID ( "redis-reloaded" , nil ) ) == nil {
2017-08-28 12:17:13 +00:00
t . Fatal ( "missing redis-reloaded service" )
2016-11-30 18:29:42 +00:00
}
2017-06-24 19:52:41 +00:00
2020-09-16 17:29:59 +00:00
require . Equal ( t , rate . Limit ( 2 ) , shim . newCfg . RPCRateLimit )
require . Equal ( t , 200 , shim . newCfg . RPCMaxBurst )
2018-04-08 10:57:01 +00:00
2017-09-25 18:40:42 +00:00
for _ , wp := range a . watchPlans {
2017-06-24 19:52:41 +00:00
if ! wp . IsStopped ( ) {
t . Fatalf ( "Reloading configs should stop watch plans of the previous configuration" )
}
}
2016-11-30 18:29:42 +00:00
}
2020-09-16 17:29:59 +00:00
type delegateConfigReloadShim struct {
delegate
newCfg consul . ReloadableConfig
}
func ( s * delegateConfigReloadShim ) ReloadConfig ( cfg consul . ReloadableConfig ) error {
s . newCfg = cfg
return s . delegate . ReloadConfig ( cfg )
}
2020-05-20 10:38:29 +00:00
// TestAgent_ReloadDoesNotTriggerWatch Ensure watches not triggered after reload
// see https://github.com/hashicorp/consul/issues/7446
func TestAgent_ReloadDoesNotTriggerWatch ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-05-20 10:38:29 +00:00
dc1 := "dc1"
2022-11-10 16:26:01 +00:00
tmpFileRaw , err := os . CreateTemp ( "" , "rexec" )
2020-05-20 10:38:29 +00:00
require . NoError ( t , err )
tmpFile := tmpFileRaw . Name ( )
defer os . Remove ( tmpFile )
handlerShell := fmt . Sprintf ( "(cat ; echo CONSUL_INDEX $CONSUL_INDEX) | tee '%s.atomic' ; mv '%s.atomic' '%s'" , tmpFile , tmpFile , tmpFile )
a := NewTestAgent ( t , `
services = [
{
name = "redis"
checks = [
{
id = "red-is-dead"
ttl = "30s"
notes = "initial check"
}
]
}
]
watches = [
{
datacenter = "`+dc1+`"
type = "service"
service = "redis"
args = [ "bash" , "-c" , "`+handlerShell+`" ]
}
]
` )
checkID := structs . NewCheckID ( "red-is-dead" , nil )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , dc1 )
require . NoError ( t , a . updateTTLCheck ( checkID , api . HealthPassing , "testing-agent-reload-001" ) )
checkStr := func ( r * retry . R , evaluator func ( string ) error ) {
2023-12-06 17:11:32 +00:00
r . Helper ( )
2020-05-20 10:38:29 +00:00
contentsStr := ""
// Wait for watch to be populated
for i := 1 ; i < 7 ; i ++ {
2022-11-10 16:26:01 +00:00
contents , err := os . ReadFile ( tmpFile )
2020-05-20 10:38:29 +00:00
if err != nil {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "should be able to read file, but had: %#v" , err )
2020-05-20 10:38:29 +00:00
}
contentsStr = string ( contents )
if contentsStr != "" {
break
}
time . Sleep ( time . Duration ( i ) * time . Second )
2023-12-06 17:11:32 +00:00
testutil . Logger ( r ) . Info ( "Watch not yet populated, retrying" )
2020-05-20 10:38:29 +00:00
}
if err := evaluator ( contentsStr ) ; err != nil {
r . Errorf ( "ERROR: Test failing: %s" , err )
}
}
ensureNothingCritical := func ( r * retry . R , mustContain string ) {
2023-12-06 17:11:32 +00:00
r . Helper ( )
2020-05-20 10:38:29 +00:00
eval := func ( contentsStr string ) error {
if strings . Contains ( contentsStr , "critical" ) {
return fmt . Errorf ( "MUST NOT contain critical:= %s" , contentsStr )
}
if ! strings . Contains ( contentsStr , mustContain ) {
return fmt . Errorf ( "MUST contain '%s' := %s" , mustContain , contentsStr )
}
return nil
}
checkStr ( r , eval )
}
retriesWithDelay := func ( ) * retry . Counter {
return & retry . Counter { Count : 10 , Wait : 1 * time . Second }
}
retry . RunWith ( retriesWithDelay ( ) , t , func ( r * retry . R ) {
2023-12-06 17:11:32 +00:00
testutil . Logger ( r ) . Info ( "Consul is now ready" )
2020-05-20 10:38:29 +00:00
// it should contain the output
checkStr ( r , func ( contentStr string ) error {
if contentStr == "[]" {
return fmt . Errorf ( "Consul is still starting up" )
}
return nil
} )
} )
retry . RunWith ( retriesWithDelay ( ) , t , func ( r * retry . R ) {
ensureNothingCritical ( r , "testing-agent-reload-001" )
} )
// Let's take almost the same config
2020-08-10 16:46:28 +00:00
cfg2 := TestConfig ( testutil . Logger ( t ) , config . FileSource {
2020-05-20 10:38:29 +00:00
Name : "reload" ,
Format : "hcl" ,
Data : `
data_dir = "` + a.Config.DataDir + `"
node_id = "` + string(a.Config.NodeID) + `"
node_name = "` + a.Config.NodeName + `"
services = [
{
name = "redis"
checks = [
{
id = "red-is-dead"
ttl = "30s"
notes = "initial check"
}
]
}
]
watches = [
{
datacenter = "` + dc1 + `"
type = "service"
service = "redis"
args = [ "bash" , "-c" , "` + handlerShell + `" ]
}
]
` ,
} )
justOnce := func ( ) * retry . Counter {
return & retry . Counter { Count : 1 , Wait : 25 * time . Millisecond }
}
retry . RunWith ( justOnce ( ) , t , func ( r * retry . R ) {
// We check that reload does not go to critical
ensureNothingCritical ( r , "red-is-dead" )
2020-06-10 20:47:35 +00:00
if err := a . reloadConfigInternal ( cfg2 ) ; err != nil {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "got error %v want nil" , err )
2020-05-20 10:38:29 +00:00
}
// We check that reload does not go to critical
ensureNothingCritical ( r , "red-is-dead" )
ensureNothingCritical ( r , "testing-agent-reload-001" )
2023-06-07 18:53:27 +00:00
require . NoError ( r , a . updateTTLCheck ( checkID , api . HealthPassing , "testing-agent-reload-002" ) )
2020-05-20 10:38:29 +00:00
ensureNothingCritical ( r , "red-is-dead" )
} )
}
2016-12-14 17:33:57 +00:00
func TestAgent_Reload_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2016-12-14 17:33:57 +00:00
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/reload" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/reload" , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
// This proves we call the ACL function, and we've got the other reload
// test to prove we do the reload, which should be sufficient.
// The reload logic is a little complex to set up so isn't worth
// repeating again here.
}
func TestAgent_Members ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2014-01-06 21:21:48 +00:00
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/members" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
2014-01-06 21:21:48 +00:00
t . Fatalf ( "Err: %v" , err )
}
2021-12-07 14:44:03 +00:00
2014-01-06 21:21:48 +00:00
if len ( val ) == 0 {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad members: %v" , val )
2014-01-06 21:21:48 +00:00
}
2017-09-25 18:40:42 +00:00
if int ( val [ 0 ] . Port ) != a . Config . SerfPortLAN {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "not lan: %v" , val )
2014-01-06 21:21:48 +00:00
}
}
2016-12-14 17:33:57 +00:00
func TestAgent_Members_WAN ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2014-01-06 21:21:48 +00:00
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/members?wan=true" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
2014-01-06 21:21:48 +00:00
t . Fatalf ( "Err: %v" , err )
}
2021-12-07 14:44:03 +00:00
2014-01-06 21:21:48 +00:00
if len ( val ) == 0 {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "bad members: %v" , val )
2014-01-06 21:21:48 +00:00
}
2017-09-25 18:40:42 +00:00
if int ( val [ 0 ] . Port ) != a . Config . SerfPortWAN {
2021-12-07 14:44:03 +00:00
t . Fatalf ( "not wan: %v" , val )
2014-01-06 21:21:48 +00:00
}
}
2016-12-14 22:16:46 +00:00
func TestAgent_Members_ACLFilter ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2021-12-03 20:36:28 +00:00
// Start 2 agents and join them together.
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2016-12-14 22:16:46 +00:00
2021-12-03 20:36:28 +00:00
b := NewTestAgent ( t , TestACLConfig ( ) )
defer b . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2021-12-03 20:36:28 +00:00
testrpc . WaitForLeader ( t , b . RPC , "dc1" )
2023-01-24 16:21:41 +00:00
joinPath := fmt . Sprintf ( "/v1/agent/join/127.0.0.1:%d" , b . Config . SerfPortLAN )
req := httptest . NewRequest ( "PUT" , joinPath , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
2023-01-24 16:21:41 +00:00
a . srv . h . ServeHTTP ( resp , req )
2021-12-07 14:44:03 +00:00
require . Equal ( t , http . StatusOK , resp . Code )
2021-12-03 20:36:28 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2021-12-07 14:44:03 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/members" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2021-12-03 20:36:28 +00:00
} )
t . Run ( "limited token" , func ( t * testing . T ) {
token := testCreateToken ( t , a , fmt . Sprintf ( `
node "%s" {
policy = "read"
}
` , b . Config . NodeName ) )
2023-01-24 16:21:41 +00:00
req := httptest . NewRequest ( "GET" , "/v1/agent/members" , nil )
req . Header . Add ( "X-Consul-Token" , token )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/members" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-03 20:36:28 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 2 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
2017-05-09 17:46:11 +00:00
} )
2024-11-20 23:26:12 +00:00
// ensure ACL filtering occurs before bexpr filtering.
bexprMatchingUserTokenPermissions := fmt . Sprintf ( "Name matches `%s.*`" , b . Config . NodeName )
bexprNotMatchingUserTokenPermissions := fmt . Sprintf ( "Name matches `%s.*`" , a . Config . NodeName )
tokenWithReadOnMemberB := testCreateToken ( t , a , fmt . Sprintf ( `
node "%s" {
policy = "read"
}
` , b . Config . NodeName ) )
t . Run ( "request with filter that matches token permissions returns 1 result and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/members?filter=" + url . QueryEscape ( bexprMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithReadOnMemberB )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 1 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that does not match token permissions returns 0 results and ResultsFilteredByACLs equal to true" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/members?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
req . Header . Add ( "X-Consul-Token" , tokenWithReadOnMemberB )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . NotEmpty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
t . Run ( "request with filter that would normally match but without any token returns zero results and ResultsFilteredByACLs equal to false" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/members?filter=" + url . QueryEscape ( bexprNotMatchingUserTokenPermissions ) , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := make ( [ ] serf . Member , 0 )
if err := dec . Decode ( & val ) ; err != nil {
t . Fatalf ( "Err: %v" , err )
}
require . Len ( t , val , 0 )
require . Empty ( t , resp . Header ( ) . Get ( "X-Consul-Results-Filtered-By-ACLs" ) )
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Join ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a1 . Shutdown ( )
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , "" )
2014-01-06 21:21:48 +00:00
defer a2 . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
2014-01-06 21:21:48 +00:00
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/join/%s" , addr ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
2014-01-06 21:21:48 +00:00
2021-10-26 20:08:55 +00:00
if len ( a1 . LANMembersInAgentPartition ( ) ) != 2 {
2014-01-06 21:21:48 +00:00
t . Fatalf ( "should have 2 members" )
}
2016-10-25 20:46:54 +00:00
2017-05-04 22:52:53 +00:00
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
if got , want := len ( a2 . LANMembersInAgentPartition ( ) ) , 2 ; got != want {
2017-04-29 16:34:02 +00:00
r . Fatalf ( "got %d LAN members want %d" , got , want )
}
} )
2014-01-06 21:21:48 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Join_WAN ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a1 . Shutdown ( )
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , "" )
2014-01-06 21:21:48 +00:00
defer a2 . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
2014-01-06 21:21:48 +00:00
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortWAN )
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/join/%s?wan=true" , addr ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
2014-01-06 21:21:48 +00:00
2017-05-21 07:11:09 +00:00
if len ( a1 . WANMembers ( ) ) != 2 {
2016-10-25 20:46:54 +00:00
t . Fatalf ( "should have 2 members" )
}
2017-05-04 22:52:53 +00:00
retry . Run ( t , func ( r * retry . R ) {
2017-04-29 16:34:02 +00:00
if got , want := len ( a2 . WANMembers ( ) ) , 2 ; got != want {
r . Fatalf ( "got %d WAN members want %d" , got , want )
}
} )
2014-01-06 21:21:48 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Join_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a1 . Shutdown ( )
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , "" )
2016-12-14 17:33:57 +00:00
defer a2 . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
2017-05-21 07:11:09 +00:00
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/join/%s" , addr ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2022-01-20 12:47:50 +00:00
t . Run ( "agent recovery token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/join/%s" , addr ) , nil )
req . Header . Add ( "X-Consul-Token" , "towel" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a1 . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/join/%s" , addr ) , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
}
2017-06-21 04:43:55 +00:00
type mockNotifier struct { s string }
func ( n * mockNotifier ) Notify ( state string ) error {
n . s = state
return nil
}
func TestAgent_JoinLANNotify ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-06-21 04:43:55 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , "" )
2017-06-21 04:43:55 +00:00
defer a1 . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
2017-06-21 04:43:55 +00:00
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , `
2017-09-25 18:40:42 +00:00
server = false
bootstrap = false
` )
2017-06-21 04:43:55 +00:00
defer a2 . Shutdown ( )
notif := & mockNotifier { }
a1 . joinLANNotifier = notif
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2021-10-26 20:08:55 +00:00
_ , err := a1 . JoinLAN ( [ ] string { addr } , nil )
2017-06-21 04:43:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if got , want := notif . s , "READY=1" ; got != want {
t . Fatalf ( "got joinLAN notification %q want %q" , got , want )
}
}
2016-12-14 17:33:57 +00:00
func TestAgent_Leave ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a1 . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
2016-11-30 18:29:42 +00:00
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , `
2017-09-25 18:40:42 +00:00
server = false
bootstrap = false
` )
2017-05-21 07:11:09 +00:00
defer a2 . Shutdown ( )
2016-11-30 18:29:42 +00:00
// Join first
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2021-10-26 20:08:55 +00:00
_ , err := a1 . JoinLAN ( [ ] string { addr } , nil )
2016-11-30 18:29:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
// Graceful leave now
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/leave" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a2 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-04 22:52:53 +00:00
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
m := a1 . LANMembersInAgentPartition ( )
2017-04-29 16:34:02 +00:00
if got , want := m [ 1 ] . Status , serf . StatusLeft ; got != want {
r . Fatalf ( "got status %q want %q" , got , want )
}
} )
2016-11-30 18:29:42 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Leave_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 17:33:57 +00:00
2017-05-10 07:08:39 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/leave" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/leave" , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2017-05-10 07:08:39 +00:00
// this sub-test will change the state so that there is no leader.
// it must therefore be the last one in this list.
2022-01-20 12:47:50 +00:00
t . Run ( "agent recovery token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/leave" , nil )
req . Header . Add ( "X-Consul-Token" , "towel" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-10 07:08:39 +00:00
} )
2016-12-14 17:33:57 +00:00
}
func TestAgent_ForceLeave ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a1 := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a1 . Shutdown ( )
2020-03-31 19:59:56 +00:00
a2 := NewTestAgent ( t , "" )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
2014-01-06 21:21:48 +00:00
// Join first
2017-09-25 18:40:42 +00:00
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2021-10-26 20:08:55 +00:00
_ , err := a1 . JoinLAN ( [ ] string { addr } , nil )
2014-01-06 21:21:48 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2017-09-25 18:40:42 +00:00
// this test probably needs work
2014-01-06 21:21:48 +00:00
a2 . Shutdown ( )
2018-08-06 23:46:09 +00:00
// Wait for agent being marked as failed, so we wait for full shutdown of Agent
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
m := a1 . LANMembersInAgentPartition ( )
2018-08-06 23:46:09 +00:00
if got , want := m [ 1 ] . Status , serf . StatusFailed ; got != want {
r . Fatalf ( "got status %q want %q" , got , want )
}
} )
2014-01-06 21:21:48 +00:00
// Force leave now
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/force-leave/%s" , a2 . Config . NodeName ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-04 22:52:53 +00:00
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
m := a1 . LANMembersInAgentPartition ( )
2017-04-29 16:34:02 +00:00
if got , want := m [ 1 ] . Status , serf . StatusLeft ; got != want {
r . Fatalf ( "got status %q want %q" , got , want )
}
} )
2014-01-06 21:21:48 +00:00
}
2014-01-30 23:51:15 +00:00
2020-03-03 13:18:19 +00:00
func TestOpenMetricsMimeTypeHeaders ( t * testing . T ) {
t . Parallel ( )
assert . False ( t , acceptsOpenMetricsMimeType ( "" ) )
assert . False ( t , acceptsOpenMetricsMimeType ( ";;;" ) )
assert . False ( t , acceptsOpenMetricsMimeType ( ",,," ) )
assert . False ( t , acceptsOpenMetricsMimeType ( "text/plain" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "text/plain;version=0.4.0," ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "text/plain;version=0.4.0;q=1,*/*;q=0.1" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "text/plain ; version=0.4.0" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "*/*, application/openmetrics-text ;" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "*/*, application/openmetrics-text ;q=1" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "application/openmetrics-text, text/plain;version=0.4.0" ) )
assert . True ( t , acceptsOpenMetricsMimeType ( "application/openmetrics-text; version=0.0.1,text/plain;version=0.0.4;q=0.5,*/*;q=0.1" ) )
}
2016-12-14 17:33:57 +00:00
func TestAgent_ForceLeave_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 17:33:57 +00:00
2019-12-02 19:06:15 +00:00
uri := fmt . Sprintf ( "/v1/agent/force-leave/%s" , a . Config . NodeName )
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2019-12-02 19:06:15 +00:00
req , _ := http . NewRequest ( "PUT" , uri , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2022-01-20 12:47:50 +00:00
t . Run ( "agent recovery token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , uri , nil )
req . Header . Add ( "X-Consul-Token" , "towel" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 17:33:57 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "read-only token" , func ( t * testing . T ) {
2021-07-20 21:52:34 +00:00
ro := createACLTokenWithAgentReadPolicy ( t , a . srv )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , uri , nil )
req . Header . Add ( "X-Consul-Token" , ro )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2020-01-14 22:40:34 +00:00
t . Run ( "operator write token" , func ( t * testing . T ) {
// Create an ACL with operator read permissions.
2021-08-20 16:57:45 +00:00
rules := `
2020-01-14 22:40:34 +00:00
operator = "write"
`
opToken := testCreateToken ( t , a , rules )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , uri , nil )
req . Header . Add ( "X-Consul-Token" , opToken )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2020-01-14 22:40:34 +00:00
} )
2016-12-14 17:33:57 +00:00
}
2019-10-04 21:10:02 +00:00
func TestAgent_ForceLeavePrune ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-10-04 21:10:02 +00:00
t . Parallel ( )
2020-03-31 20:24:39 +00:00
a1 := StartTestAgent ( t , TestAgent { Name : "Agent1" } )
2019-10-04 21:10:02 +00:00
defer a1 . Shutdown ( )
2020-03-31 20:24:39 +00:00
a2 := StartTestAgent ( t , TestAgent { Name : "Agent2" } )
2019-10-04 21:10:02 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
// Join first
addr := fmt . Sprintf ( "127.0.0.1:%d" , a2 . Config . SerfPortLAN )
2021-10-26 20:08:55 +00:00
_ , err := a1 . JoinLAN ( [ ] string { addr } , nil )
2019-10-04 21:10:02 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
// this test probably needs work
a2 . Shutdown ( )
// Wait for agent being marked as failed, so we wait for full shutdown of Agent
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
m := a1 . LANMembersInAgentPartition ( )
2019-10-04 21:10:02 +00:00
for _ , member := range m {
if member . Name == a2 . Config . NodeName {
if member . Status != serf . StatusFailed {
r . Fatalf ( "got status %q want %q" , member . Status , serf . StatusFailed )
}
}
}
} )
// Force leave now
req , _ := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/force-leave/%s?prune=true" , a2 . Config . NodeName ) , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-10-04 21:10:02 +00:00
retry . Run ( t , func ( r * retry . R ) {
2021-10-26 20:08:55 +00:00
m := len ( a1 . LANMembersInAgentPartition ( ) )
2019-10-04 21:10:02 +00:00
if m != 1 {
r . Fatalf ( "want one member, got %v" , m )
}
} )
}
2021-12-02 23:15:10 +00:00
func TestAgent_ForceLeavePrune_WAN ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
a1 := StartTestAgent ( t , TestAgent { Name : "dc1" , HCL : `
datacenter = "dc1"
primary_datacenter = "dc1"
gossip_wan {
probe_interval = "50ms"
suspicion_mult = 2
}
` } )
defer a1 . Shutdown ( )
a2 := StartTestAgent ( t , TestAgent { Name : "dc2" , HCL : `
datacenter = "dc2"
primary_datacenter = "dc1"
` } )
defer a2 . Shutdown ( )
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc2" )
// Wait for the WAN join.
addr := fmt . Sprintf ( "127.0.0.1:%d" , a1 . Config . SerfPortWAN )
_ , err := a2 . JoinWAN ( [ ] string { addr } )
require . NoError ( t , err )
testrpc . WaitForLeader ( t , a1 . RPC , "dc2" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc1" )
retry . Run ( t , func ( r * retry . R ) {
require . Len ( r , a1 . WANMembers ( ) , 2 )
require . Len ( r , a2 . WANMembers ( ) , 2 )
} )
wanNodeName_a2 := a2 . Config . NodeName + ".dc2"
// Shutdown and wait for agent being marked as failed, so we wait for full
// shutdown of Agent.
require . NoError ( t , a2 . Shutdown ( ) )
retry . Run ( t , func ( r * retry . R ) {
m := a1 . WANMembers ( )
for _ , member := range m {
if member . Name == wanNodeName_a2 {
if member . Status != serf . StatusFailed {
r . Fatalf ( "got status %q want %q" , member . Status , serf . StatusFailed )
}
}
}
} )
// Force leave now
req , err := http . NewRequest ( "PUT" , fmt . Sprintf ( "/v1/agent/force-leave/%s?prune=1&wan=1" , wanNodeName_a2 ) , nil )
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
a1 . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code , resp . Body . String ( ) )
retry . Run ( t , func ( r * retry . R ) {
require . Len ( r , a1 . WANMembers ( ) , 1 )
} )
}
2016-12-14 17:33:57 +00:00
func TestAgent_RegisterCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:51:15 +00:00
2017-06-15 16:46:06 +00:00
args := & structs . CheckDefinition {
2014-01-30 23:51:15 +00:00
Name : "test" ,
2017-05-15 19:49:13 +00:00
TTL : 15 * time . Second ,
2014-01-30 23:51:15 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2014-01-30 23:51:15 +00:00
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
checkID := structs . NewCheckID ( "test" , nil )
if existing := a . State . Check ( checkID ) ; existing == nil {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "missing test check" )
}
2017-05-21 07:11:09 +00:00
if _ , ok := a . checkTTLs [ checkID ] ; ! ok {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "missing test check ttl" )
}
2015-04-28 20:06:02 +00:00
// Ensure the token was configured
2017-08-28 12:17:13 +00:00
if token := a . State . CheckToken ( checkID ) ; token == "" {
2015-04-28 20:06:02 +00:00
t . Fatalf ( "missing token" )
}
2015-05-11 23:48:10 +00:00
2015-04-12 00:53:48 +00:00
// By default, checks start in critical state.
2019-12-10 02:26:41 +00:00
state := a . State . Check ( checkID )
2017-04-19 23:00:11 +00:00
if state . Status != api . HealthCritical {
2015-04-12 00:53:48 +00:00
t . Fatalf ( "bad: %v" , state )
}
}
2022-06-06 19:13:19 +00:00
func TestAgent_RegisterCheck_UDP ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
a := NewTestAgent ( t , "" )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . CheckDefinition {
UDP : "1.1.1.1" ,
Name : "test" ,
Interval : 10 * time . Second ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2022-06-06 19:13:19 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
// Ensure we have a check mapping
checkID := structs . NewCheckID ( "test" , nil )
if existing := a . State . Check ( checkID ) ; existing == nil {
t . Fatalf ( "missing test check" )
}
if _ , ok := a . checkUDPs [ checkID ] ; ! ok {
t . Fatalf ( "missing test check udp" )
}
// Ensure the token was configured
if token := a . State . CheckToken ( checkID ) ; token == "" {
t . Fatalf ( "missing token" )
}
// By default, checks start in critical state.
state := a . State . Check ( checkID )
if state . Status != api . HealthCritical {
t . Fatalf ( "bad: %v" , state )
}
}
2017-10-18 18:28:39 +00:00
// This verifies all the forms of the new args-style check that we need to
// support as a result of https://github.com/hashicorp/consul/issues/3587.
func TestAgent_RegisterCheck_Scripts ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-10-18 18:28:39 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2017-10-18 18:28:39 +00:00
enable_script_checks = true
` )
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2017-10-18 18:28:39 +00:00
tests := [ ] struct {
name string
check map [ string ] interface { }
} {
{
"== Consul 1.0.0" ,
map [ string ] interface { } {
"Name" : "test" ,
"Interval" : "2s" ,
"ScriptArgs" : [ ] string { "true" } ,
} ,
} ,
{
"> Consul 1.0.0 (fixup)" ,
map [ string ] interface { } {
"Name" : "test" ,
"Interval" : "2s" ,
"script_args" : [ ] string { "true" } ,
} ,
} ,
{
"> Consul 1.0.0" ,
map [ string ] interface { } {
"Name" : "test" ,
"Interval" : "2s" ,
"Args" : [ ] string { "true" } ,
} ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name + " as node check" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( tt . check ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2017-10-18 18:28:39 +00:00
if resp . Code != http . StatusOK {
t . Fatalf ( "bad: %d" , resp . Code )
}
} )
t . Run ( tt . name + " as top-level service check" , func ( t * testing . T ) {
args := map [ string ] interface { } {
"Name" : "a" ,
"Port" : 1234 ,
"Check" : tt . check ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2017-10-18 18:28:39 +00:00
if resp . Code != http . StatusOK {
t . Fatalf ( "bad: %d" , resp . Code )
}
} )
t . Run ( tt . name + " as slice-based service check" , func ( t * testing . T ) {
args := map [ string ] interface { } {
"Name" : "a" ,
"Port" : 1234 ,
"Checks" : [ ] map [ string ] interface { } { tt . check } ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2017-10-18 18:28:39 +00:00
if resp . Code != http . StatusOK {
t . Fatalf ( "bad: %d" , resp . Code )
}
} )
}
}
2018-10-11 12:22:11 +00:00
func TestAgent_RegisterCheckScriptsExecDisable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-10-11 12:22:11 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-10-11 12:22:11 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . CheckDefinition {
Name : "test" ,
ScriptArgs : [ ] string { "true" } ,
Interval : time . Second ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2018-10-11 12:22:11 +00:00
res := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( res , req )
if http . StatusInternalServerError != res . Code {
t . Fatalf ( "expected 500 code error but got %v" , res . Code )
2018-10-11 12:22:11 +00:00
}
2021-12-07 14:44:03 +00:00
if ! strings . Contains ( res . Body . String ( ) , "Scripts are disabled on this agent" ) {
t . Fatalf ( "expected script disabled error, got: %s" , res . Body . String ( ) )
2018-10-11 12:22:11 +00:00
}
2019-12-10 02:26:41 +00:00
checkID := structs . NewCheckID ( "test" , nil )
require . Nil ( t , a . State . Check ( checkID ) , "check registered with exec disabled" )
2018-10-11 12:22:11 +00:00
}
func TestAgent_RegisterCheckScriptsExecRemoteDisable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-10-11 12:22:11 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2018-10-11 12:22:11 +00:00
enable_local_script_checks = true
` )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . CheckDefinition {
Name : "test" ,
ScriptArgs : [ ] string { "true" } ,
Interval : time . Second ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2018-10-11 12:22:11 +00:00
res := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( res , req )
if http . StatusInternalServerError != res . Code {
t . Fatalf ( "expected 500 code error but got %v" , res . Code )
2018-10-11 12:22:11 +00:00
}
2021-12-07 14:44:03 +00:00
if ! strings . Contains ( res . Body . String ( ) , "Scripts are disabled on this agent" ) {
t . Fatalf ( "expected script disabled error, got: %s" , res . Body . String ( ) )
2018-10-11 12:22:11 +00:00
}
2019-12-10 02:26:41 +00:00
checkID := structs . NewCheckID ( "test" , nil )
require . Nil ( t , a . State . Check ( checkID ) , "check registered with exec disabled" )
2018-10-11 12:22:11 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_RegisterCheck_Passing ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-04-12 00:53:48 +00:00
2017-06-15 16:46:06 +00:00
args := & structs . CheckDefinition {
2017-05-15 19:49:13 +00:00
Name : "test" ,
TTL : 15 * time . Second ,
2017-04-19 23:00:11 +00:00
Status : api . HealthPassing ,
2015-04-12 00:53:48 +00:00
}
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expcted 200 but got %v" , resp . Code )
2015-04-12 00:53:48 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
checkID := structs . NewCheckID ( "test" , nil )
if existing := a . State . Check ( checkID ) ; existing == nil {
2015-04-12 00:53:48 +00:00
t . Fatalf ( "missing test check" )
}
2017-05-21 07:11:09 +00:00
if _ , ok := a . checkTTLs [ checkID ] ; ! ok {
2015-04-12 00:53:48 +00:00
t . Fatalf ( "missing test check ttl" )
}
2019-12-10 02:26:41 +00:00
state := a . State . Check ( checkID )
2017-04-19 23:00:11 +00:00
if state . Status != api . HealthPassing {
2015-04-12 00:53:48 +00:00
t . Fatalf ( "bad: %v" , state )
}
}
2016-12-14 22:16:46 +00:00
func TestAgent_RegisterCheck_BadStatus ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-04-12 00:53:48 +00:00
2017-06-15 16:46:06 +00:00
args := & structs . CheckDefinition {
2017-05-15 19:49:13 +00:00
Name : "test" ,
TTL : 15 * time . Second ,
2015-04-12 00:53:48 +00:00
Status : "fluffy" ,
}
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( args ) )
2015-04-12 00:53:48 +00:00
resp := httptest . NewRecorder ( )
2021-11-19 16:50:44 +00:00
a . srv . h . ServeHTTP ( resp , req )
2021-12-07 14:44:03 +00:00
if resp . Code != http . StatusBadRequest {
t . Fatalf ( "accepted bad status" )
}
2014-01-30 23:51:15 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_RegisterCheck_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfigNew ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
2019-04-30 23:00:57 +00:00
nodeCheck := & structs . CheckDefinition {
2016-12-14 22:16:46 +00:00
Name : "test" ,
2017-05-15 19:49:13 +00:00
TTL : 15 * time . Second ,
2016-12-14 22:16:46 +00:00
}
2017-05-09 16:58:12 +00:00
2019-04-30 23:00:57 +00:00
svc := & structs . ServiceDefinition {
ID : "foo:1234" ,
Name : "foo" ,
Port : 1234 ,
}
svcCheck := & structs . CheckDefinition {
Name : "test2" ,
ServiceID : "foo:1234" ,
TTL : 15 * time . Second ,
}
// ensure the service is ready for registering a check for it.
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( svc ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-04-30 23:00:57 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-04-30 23:00:57 +00:00
// create a policy that has write on service foo
policyReq := & structs . ACLPolicy {
Name : "write-foo" ,
Rules : ` service "foo" { policy = "write"} ` ,
}
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonReader ( policyReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-04-30 23:00:57 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-04-30 23:00:57 +00:00
// create a policy that has write on the node name of the agent
policyReq = & structs . ACLPolicy {
Name : "write-node" ,
Rules : fmt . Sprintf ( ` node "%s" { policy = "write" } ` , a . config . NodeName ) ,
}
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonReader ( policyReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-04-30 23:00:57 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-04-30 23:00:57 +00:00
// create a token using the write-foo policy
tokenReq := & structs . ACLToken {
Description : "write-foo" ,
Policies : [ ] structs . ACLTokenPolicyLink {
2020-06-16 17:19:31 +00:00
{
2019-04-30 23:00:57 +00:00
Name : "write-foo" ,
} ,
} ,
}
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/token" , jsonReader ( tokenReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-04-30 23:00:57 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
dec := json . NewDecoder ( resp . Body )
svcToken := & structs . ACLToken { }
if err := dec . Decode ( svcToken ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
2019-04-30 23:00:57 +00:00
require . NotNil ( t , svcToken )
// create a token using the write-node policy
tokenReq = & structs . ACLToken {
Description : "write-node" ,
Policies : [ ] structs . ACLTokenPolicyLink {
2020-06-16 17:19:31 +00:00
{
2019-04-30 23:00:57 +00:00
Name : "write-node" ,
} ,
} ,
}
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/token" , jsonReader ( tokenReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-04-30 23:00:57 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
dec = json . NewDecoder ( resp . Body )
nodeToken := & structs . ACLToken { }
if err := dec . Decode ( nodeToken ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
2019-04-30 23:00:57 +00:00
require . NotNil ( t , nodeToken )
t . Run ( "no token - node check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( nodeCheck ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusForbidden , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2019-04-30 23:00:57 +00:00
t . Run ( "svc token - node check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( nodeCheck ) )
req . Header . Add ( "X-Consul-Token" , svcToken . SecretID )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusForbidden , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2019-04-30 23:00:57 +00:00
} )
t . Run ( "node token - node check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( nodeCheck ) )
req . Header . Add ( "X-Consul-Token" , nodeToken . SecretID )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusOK , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2019-04-30 23:00:57 +00:00
} )
t . Run ( "no token - svc check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( svcCheck ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusForbidden , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2017-05-09 17:46:11 +00:00
} )
2019-04-30 23:00:57 +00:00
t . Run ( "node token - svc check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( svcCheck ) )
req . Header . Add ( "X-Consul-Token" , nodeToken . SecretID )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusForbidden , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2019-04-30 23:00:57 +00:00
} )
t . Run ( "svc token - svc check" , func ( t * testing . T ) {
2019-09-26 02:55:52 +00:00
retry . Run ( t , func ( r * retry . R ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( svcCheck ) )
req . Header . Add ( "X-Consul-Token" , svcToken . SecretID )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusOK , resp . Code )
2019-09-26 02:55:52 +00:00
} )
2019-04-30 23:00:57 +00:00
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_DeregisterCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:51:15 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , nil , false , "" , ConfigSourceLocal ) ; err != nil {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "err: %v" , err )
}
2022-01-06 20:38:37 +00:00
t . Run ( "remove registered check" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/test" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
} )
t . Run ( "remove non-existent check" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/test" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusNotFound , resp . Code )
} )
2014-01-30 23:51:15 +00:00
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
requireCheckMissing ( t , a , "test" )
2014-01-30 23:51:15 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_DeregisterCheckACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2019-12-10 02:26:41 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" , testrpc . WithToken ( "root" ) )
2016-12-14 22:16:46 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , nil , false , "" , ConfigSourceLocal ) ; err != nil {
2016-12-14 22:16:46 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/test" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2022-01-06 20:38:37 +00:00
t . Run ( "non-existent check without token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/_nope_" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusNotFound , resp . Code )
} )
t . Run ( "non-existent check with token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/deregister/_nope_" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2022-01-06 20:38:37 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusNotFound , resp . Code )
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_PassCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:51:15 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/pass/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expected 200 by got %v" , resp . Code )
2014-01-30 23:51:15 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
state := a . State . Check ( structs . NewCheckID ( "test" , nil ) )
2017-04-19 23:00:11 +00:00
if state . Status != api . HealthPassing {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "bad: %v" , state )
}
}
2016-12-14 22:16:46 +00:00
func TestAgent_PassCheck_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2016-12-14 22:16:46 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/pass/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/pass/test" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_WarnCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:51:15 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/warn/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expected 200 by got %v" , resp . Code )
2014-01-30 23:51:15 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
state := a . State . Check ( structs . NewCheckID ( "test" , nil ) )
2017-04-19 23:00:11 +00:00
if state . Status != api . HealthWarning {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "bad: %v" , state )
}
}
2016-12-14 22:16:46 +00:00
func TestAgent_WarnCheck_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2016-12-14 22:16:46 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/warn/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/warn/test" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_FailCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2014-01-30 23:51:15 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/fail/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expected 200 by got %v" , resp . Code )
2014-01-30 23:51:15 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
state := a . State . Check ( structs . NewCheckID ( "test" , nil ) )
2017-04-19 23:00:11 +00:00
if state . Status != api . HealthCritical {
2014-01-30 23:51:15 +00:00
t . Fatalf ( "bad: %v" , state )
}
}
2014-01-30 23:56:03 +00:00
2016-12-14 22:16:46 +00:00
func TestAgent_FailCheck_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2016-12-14 22:16:46 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/fail/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/fail/test" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_UpdateCheck ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2019-06-26 15:43:25 +00:00
maxChecksSize := 256
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , fmt . Sprintf ( "check_output_max_size=%d" , maxChecksSize ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2016-03-03 01:08:06 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2016-03-03 01:08:06 +00:00
t . Fatalf ( "err: %v" , err )
}
cases := [ ] checkUpdate {
2020-06-16 17:19:31 +00:00
{ api . HealthPassing , "hello-passing" } ,
{ api . HealthCritical , "hello-critical" } ,
{ api . HealthWarning , "hello-warning" } ,
2016-03-03 01:08:06 +00:00
}
for _ , c := range cases {
2017-05-09 17:46:11 +00:00
t . Run ( c . Status , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/update/test" , jsonReader ( c ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != http . StatusOK {
2017-05-09 17:46:11 +00:00
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
2016-03-03 01:08:06 +00:00
2019-12-10 02:26:41 +00:00
state := a . State . Check ( structs . NewCheckID ( "test" , nil ) )
2017-05-09 17:46:11 +00:00
if state . Status != c . Status || state . Output != c . Output {
t . Fatalf ( "bad: %v" , state )
}
} )
2016-03-03 01:08:06 +00:00
}
2017-05-09 17:46:11 +00:00
t . Run ( "log output limit" , func ( t * testing . T ) {
2017-05-09 16:58:12 +00:00
args := checkUpdate {
2017-04-19 23:00:11 +00:00
Status : api . HealthPassing ,
2019-06-26 15:43:25 +00:00
Output : strings . Repeat ( "-= bad -=" , 5 * maxChecksSize ) ,
2016-03-03 01:08:06 +00:00
}
2017-05-09 16:58:12 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/update/test" , jsonReader ( args ) )
2016-03-03 01:08:06 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != http . StatusOK {
2016-03-03 01:08:06 +00:00
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
// Since we append some notes about truncating, we just do a
// rough check that the output buffer was cut down so this test
// isn't super brittle.
2019-12-10 02:26:41 +00:00
state := a . State . Check ( structs . NewCheckID ( "test" , nil ) )
2019-06-26 15:43:25 +00:00
if state . Status != api . HealthPassing || len ( state . Output ) > 2 * maxChecksSize {
t . Fatalf ( "bad: %v, (len:=%d)" , state , len ( state . Output ) )
2016-03-03 01:08:06 +00:00
}
2017-05-09 17:46:11 +00:00
} )
2016-03-03 01:08:06 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "bogus status" , func ( t * testing . T ) {
2017-05-09 16:58:12 +00:00
args := checkUpdate { Status : "itscomplicated" }
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/update/test" , jsonReader ( args ) )
2016-03-03 01:08:06 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != http . StatusBadRequest {
2016-03-03 01:08:06 +00:00
t . Fatalf ( "expected 400, got %d" , resp . Code )
}
2017-05-09 17:46:11 +00:00
} )
2016-03-03 01:08:06 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_UpdateCheck_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
chk := & structs . HealthCheck { Name : "test" , CheckID : "test" }
2017-06-15 16:46:06 +00:00
chkType := & structs . CheckType { TTL : 15 * time . Second }
2018-10-11 12:22:11 +00:00
if err := a . AddCheck ( chk , chkType , false , "" , ConfigSourceLocal ) ; err != nil {
2016-12-14 22:16:46 +00:00
t . Fatalf ( "err: %v" , err )
}
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
args := checkUpdate { api . HealthPassing , "hello-passing" }
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/update/test" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
args := checkUpdate { api . HealthPassing , "hello-passing" }
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/check/update/test" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_RegisterService ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService ( t * testing . T , extraHCL string ) {
t . Helper ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:56:03 +00:00
2017-06-15 16:46:06 +00:00
args := & structs . ServiceDefinition {
2014-01-30 23:56:03 +00:00
Name : "test" ,
2018-04-21 15:34:29 +00:00
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2014-01-30 23:56:03 +00:00
Port : 8000 ,
2017-06-15 16:46:06 +00:00
Check : structs . CheckType {
2014-01-30 23:56:03 +00:00
TTL : 15 * time . Second ,
} ,
2017-06-15 16:46:06 +00:00
Checks : [ ] * structs . CheckType {
2020-06-16 17:19:31 +00:00
{
2015-01-14 03:08:30 +00:00
TTL : 20 * time . Second ,
} ,
2020-06-16 17:19:31 +00:00
{
2015-01-14 03:08:30 +00:00
TTL : 30 * time . Second ,
} ,
2022-06-06 19:13:19 +00:00
{
UDP : "1.1.1.1" ,
Interval : 5 * time . Second ,
} ,
2015-01-14 03:08:30 +00:00
} ,
2018-09-07 14:30:47 +00:00
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
2014-01-30 23:56:03 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expected 200 but got %v" , resp . Code )
2014-01-30 23:56:03 +00:00
}
2018-03-19 16:56:00 +00:00
// Ensure the service
2019-12-10 02:26:41 +00:00
sid := structs . NewServiceID ( "test" , nil )
svc := a . State . Service ( sid )
if svc == nil {
2014-01-30 23:56:03 +00:00
t . Fatalf ( "missing test service" )
}
2019-12-10 02:26:41 +00:00
if val := svc . Meta [ "hello" ] ; val != "world" {
t . Fatalf ( "Missing meta: %v" , svc . Meta )
2018-04-21 15:34:29 +00:00
}
2019-12-10 02:26:41 +00:00
if val := svc . Weights . Passing ; val != 100 {
2018-09-07 14:30:47 +00:00
t . Fatalf ( "Expected 100 for Weights.Passing, got: %v" , val )
}
2019-12-10 02:26:41 +00:00
if val := svc . Weights . Warning ; val != 3 {
2018-09-07 14:30:47 +00:00
t . Fatalf ( "Expected 3 for Weights.Warning, got: %v" , val )
}
2014-01-30 23:56:03 +00:00
// Ensure we have a check mapping
2021-07-22 18:20:45 +00:00
checks := a . State . Checks ( structs . WildcardEnterpriseMetaInDefaultPartition ( ) )
2022-06-06 19:13:19 +00:00
if len ( checks ) != 4 {
2015-01-14 03:08:30 +00:00
t . Fatalf ( "bad: %v" , checks )
2014-01-30 23:56:03 +00:00
}
2019-10-17 18:33:11 +00:00
for _ , c := range checks {
2022-06-06 19:13:19 +00:00
if c . Type != "ttl" && c . Type != "udp" {
t . Fatalf ( "expected ttl or udp check type, got %s" , c . Type )
2019-10-17 18:33:11 +00:00
}
}
2014-01-30 23:56:03 +00:00
2017-05-21 07:11:09 +00:00
if len ( a . checkTTLs ) != 3 {
t . Fatalf ( "missing test check ttls: %v" , a . checkTTLs )
2014-01-30 23:56:03 +00:00
}
2015-04-28 20:06:02 +00:00
// Ensure the token was configured
2019-12-10 02:26:41 +00:00
if token := a . State . ServiceToken ( sid ) ; token == "" {
2015-04-28 20:06:02 +00:00
t . Fatalf ( "missing token" )
}
2014-01-30 23:56:03 +00:00
}
2019-09-02 15:38:29 +00:00
func TestAgent_RegisterService_ReRegister ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_ReRegister ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ReRegister ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ReRegister ( t * testing . T , extraHCL string ) {
t . Helper ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2019-09-02 15:38:29 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2019-09-02 15:38:29 +00:00
Port : 8000 ,
Checks : [ ] * structs . CheckType {
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_1" ) ,
TTL : 20 * time . Second ,
} ,
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_2" ) ,
TTL : 30 * time . Second ,
} ,
2022-06-06 19:13:19 +00:00
{
CheckID : types . CheckID ( "check_3" ) ,
UDP : "1.1.1.1" ,
Interval : 5 * time . Second ,
} ,
2019-09-02 15:38:29 +00:00
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-09-02 15:38:29 +00:00
args = & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2019-09-02 15:38:29 +00:00
Port : 8000 ,
Checks : [ ] * structs . CheckType {
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_1" ) ,
TTL : 20 * time . Second ,
} ,
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_3" ) ,
TTL : 30 * time . Second ,
} ,
2022-06-06 19:13:19 +00:00
{
CheckID : types . CheckID ( "check_3" ) ,
UDP : "1.1.1.1" ,
Interval : 5 * time . Second ,
} ,
2019-09-02 15:38:29 +00:00
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
req , _ = http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp = httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-09-02 15:38:29 +00:00
2021-07-22 18:20:45 +00:00
checks := a . State . Checks ( structs . DefaultEnterpriseMetaInDefaultPartition ( ) )
2019-09-02 15:38:29 +00:00
require . Equal ( t , 3 , len ( checks ) )
checkIDs := [ ] string { }
for id := range checks {
2019-12-10 02:26:41 +00:00
checkIDs = append ( checkIDs , string ( id . ID ) )
2019-09-02 15:38:29 +00:00
}
2019-12-10 02:26:41 +00:00
require . ElementsMatch ( t , [ ] string { "check_1" , "check_2" , "check_3" } , checkIDs )
2019-09-02 15:38:29 +00:00
}
func TestAgent_RegisterService_ReRegister_ReplaceExistingChecks ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_ReRegister_ReplaceExistingChecks ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ReRegister_ReplaceExistingChecks ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ReRegister_ReplaceExistingChecks ( t * testing . T , extraHCL string ) {
t . Helper ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2019-09-02 15:38:29 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2019-09-02 15:38:29 +00:00
Port : 8000 ,
Checks : [ ] * structs . CheckType {
2020-06-16 17:19:31 +00:00
{
2019-11-14 15:59:06 +00:00
// explicitly not setting the check id to let it be auto-generated
2019-11-15 15:33:21 +00:00
// we want to ensure that we are testing out the cases with autogenerated names/ids
2019-11-14 15:59:06 +00:00
TTL : 20 * time . Second ,
2019-09-02 15:38:29 +00:00
} ,
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_2" ) ,
TTL : 30 * time . Second ,
} ,
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register?replace-existing-checks" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-09-02 15:38:29 +00:00
args = & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2019-09-02 15:38:29 +00:00
Port : 8000 ,
Checks : [ ] * structs . CheckType {
2020-06-16 17:19:31 +00:00
{
2019-11-14 15:59:06 +00:00
TTL : 20 * time . Second ,
2019-09-02 15:38:29 +00:00
} ,
2020-06-16 17:19:31 +00:00
{
2019-09-02 15:38:29 +00:00
CheckID : types . CheckID ( "check_3" ) ,
TTL : 30 * time . Second ,
} ,
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
req , _ = http . NewRequest ( "PUT" , "/v1/agent/service/register?replace-existing-checks" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp = httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-09-02 15:38:29 +00:00
2021-07-22 18:20:45 +00:00
checks := a . State . Checks ( structs . DefaultEnterpriseMetaInDefaultPartition ( ) )
2019-12-10 02:26:41 +00:00
require . Len ( t , checks , 2 )
2019-09-02 15:38:29 +00:00
checkIDs := [ ] string { }
for id := range checks {
2019-12-10 02:26:41 +00:00
checkIDs = append ( checkIDs , string ( id . ID ) )
2019-09-02 15:38:29 +00:00
}
2019-11-14 15:59:06 +00:00
require . ElementsMatch ( t , [ ] string { "service:test:1" , "check_3" } , checkIDs )
2019-09-02 15:38:29 +00:00
}
2017-10-10 23:40:59 +00:00
func TestAgent_RegisterService_TranslateKeys ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-02-19 21:04:23 +00:00
testAgent_RegisterService_TranslateKeys ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
2020-02-19 21:04:23 +00:00
testAgent_RegisterService_TranslateKeys ( t , "enable_central_service_config = true" )
2019-09-24 15:04:48 +00:00
} )
}
func testAgent_RegisterService_TranslateKeys ( t * testing . T , extraHCL string ) {
t . Helper ( )
2019-06-04 14:02:38 +00:00
tests := [ ] struct {
ip string
expectedTCPCheckStart string
} {
{ "127.0.0.1" , "127.0.0.1:" } , // private network address
{ "::1" , "[::1]:" } , // shared address space
}
for _ , tt := range tests {
t . Run ( tt . ip , func ( t * testing . T ) {
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2019-08-09 19:19:30 +00:00
connect { }
2019-09-24 15:04:48 +00:00
` + extraHCL )
2019-06-04 14:02:38 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2017-10-10 23:40:59 +00:00
2019-06-04 14:02:38 +00:00
json := `
2018-09-12 16:07:47 +00:00
{
2018-10-17 20:20:35 +00:00
"name" : "test" ,
"port" : 8000 ,
"enable_tag_override" : true ,
2019-06-17 14:51:50 +00:00
"tagged_addresses" : {
"lan" : {
"address" : "1.2.3.4" ,
"port" : 5353
} ,
"wan" : {
"address" : "2.3.4.5" ,
"port" : 53
}
} ,
2018-09-12 16:07:47 +00:00
"meta" : {
2018-09-27 13:33:12 +00:00
"some" : "meta" ,
"enable_tag_override" : "meta is 'opaque' so should not get translated"
2018-09-12 16:07:47 +00:00
} ,
2018-09-27 13:33:12 +00:00
"kind" : "connect-proxy" , ` +
2019-06-04 14:02:38 +00:00
// Note the uppercase P is important here - it ensures translation works
// correctly in case-insensitive way. Without it this test can pass even
// when translation is broken for other valid inputs.
` "Proxy" : {
2018-09-12 16:07:47 +00:00
"destination_service_name" : "web" ,
"destination_service_id" : "web" ,
"local_service_port" : 1234 ,
2019-06-04 14:02:38 +00:00
"local_service_address" : "` + tt.ip + `" ,
2018-09-27 13:33:12 +00:00
"config" : {
"destination_type" : "proxy.config is 'opaque' so should not get translated"
} ,
2018-09-12 16:07:47 +00:00
"upstreams" : [
{
"destination_type" : "service" ,
"destination_namespace" : "default" ,
2021-08-20 16:57:45 +00:00
"destination_partition" : "default" ,
2018-09-12 16:07:47 +00:00
"destination_name" : "db" ,
2019-06-04 14:02:38 +00:00
"local_bind_address" : "` + tt.ip + `" ,
2018-09-27 13:33:12 +00:00
"local_bind_port" : 1234 ,
"config" : {
"destination_type" : "proxy.upstreams.config is 'opaque' so should not get translated"
}
2018-09-12 16:07:47 +00:00
}
]
} ,
"connect" : {
2018-09-27 13:33:12 +00:00
"sidecar_service" : {
2018-10-17 20:20:35 +00:00
"name" : "test-proxy" ,
"port" : 8001 ,
"enable_tag_override" : true ,
2018-09-27 13:33:12 +00:00
"meta" : {
"some" : "meta" ,
"enable_tag_override" : "sidecar_service.meta is 'opaque' so should not get translated"
} ,
"kind" : "connect-proxy" ,
"proxy" : {
"destination_service_name" : "test" ,
"destination_service_id" : "test" ,
"local_service_port" : 4321 ,
2019-06-04 14:02:38 +00:00
"local_service_address" : "` + tt.ip + `" ,
2018-09-27 13:33:12 +00:00
"upstreams" : [
{
"destination_type" : "service" ,
"destination_namespace" : "default" ,
2021-08-20 16:57:45 +00:00
"destination_partition" : "default" ,
2018-09-27 13:33:12 +00:00
"destination_name" : "db" ,
2019-06-04 14:02:38 +00:00
"local_bind_address" : "` + tt.ip + `" ,
2018-09-27 13:33:12 +00:00
"local_bind_port" : 1234 ,
"config" : {
"destination_type" : "sidecar_service.proxy.upstreams.config is 'opaque' so should not get translated"
}
}
]
}
2018-09-12 16:07:47 +00:00
}
} ,
"weights" : {
"passing" : 16
}
} `
2019-06-04 14:02:38 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , strings . NewReader ( json ) )
rr := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( rr , req )
2019-06-04 14:02:38 +00:00
require . Equal ( t , 200 , rr . Code , "body: %s" , rr . Body )
svc := & structs . NodeService {
ID : "test" ,
Service : "test" ,
2019-06-17 14:51:50 +00:00
TaggedAddresses : map [ string ] structs . ServiceAddress {
"lan" : {
Address : "1.2.3.4" ,
Port : 5353 ,
} ,
"wan" : {
Address : "2.3.4.5" ,
Port : 53 ,
} ,
} ,
2019-06-04 14:02:38 +00:00
Meta : map [ string ] string {
"some" : "meta" ,
"enable_tag_override" : "meta is 'opaque' so should not get translated" ,
} ,
Port : 8000 ,
EnableTagOverride : true ,
Weights : & structs . Weights { Passing : 16 , Warning : 0 } ,
Kind : structs . ServiceKindConnectProxy ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "web" ,
DestinationServiceID : "web" ,
LocalServiceAddress : tt . ip ,
LocalServicePort : 1234 ,
2018-09-27 13:33:12 +00:00
Config : map [ string ] interface { } {
2019-06-04 14:02:38 +00:00
"destination_type" : "proxy.config is 'opaque' so should not get translated" ,
} ,
Upstreams : structs . Upstreams {
{
DestinationType : structs . UpstreamDestTypeService ,
DestinationName : "db" ,
DestinationNamespace : "default" ,
2021-08-20 16:57:45 +00:00
DestinationPartition : "default" ,
2019-06-04 14:02:38 +00:00
LocalBindAddress : tt . ip ,
LocalBindPort : 1234 ,
Config : map [ string ] interface { } {
"destination_type" : "proxy.upstreams.config is 'opaque' so should not get translated" ,
} ,
} ,
2018-09-27 13:33:12 +00:00
} ,
2018-09-12 16:07:47 +00:00
} ,
2019-06-04 14:02:38 +00:00
Connect : structs . ServiceConnect {
// The sidecar service is nilled since it is only config sugar and
// shouldn't be represented in state. We assert that the translations
// there worked by inspecting the registered sidecar below.
SidecarService : nil ,
2018-09-27 13:33:12 +00:00
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2019-06-04 14:02:38 +00:00
}
2018-09-27 14:00:51 +00:00
2019-12-10 02:26:41 +00:00
got := a . State . Service ( structs . NewServiceID ( "test" , nil ) )
2019-06-04 14:02:38 +00:00
require . Equal ( t , svc , got )
2018-09-27 14:00:51 +00:00
2019-06-04 14:02:38 +00:00
sidecarSvc := & structs . NodeService {
Kind : structs . ServiceKindConnectProxy ,
ID : "test-sidecar-proxy" ,
Service : "test-proxy" ,
Meta : map [ string ] string {
"some" : "meta" ,
"enable_tag_override" : "sidecar_service.meta is 'opaque' so should not get translated" ,
} ,
2020-02-19 21:04:23 +00:00
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
2019-06-04 14:02:38 +00:00
Port : 8001 ,
EnableTagOverride : true ,
Weights : & structs . Weights { Passing : 1 , Warning : 1 } ,
LocallyRegisteredAsSidecar : true ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "test" ,
DestinationServiceID : "test" ,
LocalServiceAddress : tt . ip ,
LocalServicePort : 4321 ,
Upstreams : structs . Upstreams {
{
DestinationType : structs . UpstreamDestTypeService ,
DestinationName : "db" ,
DestinationNamespace : "default" ,
2021-08-20 16:57:45 +00:00
DestinationPartition : "default" ,
2019-06-04 14:02:38 +00:00
LocalBindAddress : tt . ip ,
LocalBindPort : 1234 ,
Config : map [ string ] interface { } {
"destination_type" : "sidecar_service.proxy.upstreams.config is 'opaque' so should not get translated" ,
} ,
} ,
2018-09-12 16:07:47 +00:00
} ,
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2019-06-04 14:02:38 +00:00
}
2019-12-10 02:26:41 +00:00
gotSidecar := a . State . Service ( structs . NewServiceID ( "test-sidecar-proxy" , nil ) )
2019-06-04 14:02:38 +00:00
hasNoCorrectTCPCheck := true
for _ , v := range a . checkTCPs {
if strings . HasPrefix ( v . TCP , tt . expectedTCPCheckStart ) {
hasNoCorrectTCPCheck = false
break
}
fmt . Println ( "TCP Check:= " , v )
}
if hasNoCorrectTCPCheck {
2022-09-01 21:03:35 +00:00
t . Fatalf ( "Did not find the expected TCP Healthcheck '%s' in %#v " , tt . expectedTCPCheckStart , a . checkTCPs )
2019-06-04 14:02:38 +00:00
}
require . Equal ( t , sidecarSvc , gotSidecar )
} )
2017-10-10 23:40:59 +00:00
}
}
2022-06-06 19:13:19 +00:00
func TestAgent_RegisterService_TranslateKeys_UDP ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2022-06-06 19:13:19 +00:00
testAgent_RegisterService_TranslateKeys ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
2022-06-06 19:13:19 +00:00
testAgent_RegisterService_TranslateKeys ( t , "enable_central_service_config = true" )
2019-09-24 15:04:48 +00:00
} )
}
2022-06-06 19:13:19 +00:00
func testAgent_RegisterService_TranslateKeys_UDP ( t * testing . T , extraHCL string ) {
2019-09-24 15:04:48 +00:00
t . Helper ( )
2022-06-06 19:13:19 +00:00
tests := [ ] struct {
ip string
expectedUDPCheckStart string
} {
{ "127.0.0.1" , "127.0.0.1:" } , // private network address
{ "::1" , "[::1]:" } , // shared address space
}
for _ , tt := range tests {
t . Run ( tt . ip , func ( t * testing . T ) {
a := NewTestAgent ( t , `
connect { }
` + extraHCL )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
2022-06-06 19:13:19 +00:00
json := `
{
"name" : "test" ,
"port" : 8000 ,
"enable_tag_override" : true ,
"tagged_addresses" : {
"lan" : {
"address" : "1.2.3.4" ,
"port" : 5353
2016-12-14 22:16:46 +00:00
} ,
2022-06-06 19:13:19 +00:00
"wan" : {
"address" : "2.3.4.5" ,
"port" : 53
}
} ,
"meta" : {
"some" : "meta" ,
"enable_tag_override" : "meta is 'opaque' so should not get translated"
} ,
"kind" : "connect-proxy" , ` +
// Note the uppercase P is important here - it ensures translation works
// correctly in case-insensitive way. Without it this test can pass even
// when translation is broken for other valid inputs.
` "Proxy" : {
"destination_service_name" : "web" ,
"destination_service_id" : "web" ,
"local_service_port" : 1234 ,
"local_service_address" : "` + tt.ip + `" ,
"config" : {
"destination_type" : "proxy.config is 'opaque' so should not get translated"
2016-12-14 22:16:46 +00:00
} ,
2022-06-06 19:13:19 +00:00
"upstreams" : [
{
"destination_type" : "service" ,
"destination_namespace" : "default" ,
"destination_partition" : "default" ,
"destination_name" : "db" ,
"local_bind_address" : "` + tt.ip + `" ,
"local_bind_port" : 1234 ,
"config" : {
"destination_type" : "proxy.upstreams.config is 'opaque' so should not get translated"
}
}
]
2016-12-14 22:16:46 +00:00
} ,
2022-06-06 19:13:19 +00:00
"connect" : {
"sidecar_service" : {
"name" : "test-proxy" ,
"port" : 8001 ,
"enable_tag_override" : true ,
"meta" : {
"some" : "meta" ,
"enable_tag_override" : "sidecar_service.meta is 'opaque' so should not get translated"
} ,
"kind" : "connect-proxy" ,
"proxy" : {
"destination_service_name" : "test" ,
"destination_service_id" : "test" ,
"local_service_port" : 4321 ,
"local_service_address" : "` + tt.ip + `" ,
"upstreams" : [
{
"destination_type" : "service" ,
"destination_namespace" : "default" ,
"destination_partition" : "default" ,
"destination_name" : "db" ,
"local_bind_address" : "` + tt.ip + `" ,
"local_bind_port" : 1234 ,
"config" : {
"destination_type" : "sidecar_service.proxy.upstreams.config is 'opaque' so should not get translated"
}
}
]
}
}
} ,
"weights" : {
"passing" : 16
}
} `
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , strings . NewReader ( json ) )
2020-12-07 18:42:55 +00:00
2022-06-06 19:13:19 +00:00
rr := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( rr , req )
require . Equal ( t , 200 , rr . Code , "body: %s" , rr . Body )
2019-09-24 15:04:48 +00:00
2022-06-06 19:13:19 +00:00
svc := & structs . NodeService {
ID : "test" ,
Service : "test" ,
TaggedAddresses : map [ string ] structs . ServiceAddress {
"lan" : {
Address : "1.2.3.4" ,
Port : 5353 ,
} ,
"wan" : {
Address : "2.3.4.5" ,
Port : 53 ,
} ,
} ,
Meta : map [ string ] string {
"some" : "meta" ,
"enable_tag_override" : "meta is 'opaque' so should not get translated" ,
} ,
Port : 8000 ,
EnableTagOverride : true ,
Weights : & structs . Weights { Passing : 16 , Warning : 0 } ,
Kind : structs . ServiceKindConnectProxy ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "web" ,
DestinationServiceID : "web" ,
LocalServiceAddress : tt . ip ,
LocalServicePort : 1234 ,
Config : map [ string ] interface { } {
"destination_type" : "proxy.config is 'opaque' so should not get translated" ,
} ,
Upstreams : structs . Upstreams {
{
DestinationType : structs . UpstreamDestTypeService ,
DestinationName : "db" ,
DestinationNamespace : "default" ,
DestinationPartition : "default" ,
LocalBindAddress : tt . ip ,
LocalBindPort : 1234 ,
Config : map [ string ] interface { } {
"destination_type" : "proxy.upstreams.config is 'opaque' so should not get translated" ,
} ,
} ,
} ,
} ,
Connect : structs . ServiceConnect {
// The sidecar service is nilled since it is only config sugar and
// shouldn't be represented in state. We assert that the translations
// there worked by inspecting the registered sidecar below.
SidecarService : nil ,
} ,
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
}
2019-09-24 15:04:48 +00:00
2022-06-06 19:13:19 +00:00
got := a . State . Service ( structs . NewServiceID ( "test" , nil ) )
require . Equal ( t , svc , got )
2017-05-08 16:34:45 +00:00
2022-06-06 19:13:19 +00:00
sidecarSvc := & structs . NodeService {
Kind : structs . ServiceKindConnectProxy ,
ID : "test-sidecar-proxy" ,
Service : "test-proxy" ,
Meta : map [ string ] string {
"some" : "meta" ,
"enable_tag_override" : "sidecar_service.meta is 'opaque' so should not get translated" ,
} ,
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
Port : 8001 ,
EnableTagOverride : true ,
Weights : & structs . Weights { Passing : 1 , Warning : 1 } ,
LocallyRegisteredAsSidecar : true ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "test" ,
DestinationServiceID : "test" ,
LocalServiceAddress : tt . ip ,
LocalServicePort : 4321 ,
Upstreams : structs . Upstreams {
{
DestinationType : structs . UpstreamDestTypeService ,
DestinationName : "db" ,
DestinationNamespace : "default" ,
DestinationPartition : "default" ,
LocalBindAddress : tt . ip ,
LocalBindPort : 1234 ,
Config : map [ string ] interface { } {
"destination_type" : "sidecar_service.proxy.upstreams.config is 'opaque' so should not get translated" ,
} ,
} ,
} ,
} ,
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
}
gotSidecar := a . State . Service ( structs . NewServiceID ( "test-sidecar-proxy" , nil ) )
hasNoCorrectUDPCheck := true
for _ , v := range a . checkUDPs {
if strings . HasPrefix ( v . UDP , tt . expectedUDPCheckStart ) {
hasNoCorrectUDPCheck = false
break
}
fmt . Println ( "UDP Check:= " , v )
}
if hasNoCorrectUDPCheck {
t . Fatalf ( "Did not find the expected UDP Healtcheck '%s' in %#v " , tt . expectedUDPCheckStart , a . checkUDPs )
}
require . Equal ( t , sidecarSvc , gotSidecar )
} )
}
}
func TestAgent_RegisterService_ACLDeny ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ACLDeny ( t , "enable_central_service_config = false" )
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ACLDeny ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ACLDeny ( t * testing . T , extraHCL string ) {
t . Helper ( )
a := NewTestAgent ( t , TestACLConfig ( ) + " " + extraHCL )
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
args := & structs . ServiceDefinition {
Name : "test" ,
Tags : [ ] string { "primary" } ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
Checks : [ ] * structs . CheckType {
{
TTL : 20 * time . Second ,
} ,
{
TTL : 30 * time . Second ,
} ,
} ,
}
t . Run ( "no token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
} )
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2022-06-06 19:13:19 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
} )
}
func TestAgent_RegisterService_InvalidAddress ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_InvalidAddress ( t , "enable_central_service_config = false" )
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_InvalidAddress ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_InvalidAddress ( t * testing . T , extraHCL string ) {
t . Helper ( )
a := NewTestAgent ( t , extraHCL )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
for _ , addr := range [ ] string { "0.0.0.0" , "::" , "[::]" } {
t . Run ( "addr " + addr , func ( t * testing . T ) {
args := & structs . ServiceDefinition {
Name : "test" ,
Address : addr ,
Port : 8000 ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2022-06-06 19:13:19 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if got , want := resp . Code , 400 ; got != want {
2017-05-09 07:29:13 +00:00
t . Fatalf ( "got code %d want %d" , got , want )
}
} )
2017-05-08 16:34:45 +00:00
}
}
2018-04-17 12:29:02 +00:00
// This tests local agent service registration of a unmanaged connect proxy.
// This verifies that it is put in the local state store properly for syncing
2019-08-09 19:19:30 +00:00
// later.
2018-04-17 12:29:02 +00:00
func TestAgent_RegisterService_UnmanagedConnectProxy ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_UnmanagedConnectProxy ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_UnmanagedConnectProxy ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_UnmanagedConnectProxy ( t * testing . T , extraHCL string ) {
t . Helper ( )
2018-03-10 01:16:12 +00:00
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2018-03-10 01:16:12 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-10 01:16:12 +00:00
2018-09-12 16:07:47 +00:00
// Register a proxy. Note that the destination doesn't exist here on this
// agent or in the catalog at all. This is intended and part of the design.
args := & api . AgentServiceRegistration {
Kind : api . ServiceKindConnectProxy ,
Name : "connect-proxy" ,
Port : 8000 ,
Proxy : & api . AgentServiceConnectProxyConfig {
DestinationServiceName : "web" ,
Upstreams : [ ] api . Upstream {
{
// No type to force default
DestinationName : "db" ,
LocalBindPort : 1234 ,
} ,
{
DestinationType : "prepared_query" ,
DestinationName : "geo-cache" ,
LocalBindPort : 1235 ,
} ,
} ,
2021-04-13 22:08:41 +00:00
Mode : api . ProxyModeTransparent ,
TransparentProxy : & api . TransparentProxyConfig {
OutboundListenerPort : 808 ,
} ,
2018-03-10 01:16:12 +00:00
} ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2018-03-10 01:16:12 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2018-03-10 01:16:12 +00:00
2018-03-12 17:13:44 +00:00
// Ensure the service
2019-12-10 02:26:41 +00:00
sid := structs . NewServiceID ( "connect-proxy" , nil )
svc := a . State . Service ( sid )
require . NotNil ( t , svc , "has service" )
require . Equal ( t , structs . ServiceKindConnectProxy , svc . Kind )
2021-07-26 21:12:29 +00:00
// Registration sets default types and namespaces
for i := range args . Proxy . Upstreams {
if args . Proxy . Upstreams [ i ] . DestinationType == "" {
args . Proxy . Upstreams [ i ] . DestinationType = api . UpstreamDestTypeService
}
if args . Proxy . Upstreams [ i ] . DestinationNamespace == "" {
args . Proxy . Upstreams [ i ] . DestinationNamespace =
structs . DefaultEnterpriseMetaInDefaultPartition ( ) . NamespaceOrEmpty ( )
}
2021-08-20 16:57:45 +00:00
if args . Proxy . Upstreams [ i ] . DestinationPartition == "" {
args . Proxy . Upstreams [ i ] . DestinationPartition =
structs . DefaultEnterpriseMetaInDefaultPartition ( ) . PartitionOrEmpty ( )
}
2021-07-26 21:12:29 +00:00
}
2019-12-10 02:26:41 +00:00
require . Equal ( t , args . Proxy , svc . Proxy . ToAPI ( ) )
2018-03-10 01:16:12 +00:00
// Ensure the token was configured
2019-12-10 02:26:41 +00:00
require . Equal ( t , "abc123" , a . State . ServiceToken ( structs . NewServiceID ( "connect-proxy" , nil ) ) )
2018-03-10 01:16:12 +00:00
}
2018-09-27 13:33:12 +00:00
func testDefaultSidecar ( svc string , port int , fns ... func ( * structs . NodeService ) ) * structs . NodeService {
ns := & structs . NodeService {
2020-01-17 14:54:17 +00:00
ID : svc + "-sidecar-proxy" ,
Kind : structs . ServiceKindConnectProxy ,
Service : svc + "-sidecar-proxy" ,
Port : 2222 ,
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
2019-01-08 10:13:49 +00:00
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
2018-09-27 13:33:12 +00:00
// Note that LocallyRegisteredAsSidecar should be true on the internal
// NodeService, but that we never want to see it in the HTTP response as
// it's internal only state. This is being compared directly to local state
// so should be present here.
LocallyRegisteredAsSidecar : true ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : svc ,
DestinationServiceID : svc ,
LocalServiceAddress : "127.0.0.1" ,
LocalServicePort : port ,
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2018-09-27 13:33:12 +00:00
}
for _ , fn := range fns {
fn ( ns )
}
return ns
}
2019-02-20 16:23:38 +00:00
// testCreateToken creates a Policy for the provided rules and a Token linked to that Policy.
2023-12-06 17:11:32 +00:00
func testCreateToken ( t testutil . TestingTB , a * TestAgent , rules string ) string {
2019-02-20 16:23:38 +00:00
policyName , err := uuid . GenerateUUID ( ) // we just need a unique name for the test and UUIDs are definitely unique
require . NoError ( t , err )
policyID := testCreatePolicy ( t , a , policyName , rules )
2018-09-27 14:00:51 +00:00
args := map [ string ] interface { } {
2019-12-06 16:14:56 +00:00
"Description" : "User Token" ,
2019-02-20 16:23:38 +00:00
"Policies" : [ ] map [ string ] interface { } {
2020-06-16 17:19:31 +00:00
{
2019-02-20 16:23:38 +00:00
"ID" : policyID ,
} ,
} ,
"Local" : false ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/acl/token" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-02-20 16:23:38 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
dec := json . NewDecoder ( resp . Body )
aclResp := & structs . ACLToken { }
if err := dec . Decode ( aclResp ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
2019-02-20 16:23:38 +00:00
return aclResp . SecretID
}
2023-12-06 17:11:32 +00:00
func testCreatePolicy ( t testutil . TestingTB , a * TestAgent , name , rules string ) string {
2019-02-20 16:23:38 +00:00
args := map [ string ] interface { } {
"Name" : name ,
2018-09-27 14:00:51 +00:00
"Rules" : rules ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-09-27 14:00:51 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
dec := json . NewDecoder ( resp . Body )
aclResp := & structs . ACLPolicy { }
if err := dec . Decode ( aclResp ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-09-27 14:00:51 +00:00
return aclResp . ID
}
2018-09-27 13:33:12 +00:00
// This tests local agent service registration with a sidecar service. Note we
// only test simple defaults for the sidecar here since the actual logic for
// handling sidecar defaults and port assignment is tested thoroughly in
// TestAgent_sidecarServiceFromNodeService. Note it also tests Deregister
// explicitly too since setup is identical.
func TestAgent_RegisterServiceDeregisterService_Sidecar ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterServiceDeregisterService_Sidecar ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterServiceDeregisterService_Sidecar ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterServiceDeregisterService_Sidecar ( t * testing . T , extraHCL string ) {
t . Helper ( )
2018-09-27 13:33:12 +00:00
tests := [ ] struct {
name string
preRegister , preRegister2 * structs . NodeService
// Use raw JSON payloads rather than encoding to avoid subtleties with some
// internal representations and different ways they encode and decode. We
// rely on the payload being Unmarshalable to structs.ServiceDefinition
// directly.
json string
enableACL bool
2023-02-06 15:35:52 +00:00
policies string
2018-09-27 13:33:12 +00:00
wantNS * structs . NodeService
wantErr string
wantSidecarIDLeftAfterDereg bool
assertStateFn func ( t * testing . T , state * local . State )
} {
{
name : "sanity check no sidecar case" ,
json : `
{
"name" : "web" ,
"port" : 1111
}
` ,
wantNS : nil ,
wantErr : "" ,
} ,
{
name : "default sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
wantErr : "" ,
} ,
{
name : "ACL OK defaults" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2019-02-20 16:23:38 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
2018-09-27 13:33:12 +00:00
service "web" {
policy = "write"
} ` ,
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
wantErr : "" ,
} ,
{
name : "ACL denied" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
2023-02-06 15:35:52 +00:00
enableACL : true ,
2023-09-18 22:56:23 +00:00
policies : ` ` , // No policies means no valid token
2023-02-06 15:35:52 +00:00
wantNS : nil ,
wantErr : "Permission denied" ,
2018-09-27 13:33:12 +00:00
} ,
{
name : "ACL OK for service but not for sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
enableACL : true ,
// This will become more common/reasonable when ACLs support exact match.
2023-02-06 15:35:52 +00:00
policies : `
2018-09-27 13:33:12 +00:00
service "web-sidecar-proxy" {
policy = "deny"
}
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
2019-02-20 16:23:38 +00:00
name : "ACL OK for service and sidecar but not sidecar's overridden destination" ,
2018-09-27 13:33:12 +00:00
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"proxy" : {
"DestinationServiceName" : "foo"
}
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2019-02-20 16:23:38 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
2018-09-27 13:33:12 +00:00
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
name : "ACL OK for service but not for overridden sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"name" : "foo-sidecar-proxy"
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2019-02-20 16:23:38 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
2018-09-27 13:33:12 +00:00
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
name : "ACL OK for service but and overridden for sidecar" ,
// This test ensures that if the sidecar embeds it's own token with
2019-03-06 17:13:28 +00:00
// different privs from the main request token it will be honored for the
2018-09-27 13:33:12 +00:00
// sidecar registration. We use the test root token since that should have
// permission.
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"name" : "foo" ,
"token" : "root"
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2019-02-20 16:23:38 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
2018-09-27 13:33:12 +00:00
service "web" {
policy = "write"
} ` ,
wantNS : testDefaultSidecar ( "web" , 1111 , func ( ns * structs . NodeService ) {
ns . Service = "foo"
} ) ,
wantErr : "" ,
} ,
{
name : "invalid check definition in sidecar" ,
// Note no interval in the TCP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"check" : {
"TCP" : "foo"
}
}
}
}
` ,
wantNS : nil ,
wantErr : "invalid check in sidecar_service" ,
} ,
{
name : "invalid checks definitions in sidecar" ,
// Note no interval in the TCP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"checks" : [ {
"TCP" : "foo"
} ]
}
}
}
` ,
wantNS : nil ,
wantErr : "invalid check in sidecar_service" ,
} ,
{
name : "invalid check status in sidecar" ,
// Note no interval in the TCP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"check" : {
"TCP" : "foo" ,
"Interval" : 10 ,
"Status" : "unsupported-status"
}
}
}
}
` ,
wantNS : nil ,
wantErr : "Status for checks must 'passing', 'warning', 'critical'" ,
} ,
{
2019-02-20 16:23:38 +00:00
name : "invalid checks status in sidecar" ,
2018-09-27 13:33:12 +00:00
// Note no interval in the TCP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"checks" : [ {
"TCP" : "foo" ,
"Interval" : 10 ,
"Status" : "unsupported-status"
} ]
}
}
}
` ,
wantNS : nil ,
wantErr : "Status for checks must 'passing', 'warning', 'critical'" ,
} ,
{
name : "another service registered with same ID as a sidecar should not be deregistered" ,
// Add another service with the same ID that a sidecar for web would have
preRegister : & structs . NodeService {
ID : "web-sidecar-proxy" ,
Service : "fake-sidecar" ,
Port : 9999 ,
} ,
// Register web with NO SIDECAR
json : `
{
"name" : "web" ,
"port" : 1111
}
` ,
// Note here that although the registration here didn't register it, we
// should still see the NodeService we pre-registered here.
wantNS : & structs . NodeService {
2020-01-17 14:54:17 +00:00
ID : "web-sidecar-proxy" ,
Service : "fake-sidecar" ,
Port : 9999 ,
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
2019-01-08 10:13:49 +00:00
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2018-09-27 13:33:12 +00:00
} ,
// After we deregister the web service above, the fake sidecar with
// clashing ID SHOULD NOT have been removed since it wasn't part of the
// original registration.
wantSidecarIDLeftAfterDereg : true ,
} ,
{
name : "updates to sidecar should work" ,
// Add a valid sidecar already registered
preRegister : & structs . NodeService {
ID : "web-sidecar-proxy" ,
Service : "web-sidecar-proxy" ,
LocallyRegisteredAsSidecar : true ,
Port : 9999 ,
} ,
// Register web with Sidecar on different port
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"Port" : 6666
}
}
}
` ,
// Note here that although the registration here didn't register it, we
// should still see the NodeService we pre-registered here.
wantNS : & structs . NodeService {
Kind : "connect-proxy" ,
ID : "web-sidecar-proxy" ,
Service : "web-sidecar-proxy" ,
LocallyRegisteredAsSidecar : true ,
Port : 6666 ,
2020-01-17 14:54:17 +00:00
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
2019-01-08 10:13:49 +00:00
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
2018-09-27 13:33:12 +00:00
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "web" ,
DestinationServiceID : "web" ,
LocalServiceAddress : "127.0.0.1" ,
LocalServicePort : 1111 ,
} ,
2021-07-22 18:20:45 +00:00
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
2018-09-27 13:33:12 +00:00
} ,
} ,
{
name : "update that removes sidecar should NOT deregister it" ,
// Add web with a valid sidecar already registered
preRegister : & structs . NodeService {
ID : "web" ,
Service : "web" ,
Port : 1111 ,
} ,
preRegister2 : testDefaultSidecar ( "web" , 1111 ) ,
// Register (update) web and remove sidecar (and port for sanity check)
json : `
{
"name" : "web" ,
"port" : 2222
}
` ,
// Sidecar should still be there such that API can update registration
// without accidentally removing a sidecar. This is equivalent to embedded
// checks which are not removed by just not being included in an update.
// We will document that sidecar registrations via API must be explicitiy
// deregistered.
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
// Sanity check the rest of the update happened though.
assertStateFn : func ( t * testing . T , state * local . State ) {
2019-12-10 02:26:41 +00:00
svc := state . Service ( structs . NewServiceID ( "web" , nil ) )
require . NotNil ( t , svc )
2018-09-27 13:33:12 +00:00
require . Equal ( t , 2222 , svc . Port )
} ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
// Constrain auto ports to 1 available to make it deterministic
2018-10-17 20:20:35 +00:00
hcl := ` ports {
2018-09-27 13:33:12 +00:00
sidecar_min_port = 2222
sidecar_max_port = 2222
}
`
if tt . enableACL {
hcl = hcl + TestACLConfig ( )
}
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , hcl + " " + extraHCL )
2018-09-27 13:33:12 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
if tt . preRegister != nil {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , a . addServiceFromSource ( tt . preRegister , nil , false , "" , ConfigSourceLocal ) )
2018-09-27 13:33:12 +00:00
}
if tt . preRegister2 != nil {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , a . addServiceFromSource ( tt . preRegister2 , nil , false , "" , ConfigSourceLocal ) )
2018-09-27 13:33:12 +00:00
}
// Create an ACL token with require policy
var token string
2023-02-06 15:35:52 +00:00
if tt . enableACL && tt . policies != "" {
token = testCreateToken ( t , a , tt . policies )
2018-09-27 13:33:12 +00:00
}
br := bytes . NewBufferString ( tt . json )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , br )
req . Header . Add ( "X-Consul-Token" , token )
2018-09-27 13:33:12 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-09-27 13:33:12 +00:00
if tt . wantErr != "" {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Contains ( t , strings . ToLower ( resp . Body . String ( ) ) , strings . ToLower ( tt . wantErr ) )
2018-09-27 13:33:12 +00:00
return
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code , "request failed with body: %s" ,
2018-09-27 13:33:12 +00:00
resp . Body . String ( ) )
// Sanity the target service registration
2021-08-19 20:09:42 +00:00
svcs := a . State . AllServices ( )
2018-09-27 13:33:12 +00:00
// Parse the expected definition into a ServiceDefinition
var sd structs . ServiceDefinition
2021-12-07 14:44:03 +00:00
err := json . Unmarshal ( [ ] byte ( tt . json ) , & sd )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
require . NotEmpty ( t , sd . Name )
2018-09-27 13:33:12 +00:00
svcID := sd . ID
if svcID == "" {
svcID = sd . Name
}
2019-12-10 02:26:41 +00:00
sid := structs . NewServiceID ( svcID , nil )
svc , ok := svcs [ sid ]
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . True ( t , ok , "has service " + sid . String ( ) )
assert . Equal ( t , sd . Name , svc . Service )
assert . Equal ( t , sd . Port , svc . Port )
2018-09-27 13:33:12 +00:00
// Ensure that the actual registered service _doesn't_ still have it's
// sidecar info since it's duplicate and we don't want that synced up to
2019-03-06 17:13:28 +00:00
// the catalog or included in responses particularly - it's just
2018-09-27 13:33:12 +00:00
// registration syntax sugar.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Nil ( t , svc . Connect . SidecarService )
2018-09-27 13:33:12 +00:00
if tt . wantNS == nil {
// Sanity check that there was no service registered, we rely on there
// being no services at start of test so we can just use the count.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Len ( t , svcs , 1 , "should be no sidecar registered" )
2018-09-27 13:33:12 +00:00
return
}
// Ensure sidecar
2019-12-10 02:26:41 +00:00
svc , ok = svcs [ structs . NewServiceID ( tt . wantNS . ID , nil ) ]
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . True ( t , ok , "no sidecar registered at " + tt . wantNS . ID )
assert . Equal ( t , tt . wantNS , svc )
2018-09-27 13:33:12 +00:00
if tt . assertStateFn != nil {
tt . assertStateFn ( t , a . State )
}
// Now verify deregistration also removes sidecar (if there was one and it
// was added via sidecar not just coincidental ID clash)
{
req := httptest . NewRequest ( "PUT" ,
2023-01-24 16:21:41 +00:00
"/v1/agent/service/deregister/" + svcID , nil )
req . Header . Add ( "X-Consul-Token" , token )
2018-09-27 13:33:12 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusOK , resp . Code )
2018-09-27 13:33:12 +00:00
2021-08-19 20:09:42 +00:00
svcs := a . State . AllServices ( )
2020-05-14 18:41:20 +00:00
_ , ok = svcs [ structs . NewServiceID ( tt . wantNS . ID , nil ) ]
2018-09-27 13:33:12 +00:00
if tt . wantSidecarIDLeftAfterDereg {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . True ( t , ok , "removed non-sidecar service at " + tt . wantNS . ID )
2018-09-27 13:33:12 +00:00
} else {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . False ( t , ok , "sidecar not deregistered with service " + svcID )
2018-09-27 13:33:12 +00:00
}
}
} )
}
}
2022-06-06 19:13:19 +00:00
// This tests local agent service registration with a sidecar service. Note we
// only test simple defaults for the sidecar here since the actual logic for
// handling sidecar defaults and port assignment is tested thoroughly in
// TestAgent_sidecarServiceFromNodeService. Note it also tests Deregister
// explicitly too since setup is identical.
func TestAgent_RegisterServiceDeregisterService_Sidecar_UDP ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterServiceDeregisterService_Sidecar_UDP ( t , "enable_central_service_config = false" )
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterServiceDeregisterService_Sidecar_UDP ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterServiceDeregisterService_Sidecar_UDP ( t * testing . T , extraHCL string ) {
t . Helper ( )
tests := [ ] struct {
name string
preRegister , preRegister2 * structs . NodeService
// Use raw JSON payloads rather than encoding to avoid subtleties with some
// internal representations and different ways they encode and decode. We
// rely on the payload being Unmarshalable to structs.ServiceDefinition
// directly.
json string
enableACL bool
2023-02-06 15:35:52 +00:00
policies string
2022-06-06 19:13:19 +00:00
wantNS * structs . NodeService
wantErr string
wantSidecarIDLeftAfterDereg bool
assertStateFn func ( t * testing . T , state * local . State )
} {
{
name : "sanity check no sidecar case" ,
json : `
{
"name" : "web" ,
"port" : 1111
}
` ,
wantNS : nil ,
wantErr : "" ,
} ,
{
name : "default sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
wantErr : "" ,
} ,
{
name : "ACL OK defaults" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2022-06-06 19:13:19 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
service "web" {
policy = "write"
} ` ,
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
wantErr : "" ,
} ,
{
name : "ACL denied" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
2023-02-06 15:35:52 +00:00
enableACL : true ,
policies : ` ` , // No policies means no valid token
wantNS : nil ,
wantErr : "Permission denied" ,
2022-06-06 19:13:19 +00:00
} ,
{
name : "ACL OK for service but not for sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : { }
}
}
` ,
enableACL : true ,
// This will become more common/reasonable when ACLs support exact match.
2023-02-06 15:35:52 +00:00
policies : `
2022-06-06 19:13:19 +00:00
service "web-sidecar-proxy" {
policy = "deny"
}
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
name : "ACL OK for service and sidecar but not sidecar's overridden destination" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"proxy" : {
"DestinationServiceName" : "foo"
}
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2022-06-06 19:13:19 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
name : "ACL OK for service but not for overridden sidecar" ,
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"name" : "foo-sidecar-proxy"
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2022-06-06 19:13:19 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
service "web" {
policy = "write"
} ` ,
wantNS : nil ,
wantErr : "Permission denied" ,
} ,
{
name : "ACL OK for service but and overridden for sidecar" ,
// This test ensures that if the sidecar embeds it's own token with
// different privs from the main request token it will be honored for the
// sidecar registration. We use the test root token since that should have
// permission.
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"name" : "foo" ,
"token" : "root"
}
}
}
` ,
enableACL : true ,
2023-02-06 15:35:52 +00:00
policies : `
2022-06-06 19:13:19 +00:00
service "web-sidecar-proxy" {
policy = "write"
}
service "web" {
policy = "write"
} ` ,
wantNS : testDefaultSidecar ( "web" , 1111 , func ( ns * structs . NodeService ) {
ns . Service = "foo"
} ) ,
wantErr : "" ,
} ,
{
name : "invalid check definition in sidecar" ,
// Note no interval in the UDP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"check" : {
"UDP" : "foo"
}
}
}
}
` ,
wantNS : nil ,
wantErr : "invalid check in sidecar_service" ,
} ,
{
name : "invalid checks definitions in sidecar" ,
// Note no interval in the UDP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"checks" : [ {
"UDP" : "foo"
} ]
}
}
}
` ,
wantNS : nil ,
wantErr : "invalid check in sidecar_service" ,
} ,
{
name : "invalid check status in sidecar" ,
// Note no interval in the UDP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"check" : {
"UDP" : "foo" ,
"Interval" : 10 ,
"Status" : "unsupported-status"
}
}
}
}
` ,
wantNS : nil ,
wantErr : "Status for checks must 'passing', 'warning', 'critical'" ,
} ,
{
name : "invalid checks status in sidecar" ,
// Note no interval in the UDP check should fail validation
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"checks" : [ {
"UDP" : "foo" ,
"Interval" : 10 ,
"Status" : "unsupported-status"
} ]
}
}
}
` ,
wantNS : nil ,
wantErr : "Status for checks must 'passing', 'warning', 'critical'" ,
} ,
{
name : "another service registered with same ID as a sidecar should not be deregistered" ,
// Add another service with the same ID that a sidecar for web would have
preRegister : & structs . NodeService {
ID : "web-sidecar-proxy" ,
Service : "fake-sidecar" ,
Port : 9999 ,
} ,
// Register web with NO SIDECAR
json : `
{
"name" : "web" ,
"port" : 1111
}
` ,
// Note here that although the registration here didn't register it, we
// should still see the NodeService we pre-registered here.
wantNS : & structs . NodeService {
ID : "web-sidecar-proxy" ,
Service : "fake-sidecar" ,
Port : 9999 ,
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
} ,
// After we deregister the web service above, the fake sidecar with
// clashing ID SHOULD NOT have been removed since it wasn't part of the
// original registration.
wantSidecarIDLeftAfterDereg : true ,
} ,
{
name : "updates to sidecar should work" ,
// Add a valid sidecar already registered
preRegister : & structs . NodeService {
ID : "web-sidecar-proxy" ,
Service : "web-sidecar-proxy" ,
LocallyRegisteredAsSidecar : true ,
Port : 9999 ,
} ,
// Register web with Sidecar on different port
json : `
{
"name" : "web" ,
"port" : 1111 ,
"connect" : {
"SidecarService" : {
"Port" : 6666
}
}
}
` ,
// Note here that although the registration here didn't register it, we
// should still see the NodeService we pre-registered here.
wantNS : & structs . NodeService {
Kind : "connect-proxy" ,
ID : "web-sidecar-proxy" ,
Service : "web-sidecar-proxy" ,
LocallyRegisteredAsSidecar : true ,
Port : 6666 ,
TaggedAddresses : map [ string ] structs . ServiceAddress { } ,
Weights : & structs . Weights {
Passing : 1 ,
Warning : 1 ,
} ,
Proxy : structs . ConnectProxyConfig {
DestinationServiceName : "web" ,
DestinationServiceID : "web" ,
LocalServiceAddress : "127.0.0.1" ,
LocalServicePort : 1111 ,
} ,
EnterpriseMeta : * structs . DefaultEnterpriseMetaInDefaultPartition ( ) ,
} ,
} ,
{
name : "update that removes sidecar should NOT deregister it" ,
// Add web with a valid sidecar already registered
preRegister : & structs . NodeService {
ID : "web" ,
Service : "web" ,
Port : 1111 ,
} ,
preRegister2 : testDefaultSidecar ( "web" , 1111 ) ,
// Register (update) web and remove sidecar (and port for sanity check)
json : `
{
"name" : "web" ,
"port" : 2222
}
` ,
// Sidecar should still be there such that API can update registration
// without accidentally removing a sidecar. This is equivalent to embedded
// checks which are not removed by just not being included in an update.
// We will document that sidecar registrations via API must be explicitiy
// deregistered.
wantNS : testDefaultSidecar ( "web" , 1111 ) ,
// Sanity check the rest of the update happened though.
assertStateFn : func ( t * testing . T , state * local . State ) {
svc := state . Service ( structs . NewServiceID ( "web" , nil ) )
require . NotNil ( t , svc )
require . Equal ( t , 2222 , svc . Port )
} ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
// Constrain auto ports to 1 available to make it deterministic
hcl := ` ports {
sidecar_min_port = 2222
sidecar_max_port = 2222
}
`
if tt . enableACL {
hcl = hcl + TestACLConfig ( )
}
a := NewTestAgent ( t , hcl + " " + extraHCL )
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
if tt . preRegister != nil {
require . NoError ( t , a . addServiceFromSource ( tt . preRegister , nil , false , "" , ConfigSourceLocal ) )
}
if tt . preRegister2 != nil {
require . NoError ( t , a . addServiceFromSource ( tt . preRegister2 , nil , false , "" , ConfigSourceLocal ) )
}
// Create an ACL token with require policy
var token string
2023-02-06 15:35:52 +00:00
if tt . enableACL && tt . policies != "" {
token = testCreateToken ( t , a , tt . policies )
2022-06-06 19:13:19 +00:00
}
br := bytes . NewBufferString ( tt . json )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , br )
req . Header . Add ( "X-Consul-Token" , token )
2022-06-06 19:13:19 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if tt . wantErr != "" {
require . Contains ( t , strings . ToLower ( resp . Body . String ( ) ) , strings . ToLower ( tt . wantErr ) )
return
}
require . Equal ( t , 200 , resp . Code , "request failed with body: %s" ,
resp . Body . String ( ) )
// Sanity the target service registration
svcs := a . State . AllServices ( )
// Parse the expected definition into a ServiceDefinition
var sd structs . ServiceDefinition
err := json . Unmarshal ( [ ] byte ( tt . json ) , & sd )
require . NoError ( t , err )
require . NotEmpty ( t , sd . Name )
svcID := sd . ID
if svcID == "" {
svcID = sd . Name
}
sid := structs . NewServiceID ( svcID , nil )
svc , ok := svcs [ sid ]
require . True ( t , ok , "has service " + sid . String ( ) )
assert . Equal ( t , sd . Name , svc . Service )
assert . Equal ( t , sd . Port , svc . Port )
// Ensure that the actual registered service _doesn't_ still have it's
// sidecar info since it's duplicate and we don't want that synced up to
// the catalog or included in responses particularly - it's just
// registration syntax sugar.
assert . Nil ( t , svc . Connect . SidecarService )
if tt . wantNS == nil {
// Sanity check that there was no service registered, we rely on there
// being no services at start of test so we can just use the count.
assert . Len ( t , svcs , 1 , "should be no sidecar registered" )
return
}
// Ensure sidecar
svc , ok = svcs [ structs . NewServiceID ( tt . wantNS . ID , nil ) ]
require . True ( t , ok , "no sidecar registered at " + tt . wantNS . ID )
assert . Equal ( t , tt . wantNS , svc )
if tt . assertStateFn != nil {
tt . assertStateFn ( t , a . State )
}
// Now verify deregistration also removes sidecar (if there was one and it
// was added via sidecar not just coincidental ID clash)
{
req := httptest . NewRequest ( "PUT" ,
2023-01-24 16:21:41 +00:00
"/v1/agent/service/deregister/" + svcID , nil )
req . Header . Add ( "X-Consul-Token" , token )
2022-06-06 19:13:19 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
svcs := a . State . AllServices ( )
_ , ok = svcs [ structs . NewServiceID ( tt . wantNS . ID , nil ) ]
if tt . wantSidecarIDLeftAfterDereg {
require . True ( t , ok , "removed non-sidecar service at " + tt . wantNS . ID )
} else {
require . False ( t , ok , "sidecar not deregistered with service " + svcID )
}
}
} )
}
}
// END HERE
2018-03-12 20:05:06 +00:00
// This tests that connect proxy validation is done for local agent
// registration. This doesn't need to test validation exhaustively since
// that is done via a table test in the structs package.
2018-04-17 12:29:02 +00:00
func TestAgent_RegisterService_UnmanagedConnectProxyInvalid ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_UnmanagedConnectProxyInvalid ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_UnmanagedConnectProxyInvalid ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_UnmanagedConnectProxyInvalid ( t * testing . T , extraHCL string ) {
t . Helper ( )
2018-03-11 01:42:30 +00:00
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2018-03-11 01:42:30 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-11 01:42:30 +00:00
args := & structs . ServiceDefinition {
2018-09-12 16:07:47 +00:00
Kind : structs . ServiceKindConnectProxy ,
Name : "connect-proxy" ,
Proxy : & structs . ConnectProxyConfig {
DestinationServiceName : "db" ,
} ,
2018-03-11 01:42:30 +00:00
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2018-03-11 01:42:30 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Contains ( t , resp . Body . String ( ) , "Port" )
2018-03-11 01:42:30 +00:00
// Ensure the service doesn't exist
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Nil ( t , a . State . Service ( structs . NewServiceID ( "connect-proxy" , nil ) ) )
2018-03-11 01:42:30 +00:00
}
2018-06-04 05:20:16 +00:00
// Tests agent registration of a service that is connect native.
func TestAgent_RegisterService_ConnectNative ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_ConnectNative ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ConnectNative ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ConnectNative ( t * testing . T , extraHCL string ) {
t . Helper ( )
2018-06-04 05:20:16 +00:00
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2018-06-04 05:20:16 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-06-04 05:20:16 +00:00
// Register a proxy. Note that the destination doesn't exist here on
// this agent or in the catalog at all. This is intended and part
// of the design.
args := & structs . ServiceDefinition {
Name : "web" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
2018-06-05 17:51:05 +00:00
Connect : & structs . ServiceConnect {
2018-06-04 05:20:16 +00:00
Native : true ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , http . StatusOK , resp . Code )
2018-06-04 05:20:16 +00:00
// Ensure the service
2019-12-10 02:26:41 +00:00
svc := a . State . Service ( structs . NewServiceID ( "web" , nil ) )
require . NotNil ( t , svc )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , svc . Connect . Native )
2018-06-04 05:20:16 +00:00
}
2018-10-11 12:22:11 +00:00
func TestAgent_RegisterService_ScriptCheck_ExecDisable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_ScriptCheck_ExecDisable ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ScriptCheck_ExecDisable ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ScriptCheck_ExecDisable ( t * testing . T , extraHCL string ) {
t . Helper ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , extraHCL )
2018-10-11 12:22:11 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2018-10-11 12:22:11 +00:00
Port : 8000 ,
Check : structs . CheckType {
Name : "test-check" ,
Interval : time . Second ,
ScriptArgs : [ ] string { "true" } ,
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusInternalServerError != resp . Code {
t . Fatalf ( "expected 500 but got %v" , resp . Code )
2018-10-11 12:22:11 +00:00
}
2021-12-07 14:44:03 +00:00
if ! strings . Contains ( resp . Body . String ( ) , "Scripts are disabled on this agent" ) {
t . Fatalf ( "expected script disabled error, got: %s" , resp . Body . String ( ) )
2018-10-11 12:22:11 +00:00
}
checkID := types . CheckID ( "test-check" )
2019-12-10 02:26:41 +00:00
require . Nil ( t , a . State . Check ( structs . NewCheckID ( checkID , nil ) ) , "check registered with exec disabled" )
2018-10-11 12:22:11 +00:00
}
func TestAgent_RegisterService_ScriptCheck_ExecRemoteDisable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-24 15:04:48 +00:00
t . Run ( "normal" , func ( t * testing . T ) {
t . Parallel ( )
2020-10-01 14:19:14 +00:00
testAgent_RegisterService_ScriptCheck_ExecRemoteDisable ( t , "enable_central_service_config = false" )
2019-09-24 15:04:48 +00:00
} )
t . Run ( "service manager" , func ( t * testing . T ) {
t . Parallel ( )
testAgent_RegisterService_ScriptCheck_ExecRemoteDisable ( t , "enable_central_service_config = true" )
} )
}
func testAgent_RegisterService_ScriptCheck_ExecRemoteDisable ( t * testing . T , extraHCL string ) {
t . Helper ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2018-10-11 12:22:11 +00:00
enable_local_script_checks = true
2019-09-24 15:04:48 +00:00
` + extraHCL )
2018-10-11 12:22:11 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
args := & structs . ServiceDefinition {
Name : "test" ,
Meta : map [ string ] string { "hello" : "world" } ,
2022-01-20 12:47:50 +00:00
Tags : [ ] string { "primary" } ,
2018-10-11 12:22:11 +00:00
Port : 8000 ,
Check : structs . CheckType {
Name : "test-check" ,
Interval : time . Second ,
ScriptArgs : [ ] string { "true" } ,
} ,
Weights : & structs . Weights {
Passing : 100 ,
Warning : 3 ,
} ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "abc123" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusInternalServerError != resp . Code {
t . Fatalf ( "expected 500 but got %v" , resp . Code )
2018-10-11 12:22:11 +00:00
}
2021-12-07 14:44:03 +00:00
if ! strings . Contains ( resp . Body . String ( ) , "Scripts are disabled on this agent" ) {
t . Fatalf ( "expected script disabled error, got: %s" , resp . Body . String ( ) )
2018-10-11 12:22:11 +00:00
}
checkID := types . CheckID ( "test-check" )
2019-12-10 02:26:41 +00:00
require . Nil ( t , a . State . Check ( structs . NewCheckID ( checkID , nil ) ) , "check registered with exec disabled" )
2018-10-11 12:22:11 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_DeregisterService ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2014-01-30 23:56:03 +00:00
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : & structs . NodeService {
ID : "test" ,
Service : "test" ,
} ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
2014-01-30 23:56:03 +00:00
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2014-01-30 23:56:03 +00:00
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/deregister/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
t . Fatalf ( "expected 200 but got %v" , resp . Code )
2014-01-30 23:56:03 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
assert . Nil ( t , a . State . Service ( structs . NewServiceID ( "test" , nil ) ) , "have test service" )
assert . Nil ( t , a . State . Check ( structs . NewCheckID ( "test" , nil ) ) , "have test check" )
2014-01-30 23:56:03 +00:00
}
2015-01-15 09:17:35 +00:00
2016-12-14 22:16:46 +00:00
func TestAgent_DeregisterService_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : & structs . NodeService {
ID : "test" ,
Service : "test" ,
} ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
2016-12-14 22:16:46 +00:00
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/deregister/test" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/deregister/test" , nil )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
func TestAgent_ServiceMaintenance_BadRequest ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 09:17:35 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "not enabled" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/test" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2017-05-09 17:46:11 +00:00
if resp . Code != 400 {
t . Fatalf ( "expected 400, got %d" , resp . Code )
}
} )
2015-01-15 09:17:35 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no service id" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/?enable=true" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2017-05-09 17:46:11 +00:00
if resp . Code != 400 {
t . Fatalf ( "expected 400, got %d" , resp . Code )
}
} )
2015-01-15 18:51:00 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "bad service id" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/_nope_?enable=true" , nil )
resp := httptest . NewRecorder ( )
2021-07-15 21:17:49 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , 404 , resp . Code )
2022-01-05 20:18:08 +00:00
sid := structs . NewServiceID ( "_nope_" , nil )
require . Contains ( t , resp . Body . String ( ) , fmt . Sprintf ( ` Unknown service ID %q ` , sid ) )
2017-05-09 17:46:11 +00:00
} )
2015-01-15 09:17:35 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_ServiceMaintenance_Enable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 09:17:35 +00:00
// Register the service
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : & structs . NodeService {
ID : "test" ,
Service : "test" ,
} ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
2015-01-15 09:17:35 +00:00
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2015-01-15 09:17:35 +00:00
2015-01-15 18:51:00 +00:00
// Force the service into maintenance mode
2015-09-10 19:08:08 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/test?enable=true&reason=broken&token=mytoken" , nil )
2015-01-15 09:17:35 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2015-01-15 09:17:35 +00:00
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
// Ensure the maintenance check was registered
2019-12-10 02:26:41 +00:00
checkID := serviceMaintCheckID ( structs . NewServiceID ( "test" , nil ) )
check := a . State . Check ( checkID )
if check == nil {
2015-01-15 09:17:35 +00:00
t . Fatalf ( "should have registered maintenance check" )
}
2015-01-21 20:21:57 +00:00
2015-09-10 19:08:08 +00:00
// Ensure the token was added
2017-08-28 12:17:13 +00:00
if token := a . State . CheckToken ( checkID ) ; token != "mytoken" {
2015-09-10 19:08:08 +00:00
t . Fatalf ( "expected 'mytoken', got '%s'" , token )
}
2015-01-21 20:21:57 +00:00
// Ensure the reason was set in notes
if check . Notes != "broken" {
t . Fatalf ( "bad: %#v" , check )
}
2015-01-15 09:17:35 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_ServiceMaintenance_Disable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 09:17:35 +00:00
// Register the service
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : & structs . NodeService {
ID : "test" ,
Service : "test" ,
} ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
2015-01-15 09:17:35 +00:00
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2015-01-15 09:17:35 +00:00
// Force the service into maintenance mode
2019-12-10 02:26:41 +00:00
if err := a . EnableServiceMaintenance ( structs . NewServiceID ( "test" , nil ) , "" , "" ) ; err != nil {
2015-01-15 09:17:35 +00:00
t . Fatalf ( "err: %s" , err )
}
// Leave maintenance mode
2015-01-15 18:51:00 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/test?enable=false" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2015-01-15 09:17:35 +00:00
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
2015-01-15 18:51:00 +00:00
// Ensure the maintenance check was removed
2019-12-10 02:26:41 +00:00
checkID := serviceMaintCheckID ( structs . NewServiceID ( "test" , nil ) )
if existing := a . State . Check ( checkID ) ; existing != nil {
2015-01-15 18:51:00 +00:00
t . Fatalf ( "should have removed maintenance check" )
}
2015-01-15 09:17:35 +00:00
}
2015-01-15 19:26:14 +00:00
2016-12-14 22:16:46 +00:00
func TestAgent_ServiceMaintenance_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
// Register the service.
2021-12-07 14:44:03 +00:00
serviceReq := AddServiceRequest {
Service : & structs . NodeService {
ID : "test" ,
Service : "test" ,
} ,
chkTypes : nil ,
persist : false ,
token : "" ,
Source : ConfigSourceLocal ,
2016-12-14 22:16:46 +00:00
}
2021-12-07 14:44:03 +00:00
require . NoError ( t , a . AddService ( serviceReq ) )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/test?enable=true&reason=broken" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/maintenance/test?enable=true&reason=broken&token=root" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
func TestAgent_NodeMaintenance_BadRequest ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 19:26:14 +00:00
// Fails when no enable flag provided
2021-10-26 19:20:57 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/maintenance" , nil )
2017-09-26 06:11:19 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2015-01-15 19:26:14 +00:00
if resp . Code != 400 {
t . Fatalf ( "expected 400, got %d" , resp . Code )
}
}
2016-12-14 22:16:46 +00:00
func TestAgent_NodeMaintenance_Enable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 19:26:14 +00:00
// Force the node into maintenance mode
2021-10-26 19:20:57 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/maintenance?enable=true&reason=broken&token=mytoken" , nil )
2015-01-15 19:26:14 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2015-01-15 19:26:14 +00:00
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
// Ensure the maintenance check was registered
2019-12-10 02:26:41 +00:00
check := a . State . Check ( structs . NodeMaintCheckID )
if check == nil {
2015-01-15 19:26:14 +00:00
t . Fatalf ( "should have registered maintenance check" )
}
2015-01-21 20:21:57 +00:00
2015-09-10 19:08:08 +00:00
// Check that the token was used
2019-12-10 02:26:41 +00:00
if token := a . State . CheckToken ( structs . NodeMaintCheckID ) ; token != "mytoken" {
2015-09-10 19:08:08 +00:00
t . Fatalf ( "expected 'mytoken', got '%s'" , token )
}
2015-01-21 20:21:57 +00:00
// Ensure the reason was set in notes
if check . Notes != "broken" {
t . Fatalf ( "bad: %#v" , check )
}
2015-01-15 19:26:14 +00:00
}
2016-12-14 22:16:46 +00:00
func TestAgent_NodeMaintenance_Disable ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-15 19:26:14 +00:00
// Force the node into maintenance mode
2017-05-21 07:11:09 +00:00
a . EnableNodeMaintenance ( "" , "" )
2015-01-15 19:26:14 +00:00
// Leave maintenance mode
2021-10-26 19:20:57 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/maintenance?enable=false" , nil )
2015-01-15 19:26:14 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2015-01-15 19:26:14 +00:00
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
}
// Ensure the maintenance check was removed
2019-12-10 02:26:41 +00:00
if existing := a . State . Check ( structs . NodeMaintCheckID ) ; existing != nil {
2015-01-15 19:26:14 +00:00
t . Fatalf ( "should have removed maintenance check" )
}
}
2015-01-14 01:52:17 +00:00
2016-12-14 22:16:46 +00:00
func TestAgent_NodeMaintenance_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "no token" , func ( t * testing . T ) {
2021-10-26 19:20:57 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/maintenance?enable=true&reason=broken" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
2017-05-09 17:46:11 +00:00
t . Run ( "root token" , func ( t * testing . T ) {
2021-10-26 19:20:57 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/maintenance?enable=true&reason=broken&token=root" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2017-05-09 17:46:11 +00:00
} )
2016-12-14 22:16:46 +00:00
}
func TestAgent_RegisterCheck_Service ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2015-01-14 01:52:17 +00:00
2017-06-15 16:46:06 +00:00
args := & structs . ServiceDefinition {
2015-01-14 01:52:17 +00:00
Name : "memcache" ,
Port : 8000 ,
2017-06-15 16:46:06 +00:00
Check : structs . CheckType {
2015-01-14 01:52:17 +00:00
TTL : 15 * time . Second ,
} ,
}
2017-05-09 16:58:12 +00:00
// First register the service
2017-09-26 06:11:19 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
2015-01-14 01:52:17 +00:00
}
// Now register an additional check
2017-06-15 16:46:06 +00:00
checkArgs := & structs . CheckDefinition {
2015-01-14 01:52:17 +00:00
Name : "memcache_check2" ,
ServiceID : "memcache" ,
2017-05-15 19:49:13 +00:00
TTL : 15 * time . Second ,
2015-01-14 01:52:17 +00:00
}
2017-09-26 06:11:19 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/agent/check/register" , jsonReader ( checkArgs ) )
2021-12-07 14:44:03 +00:00
resp = httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != 200 {
t . Fatalf ( "expected 200, got %d" , resp . Code )
2015-01-14 01:52:17 +00:00
}
// Ensure we have a check mapping
2019-12-10 02:26:41 +00:00
result := a . State . Checks ( nil )
if _ , ok := result [ structs . NewCheckID ( "service:memcache" , nil ) ] ; ! ok {
2015-01-14 01:52:17 +00:00
t . Fatalf ( "missing memcached check" )
}
2019-12-10 02:26:41 +00:00
if _ , ok := result [ structs . NewCheckID ( "memcache_check2" , nil ) ] ; ! ok {
2015-01-14 01:52:17 +00:00
t . Fatalf ( "missing memcache_check2 check" )
}
// Make sure the new check is associated with the service
2019-12-10 02:26:41 +00:00
if result [ structs . NewCheckID ( "memcache_check2" , nil ) ] . ServiceID != "memcache" {
t . Fatalf ( "bad: %#v" , result [ structs . NewCheckID ( "memcached_check2" , nil ) ] )
2015-01-14 01:52:17 +00:00
}
2019-10-17 18:33:11 +00:00
// Make sure the new check has the right type
2019-12-10 02:26:41 +00:00
if result [ structs . NewCheckID ( "memcache_check2" , nil ) ] . Type != "ttl" {
t . Fatalf ( "expected TTL type, got %s" , result [ structs . NewCheckID ( "memcache_check2" , nil ) ] . Type )
2019-10-17 18:33:11 +00:00
}
2015-01-14 01:52:17 +00:00
}
2016-11-16 21:45:26 +00:00
2016-12-14 17:33:57 +00:00
func TestAgent_Monitor ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2016-11-16 21:45:26 +00:00
2020-01-28 23:50:41 +00:00
t . Run ( "unknown log level" , func ( t * testing . T ) {
// Try passing an invalid log level
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor?loglevel=invalid" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if http . StatusBadRequest != resp . Code {
t . Fatalf ( "expected 400 but got %v" , resp . Code )
2020-01-28 23:50:41 +00:00
}
substring := "Unknown log level"
2021-12-07 14:44:03 +00:00
if ! strings . Contains ( resp . Body . String ( ) , substring ) {
t . Fatalf ( "got: %s, wanted message containing: %s" , resp . Body . String ( ) , substring )
2020-01-28 23:50:41 +00:00
}
} )
t . Run ( "stream unstructured logs" , func ( t * testing . T ) {
// Try to stream logs until we see the expected log line
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor?loglevel=debug" , nil )
cancelCtx , cancelFunc := context . WithCancel ( context . Background ( ) )
req = req . WithContext ( cancelCtx )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
codeCh := make ( chan int )
2020-01-28 23:50:41 +00:00
go func ( ) {
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
codeCh <- resp . Code
2020-01-28 23:50:41 +00:00
} ( )
args := & structs . ServiceDefinition {
Name : "monitor" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
2016-11-16 21:45:26 +00:00
}
2020-01-28 23:50:41 +00:00
registerReq , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
res := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( res , registerReq )
if http . StatusOK != res . Code {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "expected 200 but got %v" , res . Code )
2020-01-28 23:50:41 +00:00
}
2016-12-15 02:13:30 +00:00
2020-01-28 23:50:41 +00:00
// Wait until we have received some type of logging output
2023-06-07 18:53:27 +00:00
require . Eventually ( r , func ( ) bool {
2020-01-28 23:50:41 +00:00
return len ( resp . Body . Bytes ( ) ) > 0
} , 3 * time . Second , 100 * time . Millisecond )
cancelFunc ( )
2021-12-07 14:44:03 +00:00
code := <- codeCh
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusOK , code )
2020-01-28 23:50:41 +00:00
got := resp . Body . String ( )
// Only check a substring that we are highly confident in finding
want := "Synced service: service="
if ! strings . Contains ( got , want ) {
r . Fatalf ( "got %q and did not find %q" , got , want )
}
} )
2017-04-29 16:34:02 +00:00
} )
2016-11-16 21:45:26 +00:00
2020-06-08 08:10:08 +00:00
t . Run ( "stream compressed unstructured logs" , func ( t * testing . T ) {
// The only purpose of this test is to see something being
// logged. Because /v1/agent/monitor is streaming the response
// it needs special handling with the compression.
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor?loglevel=debug" , nil )
// Usually this would be automatically set by transport content
// negotiation, but since this call doesn't go through a real
// transport, the header has to be set manually
req . Header [ "Accept-Encoding" ] = [ ] string { "gzip" }
cancelCtx , cancelFunc := context . WithCancel ( context . Background ( ) )
req = req . WithContext ( cancelCtx )
2023-06-30 03:00:29 +00:00
a . enableDebug . Store ( true )
2020-06-08 08:10:08 +00:00
resp := httptest . NewRecorder ( )
2023-06-30 03:00:29 +00:00
handler := a . srv . handler ( )
2020-07-02 20:47:54 +00:00
go handler . ServeHTTP ( resp , req )
2020-06-08 08:10:08 +00:00
args := & structs . ServiceDefinition {
Name : "monitor" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
registerReq , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
res := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( res , registerReq )
if http . StatusOK != res . Code {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "expected 200 but got %v" , res . Code )
2020-06-08 08:10:08 +00:00
}
// Wait until we have received some type of logging output
2023-06-07 18:53:27 +00:00
require . Eventually ( r , func ( ) bool {
2020-06-08 08:10:08 +00:00
return len ( resp . Body . Bytes ( ) ) > 0
} , 3 * time . Second , 100 * time . Millisecond )
cancelFunc ( )
} )
} )
2020-01-28 23:50:41 +00:00
t . Run ( "stream JSON logs" , func ( t * testing . T ) {
// Try to stream logs until we see the expected log line
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor?loglevel=debug&logjson" , nil )
cancelCtx , cancelFunc := context . WithCancel ( context . Background ( ) )
req = req . WithContext ( cancelCtx )
2016-11-16 21:45:26 +00:00
2020-01-28 23:50:41 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
codeCh := make ( chan int )
2020-01-28 23:50:41 +00:00
go func ( ) {
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
codeCh <- resp . Code
2020-01-28 23:50:41 +00:00
} ( )
2016-11-16 21:45:26 +00:00
2020-01-28 23:50:41 +00:00
args := & structs . ServiceDefinition {
Name : "monitor" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
registerReq , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
2021-12-07 14:44:03 +00:00
res := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( res , registerReq )
if http . StatusOK != res . Code {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "expected 200 but got %v" , res . Code )
2020-01-28 23:50:41 +00:00
}
// Wait until we have received some type of logging output
2023-06-07 18:53:27 +00:00
require . Eventually ( r , func ( ) bool {
2020-01-28 23:50:41 +00:00
return len ( resp . Body . Bytes ( ) ) > 0
} , 3 * time . Second , 100 * time . Millisecond )
cancelFunc ( )
2021-12-07 14:44:03 +00:00
code := <- codeCh
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusOK , code )
2016-12-15 02:13:30 +00:00
2020-01-28 23:50:41 +00:00
// Each line is output as a separate JSON object, we grab the first and
// make sure it can be unmarshalled.
firstLine := bytes . Split ( resp . Body . Bytes ( ) , [ ] byte ( "\n" ) ) [ 0 ]
var output map [ string ] interface { }
if err := json . Unmarshal ( firstLine , & output ) ; err != nil {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "err: %v" , err )
2020-01-28 23:50:41 +00:00
}
} )
} )
// hopefully catch any potential regression in serf/memberlist logging setup.
t . Run ( "serf shutdown logging" , func ( t * testing . T ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor?loglevel=debug" , nil )
cancelCtx , cancelFunc := context . WithCancel ( context . Background ( ) )
req = req . WithContext ( cancelCtx )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
codeCh := make ( chan int )
2020-08-13 21:48:46 +00:00
chStarted := make ( chan struct { } )
2020-01-28 23:50:41 +00:00
go func ( ) {
2020-08-13 21:48:46 +00:00
close ( chStarted )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
codeCh <- resp . Code
2020-01-28 23:50:41 +00:00
} ( )
2020-08-13 21:48:46 +00:00
<- chStarted
2020-01-28 23:50:41 +00:00
require . NoError ( t , a . Shutdown ( ) )
// Wait until we have received some type of logging output
require . Eventually ( t , func ( ) bool {
return len ( resp . Body . Bytes ( ) ) > 0
} , 3 * time . Second , 100 * time . Millisecond )
cancelFunc ( )
2021-12-07 14:44:03 +00:00
code := <- codeCh
require . Equal ( t , http . StatusOK , code )
2020-01-28 23:50:41 +00:00
got := resp . Body . String ( )
want := "serf: Shutdown without a Leave"
if ! strings . Contains ( got , want ) {
t . Fatalf ( "got %q and did not find %q" , got , want )
}
} )
2016-11-16 21:45:26 +00:00
}
2016-12-14 17:33:57 +00:00
func TestAgent_Monitor_ACLDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-05-21 07:54:40 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2017-05-21 07:11:09 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2016-12-14 17:33:57 +00:00
// Try without a token.
2017-05-09 11:38:05 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/monitor" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if http . StatusForbidden != resp . Code {
t . Fatalf ( "expected 403 but got %v" , resp . Code )
2016-12-14 17:33:57 +00:00
}
// This proves we call the ACL function, and we've got the other monitor
// test to prove monitor works, which should be sufficient. The monitor
// logic is a little complex to set up so isn't worth repeating again
// here.
}
2017-07-26 18:03:43 +00:00
2019-10-04 18:37:34 +00:00
func TestAgent_TokenTriggersFullSync ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-10-04 18:37:34 +00:00
t . Parallel ( )
body := func ( token string ) io . Reader {
return jsonReader ( & api . AgentToken { Token : token } )
}
createNodePolicy := func ( t * testing . T , a * TestAgent , policyName string ) * structs . ACLPolicy {
policy := & structs . ACLPolicy {
Name : policyName ,
Rules : ` node_prefix "" { policy = "write" } ` ,
}
2023-01-24 16:21:41 +00:00
req , err := http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonBody ( policy ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-10-04 18:37:34 +00:00
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-10-04 18:37:34 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
policy = & structs . ACLPolicy { }
require . NoError ( t , dec . Decode ( policy ) )
2019-10-04 18:37:34 +00:00
return policy
}
createNodeToken := func ( t * testing . T , a * TestAgent , policyName string ) * structs . ACLToken {
createNodePolicy ( t , a , policyName )
token := & structs . ACLToken {
Description : "test" ,
Policies : [ ] structs . ACLTokenPolicyLink {
2020-06-16 17:19:31 +00:00
{ Name : policyName } ,
2019-10-04 18:37:34 +00:00
} ,
}
2023-01-24 16:21:41 +00:00
req , err := http . NewRequest ( "PUT" , "/v1/acl/token" , jsonBody ( token ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2019-10-04 18:37:34 +00:00
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
2019-10-04 18:37:34 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
token = & structs . ACLToken { }
require . NoError ( t , dec . Decode ( token ) )
2019-10-04 18:37:34 +00:00
return token
}
cases := [ ] struct {
path string
tokenGetFn func ( * token . Store ) string
} {
{
path : "acl_agent_token" ,
tokenGetFn : ( * token . Store ) . AgentToken ,
} ,
{
path : "agent" ,
tokenGetFn : ( * token . Store ) . AgentToken ,
} ,
{
path : "acl_token" ,
tokenGetFn : ( * token . Store ) . UserToken ,
} ,
{
path : "default" ,
tokenGetFn : ( * token . Store ) . UserToken ,
} ,
}
for _ , tt := range cases {
tt := tt
t . Run ( tt . path , func ( t * testing . T ) {
2023-01-24 16:21:41 +00:00
url := fmt . Sprintf ( "/v1/agent/token/%s" , tt . path )
2019-10-04 18:37:34 +00:00
2021-12-07 12:48:50 +00:00
a := NewTestAgent ( t , `
primary_datacenter = "dc1"
2019-10-04 18:37:34 +00:00
acl {
2021-12-07 12:48:50 +00:00
enabled = true
default_policy = "deny"
2019-10-04 18:37:34 +00:00
tokens {
2021-12-07 12:48:50 +00:00
initial_management = "root"
2019-10-04 18:37:34 +00:00
default = ""
agent = ""
2022-01-20 12:47:50 +00:00
agent_recovery = ""
2019-10-04 18:37:34 +00:00
replication = ""
}
}
` )
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
// create node policy and token
token := createNodeToken ( t , a , "test" )
req , err := http . NewRequest ( "PUT" , url , body ( token . SecretID ) )
2023-01-24 16:21:41 +00:00
req . Header . Add ( "X-Consul-Token" , "root" )
2019-10-04 18:37:34 +00:00
require . NoError ( t , err )
resp := httptest . NewRecorder ( )
2021-11-03 15:12:36 +00:00
a . srv . h . ServeHTTP ( resp , req )
2019-10-04 18:37:34 +00:00
require . Equal ( t , http . StatusOK , resp . Code )
require . Equal ( t , token . SecretID , tt . tokenGetFn ( a . tokens ) )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" ,
testrpc . WithToken ( "root" ) ,
testrpc . WaitForAntiEntropySync ( ) )
} )
}
}
2017-07-26 18:03:43 +00:00
func TestAgent_Token ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2017-07-26 18:03:43 +00:00
t . Parallel ( )
2017-11-28 21:47:30 +00:00
// The behavior of this handler when ACLs are disabled is vetted over
// in TestACL_Disabled_Response since there's already good infra set
// up over there to test this, and it calls the common function.
2021-12-07 12:48:50 +00:00
a := NewTestAgent ( t , `
primary_datacenter = "dc1"
2019-02-27 19:28:31 +00:00
acl {
2021-12-07 12:48:50 +00:00
enabled = true
default_policy = "deny"
2019-02-27 19:28:31 +00:00
tokens {
2021-12-07 12:48:50 +00:00
initial_management = "root"
2019-02-27 19:28:31 +00:00
default = ""
agent = ""
2022-01-20 12:47:50 +00:00
agent_recovery = ""
2019-02-27 19:28:31 +00:00
replication = ""
2023-01-10 16:24:02 +00:00
config_file_service_registration = ""
2019-02-27 19:28:31 +00:00
}
}
2017-09-25 18:40:42 +00:00
` )
2017-07-26 18:03:43 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2017-07-26 18:03:43 +00:00
2017-08-03 22:39:31 +00:00
type tokens struct {
2022-01-20 12:47:50 +00:00
user string
userSource tokenStore . TokenSource
agent string
agentSource tokenStore . TokenSource
agentRecovery string
agentRecoverySource tokenStore . TokenSource
repl string
replSource tokenStore . TokenSource
2023-01-10 16:24:02 +00:00
registration string
registrationSource tokenStore . TokenSource
2017-08-03 22:39:31 +00:00
}
2019-02-27 19:28:31 +00:00
resetTokens := func ( init tokens ) {
a . tokens . UpdateUserToken ( init . user , init . userSource )
a . tokens . UpdateAgentToken ( init . agent , init . agentSource )
2022-01-20 12:47:50 +00:00
a . tokens . UpdateAgentRecoveryToken ( init . agentRecovery , init . agentRecoverySource )
2019-02-27 19:28:31 +00:00
a . tokens . UpdateReplicationToken ( init . repl , init . replSource )
2023-01-10 16:24:02 +00:00
a . tokens . UpdateConfigFileRegistrationToken ( init . registration , init . registrationSource )
2017-08-03 22:39:31 +00:00
}
body := func ( token string ) io . Reader {
2017-07-26 18:03:43 +00:00
return jsonReader ( & api . AgentToken { Token : token } )
}
badJSON := func ( ) io . Reader {
return jsonReader ( false )
}
tests := [ ] struct {
name string
method , url string
body io . Reader
code int
2019-02-27 19:28:31 +00:00
init tokens
raw tokens
effective tokens
2021-10-26 19:20:57 +00:00
expectedErr string
2017-07-26 18:03:43 +00:00
} {
2017-08-03 22:39:31 +00:00
{
2020-08-17 23:30:25 +00:00
name : "bad token name" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "nope" ,
2020-08-17 23:30:25 +00:00
body : body ( "X" ) ,
2021-11-03 15:12:36 +00:00
code : http . StatusNotFound ,
2021-10-26 19:20:57 +00:00
expectedErr : ` Token "nope" is unknown ` ,
2017-08-03 22:39:31 +00:00
} ,
{
2021-10-26 19:20:57 +00:00
name : "bad JSON" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_token" ,
2021-10-26 19:20:57 +00:00
body : badJSON ( ) ,
2021-11-03 15:12:36 +00:00
code : http . StatusBadRequest ,
2022-04-29 17:42:49 +00:00
expectedErr : ` Request decode failed: json: cannot unmarshal bool into Go value of type api.AgentToken ` ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "set user legacy" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "U" ) ,
code : http . StatusOK ,
raw : tokens { user : "U" , userSource : tokenStore . TokenSourceAPI } ,
effective : tokens { user : "U" , agent : "U" } ,
} ,
{
name : "set default" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "default" ,
2019-02-27 19:28:31 +00:00
body : body ( "U" ) ,
code : http . StatusOK ,
raw : tokens { user : "U" , userSource : tokenStore . TokenSourceAPI } ,
effective : tokens { user : "U" , agent : "U" } ,
} ,
{
name : "set agent legacy" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_agent_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "A" ) ,
code : http . StatusOK ,
init : tokens { user : "U" , agent : "U" } ,
raw : tokens { user : "U" , agent : "A" , agentSource : tokenStore . TokenSourceAPI } ,
effective : tokens { user : "U" , agent : "A" } ,
} ,
{
name : "set agent" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent" ,
2019-02-27 19:28:31 +00:00
body : body ( "A" ) ,
code : http . StatusOK ,
init : tokens { user : "U" , agent : "U" } ,
raw : tokens { user : "U" , agent : "A" , agentSource : tokenStore . TokenSourceAPI } ,
effective : tokens { user : "U" , agent : "A" } ,
} ,
{
name : "set master legacy" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_agent_master_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "M" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
raw : tokens { agentRecovery : "M" , agentRecoverySource : tokenStore . TokenSourceAPI } ,
effective : tokens { agentRecovery : "M" } ,
2019-02-27 19:28:31 +00:00
} ,
{
2021-12-02 17:05:27 +00:00
name : "set master" ,
2019-02-27 19:28:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent_master" ,
2019-02-27 19:28:31 +00:00
body : body ( "M" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
raw : tokens { agentRecovery : "M" , agentRecoverySource : tokenStore . TokenSourceAPI } ,
effective : tokens { agentRecovery : "M" } ,
2019-02-27 19:28:31 +00:00
} ,
2021-12-02 17:05:27 +00:00
{
name : "set recovery" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent_recovery" ,
2021-12-02 17:05:27 +00:00
body : body ( "R" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
raw : tokens { agentRecovery : "R" , agentRecoverySource : tokenStore . TokenSourceAPI } ,
effective : tokens { agentRecovery : "R" , agentRecoverySource : tokenStore . TokenSourceAPI } ,
2021-12-02 17:05:27 +00:00
} ,
2019-02-27 19:28:31 +00:00
{
name : "set repl legacy" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_replication_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "R" ) ,
code : http . StatusOK ,
raw : tokens { repl : "R" , replSource : tokenStore . TokenSourceAPI } ,
effective : tokens { repl : "R" } ,
} ,
{
name : "set repl" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "replication" ,
2019-02-27 19:28:31 +00:00
body : body ( "R" ) ,
code : http . StatusOK ,
raw : tokens { repl : "R" , replSource : tokenStore . TokenSourceAPI } ,
effective : tokens { repl : "R" } ,
} ,
2023-01-10 16:24:02 +00:00
{
name : "set registration" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "config_file_service_registration" ,
2023-01-10 16:24:02 +00:00
body : body ( "G" ) ,
code : http . StatusOK ,
raw : tokens { registration : "G" , registrationSource : tokenStore . TokenSourceAPI } ,
effective : tokens { registration : "G" } ,
} ,
2019-02-27 19:28:31 +00:00
{
name : "clear user legacy" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "" ) ,
2017-08-03 22:39:31 +00:00
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { user : "U" } ,
raw : tokens { userSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "clear default" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "default" ,
2019-02-27 19:28:31 +00:00
body : body ( "" ) ,
2017-08-03 22:39:31 +00:00
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { user : "U" } ,
raw : tokens { userSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "clear agent legacy" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_agent_token" ,
2019-02-27 19:28:31 +00:00
body : body ( "" ) ,
2017-08-03 22:39:31 +00:00
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { agent : "A" } ,
raw : tokens { agentSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "clear agent" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent" ,
2019-02-27 19:28:31 +00:00
body : body ( "" ) ,
2017-08-03 22:39:31 +00:00
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { agent : "A" } ,
raw : tokens { agentSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "clear master legacy" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_agent_master_token" ,
2017-08-03 22:39:31 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
init : tokens { agentRecovery : "M" } ,
raw : tokens { agentRecoverySource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
2019-02-27 19:28:31 +00:00
name : "clear master" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent_master" ,
2017-08-03 22:39:31 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
init : tokens { agentRecovery : "M" } ,
raw : tokens { agentRecoverySource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
2021-12-02 17:05:27 +00:00
{
name : "clear recovery" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "agent_recovery" ,
2021-12-02 17:05:27 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
2022-01-20 12:47:50 +00:00
init : tokens { agentRecovery : "R" } ,
raw : tokens { agentRecoverySource : tokenStore . TokenSourceAPI } ,
2021-12-02 17:05:27 +00:00
} ,
2017-08-03 22:39:31 +00:00
{
2019-02-27 19:28:31 +00:00
name : "clear repl legacy" ,
2017-08-03 22:39:31 +00:00
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "acl_replication_token" ,
2017-08-03 22:39:31 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { repl : "R" } ,
raw : tokens { replSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
{
name : "clear repl" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "replication" ,
2017-08-03 22:39:31 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
2019-02-27 19:28:31 +00:00
init : tokens { repl : "R" } ,
raw : tokens { replSource : tokenStore . TokenSourceAPI } ,
2017-08-03 22:39:31 +00:00
} ,
2023-01-10 16:24:02 +00:00
{
name : "clear registration" ,
method : "PUT" ,
2023-01-24 16:21:41 +00:00
url : "config_file_service_registration" ,
2023-01-10 16:24:02 +00:00
body : body ( "" ) ,
code : http . StatusOK ,
init : tokens { registration : "G" } ,
raw : tokens { registrationSource : tokenStore . TokenSourceAPI } ,
} ,
2017-07-26 18:03:43 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2019-02-27 19:28:31 +00:00
resetTokens ( tt . init )
2017-07-26 18:03:43 +00:00
url := fmt . Sprintf ( "/v1/agent/token/%s" , tt . url )
resp := httptest . NewRecorder ( )
req , _ := http . NewRequest ( tt . method , url , tt . body )
2023-01-24 16:21:41 +00:00
req . Header . Add ( "X-Consul-Token" , "root" )
2020-08-17 23:30:25 +00:00
2021-11-03 15:12:36 +00:00
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , tt . code , resp . Code )
2021-10-26 19:20:57 +00:00
if tt . expectedErr != "" {
2021-11-03 15:12:36 +00:00
require . Contains ( t , resp . Body . String ( ) , tt . expectedErr )
2020-08-17 23:30:25 +00:00
return
}
2019-02-27 19:28:31 +00:00
require . Equal ( t , tt . effective . user , a . tokens . UserToken ( ) )
require . Equal ( t , tt . effective . agent , a . tokens . AgentToken ( ) )
2022-01-20 12:47:50 +00:00
require . Equal ( t , tt . effective . agentRecovery , a . tokens . AgentRecoveryToken ( ) )
2019-02-27 19:28:31 +00:00
require . Equal ( t , tt . effective . repl , a . tokens . ReplicationToken ( ) )
2023-01-10 16:24:02 +00:00
require . Equal ( t , tt . effective . registration , a . tokens . ConfigFileRegistrationToken ( ) )
2019-02-27 19:28:31 +00:00
tok , src := a . tokens . UserTokenAndSource ( )
require . Equal ( t , tt . raw . user , tok )
require . Equal ( t , tt . raw . userSource , src )
tok , src = a . tokens . AgentTokenAndSource ( )
require . Equal ( t , tt . raw . agent , tok )
require . Equal ( t , tt . raw . agentSource , src )
2021-12-07 12:12:47 +00:00
tok , src = a . tokens . AgentRecoveryTokenAndSource ( )
2022-01-20 12:47:50 +00:00
require . Equal ( t , tt . raw . agentRecovery , tok )
require . Equal ( t , tt . raw . agentRecoverySource , src )
2019-02-27 19:28:31 +00:00
tok , src = a . tokens . ReplicationTokenAndSource ( )
require . Equal ( t , tt . raw . repl , tok )
require . Equal ( t , tt . raw . replSource , src )
2023-01-10 16:24:02 +00:00
tok , src = a . tokens . ConfigFileRegistrationTokenAndSource ( )
require . Equal ( t , tt . raw . registration , tok )
require . Equal ( t , tt . raw . registrationSource , src )
2017-07-26 18:03:43 +00:00
} )
}
// This one returns an error that is interpreted by the HTTP wrapper, so
// doesn't fit into our table above.
t . Run ( "permission denied" , func ( t * testing . T ) {
2017-08-03 22:39:31 +00:00
resetTokens ( tokens { } )
req , _ := http . NewRequest ( "PUT" , "/v1/agent/token/acl_token" , body ( "X" ) )
2021-11-03 15:12:36 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusForbidden , resp . Code )
2019-02-27 19:28:31 +00:00
require . Equal ( t , "" , a . tokens . UserToken ( ) )
2017-07-26 18:03:43 +00:00
} )
}
2018-03-21 17:20:35 +00:00
func TestAgentConnectCARoots_empty ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-21 17:20:35 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "connect { enabled = false }" )
2018-03-21 17:20:35 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-21 17:20:35 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/roots" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusInternalServerError , resp . Code )
require . Contains ( t , resp . Body . String ( ) , "Connect must be enabled" )
2018-03-21 17:20:35 +00:00
}
func TestAgentConnectCARoots_list ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2022-09-14 00:21:04 +00:00
// Disable peering to avoid setting up a roots watch for the server certificate,
// which leads to cache hit on the first query below.
a := NewTestAgent ( t , "peering { enabled = false }" )
2018-03-21 17:20:35 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-21 17:20:35 +00:00
2018-04-30 21:23:49 +00:00
// Set some CAs. Note that NewTestAgent already bootstraps one CA so this just
// adds a second and makes it active.
ca2 := connect . TestCAConfigSet ( t , a , nil )
2018-03-21 17:20:35 +00:00
// List
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/roots" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
value := & structs . IndexedCARoots { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( value ) )
2018-03-21 17:20:35 +00:00
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , value . ActiveRootID , ca2 . ID )
2018-05-09 16:15:29 +00:00
// Would like to assert that it's the same as the TestAgent domain but the
// only way to access that state via this package is by RPC to the server
// implementation running in TestAgent which is more or less a tautology.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . NotEmpty ( t , value . TrustDomain )
assert . Len ( t , value . Roots , 2 )
2018-03-21 17:20:35 +00:00
// We should never have the secret information
for _ , r := range value . Roots {
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , "" , r . SigningCert )
assert . Equal ( t , "" , r . SigningKey )
2018-04-11 09:18:24 +00:00
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-04-11 09:18:24 +00:00
// Test caching
{
// List it again
2018-06-15 12:13:54 +00:00
resp2 := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp2 , req )
dec := json . NewDecoder ( resp2 . Body )
value2 := & structs . IndexedCARoots { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( value2 ) )
assert . Equal ( t , value , value2 )
2018-04-11 09:18:24 +00:00
// Should cache hit this time and not make request
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , "HIT" , resp2 . Header ( ) . Get ( "X-Cache" ) )
2018-04-11 09:18:24 +00:00
}
// Test that caching is updated in the background
{
2018-04-30 21:23:49 +00:00
// Set a new CA
ca := connect . TestCAConfigSet ( t , a , nil )
2018-04-11 09:18:24 +00:00
2018-04-22 21:00:32 +00:00
retry . Run ( t , func ( r * retry . R ) {
// List it again
2018-06-15 12:13:54 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-04-11 09:18:24 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
value := & structs . IndexedCARoots { }
2023-06-07 18:53:27 +00:00
require . NoError ( r , dec . Decode ( value ) )
2018-04-22 21:00:32 +00:00
if ca . ID != value . ActiveRootID {
r . Fatalf ( "%s != %s" , ca . ID , value . ActiveRootID )
}
2018-04-30 21:23:49 +00:00
// There are now 3 CAs because we didn't complete rotation on the original
// 2
if len ( value . Roots ) != 3 {
2018-04-22 21:00:32 +00:00
r . Fatalf ( "bad len: %d" , len ( value . Roots ) )
}
2018-04-11 09:18:24 +00:00
2018-06-15 12:13:54 +00:00
// Should be a cache hit! The data should've updated in the cache
// in the background so this should've been fetched directly from
// the cache.
if resp . Header ( ) . Get ( "X-Cache" ) != "HIT" {
r . Fatalf ( "should be a cache hit" )
}
} )
2018-03-21 17:20:35 +00:00
}
}
2018-03-21 17:55:39 +00:00
2018-05-07 04:46:22 +00:00
func TestAgentConnectCALeafCert_aclDefaultDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-05-07 04:46:22 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2018-05-07 04:46:22 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2020-01-30 03:23:11 +00:00
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
2018-05-07 04:46:22 +00:00
// Register a service with a managed proxy
{
reg := & structs . ServiceDefinition {
ID : "test-id" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
2019-08-09 19:19:30 +00:00
Connect : & structs . ServiceConnect { } ,
2018-05-07 04:46:22 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( reg ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
2018-05-07 04:46:22 +00:00
}
2018-05-19 06:27:02 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusForbidden , resp . Code )
2018-05-07 04:46:22 +00:00
}
2019-08-09 19:19:30 +00:00
func TestAgentConnectCALeafCert_aclServiceWrite ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-05-07 04:46:22 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2018-05-07 04:46:22 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2020-01-30 03:23:11 +00:00
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
2018-05-07 04:46:22 +00:00
// Register a service with a managed proxy
{
reg := & structs . ServiceDefinition {
ID : "test-id" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
2019-08-09 19:19:30 +00:00
Connect : & structs . ServiceConnect { } ,
2018-05-07 04:46:22 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( reg ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
2018-05-07 04:46:22 +00:00
}
2021-07-20 21:52:34 +00:00
token := createACLTokenWithServicePolicy ( t , a . srv , "write" )
2018-05-07 04:46:22 +00:00
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
req . Header . Add ( "X-Consul-Token" , token )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-05-07 04:46:22 +00:00
// Get the issued cert
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
value := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( value ) )
require . NotNil ( t , value )
2018-05-07 04:46:22 +00:00
}
2021-07-20 21:52:34 +00:00
func createACLTokenWithServicePolicy ( t * testing . T , srv * HTTPHandlers , policy string ) string {
policyReq := & structs . ACLPolicy {
Name : "service-test-write" ,
Rules : fmt . Sprintf ( ` service "test" { policy = "%v" } ` , policy ) ,
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/acl/policy" , jsonReader ( policyReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-07-20 21:52:34 +00:00
resp := httptest . NewRecorder ( )
_ , err := srv . ACLPolicyCreate ( resp , req )
require . NoError ( t , err )
tokenReq := & structs . ACLToken {
Description : "token-for-test" ,
Policies : [ ] structs . ACLTokenPolicyLink { { Name : "service-test-write" } } ,
}
2023-01-24 16:21:41 +00:00
req , _ = http . NewRequest ( "PUT" , "/v1/acl/token" , jsonReader ( tokenReq ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2021-07-20 21:52:34 +00:00
resp = httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
svcToken := & structs . ACLToken { }
require . NoError ( t , dec . Decode ( svcToken ) )
2021-07-20 21:52:34 +00:00
return svcToken . SecretID
}
2019-08-09 19:19:30 +00:00
func TestAgentConnectCALeafCert_aclServiceReadDeny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-05-07 04:46:22 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2018-05-07 04:46:22 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2020-01-30 03:23:11 +00:00
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
2018-05-07 04:46:22 +00:00
// Register a service with a managed proxy
{
reg := & structs . ServiceDefinition {
ID : "test-id" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
2019-08-09 19:19:30 +00:00
Connect : & structs . ServiceConnect { } ,
2018-05-07 04:46:22 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( reg ) )
req . Header . Add ( "X-Consul-Token" , "root" )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code , "body: %s" , resp . Body . String ( ) )
2018-05-07 04:46:22 +00:00
}
2021-07-20 21:52:34 +00:00
token := createACLTokenWithServicePolicy ( t , a . srv , "read" )
2018-05-07 04:46:22 +00:00
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
req . Header . Add ( "X-Consul-Token" , token )
2018-05-07 04:46:22 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusForbidden , resp . Code )
2018-05-07 04:46:22 +00:00
}
2018-03-21 17:55:39 +00:00
func TestAgentConnectCALeafCert_good ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2020-06-10 20:47:35 +00:00
a := StartTestAgent ( t , TestAgent { Overrides : `
connect {
test_ca_leaf_root_change_spread = "1ns"
}
` } )
2018-03-21 17:55:39 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2020-01-30 03:23:11 +00:00
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
2018-03-21 17:55:39 +00:00
2018-04-30 21:23:49 +00:00
// CA already setup by default by NewTestAgent but force a new one so we can
// verify it was signed easily.
ca1 := connect . TestCAConfigSet ( t , a , nil )
2018-03-21 17:55:39 +00:00
{
// Register a local service
args := & structs . ServiceDefinition {
ID : "foo" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
if ! assert . Equal ( t , 200 , resp . Code ) {
2018-03-21 17:55:39 +00:00
t . Log ( "Body: " , resp . Body . String ( ) )
}
}
// List
2018-05-19 06:27:02 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-06-13 19:43:34 +00:00
2018-05-19 06:27:02 +00:00
// Get the issued cert
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued ) )
2018-05-19 06:27:02 +00:00
// Verify that the cert is signed by the CA
requireLeafValidUnderCA ( t , issued , ca1 )
// Verify blocking index
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , issued . ModifyIndex > 0 )
assert . Equal ( t , fmt . Sprintf ( "%d" , issued . ModifyIndex ) ,
2018-05-19 06:27:02 +00:00
resp . Header ( ) . Get ( "X-Consul-Index" ) )
2020-07-20 20:09:20 +00:00
index := resp . Header ( ) . Get ( "X-Consul-Index" )
2018-05-19 06:27:02 +00:00
// Test caching
{
// Fetch it again
2018-06-15 12:13:54 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued2 ) )
require . Equal ( t , issued , issued2 )
2018-05-19 06:27:02 +00:00
}
2023-06-13 15:54:45 +00:00
replyCh := make ( chan * httptest . ResponseRecorder , 1 )
go func ( index string ) {
resp := httptest . NewRecorder ( )
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test?index=" + index , nil )
a . srv . h . ServeHTTP ( resp , req )
replyCh <- resp
} ( index )
2021-12-02 19:32:15 +00:00
// Set a new CA
ca2 := connect . TestCAConfigSet ( t , a , nil )
2020-07-20 20:09:20 +00:00
// Issue a blocking query to ensure that the cert gets updated appropriately
2022-08-09 14:36:47 +00:00
t . Run ( "test blocking queries update leaf cert" , func ( t * testing . T ) {
2023-06-13 15:54:45 +00:00
var resp * httptest . ResponseRecorder
select {
case resp = <- replyCh :
case <- time . After ( 500 * time . Millisecond ) :
t . Fatal ( "blocking query did not wake up during rotation" )
}
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued2 ) )
require . NotEqual ( t , issued . CertPEM , issued2 . CertPEM )
require . NotEqual ( t , issued . PrivateKeyPEM , issued2 . PrivateKeyPEM )
2018-05-19 06:27:02 +00:00
2020-07-20 20:09:20 +00:00
// Verify that the cert is signed by the new CA
2021-12-02 19:32:15 +00:00
requireLeafValidUnderCA ( t , issued2 , ca2 )
2018-05-19 06:27:02 +00:00
2020-07-20 20:09:20 +00:00
// Should not be a cache hit! The data was updated in response to the blocking
// query being made.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2022-08-09 14:36:47 +00:00
} )
2021-12-02 19:32:15 +00:00
t . Run ( "test non-blocking queries update leaf cert" , func ( t * testing . T ) {
resp := httptest . NewRecorder ( )
obj , err := a . srv . AgentConnectCALeafCert ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2021-12-02 19:32:15 +00:00
// Get the issued cert
issued , ok := obj . ( * structs . IssuedCert )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , ok )
2021-12-02 19:32:15 +00:00
// Verify that the cert is signed by the CA
requireLeafValidUnderCA ( t , issued , ca2 )
// Issue a non blocking query to ensure that the cert gets updated appropriately
{
// Set a new CA
ca3 := connect . TestCAConfigSet ( t , a , nil )
req , err := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2021-12-02 19:32:15 +00:00
2022-08-09 14:36:47 +00:00
retry . Run ( t , func ( r * retry . R ) {
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
2021-12-02 19:32:15 +00:00
2022-08-09 14:36:47 +00:00
// Should not be a cache hit!
require . Equal ( r , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2021-12-02 19:32:15 +00:00
2022-08-09 14:36:47 +00:00
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
require . NoError ( r , dec . Decode ( issued2 ) )
2021-12-02 19:32:15 +00:00
2022-08-09 14:36:47 +00:00
require . NotEqual ( r , issued . CertPEM , issued2 . CertPEM )
require . NotEqual ( r , issued . PrivateKeyPEM , issued2 . PrivateKeyPEM )
2021-12-02 19:32:15 +00:00
2022-08-09 14:36:47 +00:00
// Verify that the cert is signed by the new CA
requireLeafValidUnderCA ( r , issued2 , ca3 )
} )
2021-12-02 19:32:15 +00:00
}
} )
2018-05-07 04:02:44 +00:00
}
2019-08-09 19:19:30 +00:00
// Test we can request a leaf cert for a service we have permission for
// but is not local to this agent.
func TestAgentConnectCALeafCert_goodNotLocal ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-05-07 04:02:44 +00:00
t . Parallel ( )
2020-06-10 20:47:35 +00:00
a := StartTestAgent ( t , TestAgent { Overrides : `
connect {
test_ca_leaf_root_change_spread = "1ns"
}
` } )
2018-05-07 04:02:44 +00:00
defer a . Shutdown ( )
2019-08-09 19:19:30 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2020-01-30 03:23:11 +00:00
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
2019-08-09 19:19:30 +00:00
// CA already setup by default by NewTestAgent but force a new one so we can
// verify it was signed easily.
ca1 := connect . TestCAConfigSet ( t , a , nil )
2018-05-07 04:02:44 +00:00
{
2019-08-09 19:19:30 +00:00
// Register a non-local service (central catalog)
args := & structs . RegisterRequest {
Node : "foo" ,
2018-05-07 04:02:44 +00:00
Address : "127.0.0.1" ,
2019-08-09 19:19:30 +00:00
Service : & structs . NodeService {
Service : "test" ,
Address : "127.0.0.1" ,
Port : 8080 ,
2018-05-07 04:02:44 +00:00
} ,
}
2019-08-09 19:19:30 +00:00
req , _ := http . NewRequest ( "PUT" , "/v1/catalog/register" , jsonReader ( args ) )
2018-05-07 04:02:44 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
if ! assert . Equal ( t , 200 , resp . Code ) {
2019-08-09 19:19:30 +00:00
t . Log ( "Body: " , resp . Body . String ( ) )
2018-05-07 04:02:44 +00:00
}
}
2019-08-09 19:19:30 +00:00
// List
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
2018-05-07 04:02:44 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-05-07 04:02:44 +00:00
2019-08-09 19:19:30 +00:00
// Get the issued cert
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued ) )
2018-06-07 13:11:06 +00:00
2019-08-09 19:19:30 +00:00
// Verify that the cert is signed by the CA
requireLeafValidUnderCA ( t , issued , ca1 )
2018-04-26 13:01:20 +00:00
2019-08-09 19:19:30 +00:00
// Verify blocking index
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , issued . ModifyIndex > 0 )
assert . Equal ( t , fmt . Sprintf ( "%d" , issued . ModifyIndex ) ,
2019-08-09 19:19:30 +00:00
resp . Header ( ) . Get ( "X-Consul-Index" ) )
2018-05-03 17:44:10 +00:00
2019-08-09 19:19:30 +00:00
// Test caching
{
// Fetch it again
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued2 ) )
require . Equal ( t , issued , issued2 )
2018-04-26 13:01:20 +00:00
}
2019-08-09 19:19:30 +00:00
// Test Blocking - see https://github.com/hashicorp/consul/issues/4462
{
// Fetch it again
resp := httptest . NewRecorder ( )
blockingReq , _ := http . NewRequest ( "GET" , fmt . Sprintf ( "/v1/agent/connect/ca/leaf/test?wait=125ms&index=%d" , issued . ModifyIndex ) , nil )
doneCh := make ( chan struct { } )
go func ( ) {
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , blockingReq )
2019-08-09 19:19:30 +00:00
close ( doneCh )
} ( )
select {
case <- time . After ( 500 * time . Millisecond ) :
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . FailNow ( t , "Shouldn't block for this long - not respecting wait parameter in the query" )
2019-08-09 19:19:30 +00:00
case <- doneCh :
}
2018-04-26 13:01:20 +00:00
}
2019-08-09 19:19:30 +00:00
// Test that caching is updated in the background
{
// Set a new CA
ca := connect . TestCAConfigSet ( t , a , nil )
2018-04-26 13:01:20 +00:00
2019-08-09 19:19:30 +00:00
retry . Run ( t , func ( r * retry . R ) {
resp := httptest . NewRecorder ( )
// Try and sign again (note no index/wait arg since cache should update in
// background even if we aren't actively blocking)
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
2018-04-26 13:01:20 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
2023-06-07 18:53:27 +00:00
require . NoError ( r , dec . Decode ( issued2 ) )
2019-08-09 19:19:30 +00:00
if issued . CertPEM == issued2 . CertPEM {
r . Fatalf ( "leaf has not updated" )
2018-04-26 13:01:20 +00:00
}
2019-08-09 19:19:30 +00:00
// Got a new leaf. Sanity check it's a whole new key as well as different
// cert.
if issued . PrivateKeyPEM == issued2 . PrivateKeyPEM {
r . Fatalf ( "new leaf has same private key as before" )
2018-06-18 19:37:00 +00:00
}
2018-04-26 13:01:20 +00:00
2019-08-09 19:19:30 +00:00
// Verify that the cert is signed by the new CA
2023-06-07 18:53:27 +00:00
requireLeafValidUnderCA ( r , issued2 , ca )
2019-08-09 19:19:30 +00:00
2023-06-07 18:53:27 +00:00
require . NotEqual ( r , issued , issued2 )
2018-04-26 13:01:20 +00:00
} )
}
2018-04-18 20:05:30 +00:00
}
2022-04-20 17:21:47 +00:00
func TestAgentConnectCALeafCert_nonBlockingQuery_after_blockingQuery_shouldNotBlock ( t * testing . T ) {
// see: https://github.com/hashicorp/consul/issues/12048
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
a := NewTestAgent ( t , "" )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
{
// Register a local service
args := & structs . ServiceDefinition {
ID : "foo" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
req := httptest . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
if ! assert . Equal ( t , 200 , resp . Code ) {
t . Log ( "Body: " , resp . Body . String ( ) )
}
}
var (
serialNumber string
index string
issued structs . IssuedCert
)
2022-05-10 20:25:51 +00:00
testutil . RunStep ( t , "do initial non-blocking query" , func ( t * testing . T ) {
2022-04-20 17:21:47 +00:00
req := httptest . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
require . NoError ( t , dec . Decode ( & issued ) )
serialNumber = issued . SerialNumber
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) ,
"for the leaf cert cache type these are always MISS" )
index = resp . Header ( ) . Get ( "X-Consul-Index" )
} )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
go func ( ) {
// launch goroutine for blocking query
req := httptest . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test?index=" + index , nil ) . Clone ( ctx )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
} ( )
// We just need to ensure that the above blocking query is in-flight before
// the next step, so do a little sleep.
time . Sleep ( 50 * time . Millisecond )
// The initial non-blocking query populated the leaf cert cache entry
// implicitly. The agent cache doesn't prune entries very often at all, so
// in between both of these steps the data should still be there, causing
// this to be a HIT that completes in less than 10m (the default inner leaf
// cert blocking query timeout).
2022-05-10 20:25:51 +00:00
testutil . RunStep ( t , "do a non-blocking query that should not block" , func ( t * testing . T ) {
2022-04-20 17:21:47 +00:00
req := httptest . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
var issued2 structs . IssuedCert
dec := json . NewDecoder ( resp . Body )
require . NoError ( t , dec . Decode ( & issued2 ) )
require . Equal ( t , "HIT" , resp . Header ( ) . Get ( "X-Cache" ) )
// If this is actually returning a cached result, the serial number
// should be unchanged.
require . Equal ( t , serialNumber , issued2 . SerialNumber )
require . Equal ( t , issued , issued2 )
} )
}
2021-02-08 19:18:51 +00:00
func TestAgentConnectCALeafCert_Vault_doesNotChurnLeafCertsAtIdle ( t * testing . T ) {
ca . SkipIfVaultNotPresent ( t )
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
testVault := ca . NewTestVaultServer ( t )
2022-12-06 16:06:36 +00:00
vaultToken := ca . CreateVaultTokenWithAttrs ( t , testVault . Client ( ) , & ca . VaultTokenAttributes {
RootPath : "pki-root" ,
IntermediatePath : "pki-intermediate" ,
ConsulManaged : true ,
} )
2021-02-08 19:18:51 +00:00
a := StartTestAgent ( t , TestAgent { Overrides : fmt . Sprintf ( `
connect {
test_ca_leaf_root_change_spread = "1ns"
ca_provider = "vault"
ca_config {
address = % [ 1 ] q
token = % [ 2 ] q
root_pki_path = "pki-root/"
intermediate_pki_path = "pki-intermediate/"
}
}
2022-12-06 16:06:36 +00:00
` , testVault . Addr , vaultToken ) } )
2021-02-08 19:18:51 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
testrpc . WaitForActiveCARoot ( t , a . RPC , "dc1" , nil )
var ca1 * structs . CARoot
{
args := & structs . DCSpecificRequest { Datacenter : "dc1" }
var reply structs . IndexedCARoots
2022-12-14 15:24:22 +00:00
require . NoError ( t , a . RPC ( context . Background ( ) , "ConnectCA.Roots" , args , & reply ) )
2021-02-08 19:18:51 +00:00
for _ , r := range reply . Roots {
if r . ID == reply . ActiveRootID {
ca1 = r
break
}
}
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NotNil ( t , ca1 )
2021-02-08 19:18:51 +00:00
}
{
// Register a local service
args := & structs . ServiceDefinition {
ID : "foo" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
if ! assert . Equal ( t , 200 , resp . Code ) {
2021-02-08 19:18:51 +00:00
t . Log ( "Body: " , resp . Body . String ( ) )
}
}
// List
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2021-02-08 19:18:51 +00:00
// Get the issued cert
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued ) )
2021-02-08 19:18:51 +00:00
// Verify that the cert is signed by the CA
requireLeafValidUnderCA ( t , issued , ca1 )
// Verify blocking index
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , issued . ModifyIndex > 0 )
assert . Equal ( t , fmt . Sprintf ( "%d" , issued . ModifyIndex ) ,
2021-02-08 19:18:51 +00:00
resp . Header ( ) . Get ( "X-Consul-Index" ) )
// Test caching
{
// Fetch it again
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued2 ) )
require . Equal ( t , issued , issued2 )
2021-02-08 19:18:51 +00:00
}
// Test that we aren't churning leaves for no reason at idle.
{
ch := make ( chan error , 1 )
go func ( ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test?index=" + strconv . Itoa ( int ( issued . ModifyIndex ) ) , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
if resp . Code != http . StatusOK {
ch <- fmt . Errorf ( resp . Body . String ( ) )
return
}
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
if err := dec . Decode ( issued2 ) ; err != nil {
2021-02-08 19:18:51 +00:00
ch <- err
} else {
if issued . CertPEM == issued2 . CertPEM {
ch <- fmt . Errorf ( "leaf woke up unexpectedly with same cert" )
} else {
ch <- fmt . Errorf ( "leaf woke up unexpectedly with new cert" )
}
}
} ( )
start := time . Now ( )
select {
case <- time . After ( 5 * time . Second ) :
case err := <- ch :
dur := time . Since ( start )
t . Fatalf ( "unexpected return from blocking query; leaf churned during idle period, took %s: %v" , dur , err )
}
}
}
2019-09-26 16:54:14 +00:00
func TestAgentConnectCALeafCert_secondaryDC_good ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-26 16:54:14 +00:00
t . Parallel ( )
2020-03-31 20:24:39 +00:00
a1 := StartTestAgent ( t , TestAgent { Name : "dc1" , HCL : `
2019-09-26 16:54:14 +00:00
datacenter = "dc1"
primary_datacenter = "dc1"
2020-06-10 20:47:35 +00:00
` , Overrides: `
connect {
test_ca_leaf_root_change_spread = "1ns"
}
2020-03-31 20:12:33 +00:00
` } )
2019-09-26 16:54:14 +00:00
defer a1 . Shutdown ( )
testrpc . WaitForTestAgent ( t , a1 . RPC , "dc1" )
2020-03-31 20:24:39 +00:00
a2 := StartTestAgent ( t , TestAgent { Name : "dc2" , HCL : `
2019-09-26 16:54:14 +00:00
datacenter = "dc2"
primary_datacenter = "dc1"
2020-06-10 20:47:35 +00:00
` , Overrides: `
connect {
test_ca_leaf_root_change_spread = "1ns"
}
2020-03-31 20:12:33 +00:00
` } )
2019-09-26 16:54:14 +00:00
defer a2 . Shutdown ( )
testrpc . WaitForTestAgent ( t , a2 . RPC , "dc2" )
// Wait for the WAN join.
addr := fmt . Sprintf ( "127.0.0.1:%d" , a1 . Config . SerfPortWAN )
_ , err := a2 . JoinWAN ( [ ] string { addr } )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2019-09-26 16:54:14 +00:00
testrpc . WaitForLeader ( t , a1 . RPC , "dc1" )
testrpc . WaitForLeader ( t , a2 . RPC , "dc2" )
retry . Run ( t , func ( r * retry . R ) {
if got , want := len ( a1 . WANMembers ( ) ) , 2 ; got < want {
r . Fatalf ( "got %d WAN members want at least %d" , got , want )
}
} )
// CA already setup by default by NewTestAgent but force a new one so we can
// verify it was signed easily.
dc1_ca1 := connect . TestCAConfigSet ( t , a1 , nil )
// Wait until root is updated in both dcs.
waitForActiveCARoot ( t , a1 . srv , dc1_ca1 )
waitForActiveCARoot ( t , a2 . srv , dc1_ca1 )
{
// Register a local service in the SECONDARY
args := & structs . ServiceDefinition {
ID : "foo" ,
Name : "test" ,
Address : "127.0.0.1" ,
Port : 8000 ,
Check : structs . CheckType {
TTL : 15 * time . Second ,
} ,
}
req , _ := http . NewRequest ( "PUT" , "/v1/agent/service/register" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a2 . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
if ! assert . Equal ( t , 200 , resp . Code ) {
2019-09-26 16:54:14 +00:00
t . Log ( "Body: " , resp . Body . String ( ) )
}
}
// List
2021-12-02 19:32:15 +00:00
req , err := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test" , nil )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , err )
2019-09-26 16:54:14 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a2 . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusOK , resp . Code )
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2019-09-26 16:54:14 +00:00
// Get the issued cert
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued ) )
2019-09-26 16:54:14 +00:00
// Verify that the cert is signed by the CA
requireLeafValidUnderCA ( t , issued , dc1_ca1 )
// Verify blocking index
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . True ( t , issued . ModifyIndex > 0 )
assert . Equal ( t , fmt . Sprintf ( "%d" , issued . ModifyIndex ) ,
2019-09-26 16:54:14 +00:00
resp . Header ( ) . Get ( "X-Consul-Index" ) )
// Test caching
{
// Fetch it again
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a2 . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( issued2 ) )
require . Equal ( t , issued , issued2 )
2019-09-26 16:54:14 +00:00
}
// Test that we aren't churning leaves for no reason at idle.
{
ch := make ( chan error , 1 )
go func ( ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/leaf/test?index=" + strconv . Itoa ( int ( issued . ModifyIndex ) ) , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a2 . srv . h . ServeHTTP ( resp , req )
if resp . Code != http . StatusOK {
ch <- fmt . Errorf ( resp . Body . String ( ) )
return
}
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
if err := dec . Decode ( issued2 ) ; err != nil {
2019-09-26 16:54:14 +00:00
ch <- err
} else {
if issued . CertPEM == issued2 . CertPEM {
ch <- fmt . Errorf ( "leaf woke up unexpectedly with same cert" )
} else {
ch <- fmt . Errorf ( "leaf woke up unexpectedly with new cert" )
}
}
} ( )
start := time . Now ( )
// Before applying the fix from PR-6513 this would reliably wake up
// after ~20ms with a new cert. Since this test is necessarily a bit
// timing dependent we'll chill out for 5 seconds which should be enough
// time to disprove the original bug.
select {
case <- time . After ( 5 * time . Second ) :
case err := <- ch :
dur := time . Since ( start )
t . Fatalf ( "unexpected return from blocking query; leaf churned during idle period, took %s: %v" , dur , err )
}
}
// Set a new CA
dc1_ca2 := connect . TestCAConfigSet ( t , a2 , nil )
// Wait until root is updated in both dcs.
waitForActiveCARoot ( t , a1 . srv , dc1_ca2 )
waitForActiveCARoot ( t , a2 . srv , dc1_ca2 )
// Test that caching is updated in the background
retry . Run ( t , func ( r * retry . R ) {
resp := httptest . NewRecorder ( )
// Try and sign again (note no index/wait arg since cache should update in
// background even if we aren't actively blocking)
2021-12-07 14:44:03 +00:00
a2 . srv . h . ServeHTTP ( resp , req )
2023-06-07 18:53:27 +00:00
require . Equal ( r , http . StatusOK , resp . Code )
2019-09-26 16:54:14 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
issued2 := & structs . IssuedCert { }
2023-06-07 18:53:27 +00:00
require . NoError ( r , dec . Decode ( issued2 ) )
2019-09-26 16:54:14 +00:00
if issued . CertPEM == issued2 . CertPEM {
r . Fatalf ( "leaf has not updated" )
}
// Got a new leaf. Sanity check it's a whole new key as well as different
// cert.
if issued . PrivateKeyPEM == issued2 . PrivateKeyPEM {
r . Fatalf ( "new leaf has same private key as before" )
}
// Verify that the cert is signed by the new CA
2023-06-07 18:53:27 +00:00
requireLeafValidUnderCA ( r , issued2 , dc1_ca2 )
2019-09-26 16:54:14 +00:00
2023-06-07 18:53:27 +00:00
require . NotEqual ( r , issued , issued2 )
2019-09-26 16:54:14 +00:00
} )
}
2020-09-04 18:42:15 +00:00
func waitForActiveCARoot ( t * testing . T , srv * HTTPHandlers , expect * structs . CARoot ) {
2019-09-26 16:54:14 +00:00
retry . Run ( t , func ( r * retry . R ) {
req , _ := http . NewRequest ( "GET" , "/v1/agent/connect/ca/roots" , nil )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
srv . h . ServeHTTP ( resp , req )
if http . StatusOK != resp . Code {
2023-06-07 18:53:27 +00:00
r . Fatalf ( "expected 200 but got %v" , resp . Code )
2019-09-26 16:54:14 +00:00
}
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
roots := & structs . IndexedCARoots { }
2023-06-07 18:53:27 +00:00
require . NoError ( r , dec . Decode ( roots ) )
2019-09-26 16:54:14 +00:00
var root * structs . CARoot
for _ , r := range roots . Roots {
if r . ID == roots . ActiveRootID {
root = r
break
}
}
if root == nil {
r . Fatal ( "no active root" )
}
if root . ID != expect . ID {
r . Fatalf ( "current active root is %s; waiting for %s" , root . ID , expect . ID )
}
} )
}
2022-08-09 14:36:47 +00:00
func requireLeafValidUnderCA ( t require . TestingT , issued * structs . IssuedCert , ca * structs . CARoot ) {
2019-09-26 16:54:14 +00:00
leaf , intermediates , err := connect . ParseLeafCerts ( issued . CertPEM )
require . NoError ( t , err )
2019-08-09 19:19:30 +00:00
roots := x509 . NewCertPool ( )
require . True ( t , roots . AppendCertsFromPEM ( [ ] byte ( ca . RootCert ) ) )
2019-09-26 16:54:14 +00:00
2019-08-09 19:19:30 +00:00
_ , err = leaf . Verify ( x509 . VerifyOptions {
2019-09-26 16:54:14 +00:00
Roots : roots ,
Intermediates : intermediates ,
2019-08-09 19:19:30 +00:00
} )
require . NoError ( t , err )
// Verify the private key matches. tls.LoadX509Keypair does this for us!
_ , err = tls . X509KeyPair ( [ ] byte ( issued . CertPEM ) , [ ] byte ( issued . PrivateKeyPEM ) )
require . NoError ( t , err )
}
2018-03-26 00:52:26 +00:00
func TestAgentConnectAuthorize_badBody ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
args := [ ] string { }
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Contains ( t , resp . Body . String ( ) , "decode failed" )
2018-03-26 00:52:26 +00:00
}
func TestAgentConnectAuthorize_noTarget ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
args := & structs . ConnectAuthorizeRequest { }
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Contains ( t , resp . Body . String ( ) , "Target service must be specified" )
2018-03-26 00:52:26 +00:00
}
// Client ID is not in the valid URI format
func TestAgentConnectAuthorize_idInvalidFormat ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
args := & structs . ConnectAuthorizeRequest {
2018-03-28 21:29:35 +00:00
Target : "web" ,
ClientCertURI : "tubes" ,
2018-03-26 00:52:26 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Contains ( t , resp . Body . String ( ) , "ClientCertURI not a valid Connect identifier" )
2018-03-26 00:52:26 +00:00
}
// Client ID is a valid URI but its not a service URI
func TestAgentConnectAuthorize_idNotService ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
args := & structs . ConnectAuthorizeRequest {
2018-03-28 21:29:35 +00:00
Target : "web" ,
ClientCertURI : "spiffe://1234.consul" ,
2018-03-26 00:52:26 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Contains ( t , resp . Body . String ( ) , "ClientCertURI not a valid Service identifier" )
2018-03-26 00:52:26 +00:00
}
// Test when there is an intention allowing the connection
func TestAgentConnectAuthorize_allow ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
target := "db"
// Create some intentions
2018-04-17 23:26:58 +00:00
var ixnId string
2018-03-26 00:52:26 +00:00
{
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpCreate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "web"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionAllow
2022-12-14 15:24:22 +00:00
require . Nil ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & ixnId ) )
2018-03-26 00:52:26 +00:00
}
args := & structs . ConnectAuthorizeRequest {
2018-05-10 16:04:33 +00:00
Target : target ,
ClientCertURI : connect . TestSpiffeIDService ( t , "web" ) . URI ( ) . String ( ) ,
2018-03-26 00:52:26 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code )
require . Equal ( t , "MISS" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-03-26 00:52:26 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
require . True ( t , obj . Authorized )
require . Contains ( t , obj . Reason , "Matched" )
2018-04-17 23:26:58 +00:00
// Make the request again
{
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code )
2018-04-17 23:26:58 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
require . True ( t , obj . Authorized )
require . Contains ( t , obj . Reason , "Matched" )
2018-04-17 23:26:58 +00:00
2018-06-15 12:13:54 +00:00
// That should've been a cache hit.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "HIT" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-06-15 12:13:54 +00:00
}
2018-04-17 23:26:58 +00:00
// Change the intention
{
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpUpdate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . ID = ixnId
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "web"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionDeny
2022-12-14 15:24:22 +00:00
require . Nil ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & ixnId ) )
2018-04-17 23:26:58 +00:00
}
// Short sleep lets the cache background refresh happen
time . Sleep ( 100 * time . Millisecond )
// Make the request again
{
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , 200 , resp . Code )
2018-04-17 23:26:58 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
require . False ( t , obj . Authorized )
require . Contains ( t , obj . Reason , "Matched" )
2018-04-17 23:26:58 +00:00
2018-06-15 12:13:54 +00:00
// That should've been a cache hit, too, since it updated in the
// background.
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . Equal ( t , "HIT" , resp . Header ( ) . Get ( "X-Cache" ) )
2018-06-15 12:13:54 +00:00
}
2018-03-26 00:52:26 +00:00
}
// Test when there is an intention denying the connection
func TestAgentConnectAuthorize_deny ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 00:52:26 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-03-26 00:52:26 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-03-26 00:52:26 +00:00
target := "db"
// Create some intentions
{
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpCreate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "web"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionDeny
var reply string
2022-12-14 15:24:22 +00:00
assert . Nil ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & reply ) )
2018-03-26 00:52:26 +00:00
}
args := & structs . ConnectAuthorizeRequest {
2018-05-10 16:04:33 +00:00
Target : target ,
ClientCertURI : connect . TestSpiffeIDService ( t , "web" ) . URI ( ) . String ( ) ,
2018-03-26 00:52:26 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , 200 , resp . Code )
2018-03-26 00:52:26 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
require . NoError ( t , dec . Decode ( obj ) )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . False ( t , obj . Authorized )
assert . Contains ( t , obj . Reason , "Matched" )
2018-03-26 00:52:26 +00:00
}
2018-03-26 01:50:05 +00:00
2018-11-12 20:20:12 +00:00
// Test when there is an intention allowing service with a different trust
// domain. We allow this because migration between trust domains shouldn't cause
// an outage even if we have stale info about current trusted domains. It's safe
// because the CA root is either unique to this cluster and not used to sign
// anything external, or path validation can be used to ensure that the CA can
// only issue certs that are valid for the specific cluster trust domain at x509
// level which is enforced by TLS handshake.
func TestAgentConnectAuthorize_allowTrustDomain ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-05-09 19:30:43 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-05-09 19:30:43 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-05-09 19:30:43 +00:00
target := "db"
// Create some intentions
{
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpCreate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "web"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionAllow
var reply string
2022-12-14 15:24:22 +00:00
require . NoError ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & reply ) )
2018-05-09 19:30:43 +00:00
}
{
args := & structs . ConnectAuthorizeRequest {
2018-05-10 16:04:33 +00:00
Target : target ,
ClientCertURI : "spiffe://fake-domain.consul/ns/default/dc/dc1/svc/web" ,
2018-05-09 19:30:43 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , 200 , resp . Code )
2018-05-09 19:30:43 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
require . True ( t , obj . Authorized )
require . Contains ( t , obj . Reason , "Matched" )
2018-05-09 19:30:43 +00:00
}
}
2018-04-05 11:53:42 +00:00
func TestAgentConnectAuthorize_denyWildcard ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-04-05 11:53:42 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2018-04-05 11:53:42 +00:00
defer a . Shutdown ( )
2018-09-12 13:49:27 +00:00
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
2018-04-05 11:53:42 +00:00
target := "db"
// Create some intentions
{
// Deny wildcard to DB
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpCreate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "*"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionDeny
var reply string
2022-12-14 15:24:22 +00:00
require . NoError ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & reply ) )
2018-04-05 11:53:42 +00:00
}
{
// Allow web to DB
req := structs . IntentionRequest {
Datacenter : "dc1" ,
Op : structs . IntentionOpCreate ,
Intention : structs . TestIntention ( t ) ,
}
req . Intention . SourceNS = structs . IntentionDefaultNamespace
req . Intention . SourceName = "web"
req . Intention . DestinationNS = structs . IntentionDefaultNamespace
req . Intention . DestinationName = target
req . Intention . Action = structs . IntentionActionAllow
var reply string
2022-12-14 15:24:22 +00:00
assert . Nil ( t , a . RPC ( context . Background ( ) , "Intention.Apply" , & req , & reply ) )
2018-04-05 11:53:42 +00:00
}
// Web should be allowed
{
args := & structs . ConnectAuthorizeRequest {
2018-05-10 16:04:33 +00:00
Target : target ,
ClientCertURI : connect . TestSpiffeIDService ( t , "web" ) . URI ( ) . String ( ) ,
2018-04-05 11:53:42 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , 200 , resp . Code )
2018-04-05 11:53:42 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
assert . True ( t , obj . Authorized )
assert . Contains ( t , obj . Reason , "Matched" )
2018-04-05 11:53:42 +00:00
}
// API should be denied
{
args := & structs . ConnectAuthorizeRequest {
2018-05-10 16:04:33 +00:00
Target : target ,
ClientCertURI : connect . TestSpiffeIDService ( t , "api" ) . URI ( ) . String ( ) ,
2018-04-05 11:53:42 +00:00
}
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , 200 , resp . Code )
2018-04-05 11:53:42 +00:00
2021-12-07 14:44:03 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
require . NoError ( t , dec . Decode ( obj ) )
assert . False ( t , obj . Authorized )
assert . Contains ( t , obj . Reason , "Matched" )
2018-04-05 11:53:42 +00:00
}
}
2018-03-26 01:50:05 +00:00
// Test that authorize fails without service:write for the target service.
func TestAgentConnectAuthorize_serviceWrite ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 01:50:05 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , TestACLConfig ( ) )
2018-03-26 01:50:05 +00:00
defer a . Shutdown ( )
2018-08-06 23:46:09 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2018-03-26 01:50:05 +00:00
2021-07-20 21:52:34 +00:00
token := createACLTokenWithServicePolicy ( t , a . srv , "read" )
2018-03-26 01:50:05 +00:00
args := & structs . ConnectAuthorizeRequest {
2021-07-20 21:52:34 +00:00
Target : "test" ,
2018-03-28 21:29:35 +00:00
ClientCertURI : connect . TestSpiffeIDService ( t , "web" ) . URI ( ) . String ( ) ,
2018-03-26 01:50:05 +00:00
}
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , token )
2018-03-26 01:50:05 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
a . srv . h . ServeHTTP ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Equal ( t , http . StatusForbidden , resp . Code )
2018-03-26 01:50:05 +00:00
}
2024-02-08 20:25:42 +00:00
func TestAgentConnectAuthorize_DefaultIntentionPolicy ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-03-26 01:50:05 +00:00
t . Parallel ( )
2024-02-08 20:25:42 +00:00
agentConfig := ` primary_datacenter = "dc1"
default_intention_policy = "%s"
`
aclBlock := ` acl {
enabled = true
default_policy = "%s"
tokens {
initial_management = "root"
agent = "root"
agent_recovery = "towel"
}
}
`
type testcase struct {
aclsEnabled bool
defaultACL string
defaultIxn string
expectAuthz bool
expectReason string
}
tcs := map [ string ] testcase {
"no ACLs, default intention allow" : {
aclsEnabled : false ,
defaultIxn : "allow" ,
expectAuthz : true ,
expectReason : "Default intention policy" ,
} ,
"no ACLs, default intention deny" : {
aclsEnabled : false ,
defaultIxn : "deny" ,
expectAuthz : false ,
expectReason : "Default intention policy" ,
} ,
"ACL deny, no intention policy" : {
aclsEnabled : true ,
defaultACL : "deny" ,
expectAuthz : false ,
expectReason : "Default behavior configured by ACLs" ,
} ,
"ACL allow, no intention policy" : {
aclsEnabled : true ,
defaultACL : "allow" ,
expectAuthz : true ,
expectReason : "Default behavior configured by ACLs" ,
} ,
"ACL deny, default intentions allow" : {
aclsEnabled : true ,
defaultACL : "deny" ,
defaultIxn : "allow" ,
expectAuthz : true ,
expectReason : "Default intention policy" ,
} ,
"ACL allow, default intentions deny" : {
aclsEnabled : true ,
defaultACL : "allow" ,
defaultIxn : "deny" ,
expectAuthz : false ,
expectReason : "Default intention policy" ,
} ,
}
for name , tc := range tcs {
tc := tc
t . Run ( name , func ( t * testing . T ) {
t . Parallel ( )
2018-03-26 01:50:05 +00:00
2024-02-08 20:25:42 +00:00
conf := fmt . Sprintf ( agentConfig , tc . defaultIxn )
if tc . aclsEnabled {
conf += fmt . Sprintf ( aclBlock , tc . defaultACL )
}
a := NewTestAgent ( t , conf )
2022-01-20 12:47:50 +00:00
2024-02-08 20:25:42 +00:00
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2022-01-20 12:47:50 +00:00
2024-02-08 20:25:42 +00:00
args := & structs . ConnectAuthorizeRequest {
Target : "foo" ,
ClientCertURI : connect . TestSpiffeIDService ( t , "web" ) . URI ( ) . String ( ) ,
2022-01-20 12:47:50 +00:00
}
2024-02-08 20:25:42 +00:00
req , _ := http . NewRequest ( "POST" , "/v1/agent/connect/authorize" , jsonReader ( args ) )
req . Header . Add ( "X-Consul-Token" , "root" )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
assert . Equal ( t , 200 , resp . Code )
2018-03-26 01:50:05 +00:00
2024-02-08 20:25:42 +00:00
dec := json . NewDecoder ( resp . Body )
obj := & connectAuthorizeResp { }
require . NoError ( t , dec . Decode ( obj ) )
assert . Equal ( t , tc . expectAuthz , obj . Authorized )
assert . Contains ( t , obj . Reason , tc . expectReason )
} )
2018-03-26 01:50:05 +00:00
}
}
2018-06-13 08:34:20 +00:00
2018-10-17 20:20:35 +00:00
func TestAgent_Host ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-10-17 20:20:35 +00:00
t . Parallel ( )
dc1 := "dc1"
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2022-01-20 12:47:50 +00:00
primary_datacenter = "`+dc1+`"
acl {
enabled = true
default_policy = "allow"
tokens {
initial_management = "initial-management"
agent = "agent"
agent_recovery = "towel"
}
}
` )
2018-10-17 20:20:35 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/host" , nil )
req . Header . Add ( "X-Consul-Token" , "initial-management" )
2018-10-17 20:20:35 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
// TODO: AgentHost should write to response so that we can test using ServeHTTP()
2018-10-17 20:20:35 +00:00
respRaw , err := a . srv . AgentHost ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . Nil ( t , err )
assert . Equal ( t , http . StatusOK , resp . Code )
assert . NotNil ( t , respRaw )
2018-10-17 20:20:35 +00:00
obj := respRaw . ( * debug . HostInfo )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . NotNil ( t , obj . CollectionTime )
assert . Empty ( t , obj . Errors )
2018-10-17 20:20:35 +00:00
}
func TestAgent_HostBadACL ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2018-10-17 20:20:35 +00:00
t . Parallel ( )
dc1 := "dc1"
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , `
2022-01-20 12:47:50 +00:00
primary_datacenter = "`+dc1+`"
acl {
enabled = true
default_policy = "deny"
tokens {
initial_management = "root"
agent = "agent"
agent_recovery = "towel"
}
}
` )
2018-10-17 20:20:35 +00:00
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
2023-01-24 16:21:41 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/host" , nil )
req . Header . Add ( "X-Consul-Token" , "agent" )
2018-10-17 20:20:35 +00:00
resp := httptest . NewRecorder ( )
2021-12-07 14:44:03 +00:00
// TODO: AgentHost should write to response so that we can test using ServeHTTP()
_ , err := a . srv . AgentHost ( resp , req )
bulk rewrite using this script
set -euo pipefail
unset CDPATH
cd "$(dirname "$0")"
for f in $(git grep '\brequire := require\.New(' | cut -d':' -f1 | sort -u); do
echo "=== require: $f ==="
sed -i '/require := require.New(t)/d' $f
# require.XXX(blah) but not require.XXX(tblah) or require.XXX(rblah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\([^tr]\)/require.\1(t,\2/g' $f
# require.XXX(tblah) but not require.XXX(t, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/require.\1(t,\2/g' $f
# require.XXX(rblah) but not require.XXX(r, blah)
sed -i 's/\brequire\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/require.\1(t,\2/g' $f
gofmt -s -w $f
done
for f in $(git grep '\bassert := assert\.New(' | cut -d':' -f1 | sort -u); do
echo "=== assert: $f ==="
sed -i '/assert := assert.New(t)/d' $f
# assert.XXX(blah) but not assert.XXX(tblah) or assert.XXX(rblah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\([^tr]\)/assert.\1(t,\2/g' $f
# assert.XXX(tblah) but not assert.XXX(t, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(t[^,]\)/assert.\1(t,\2/g' $f
# assert.XXX(rblah) but not assert.XXX(r, blah)
sed -i 's/\bassert\.\([a-zA-Z0-9_]*\)(\(r[^,]\)/assert.\1(t,\2/g' $f
gofmt -s -w $f
done
2022-01-20 16:46:23 +00:00
assert . EqualError ( t , err , "ACL not found" )
assert . Equal ( t , http . StatusOK , resp . Code )
2018-10-17 20:20:35 +00:00
}
2019-09-26 02:55:52 +00:00
2023-05-30 22:25:48 +00:00
func TestAgent_Version ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
dc1 := "dc1"
a := NewTestAgent ( t , `
primary_datacenter = "`+dc1+`"
` )
defer a . Shutdown ( )
testrpc . WaitForLeader ( t , a . RPC , "dc1" )
req , _ := http . NewRequest ( "GET" , "/v1/agent/version" , nil )
// req.Header.Add("X-Consul-Token", "initial-management")
resp := httptest . NewRecorder ( )
respRaw , err := a . srv . AgentVersion ( resp , req )
assert . Nil ( t , err )
assert . Equal ( t , http . StatusOK , resp . Code )
assert . NotNil ( t , respRaw )
obj := respRaw . ( * version . BuildInfo )
assert . NotNil ( t , obj . HumanVersion )
}
2019-09-26 02:55:52 +00:00
// Thie tests that a proxy with an ExposeConfig is returned as expected.
func TestAgent_Services_ExposeConfig ( t * testing . T ) {
2020-12-07 18:42:55 +00:00
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
2019-09-26 02:55:52 +00:00
t . Parallel ( )
2020-03-31 19:59:56 +00:00
a := NewTestAgent ( t , "" )
2019-09-26 02:55:52 +00:00
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
srv1 := & structs . NodeService {
Kind : structs . ServiceKindConnectProxy ,
ID : "proxy-id" ,
Service : "proxy-name" ,
Port : 8443 ,
Proxy : structs . ConnectProxyConfig {
Expose : structs . ExposeConfig {
Checks : true ,
Paths : [ ] structs . ExposePath {
{
ListenerPort : 8080 ,
LocalPathPort : 21500 ,
Protocol : "http2" ,
Path : "/metrics" ,
} ,
} ,
} ,
} ,
}
2023-01-10 16:24:02 +00:00
a . State . AddServiceWithChecks ( srv1 , nil , "" , false )
2019-09-26 02:55:52 +00:00
req , _ := http . NewRequest ( "GET" , "/v1/agent/services" , nil )
2021-12-07 14:44:03 +00:00
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
require . Equal ( t , http . StatusOK , resp . Code )
dec := json . NewDecoder ( resp . Body )
val := make ( map [ string ] * api . AgentService )
require . NoError ( t , dec . Decode ( & val ) )
2019-09-26 02:55:52 +00:00
require . Len ( t , val , 1 )
actual := val [ "proxy-id" ]
require . NotNil ( t , actual )
require . Equal ( t , api . ServiceKindConnectProxy , actual . Kind )
2021-12-07 14:44:03 +00:00
// Proxy.ToAPI() creates an empty Upstream list instead of keeping nil so do the same with actual.
if actual . Proxy . Upstreams == nil {
actual . Proxy . Upstreams = make ( [ ] api . Upstream , 0 )
}
2019-09-26 02:55:52 +00:00
require . Equal ( t , srv1 . Proxy . ToAPI ( ) , actual . Proxy )
}
2023-09-07 23:47:31 +00:00
func TestAgent_Self_Reload ( t * testing . T ) {
if testing . Short ( ) {
t . Skip ( "too slow for testing.Short" )
}
t . Parallel ( )
// create new test agent
a := NewTestAgent ( t , `
log_level = "info"
raft_snapshot_threshold = 100
` )
defer a . Shutdown ( )
testrpc . WaitForTestAgent ( t , a . RPC , "dc1" )
req , _ := http . NewRequest ( "GET" , "/v1/agent/self" , nil )
resp := httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec := json . NewDecoder ( resp . Body )
val := & Self { }
require . NoError ( t , dec . Decode ( val ) )
require . Equal ( t , "info" , val . DebugConfig [ "Logging" ] . ( map [ string ] interface { } ) [ "LogLevel" ] )
require . Equal ( t , float64 ( 100 ) , val . DebugConfig [ "RaftSnapshotThreshold" ] . ( float64 ) )
// reload with new config
shim := & delegateConfigReloadShim { delegate : a . delegate }
a . delegate = shim
newCfg := TestConfig ( testutil . Logger ( t ) , config . FileSource {
Name : "Reload" ,
Format : "hcl" ,
Data : `
data_dir = "` + a.Config.DataDir + `"
log_level = "debug"
raft_snapshot_threshold = 200
` ,
} )
if err := a . reloadConfigInternal ( newCfg ) ; err != nil {
t . Fatalf ( "got error %v want nil" , err )
}
require . Equal ( t , 200 , shim . newCfg . RaftSnapshotThreshold )
// validate new config is reflected in API response
req , _ = http . NewRequest ( "GET" , "/v1/agent/self" , nil )
resp = httptest . NewRecorder ( )
a . srv . h . ServeHTTP ( resp , req )
dec = json . NewDecoder ( resp . Body )
val = & Self { }
require . NoError ( t , dec . Decode ( val ) )
require . Equal ( t , "debug" , val . DebugConfig [ "Logging" ] . ( map [ string ] interface { } ) [ "LogLevel" ] )
require . Equal ( t , float64 ( 200 ) , val . DebugConfig [ "RaftSnapshotThreshold" ] . ( float64 ) )
}