From f6f3ccb86a673c18cd27db4629f9b260772fee07 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Tue, 8 Sep 2015 22:25:22 +0200 Subject: [PATCH 1/2] Added environment variable to change the Scaleway Metadata URL --- pkg/api/api.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/api/api.go b/pkg/api/api.go index a70569777e..899e160ad9 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -1719,6 +1719,9 @@ func (s *ScalewayAPI) DisableAccountAPI() { // EnableMetadataAPI enable metadataAPI func (s *ScalewayAPI) EnableMetadataAPI() { s.APIUrl = MetadataAPI + if os.Getenv("SCW_METADATA_URL") != "" { + s.APIUrl = os.Getenv("SCW_METADATA_URL") + } s.isMetadata = true } From 145e04aa1174e7246d552916fbe9910c7deb2726 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Tue, 8 Sep 2015 23:03:44 +0200 Subject: [PATCH 2/2] Now contacting metadata API using privileged source ports (fix #174) --- pkg/api/api.go | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 899e160ad9..04d6264edf 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -13,6 +13,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "net/http" "net/url" "os" @@ -20,6 +21,7 @@ import ( "strings" "text/tabwriter" "text/template" + "time" log "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" "github.com/scaleway/scaleway-cli/vendor/github.com/moul/anonuuid" @@ -56,9 +58,11 @@ type ScalewayAPI struct { // Cache is used to quickly resolve identifiers from names Cache *ScalewayCache - client *http.Client - anonuuid anonuuid.AnonUUID - isMetadata bool + client *http.Client + // Used when switching from an API to another + oldTransport *http.RoundTripper + anonuuid anonuuid.AnonUUID + isMetadata bool } // ScalewayAPIError represents a Scaleway API Error @@ -1716,18 +1720,54 @@ func (s *ScalewayAPI) DisableAccountAPI() { s.APIUrl = s.ComputeAPI } +func rootNetDial(network, addr string) (net.Conn, error) { + dialer := net.Dialer{ + Timeout: 10 * time.Second, + KeepAlive: 10 * time.Second, + } + + // bruteforce privileged ports + var localAddr net.Addr + var err error + for port := 1; port <= 1024; port++ { + localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf(":%d", port)) + + // this should never happen + if err != nil { + return nil, err + } + + dialer.LocalAddr = localAddr + + conn, err := dialer.Dial(network, addr) + + // if err is nil, dialer.Dial succeed, so let's go + // else, err != nil, but we don't care + if err == nil { + return conn, nil + } + } + // if here, all privileged ports were tried without success + return nil, fmt.Errorf("bind: permission denied, are you root ?") +} + // EnableMetadataAPI enable metadataAPI func (s *ScalewayAPI) EnableMetadataAPI() { s.APIUrl = MetadataAPI if os.Getenv("SCW_METADATA_URL") != "" { s.APIUrl = os.Getenv("SCW_METADATA_URL") } + s.oldTransport = &s.client.Transport + s.client.Transport = &http.Transport{ + Dial: rootNetDial, + } s.isMetadata = true } // DisableMetadataAPI disable metadataAPI func (s *ScalewayAPI) DisableMetadataAPI() { s.APIUrl = s.ComputeAPI + s.client.Transport = *s.oldTransport s.isMetadata = false }