Skip to content

Commit 3bafbf6

Browse files
smasset-orangeshanduur
authored andcommitted
feat: add authority in GRPC client initialization
Enables support for trustd behind load balancer by providing SNI. (cherry picked from commit b593bc6) (cherry picked from commit 33f336d) Signed-off-by: Sébastien Masset <86793256+smasset-orange@users.noreply.github.com> Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com>
1 parent 080efcb commit 3bafbf6

File tree

5 files changed

+74
-20
lines changed

5 files changed

+74
-20
lines changed

internal/app/machined/pkg/controllers/secrets/api.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (ctrl *APIController) reconcile(ctx context.Context, r controller.Runtime,
269269
return err
270270
}
271271
} else {
272-
if err := ctrl.generateWorker(ctx, r, logger, rootSpec, endpointsStr, certSANs); err != nil {
272+
if err := ctrl.generateWorker(ctx, r, logger, rootSpec, endpointsStr, "", certSANs); err != nil {
273273
return err
274274
}
275275
}
@@ -336,9 +336,11 @@ func (ctrl *APIController) generateControlPlane(ctx context.Context, r controlle
336336
}
337337

338338
func (ctrl *APIController) generateWorker(ctx context.Context, r controller.Runtime, logger *zap.Logger,
339-
rootSpec *secrets.OSRootSpec, endpointsStr []string, certSANs *secrets.CertSANSpec,
339+
rootSpec *secrets.OSRootSpec, endpointsStr []string, endpointHost string, certSANs *secrets.CertSANSpec,
340340
) error {
341-
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.AcceptedCAs)
341+
logger.Debug("Initializing CSR generator", zap.Strings("endpoints", endpointsStr), zap.String("host", endpointHost))
342+
343+
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, endpointHost, rootSpec.AcceptedCAs)
342344
if err != nil {
343345
return fmt.Errorf("failed creating trustd client: %w", err)
344346
}

pkg/grpc/gen/remote.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type RemoteGenerator struct {
3131
}
3232

3333
// NewRemoteGenerator initializes a RemoteGenerator with a preconfigured grpc.ClientConn.
34-
func NewRemoteGenerator(token string, endpoints []string, acceptedCAs []*x509.PEMEncodedCertificate) (g *RemoteGenerator, err error) {
34+
func NewRemoteGenerator(token string, endpoints []string, host string, acceptedCAs []*x509.PEMEncodedCertificate) (g *RemoteGenerator, err error) {
3535
if len(endpoints) == 0 {
3636
return nil, errors.New("at least one root of trust endpoint is required")
3737
}
@@ -42,7 +42,7 @@ func NewRemoteGenerator(token string, endpoints []string, acceptedCAs []*x509.PE
4242

4343
remoteGeneratorPprof.Add(g, 1)
4444

45-
conn, err := basic.NewConnection(fmt.Sprintf("%s:///%s", resolver.RoundRobinResolverScheme, strings.Join(endpoints, ",")), basic.NewTokenCredentials(token), acceptedCAs)
45+
conn, err := basic.NewConnection(fmt.Sprintf("%s:///%s", resolver.RoundRobinResolverScheme, strings.Join(endpoints, ",")), host, basic.NewTokenCredentials(token), acceptedCAs)
4646
if err != nil {
4747
return nil, err
4848
}

pkg/grpc/middleware/auth/basic/basic.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"crypto/tls"
1010
stdx509 "crypto/x509"
11+
"net"
1112

1213
"github.com/siderolabs/crypto/x509"
1314
"github.com/siderolabs/gen/xslices"
@@ -16,6 +17,7 @@ import (
1617

1718
"github.com/siderolabs/talos/pkg/httpdefaults"
1819
"github.com/siderolabs/talos/pkg/machinery/client/dialer"
20+
"github.com/siderolabs/talos/pkg/machinery/labels"
1921
)
2022

2123
// Credentials describes an authorization method.
@@ -27,7 +29,7 @@ type Credentials interface {
2729

2830
// NewConnection initializes a grpc.ClientConn configured for basic
2931
// authentication.
30-
func NewConnection(address string, creds credentials.PerRPCCredentials, acceptedCAs []*x509.PEMEncodedCertificate) (conn *grpc.ClientConn, err error) {
32+
func NewConnection(address string, host string, creds credentials.PerRPCCredentials, acceptedCAs []*x509.PEMEncodedCertificate) (conn *grpc.ClientConn, err error) {
3133
tlsConfig := &tls.Config{}
3234

3335
tlsConfig.RootCAs = stdx509.NewCertPool()
@@ -42,6 +44,7 @@ func NewConnection(address string, creds credentials.PerRPCCredentials, accepted
4244
))
4345

4446
grpcOpts := []grpc.DialOption{
47+
grpc.WithAuthority(ParseAuthority(host)),
4548
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
4649
grpc.WithPerRPCCredentials(creds),
4750
grpc.WithSharedWriteBuffer(true),
@@ -55,3 +58,34 @@ func NewConnection(address string, creds credentials.PerRPCCredentials, accepted
5558

5659
return conn, nil
5760
}
61+
62+
// ParseAuthority checks if provided host parameter is neither empty nor
63+
// an IP address and returns the extracted host if found
64+
// or an empty string in all other cases.
65+
func ParseAuthority(host string) string {
66+
if host == "" {
67+
return ""
68+
}
69+
70+
var parsedHost string
71+
72+
// Check if port is provided and remove it
73+
h, _, err := net.SplitHostPort(host)
74+
if err == nil {
75+
parsedHost = h
76+
} else {
77+
parsedHost = host
78+
}
79+
80+
// If parsedHost is an IP address it should not be used as an authority
81+
if ip := net.ParseIP(parsedHost); ip != nil {
82+
return ""
83+
}
84+
85+
if err := labels.ValidateDNS1123Subdomain(parsedHost); err != nil {
86+
return ""
87+
}
88+
89+
// Otherwise return the parsed host
90+
return parsedHost
91+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
package basic_test
6+
7+
import (
8+
"testing"
9+
10+
"github.com/siderolabs/talos/pkg/grpc/middleware/auth/basic"
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestParseAuthority(t *testing.T) {
15+
for _, tc := range []struct {
16+
host string
17+
want string
18+
}{
19+
{"", ""},
20+
{"::1", ""},
21+
{"[::1]", ""},
22+
{"[::1]:443", ""},
23+
{"127.0.0.1", ""},
24+
{"127.0.0.1:443", ""},
25+
{"[example.com]", ""},
26+
{"example.com", "example.com"},
27+
{"example.com:443", "example.com"},
28+
{"[example.com]:443", "example.com"},
29+
} {
30+
assert.Equalf(t, tc.want, basic.ParseAuthority(tc.host), "ParseAuthority(%q)", tc.host)
31+
}
32+
}

pkg/grpc/middleware/auth/basic/username_and_password_test.go

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)