s2a_options.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. *
  3. * Copyright 2021 Google LLC
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * https://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package s2a
  19. import (
  20. "context"
  21. "crypto/tls"
  22. "errors"
  23. "sync"
  24. "github.com/google/s2a-go/fallback"
  25. "github.com/google/s2a-go/stream"
  26. s2apb "github.com/google/s2a-go/internal/proto/common_go_proto"
  27. )
  28. // Identity is the interface for S2A identities.
  29. type Identity interface {
  30. // Name returns the name of the identity.
  31. Name() string
  32. }
  33. type spiffeID struct {
  34. spiffeID string
  35. }
  36. func (s *spiffeID) Name() string { return s.spiffeID }
  37. // NewSpiffeID creates a SPIFFE ID from id.
  38. func NewSpiffeID(id string) Identity {
  39. return &spiffeID{spiffeID: id}
  40. }
  41. type hostname struct {
  42. hostname string
  43. }
  44. func (h *hostname) Name() string { return h.hostname }
  45. // NewHostname creates a hostname from name.
  46. func NewHostname(name string) Identity {
  47. return &hostname{hostname: name}
  48. }
  49. type uid struct {
  50. uid string
  51. }
  52. func (h *uid) Name() string { return h.uid }
  53. // NewUID creates a UID from name.
  54. func NewUID(name string) Identity {
  55. return &uid{uid: name}
  56. }
  57. // VerificationModeType specifies the mode that S2A must use to verify the peer
  58. // certificate chain.
  59. type VerificationModeType int
  60. // Three types of verification modes.
  61. const (
  62. Unspecified = iota
  63. ConnectToGoogle
  64. Spiffe
  65. )
  66. // ClientOptions contains the client-side options used to establish a secure
  67. // channel using the S2A handshaker service.
  68. type ClientOptions struct {
  69. // TargetIdentities contains a list of allowed server identities. One of the
  70. // target identities should match the peer identity in the handshake
  71. // result; otherwise, the handshake fails.
  72. TargetIdentities []Identity
  73. // LocalIdentity is the local identity of the client application. If none is
  74. // provided, then the S2A will choose the default identity, if one exists.
  75. LocalIdentity Identity
  76. // S2AAddress is the address of the S2A.
  77. S2AAddress string
  78. // EnsureProcessSessionTickets waits for all session tickets to be sent to
  79. // S2A before a process completes.
  80. //
  81. // This functionality is crucial for processes that complete very soon after
  82. // using S2A to establish a TLS connection, but it can be ignored for longer
  83. // lived processes.
  84. //
  85. // Usage example:
  86. // func main() {
  87. // var ensureProcessSessionTickets sync.WaitGroup
  88. // clientOpts := &s2a.ClientOptions{
  89. // EnsureProcessSessionTickets: &ensureProcessSessionTickets,
  90. // // Set other members.
  91. // }
  92. // creds, _ := s2a.NewClientCreds(clientOpts)
  93. // conn, _ := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds))
  94. // defer conn.Close()
  95. //
  96. // // Make RPC call.
  97. //
  98. // // The process terminates right after the RPC call ends.
  99. // // ensureProcessSessionTickets can be used to ensure resumption
  100. // // tickets are fully processed. If the process is long-lived, using
  101. // // ensureProcessSessionTickets is not necessary.
  102. // ensureProcessSessionTickets.Wait()
  103. // }
  104. EnsureProcessSessionTickets *sync.WaitGroup
  105. // If true, enables the use of legacy S2Av1.
  106. EnableLegacyMode bool
  107. // VerificationMode specifies the mode that S2A must use to verify the
  108. // peer certificate chain.
  109. VerificationMode VerificationModeType
  110. // Optional fallback after dialing with S2A fails.
  111. FallbackOpts *FallbackOptions
  112. // Generates an S2AStream interface for talking to the S2A server.
  113. getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error)
  114. // Serialized user specified policy for server authorization.
  115. serverAuthorizationPolicy []byte
  116. }
  117. // FallbackOptions prescribes the fallback logic that should be taken if the application fails to connect with S2A.
  118. type FallbackOptions struct {
  119. // FallbackClientHandshakeFunc is used to specify fallback behavior when calling s2a.NewClientCreds().
  120. // It will be called by ClientHandshake function, after handshake with S2A fails.
  121. // s2a.NewClientCreds() ignores the other FallbackDialer field.
  122. FallbackClientHandshakeFunc fallback.ClientHandshake
  123. // FallbackDialer is used to specify fallback behavior when calling s2a.NewS2aDialTLSContextFunc().
  124. // It passes in a custom fallback dialer and server address to use after dialing with S2A fails.
  125. // s2a.NewS2aDialTLSContextFunc() ignores the other FallbackClientHandshakeFunc field.
  126. FallbackDialer *FallbackDialer
  127. }
  128. // FallbackDialer contains a fallback tls.Dialer and a server address to connect to.
  129. type FallbackDialer struct {
  130. // Dialer specifies a fallback tls.Dialer.
  131. Dialer *tls.Dialer
  132. // ServerAddr is used by Dialer to establish fallback connection.
  133. ServerAddr string
  134. }
  135. // DefaultClientOptions returns the default client options.
  136. func DefaultClientOptions(s2aAddress string) *ClientOptions {
  137. return &ClientOptions{
  138. S2AAddress: s2aAddress,
  139. VerificationMode: ConnectToGoogle,
  140. }
  141. }
  142. // ServerOptions contains the server-side options used to establish a secure
  143. // channel using the S2A handshaker service.
  144. type ServerOptions struct {
  145. // LocalIdentities is the list of local identities that may be assumed by
  146. // the server. If no local identity is specified, then the S2A chooses a
  147. // default local identity, if one exists.
  148. LocalIdentities []Identity
  149. // S2AAddress is the address of the S2A.
  150. S2AAddress string
  151. // If true, enables the use of legacy S2Av1.
  152. EnableLegacyMode bool
  153. // VerificationMode specifies the mode that S2A must use to verify the
  154. // peer certificate chain.
  155. VerificationMode VerificationModeType
  156. // Generates an S2AStream interface for talking to the S2A server.
  157. getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error)
  158. }
  159. // DefaultServerOptions returns the default server options.
  160. func DefaultServerOptions(s2aAddress string) *ServerOptions {
  161. return &ServerOptions{
  162. S2AAddress: s2aAddress,
  163. VerificationMode: ConnectToGoogle,
  164. }
  165. }
  166. func toProtoIdentity(identity Identity) (*s2apb.Identity, error) {
  167. if identity == nil {
  168. return nil, nil
  169. }
  170. switch id := identity.(type) {
  171. case *spiffeID:
  172. return &s2apb.Identity{IdentityOneof: &s2apb.Identity_SpiffeId{SpiffeId: id.Name()}}, nil
  173. case *hostname:
  174. return &s2apb.Identity{IdentityOneof: &s2apb.Identity_Hostname{Hostname: id.Name()}}, nil
  175. case *uid:
  176. return &s2apb.Identity{IdentityOneof: &s2apb.Identity_Uid{Uid: id.Name()}}, nil
  177. default:
  178. return nil, errors.New("unrecognized identity type")
  179. }
  180. }