credentials.go raw

   1  /*
   2   *
   3   * Copyright 2014 gRPC authors.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   *
  17   */
  18  
  19  // Package credentials implements various credentials supported by gRPC library,
  20  // which encapsulate all the state needed by a client to authenticate with a
  21  // server and make various assertions, e.g., about the client's identity, role,
  22  // or whether it is authorized to make a particular call.
  23  package credentials // import "google.golang.org/grpc/credentials"
  24  
  25  import (
  26  	"context"
  27  	"errors"
  28  	"fmt"
  29  	"net"
  30  
  31  	"google.golang.org/grpc/attributes"
  32  	icredentials "google.golang.org/grpc/internal/credentials"
  33  	"google.golang.org/protobuf/proto"
  34  )
  35  
  36  // PerRPCCredentials defines the common interface for the credentials which need to
  37  // attach security information to every RPC (e.g., oauth2).
  38  type PerRPCCredentials interface {
  39  	// GetRequestMetadata gets the current request metadata, refreshing tokens
  40  	// if required. This should be called by the transport layer on each
  41  	// request, and the data should be populated in headers or other
  42  	// context. If a status code is returned, it will be used as the status for
  43  	// the RPC (restricted to an allowable set of codes as defined by gRFC
  44  	// A54). uri is the URI of the entry point for the request.  When supported
  45  	// by the underlying implementation, ctx can be used for timeout and
  46  	// cancellation. Additionally, RequestInfo data will be available via ctx
  47  	// to this call.
  48  	GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
  49  	// RequireTransportSecurity indicates whether the credentials requires
  50  	// transport security.
  51  	RequireTransportSecurity() bool
  52  }
  53  
  54  // SecurityLevel defines the protection level on an established connection.
  55  //
  56  // This API is experimental.
  57  type SecurityLevel int
  58  
  59  const (
  60  	// InvalidSecurityLevel indicates an invalid security level.
  61  	// The zero SecurityLevel value is invalid for backward compatibility.
  62  	InvalidSecurityLevel SecurityLevel = iota
  63  	// NoSecurity indicates a connection is insecure.
  64  	NoSecurity
  65  	// IntegrityOnly indicates a connection only provides integrity protection.
  66  	IntegrityOnly
  67  	// PrivacyAndIntegrity indicates a connection provides both privacy and integrity protection.
  68  	PrivacyAndIntegrity
  69  )
  70  
  71  // String returns SecurityLevel in a string format.
  72  func (s SecurityLevel) String() string {
  73  	switch s {
  74  	case NoSecurity:
  75  		return "NoSecurity"
  76  	case IntegrityOnly:
  77  		return "IntegrityOnly"
  78  	case PrivacyAndIntegrity:
  79  		return "PrivacyAndIntegrity"
  80  	}
  81  	return fmt.Sprintf("invalid SecurityLevel: %v", int(s))
  82  }
  83  
  84  // CommonAuthInfo contains authenticated information common to AuthInfo implementations.
  85  // It should be embedded in a struct implementing AuthInfo to provide additional information
  86  // about the credentials.
  87  //
  88  // This API is experimental.
  89  type CommonAuthInfo struct {
  90  	SecurityLevel SecurityLevel
  91  }
  92  
  93  // GetCommonAuthInfo returns the pointer to CommonAuthInfo struct.
  94  func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
  95  	return c
  96  }
  97  
  98  // ProtocolInfo provides static information regarding transport credentials.
  99  type ProtocolInfo struct {
 100  	// ProtocolVersion is the gRPC wire protocol version.
 101  	//
 102  	// Deprecated: this is unused by gRPC.
 103  	ProtocolVersion string
 104  	// SecurityProtocol is the security protocol in use.
 105  	SecurityProtocol string
 106  	// SecurityVersion is the security protocol version.  It is a static version string from the
 107  	// credentials, not a value that reflects per-connection protocol negotiation.  To retrieve
 108  	// details about the credentials used for a connection, use the Peer's AuthInfo field instead.
 109  	//
 110  	// Deprecated: please use Peer.AuthInfo.
 111  	SecurityVersion string
 112  	// ServerName is the user-configured server name.  If set, this overrides
 113  	// the default :authority header used for all RPCs on the channel using the
 114  	// containing credentials, unless grpc.WithAuthority is set on the channel,
 115  	// in which case that setting will take precedence.
 116  	//
 117  	// This must be a valid `:authority` header according to
 118  	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
 119  	//
 120  	// Deprecated: Users should use grpc.WithAuthority to override the authority
 121  	// on a channel instead of configuring the credentials.
 122  	ServerName string
 123  }
 124  
 125  // AuthInfo defines the common interface for the auth information the users are interested in.
 126  // A struct that implements AuthInfo should embed CommonAuthInfo by including additional
 127  // information about the credentials in it.
 128  type AuthInfo interface {
 129  	AuthType() string
 130  }
 131  
 132  // AuthorityValidator validates the authority used to override the `:authority`
 133  // header. This is an optional interface that implementations of AuthInfo can
 134  // implement if they support per-RPC authority overrides. It is invoked when the
 135  // application attempts to override the HTTP/2 `:authority` header using the
 136  // CallAuthority call option.
 137  type AuthorityValidator interface {
 138  	// ValidateAuthority checks the authority value used to override the
 139  	// `:authority` header. The authority parameter is the override value
 140  	// provided by the application via the CallAuthority option. This value
 141  	// typically corresponds to the server hostname or endpoint the RPC is
 142  	// targeting. It returns non-nil error if the validation fails.
 143  	ValidateAuthority(authority string) error
 144  }
 145  
 146  // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
 147  // and the caller should not close rawConn.
 148  var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
 149  
 150  // TransportCredentials defines the common interface for all the live gRPC wire
 151  // protocols and supported transport security protocols (e.g., TLS, SSL).
 152  type TransportCredentials interface {
 153  	// ClientHandshake does the authentication handshake specified by the
 154  	// corresponding authentication protocol on rawConn for clients. It returns
 155  	// the authenticated connection and the corresponding auth information
 156  	// about the connection.  The auth information should embed CommonAuthInfo
 157  	// to return additional information about the credentials. Implementations
 158  	// must use the provided context to implement timely cancellation.  gRPC
 159  	// will try to reconnect if the error returned is a temporary error
 160  	// (io.EOF, context.DeadlineExceeded or err.Temporary() == true).  If the
 161  	// returned error is a wrapper error, implementations should make sure that
 162  	// the error implements Temporary() to have the correct retry behaviors.
 163  	// Additionally, ClientHandshakeInfo data will be available via the context
 164  	// passed to this call.
 165  	//
 166  	// The second argument to this method is the `:authority` header value used
 167  	// while creating new streams on this connection after authentication
 168  	// succeeds. Implementations must use this as the server name during the
 169  	// authentication handshake.
 170  	//
 171  	// If the returned net.Conn is closed, it MUST close the net.Conn provided.
 172  	ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
 173  	// ServerHandshake does the authentication handshake for servers. It returns
 174  	// the authenticated connection and the corresponding auth information about
 175  	// the connection. The auth information should embed CommonAuthInfo to return additional information
 176  	// about the credentials.
 177  	//
 178  	// If the returned net.Conn is closed, it MUST close the net.Conn provided.
 179  	ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
 180  	// Info provides the ProtocolInfo of this TransportCredentials.
 181  	Info() ProtocolInfo
 182  	// Clone makes a copy of this TransportCredentials.
 183  	Clone() TransportCredentials
 184  	// OverrideServerName specifies the value used for the following:
 185  	//
 186  	// - verifying the hostname on the returned certificates
 187  	// - as SNI in the client's handshake to support virtual hosting
 188  	// - as the value for `:authority` header at stream creation time
 189  	//
 190  	// The provided string should be a valid `:authority` header according to
 191  	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
 192  	//
 193  	// Deprecated: this method is unused by gRPC.  Users should use
 194  	// grpc.WithAuthority to override the authority on a channel instead of
 195  	// configuring the credentials.
 196  	OverrideServerName(string) error
 197  }
 198  
 199  // Bundle is a combination of TransportCredentials and PerRPCCredentials.
 200  //
 201  // It also contains a mode switching method, so it can be used as a combination
 202  // of different credential policies.
 203  //
 204  // Bundle cannot be used together with individual TransportCredentials.
 205  // PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
 206  //
 207  // This API is experimental.
 208  type Bundle interface {
 209  	// TransportCredentials returns the transport credentials from the Bundle.
 210  	//
 211  	// Implementations must return non-nil transport credentials. If transport
 212  	// security is not needed by the Bundle, implementations may choose to
 213  	// return insecure.NewCredentials().
 214  	TransportCredentials() TransportCredentials
 215  
 216  	// PerRPCCredentials returns the per-RPC credentials from the Bundle.
 217  	//
 218  	// May be nil if per-RPC credentials are not needed.
 219  	PerRPCCredentials() PerRPCCredentials
 220  
 221  	// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
 222  	// existing Bundle may cause races.
 223  	//
 224  	// NewWithMode returns nil if the requested mode is not supported.
 225  	NewWithMode(mode string) (Bundle, error)
 226  }
 227  
 228  // RequestInfo contains request data attached to the context passed to GetRequestMetadata calls.
 229  //
 230  // This API is experimental.
 231  type RequestInfo struct {
 232  	// The method passed to Invoke or NewStream for this RPC. (For proto methods, this has the format "/some.Service/Method")
 233  	Method string
 234  	// AuthInfo contains the information from a security handshake (TransportCredentials.ClientHandshake, TransportCredentials.ServerHandshake)
 235  	AuthInfo AuthInfo
 236  }
 237  
 238  // requestInfoKey is a struct to be used as the key to store RequestInfo in a
 239  // context.
 240  type requestInfoKey struct{}
 241  
 242  // RequestInfoFromContext extracts the RequestInfo from the context if it exists.
 243  //
 244  // This API is experimental.
 245  func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
 246  	ri, ok = ctx.Value(requestInfoKey{}).(RequestInfo)
 247  	return ri, ok
 248  }
 249  
 250  // NewContextWithRequestInfo creates a new context from ctx and attaches ri to it.
 251  //
 252  // This RequestInfo will be accessible via RequestInfoFromContext.
 253  //
 254  // Intended to be used from tests for PerRPCCredentials implementations (that
 255  // often need to check connection's SecurityLevel). Should not be used from
 256  // non-test code: the gRPC client already prepares a context with the correct
 257  // RequestInfo attached when calling PerRPCCredentials.GetRequestMetadata.
 258  //
 259  // This API is experimental.
 260  func NewContextWithRequestInfo(ctx context.Context, ri RequestInfo) context.Context {
 261  	return context.WithValue(ctx, requestInfoKey{}, ri)
 262  }
 263  
 264  // ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
 265  // it possible to pass arbitrary data to the handshaker from gRPC, resolver,
 266  // balancer etc. Individual credential implementations control the actual
 267  // format of the data that they are willing to receive.
 268  //
 269  // This API is experimental.
 270  type ClientHandshakeInfo struct {
 271  	// Attributes contains the attributes for the address. It could be provided
 272  	// by the gRPC, resolver, balancer etc.
 273  	Attributes *attributes.Attributes
 274  }
 275  
 276  // ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
 277  // in ctx.
 278  //
 279  // This API is experimental.
 280  func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
 281  	chi, _ := icredentials.ClientHandshakeInfoFromContext(ctx).(ClientHandshakeInfo)
 282  	return chi
 283  }
 284  
 285  // CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one.
 286  // It returns success if 1) the condition is satisfied or 2) AuthInfo struct does not implement GetCommonAuthInfo() method
 287  // or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
 288  //
 289  // This API is experimental.
 290  func CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {
 291  	type internalInfo interface {
 292  		GetCommonAuthInfo() CommonAuthInfo
 293  	}
 294  	if ai == nil {
 295  		return errors.New("AuthInfo is nil")
 296  	}
 297  	if ci, ok := ai.(internalInfo); ok {
 298  		// CommonAuthInfo.SecurityLevel has an invalid value.
 299  		if ci.GetCommonAuthInfo().SecurityLevel == InvalidSecurityLevel {
 300  			return nil
 301  		}
 302  		if ci.GetCommonAuthInfo().SecurityLevel < level {
 303  			return fmt.Errorf("requires SecurityLevel %v; connection has %v", level, ci.GetCommonAuthInfo().SecurityLevel)
 304  		}
 305  	}
 306  	// The condition is satisfied or AuthInfo struct does not implement GetCommonAuthInfo() method.
 307  	return nil
 308  }
 309  
 310  // ChannelzSecurityInfo defines the interface that security protocols should implement
 311  // in order to provide security info to channelz.
 312  //
 313  // This API is experimental.
 314  type ChannelzSecurityInfo interface {
 315  	GetSecurityValue() ChannelzSecurityValue
 316  }
 317  
 318  // ChannelzSecurityValue defines the interface that GetSecurityValue() return value
 319  // should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
 320  // and *OtherChannelzSecurityValue.
 321  //
 322  // This API is experimental.
 323  type ChannelzSecurityValue interface {
 324  	isChannelzSecurityValue()
 325  }
 326  
 327  // OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
 328  // from GetSecurityValue(), which contains protocol specific security info. Note
 329  // the Value field will be sent to users of channelz requesting channel info, and
 330  // thus sensitive info should better be avoided.
 331  //
 332  // This API is experimental.
 333  type OtherChannelzSecurityValue struct {
 334  	ChannelzSecurityValue
 335  	Name  string
 336  	Value proto.Message
 337  }
 338