Skip to content
Open
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
6 changes: 3 additions & 3 deletions internal/handlers/cargo_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ type cargoRepositoryCredentials struct {
password string
}

func NewCargoRegistryHandler(credentials config.Credentials) *CargoRegistryHandler {
func NewCargoRegistryHandler(credentials config.Credentials, client *http.Client) *CargoRegistryHandler {
handler := CargoRegistryHandler{
credentials: []cargoRepositoryCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, credential := range credentials {
Expand All @@ -68,7 +68,7 @@ func NewCargoRegistryHandler(credentials config.Credentials) *CargoRegistryHandl
if oidcCred, _, _ := handler.oidcRegistry.Register(credential, []string{"url"}, "cargo registry"); oidcCred != nil {
continue
}
} else if oidcCred, _ := oidc.CreateOIDCCredential(credential); oidcCred != nil {
} else if oidcCred, _ := oidc.CreateOIDCCredential(credential, client); oidcCred != nil {
continue
}

Expand Down
14 changes: 7 additions & 7 deletions internal/handlers/cargo_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestCargoRegistryHandler(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// valid request, should authenticate
url := validURL
Expand Down Expand Up @@ -108,7 +108,7 @@ func TestCargoRegistryHandlerWithHost(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// matching host should authenticate
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://cargo.example.com/some/path", nil)
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestCargoRegistryHandlerWithUsernamePassword(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// matching url should authenticate with basic auth
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://cargo.example.com/registry/crate", nil)
Expand All @@ -165,7 +165,7 @@ func TestCargoRegistryHandlerWithHostAndUsernamePassword(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// matching host should authenticate with basic auth
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://cargo.example.com/any/path", nil)
Expand All @@ -191,7 +191,7 @@ func TestCargoRegistryHandlerTokenTakesPrecedenceOverPassword(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// token should take precedence over username/password
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://cargo.example.com/registry/crate", nil)
Expand All @@ -207,7 +207,7 @@ func TestCargoRegistryHandlerIgnoresNoUrlOrHost(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// should not authenticate any request since no url or host was provided
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://anything.example.com/path", nil)
Expand All @@ -227,7 +227,7 @@ func TestCargoRegistryHandlerUrlScopingNotBypassedByHost(t *testing.T) {
},
}

handler := NewCargoRegistryHandler(credentials)
handler := NewCargoRegistryHandler(credentials, testOIDCClient)

// in-scope path should authenticate
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://cargo.example.com/myorg/crate", nil)
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/composer.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ type composerCredentials struct {
}

// NewComposerHandler returns a new ComposerHandler.
func NewComposerHandler(creds config.Credentials) *ComposerHandler {
func NewComposerHandler(creds config.Credentials, client *http.Client) *ComposerHandler {
handler := ComposerHandler{
credentials: []composerCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/composer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestComposerHandler(t *testing.T) {
"token": "",
},
}
handler := NewComposerHandler(credentials)
handler := NewComposerHandler(credentials, testOIDCClient)

req := httptest.NewRequestWithContext(t.Context(), "GET", "https://phpreg.bigco.com/somepkg", nil)
req = handleRequestAndClose(handler, req, nil)
Expand Down
16 changes: 10 additions & 6 deletions internal/handlers/docker_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type ecrClient interface {
GetAuthorizationToken(ctx context.Context, input *ecr.GetAuthorizationTokenInput, optFns ...func(*ecr.Options)) (*ecr.GetAuthorizationTokenOutput, error)
}

type getECRClient func(ctx context.Context, region, keyID, secretKey string) (ecrClient, error)
type getECRClient func(ctx context.Context, region, keyID, secretKey string, client *http.Client) (ecrClient, error)

// DockerRegistryHandler handles requests to Docker registries, adding auth.
type DockerRegistryHandler struct {
Expand All @@ -39,11 +39,12 @@ type DockerRegistryHandler struct {
}

// NewDockerRegistryHandler returns a new DockerRegistryHandler.
func NewDockerRegistryHandler(creds config.Credentials, transport http.RoundTripper, getECRClient getECRClient) *DockerRegistryHandler {
func NewDockerRegistryHandler(creds config.Credentials, client *http.Client, getECRClient getECRClient) *DockerRegistryHandler {
oidcRegistry := oidc.NewOIDCRegistry(client)
handler := DockerRegistryHandler{
credentials: []*dockerRegistryCredentials{},
transport: transport,
oidcRegistry: oidc.NewOIDCRegistry(),
transport: client.Transport,
oidcRegistry: oidcRegistry,
}

if getECRClient == nil {
Expand All @@ -69,6 +70,7 @@ func NewDockerRegistryHandler(creds config.Credentials, transport http.RoundTrip
registry: registry,
username: cred.GetString("username"),
password: cred.GetString("password"),
httpClient: client,
getECRClient: getECRClient,
}
handler.credentials = append(handler.credentials, registryCred)
Expand Down Expand Up @@ -147,11 +149,12 @@ func (h *DockerRegistryHandler) HandleRequest(req *http.Request, proxyCtx *gopro
return req, nil
}

func defaultGetECRClient(ctx context.Context, region, keyID, secretKey string) (ecrClient, error) {
func defaultGetECRClient(ctx context.Context, region, keyID, secretKey string, client *http.Client) (ecrClient, error) {
cfg, err := awsconfig.LoadDefaultConfig(
ctx,
awsconfig.WithRegion(region),
awsconfig.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(keyID, secretKey, "")),
awsconfig.WithHTTPClient(client),
)
if err != nil {
return nil, err
Expand All @@ -166,6 +169,7 @@ type dockerRegistryCredentials struct {
password string
ecrUsername string
ecrPassword string
httpClient *http.Client
getECRClient getECRClient
}

Expand All @@ -185,7 +189,7 @@ func (c *dockerRegistryCredentials) getECRCredentials(requestCtx context.Context
}

region := match[1]
ecrSvc, err := c.getECRClient(requestCtx, region, c.username, c.password)
ecrSvc, err := c.getECRClient(requestCtx, region, c.username, c.password, c.httpClient)
if err != nil {
logging.RequestLogf(proxyCtx, "! failed to initialize aws ecr client (key_id=%s)", c.username)
return false
Expand Down
38 changes: 36 additions & 2 deletions internal/handlers/docker_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package handlers
import (
"context"
"encoding/base64"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecr/types"
"github.com/elazarl/goproxy"
"github.com/stackrox/docker-registry-client/registry"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/dependabot/proxy/internal/config"
)
Expand Down Expand Up @@ -60,15 +63,17 @@ func TestDockerRegistryHandler(t *testing.T) {
},
}
mockECR := &mockECRClient{user: ecrDockerUser, token: ecrDockerPassword}
httpClient := &http.Client{Transport: &http.Transport{}, Timeout: testOIDCClient.Timeout}
var factoryContext context.Context
getECRClient := func(ctx context.Context, region, keyID, secretKey string) (ecrClient, error) {
getECRClient := func(ctx context.Context, region, keyID, secretKey string, client *http.Client) (ecrClient, error) {
factoryContext = ctx
assert.Same(t, httpClient, client, "ECR uses the bounded handler client")
assert.Equal(t, "us-east-2", region, "ecr region is parsed from the registry host")
assert.Equal(t, ecrKeyID, keyID, "docker username is used as the aws access key id")
assert.Equal(t, ecrSecretKey, secretKey, "docker password is used as the aws secret access key")
return mockECR, nil
}
handler := NewDockerRegistryHandler(credentials, &http.Transport{}, getECRClient)
handler := NewDockerRegistryHandler(credentials, httpClient, getECRClient)

// Regular private registry
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://registry.hub.docker.com/my-repo", nil)
Expand Down Expand Up @@ -164,6 +169,35 @@ func TestDockerRegistryHandler(t *testing.T) {
assert.Equal(t, "https://nexus.someco.com", trans.URL, "correct URL is set")
}

//nolint:gosec // The test credentials are intentionally fake fixtures.
func TestDefaultGetECRClientUsesInjectedHTTPClient(t *testing.T) {
transport := &recordingECRTransport{}
client := &http.Client{Transport: transport, Timeout: testOIDCClient.Timeout}

ecrClient, err := defaultGetECRClient(t.Context(), "us-east-2", "access-key", "secret-key", client)
require.NoError(t, err)
_, err = ecrClient.GetAuthorizationToken(t.Context(), &ecr.GetAuthorizationTokenInput{})
require.NoError(t, err)

require.NotNil(t, transport.request)
assert.Equal(t, http.MethodPost, transport.request.Method)
assert.Equal(t, "api.ecr.us-east-2.amazonaws.com", transport.request.URL.Host)
}

type recordingECRTransport struct {
request *http.Request
}

func (t *recordingECRTransport) RoundTrip(req *http.Request) (*http.Response, error) {
t.request = req
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader(`{"authorizationData":[]}`)),
Header: make(http.Header),
Request: req,
}, nil
}

type mockECRClient struct {
user string
token string
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/goproxy_server_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ type goProxyServerCredentials struct {
}

// NewGoProxyServerHandler returns a new GoProxyServerHandler.
func NewGoProxyServerHandler(creds config.Credentials) *GoProxyServerHandler {
func NewGoProxyServerHandler(creds config.Credentials, client *http.Client) *GoProxyServerHandler {
handler := GoProxyServerHandler{
credentials: []goProxyServerCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/goproxy_server_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestGoProxyHandler(t *testing.T) {
"password": deltaForcePassword,
},
}
handler := NewGoProxyServerHandler(credentials)
handler := NewGoProxyServerHandler(credentials, testOIDCClient)

req := httptest.NewRequestWithContext(t.Context(), "GET", "https://corp.dependabot.com/packages/somepkg", nil)
req = handleRequestAndClose(handler, req, nil)
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/helm_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ type helmRegistryCredentials struct {
}

// NewHelmRegistryHandler returns a new HelmRegistryHandler.
func NewHelmRegistryHandler(creds config.Credentials) *HelmRegistryHandler {
func NewHelmRegistryHandler(creds config.Credentials, client *http.Client) *HelmRegistryHandler {
handler := HelmRegistryHandler{
credentials: []helmRegistryCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/helm_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestHelmRegistryHandler(t *testing.T) {
"password": bigCoPassword,
},
}
handler := NewHelmRegistryHandler(credentials)
handler := NewHelmRegistryHandler(credentials, testOIDCClient)

req := httptest.NewRequestWithContext(t.Context(), "GET", "https://helmreg.bigco.com/some_chart", nil)
req = handleRequestAndClose(handler, req, nil)
Expand Down
6 changes: 3 additions & 3 deletions internal/handlers/hex_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ type hexRepositoryCredentials struct {
authKey string
}

func NewHexRepositoryHandler(creds config.Credentials) *HexRepositoryHandler {
func NewHexRepositoryHandler(creds config.Credentials, client *http.Client) *HexRepositoryHandler {
handler := HexRepositoryHandler{
credentials: []hexRepositoryCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand All @@ -43,7 +43,7 @@ func NewHexRepositoryHandler(creds config.Credentials) *HexRepositoryHandler {
if oidcCred, _, _ := handler.oidcRegistry.Register(cred, []string{"url"}, "hex repository"); oidcCred != nil {
continue
}
} else if oidcCred, _ := oidc.CreateOIDCCredential(cred); oidcCred != nil {
} else if oidcCred, _ := oidc.CreateOIDCCredential(cred, client); oidcCred != nil {
continue
}

Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/hex_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestHexRepositoryHandler(t *testing.T) {

validPath := "/repos/my_wonderful_repo/version"

handler := NewHexRepositoryHandler(credentials)
handler := NewHexRepositoryHandler(credentials, testOIDCClient)

// valid request, should authenticate
url := validConfigUrl + validPath
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/maven_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ type mavenRepositoryCredentials struct {
}

// NewMavenRepositoryHandler returns a new MavenRepositoryHandler.
func NewMavenRepositoryHandler(creds config.Credentials) *MavenRepositoryHandler {
func NewMavenRepositoryHandler(creds config.Credentials, client *http.Client) *MavenRepositoryHandler {
handler := MavenRepositoryHandler{
credentials: []mavenRepositoryCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/maven_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestMavenRepositoryHandler(t *testing.T) {
"password": deltaForcePassword,
},
}
handler := NewMavenRepositoryHandler(credentials)
handler := NewMavenRepositoryHandler(credentials, testOIDCClient)

req := httptest.NewRequestWithContext(t.Context(), "GET", "https://corp.dependabot.com/packages/somepkg", nil)
req = handleRequestAndClose(handler, req, nil)
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/npm_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ type npmRegistryCredentials struct {
}

// NewNPMRegistryHandler returns a new NPMRegistryHandler,
func NewNPMRegistryHandler(creds config.Credentials) *NPMRegistryHandler {
func NewNPMRegistryHandler(creds config.Credentials, client *http.Client) *NPMRegistryHandler {
handler := NPMRegistryHandler{
credentials: []npmRegistryCredentials{},
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/npm_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestNPMRegistryHandler(t *testing.T) {
"token": privateRegToken,
},
}
handler := NewNPMRegistryHandler(credentials)
handler := NewNPMRegistryHandler(credentials, testOIDCClient)

req := httptest.NewRequestWithContext(t.Context(), "GET", "https://registry.npmjs.org/private-package", nil)
req = handleRequestAndClose(handler, req, nil)
Expand Down Expand Up @@ -104,7 +104,7 @@ func TestNPMRegistryHandler_SameHostDifferentPaths(t *testing.T) {
"token": teamBToken,
},
}
handler := NewNPMRegistryHandler(credentials)
handler := NewNPMRegistryHandler(credentials, testOIDCClient)

// Request to team-a path should use team-a token
req := httptest.NewRequestWithContext(t.Context(), "GET", "https://artifactory.example.com/api/npm/team-a-npm/@scope/pkg", nil)
Expand Down
4 changes: 2 additions & 2 deletions internal/handlers/nuget_feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ type nugetDiscoveryAuth struct {
}

// NewNugetFeedHandler returns a new NugetFeedHandler.
func NewNugetFeedHandler(creds config.Credentials) *NugetFeedHandler {
func NewNugetFeedHandler(creds config.Credentials, client *http.Client) *NugetFeedHandler {
handler := NugetFeedHandler{
credentials: []nugetFeedCredentials{},
credentialURLs: make(map[string]struct{}),
discoverySourceURLs: make(map[string]struct{}),
oidcRegistry: oidc.NewOIDCRegistry(),
oidcRegistry: oidc.NewOIDCRegistry(client),
}

for _, cred := range creds {
Expand Down
Loading
Loading