diff --git a/proxy/interceptors/npm_registry.go b/proxy/interceptors/npm_registry.go index addf73f..6e9161f 100644 --- a/proxy/interceptors/npm_registry.go +++ b/proxy/interceptors/npm_registry.go @@ -37,6 +37,7 @@ type NpmRegistryInterceptor struct { } var _ proxy.Interceptor = (*NpmRegistryInterceptor)(nil) +var _ proxy.MITMDecider = (*NpmRegistryInterceptor)(nil) // NewNpmRegistryInterceptor creates a new NPM registry interceptor func NewNpmRegistryInterceptor( @@ -60,6 +61,15 @@ func (i *NpmRegistryInterceptor) Name() string { return "npm-registry-interceptor" } +func (i *NpmRegistryInterceptor) ShouldMITM(ctx *proxy.RequestContext) bool { + config := npmRegistryDomains.GetConfigForHostname(ctx.Hostname) + if config == nil { + return false + } + + return config.SupportedForAnalysis +} + // ShouldIntercept determines if this interceptor should handle the given request func (i *NpmRegistryInterceptor) ShouldIntercept(ctx *proxy.RequestContext) bool { return npmRegistryDomains.ContainsHostname(ctx.Hostname) diff --git a/proxy/interceptors/npm_registry_test.go b/proxy/interceptors/npm_registry_test.go new file mode 100644 index 0000000..9eda84f --- /dev/null +++ b/proxy/interceptors/npm_registry_test.go @@ -0,0 +1,54 @@ +package interceptors + +import ( + "testing" + + "github.com/safedep/pmg/proxy" + "github.com/stretchr/testify/assert" +) + +func TestNpmRegistryInterceptor_ShouldMITM(t *testing.T) { + interceptor := NewNpmRegistryInterceptor(nil, nil, nil, nil) + + tests := []struct { + name string + hostname string + wantMITM bool + }{ + {"public registry is MITM'd", "registry.npmjs.org", true}, + {"yarn registry is MITM'd", "registry.yarnpkg.com", true}, + {"github packages is NOT MITM'd", "npm.pkg.github.com", false}, + {"github blob storage is NOT MITM'd", "pkg-npm.githubusercontent.com", false}, + {"unknown registry is NOT MITM'd", "registry.example.com", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := &proxy.RequestContext{Hostname: tt.hostname} + assert.Equal(t, tt.wantMITM, interceptor.ShouldMITM(ctx)) + }) + } +} + +func TestNpmRegistryInterceptor_ShouldIntercept(t *testing.T) { + interceptor := NewNpmRegistryInterceptor(nil, nil, nil, nil) + + tests := []struct { + name string + hostname string + wantIntercept bool + }{ + {"public registry", "registry.npmjs.org", true}, + {"yarn registry", "registry.yarnpkg.com", true}, + {"github packages", "npm.pkg.github.com", true}, + {"github blob storage", "pkg-npm.githubusercontent.com", true}, + {"unknown registry", "registry.example.com", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := &proxy.RequestContext{Hostname: tt.hostname} + assert.Equal(t, tt.wantIntercept, interceptor.ShouldIntercept(ctx)) + }) + } +} diff --git a/proxy/interceptors/pypi_registry.go b/proxy/interceptors/pypi_registry.go index 5ba7a42..3ebad2a 100644 --- a/proxy/interceptors/pypi_registry.go +++ b/proxy/interceptors/pypi_registry.go @@ -38,6 +38,7 @@ type PypiRegistryInterceptor struct { } var _ proxy.Interceptor = (*PypiRegistryInterceptor)(nil) +var _ proxy.MITMDecider = (*PypiRegistryInterceptor)(nil) // NewPypiRegistryInterceptor creates a new PyPI registry interceptor func NewPypiRegistryInterceptor( @@ -61,6 +62,15 @@ func (i *PypiRegistryInterceptor) Name() string { return "pypi-registry-interceptor" } +func (i *PypiRegistryInterceptor) ShouldMITM(ctx *proxy.RequestContext) bool { + config := pypiRegistryDomains.GetConfigForHostname(ctx.Hostname) + if config == nil { + return false + } + + return config.SupportedForAnalysis +} + // ShouldIntercept determines if this interceptor should handle the given request func (i *PypiRegistryInterceptor) ShouldIntercept(ctx *proxy.RequestContext) bool { return pypiRegistryDomains.ContainsHostname(ctx.Hostname) diff --git a/proxy/interceptors/pypi_registry_test.go b/proxy/interceptors/pypi_registry_test.go new file mode 100644 index 0000000..d379a1c --- /dev/null +++ b/proxy/interceptors/pypi_registry_test.go @@ -0,0 +1,31 @@ +package interceptors + +import ( + "testing" + + "github.com/safedep/pmg/proxy" + "github.com/stretchr/testify/assert" +) + +func TestPypiRegistryInterceptor_ShouldMITM(t *testing.T) { + interceptor := NewPypiRegistryInterceptor(nil, nil, nil, nil) + + tests := []struct { + name string + hostname string + wantMITM bool + }{ + {"pypi files is MITM'd", "files.pythonhosted.org", true}, + {"pypi org is MITM'd", "pypi.org", true}, + {"test pypi is NOT MITM'd", "test.pypi.org", false}, + {"test pypi files is NOT MITM'd", "test-files.pythonhosted.org", false}, + {"unknown registry is NOT MITM'd", "registry.example.com", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := &proxy.RequestContext{Hostname: tt.hostname} + assert.Equal(t, tt.wantMITM, interceptor.ShouldMITM(ctx)) + }) + } +}