| 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" |
| 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 = retry.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 |