Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit bf33fd0

Browse files
authored
Merge pull request #19 from eunomie/dd-proxy
chore: use Docker Desktop proxy if available
2 parents 00c5852 + 25765fd commit bf33fd0

File tree

8 files changed

+115
-17
lines changed

8 files changed

+115
-17
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/docker/index-cli-plugin
33
go 1.19
44

55
require (
6+
github.com/Microsoft/go-winio v0.5.2
67
github.com/anchore/packageurl-go v0.1.1-0.20220428202044-a072fa3cb6d7
78
github.com/anchore/stereoscope v0.0.0-20221006201143-d24c9d626b33
89
github.com/anchore/syft v0.62.1
@@ -46,7 +47,6 @@ require (
4647
github.com/Masterminds/goutils v1.1.1 // indirect
4748
github.com/Masterminds/semver/v3 v3.1.1 // indirect
4849
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
49-
github.com/Microsoft/go-winio v0.5.2 // indirect
5050
github.com/Microsoft/hcsshim v0.9.5 // indirect
5151
github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 // indirect
5252
github.com/acobaugh/osrelease v0.1.0 // indirect

internal/ddhttp/ddhttp.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package ddhttp
2+
3+
import (
4+
"context"
5+
"net"
6+
"net/http"
7+
"net/url"
8+
)
9+
10+
var transport http.RoundTripper
11+
12+
func init() {
13+
// Check if we can discuss with the proxy socket from Docker Desktop.
14+
// If we can, it doesn't necessarily mean there a configured proxy.
15+
// But we delegate that management to Docker Desktop: if the socket is open, we connect to it. Docker Desktop can
16+
// then send the requests to a proxy or not, but that's Docker Desktop scope.
17+
// If we can't connect to the socket, then just use plain default transport.
18+
if !isDesktopHTTPProxyAvailable() {
19+
transport = http.DefaultTransport
20+
return
21+
}
22+
23+
transport = &http.Transport{
24+
Proxy: http.ProxyURL(&url.URL{
25+
Scheme: "http",
26+
}),
27+
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
28+
return dialDesktopHTTPProxy()
29+
},
30+
}
31+
}
32+
33+
func isDesktopHTTPProxyAvailable() bool {
34+
c, err := dialDesktopHTTPProxy()
35+
if err != nil {
36+
return false
37+
}
38+
_ = c.Close()
39+
return true
40+
}
41+
42+
func DefaultClient() *http.Client {
43+
return &http.Client{
44+
Transport: transport,
45+
}
46+
}
47+
48+
func DefaultTransport() *http.Transport {
49+
if t, ok := transport.(*http.Transport); ok {
50+
return t
51+
}
52+
panic("could not get transport")
53+
}

internal/ddhttp/desktop_darwin.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ddhttp
2+
3+
import (
4+
"net"
5+
"os/user"
6+
"path"
7+
)
8+
9+
func dialDesktopHTTPProxy() (net.Conn, error) {
10+
current, err := user.Current()
11+
if err != nil {
12+
return nil, err
13+
}
14+
socket := path.Join(current.HomeDir, "Library/Containers/com.docker.docker/Data/httpproxy.sock")
15+
return net.Dial("unix", socket)
16+
}

internal/ddhttp/desktop_linux.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ddhttp
2+
3+
import (
4+
"net"
5+
"os/user"
6+
"path"
7+
)
8+
9+
func dialDesktopHTTPProxy() (net.Conn, error) {
10+
current, err := user.Current()
11+
if err != nil {
12+
return nil, err
13+
}
14+
socket := path.Join(current.HomeDir, ".docker/desktop/httpproxy.sock")
15+
return net.Dial("unix", socket)
16+
}

internal/ddhttp/desktop_windows.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ddhttp
2+
3+
import (
4+
"net"
5+
"time"
6+
7+
"github.com/Microsoft/go-winio"
8+
)
9+
10+
func dialDesktopHTTPProxy() (net.Conn, error) {
11+
timeout := time.Second
12+
return winio.DialPipe(`\\.\pipe\dockerHTTPProxy`, &timeout)
13+
}

query/base.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"encoding/json"
2323
"fmt"
2424
"io"
25-
"net/http"
2625
"sort"
2726
"strings"
2827

@@ -34,7 +33,7 @@ import (
3433
"olympos.io/encoding/edn"
3534

3635
"github.com/atomist-skills/go-skill"
37-
36+
"github.com/docker/index-cli-plugin/internal/ddhttp"
3837
"github.com/docker/index-cli-plugin/types"
3938
)
4039

@@ -94,7 +93,7 @@ func Detect(sb *types.Sbom, excludeSelf bool, workspace string, apiKey string) (
9493
func ForBaseImageInIndex(digest digest.Digest, workspace string, apiKey string) (*[]types.Image, error) {
9594
url := fmt.Sprintf("https://api.dso.docker.com/docker-images/chain-ids/%s.json", digest.String())
9695

97-
resp, err := http.Get(url)
96+
resp, err := ddhttp.DefaultClient().Get(url)
9897
if err != nil {
9998
return nil, errors.Wrapf(err, "failed to query index")
10099
}
@@ -243,7 +242,7 @@ func ForBaseImageInGraphQL(cfg *v1.ConfigFile) (*types.BaseImagesByDiffIdsQuery,
243242
}
244243

245244
url := "https://api.dso.docker.com/v1/graphql"
246-
client := graphql.NewClient(url, nil)
245+
client := graphql.NewClient(url, ddhttp.DefaultClient())
247246
variables := map[string]interface{}{
248247
"diffIds": diffIds,
249248
}
@@ -270,7 +269,7 @@ func ForBaseImageInGraphQL(cfg *v1.ConfigFile) (*types.BaseImagesByDiffIdsQuery,
270269

271270
func ForImageInGraphQL(sb *types.Sbom) (*types.ImageByDigestQuery, error) {
272271
url := "https://api.dso.docker.com/v1/graphql"
273-
client := graphql.NewClient(url, nil)
272+
client := graphql.NewClient(url, ddhttp.DefaultClient())
274273
variables := map[string]interface{}{
275274
"digest": sb.Source.Image.Digest,
276275
"os": sb.Source.Image.Platform.Os,

query/query.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@ import (
2424
"strings"
2525

2626
"github.com/hasura/go-graphql-client"
27-
28-
"github.com/docker/index-cli-plugin/internal"
29-
"github.com/docker/index-cli-plugin/types"
30-
3127
"github.com/pkg/errors"
3228
"olympos.io/encoding/edn"
3329

3430
"github.com/atomist-skills/go-skill"
31+
"github.com/docker/index-cli-plugin/internal"
32+
"github.com/docker/index-cli-plugin/internal/ddhttp"
33+
"github.com/docker/index-cli-plugin/types"
3534
)
3635

3736
type CveResult struct {
@@ -115,7 +114,7 @@ func query(query string, name string, workspace string, apiKey string) (*http.Re
115114
}
116115
query = fmt.Sprintf(`{:queries [{:name "query" :query %s}]}`, query)
117116
skill.Log.Debugf("Query %s", query)
118-
client := &http.Client{}
117+
client := ddhttp.DefaultClient()
119118
req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(query))
120119
if err != nil {
121120
return nil, errors.Wrapf(err, "failed to create http request")
@@ -139,7 +138,7 @@ func query(query string, name string, workspace string, apiKey string) (*http.Re
139138

140139
func ForVulnerabilitiesInGraphQL(sb *types.Sbom) (*types.VulnerabilitiesByPurls, error) {
141140
url := "https://api.dso.docker.com/v1/graphql"
142-
client := graphql.NewClient(url, nil)
141+
client := graphql.NewClient(url, ddhttp.DefaultClient())
143142

144143
purls := make([]string, 0)
145144
for _, p := range sb.Artifacts {

registry/save.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ import (
2626

2727
stereoscopeimage "github.com/anchore/stereoscope/pkg/image"
2828
"github.com/anchore/syft/syft/source"
29-
"github.com/atomist-skills/go-skill"
30-
"github.com/docker/cli/cli/command"
31-
"github.com/docker/distribution/reference"
32-
"github.com/docker/index-cli-plugin/internal"
3329
"github.com/dustin/go-humanize"
3430
"github.com/google/go-containerregistry/pkg/authn"
3531
"github.com/google/go-containerregistry/pkg/name"
@@ -41,6 +37,12 @@ import (
4137
"github.com/google/go-containerregistry/pkg/v1/tarball"
4238
"github.com/google/uuid"
4339
"github.com/pkg/errors"
40+
41+
"github.com/atomist-skills/go-skill"
42+
"github.com/docker/cli/cli/command"
43+
"github.com/docker/distribution/reference"
44+
"github.com/docker/index-cli-plugin/internal"
45+
"github.com/docker/index-cli-plugin/internal/ddhttp"
4446
)
4547

4648
type ImageId struct {
@@ -287,7 +289,7 @@ func SaveImage(image string, username string, password string, cli command.Cli)
287289
}, nil
288290
}
289291
// try remote image next
290-
desc, err := remote.Get(ref, WithAuth(username, password))
292+
desc, err := remote.Get(ref, WithAuth(username, password), remote.WithTransport(ddhttp.DefaultTransport()))
291293
if err != nil {
292294
return nil, errors.Wrapf(err, "failed to pull image: %s", image)
293295
}

0 commit comments

Comments
 (0)