blob: ec3a4e4d482fd09db90e5f5153779a04bbcbde86 [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +02004package main
5
6import (
7 "context"
Serge Bazanski925ec3d2024-02-05 14:38:20 +01008 "crypto/tls"
Serge Bazanskib91938f2023-03-29 14:31:22 +02009 "crypto/x509"
Tim Windelschmidtd5f851b2024-04-23 14:59:37 +020010 "errors"
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020011 "fmt"
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000012 "net"
13 "net/http"
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020014
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000015 "golang.org/x/net/proxy"
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020016 "google.golang.org/grpc"
17
Mateusz Zalega18a67b02022-08-02 13:37:50 +020018 "source.monogon.dev/metropolis/cli/metroctl/core"
Serge Bazanski925ec3d2024-02-05 14:38:20 +010019 "source.monogon.dev/metropolis/node/core/rpc"
20 "source.monogon.dev/metropolis/node/core/rpc/resolver"
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020021)
22
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020023func dialAuthenticated(ctx context.Context) (*grpc.ClientConn, error) {
Mateusz Zalega18a67b02022-08-02 13:37:50 +020024 // Collect credentials, validate command parameters, and try dialing the
25 // cluster.
Serge Bazanskicf23ebc2023-03-14 17:02:04 +010026 ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
Tim Windelschmidt513df182024-04-18 23:44:50 +020027 if errors.Is(err, core.ErrNoCredentials) {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020028 return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020029 }
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000030 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020031 return nil, fmt.Errorf("failed to get owner credentials: %w", err)
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000032 }
Mateusz Zalegadb75e212022-08-04 17:31:34 +020033 if len(flags.clusterEndpoints) == 0 {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020034 return nil, fmt.Errorf("please provide at least one cluster endpoint using the --endpoint parameter")
Mateusz Zalegadb75e212022-08-04 17:31:34 +020035 }
Serge Bazanski7eeef0f2024-02-05 14:40:15 +010036
37 ca, err := core.GetClusterCAWithTOFU(ctx, connectOptions())
38 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020039 return nil, fmt.Errorf("failed to get cluster CA: %w", err)
Serge Bazanski7eeef0f2024-02-05 14:40:15 +010040 }
41
Serge Bazanski925ec3d2024-02-05 14:38:20 +010042 tlsc := tls.Certificate{
43 Certificate: [][]byte{ocert.Raw},
44 PrivateKey: opkey,
45 }
Serge Bazanski7eeef0f2024-02-05 14:40:15 +010046 creds := rpc.NewAuthenticatedCredentials(tlsc, rpc.WantRemoteCluster(ca))
Serge Bazanski925ec3d2024-02-05 14:38:20 +010047 opts, err := core.DialOpts(ctx, connectOptions())
48 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020049 return nil, fmt.Errorf("while configuring dial options: %w", err)
Serge Bazanski925ec3d2024-02-05 14:38:20 +010050 }
51 opts = append(opts, grpc.WithTransportCredentials(creds))
52
53 cc, err := grpc.Dial(resolver.MetropolisControlAddress, opts...)
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020054 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020055 return nil, fmt.Errorf("while dialing cluster: %w", err)
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020056 }
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020057 return cc, nil
Mateusz Zalegad5f2f7a2022-07-05 18:48:56 +020058}
Serge Bazanskib91938f2023-03-29 14:31:22 +020059
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020060func dialAuthenticatedNode(ctx context.Context, id, address string, cacert *x509.Certificate) (*grpc.ClientConn, error) {
Serge Bazanskib91938f2023-03-29 14:31:22 +020061 // Collect credentials, validate command parameters, and try dialing the
62 // cluster.
63 ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
Tim Windelschmidt513df182024-04-18 23:44:50 +020064 if errors.Is(err, core.ErrNoCredentials) {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020065 return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
Serge Bazanskib91938f2023-03-29 14:31:22 +020066 }
67 cc, err := core.DialNode(ctx, opkey, ocert, cacert, flags.proxyAddr, id, address)
68 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020069 return nil, fmt.Errorf("while dialing node: %w", err)
Serge Bazanskib91938f2023-03-29 14:31:22 +020070 }
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020071 return cc, nil
Serge Bazanskib91938f2023-03-29 14:31:22 +020072}
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000073
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020074func newAuthenticatedNodeHTTPTransport(ctx context.Context, id string) (*http.Transport, error) {
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000075 cacert, err := core.GetClusterCAWithTOFU(ctx, connectOptions())
76 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020077 return nil, fmt.Errorf("could not get CA certificate: %w", err)
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000078 }
79 ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
80 if errors.Is(err, core.ErrNoCredentials) {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020081 return nil, fmt.Errorf("you have to take ownership of the cluster first: %w", err)
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000082 }
83 tlsc := tls.Certificate{
84 Certificate: [][]byte{ocert.Raw},
85 PrivateKey: opkey,
86 }
87 tlsconf := rpc.NewAuthenticatedTLSConfig(tlsc, rpc.WantRemoteCluster(cacert), rpc.WantRemoteNode(id))
88 transport := &http.Transport{
89 TLSClientConfig: tlsconf,
90 }
91 if flags.proxyAddr != "" {
92 dialer, err := proxy.SOCKS5("tcp", flags.proxyAddr, nil, proxy.Direct)
93 if err != nil {
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020094 return nil, fmt.Errorf("failed to create proxy dialer: %w", err)
Serge Bazanskia3e38cf2024-07-31 14:40:04 +000095 }
96 transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
97 // TODO(q3k): handle context
98 return dialer.Dial(network, addr)
99 }
100 }
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +0200101 return transport, nil
Serge Bazanskia3e38cf2024-07-31 14:40:04 +0000102}