Skip to content

Commit ac74520

Browse files
authored
feat(misconf): resolve tf module from OpenTofu compatible registry (#6743)
1 parent 49678ae commit ac74520

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

pkg/iac/scanners/terraform/parser/module_retrieval.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ import (
55
"fmt"
66
"io/fs"
77

8-
resolvers2 "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser/resolvers"
8+
"github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser/resolvers"
99
)
1010

1111
type ModuleResolver interface {
12-
Resolve(context.Context, fs.FS, resolvers2.Options) (filesystem fs.FS, prefix string, downloadPath string, applies bool, err error)
12+
Resolve(context.Context, fs.FS, resolvers.Options) (filesystem fs.FS, prefix string, downloadPath string, applies bool, err error)
1313
}
1414

1515
var defaultResolvers = []ModuleResolver{
16-
resolvers2.Cache,
17-
resolvers2.Local,
18-
resolvers2.Remote,
19-
resolvers2.Registry,
16+
resolvers.Cache,
17+
resolvers.Local,
18+
resolvers.Remote,
19+
resolvers.Registry,
2020
}
2121

22-
func resolveModule(ctx context.Context, current fs.FS, opt resolvers2.Options) (filesystem fs.FS, sourcePrefix, downloadPath string, err error) {
22+
func resolveModule(ctx context.Context, current fs.FS, opt resolvers.Options) (filesystem fs.FS, sourcePrefix, downloadPath string, err error) {
2323
opt.Debug("Resolving module '%s' with source: '%s'...", opt.Name, opt.Source)
2424
for _, resolver := range defaultResolvers {
2525
if filesystem, prefix, path, applies, err := resolver.Resolve(ctx, current, opt); err != nil {

pkg/iac/scanners/terraform/parser/resolvers/registry.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,29 @@ func (r *registryResolver) Resolve(ctx context.Context, target fs.FS, opt Option
122122
return nil, "", "", true, err
123123
}
124124
defer func() { _ = resp.Body.Close() }()
125-
if resp.StatusCode != http.StatusNoContent {
125+
126+
// OpenTofu may return 200 with body
127+
switch resp.StatusCode {
128+
case http.StatusOK:
129+
// https://opentofu.org/docs/internals/module-registry-protocol/#sample-response-1
130+
var downloadResponse struct {
131+
Location string `json:"location"`
132+
}
133+
if err := json.NewDecoder(resp.Body).Decode(&downloadResponse); err != nil {
134+
return nil, "", "", true, fmt.Errorf("failed to decode download response: %w", err)
135+
}
136+
137+
opt.Source = downloadResponse.Location
138+
case http.StatusNoContent:
139+
opt.Source = resp.Header.Get("X-Terraform-Get")
140+
default:
126141
return nil, "", "", true, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
127142
}
128143

129-
opt.Source = resp.Header.Get("X-Terraform-Get")
144+
if opt.Source == "" {
145+
return nil, "", "", true, fmt.Errorf("no source was found for the registry at %s", hostname)
146+
}
147+
130148
opt.Debug("Module '%s' resolved via registry to new source: '%s'", opt.Name, opt.Source)
131149
opt.RelativePath = relativePath
132150
filesystem, prefix, downloadPath, _, err = Remote.Resolve(ctx, target, opt)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package resolvers_test
2+
3+
import (
4+
"context"
5+
"io/fs"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser/resolvers"
12+
)
13+
14+
func TestResolveModuleFromOpenTofuRegistry(t *testing.T) {
15+
if testing.Short() {
16+
t.Skip("skipping integration test in short mode")
17+
}
18+
19+
fsys, _, path, _, err := resolvers.Registry.Resolve(context.Background(), nil, resolvers.Options{
20+
Source: "registry.opentofu.org/terraform-aws-modules/s3-bucket/aws",
21+
RelativePath: "test",
22+
Name: "bucket",
23+
Version: "4.1.2",
24+
AllowDownloads: true,
25+
SkipCache: true,
26+
})
27+
require.NoError(t, err)
28+
29+
_, err = fs.Stat(fsys, filepath.Join(path, "main.tf"))
30+
require.NoError(t, err)
31+
}

0 commit comments

Comments
 (0)