@@ -2,19 +2,10 @@ package plugin
2
2
3
3
import (
4
4
"context"
5
- "crypto/ed25519"
6
- "crypto/rand"
7
- "crypto/tls"
8
- "crypto/x509"
9
- "fmt"
10
- "log"
11
5
"net"
12
- "os"
13
6
14
7
"github.com/gotify/plugin-api/v2/generated/protobuf"
15
8
"google.golang.org/grpc"
16
- "google.golang.org/grpc/credentials"
17
- "google.golang.org/grpc/peer"
18
9
"google.golang.org/protobuf/types/known/emptypb"
19
10
)
20
11
@@ -48,237 +39,3 @@ func NewPluginRpc(infraDialer GrpcDialer) *PluginRpc {
48
39
func (h * PluginRpc ) Serve (listener net.Listener ) error {
49
40
return h .pluginServer .Serve (listener )
50
41
}
51
-
52
- type ServerVersionInfo struct {
53
- Version string
54
- Commit string
55
- BuildDate string
56
- }
57
-
58
- type infraServerImpl struct {
59
- server * ServerMux
60
- version ServerVersionInfo
61
- protobuf.UnimplementedInfraServer
62
- }
63
-
64
- func (s * infraServerImpl ) GetServerVersion (ctx context.Context , req * emptypb.Empty ) (* protobuf.ServerVersionInfo , error ) {
65
- return & protobuf.ServerVersionInfo {
66
- Version : s .version .Version ,
67
- Commit : s .version .Commit ,
68
- BuildDate : s .version .BuildDate ,
69
- }, nil
70
- }
71
-
72
- func (s * infraServerImpl ) WhoAmI (ctx context.Context , req * emptypb.Empty ) (* protobuf.Info , error ) {
73
- peer , ok := peer .FromContext (ctx )
74
- if ! ok {
75
- return nil , fmt .Errorf ("no peer in context" )
76
- }
77
- authInfo := peer .AuthInfo .(* infraTlsAuthInfo )
78
- return s .server .GetPluginInfo (authInfo .moduleName )
79
- }
80
-
81
- type PluginConnection struct {
82
- info * protobuf.Info
83
- conn * grpc.ClientConn
84
- }
85
-
86
- type ServerMux struct {
87
- version ServerVersionInfo
88
- tlsClient * EphemeralTLSClient
89
- infraAddr net.Addr
90
- infraListener net.Listener
91
- infraServer * grpc.Server
92
- pluginDNSToModulePath map [string ]string
93
- pluginConnections map [string ]PluginConnection
94
- protobuf.UnimplementedInfraServer
95
- }
96
-
97
- func (s * ServerMux ) GetServerVersion (ctx context.Context , req * emptypb.Empty ) (* protobuf.ServerVersionInfo , error ) {
98
- return & protobuf.ServerVersionInfo {
99
- Version : s .version .Version ,
100
- Commit : s .version .Commit ,
101
- BuildDate : s .version .BuildDate ,
102
- }, nil
103
- }
104
-
105
- func (s * ServerMux ) WhoAmI (ctx context.Context , req * emptypb.Empty ) (* protobuf.Info , error ) {
106
- peer , ok := peer .FromContext (ctx )
107
- if ! ok {
108
- return nil , fmt .Errorf ("no peer in context" )
109
- }
110
- authInfo := peer .AuthInfo .(* infraTlsAuthInfo )
111
- return s .GetPluginInfo (authInfo .moduleName )
112
- }
113
-
114
- type infraTlsCreds struct {
115
- pluginDNSToModulePath map [string ]string
116
- credentials.TransportCredentials
117
- }
118
-
119
- type infraTlsAuthInfo struct {
120
- moduleName string
121
- credentials.TLSInfo
122
- }
123
-
124
- func (c * infraTlsCreds ) ServerHandshake (rawConn net.Conn ) (net.Conn , credentials.AuthInfo , error ) {
125
- netConn , authInfo , err := c .TransportCredentials .ServerHandshake (rawConn )
126
- if err != nil {
127
- log .Printf ("ServerHandshake: error %v" , err )
128
- rawConn .Close ()
129
- return nil , nil , err
130
- }
131
- protocolInfo := authInfo .(credentials.TLSInfo )
132
- serverName := protocolInfo .State .VerifiedChains [0 ][0 ].DNSNames [0 ]
133
- moduleName , ok := c .pluginDNSToModulePath [serverName ]
134
- if ! ok {
135
- log .Printf ("ServerHandshake: unknown server name %s" , serverName )
136
- netConn .Close ()
137
- rawConn .Close ()
138
- return nil , nil , fmt .Errorf ("unknown server name %s" , serverName )
139
- }
140
-
141
- return netConn , & infraTlsAuthInfo {
142
- moduleName : moduleName ,
143
- TLSInfo : protocolInfo ,
144
- }, nil
145
- }
146
-
147
- // NewServerMux creates a server-side mux with an infra server that handles plugin-to-server calls.
148
- func NewServerMux (info ServerVersionInfo ) * ServerMux {
149
- tlsClient , err := NewEphemeralTLSClient ()
150
- if err != nil {
151
- panic (err )
152
- }
153
- _ , infraPriv , err := ed25519 .GenerateKey (rand .Reader )
154
- if err != nil {
155
- panic (err )
156
- }
157
- infraCsrBytes , err := x509 .CreateCertificateRequest (rand .Reader , new (x509.CertificateRequest ), infraPriv )
158
- if err != nil {
159
- panic (err )
160
- }
161
- infraCsr , err := x509 .ParseCertificateRequest (infraCsrBytes )
162
- if err != nil {
163
- panic (err )
164
- }
165
- if err := infraCsr .CheckSignature (); err != nil {
166
- panic (err )
167
- }
168
- infraCert , err := tlsClient .SignCSR (ServerTLSName , infraCsr )
169
- if err != nil {
170
- panic (err )
171
- }
172
- infraCertParsed , err := x509 .ParseCertificate (infraCert )
173
- if err != nil {
174
- panic (err )
175
- }
176
- caCertPool := x509 .NewCertPool ()
177
- caCertPool .AddCert (tlsClient .caCert )
178
- infraTlsConfig := & tls.Config {
179
- Certificates : []tls.Certificate {
180
- {
181
- Certificate : [][]byte {infraCert , tlsClient .caCert .Raw },
182
- PrivateKey : infraPriv ,
183
- Leaf : infraCertParsed ,
184
- },
185
- },
186
- ClientAuth : tls .RequireAndVerifyClientCert ,
187
- ClientCAs : caCertPool ,
188
- ServerName : ServerTLSName ,
189
- }
190
-
191
- pluginDNSToModulePath := make (map [string ]string )
192
- infraServer := grpc .NewServer (grpc .Creds (& infraTlsCreds {
193
- pluginDNSToModulePath : pluginDNSToModulePath ,
194
- TransportCredentials : credentials .NewTLS (infraTlsConfig ),
195
- }))
196
-
197
- listener , err := newListener ()
198
- if err != nil {
199
- panic (err )
200
- }
201
- mux := & ServerMux {
202
- version : info ,
203
- tlsClient : tlsClient ,
204
- infraAddr : listener .Addr (),
205
- infraListener : listener ,
206
- infraServer : infraServer ,
207
- pluginDNSToModulePath : pluginDNSToModulePath ,
208
- pluginConnections : make (map [string ]PluginConnection ),
209
- }
210
- protobuf .RegisterInfraServer (infraServer , & infraServerImpl {
211
- server : mux ,
212
- version : info ,
213
- })
214
-
215
- go infraServer .Serve (listener )
216
-
217
- return mux
218
- }
219
-
220
- // InfraAddr returns the address of the infra server for plugin-to-server callbacks.
221
- func (s * ServerMux ) InfraAddr () net.Addr {
222
- return s .infraAddr
223
- }
224
-
225
- // CACert returns the CA certificate for mutual TLS authentication.
226
- func (s * ServerMux ) CACert () * x509.Certificate {
227
- return s .tlsClient .caCert
228
- }
229
-
230
- // SignPluginCSR signs a certificate request for a plugin.
231
- func (s * ServerMux ) SignPluginCSR (moduleName string , csr * x509.CertificateRequest ) ([]byte , error ) {
232
- return s .tlsClient .SignPluginCSR (moduleName , csr )
233
- }
234
-
235
- func (s * ServerMux ) RegisterPlugin (target string , moduleName string ) (* grpc.ClientConn , error ) {
236
- grpcConn , err := grpc .NewClient (target , grpc .WithTransportCredentials (credentials .NewTLS (s .tlsClient .ClientTLSConfig (moduleName ))))
237
- if err != nil {
238
- return nil , err
239
- }
240
- if _ , exists := s .pluginDNSToModulePath [buildPluginTLSName (moduleName )]; exists {
241
- return nil , fmt .Errorf ("plugin %s already registered" , moduleName )
242
- }
243
- s .pluginDNSToModulePath [buildPluginTLSName (moduleName )] = moduleName
244
- pluginClient := protobuf .NewPluginClient (grpcConn )
245
- pluginInfo , err := pluginClient .GetPluginInfo (context .Background (), & emptypb.Empty {})
246
- if err != nil {
247
- return nil , err
248
- }
249
- s .pluginConnections [moduleName ] = PluginConnection {
250
- info : pluginInfo ,
251
- conn : grpcConn ,
252
- }
253
- return grpcConn , nil
254
- }
255
-
256
- // GetPluginInfo returns the info of a plugin.
257
- func (s * ServerMux ) GetPluginInfo (moduleName string ) (* protobuf.Info , error ) {
258
- conn , ok := s .pluginConnections [moduleName ]
259
- if ! ok {
260
- return nil , fmt .Errorf ("plugin %s not registered" , moduleName )
261
- }
262
- return conn .info , nil
263
- }
264
-
265
- // GetPluginConnection returns the connection to the plugin for Server-to-Plugin calls.
266
- func (s * ServerMux ) GetPluginConnection (moduleName string ) (* grpc.ClientConn , error ) {
267
- conn , ok := s .pluginConnections [moduleName ]
268
- if ! ok {
269
- return nil , fmt .Errorf ("plugin %s not registered" , moduleName )
270
- }
271
- return conn .conn , nil
272
- }
273
-
274
- func (s * ServerMux ) Close () error {
275
- for _ , conn := range s .pluginConnections {
276
- conn .conn .Close ()
277
- }
278
- s .infraServer .GracefulStop ()
279
- if s .infraAddr .Network () == "unix" {
280
- os .Remove (s .infraAddr .String ())
281
- }
282
- s .infraListener .Close ()
283
- return nil
284
- }
0 commit comments