feat: download metadata on Scaleway using low source port

This feature allow to us use low source port <1024 to make a http calls.

Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>
Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Serge Logvinov 2022-02-16 18:15:59 +00:00 committed by Andrey Smirnov
parent 1800b4c707
commit d749643e7e
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
3 changed files with 41 additions and 8 deletions

2
go.mod
View File

@ -59,6 +59,7 @@ require (
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/gosuri/uiprogress v0.0.1 github.com/gosuri/uiprogress v0.0.1
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-getter v1.5.11 github.com/hashicorp/go-getter v1.5.11
github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.4.0 github.com/hashicorp/go-version v1.4.0
@ -188,7 +189,6 @@ require (
github.com/gosuri/uilive v0.0.4 // indirect github.com/gosuri/uilive v0.0.4 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-memdb v1.3.2 // indirect github.com/hashicorp/go-memdb v1.3.2 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect

View File

@ -24,6 +24,8 @@ import (
const ( const (
// ScalewayMetadataEndpoint is the local Scaleway endpoint. // ScalewayMetadataEndpoint is the local Scaleway endpoint.
ScalewayMetadataEndpoint = "http://169.254.42.42/conf?format=json" ScalewayMetadataEndpoint = "http://169.254.42.42/conf?format=json"
// ScalewayUserDataEndpoint is the local Scaleway endpoint for the config.
ScalewayUserDataEndpoint = "http://169.254.42.42/user_data/cloud-init"
) )
// Scaleway is the concrete type that implements the runtime.Platform interface. // Scaleway is the concrete type that implements the runtime.Platform interface.
@ -125,11 +127,10 @@ func (s *Scaleway) ParseMetadata(metadataConfig *instance.Metadata) (*runtime.Pl
// Configuration implements the runtime.Platform interface. // Configuration implements the runtime.Platform interface.
func (s *Scaleway) Configuration(ctx context.Context) ([]byte, error) { func (s *Scaleway) Configuration(ctx context.Context) ([]byte, error) {
log.Printf("fetching machine config from scaleway metadata server") log.Printf("fetching machine config from %q", ScalewayUserDataEndpoint)
instanceAPI := instance.NewMetadataAPI() machineConfigDl, err := download.Download(ctx, ScalewayUserDataEndpoint,
download.WithLowSrcPort())
machineConfigDl, err := instanceAPI.GetUserData("cloud-init")
if err != nil { if err != nil {
return nil, errors.ErrNoConfigSource return nil, errors.ErrNoConfigSource
} }

View File

@ -9,10 +9,14 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math/rand"
"net"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"time" "time"
"github.com/hashicorp/go-cleanhttp"
"github.com/talos-systems/go-retry/retry" "github.com/talos-systems/go-retry/retry"
) )
@ -21,6 +25,7 @@ const b64 = "base64"
type downloadOptions struct { type downloadOptions struct {
Headers map[string]string Headers map[string]string
Format string Format string
LowSrcPort bool
ErrorOnNotFound error ErrorOnNotFound error
ErrorOnEmptyResponse error ErrorOnEmptyResponse error
@ -57,6 +62,14 @@ func WithHeaders(headers map[string]string) Option {
} }
} }
// WithLowSrcPort sets low source port to download
// the config.
func WithLowSrcPort() Option {
return func(d *downloadOptions) {
d.LowSrcPort = true
}
}
// WithErrorOnNotFound provides specific error to return when response has HTTP 404 error. // WithErrorOnNotFound provides specific error to return when response has HTTP 404 error.
func WithErrorOnNotFound(e error) Option { func WithErrorOnNotFound(e error) Option {
return func(d *downloadOptions) { return func(d *downloadOptions) {
@ -130,6 +143,25 @@ func Download(ctx context.Context, endpoint string, opts ...Option) (b []byte, e
func download(req *http.Request, dlOpts *downloadOptions) (data []byte, err error) { func download(req *http.Request, dlOpts *downloadOptions) (data []byte, err error) {
client := &http.Client{} client := &http.Client{}
if dlOpts.LowSrcPort {
port := 100 + rand.Intn(512)
localTCPAddr, tcperr := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(port))
if tcperr != nil {
return nil, retry.ExpectedError(fmt.Errorf("resolving source tcp address: %s", tcperr.Error()))
}
d := (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
LocalAddr: localTCPAddr,
}).DialContext
client.Transport = cleanhttp.DefaultTransport()
client.Transport.(*http.Transport).DialContext = d
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
return data, retry.ExpectedError(err) return data, retry.ExpectedError(err)