Browse Source

xds: document how authorization works

pull/10849/head
Daniel Nephin 3 years ago
parent
commit
8252a2691c
  1. 2
      agent/xds/delta.go
  2. 17
      agent/xds/server.go
  3. 9
      contributing/service-mesh/README.md
  4. 25
      contributing/service-mesh/xds.md

2
agent/xds/delta.go

@ -138,7 +138,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove
}
checkStreamACLs := func(cfgSnap *proxycfg.ConfigSnapshot) error {
return s.checkStreamACLs(stream.Context(), cfgSnap)
return s.authorize(stream.Context(), cfgSnap)
}
for {

17
agent/xds/server.go

@ -327,7 +327,7 @@ func (s *Server) process(stream ADSStream, reqCh <-chan *envoy_discovery_v3.Disc
}
checkStreamACLs := func(cfgSnap *proxycfg.ConfigSnapshot) error {
return s.checkStreamACLs(stream.Context(), cfgSnap)
return s.authorize(stream.Context(), cfgSnap)
}
for {
@ -564,13 +564,22 @@ func NewGRPCServer(s *Server, tlsConfigurator *tlsutil.Configurator) *grpc.Serve
return srv
}
func (s *Server) checkStreamACLs(streamCtx context.Context, cfgSnap *proxycfg.ConfigSnapshot) error {
// authorize the xDS request using the token stored in ctx. This authorization is
// a bit different from most interfaces. Instead of explicitly authorizing or
// filtering each piece of data in the response, the request is authorized
// by checking the token has `service:write` for the service ID of the destination
// service (for kind=ConnectProxy), or the gateway service (for other kinds).
// This authorization strategy requires that agent/proxycfg only fetches data
// using a token with the same permissions, and that it stores the data by
// proxy ID. We assume that any data in the snapshot was already filtered,
// which allows this authorization to be a shallow authorization check
// for all the data in a ConfigSnapshot.
func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot) error {
if cfgSnap == nil {
return status.Errorf(codes.Unauthenticated, "unauthenticated: no config snapshot")
}
authz, err := s.ResolveToken(tokenFromContext(streamCtx))
authz, err := s.ResolveToken(tokenFromContext(ctx))
if acl.IsErrNotFound(err) {
return status.Errorf(codes.Unauthenticated, "unauthenticated: %v", err)
} else if acl.IsErrPermissionDenied(err) {

9
contributing/service-mesh/README.md

@ -1,12 +1,15 @@
# Service Mesh (Connect)
- call out: envoy/proxy is the data plane, Consul is the control plane
- agent/xds - gRPC service that implements
[xDS](https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol)
- [agent/proxycfg](https://github.com/hashicorp/consul/blob/master/agent/proxycfg/proxycfg.go)
- [xDS Server] - a gRPC service that implements [xDS] and handles requests from an [envoy proxy].
- [agent/proxycfg]
- CA Manager - certificate authority
- command/connect/envoy - bootstrapping and running envoy
- command/connect/proxy - built-in proxy that is dev-only and not supported
for production.
- `connect/` - "Native" service mesh
[xDS Server]: ./xds.md
[xDS]: https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol
[envoy proxy]: https://www.consul.io/docs/connect/proxies/envoy
[agent/proxycfg]: https://github.com/hashicorp/consul/blob/main/agent/proxycfg

25
contributing/service-mesh/xds.md

@ -0,0 +1,25 @@
# xDS Server
The xDS Server is a gRPC service that implements [xDS] and handles requests from
an [envoy proxy].
[xDS]: https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol
[envoy proxy]: https://www.consul.io/docs/connect/proxies/envoy
## Authorization
Requests to the xDS server are authorized based on an assumption of how
`proxycfg.ConfigSnapshot` are constructed. Most interfaces (HTTP, DNS, RPC)
authorize requests by authorizing the data in the response, or by filtering
out data that the requester is not authorized to view. The xDS server authorizes
requests by looking at the proxy ID in the request and ensuring the ACL token has
`service:write` access to either the destination service (for kind=ConnectProxy), or
the gateway service (for other kinds).
This authorization strategy requires that [agent/proxycfg] only fetches data using a
token with the same permissions, and that it only stores data by proxy ID. We assume
that any data in the snapshot was already filtered, which allows this authorization to
only perform a shallow check against the proxy ID.
[agent/proxycfg]: https://github.com/hashicorp/consul/blob/main/agent/proxycfg
Loading…
Cancel
Save