@@ -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
@@ -1716,18 +1720,54 @@ func (s *ScalewayAPI) DisableAccountAPI() {
17161720 s .APIUrl = s .ComputeAPI
17171721}
17181722
1723+ func rootNetDial (network , addr string ) (net.Conn , error ) {
1724+ dialer := net.Dialer {
1725+ Timeout : 10 * time .Second ,
1726+ KeepAlive : 10 * time .Second ,
1727+ }
1728+
1729+ // bruteforce privileged ports
1730+ var localAddr net.Addr
1731+ var err error
1732+ for port := 1 ; port <= 1024 ; port ++ {
1733+ localAddr , err = net .ResolveTCPAddr ("tcp" , fmt .Sprintf (":%d" , port ))
1734+
1735+ // this should never happen
1736+ if err != nil {
1737+ return nil , err
1738+ }
1739+
1740+ dialer .LocalAddr = localAddr
1741+
1742+ conn , err := dialer .Dial (network , addr )
1743+
1744+ // if err is nil, dialer.Dial succeed, so let's go
1745+ // else, err != nil, but we don't care
1746+ if err == nil {
1747+ return conn , nil
1748+ }
1749+ }
1750+ // if here, all privileged ports were tried without success
1751+ return nil , fmt .Errorf ("bind: permission denied, are you root ?" )
1752+ }
1753+
17191754// EnableMetadataAPI enable metadataAPI
17201755func (s * ScalewayAPI ) EnableMetadataAPI () {
17211756 s .APIUrl = MetadataAPI
17221757 if os .Getenv ("SCW_METADATA_URL" ) != "" {
17231758 s .APIUrl = os .Getenv ("SCW_METADATA_URL" )
17241759 }
1760+ s .oldTransport = & s .client .Transport
1761+ s .client .Transport = & http.Transport {
1762+ Dial : rootNetDial ,
1763+ }
17251764 s .isMetadata = true
17261765}
17271766
17281767// DisableMetadataAPI disable metadataAPI
17291768func (s * ScalewayAPI ) DisableMetadataAPI () {
17301769 s .APIUrl = s .ComputeAPI
1770+ s .client .Transport = * s .oldTransport
17311771 s .isMetadata = false
17321772}
17331773
0 commit comments