-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Conversation
@@ -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 |
There was a problem hiding this comment.
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/" |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
745ff04
to
6c58b32
Compare
There was a problem hiding this 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. |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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()} |
There was a problem hiding this comment.
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()} |
There was a problem hiding this comment.
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 | ||
} |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/serverConnState/serverAuthInfo
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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 {
...
}
Issue #934