blob: 91d517508919924d27cbef8cd6c711fcb7956394 [file] [log] [blame]
Mateusz Zalega18a67b02022-08-02 13:37:50 +02001package core
2
3import (
4 "context"
5 "crypto/ed25519"
6 "crypto/tls"
7 "crypto/x509"
8 "fmt"
9 "io"
10 "net"
11
12 "golang.org/x/net/proxy"
13 "google.golang.org/grpc"
14
15 "source.monogon.dev/metropolis/node"
16 "source.monogon.dev/metropolis/node/core/rpc"
17 "source.monogon.dev/metropolis/node/core/rpc/resolver"
18 "source.monogon.dev/metropolis/proto/api"
19)
20
Serge Bazanski925ec3d2024-02-05 14:38:20 +010021func DialOpts(ctx context.Context, c *ConnectOptions) ([]grpc.DialOption, error) {
22 var opts []grpc.DialOption
23 if c.ProxyServer != "" {
24 socksDialer, err := proxy.SOCKS5("tcp", c.ProxyServer, nil, proxy.Direct)
Mateusz Zalega18a67b02022-08-02 13:37:50 +020025 if err != nil {
Tim Windelschmidt58786032024-05-21 13:47:41 +020026 return nil, fmt.Errorf("failed to build a SOCKS dialer: %w", err)
Mateusz Zalega18a67b02022-08-02 13:37:50 +020027 }
28 grpcd := func(_ context.Context, addr string) (net.Conn, error) {
29 return socksDialer.Dial("tcp", addr)
30 }
Serge Bazanski925ec3d2024-02-05 14:38:20 +010031 opts = append(opts, grpc.WithContextDialer(grpcd))
Mateusz Zalega18a67b02022-08-02 13:37:50 +020032 }
33
34 var resolverOpts []resolver.ResolverOption
Serge Bazanski925ec3d2024-02-05 14:38:20 +010035 if c.ResolverLogger != nil {
36 resolverOpts = append(resolverOpts, resolver.WithLogger(c.ResolverLogger))
Mateusz Zalega18a67b02022-08-02 13:37:50 +020037 }
Serge Bazanski925ec3d2024-02-05 14:38:20 +010038
Mateusz Zalega18a67b02022-08-02 13:37:50 +020039 r := resolver.New(ctx, resolverOpts...)
40
Serge Bazanski925ec3d2024-02-05 14:38:20 +010041 if len(c.Endpoints) == 0 {
42 return nil, fmt.Errorf("no cluster endpoints specified")
43 }
44 for _, eps := range c.Endpoints {
Mateusz Zalega18a67b02022-08-02 13:37:50 +020045 ep := resolver.NodeByHostPort(eps, uint16(node.CuratorServicePort))
46 r.AddEndpoint(ep)
47 }
Serge Bazanski925ec3d2024-02-05 14:38:20 +010048 opts = append(opts, grpc.WithResolvers(r))
Mateusz Zalega18a67b02022-08-02 13:37:50 +020049
Serge Bazanski925ec3d2024-02-05 14:38:20 +010050 return opts, nil
Mateusz Zalega18a67b02022-08-02 13:37:50 +020051}
52
Serge Bazanskib91938f2023-03-29 14:31:22 +020053func DialNode(ctx context.Context, opkey ed25519.PrivateKey, ocert, ca *x509.Certificate, proxyAddr, nodeId, nodeAddr string) (*grpc.ClientConn, error) {
54 var dialOpts []grpc.DialOption
55
56 if opkey == nil {
57 return nil, fmt.Errorf("an owner's private key must be provided")
58 }
59 if proxyAddr != "" {
60 socksDialer, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
61 if err != nil {
Tim Windelschmidt58786032024-05-21 13:47:41 +020062 return nil, fmt.Errorf("failed to build a SOCKS dialer: %w", err)
Serge Bazanskib91938f2023-03-29 14:31:22 +020063 }
64 grpcd := func(_ context.Context, addr string) (net.Conn, error) {
65 return socksDialer.Dial("tcp", addr)
66 }
67 dialOpts = append(dialOpts, grpc.WithContextDialer(grpcd))
68 }
69 tlsc := tls.Certificate{
70 Certificate: [][]byte{ocert.Raw},
71 PrivateKey: opkey,
72 }
73 creds := rpc.NewAuthenticatedCredentials(tlsc, rpc.WantRemoteCluster(ca), rpc.WantRemoteNode(nodeId))
74 dialOpts = append(dialOpts, grpc.WithTransportCredentials(creds))
75
Tim Windelschmidtec2906a2024-03-27 01:36:43 +010076 endpoint := net.JoinHostPort(nodeAddr, node.NodeManagementPort.PortString())
Serge Bazanskib91938f2023-03-29 14:31:22 +020077 return grpc.Dial(endpoint, dialOpts...)
78}
79
Mateusz Zalega18a67b02022-08-02 13:37:50 +020080// GetNodes retrieves node records, filtered by the supplied node filter
81// expression fexp.
82func GetNodes(ctx context.Context, mgmt api.ManagementClient, fexp string) ([]*api.Node, error) {
83 resN, err := mgmt.GetNodes(ctx, &api.GetNodesRequest{
84 Filter: fexp,
85 })
86 if err != nil {
87 return nil, err
88 }
89
90 var nodes []*api.Node
91 for {
92 node, err := resN.Recv()
93 if err == io.EOF {
94 break
95 }
96 if err != nil {
97 return nil, err
98 }
99 nodes = append(nodes, node)
100 }
101 return nodes, nil
102}