Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClientHandshake to return AuthInfo #956

Merged
merged 20 commits into from
Jan 9, 2017
Merged

Conversation

MakMukhi
Copy link
Contributor

Issue #934

@MakMukhi MakMukhi changed the title Mmukhi tlsinfo ClientHandshake to return AuthInfo Oct 28, 2016
@@ -167,7 +167,7 @@ func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net
}
// TODO(zhaoq): Omit the auth info for client now. It is more for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this TODO


func TestTLSClientHandshakeReturnsAuthInfo(t *testing.T) {
localPort := ":5050"
tlsDir := "../test/testdata/"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

define this as a file level const
const tlsDir := ...

func TestTLSClientHandshakeReturnsAuthInfo(t *testing.T) {
localPort := ":5050"
tlsDir := "../test/testdata/"
lis, err := net.Listen("tcp", localPort)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do listen() on localhost:0 and get the listening address from lis

}
serverAuthInfo = TLSInfo{serverConn.ConnectionState()}
}()
defer lis.Close()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to the place right after listen().
If something fails before this line, lis will not be closed().

tlsDir := "../test/testdata/"
lis, err := net.Listen("tcp", localPort)
if err != nil {
t.Fatalf("Failed to start local server. Listener error: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simplify the error message to be just
t.Fatalf("Failed to listen: %v", err)

defer func() {
done <- true
}()
serverRawConn, _ := lis.Accept()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check the error here?

case <-done:
// wait until server has populated the serverAuthInfo struct.
}
if authInfo.AuthType() != serverAuthInfo.AuthType() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLSInfo.AuthType always returns "tls".
How about comparing something inside ConnectionState instead? like Version?

t.Fatalf("Error on client while handshake. Error: %v", err)
}
select {
case <-done:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the select is not necessary, just <-done.

serverAuthInfo = TLSInfo{serverConn.ConnectionState()}
}()
defer lis.Close()
conn, err := net.Dial("tcp", localPort)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defer close this connection

}()
serverRawConn, err := lis.Accept()
if err != nil {
t.Fatalf("Server failed to accept connection: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use t.Errorf

serverConn := tls.Server(serverRawConn, serverTLS.(*tlsCreds).config)
serverErr := serverConn.Handshake()
if serverErr != nil {
t.Fatalf("Error on server while handshake. Error: %v", serverErr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Errorf

}()
conn, err := net.Dial("tcp", lis.Addr().String())
if err != nil {
t.Fatalf("Client failed to connect to local server. Error: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print lis.Addr().String() instead of "local server".

}

func TestTLSServerHandshakeReturnsAuthInfo(t *testing.T) {
lis, err := net.Listen("tcp", "localhost:0")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above comments apply to this test case too.

t.Fatalf("Error on client while handshake. Error: %v", err)
}
// wait until server has populated the serverAuthInfo struct.
<-done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err := <-done; err != nil {
  return
}

debug

debug
Copy link
Contributor

@iamqizhao iamqizhao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With those 2 wrappers I mentioned in the comments, the existing 2 tests are just slightly more than calling these 2 wrappers and you can easily add the 3rd test I just mentioned in our talk.

if err != nil {
t.Fatalf("Error on client while handshake. Error: %v", err)
}
// wait until server has populated the serverAuthInfo struct.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.... populated the server AuthInfo or failed.

t.Fatalf("Failed to create server TLS. Error: %v", err)
}
var serverAuthInfo TLSInfo
errChan := make(chan error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make(chan error, 1) so that this goroutine can finish even though the test fails at line 101.

return
}
if authInfo.(TLSInfo).State.Version != serverAuthInfo.State.Version {
t.Fatalf("c.ClientHandshake(_, %v, _) = %v, want %v.", lis.Addr().String(), authInfo, serverAuthInfo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%s for list.Addr().String()

if err != nil {
t.Fatalf("Failed to create server TLS. Error: %v", err)
}
var serverAuthInfo TLSInfo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use tls.ConnectionState directly?

if err != nil {
t.Fatalf("Error on client while handshake. Error: %v", err)
}
authInfo := TLSInfo{clientConn.ConnectionState()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use tls.ConnectionState directly?

t.Errorf("Error on server while handshake. Error: %v", sErr)
return
}
serverAuthInfo = TLSInfo{serverConn.ConnectionState()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The body can be written in a separate function like:

func serverHandle(hs func(net.Conn) (net.Conn, AuthInfo, error)) {
    ...
}

// wait until server has populated the serverAuthInfo struct.
if err = <-errChan; err != nil {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the above client side logic can be wrapped into a function too:

func clientHandle(hs func(context.Context, string, net.Conn) (net.Conn, AuthInfo, error))

func launchServer(t *testing.T, serverConnState *tls.ConnectionState, hs serverHandshake, errChan chan error) (string, error) {
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Errorf("Failed to listen: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can t.Fatalf directly so that this function only needs to return lis.Addr().String().

func clientHandle(t *testing.T, hs func(net.Conn, string) (tls.ConnectionState, error), lisAddr string) (tls.ConnectionState, error) {
conn, err := net.Dial("tcp", lisAddr)
if err != nil {
t.Errorf("Client failed to connect to %s. Error: %v", lisAddr, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use t.Fatalf and this function only returns tls.ConnectionState.

defer conn.Close()
clientConnState, err := hs(conn, lisAddr)
if err != nil {
t.Errorf("Error on client while handshake. Error: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Fatalf

return nil
}

// Client handshake implementation using gRPC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/using/in

return clientConnState, err
}

// Server handshake implementation using gRPC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/using/in

return authInfo.(TLSInfo).State, nil
}

// Server handshake implementation using tls.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the comment.

return nil
}

// Client handskae implementation using tls.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the comment.


func TestClientHandshakeReturnsAuthInfo(t *testing.T) {
var serverConnState tls.ConnectionState
errChan := make(chan error, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more like a channel to notify the completion of serverHandle. Can you rename it to "done"? Applies to all the tests you added.

return lis.Addr().String()
}

// Is run in a seperate go routine.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goroutine is one word.


func TestClientHandshakeReturnsAuthInfo(t *testing.T) {
var serverConnState tls.ConnectionState
done := make(chan error, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this a channel of authInfo. The way launchServer does (&serverConnState) is more like C/C++ way instead of Go idiom. In this way, serverHandshake does not need the second param.

lisAddr := launchServer(t, tlsServerHandshake, done)
clientConnState := clientHandle(t, gRPCClientHandshake, lisAddr)
// wait until server sends serverConnState or fails.
serverConnState := <-done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"done" should be closed if there is an error.

sAuthInfo, ok := <-done
if !ok {
    t.Fatalf(....)
}

lisAddr := launchServer(t, gRPCServerHandshake, done)
clientConnState := clientHandle(t, tlsClientHandshake, lisAddr)
// wait until server sends serverConnState or fails.
serverConnState := <-done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

lisAddr := launchServer(t, gRPCServerHandshake, done)
clientConnState := clientHandle(t, gRPCClientHandshake, lisAddr)
// wait until server sends serverConnState or fails.
serverConnState := <-done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

defer lis.Close()
var serverConnState tls.ConnectionState
defer func() {
done <- serverConnState
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done should be closed when there is an error (e.g., line 142 and 147).


const tlsDir = "../test/testdata/"

type serverHandshake func(net.Conn) (tls.ConnectionState, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we define it as security-protocol agnostic -- it should return AuthInfo instead of tls.ConnectionState?

type serverHandshake func(net.Conn) (tls.ConnectionState, error)

func TestClientHandshakeReturnsAuthInfo(t *testing.T) {
done := make(chan tls.ConnectionState, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto. should be chan AuthInfo?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this applies to the rest of the tests. Please fix.

func TestClientHandshakeReturnsAuthInfo(t *testing.T) {
done := make(chan AuthInfo, 1)
lisAddr := launchServer(t, tlsServerHandshake, done)
clientConnState := clientHandle(t, gRPCClientHandshake, lisAddr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/clientConnState/clientAuthInfo

lisAddr := launchServer(t, tlsServerHandshake, done)
clientConnState := clientHandle(t, gRPCClientHandshake, lisAddr)
// wait until server sends serverConnState or fails.
serverConnState, ok := <-done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/serverConnState/serverAuthInfo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applies to the other tests.

}
_, serverAuthInfo, err := serverTLS.ServerHandshake(conn)
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nil, err?

func gRPCServerHandshake(conn net.Conn) (AuthInfo, error) {
serverTLS, err := NewServerTLSFromFile(tlsDir+"server1.pem", tlsDir+"server1.key")
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nil, err?

clientTLS := NewTLS(&tls.Config{InsecureSkipVerify: true})
_, authInfo, err := clientTLS.ClientHandshake(context.Background(), lisAddr, conn)
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

func tlsServerHandshake(conn net.Conn) (AuthInfo, error) {
cert, err := tls.LoadX509KeyPair(tlsDir+"server1.pem", tlsDir+"server1.key")
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

serverConn := tls.Server(conn, serverTLSConfig)
err = serverConn.Handshake()
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

clientConn := tls.Client(conn, clientTLSConfig)
err := clientConn.Handshake()
if err != nil {
return TLSInfo{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

func tlsClientHandshake(conn net.Conn, _ string) (AuthInfo, error) {
clientTLSConfig := &tls.Config{InsecureSkipVerify: true}
clientConn := tls.Client(conn, clientTLSConfig)
err := clientConn.Handshake()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err := clientConn.Handshake(); err != nil {
  ...
}

@iamqizhao iamqizhao merged commit 4ed3489 into grpc:master Jan 9, 2017
@MakMukhi MakMukhi deleted the mmukhi_tlsinfo branch May 4, 2018 02:07
@lock lock bot locked as resolved and limited conversation to collaborators Oct 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants