Fix a couple bugs regarding intentions with namespaces (#7169)
This commit is contained in:
parent
3f253080a2
commit
25568626f7
|
@ -0,0 +1,13 @@
|
|||
// +build !consulent
|
||||
|
||||
package connect
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// GetEnterpriseMeta will synthesize an EnterpriseMeta struct from the SpiffeIDService.
|
||||
// in OSS this just returns an empty (but never nil) struct pointer
|
||||
func (id *SpiffeIDService) GetEnterpriseMeta() *structs.EnterpriseMeta {
|
||||
return &structs.EnterpriseMeta{}
|
||||
}
|
|
@ -288,9 +288,6 @@ func parseIntentionMatchEntry(input string) (structs.IntentionMatchEntry, error)
|
|||
var result structs.IntentionMatchEntry
|
||||
result.Namespace = structs.IntentionDefaultNamespace
|
||||
|
||||
// TODO(mitchellh): when namespaces are introduced, set the default
|
||||
// namespace to be the namespace of the requestor.
|
||||
|
||||
// Get the index to the '/'. If it doesn't exist, we have just a name
|
||||
// so just set that and return.
|
||||
idx := strings.IndexByte(input, '/')
|
||||
|
|
|
@ -505,8 +505,9 @@ func (s *Server) Check(ctx context.Context, r *envoyauthz.CheckRequest) (*envoya
|
|||
|
||||
// Create an authz request
|
||||
req := &structs.ConnectAuthorizeRequest{
|
||||
Target: destID.Service,
|
||||
ClientCertURI: r.Attributes.Source.Principal,
|
||||
Target: destID.Service,
|
||||
EnterpriseMeta: *destID.GetEnterpriseMeta(),
|
||||
ClientCertURI: r.Attributes.Source.Principal,
|
||||
// TODO(banks): need Envoy to support sending cert serial/hash to enforce
|
||||
// revocation later.
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/flags"
|
||||
|
@ -135,6 +136,27 @@ func (c *cmd) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// parseIntentionTarget parses a target of the form <namespace>/<name> and returns
|
||||
// the two distinct parts. In some cases the namespace may be elided and this function
|
||||
// will return the empty string for the namespace then.
|
||||
func parseIntentionTarget(input string) (name string, namespace string, err error) {
|
||||
// Get the index to the '/'. If it doesn't exist, we have just a name
|
||||
// so just set that and return.
|
||||
idx := strings.IndexByte(input, '/')
|
||||
if idx == -1 {
|
||||
// let the agent do token based defaulting of the namespace
|
||||
return input, "", nil
|
||||
}
|
||||
|
||||
namespace = input[:idx]
|
||||
name = input[idx+1:]
|
||||
if strings.IndexByte(name, '/') != -1 {
|
||||
return "", "", fmt.Errorf("target can contain at most one '/'")
|
||||
}
|
||||
|
||||
return name, namespace, nil
|
||||
}
|
||||
|
||||
// ixnsFromArgs returns the set of intentions to create based on the arguments
|
||||
// given and the flags set. This will call ixnsFromFiles if the -file flag
|
||||
// was set.
|
||||
|
@ -149,9 +171,21 @@ func (c *cmd) ixnsFromArgs(args []string) ([]*api.Intention, error) {
|
|||
return nil, fmt.Errorf("Must specify two arguments: source and destination")
|
||||
}
|
||||
|
||||
srcName, srcNamespace, err := parseIntentionTarget(args[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid intention source: %v", err)
|
||||
}
|
||||
|
||||
dstName, dstNamespace, err := parseIntentionTarget(args[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid intention destination: %v", err)
|
||||
}
|
||||
|
||||
return []*api.Intention{&api.Intention{
|
||||
SourceName: args[0],
|
||||
DestinationName: args[1],
|
||||
SourceNS: srcNamespace,
|
||||
SourceName: srcName,
|
||||
DestinationNS: dstNamespace,
|
||||
DestinationName: dstName,
|
||||
SourceType: api.IntentionSourceConsul,
|
||||
Action: c.ixnAction(),
|
||||
Meta: c.flagMeta,
|
||||
|
|
|
@ -84,7 +84,7 @@ func (f *Finder) Find(src, dst string) (*api.Intention, error) {
|
|||
func StripDefaultNS(v string) string {
|
||||
if idx := strings.IndexByte(v, '/'); idx > 0 {
|
||||
if v[:idx] == api.IntentionDefaultNamespace {
|
||||
return v[:idx+1]
|
||||
return v[idx+1:]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -351,6 +351,27 @@ function assert_service_has_healthy_instances {
|
|||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
function check_intention {
|
||||
local SOURCE=$1
|
||||
local DESTINATION=$2
|
||||
|
||||
curl -s -f "localhost:8500/v1/connect/intentions/check?source=${SOURCE}&destination=${DESTINATION}" | jq ".Allowed"
|
||||
}
|
||||
|
||||
function assert_intention_allowed {
|
||||
local SOURCE=$1
|
||||
local DESTINATION=$2
|
||||
|
||||
[ "$(check_intention "${SOURCE}" "${DESTINATION}")" == "true" ]
|
||||
}
|
||||
|
||||
function assert_intention_denied {
|
||||
local SOURCE=$1
|
||||
local DESTINATION=$2
|
||||
|
||||
[ "$(check_intention "${SOURCE}" "${DESTINATION}")" == "false" ]
|
||||
}
|
||||
|
||||
function docker_consul {
|
||||
local DC=$1
|
||||
shift 1
|
||||
|
@ -506,6 +527,54 @@ function delete_config_entry {
|
|||
retry_default curl -sL -XDELETE "http://127.0.0.1:8500/v1/config/${KIND}/${NAME}"
|
||||
}
|
||||
|
||||
function list_intentions {
|
||||
curl -s -f "http://localhost:8500/v1/connect/intentions"
|
||||
}
|
||||
|
||||
function get_intention_target_name {
|
||||
awk -F / '{ if ( NF == 1 ) { print $0 } else { print $2 }}'
|
||||
}
|
||||
|
||||
function get_intention_target_namespace {
|
||||
awk -F / '{ if ( NF != 1 ) { print $1 } }'
|
||||
}
|
||||
|
||||
function get_intention_by_targets {
|
||||
local SOURCE=$1
|
||||
local DESTINATION=$2
|
||||
|
||||
local SOURCE_NS=$(get_intention_target_namespace <<< "${SOURCE}")
|
||||
local SOURCE_NAME=$(get_intention_target_name <<< "${SOURCE}")
|
||||
local DESTINATION_NS=$(get_intention_target_namespace <<< "${DESTINATION}")
|
||||
local DESTINATION_NAME=$(get_intention_target_name <<< "${DESTINATION}")
|
||||
|
||||
existing=$(list_intentions | jq ".[] | select(.SourceNS == \"$SOURCE_NS\" and .SourceName == \"$SOURCE_NAME\" and .DestinationNS == \"$DESTINATION_NS\" and .DestinationName == \"$DESTINATION_NAME\")")
|
||||
if test -z "$existing"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
echo "$existing"
|
||||
return 0
|
||||
}
|
||||
|
||||
function update_intention {
|
||||
local SOURCE=$1
|
||||
local DESTINATION=$2
|
||||
local ACTION=$3
|
||||
|
||||
intention=$(get_intention_by_targets "${SOURCE}" "${DESTINATION}")
|
||||
if test $? -ne 0
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
id=$(jq -r .ID <<< "${intention}")
|
||||
updated=$(jq ".Action = \"$ACTION\"" <<< "${intention}")
|
||||
|
||||
curl -s -X PUT "http://localhost:8500/v1/connect/intentions/${id}" -d "${updated}"
|
||||
return $?
|
||||
}
|
||||
|
||||
function wait_for_agent_service_register {
|
||||
local SERVICE_ID=$1
|
||||
local DC=${2:-primary}
|
||||
|
|
Loading…
Reference in New Issue