github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/Godeps/_workspace/src/google.golang.org/grpc/credentials/credentials.go (about) 1 /* 2 * 3 * Copyright 2014, Google Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following disclaimer 14 * in the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Google Inc. nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34 // Package credentials implements various credentials supported by gRPC library, 35 // which encapsulate all the state needed by a client to authenticate with a 36 // server and make various assertions, e.g., about the client's identity, role, 37 // or whether it is authorized to make a particular call. 38 package credentials 39 40 import ( 41 "crypto/tls" 42 "crypto/x509" 43 "fmt" 44 "io/ioutil" 45 "net" 46 "strings" 47 "time" 48 49 "github.com/coreos/rkt/Godeps/_workspace/src/golang.org/x/net/context" 50 ) 51 52 var ( 53 // alpnProtoStr are the specified application level protocols for gRPC. 54 alpnProtoStr = []string{"h2"} 55 ) 56 57 // Credentials defines the common interface all supported credentials must 58 // implement. 59 type Credentials interface { 60 // GetRequestMetadata gets the current request metadata, refreshing 61 // tokens if required. This should be called by the transport layer on 62 // each request, and the data should be populated in headers or other 63 // context. uri is the URI of the entry point for the request. When 64 // supported by the underlying implementation, ctx can be used for 65 // timeout and cancellation. 66 // TODO(zhaoq): Define the set of the qualified keys instead of leaving 67 // it as an arbitrary string. 68 GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) 69 // RequireTransportSecurity indicates whether the credentails requires 70 // transport security. 71 RequireTransportSecurity() bool 72 } 73 74 // ProtocolInfo provides information regarding the gRPC wire protocol version, 75 // security protocol, security protocol version in use, etc. 76 type ProtocolInfo struct { 77 // ProtocolVersion is the gRPC wire protocol version. 78 ProtocolVersion string 79 // SecurityProtocol is the security protocol in use. 80 SecurityProtocol string 81 // SecurityVersion is the security protocol version. 82 SecurityVersion string 83 } 84 85 // AuthInfo defines the common interface for the auth information the users are interested in. 86 type AuthInfo interface { 87 AuthType() string 88 } 89 90 type authInfoKey struct{} 91 92 // NewContext creates a new context with authInfo attached. 93 func NewContext(ctx context.Context, authInfo AuthInfo) context.Context { 94 return context.WithValue(ctx, authInfoKey{}, authInfo) 95 } 96 97 // FromContext returns the authInfo in ctx if it exists. 98 func FromContext(ctx context.Context) (authInfo AuthInfo, ok bool) { 99 authInfo, ok = ctx.Value(authInfoKey{}).(AuthInfo) 100 return 101 } 102 103 // TransportAuthenticator defines the common interface for all the live gRPC wire 104 // protocols and supported transport security protocols (e.g., TLS, SSL). 105 type TransportAuthenticator interface { 106 // ClientHandshake does the authentication handshake specified by the corresponding 107 // authentication protocol on rawConn for clients. It returns the authenticated 108 // connection and the corresponding auth information about the connection. 109 ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error) 110 // ServerHandshake does the authentication handshake for servers. It returns 111 // the authenticated connection and the corresponding auth information about 112 // the connection. 113 ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) 114 // Info provides the ProtocolInfo of this TransportAuthenticator. 115 Info() ProtocolInfo 116 Credentials 117 } 118 119 // TLSInfo contains the auth information for a TLS authenticated connection. 120 // It implements the AuthInfo interface. 121 type TLSInfo struct { 122 state tls.ConnectionState 123 } 124 125 func (t TLSInfo) AuthType() string { 126 return "tls" 127 } 128 129 // tlsCreds is the credentials required for authenticating a connection using TLS. 130 type tlsCreds struct { 131 // TLS configuration 132 config tls.Config 133 } 134 135 func (c tlsCreds) Info() ProtocolInfo { 136 return ProtocolInfo{ 137 SecurityProtocol: "tls", 138 SecurityVersion: "1.2", 139 } 140 } 141 142 // GetRequestMetadata returns nil, nil since TLS credentials does not have 143 // metadata. 144 func (c *tlsCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 145 return nil, nil 146 } 147 148 func (c *tlsCreds) RequireTransportSecurity() bool { 149 return true 150 } 151 152 type timeoutError struct{} 153 154 func (timeoutError) Error() string { return "credentials: Dial timed out" } 155 func (timeoutError) Timeout() bool { return true } 156 func (timeoutError) Temporary() bool { return true } 157 158 func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) { 159 // borrow some code from tls.DialWithDialer 160 var errChannel chan error 161 if timeout != 0 { 162 errChannel = make(chan error, 2) 163 time.AfterFunc(timeout, func() { 164 errChannel <- timeoutError{} 165 }) 166 } 167 if c.config.ServerName == "" { 168 colonPos := strings.LastIndex(addr, ":") 169 if colonPos == -1 { 170 colonPos = len(addr) 171 } 172 c.config.ServerName = addr[:colonPos] 173 } 174 conn := tls.Client(rawConn, &c.config) 175 if timeout == 0 { 176 err = conn.Handshake() 177 } else { 178 go func() { 179 errChannel <- conn.Handshake() 180 }() 181 err = <-errChannel 182 } 183 if err != nil { 184 rawConn.Close() 185 return nil, nil, err 186 } 187 // TODO(zhaoq): Omit the auth info for client now. It is more for 188 // information than anything else. 189 return conn, nil, nil 190 } 191 192 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { 193 conn := tls.Server(rawConn, &c.config) 194 if err := conn.Handshake(); err != nil { 195 rawConn.Close() 196 return nil, nil, err 197 } 198 return conn, TLSInfo{conn.ConnectionState()}, nil 199 } 200 201 // NewTLS uses c to construct a TransportAuthenticator based on TLS. 202 func NewTLS(c *tls.Config) TransportAuthenticator { 203 tc := &tlsCreds{*c} 204 tc.config.NextProtos = alpnProtoStr 205 return tc 206 } 207 208 // NewClientTLSFromCert constructs a TLS from the input certificate for client. 209 func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportAuthenticator { 210 return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}) 211 } 212 213 // NewClientTLSFromFile constructs a TLS from the input certificate file for client. 214 func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, error) { 215 b, err := ioutil.ReadFile(certFile) 216 if err != nil { 217 return nil, err 218 } 219 cp := x509.NewCertPool() 220 if !cp.AppendCertsFromPEM(b) { 221 return nil, fmt.Errorf("credentials: failed to append certificates") 222 } 223 return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}), nil 224 } 225 226 // NewServerTLSFromCert constructs a TLS from the input certificate for server. 227 func NewServerTLSFromCert(cert *tls.Certificate) TransportAuthenticator { 228 return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}}) 229 } 230 231 // NewServerTLSFromFile constructs a TLS from the input certificate file and key 232 // file for server. 233 func NewServerTLSFromFile(certFile, keyFile string) (TransportAuthenticator, error) { 234 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 235 if err != nil { 236 return nil, err 237 } 238 return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil 239 }