Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Claim gateways on The Things Gateway Controller #7201

Merged
merged 4 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ For details about compatibility between different releases, see the **Commitment

### Added

- Support for managed gateways through The Things Gateway Controller.
- Support for managed gateways and claiming through The Things Gateway Controller.
- Support for The Things Industries gateway protocol. This is adds a new pair of ports to Gateway Server: `1889` for Envoy or Traefik terminated TLS mutual authentication, and `8889` for The Things Stack terminated TLS mutual authentication.

### Changed
Expand Down
1 change: 1 addition & 0 deletions api/ttn/lorawan/v3/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3100,6 +3100,7 @@ DEPRECATED: This message is deprecated and will be removed in a future version o
| ----- | ---- | ----- | ----------- |
| `eui` | [`bytes`](#bytes) | | |
| `supports_claiming` | [`bool`](#bool) | | |
| `is_managed` | [`bool`](#bool) | | Indicates whether the gateway is a managed gateway. If true, when the gateway is successfully claimed, it can be managed with ManagedGatewayConfigurationService. |

#### Field Rules

Expand Down
4 changes: 4 additions & 0 deletions api/ttn/lorawan/v3/api.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -24696,6 +24696,10 @@
},
"supports_claiming": {
"type": "boolean"
},
"is_managed": {
"type": "boolean",
"description": "Indicates whether the gateway is a managed gateway.\nIf true, when the gateway is successfully claimed, it can be managed with ManagedGatewayConfigurationService."
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions api/ttn/lorawan/v3/deviceclaimingserver.proto
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ message GetInfoByGatewayEUIResponse {
}
];
bool supports_claiming = 2;
// Indicates whether the gateway is a managed gateway.
// If true, when the gateway is successfully claimed, it can be managed with ManagedGatewayConfigurationService.
bool is_managed = 3;
}

// The GatewayClaimingServer service support claiming and managing gateway claims.
Expand Down
24 changes: 21 additions & 3 deletions config/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3923,13 +3923,22 @@
"file": "ttjs.go"
}
},
"error:pkg/deviceclaimingserver/gateways/ttgc:not_implemented": {
"error:pkg/deviceclaimingserver/gateways/ttgc:dial_gateway_server": {
"translations": {
"en": "not implemented"
"en": "dial Gateway Gerver"
},
"description": {
"package": "pkg/deviceclaimingserver/gateways/ttgc",
"file": "ttgc.go"
"file": "root_ca.go"
}
},
"error:pkg/deviceclaimingserver/gateways/ttgc:gateway_server_tls": {
"translations": {
"en": "establish TLS connection with Gateway Server"
},
"description": {
"package": "pkg/deviceclaimingserver/gateways/ttgc",
"file": "root_ca.go"
}
},
"error:pkg/deviceclaimingserver/gateways:invalid_upstream": {
Expand All @@ -3941,6 +3950,15 @@
"file": "gateways.go"
}
},
"error:pkg/deviceclaimingserver/gateways:ttgc_not_enabled": {
"translations": {
"en": "TTGC is not enabled"
},
"description": {
"package": "pkg/deviceclaimingserver/gateways",
"file": "gateways.go"
}
},
"error:pkg/deviceclaimingserver:claim gateway": {
"translations": {
"en": "claim gateway"
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ require (
go.packetbroker.org/api/mapping/v2 v2.3.2
go.packetbroker.org/api/routing v1.9.2
go.packetbroker.org/api/v3 v3.17.1
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240723094213-b40a14f3b543
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240729145607-ea516688afbd
go.thethings.industries/pkg/ca v0.0.0-20240723151912-b9bb4097ae6c
go.thethings.network/lorawan-application-payload v0.0.0-20220125153912-1198ff1e403e
go.thethings.network/lorawan-stack-legacy/v2 v2.1.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,8 @@ go.packetbroker.org/api/routing v1.9.2 h1:J4+4vYZxa60UWC70Y9yy7sktU7DXaAp9Q13Bfq
go.packetbroker.org/api/routing v1.9.2/go.mod h1:kd2K7gieDI35YfPA8/zDmLX3qiKPuXia/MA77BEAeUA=
go.packetbroker.org/api/v3 v3.17.1 h1:LcyFPUGqVubGWMvQ16tZlQIKd+noGx7urzEYhSLiEQA=
go.packetbroker.org/api/v3 v3.17.1/go.mod h1:6bVbdWAYLnvZ5kgXxA7GBQvZTN7vxI0DoF1Di1NoAT4=
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240723094213-b40a14f3b543 h1:CpDA1J3O/krqQrPypf+ePIV5xiLyy9RIayLXRnxiDSI=
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240723094213-b40a14f3b543/go.mod h1:2+WsMwIunNLh22oauBzGL56JazE3UY34W1fstqEbacw=
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240729145607-ea516688afbd h1:FvD516hdD/iWqoS20SFdcoiUgwRJP3egNXNiN+Ux2d0=
go.thethings.industries/pkg/api/gen/tti/gateway v0.0.0-20240729145607-ea516688afbd/go.mod h1:2+WsMwIunNLh22oauBzGL56JazE3UY34W1fstqEbacw=
go.thethings.industries/pkg/ca v0.0.0-20240723151912-b9bb4097ae6c h1:QkZ+O889SvaXAoJdIu2hyrAXvlIfuHDWOmlpOh97RHg=
go.thethings.industries/pkg/ca v0.0.0-20240723151912-b9bb4097ae6c/go.mod h1:89OU623VYKW9i3W4CZgIGFmtgb/jsN8JV2PAuCsj+7w=
go.thethings.network/lorawan-application-payload v0.0.0-20220125153912-1198ff1e403e h1:TWGQ3lh7gI2W5hnb6qPdpoAa0d7s/XPwvgf2VVCMJaY=
Expand Down
2 changes: 1 addition & 1 deletion pkg/deviceclaimingserver/deviceclaimingserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func New(c *component.Component, conf *Config, opts ...Option) (*DeviceClaimingS
}

if dcs.grpc.gatewayClaimingServer == nil {
upstream, err := gateways.NewUpstream(ctx, conf.GatewayClaimingServerConfig)
upstream, err := gateways.NewUpstream(ctx, c, conf.GatewayClaimingServerConfig)
if err != nil {
return nil, err
}
Expand Down
42 changes: 35 additions & 7 deletions pkg/deviceclaimingserver/gateways/gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,39 @@ package gateways

import (
"context"
"crypto/tls"
"strings"

"go.thethings.network/lorawan-stack/v3/pkg/config"
"go.thethings.network/lorawan-stack/v3/pkg/config/tlsconfig"
"go.thethings.network/lorawan-stack/v3/pkg/deviceclaimingserver/gateways/ttgc"
dcstypes "go.thethings.network/lorawan-stack/v3/pkg/deviceclaimingserver/types"
"go.thethings.network/lorawan-stack/v3/pkg/errors"
"go.thethings.network/lorawan-stack/v3/pkg/types"
)

// Component is the interface to the component.
type Component interface {
GetBaseConfig(context.Context) config.ServiceBase
GetTLSClientConfig(context.Context, ...tlsconfig.Option) (*tls.Config, error)
}

// Config is the configuration for the Gateway Claiming Server.
type Config struct {
CreateOnNotFound bool `name:"create-on-not-found" description:"DEPRECATED"` // nolint:lll
DefaultGatewayServerAddress string `name:"default-gateway-server-address" description:"The default Gateway Server Address"` // nolint:lll
Upstreams map[string][]string `name:"upstreams" description:"Map of upstream type and the supported Gateway EUI ranges"` // nolint:lll
TTGC ttgc.Config `name:"ttgc"`
}

var errInvalidUpstream = errors.DefineInvalidArgument("invalid_upstream", "upstream `{name}` is invalid")
var (
errInvalidUpstream = errors.DefineInvalidArgument("invalid_upstream", "upstream `{name}` is invalid")
errTTGCNotEnabled = errors.DefineFailedPrecondition("ttgc_not_enabled", "TTGC is not enabled")
)

// ParseGatewayEUIRanges parses the configured upstream map and returns map of ranges.
func ParseGatewayEUIRanges(config map[string][]string) (map[string][]dcstypes.EUI64Range, error) {
res := make(map[string][]dcstypes.EUI64Range, len(config))
for host, ranges := range config {
func ParseGatewayEUIRanges(conf map[string][]string) (map[string][]dcstypes.EUI64Range, error) {
res := make(map[string][]dcstypes.EUI64Range, len(conf))
for host, ranges := range conf {
res[host] = make([]dcstypes.EUI64Range, 0, len(ranges))
for _, val := range ranges {
var r dcstypes.EUI64Range
Expand Down Expand Up @@ -76,7 +87,9 @@ type Claimer interface {
// Claim claims a gateway.
Claim(ctx context.Context, eui types.EUI64, ownerToken string, clusterAddress string) error
// Unclaim unclaims a gateway.
Unclaim(context.Context, types.EUI64, string) error
Unclaim(ctx context.Context, eui types.EUI64) error
// IsManagedGateway returns true if the gateway is a managed gateway.
IsManagedGateway(ctx context.Context, eui types.EUI64) (bool, error)
}

// rangeClaimer supports claiming a range of EUIs.
Expand All @@ -93,6 +106,7 @@ type Upstream struct {
// NewUpstream returns a new upstream based on the provided configuration.
func NewUpstream(
ctx context.Context,
c Component,
conf Config,
opts ...Option,
) (*Upstream, error) {
Expand All @@ -107,6 +121,17 @@ func NewUpstream(
if err != nil {
return nil, err
}

// Implicitly add TTGC if it is enabled and not already configured.
ttgcConf := c.GetBaseConfig(ctx).TTGC
if _, ttgcAdded := hosts["ttgc"]; ttgcConf.Enabled && !ttgcAdded {
ttgcRanges := make([]dcstypes.EUI64Range, len(ttgcConf.GatewayEUIs))
for i, prefix := range ttgcConf.GatewayEUIs {
ttgcRanges[i] = dcstypes.RangeFromEUI64Prefix(prefix)
}
hosts["ttgc"] = ttgcRanges
}

// Setup upstream table.
for name, ranges := range hosts {
if len(ranges) == 0 || name == "" {
Expand All @@ -115,7 +140,10 @@ func NewUpstream(
var claimer Claimer
switch name {
case "ttgc":
claimer, err = conf.TTGC.NewClient(ctx)
if !ttgcConf.Enabled {
return nil, errTTGCNotEnabled.New()
}
claimer, err = ttgc.New(ctx, c, ttgcConf)
if err != nil {
return nil, err
}
Expand Down
40 changes: 30 additions & 10 deletions pkg/deviceclaimingserver/gateways/gateways_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ package gateways_test
import (
"testing"

"go.thethings.network/lorawan-stack/v3/pkg/component"
componenttest "go.thethings.network/lorawan-stack/v3/pkg/component/test"
"go.thethings.network/lorawan-stack/v3/pkg/config"
"go.thethings.network/lorawan-stack/v3/pkg/config/tlsconfig"
"go.thethings.network/lorawan-stack/v3/pkg/deviceclaimingserver/gateways"
"go.thethings.network/lorawan-stack/v3/pkg/deviceclaimingserver/gateways/ttgc"
dcstypes "go.thethings.network/lorawan-stack/v3/pkg/deviceclaimingserver/types"
"go.thethings.network/lorawan-stack/v3/pkg/errors"
"go.thethings.network/lorawan-stack/v3/pkg/ttgc"
"go.thethings.network/lorawan-stack/v3/pkg/types"
"go.thethings.network/lorawan-stack/v3/pkg/util/test"
"go.thethings.network/lorawan-stack/v3/pkg/util/test/assertions/should"
Expand All @@ -31,6 +35,25 @@ func TestUpstream(t *testing.T) {

a, ctx := test.New(t)

c := componenttest.NewComponent(t, &component.Config{
ServiceBase: config.ServiceBase{
TTGC: ttgc.Config{
Enabled: true,
GatewayEUIs: []types.EUI64Prefix{
{
EUI64: types.EUI64{0x58, 0xa0, 0xcb, 0xff, 0xfe, 0x80, 0x00, 0x00},
Length: 48,
},
},
TLS: tlsconfig.ClientAuth{
Source: "file",
Certificate: "testdata/client.pem",
Key: "testdata/client-key.pem",
},
},
},
})

// Invalid ranges.
ranges := map[string][]string{"ttgc": {"&S(FU*)"}}
euiPrefixes, err := gateways.ParseGatewayEUIRanges(ranges)
Expand Down Expand Up @@ -85,28 +108,25 @@ func TestUpstream(t *testing.T) {
})

// Invalid configurations
config := gateways.Config{
conf := gateways.Config{
Upstreams: map[string][]string{"ttgc": {"&S(FU*)"}},
TTGC: ttgc.Config{},
}
upstream, err := gateways.NewUpstream(ctx, config)
upstream, err := gateways.NewUpstream(ctx, c, conf)
a.So(errors.IsInvalidArgument(err), should.BeTrue)
a.So(upstream, should.BeNil)

config = gateways.Config{
conf = gateways.Config{
Upstreams: map[string][]string{"unsupported": {"58A0CBFFFE800000/48"}},
TTGC: ttgc.Config{},
}
upstream, err = gateways.NewUpstream(ctx, config)
upstream, err = gateways.NewUpstream(ctx, c, conf)
a.So(errors.IsInvalidArgument(err), should.BeTrue)
a.So(upstream, should.BeNil)

// Valid Configuration
config = gateways.Config{
conf = gateways.Config{
Upstreams: map[string][]string{"ttgc": {"58A0CBFFFE800000/48"}},
TTGC: ttgc.Config{},
}
upstream, err = gateways.NewUpstream(ctx, config)
upstream, err = gateways.NewUpstream(ctx, c, conf)
a.So(err, should.BeNil)
a.So(upstream, should.NotBeNil)

Expand Down
28 changes: 28 additions & 0 deletions pkg/deviceclaimingserver/gateways/testdata/client-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDF+is3SbxVrjeO
yooAeJfjAD9GylMI5Z4cfHjPgeTf2bZlfVnmx+q5rdrN6B/cQo1BEIqFHZ9B6oqx
CZUgBBg9yZx12XjQk4kWvGhEnuHfJI3c188iZdUt6aJHITKaGGkbu6JJzaJ+eUl+
pa4Ghae4gsP5qOgsp03LdSAZXByeP9E1nFu9MR1lJCfI2sBLoHLEIh3pA6YPhRvL
/aPBeCdKqnTVce61YnXxQQVHrA82smeICHRvx1KQWkvN7Y0icDSBh74vsRaaO+zP
suHTR5EmpmqNX5VZosoUrNCQHddAvQwBGZv/ULzykVPInKAzvHAnAKGyYmwdOrJM
fAVOQl3tAgMBAAECggEBALLy67kv1yKDNQjGnnLKjk/LW2a7Xs697mrFP9YhDSYh
fjLCWU63Cb4IHazc0l+fcFqNfwfPvLIyNGbNyJOF3/uJjvkfN4sgsFtytbTBAF1Y
hzpFf58R+N1lPx+YLEsJIYjF021uiCBVtU7apzCSAwZOfKHgQOyL1U/AcOE7V0rZ
v7efhQCSDJ76RAY1FuUDw8vk4kevWmWbjeVOoxnMjKfhOwL3Tfm8QXfc3USCv7Xk
85Od8mXxhrxRQLIk1RBYxhUj8uWSK0IvDE/jbyFEZQK10D8LnNWwbk1dg26nE3xu
oQbqUcF05ujlsDFGWCZ40d2mlu0Na/pskyjxu/9GQykCgYEA9lr8kVj+mTNamyPF
/ltc6l/+ofYDaMqZctZdYieZXg3J/6HN7y/xSDS5TBn4TVX7JvSw5rzoY3spzsO/
49ZbCR4bTxM+ZdVZkkLrtNzVonVAiSSLWpK+1oCPOO+1ULIUMmJanJHKkQ5R33iH
2BZaDSC2J11uJc1E+moXnr+YMu8CgYEAzbpUBcB3bmsG14kHh2PEcO03Gm9v7wuF
nPEcrANVuwAxrow/keM+oyKaj3g5EUvlZDMwh6PvlhOo3Xtp5gS+RRfkMVLcQPXd
Apf7B6OEPL54rwrcoZbxEl2+Hf3UUl9SIKastMCdtHzvLmCYh+12eM/R9Lp1D6DL
3sWQRw62DOMCgYEA1o7L5fLyWo9lXDS93hfIRsAwTvKqaXv6RQ/56ODALDAqO5+6
cZT5uX9h2qvLm99Ei9sUrwDcDLhZ4yCNYWtxgfFcq3QBJkO4bTAnhS/ISGOCP286
hznDR6JUGqx657sQ6AjNDgvTtp4YJF8fQM3GxCQ3QPWYVwf+CXKY+8O2VLUCgYEA
i75mtqV/OvTeZ+f/wjrFxEOOK5nIueLktq+dX0bApE7EcKF5yPpIoP2vaYcrlJEu
V7rh2zFDXHksOo5LZ+CO8lYBPnPfgwy/PLTJ4u1ytORZC+Xf6q+iP2yH6M1zvSRc
oCs3o2w3c9NtkN4ynhpyYCwinQ9O1vfNpBwlHe9jQCsCgYB3KRWR4UGc2faQbBE9
fMmbdTkA79gkwvr1q4pRQlCGnOxeIE4vfR4RCkfRkBJimMSI2sNDHFiDQZ8DJq6Y
3cwaL4uUSo9MEdY2ZZxaGgxWaEu4DH+ZV0lJv/RDgTbjD0xwomxXOn/+9UM17Nf9
KYSfdCWcjW0kxJJ7PO4n8d65rQ==
-----END PRIVATE KEY-----
26 changes: 26 additions & 0 deletions pkg/deviceclaimingserver/gateways/testdata/client.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWzCCAsOgAwIBAgIQNsTUWUKitSTLD+uN4zzpuzANBgkqhkiG9w0BAQsFADCB
hTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMS0wKwYDVQQLDCRqb2hh
bkBKb2hhbi0yLmxvY2FsIChKb2hhbiBTdG9ra2luZykxNDAyBgNVBAMMK21rY2Vy
dCBqb2hhbkBKb2hhbi0yLmxvY2FsIChKb2hhbiBTdG9ra2luZykwHhcNMTkwNjAx
MDAwMDAwWhcNMzAwOTAzMTYyMDU0WjBYMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxv
cG1lbnQgY2VydGlmaWNhdGUxLTArBgNVBAsMJGpvaGFuQEpvaGFuLTIubG9jYWwg
KEpvaGFuIFN0b2traW5nKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMX6KzdJvFWuN47KigB4l+MAP0bKUwjlnhx8eM+B5N/ZtmV9WebH6rmt2s3oH9xC
jUEQioUdn0HqirEJlSAEGD3JnHXZeNCTiRa8aESe4d8kjdzXzyJl1S3pokchMpoY
aRu7oknNon55SX6lrgaFp7iCw/mo6CynTct1IBlcHJ4/0TWcW70xHWUkJ8jawEug
csQiHekDpg+FG8v9o8F4J0qqdNVx7rVidfFBBUesDzayZ4gIdG/HUpBaS83tjSJw
NIGHvi+xFpo77M+y4dNHkSamao1flVmiyhSs0JAd10C9DAEZm/9QvPKRU8icoDO8
cCcAobJibB06skx8BU5CXe0CAwEAAaNzMHEwDgYDVR0PAQH/BAQDAgWgMB0GA1Ud
JQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB8GA1UdIwQY
MBaAFDzAUZ9AtGTILuMWdD2VfCm0D72DMBEGA1UdEQQKMAiCBjAwMDAwMTANBgkq
hkiG9w0BAQsFAAOCAYEAI8mhLKPl4qUlZ2g1vmVrAGTGc0M2dzs4Xp2gyys+puup
sP4pRPQnIrEJaZcI2mk/4TTOpyF1tmLGaZ0V/hMzf07I5vB/Kz+jdj0+3AGVixwR
+KehvHVn6njfcZqa3l4Q7pFWyQtb199M1XPwGkQSEzxthU7dKH/447T8HwKp3xoK
hKb3pNd0h0MXgGGhawHFP5AHpI0x05cWT5zLXu5nXnjYt9UKpPCUH6Htcofg33GX
Y3rj3KvUz9WHYw/6LE+LlKjUKLkCG8bq2qaTRSrJQh5qTJRldzqjJ4qa7A7hUYJN
qm+Wb/FIMIA/sdfdMEwGAWhkZJjZlYoGv3LU7QLIkaCWjRsTs1gRw2EVCo0mFJ6x
LRm0UDBIIr30fEkGhSk38EYiX3HbxkCF61HPehhzL4noMkoDAuMq+8gFRVDBHOlv
YiNn1Y22LBsFdoKkbqI3nI62sFvI8lXpKRrL34lndSCevVXOEUOeupDdD1XvHYHQ
0bPVWAqh/KAO8JMDauCa
-----END CERTIFICATE-----
54 changes: 54 additions & 0 deletions pkg/deviceclaimingserver/gateways/ttgc/root_ca.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright © 2024 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package ttgc provides functions to use The Things Gateway Controller.
package ttgc

import (
"context"
"crypto/tls"
"crypto/x509"
"net"

"go.thethings.network/lorawan-stack/v3/pkg/errors"
)

var (
errDialGatewayServer = errors.DefineAborted("dial_gateway_server", "dial Gateway Gerver")
errGatewayServerTLS = errors.DefineAborted(
"gateway_server_tls", "establish TLS connection with Gateway Server",
)
)

func (u *Upstream) getRootCA(ctx context.Context, address string) (*x509.Certificate, error) {
d := new(net.Dialer)
netConn, err := d.DialContext(ctx, "tcp", address)
if err != nil {
return nil, errDialGatewayServer.WithCause(err)
}
defer netConn.Close()

tlsConfig, err := u.GetTLSClientConfig(ctx)
if err != nil {
return nil, err
}
tlsConn := tls.Client(netConn, tlsConfig)
if err := tlsConn.HandshakeContext(ctx); err != nil {
return nil, errGatewayServerTLS.WithCause(err)
}

state := tlsConn.ConnectionState()
verifiedChain := state.VerifiedChains[0]
return verifiedChain[len(verifiedChain)-1], nil
}
Loading
Loading