@@ -13,13 +13,15 @@ import (
1313 "encoding/json"
1414 "fmt"
1515 "io/ioutil"
16+ "net"
1617 "net/http"
1718 "net/url"
1819 "os"
1920 "sort"
2021 "strings"
2122 "text/tabwriter"
2223 "text/template"
24+ "time"
2325
2426 log "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus"
2527 "github.com/scaleway/scaleway-cli/vendor/github.com/moul/anonuuid"
@@ -56,9 +58,11 @@ type ScalewayAPI struct {
5658 // Cache is used to quickly resolve identifiers from names
5759 Cache * ScalewayCache
5860
59- client * http.Client
60- anonuuid anonuuid.AnonUUID
61- isMetadata bool
61+ client * http.Client
62+ // Used when switching from an API to another
63+ oldTransport * http.RoundTripper
64+ anonuuid anonuuid.AnonUUID
65+ isMetadata bool
6266}
6367
6468// ScalewayAPIError represents a Scaleway API Error
@@ -1720,15 +1724,54 @@ func (s *ScalewayAPI) DisableAccountAPI() {
17201724 s .APIUrl = s .ComputeAPI
17211725}
17221726
1727+ func rootNetDial (network , addr string ) (net.Conn , error ) {
1728+ dialer := net.Dialer {
1729+ Timeout : 10 * time .Second ,
1730+ KeepAlive : 10 * time .Second ,
1731+ }
1732+
1733+ // bruteforce privileged ports
1734+ var localAddr net.Addr
1735+ var err error
1736+ for port := 1 ; port <= 1024 ; port ++ {
1737+ localAddr , err = net .ResolveTCPAddr ("tcp" , fmt .Sprintf (":%d" , port ))
1738+
1739+ // this should never happen
1740+ if err != nil {
1741+ return nil , err
1742+ }
1743+
1744+ dialer .LocalAddr = localAddr
1745+
1746+ conn , err := dialer .Dial (network , addr )
1747+
1748+ // if err is nil, dialer.Dial succeed, so let's go
1749+ // else, err != nil, but we don't care
1750+ if err == nil {
1751+ return conn , nil
1752+ }
1753+ }
1754+ // if here, all privileged ports were tried without success
1755+ return nil , fmt .Errorf ("bind: permission denied, are you root ?" )
1756+ }
1757+
17231758// EnableMetadataAPI enable metadataAPI
17241759func (s * ScalewayAPI ) EnableMetadataAPI () {
17251760 s .APIUrl = MetadataAPI
1761+ if os .Getenv ("SCW_METADATA_URL" ) != "" {
1762+ s .APIUrl = os .Getenv ("SCW_METADATA_URL" )
1763+ }
1764+ s .oldTransport = & s .client .Transport
1765+ s .client .Transport = & http.Transport {
1766+ Dial : rootNetDial ,
1767+ }
17261768 s .isMetadata = true
17271769}
17281770
17291771// DisableMetadataAPI disable metadataAPI
17301772func (s * ScalewayAPI ) DisableMetadataAPI () {
17311773 s .APIUrl = s .ComputeAPI
1774+ s .client .Transport = * s .oldTransport
17321775 s .isMetadata = false
17331776}
17341777
0 commit comments