credentials.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. // Package credentials implements various credentials supported by gRPC library,
  19. // which encapsulate all the state needed by a client to authenticate with a
  20. // server and make various assertions, e.g., about the client's identity, role,
  21. // or whether it is authorized to make a particular call.
  22. package credentials // import "google.golang.org/grpc/credentials"
  23. import (
  24. "context"
  25. "errors"
  26. "fmt"
  27. "net"
  28. "github.com/golang/protobuf/proto"
  29. "google.golang.org/grpc/attributes"
  30. "google.golang.org/grpc/internal"
  31. )
  32. // PerRPCCredentials defines the common interface for the credentials which need to
  33. // attach security information to every RPC (e.g., oauth2).
  34. type PerRPCCredentials interface {
  35. // GetRequestMetadata gets the current request metadata, refreshing
  36. // tokens if required. This should be called by the transport layer on
  37. // each request, and the data should be populated in headers or other
  38. // context. If a status code is returned, it will be used as the status
  39. // for the RPC. uri is the URI of the entry point for the request.
  40. // When supported by the underlying implementation, ctx can be used for
  41. // timeout and cancellation. Additionally, RequestInfo data will be
  42. // available via ctx to this call.
  43. // TODO(zhaoq): Define the set of the qualified keys instead of leaving
  44. // it as an arbitrary string.
  45. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
  46. // RequireTransportSecurity indicates whether the credentials requires
  47. // transport security.
  48. RequireTransportSecurity() bool
  49. }
  50. // SecurityLevel defines the protection level on an established connection.
  51. //
  52. // This API is experimental.
  53. type SecurityLevel int
  54. const (
  55. // Invalid indicates an invalid security level.
  56. // The zero SecurityLevel value is invalid for backward compatibility.
  57. Invalid SecurityLevel = iota
  58. // NoSecurity indicates a connection is insecure.
  59. NoSecurity
  60. // IntegrityOnly indicates a connection only provides integrity protection.
  61. IntegrityOnly
  62. // PrivacyAndIntegrity indicates a connection provides both privacy and integrity protection.
  63. PrivacyAndIntegrity
  64. )
  65. // String returns SecurityLevel in a string format.
  66. func (s SecurityLevel) String() string {
  67. switch s {
  68. case NoSecurity:
  69. return "NoSecurity"
  70. case IntegrityOnly:
  71. return "IntegrityOnly"
  72. case PrivacyAndIntegrity:
  73. return "PrivacyAndIntegrity"
  74. }
  75. return fmt.Sprintf("invalid SecurityLevel: %v", int(s))
  76. }
  77. // CommonAuthInfo contains authenticated information common to AuthInfo implementations.
  78. // It should be embedded in a struct implementing AuthInfo to provide additional information
  79. // about the credentials.
  80. //
  81. // This API is experimental.
  82. type CommonAuthInfo struct {
  83. SecurityLevel SecurityLevel
  84. }
  85. // GetCommonAuthInfo returns the pointer to CommonAuthInfo struct.
  86. func (c *CommonAuthInfo) GetCommonAuthInfo() *CommonAuthInfo {
  87. return c
  88. }
  89. // ProtocolInfo provides information regarding the gRPC wire protocol version,
  90. // security protocol, security protocol version in use, server name, etc.
  91. type ProtocolInfo struct {
  92. // ProtocolVersion is the gRPC wire protocol version.
  93. ProtocolVersion string
  94. // SecurityProtocol is the security protocol in use.
  95. SecurityProtocol string
  96. // SecurityVersion is the security protocol version. It is a static version string from the
  97. // credentials, not a value that reflects per-connection protocol negotiation. To retrieve
  98. // details about the credentials used for a connection, use the Peer's AuthInfo field instead.
  99. //
  100. // Deprecated: please use Peer.AuthInfo.
  101. SecurityVersion string
  102. // ServerName is the user-configured server name.
  103. ServerName string
  104. }
  105. // AuthInfo defines the common interface for the auth information the users are interested in.
  106. // A struct that implements AuthInfo should embed CommonAuthInfo by including additional
  107. // information about the credentials in it.
  108. type AuthInfo interface {
  109. AuthType() string
  110. }
  111. // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
  112. // and the caller should not close rawConn.
  113. var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
  114. // TransportCredentials defines the common interface for all the live gRPC wire
  115. // protocols and supported transport security protocols (e.g., TLS, SSL).
  116. type TransportCredentials interface {
  117. // ClientHandshake does the authentication handshake specified by the
  118. // corresponding authentication protocol on rawConn for clients. It returns
  119. // the authenticated connection and the corresponding auth information
  120. // about the connection. The auth information should embed CommonAuthInfo
  121. // to return additional information about the credentials. Implementations
  122. // must use the provided context to implement timely cancellation. gRPC
  123. // will try to reconnect if the error returned is a temporary error
  124. // (io.EOF, context.DeadlineExceeded or err.Temporary() == true). If the
  125. // returned error is a wrapper error, implementations should make sure that
  126. // the error implements Temporary() to have the correct retry behaviors.
  127. // Additionally, ClientHandshakeInfo data will be available via the context
  128. // passed to this call.
  129. //
  130. // If the returned net.Conn is closed, it MUST close the net.Conn provided.
  131. ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
  132. // ServerHandshake does the authentication handshake for servers. It returns
  133. // the authenticated connection and the corresponding auth information about
  134. // the connection. The auth information should embed CommonAuthInfo to return additional information
  135. // about the credentials.
  136. //
  137. // If the returned net.Conn is closed, it MUST close the net.Conn provided.
  138. ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
  139. // Info provides the ProtocolInfo of this TransportCredentials.
  140. Info() ProtocolInfo
  141. // Clone makes a copy of this TransportCredentials.
  142. Clone() TransportCredentials
  143. // OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
  144. // gRPC internals also use it to override the virtual hosting name if it is set.
  145. // It must be called before dialing. Currently, this is only used by grpclb.
  146. OverrideServerName(string) error
  147. }
  148. // Bundle is a combination of TransportCredentials and PerRPCCredentials.
  149. //
  150. // It also contains a mode switching method, so it can be used as a combination
  151. // of different credential policies.
  152. //
  153. // Bundle cannot be used together with individual TransportCredentials.
  154. // PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
  155. //
  156. // This API is experimental.
  157. type Bundle interface {
  158. TransportCredentials() TransportCredentials
  159. PerRPCCredentials() PerRPCCredentials
  160. // NewWithMode should make a copy of Bundle, and switch mode. Modifying the
  161. // existing Bundle may cause races.
  162. //
  163. // NewWithMode returns nil if the requested mode is not supported.
  164. NewWithMode(mode string) (Bundle, error)
  165. }
  166. // RequestInfo contains request data attached to the context passed to GetRequestMetadata calls.
  167. //
  168. // This API is experimental.
  169. type RequestInfo struct {
  170. // The method passed to Invoke or NewStream for this RPC. (For proto methods, this has the format "/some.Service/Method")
  171. Method string
  172. // AuthInfo contains the information from a security handshake (TransportCredentials.ClientHandshake, TransportCredentials.ServerHandshake)
  173. AuthInfo AuthInfo
  174. }
  175. // requestInfoKey is a struct to be used as the key when attaching a RequestInfo to a context object.
  176. type requestInfoKey struct{}
  177. // RequestInfoFromContext extracts the RequestInfo from the context if it exists.
  178. //
  179. // This API is experimental.
  180. func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
  181. ri, ok = ctx.Value(requestInfoKey{}).(RequestInfo)
  182. return
  183. }
  184. // ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
  185. // it possible to pass arbitrary data to the handshaker from gRPC, resolver,
  186. // balancer etc. Individual credential implementations control the actual
  187. // format of the data that they are willing to receive.
  188. //
  189. // This API is experimental.
  190. type ClientHandshakeInfo struct {
  191. // Attributes contains the attributes for the address. It could be provided
  192. // by the gRPC, resolver, balancer etc.
  193. Attributes *attributes.Attributes
  194. }
  195. // clientHandshakeInfoKey is a struct used as the key to store
  196. // ClientHandshakeInfo in a context.
  197. type clientHandshakeInfoKey struct{}
  198. // ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
  199. // in ctx.
  200. //
  201. // This API is experimental.
  202. func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
  203. chi, _ := ctx.Value(clientHandshakeInfoKey{}).(ClientHandshakeInfo)
  204. return chi
  205. }
  206. // CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one.
  207. // It returns success if 1) the condition is satisified or 2) AuthInfo struct does not implement GetCommonAuthInfo() method
  208. // or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
  209. //
  210. // This API is experimental.
  211. func CheckSecurityLevel(ctx context.Context, level SecurityLevel) error {
  212. type internalInfo interface {
  213. GetCommonAuthInfo() *CommonAuthInfo
  214. }
  215. ri, _ := RequestInfoFromContext(ctx)
  216. if ri.AuthInfo == nil {
  217. return errors.New("unable to obtain SecurityLevel from context")
  218. }
  219. if ci, ok := ri.AuthInfo.(internalInfo); ok {
  220. // CommonAuthInfo.SecurityLevel has an invalid value.
  221. if ci.GetCommonAuthInfo().SecurityLevel == Invalid {
  222. return nil
  223. }
  224. if ci.GetCommonAuthInfo().SecurityLevel < level {
  225. return fmt.Errorf("requires SecurityLevel %v; connection has %v", level, ci.GetCommonAuthInfo().SecurityLevel)
  226. }
  227. }
  228. // The condition is satisfied or AuthInfo struct does not implement GetCommonAuthInfo() method.
  229. return nil
  230. }
  231. func init() {
  232. internal.NewRequestInfoContext = func(ctx context.Context, ri RequestInfo) context.Context {
  233. return context.WithValue(ctx, requestInfoKey{}, ri)
  234. }
  235. internal.NewClientHandshakeInfoContext = func(ctx context.Context, chi ClientHandshakeInfo) context.Context {
  236. return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
  237. }
  238. }
  239. // ChannelzSecurityInfo defines the interface that security protocols should implement
  240. // in order to provide security info to channelz.
  241. //
  242. // This API is experimental.
  243. type ChannelzSecurityInfo interface {
  244. GetSecurityValue() ChannelzSecurityValue
  245. }
  246. // ChannelzSecurityValue defines the interface that GetSecurityValue() return value
  247. // should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
  248. // and *OtherChannelzSecurityValue.
  249. //
  250. // This API is experimental.
  251. type ChannelzSecurityValue interface {
  252. isChannelzSecurityValue()
  253. }
  254. // OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
  255. // from GetSecurityValue(), which contains protocol specific security info. Note
  256. // the Value field will be sent to users of channelz requesting channel info, and
  257. // thus sensitive info should better be avoided.
  258. //
  259. // This API is experimental.
  260. type OtherChannelzSecurityValue struct {
  261. ChannelzSecurityValue
  262. Name string
  263. Value proto.Message
  264. }