-
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
Access to TLS client certificate #111
Comments
Don't know how well this aligns with your plans, but adding a |
I would suggest adding a read-only accessor (e.g., Conn()) to On Tue, Mar 10, 2015 at 1:24 PM, Tv notifications@github.com wrote:
|
Probably credentials.TransportAuthenticator.ConnectionState() returns a struct similar to http://golang.org/pkg/crypto/tls/#ConnectionState. |
I don't see I agree that exposing Perhaps the really modular way is something like If |
On Tue, Mar 10, 2015 at 4:20 PM, Tv notifications@github.com wrote:
|
I still don't see how you want the RPC method to actually access the If you're still talking about exposing If you're talking about passing I'm really keen to know if you have a plan for all this, e.g. based on some Google internal service or Java code, that's just slowly getting written in Go.. |
Hi Tv, I think there was a miscommunication in the beginning. To clarify, your On Tue, Mar 10, 2015 at 4:43 PM, Tv notifications@github.com wrote:
|
My use case is this: I'm porting a peer-to-peer communication protocol to gRPC. An ealier version did it by streaming protobufs both ways over a HTTP POST, with the URL path deciding which "method" to call. From that perspective, gRPC sounds pretty familiar, right? To me, gRPC seemed like a good way to avoid boilerplate or writing my own custom framework. I identify which peer I'm talking to by the client certificate (and respectively, the peer verifies the server identity with the server cert). The RPC methods naturally need to know which exact peer is calling them. |
And just to state this explicitly one more time, my current needs would be 100% covered with either of these:
Of these, 1. seems prettier to me. (I typoed option 1. earlier and left out the net.Conn, sorry about that; updated the comment above.) |
Example use of for {
c, err := l.Accept()
if err != nil { ... }
ctx := context.WithValue(context.Background(), myKey, metadata(c))
go srv.ServeConn(ctx, c)
} |
The default approach to this would be to be able to define a set of handlers execute before the actual RPC request that can modify the context to add whatever info we need. It would be nice to have a set of handlers for the connection and another for each stream. In the set of handlers that execute when a new connection is received we could do authentication and stuff like that.
Maybe the stream handlers can be defined in the service? |
@acasajus For 2., the authentication also needs to pass information to the RPC method, e.g. who the current user is. Making the function both take and return a |
@tv42 agreed 👍 |
This sounds pretty handy. |
For handlers per connection there's no service yet defined so somehow we'd need to add some info to the context so the handler can check if the authentication credentials are valid. |
Here's a concrete proposal. Let me know what you think:
Optionally, to make access control even easier, let the For example, I'm not 100% sure about the right arguments, your judgement is appreciated. That last part might also tie into how a Dapper-like tracing system would plugin -- perhaps there should be something to see the end of the request, too? |
Maybe that error in 5. above should be just
|
Thanks. Haven't got time reading through. will get back to you shortly. On Thu, Mar 19, 2015 at 6:16 PM, Tv notifications@github.com wrote:
|
This commit assumes a fork of gRPC with the changes described in grpc/grpc-go#111 (comment) Something like this should be enough to use the unofficial branch: go get -d google.golang.org/grpc cd "$(go list -f '{{.Dir}}' google.golang.org/grpc)" git checkout -b auth git pull https://github.com/bazillion/grpc-go auth go install
This commit assumes a fork of gRPC with the changes described in grpc/grpc-go#111 (comment) Something like this should be enough to use the unofficial branch: go get -d google.golang.org/grpc cd "$(go list -f '{{.Dir}}' google.golang.org/grpc)" git checkout -b auth git pull https://github.com/bazillion/grpc-go auth go install
Any update on this? |
Given the recent change, users can write a custom TransportAuthenticator to On Thu, May 14, 2015 at 7:52 AM, Peter Sanford notifications@github.com
|
There is still no easy way to get certificate info inside a handler. What do you think of @tv42's patch for this: bazil@3ff306a? |
FWIW the numbered branches are historical, the one without the number is latest: https://github.com/bazil/grpc-go/commits/auth |
This API is under design for the beta. I'll finalize the design ASAP once I On Tue, Jun 23, 2015 at 4:21 PM, Tv notifications@github.com wrote:
|
Awesome. Thanks for the update. |
working on it. Instead of giving the entire certificate, I would like to know which fields in tls.ConnectionState are needed typically? The plan is to return the required fields to server handler as part of metadata. Using entire certificate introduces a lot of problems because we do not know the exact type of the certificate. |
I'm glad to hear that you are working on it. Which fields of tls.ConnectionState should be passed through depends on the limitations you are willing to impose on the users of this library -- tls.ConnectionState is already a chosen subset of the connection parameters, selected to be presented to the application developers.
|
After talking to grpc c ppl, I am going to provide a minimal set of info which is consistent with what grpc c does right now in TLS transport authenticator. If it does not fit your requirements, it is trivial to provide your own custom authenticator impl to grpc. |
How would one provide a custom authenticator impl? |
A custom authenticator only solves the problem if it can pass information about the certificate on to the rpc endpoints. I don't know how you would do that with the current implementation. |
@psanford I will tune the authenticator API so that it can pass info about the cert in the coming PR. |
It seems like the information is still not available to the rpc endpoints. From my brief investigation, it looks like the code in |
You can add a print at On Tue, Aug 25, 2015 at 4:41 PM, Peter Sanford notifications@github.com
|
#304 changes the way on how to access client auth info. Now it is not part of normal metadata. Check https://github.com/grpc/grpc-go/blob/master/test/end2end_test.go#L116 as an example on how to access auth info in service handler. |
This looks great! Thanks for getting this merged. |
This still seems unusable for the TLS case. |
You still have to implement your own TransportAuthenticator to get access to the certificates. Its probably easiest to make a new struct type that embeds a TransportAuthenticator and just overrides the ServerHandshake method. |
That seems wrong. What is the point of EDIT: |
It should be exported (I made a mistake when I switched among multiple On Sun, Sep 6, 2015 at 9:49 AM, Tamir Duberstein notifications@github.com
|
So if I want access to the client certificate, what is the conclusion here? Do I have to write my own TransportAuthenticator and override the ServerHandshake method? If yes, is there an example? It would be very useful to have a simple example of how to access the client certificate. Thanks |
This is also something I require in my project -> after reading through this and some of the Credentials source code I've come up with the following. Would appreciate some feedback on whether this is the intended way to solve this problem or if there is something more elegant...
|
Currently, to access the connection state you have to assert that type of
AuthInfo object returned from handshake is TLSInfo and access the field
named State.
…On Fri, Jan 27, 2017 at 2:47 PM, John Cramb ***@***.***> wrote:
This is also something I require in my project -> after reading through
this and some of the Credentials source code I've come up with the
following. Would appreciate some feedback on whether this is the intended
way to solve this problem or if there is something more elegant...
` type custom struct {
creds credentials.TransportCredentials
}
func (c *custom) ClientHandshake(ctx context.Context, s string, conn
net.Conn) (net.Conn, credentials. AuthInfo, error) {
return c.creds.ClientHandshake(ctx, s, conn)
}
func (c *custom) ServerHandshake(conn net.Conn) (net.Conn,
credentials.AuthInfo, error) {
conn, authInfo, err := c.creds.ServerHandshake(conn)
tlsInfo := authInfo.(credentials.TLSInfo)
name := tlsInfo.State.PeerCertificates[0].Subject.CommonName
fmt.Printf("%v\n", name)
return conn, authInfo, err
}
func (c *custom) Info() credentials.ProtocolInfo {
return c.creds.Info()
}
func (c *custom) Clone() credentials.TransportCredentials {
return c.creds.Clone()
}
func (c *custom) OverrideServerName(s string) error {
return c.creds.OverrideServerName(s)
}`
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#111 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ATtnRw0pT9BiYCDW4Q1MZll8jnOzejveks5rWnQagaJpZM4DshP5>
.
|
@smithbk Actually for posterity, I've just discovered that the client certificate can also be accessed using the grpc Peer package to extract the Addr/AuthInfo for a client from within an RPC call.
|
@jcramb that works, although I was after the public key, so I did:
Unfortunately I've not figured out how to access the server public key from the client. |
Closes grpc#111, at least as far as I can tell, I'm not seeing other cases.
I can't see any way for an RPC method to authenticate a client based on a TLS certificate.
An example program where an RPC method echoes the client TLS certificate would be great.
The text was updated successfully, but these errors were encountered: