-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy paths2a_options.go
272 lines (237 loc) · 8.49 KB
/
s2a_options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package s2a
import (
"crypto/tls"
"errors"
"sync"
"github.com/google/s2a-go/fallback"
"github.com/google/s2a-go/stream"
"google.golang.org/grpc/credentials"
s2av1pb "github.com/google/s2a-go/internal/proto/common_go_proto"
s2apb "github.com/google/s2a-go/internal/proto/v2/common_go_proto"
)
// Identity is the interface for S2A identities.
type Identity interface {
// Name returns the name of the identity.
Name() string
Attributes() map[string]string
}
type UnspecifiedID struct {
Attr map[string]string
}
func (u *UnspecifiedID) Name() string { return "" }
func (u *UnspecifiedID) Attributes() map[string]string {
return u.Attr
}
type spiffeID struct {
spiffeID string
}
func (s *spiffeID) Name() string { return s.spiffeID }
func (spiffeID) Attributes() map[string]string { return nil }
// NewSpiffeID creates a SPIFFE ID from id.
func NewSpiffeID(id string) Identity { return &spiffeID{spiffeID: id} }
type hostname struct {
hostname string
}
func (h *hostname) Name() string { return h.hostname }
func (hostname) Attributes() map[string]string { return nil }
// NewHostname creates a hostname from name.
func NewHostname(name string) Identity { return &hostname{hostname: name} }
type uid struct {
uid string
}
func (h *uid) Name() string { return h.uid }
func (uid) Attributes() map[string]string { return nil }
// NewUID creates a UID from name.
func NewUID(name string) Identity { return &uid{uid: name} }
// VerificationModeType specifies the mode that S2A must use to verify the peer
// certificate chain.
type VerificationModeType int
// Three types of verification modes.
const (
Unspecified VerificationModeType = iota
Spiffe
ConnectToGoogle
ReservedCustomVerificationMode3
ReservedCustomVerificationMode4
ReservedCustomVerificationMode5
ReservedCustomVerificationMode6
)
// ClientOptions contains the client-side options used to establish a secure
// channel using the S2A handshaker service.
type ClientOptions struct {
// TargetIdentities contains a list of allowed server identities. One of the
// target identities should match the peer identity in the handshake
// result; otherwise, the handshake fails.
TargetIdentities []Identity
// LocalIdentity is the local identity of the client application. If none is
// provided, then the S2A will choose the default identity, if one exists.
LocalIdentity Identity
// S2AAddress is the address of the S2A.
S2AAddress string
// Optional transport credentials.
// If set, this will be used for the gRPC connection to the S2A server.
TransportCreds credentials.TransportCredentials
// EnsureProcessSessionTickets waits for all session tickets to be sent to
// S2A before a process completes.
//
// This functionality is crucial for processes that complete very soon after
// using S2A to establish a TLS connection, but it can be ignored for longer
// lived processes.
//
// Usage example:
// func main() {
// var ensureProcessSessionTickets sync.WaitGroup
// clientOpts := &s2a.ClientOptions{
// EnsureProcessSessionTickets: &ensureProcessSessionTickets,
// // Set other members.
// }
// creds, _ := s2a.NewClientCreds(clientOpts)
// conn, _ := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds))
// defer conn.Close()
//
// // Make RPC call.
//
// // The process terminates right after the RPC call ends.
// // ensureProcessSessionTickets can be used to ensure resumption
// // tickets are fully processed. If the process is long-lived, using
// // ensureProcessSessionTickets is not necessary.
// ensureProcessSessionTickets.Wait()
// }
EnsureProcessSessionTickets *sync.WaitGroup
// If true, enables the use of legacy S2Av1.
EnableLegacyMode bool
// VerificationMode specifies the mode that S2A must use to verify the
// peer certificate chain.
VerificationMode VerificationModeType
// Optional fallback after dialing with S2A fails.
FallbackOpts *FallbackOptions
// Generates an S2AStream interface for talking to the S2A server.
getS2AStream stream.GetS2AStream
// Serialized user specified policy for server authorization.
serverAuthorizationPolicy []byte
}
// FallbackOptions prescribes the fallback logic that should be taken if the application fails to connect with S2A.
type FallbackOptions struct {
// FallbackClientHandshakeFunc is used to specify fallback behavior when calling s2a.NewClientCreds().
// It will be called by ClientHandshake function, after handshake with S2A fails.
// s2a.NewClientCreds() ignores the other FallbackDialer field.
FallbackClientHandshakeFunc fallback.ClientHandshake
// FallbackDialer is used to specify fallback behavior when calling s2a.NewS2aDialTLSContextFunc().
// It passes in a custom fallback dialer and server address to use after dialing with S2A fails.
// s2a.NewS2aDialTLSContextFunc() ignores the other FallbackClientHandshakeFunc field.
FallbackDialer *FallbackDialer
}
// FallbackDialer contains a fallback tls.Dialer and a server address to connect to.
type FallbackDialer struct {
// Dialer specifies a fallback tls.Dialer.
Dialer *tls.Dialer
// ServerAddr is used by Dialer to establish fallback connection.
ServerAddr string
}
// DefaultClientOptions returns the default client options.
func DefaultClientOptions(s2aAddress string) *ClientOptions {
return &ClientOptions{
S2AAddress: s2aAddress,
VerificationMode: ConnectToGoogle,
}
}
// ServerOptions contains the server-side options used to establish a secure
// channel using the S2A handshaker service.
type ServerOptions struct {
// LocalIdentities is the list of local identities that may be assumed by
// the server. If no local identity is specified, then the S2A chooses a
// default local identity, if one exists.
LocalIdentities []Identity
// S2AAddress is the address of the S2A.
S2AAddress string
// Optional transport credentials.
// If set, this will be used for the gRPC connection to the S2A server.
TransportCreds credentials.TransportCredentials
// If true, enables the use of legacy S2Av1.
EnableLegacyMode bool
// VerificationMode specifies the mode that S2A must use to verify the
// peer certificate chain.
VerificationMode VerificationModeType
// Generates an S2AStream interface for talking to the S2A server.
getS2AStream stream.GetS2AStream
}
// DefaultServerOptions returns the default server options.
func DefaultServerOptions(s2aAddress string) *ServerOptions {
return &ServerOptions{
S2AAddress: s2aAddress,
VerificationMode: ConnectToGoogle,
}
}
func toProtoIdentity(identity Identity) (*s2av1pb.Identity, error) {
if identity == nil {
return nil, nil
}
switch id := identity.(type) {
case *spiffeID:
return &s2av1pb.Identity{
IdentityOneof: &s2av1pb.Identity_SpiffeId{SpiffeId: id.Name()},
Attributes: id.Attributes(),
}, nil
case *hostname:
return &s2av1pb.Identity{
IdentityOneof: &s2av1pb.Identity_Hostname{Hostname: id.Name()},
Attributes: id.Attributes(),
}, nil
case *uid:
return &s2av1pb.Identity{
IdentityOneof: &s2av1pb.Identity_Uid{Uid: id.Name()},
Attributes: id.Attributes(),
}, nil
case *UnspecifiedID:
return &s2av1pb.Identity{
Attributes: id.Attributes(),
}, nil
default:
return nil, errors.New("unrecognized identity type")
}
}
func toV2ProtoIdentity(identity Identity) (*s2apb.Identity, error) {
if identity == nil {
return nil, nil
}
switch id := identity.(type) {
case *spiffeID:
return &s2apb.Identity{
IdentityOneof: &s2apb.Identity_SpiffeId{SpiffeId: id.Name()},
Attributes: id.Attributes(),
}, nil
case *hostname:
return &s2apb.Identity{
IdentityOneof: &s2apb.Identity_Hostname{Hostname: id.Name()},
Attributes: id.Attributes(),
}, nil
case *uid:
return &s2apb.Identity{
IdentityOneof: &s2apb.Identity_Uid{Uid: id.Name()},
Attributes: id.Attributes(),
}, nil
case *UnspecifiedID:
return &s2apb.Identity{
Attributes: id.Attributes(),
}, nil
default:
return nil, errors.New("unrecognized identity type")
}
}