Skip to content

Commit e6fc00f

Browse files
move ServerMux to server repo
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
1 parent 8a89a6b commit e6fc00f

File tree

7 files changed

+13
-370
lines changed

7 files changed

+13
-370
lines changed

v2/pipe_net_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ func TestGrpcPipeNet(t *testing.T) {
4646
defer listener.Close()
4747
serverCsrBytes, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
4848
Subject: pkix.Name{
49-
CommonName: buildPluginTLSName("test"),
49+
CommonName: BuildPluginTLSName("test"),
5050
},
5151
DNSNames: []string{
52-
buildPluginTLSName("test"),
52+
BuildPluginTLSName("test"),
5353
},
5454
PublicKey: serverPub,
5555
}, serverPriv)

v2/pipe_not_unix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package plugin
44

55
import "net"
66

7-
func newListener() (net.Listener, error) {
7+
func NewListener() (net.Listener, error) {
88
listener, err := net.Listen("tcp", "[::1]:0")
99
if err != nil {
1010
return nil, err

v2/pipe_unix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"path/filepath"
99
)
1010

11-
func newListener() (net.Listener, error) {
11+
func NewListener() (net.Listener, error) {
1212
tmpDir, err := os.MkdirTemp("", "gotify-plugin-*")
1313
if err != nil {
1414
return nil, err

v2/rpc.go

Lines changed: 0 additions & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,10 @@ package plugin
22

33
import (
44
"context"
5-
"crypto/ed25519"
6-
"crypto/rand"
7-
"crypto/tls"
8-
"crypto/x509"
9-
"fmt"
10-
"log"
115
"net"
12-
"os"
136

147
"github.com/gotify/plugin-api/v2/generated/protobuf"
158
"google.golang.org/grpc"
16-
"google.golang.org/grpc/credentials"
17-
"google.golang.org/grpc/peer"
189
"google.golang.org/protobuf/types/known/emptypb"
1910
)
2011

@@ -48,237 +39,3 @@ func NewPluginRpc(infraDialer GrpcDialer) *PluginRpc {
4839
func (h *PluginRpc) Serve(listener net.Listener) error {
4940
return h.pluginServer.Serve(listener)
5041
}
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

Comments
 (0)