Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions pkg/compose/config.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package compose

import (
"github.com/docker/cli/cli/config/configfile"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"crypto/x509"
"net/url"
"path/filepath"
"time"

"github.com/docker/cli/cli/config/configfile"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)

type (
Expand All @@ -20,6 +23,9 @@ type (
AppStoreFactoryFunc func(c *Config) (AppStore, error)
BlockSize int64
DBFilePath string

ProxyURL *url.URL
ProxyCerts *x509.CertPool
}
)

Expand Down
44 changes: 41 additions & 3 deletions pkg/compose/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path"

"github.com/containerd/containerd/content"
"github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"io"
"os"
"path"
)

type (
Expand Down Expand Up @@ -59,8 +62,43 @@ func NewLocalBlobProvider(fileProvider content.Store) BlobProvider {
}
}

type tokenProxyTripper struct {
base http.RoundTripper
host *url.URL
}

func (t tokenProxyTripper) RoundTrip(req *http.Request) (*http.Response, error) {
reqBodyClosed := false
if req.Body != nil {
defer func() {
if !reqBodyClosed {
req.Body.Close()
}
}()
}

req2 := req.Clone(req.Context())
req2.URL = t.host.JoinPath(req2.URL.Path)
req2.Host = t.host.Host

// req.Body is assumed to be closed by the base RoundTripper.
reqBodyClosed = true
return t.base.RoundTrip(req2)
}

func NewRemoteBlobProviderFromConfig(config *Config) BlobProvider {
client := NewHttpClient(config.ConnectTimeout, config.ReadTimeout)
if config.ProxyURL != nil {
tpt := tokenProxyTripper{
base: client.Transport,
host: config.ProxyURL,
}

if config.ProxyCerts != nil {
client.Transport.(*http.Transport).TLSClientConfig.RootCAs = config.ProxyCerts
}
client.Transport = tpt
}
authorizer := NewRegistryAuthorizer(config.DockerCfg, client)
resolver := NewResolver(authorizer, client)
return newRemoteBlobProvider(resolver)
Expand Down
34 changes: 31 additions & 3 deletions pkg/compose/v1/config.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package v1

import (
"crypto/x509"
"fmt"
"github.com/containerd/containerd/platforms"
dockercfg "github.com/docker/cli/cli/config"
"github.com/foundriesio/composeapp/pkg/compose"
"net/url"
"os"
"path"
"path/filepath"
"time"

"github.com/containerd/containerd/platforms"
dockercfg "github.com/docker/cli/cli/config"
"github.com/foundriesio/composeapp/pkg/compose"
)

type (
Expand Down Expand Up @@ -110,6 +113,29 @@ func NewDefaultConfig(options ...ConfigOpt) (*compose.Config, error) {
return nil, fmt.Errorf("failed to get file system stat; path: %s, err: %s", opts.StoreRoot, err.Error())
}

var proxyURL *url.URL
var proxyCerts *x509.CertPool

proxyEnv := os.Getenv("COMPOSE_APPS_PROXY")
if len(proxyEnv) > 0 {
proxyURL, err = url.Parse(proxyEnv)
if err != nil {
return nil, fmt.Errorf("invalid COMPOSE_APPS_PROXY: %s: %w", proxyEnv, err)
}

proxyCa := os.Getenv("COMPOSE_APPS_PROXY_CA")
if len(proxyCa) > 0 {
proxyCerts = x509.NewCertPool()

pemData, err := os.ReadFile(proxyCa)
if err != nil {
return nil, fmt.Errorf("unable to read COMPOSE_APPS_PROXY_CA: %w", err)
} else if ok := proxyCerts.AppendCertsFromPEM(pemData); !ok {
return nil, fmt.Errorf("failed to set COMPOSE_APPS_PROXY_CA: %w", err)
}
}
}

// Load docker config
dockerCfg, err := dockercfg.Load("")
if err != nil {
Expand All @@ -131,5 +157,7 @@ func NewDefaultConfig(options ...ConfigOpt) (*compose.Config, error) {
},
BlockSize: s.BlockSize,
DBFilePath: opts.UpdateDBPath,
ProxyURL: proxyURL,
ProxyCerts: proxyCerts,
}, nil
}