OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package client | 5 package client |
6 | 6 |
7 import ( | 7 import ( |
8 "crypto/x509" | 8 "crypto/x509" |
9 "fmt" | 9 "fmt" |
10 | 10 |
11 "github.com/golang/protobuf/proto" | 11 "github.com/golang/protobuf/proto" |
12 "golang.org/x/net/context" | 12 "golang.org/x/net/context" |
13 "google.golang.org/grpc" | 13 "google.golang.org/grpc" |
14 "google.golang.org/grpc/codes" | 14 "google.golang.org/grpc/codes" |
15 | 15 |
16 "github.com/luci/luci-go/common/clock" | 16 "github.com/luci/luci-go/common/clock" |
17 "github.com/luci/luci-go/common/errors" | |
18 "github.com/luci/luci-go/common/proto/google" | 17 "github.com/luci/luci-go/common/proto/google" |
| 18 "github.com/luci/luci-go/common/retry/transient" |
19 "github.com/luci/luci-go/grpc/grpcutil" | 19 "github.com/luci/luci-go/grpc/grpcutil" |
20 | 20 |
21 "github.com/luci/luci-go/tokenserver/api/minter/v1" | 21 "github.com/luci/luci-go/tokenserver/api/minter/v1" |
22 ) | 22 ) |
23 | 23 |
24 // Client can make signed requests to the token server. | 24 // Client can make signed requests to the token server. |
25 type Client struct { | 25 type Client struct { |
26 // Client is interface to use for raw RPC calls to the token server. | 26 // Client is interface to use for raw RPC calls to the token server. |
27 // | 27 // |
28 // Use minter.NewTokenMinterClient (or NewTokenMinterPRPCClient) to | 28 // Use minter.NewTokenMinterClient (or NewTokenMinterPRPCClient) to |
(...skipping 20 matching lines...) Expand all Loading... |
49 // | 49 // |
50 // Use typecast to distinguish recognized and unrecognized errors. | 50 // Use typecast to distinguish recognized and unrecognized errors. |
51 type RPCError struct { | 51 type RPCError struct { |
52 error | 52 error |
53 | 53 |
54 GrpcCode codes.Code // grpc-level status code | 54 GrpcCode codes.Code // grpc-level status code |
55 ErrorCode minter.ErrorCode // protocol-level status code | 55 ErrorCode minter.ErrorCode // protocol-level status code |
56 ServiceVersion string // version of the backend, if known | 56 ServiceVersion string // version of the backend, if known |
57 } | 57 } |
58 | 58 |
59 // IsTransient is needed to implement errors.Transient. | |
60 func (e RPCError) IsTransient() bool { | |
61 return e.error != nil && grpcutil.IsTransientCode(e.GrpcCode) | |
62 } | |
63 | |
64 var _ errors.Transient = RPCError{} | |
65 | |
66 // MintMachineToken signs the request using the signer and sends it. | 59 // MintMachineToken signs the request using the signer and sends it. |
67 // | 60 // |
68 // It will update in-place the following fields of the request: | 61 // It will update in-place the following fields of the request: |
69 // * Certificate will be set to ASN1 cert corresponding to the signer key. | 62 // * Certificate will be set to ASN1 cert corresponding to the signer key. |
70 // * SignatureAlgorithm will be set to the algorithm used to sign the request. | 63 // * SignatureAlgorithm will be set to the algorithm used to sign the request. |
71 // * IssuedAt will be set to the current time. | 64 // * IssuedAt will be set to the current time. |
72 // | 65 // |
73 // The rest of the fields must be already populated by the caller and will be | 66 // The rest of the fields must be already populated by the caller and will be |
74 // sent to the server as is. | 67 // sent to the server as is. |
75 // | 68 // |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 102 } |
110 | 103 |
111 // Make an RPC call (with retries done by pRPC client). | 104 // Make an RPC call (with retries done by pRPC client). |
112 resp, err := c.Client.MintMachineToken(ctx, &minter.MintMachineTokenRequ
est{ | 105 resp, err := c.Client.MintMachineToken(ctx, &minter.MintMachineTokenRequ
est{ |
113 SerializedTokenRequest: tokenRequest, | 106 SerializedTokenRequest: tokenRequest, |
114 Signature: signature, | 107 Signature: signature, |
115 }, opts...) | 108 }, opts...) |
116 | 109 |
117 // Fatal pRPC-level error or transient error in case retries didn't help
. | 110 // Fatal pRPC-level error or transient error in case retries didn't help
. |
118 if err != nil { | 111 if err != nil { |
119 » » return nil, RPCError{ | 112 » » code := grpc.Code(err) |
| 113 » » err = RPCError{ |
120 error: err, | 114 error: err, |
121 » » » GrpcCode: grpc.Code(err), | 115 » » » GrpcCode: code, |
122 } | 116 } |
| 117 if grpcutil.IsTransientCode(code) { |
| 118 err = transient.Tag.Apply(err) |
| 119 } |
| 120 return nil, err |
123 } | 121 } |
124 | 122 |
125 // The response still may indicate a fatal error. | 123 // The response still may indicate a fatal error. |
126 if resp.ErrorCode != minter.ErrorCode_SUCCESS { | 124 if resp.ErrorCode != minter.ErrorCode_SUCCESS { |
127 details := resp.ErrorMessage | 125 details := resp.ErrorMessage |
128 if details == "" { | 126 if details == "" { |
129 details = "no detailed error message" | 127 details = "no detailed error message" |
130 } | 128 } |
131 return nil, RPCError{ | 129 return nil, RPCError{ |
132 error: fmt.Errorf("token server error %s - %s",
resp.ErrorCode, details), | 130 error: fmt.Errorf("token server error %s - %s",
resp.ErrorCode, details), |
133 GrpcCode: codes.OK, | 131 GrpcCode: codes.OK, |
134 ErrorCode: resp.ErrorCode, | 132 ErrorCode: resp.ErrorCode, |
135 ServiceVersion: resp.ServiceVersion, | 133 ServiceVersion: resp.ServiceVersion, |
136 } | 134 } |
137 } | 135 } |
138 | 136 |
139 // Must not happen. But better return an error than nil-panic if it does
. | 137 // Must not happen. But better return an error than nil-panic if it does
. |
140 if resp.TokenResponse == nil { | 138 if resp.TokenResponse == nil { |
141 return nil, fmt.Errorf("token server didn't return a token") | 139 return nil, fmt.Errorf("token server didn't return a token") |
142 } | 140 } |
143 | 141 |
144 return resp.TokenResponse, nil | 142 return resp.TokenResponse, nil |
145 } | 143 } |
OLD | NEW |