Merge pull request #10849 from hashicorp/dnephin/contrib-doc-xds-auth

xds: document how authorization works
This commit is contained in:
Daniel Nephin 2021-08-18 13:25:16 -04:00 committed by GitHub
commit 4a0ae4048d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 8 deletions

View file

@ -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 {

View file

@ -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) {

View file

@ -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

View file

@ -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