From 1c5e1aeef744133ce9ee06d1351a0033e6f3f4bf Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Mon, 14 Jul 2025 13:23:22 +0200 Subject: [PATCH 1/6] feat: add policy develop lint Signed-off-by: Sylwester Piskozub --- app/cli/cmd/policy.go | 30 ++ app/cli/cmd/policy_develop.go | 31 ++ app/cli/cmd/policy_develop_lint.go | 67 +++ app/cli/cmd/root.go | 2 +- app/cli/documentation/cli-reference.mdx | 160 +++++++ .../internal/action/policy_develop_lint.go | 75 ++++ app/cli/internal/policydevel/lint.go | 390 ++++++++++++++++++ go.mod | 98 ++--- go.sum | 227 +++++----- 9 files changed, 927 insertions(+), 153 deletions(-) create mode 100644 app/cli/cmd/policy.go create mode 100644 app/cli/cmd/policy_develop.go create mode 100644 app/cli/cmd/policy_develop_lint.go create mode 100644 app/cli/internal/action/policy_develop_lint.go create mode 100644 app/cli/internal/policydevel/lint.go diff --git a/app/cli/cmd/policy.go b/app/cli/cmd/policy.go new file mode 100644 index 000000000..db34a4425 --- /dev/null +++ b/app/cli/cmd/policy.go @@ -0,0 +1,30 @@ +// +// Copyright 2025 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +func newPolicyCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "policy", + Short: "Craft chainloop policies", + } + + cmd.AddCommand(newPolicyDevelopCmd()) + return cmd +} diff --git a/app/cli/cmd/policy_develop.go b/app/cli/cmd/policy_develop.go new file mode 100644 index 000000000..c18345a00 --- /dev/null +++ b/app/cli/cmd/policy_develop.go @@ -0,0 +1,31 @@ +// +// Copyright 2025 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +func newPolicyDevelopCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "develop", + Aliases: []string{"devel"}, + Short: "Tools for policy development", + } + + cmd.AddCommand(newPolicyDevelopLintCmd()) + return cmd +} diff --git a/app/cli/cmd/policy_develop_lint.go b/app/cli/cmd/policy_develop_lint.go new file mode 100644 index 000000000..c2112ceb5 --- /dev/null +++ b/app/cli/cmd/policy_develop_lint.go @@ -0,0 +1,67 @@ +// +// Copyright 2025 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/chainloop-dev/chainloop/app/cli/internal/action" + "github.com/spf13/cobra" +) + +func newPolicyDevelopLintCmd() *cobra.Command { + var ( + policyPath string + format bool + ) + + cmd := &cobra.Command{ + Use: "lint", + Short: "Lint chainloop policy structure and content", + Long: `Performs comprehensive validation of: +- *.yaml files (schema validation) +- *.rego (formatting, linting, structure)`, + RunE: func(cmd *cobra.Command, args []string) error { + a, err := action.NewPolicyLint(actionOpts) + if err != nil { + return fmt.Errorf("failed to initialize linter: %w", err) + } + + result, err := a.Run(cmd.Context(), &action.PolicyLintOpts{ + PolicyPath: policyPath, + Format: format, + }) + if err != nil { + return fmt.Errorf("linting failed: %w", err) + } + + if result.Valid { + logger.Info().Msg("policy is valid!") + return nil + } + + // Print all validation errors + for _, err := range result.Errors { + logger.Error().Msg(err) + } + return fmt.Errorf("policy validation failed with %d issues", len(result.Errors)) + }, + } + + cmd.Flags().StringVarP(&policyPath, "policy", "p", ".", "Path to policy directory") + cmd.Flags().BoolVar(&format, "format", false, "Auto-format file with opa fmt") + return cmd +} diff --git a/app/cli/cmd/root.go b/app/cli/cmd/root.go index 7e2e2422a..558f8477c 100644 --- a/app/cli/cmd/root.go +++ b/app/cli/cmd/root.go @@ -242,7 +242,7 @@ func NewRootCmd(l zerolog.Logger) *cobra.Command { rootCmd.AddCommand(newWorkflowCmd(), newAuthCmd(), NewVersionCmd(), newAttestationCmd(), newArtifactCmd(), newConfigCmd(), newIntegrationCmd(), newOrganizationCmd(), newCASBackendCmd(), - newReferrerDiscoverCmd(), + newReferrerDiscoverCmd(), newPolicyCmd(), ) // Load plugins if we are not running a subcommand diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index 71da46184..d009776b9 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -2700,6 +2700,166 @@ Options inherited from parent commands -y, --yes Skip confirmation ``` +## chainloop policy + +Craft chainloop policies + +Options + +``` +-h, --help help for policy +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + +### chainloop policy develop + +Tools for policy development + +Options + +``` +-h, --help help for develop +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + +#### chainloop policy develop help + +Help about any command + +Synopsis + +Help provides help for any command in the application. +Simply type develop help [path to command] for full details. + +``` +chainloop policy develop help [command] [flags] +``` + +Options + +``` +-h, --help help for help +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + +#### chainloop policy develop lint + +Lint chainloop policy structure and content + +Synopsis + +Performs comprehensive validation of: +- *.yaml files (schema validation) +- *.rego (formatting, linting, structure) + +``` +chainloop policy develop lint [flags] +``` + +Options + +``` +--format Auto-format file with opa fmt +-h, --help help for lint +-p, --policy string Path to policy directory (default ".") +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + +### chainloop policy help + +Help about any command + +Synopsis + +Help provides help for any command in the application. +Simply type policy help [path to command] for full details. + +``` +chainloop policy help [command] [flags] +``` + +Options + +``` +-h, --help help for help +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + ## chainloop version Command line version diff --git a/app/cli/internal/action/policy_develop_lint.go b/app/cli/internal/action/policy_develop_lint.go new file mode 100644 index 000000000..d0495abac --- /dev/null +++ b/app/cli/internal/action/policy_develop_lint.go @@ -0,0 +1,75 @@ +// +// Copyright 2025 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package action + +import ( + "context" + "fmt" + "path/filepath" + + policy "github.com/chainloop-dev/chainloop/app/cli/internal/policydevel" +) + +type PolicyLintOpts struct { + PolicyPath string + Format bool +} + +type PolicyLintResult struct { + Valid bool + Errors []string +} + +type PolicyLint struct { + *ActionsOpts +} + +func NewPolicyLint(actionOpts *ActionsOpts) (*PolicyLint, error) { + return &PolicyLint{ + ActionsOpts: actionOpts, + }, nil +} + +func (action *PolicyLint) Run(_ context.Context, opts *PolicyLintOpts) (*PolicyLintResult, error) { + // Resolve absolute path to policy directory + absPath, err := filepath.Abs(opts.PolicyPath) + if err != nil { + return nil, fmt.Errorf("resolving absolute path: %w", err) + } + + // Read policies + policy, err := policy.Read(absPath, opts.Format) + if err != nil { + return nil, fmt.Errorf("loading policy: %w", err) + } + + // Run all validations + validationErrors := policy.Validate() + + // Convert errors to strings + errorStrings := make([]string, 0, len(validationErrors)) + for _, err := range validationErrors { + errorStrings = append(errorStrings, err.Error()) + } + + // Prepare result + result := &PolicyLintResult{ + Valid: len(validationErrors) == 0, + Errors: errorStrings, + } + + return result, nil +} diff --git a/app/cli/internal/policydevel/lint.go b/app/cli/internal/policydevel/lint.go new file mode 100644 index 000000000..58985296d --- /dev/null +++ b/app/cli/internal/policydevel/lint.go @@ -0,0 +1,390 @@ +// +// Copyright 2025 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package policy + +import ( + "context" + "fmt" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/open-policy-agent/opa/v1/format" + "github.com/styrainc/regal/pkg/linter" + "github.com/styrainc/regal/pkg/rules" + "gopkg.in/yaml.v3" +) + +type Policy struct { + Path string + YAMLFiles []*File + RegoFiles []*File + Format bool +} + +type File struct { + Path string + Content []byte +} + +type EmbeddedPolicy struct { + Kind string + Rego string +} + +// Read policy files from the given directory +func Read(absPath string, format bool) (*Policy, error) { + fileInfo, err := os.Stat(absPath) + if os.IsNotExist(err) { + return nil, fmt.Errorf("path does not exist: %s", absPath) + } + + policy := &Policy{ + Path: absPath, + Format: format, + } + + if fileInfo.IsDir() { + // Read all *.yaml and *.rego files in the directory + files, err := os.ReadDir(absPath) + if err != nil { + return nil, fmt.Errorf("reading directory: %w", err) + } + + for _, file := range files { + if file.IsDir() { + continue + } + + filePath := filepath.Join(absPath, file.Name()) + content, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("reading %s: %w", file.Name(), err) + } + + switch strings.ToLower(filepath.Ext(file.Name())) { + case ".yaml", ".yml": + policy.YAMLFiles = append(policy.YAMLFiles, &File{ + Path: filePath, + Content: content, + }) + case ".rego": + policy.RegoFiles = append(policy.RegoFiles, &File{ + Path: filePath, + Content: content, + }) + } + + if len(policy.YAMLFiles) == 0 && len(policy.RegoFiles) == 0 { + return nil, fmt.Errorf("directory must contain at least one .yaml/.yml or .rego file") + } + } + } else { + // Read given file + content, err := os.ReadFile(absPath) + if err != nil { + return nil, fmt.Errorf("reading file: %w", err) + } + + switch strings.ToLower(filepath.Ext(absPath)) { + case ".yaml", ".yml": + policy.YAMLFiles = append(policy.YAMLFiles, &File{ + Path: absPath, + Content: content, + }) + case ".rego": + policy.RegoFiles = append(policy.RegoFiles, &File{ + Path: absPath, + Content: content, + }) + default: + return nil, fmt.Errorf("file must be either .yaml/.yml or .rego") + } + } + + return policy, nil +} + +func (p *Policy) Validate() []error { + var allErrors []error + + // Validate all YAML files (including their embedded policies) + for _, yamlFile := range p.YAMLFiles { + if yamlErrs := p.validateYAMLFile(yamlFile); len(yamlErrs) > 0 { + allErrors = append(allErrors, yamlErrs...) + } + } + + // Validate standalone rego files + for _, regoFile := range p.RegoFiles { + if regoErrs := p.validateRegoFile(regoFile); len(regoErrs) > 0 { + allErrors = append(allErrors, regoErrs...) + } + } + + return allErrors +} + +func (p *Policy) validateYAMLFile(file *File) []error { + var errors []error + var node yaml.Node + + if err := yaml.Unmarshal(file.Content, &node); err != nil { + return []error{fmt.Errorf("%s: invalid YAML: %w", file.Path, err)} + } + + var data map[string]interface{} + if err := node.Decode(&data); err != nil { + return []error{fmt.Errorf("%s: invalid YAML structure: %w", file.Path, err)} + } + + // Validate YAML structure + if missing := checkRequiredFields(data, []string{"apiVersion", "kind", "spec"}); len(missing) > 0 { + errors = append(errors, fmt.Errorf("%s: missing required fields: %s", file.Path, strings.Join(missing, ", "))) + } + + // Process each embedded policy + if spec, ok := data["spec"].(map[string]interface{}); ok { + if policies, ok := spec["policies"].([]interface{}); ok { + for i, policy := range policies { + if policyMap, ok := policy.(map[string]interface{}); ok { + if regoContent, ok := policyMap["rego"].(string); ok { + regoLine := findRegoLineInYAML(&node, i) + formattedContent, regoErrors := p.validateAndFormatRego( + regoContent, + fmt.Sprintf("%s (policy #%d)", file.Path, i+1), + regoLine, + ) + + errors = append(errors, regoErrors...) + + // Check and apply formatting changes + if p.Format && formattedContent != regoContent { + policyMap["rego"] = formattedContent + + updatedContent, err := yaml.Marshal(data) + if err != nil { + errors = append(errors, fmt.Errorf("%s: failed to marshal updated YAML: %w", file.Path, err)) + } else if err := os.WriteFile(file.Path, updatedContent, 0600); err != nil { + errors = append(errors, fmt.Errorf("%s: failed to save formatted file: %w", file.Path, err)) + } else { + file.Content = updatedContent + } + } + } + } + } + } + } + + return errors +} + +func checkRequiredFields(data map[string]interface{}, fields []string) []string { + var missing []string + for _, field := range fields { + if _, exists := data[field]; !exists { + missing = append(missing, field) + } + } + return missing +} + +func (p *Policy) validateRegoFile(file *File) []error { + var errors []error + original := string(file.Content) + + formatted, errs := p.validateAndFormatRego(original, file.Path, 1) + errors = append(errors, errs...) + + if p.Format && formatted != original { + if err := os.WriteFile(file.Path, []byte(formatted), 0600); err != nil { + errors = append(errors, fmt.Errorf("%s: failed to auto-format: %w", file.Path, err)) + } else { + file.Content = []byte(formatted) + } + } + + return errors +} + +// Runs the Regal linter on the given rego content and returns any violations as errors +func (p *Policy) runRegalLinter(filePath, content string, lineOffset int) []error { + inputModules, err := rules.InputFromText(filePath, content) + if err != nil { + return []error{err} + } + + lntr := linter.NewLinter().WithInputModules(&inputModules) + report, err := lntr.Lint(context.Background()) + if err != nil { + return []error{err} + } + + errors := make([]error, 0, len(report.Violations)) + for _, v := range report.Violations { + errors = append(errors, fmt.Errorf("%d: %s", + v.Location.Row+lineOffset, + v.Description, + )) + } + + return errors +} + +func (p *Policy) validateAndFormatRego(content, file string, offset int) (string, []error) { + var errs []error + + // 1. Optionally format + if p.Format { + formatted, err := p.applyOPAFmt(content, file) + if err != nil { + errs = append(errs, err) + } else { + content = formatted + } + } + + // 2. Structural validation + errs = append(errs, checkResultStructure(content, file, []string{"skipped", "violations", "skip_reason"})...) + + // 3. Run Regal linter and remap OPA fmt lines + errs = append(errs, p.runLintWithOffset(content, file, offset)...) + + return content, errs +} + +func (p *Policy) applyOPAFmt(content, file string) (string, error) { + formatted, err := format.SourceWithOpts(file, []byte(content), format.Opts{}) + if err != nil { + // formatting failed, keep original + return content, fmt.Errorf("%s: Auto-formatting failed", file) + } + return string(formatted), nil +} + +func checkResultStructure(content, path string, keys []string) []error { + var errs []error + + // Regex to capture result := { ... } including multiline + re := regexp.MustCompile(`(?s)result\s*:=\s*\{(.+?)\}`) + match := re.FindStringSubmatch(content) + if match == nil { + return append(errs, fmt.Errorf("%s: no result literal found", path)) + } + + body := match[1] + // Find quoted keys inside the object literal + keyRe := regexp.MustCompile(`"([^"]+)"\s*:`) + found := make(map[string]bool) + for _, m := range keyRe.FindAllStringSubmatch(body, -1) { + found[m[1]] = true + } + + for _, want := range keys { + if !found[want] { + errs = append(errs, fmt.Errorf("%s: missing %q key in result", path, want)) + } + } + return errs +} + +func (p *Policy) runLintWithOffset(content, path string, offset int) []error { + rawErrs := p.runRegalLinter(path, content, offset) + return p.remapOPAfmtErrors(rawErrs, path, offset) +} + +// Processes raw errors from OPA fmr ran by Regal and: +// 1. Splits grouped errors into individual errors +// 2. Adjusts line numbers for embedded rego scripts +func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string, offset int) []error { + var errs []error + // Regex matches file path, line number and error message like: /path/file:line: message + errorRegex := regexp.MustCompile(`^` + regexp.QuoteMeta(path) + `:(\d+):\s*(.+)$`) + + for _, err := range rawErrs { + errorStr := err.Error() + + // Split by newlines to handle both single and multi-line errors + lines := strings.Split(errorStr, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if line == "" { + continue + } + + // Skip the "N errors occurred" header + if strings.Contains(line, "errors occurred:") { + continue + } + + // Try to match the standard error format + if matches := errorRegex.FindStringSubmatch(line); len(matches) == 3 { + if lineNum, convErr := strconv.Atoi(matches[1]); convErr == nil { + errs = append(errs, fmt.Errorf("%s:%d: %s", path, lineNum+offset, matches[2])) + continue + } + } + + // If we didn't match the standard format, preserve the original error + errs = append(errs, fmt.Errorf("%s: %s", path, line)) + } + } + + return errs +} + +// Locates beginning line of embedded rego script +func findRegoLineInYAML(doc *yaml.Node, sectionIdx int) int { + if doc == nil || len(doc.Content) == 0 { + return 1 + } + + // Navigate through the YAML structure + root := doc.Content[0] + spec := findKey(root, "spec") + if spec == nil { + return 1 + } + + policies := findKey(spec, "policies") + if policies == nil || policies.Kind != yaml.SequenceNode || sectionIdx >= len(policies.Content) { + return 1 + } + + policy := policies.Content[sectionIdx] + rego := findKey(policy, "rego") + if rego == nil { + return 1 + } + + return rego.Line +} + +func findKey(node *yaml.Node, key string) *yaml.Node { + if node == nil || node.Kind != yaml.MappingNode { + return nil + } + + for i := 0; i < len(node.Content)-1; i += 2 { + if node.Content[i].Value == key { + return node.Content[i+1] + } + } + return nil +} diff --git a/go.mod b/go.mod index cd1787fcd..13d2484ff 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/lib/pq v1.10.9 github.com/moby/moby v26.1.0+incompatible github.com/opencontainers/image-spec v1.1.1 - github.com/prometheus/client_golang v1.21.1 + github.com/prometheus/client_golang v1.22.0 github.com/rs/zerolog v1.32.0 github.com/secure-systems-lab/go-securesystemslib v0.8.0 github.com/sigstore/cosign/v2 v2.4.1 @@ -51,12 +51,12 @@ require ( github.com/testcontainers/testcontainers-go v0.35.0 go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/oauth2 v0.26.0 - golang.org/x/term v0.30.0 + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f + golang.org/x/oauth2 v0.27.0 + golang.org/x/term v0.32.0 google.golang.org/api v0.215.0 google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/grpc v1.71.1 + google.golang.org/grpc v1.72.2 google.golang.org/protobuf v1.36.6 sigs.k8s.io/yaml v1.4.0 ) @@ -74,7 +74,7 @@ require ( github.com/denisbrodbeck/machineid v1.0.1 github.com/google/go-github/v66 v66.0.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/in-toto/attestation v1.1.0 @@ -82,7 +82,7 @@ require ( github.com/jackc/pgx/v5 v5.7.2 github.com/muesli/reflow v0.3.0 github.com/nats-io/nats.go v1.34.0 - github.com/open-policy-agent/opa v1.4.0 + github.com/open-policy-agent/opa v1.6.0 github.com/openvex/go-vex v0.2.5 github.com/posthog/posthog-go v0.0.0-20240327112532-87b23fe11103 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 @@ -93,28 +93,30 @@ require ( github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8 github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.8 github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8 + github.com/styrainc/regal v0.35.1 github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 gitlab.com/gitlab-org/security-products/analyzers/report/v5 v5.3.0 - google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 google.golang.org/genproto/googleapis/bytestream v0.0.0-20241223144023-3abc09e42ca8 ) require ( - cel.dev/expr v0.19.1 // indirect + cel.dev/expr v0.20.0 // indirect cloud.google.com/go/auth v0.13.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect cloud.google.com/go/kms v1.20.1 // indirect cloud.google.com/go/longrunning v0.6.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/pubsub v1.45.1 // indirect - dario.cat/mergo v1.0.1 // indirect + dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/agnivade/levenshtein v1.2.1 // indirect @@ -126,23 +128,24 @@ require ( github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect github.com/casbin/govaluate v1.3.0 // indirect - github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect + github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect + github.com/containerd/platforms v1.0.0-rc.1 // indirect + github.com/coreos/go-semver v0.3.1 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/creack/pty v1.1.21 // indirect - github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.1 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -180,12 +183,12 @@ require ( github.com/otiai10/copy v1.11.0 // indirect github.com/package-url/packageurl-go v0.1.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect github.com/rs/xid v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect @@ -194,30 +197,33 @@ require ( github.com/shirou/gopsutil/v3 v3.24.5 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/test v0.6.6 // indirect - github.com/skeema/knownhosts v1.3.0 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spiffe/go-spiffe/v2 v2.3.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/styrainc/roast v0.15.0 // indirect github.com/tchap/go-patricia/v2 v2.3.2 // indirect github.com/theupdateframework/go-tuf/v2 v2.0.1 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.9.0 // indirect + github.com/vektah/gqlparser/v2 v2.5.28 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zclconf/go-cty-yaml v1.1.0 // indirect + github.com/zeebo/errs v1.4.0 // indirect gitlab.com/gitlab-org/security-products/analyzers/common/v3 v3.2.1 // indirect gitlab.com/gitlab-org/security-products/analyzers/ruleset/v3 v3.0.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect go.step.sm/crypto v0.51.2 // indirect goa.design/goa v2.2.5+incompatible // indirect gopkg.in/warnings.v0 v0.1.2 // indirect @@ -232,7 +238,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/IguteChung/casbin-psql-watcher v1.0.0 github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/ThalesIgnite/crypto11 v1.2.5 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect @@ -260,13 +266,13 @@ require ( github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsouza/fake-gcs-server v1.47.6 github.com/go-chi/chi v4.1.2+incompatible // indirect - github.com/go-git/go-git/v5 v5.13.1 + github.com/go-git/go-git/v5 v5.16.0 github.com/go-jose/go-jose/v3 v3.0.4 // indirect github.com/go-kratos/aegis v0.2.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.23.0 // indirect github.com/go-openapi/errors v0.22.0 // indirect @@ -281,7 +287,7 @@ require ( github.com/go-openapi/validate v0.24.0 // indirect github.com/go-playground/form/v4 v4.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.2.1 // indirect @@ -316,7 +322,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/minio/minio-go/v7 v7.0.63 github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -333,13 +339,13 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/owenrumney/go-sarif v1.1.1 - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 - github.com/prometheus/procfs v0.15.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.63.0 + github.com/prometheus/procfs v0.16.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/cors v1.11.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect @@ -361,22 +367,22 @@ require ( github.com/zclconf/go-cty v1.16.2 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.36.0 - golang.org/x/mod v0.23.0 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.38.0 + golang.org/x/mod v0.24.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.30.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + golang.org/x/tools v0.32.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.28.6 // indirect k8s.io/apimachinery v0.28.6 k8s.io/client-go v0.28.6 // indirect diff --git a/go.sum b/go.sum index 10e45e5c7..ae52312ca 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 h1:nX4HXncwIdvQ8/8sIUIf1nyC ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1 h1:2IGhRovxlsOIQgx2ekZWo4wTPAYpck41+18ICxs37is= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw= -cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= -cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI= +cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -85,16 +85,16 @@ cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23 cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs= cuelang.org/go v0.9.2/go.mod h1:qpAYsLOf7gTM1YdEg6cxh553uZ4q9ZDWlPbtZr9q1Wk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= entgo.io/ent v0.10.1/go.mod h1:YPgxeLnoQ/YdpVORRtqjBF+wCy9NX9IR7veTv3Bffus= entgo.io/ent v0.14.4 h1:/DhDraSLXIkBhyiVoJeSshr4ZYi7femzhj6/TckzZuI= entgo.io/ent v0.14.4/go.mod h1:aDPE/OziPEu8+OWbzy4UlvWmD2/kbRuWfK2A40hcxJM= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM= github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.14.0 h1:kcnfY4vljxXliXDBrA9K9lwF8IoEZ4Up6Eg9kWTIm28= @@ -145,8 +145,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 h1:f2Qw/Ehhimh5uO1fayV0QIW7DShEQqhtUfhYc+cBPlw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0/go.mod h1:2bIszWvQRlJVmJLiuLhukLImRjKPcYdzzsx6darK02A= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -162,8 +162,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= -github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= @@ -209,6 +209,8 @@ github.com/aliyun/credentials-go v1.3.2/go.mod h1:tlpz4uys4Rn7Ik4/piGRrTbXy2uLKv github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 h1:6COpXWpHbhWM1wgcQN95TdsmrLTba8KQfPgImBXzkjA= github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -311,12 +313,15 @@ github.com/casbin/ent-adapter v0.5.0 h1:ZS92OFmNkYF1G972Uy9XG3Zkr4rJ/glyzs98JxfH github.com/casbin/ent-adapter v0.5.0/go.mod h1:V4eFuva0HzqiQAyByjri1HYT9JlFd0zPULQIzqLht5U= github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -348,8 +353,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 h1:boJj011Hh+874zpIySeApCX4GeOjPl9qhRF3QuIZq+Q= -github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -360,14 +365,16 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -386,8 +393,8 @@ github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 h1:2Dx4IHfC1yHWI12AxQDJM1QbRCDfk6M+blLzlZCXdrc= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= -github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -434,8 +441,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= -github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ= -github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -466,8 +473,8 @@ github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2T github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= @@ -483,8 +490,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsouza/fake-gcs-server v1.47.6 h1:/d/879q/Os9Zc5gyV3QVLfZoajN1KcWucf2zYCFeFxs= github.com/fsouza/fake-gcs-server v1.47.6/go.mod h1:ApSXKexpG1BUXJ4f2tNCxvhTKwCPFqFLBDW2UNQDODE= github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= @@ -503,13 +510,13 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA= -github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= -github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= +github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ= +github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -535,8 +542,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -619,8 +626,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -716,8 +724,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416 h1:1/qwHx8P72glDXdyCKesJ+/c40x71SY4q2avOxJ2iYQ= +github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= @@ -766,8 +774,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c9 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -979,8 +987,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= @@ -1123,8 +1131,8 @@ github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3ev github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/open-policy-agent/opa v1.4.0 h1:IGO3xt5HhQKQq2axfa9memIFx5lCyaBlG+fXcgHpd3A= -github.com/open-policy-agent/opa v1.4.0/go.mod h1:DNzZPKqKh4U0n0ANxcCVlw8lCSv2c+h5G/3QvSYdWZ8= +github.com/open-policy-agent/opa v1.6.0 h1:/S/cnNQJ2MUMNzizHPbisTWBHowmLkPrugY5jjkPlRQ= +github.com/open-policy-agent/opa v1.6.0/go.mod h1:zFmw4P+W62+CWGYRDDswfVYSCnPo6oYaktQnfIaRFC4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -1158,15 +1166,16 @@ github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -1199,16 +1208,16 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= -github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1216,8 +1225,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= +github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1225,25 +1234,25 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf h1:014O62zIzQwvoD7Ekj3ePDF5bv9Xxy0w6AZk0qYbjUk= github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= +github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -1317,8 +1326,8 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= -github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= -github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= @@ -1353,8 +1362,8 @@ github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/spiffe/go-spiffe/v2 v2.3.0 h1:g2jYNb/PDMB8I7mBGL2Zuq/Ur6hUhoroxGQFyD6tTj8= -github.com/spiffe/go-spiffe/v2 v2.3.0/go.mod h1:Oxsaio7DBgSNqhAO9i/9tLClaVlfRok7zvJnTV8ZyIY= +github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= +github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1384,6 +1393,10 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/styrainc/regal v0.35.1 h1:3WZqPtKEbfxx1IWLkQ1OHhTpP4Nx3v/Zd+cuoBecd7I= +github.com/styrainc/regal v0.35.1/go.mod h1:1hCkmFTWMPqzqgYsbWbaRDlXIMupI6qkcSg4LYSd16E= +github.com/styrainc/roast v0.15.0 h1:cEjm6AfIPp0Z6fTVHK+kW5pWevekmZ69H4XlEcXrTRk= +github.com/styrainc/roast v0.15.0/go.mod h1:jQH3mOwoaOHrwgtj5B91dOHlfWaEE+lgLV6H+UAaYGo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1418,6 +1431,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= +github.com/vektah/gqlparser/v2 v2.5.28 h1:bIulcl3LF69ba6EiZVGD88y4MkM+Jxrf3P2MX8xLRkY= +github.com/vektah/gqlparser/v2 v2.5.28/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= @@ -1467,8 +1482,8 @@ github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6 github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= -github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= -github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= gitlab.com/gitlab-org/security-products/analyzers/common/v3 v3.2.1 h1:XX5DKq473xrw/TnJB069cVRDhsN/AFX6ZJi0LQWmK74= gitlab.com/gitlab-org/security-products/analyzers/common/v3 v3.2.1/go.mod h1:MaLrVtJgCo/X9jxNkZUkZPCa7sc5lFAMqJVjsKFMUpc= gitlab.com/gitlab-org/security-products/analyzers/report/v5 v5.3.0 h1:raTSihUYSva9irNTmY2exbLSlqdsHX/TZjIDxqySfxM= @@ -1501,29 +1516,29 @@ go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//sn go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= go.step.sm/crypto v0.51.2 h1:5EiCGIMg7IvQTGmJrwRosbXeprtT80OhoS/PJarg60o= go.step.sm/crypto v0.51.2/go.mod h1:QK7czLjN2k+uqVp5CHXxJbhc70kVRSP+0CQF3zsR5M0= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1573,8 +1588,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1586,8 +1601,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1624,8 +1639,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1696,8 +1711,8 @@ golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1715,8 +1730,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1733,8 +1748,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1847,8 +1862,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1864,8 +1879,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1884,8 +1899,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1965,8 +1980,8 @@ golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2083,12 +2098,12 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= google.golang.org/genproto/googleapis/bytestream v0.0.0-20241223144023-3abc09e42ca8 h1:qlXhWiX84AGgaN7LuORWBEQCCTqj3szNbh2am45O3W8= google.golang.org/genproto/googleapis/bytestream v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:bLYPejkLzwgJuAHlIk1gdPOlx9CUYXLZi2rZxL/ursM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -2123,8 +2138,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 33151f4c32ae4a279fbb6dfb06eaad340c38ca3f Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Mon, 14 Jul 2025 13:46:33 +0200 Subject: [PATCH 2/6] fix linting error Signed-off-by: Sylwester Piskozub --- app/cli/cmd/policy_develop_lint.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/cli/cmd/policy_develop_lint.go b/app/cli/cmd/policy_develop_lint.go index c2112ceb5..996506ead 100644 --- a/app/cli/cmd/policy_develop_lint.go +++ b/app/cli/cmd/policy_develop_lint.go @@ -34,7 +34,7 @@ func newPolicyDevelopLintCmd() *cobra.Command { Long: `Performs comprehensive validation of: - *.yaml files (schema validation) - *.rego (formatting, linting, structure)`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { a, err := action.NewPolicyLint(actionOpts) if err != nil { return fmt.Errorf("failed to initialize linter: %w", err) From d5cbbea9d3e25f200830780a8eebfb0edeb98a4f Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Wed, 16 Jul 2025 14:03:09 +0200 Subject: [PATCH 3/6] use proto unmarshal and validation for yaml schema validation; remove replicated code Signed-off-by: Sylwester Piskozub --- .../internal/action/policy_develop_lint.go | 4 +- app/cli/internal/policydevel/lint.go | 273 +++++++----------- 2 files changed, 111 insertions(+), 166 deletions(-) diff --git a/app/cli/internal/action/policy_develop_lint.go b/app/cli/internal/action/policy_develop_lint.go index d0495abac..e076c6436 100644 --- a/app/cli/internal/action/policy_develop_lint.go +++ b/app/cli/internal/action/policy_develop_lint.go @@ -20,7 +20,7 @@ import ( "fmt" "path/filepath" - policy "github.com/chainloop-dev/chainloop/app/cli/internal/policydevel" + "github.com/chainloop-dev/chainloop/app/cli/internal/policydevel" ) type PolicyLintOpts struct { @@ -51,7 +51,7 @@ func (action *PolicyLint) Run(_ context.Context, opts *PolicyLintOpts) (*PolicyL } // Read policies - policy, err := policy.Read(absPath, opts.Format) + policy, err := policydevel.Read(absPath, opts.Format) if err != nil { return nil, fmt.Errorf("loading policy: %w", err) } diff --git a/app/cli/internal/policydevel/lint.go b/app/cli/internal/policydevel/lint.go index 58985296d..cfc852c23 100644 --- a/app/cli/internal/policydevel/lint.go +++ b/app/cli/internal/policydevel/lint.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package policy +package policydevel import ( "context" @@ -24,10 +24,12 @@ import ( "strconv" "strings" + "github.com/bufbuild/protoyaml-go" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/unmarshal" "github.com/open-policy-agent/opa/v1/format" "github.com/styrainc/regal/pkg/linter" "github.com/styrainc/regal/pkg/rules" - "gopkg.in/yaml.v3" ) type Policy struct { @@ -42,12 +44,7 @@ type File struct { Content []byte } -type EmbeddedPolicy struct { - Kind string - Rego string -} - -// Read policy files from the given directory +// Read policy files from the given directory or file func Read(absPath string, format bool) (*Policy, error) { fileInfo, err := os.Stat(absPath) if os.IsNotExist(err) { @@ -60,64 +57,77 @@ func Read(absPath string, format bool) (*Policy, error) { } if fileInfo.IsDir() { - // Read all *.yaml and *.rego files in the directory - files, err := os.ReadDir(absPath) - if err != nil { - return nil, fmt.Errorf("reading directory: %w", err) + if err := readDirectory(policy, absPath); err != nil { + return nil, err + } + } else { + if err := readSingleFile(policy, absPath); err != nil { + return nil, err } + } - for _, file := range files { - if file.IsDir() { - continue - } + // Verify we found at least one valid file + if len(policy.YAMLFiles) == 0 && len(policy.RegoFiles) == 0 { + return nil, fmt.Errorf("no valid .yaml/.yml or .rego files found") + } - filePath := filepath.Join(absPath, file.Name()) - content, err := os.ReadFile(filePath) - if err != nil { - return nil, fmt.Errorf("reading %s: %w", file.Name(), err) - } + return policy, nil +} - switch strings.ToLower(filepath.Ext(file.Name())) { - case ".yaml", ".yml": - policy.YAMLFiles = append(policy.YAMLFiles, &File{ - Path: filePath, - Content: content, - }) - case ".rego": - policy.RegoFiles = append(policy.RegoFiles, &File{ - Path: filePath, - Content: content, - }) - } +func readDirectory(policy *Policy, dirPath string) error { + files, err := os.ReadDir(dirPath) + if err != nil { + return fmt.Errorf("reading directory: %w", err) + } - if len(policy.YAMLFiles) == 0 && len(policy.RegoFiles) == 0 { - return nil, fmt.Errorf("directory must contain at least one .yaml/.yml or .rego file") - } - } - } else { - // Read given file - content, err := os.ReadFile(absPath) - if err != nil { - return nil, fmt.Errorf("reading file: %w", err) + var foundValidFile bool + for _, file := range files { + if file.IsDir() { + continue } - switch strings.ToLower(filepath.Ext(absPath)) { - case ".yaml", ".yml": - policy.YAMLFiles = append(policy.YAMLFiles, &File{ - Path: absPath, - Content: content, - }) - case ".rego": - policy.RegoFiles = append(policy.RegoFiles, &File{ - Path: absPath, - Content: content, - }) - default: - return nil, fmt.Errorf("file must be either .yaml/.yml or .rego") + filePath := filepath.Join(dirPath, file.Name()) + if err := processFile(policy, filePath); err != nil { + // Skip unsupported files but continue processing others + continue } + foundValidFile = true } - return policy, nil + if !foundValidFile { + return fmt.Errorf("no valid .yaml/.yml or .rego files found in directory") + } + + return nil +} + +func readSingleFile(policy *Policy, filePath string) error { + return processFile(policy, filePath) +} + +func processFile(policy *Policy, filePath string) error { + content, err := os.ReadFile(filePath) + if err != nil { + return fmt.Errorf("reading %s: %w", filepath.Base(filePath), err) + } + + ext := strings.ToLower(filepath.Ext(filePath)) + switch ext { + case ".yaml", ".yml": + policy.YAMLFiles = append(policy.YAMLFiles, &File{ + Path: filePath, + Content: content, + }) + case ".rego": + policy.RegoFiles = append(policy.RegoFiles, &File{ + Path: filePath, + Content: content, + }) + default: + return fmt.Errorf("unsupported file extension %s, must be .yaml/.yml or .rego", ext) + } + + return nil } func (p *Policy) Validate() []error { @@ -141,75 +151,53 @@ func (p *Policy) Validate() []error { } func (p *Policy) validateYAMLFile(file *File) []error { - var errors []error - var node yaml.Node - - if err := yaml.Unmarshal(file.Content, &node); err != nil { - return []error{fmt.Errorf("%s: invalid YAML: %w", file.Path, err)} + var policy v1.Policy + if err := unmarshal.FromRaw(file.Content, unmarshal.RawFormatYAML, &policy, true); err != nil { + return []error{fmt.Errorf("%s: failed to parse/validate: %w", file.Path, err)} } - var data map[string]interface{} - if err := node.Decode(&data); err != nil { - return []error{fmt.Errorf("%s: invalid YAML structure: %w", file.Path, err)} - } + errs := p.processEmbeddedPolicies(&policy, file) - // Validate YAML structure - if missing := checkRequiredFields(data, []string{"apiVersion", "kind", "spec"}); len(missing) > 0 { - errors = append(errors, fmt.Errorf("%s: missing required fields: %s", file.Path, strings.Join(missing, ", "))) - } - - // Process each embedded policy - if spec, ok := data["spec"].(map[string]interface{}); ok { - if policies, ok := spec["policies"].([]interface{}); ok { - for i, policy := range policies { - if policyMap, ok := policy.(map[string]interface{}); ok { - if regoContent, ok := policyMap["rego"].(string); ok { - regoLine := findRegoLineInYAML(&node, i) - formattedContent, regoErrors := p.validateAndFormatRego( - regoContent, - fmt.Sprintf("%s (policy #%d)", file.Path, i+1), - regoLine, - ) - - errors = append(errors, regoErrors...) - - // Check and apply formatting changes - if p.Format && formattedContent != regoContent { - policyMap["rego"] = formattedContent - - updatedContent, err := yaml.Marshal(data) - if err != nil { - errors = append(errors, fmt.Errorf("%s: failed to marshal updated YAML: %w", file.Path, err)) - } else if err := os.WriteFile(file.Path, updatedContent, 0600); err != nil { - errors = append(errors, fmt.Errorf("%s: failed to save formatted file: %w", file.Path, err)) - } else { - file.Content = updatedContent - } - } - } - } - } + // Update policy file with formatted content + if p.Format { + outYAML, err := protoyaml.Marshal(&policy) + if err != nil { + errs = append(errs, fmt.Errorf("%s: failed to marshal updated YAML: %w", file.Path, err)) + } else if err := os.WriteFile(file.Path, outYAML, 0600); err != nil { + errs = append(errs, fmt.Errorf("%s: failed to save updated file: %w", file.Path, err)) + } else { + file.Content = outYAML } } - return errors + return errs } -func checkRequiredFields(data map[string]interface{}, fields []string) []string { - var missing []string - for _, field := range fields { - if _, exists := data[field]; !exists { - missing = append(missing, field) +func (p *Policy) processEmbeddedPolicies(pa *v1.Policy, file *File) []error { + var errs []error + + for idx, spec := range pa.Spec.Policies { + if regoSrc := spec.GetEmbedded(); regoSrc != "" { + formatted, reErrs := p.validateAndFormatRego( + regoSrc, + fmt.Sprintf("%s:(embedded #%d)", file.Path, idx+1), + ) + errs = append(errs, reErrs...) + + if p.Format && formatted != regoSrc { + spec.Source = &v1.PolicySpecV2_Embedded{Embedded: formatted} + } } } - return missing + + return errs } func (p *Policy) validateRegoFile(file *File) []error { var errors []error original := string(file.Content) - formatted, errs := p.validateAndFormatRego(original, file.Path, 1) + formatted, errs := p.validateAndFormatRego(original, file.Path) errors = append(errors, errs...) if p.Format && formatted != original { @@ -224,7 +212,7 @@ func (p *Policy) validateRegoFile(file *File) []error { } // Runs the Regal linter on the given rego content and returns any violations as errors -func (p *Policy) runRegalLinter(filePath, content string, lineOffset int) []error { +func (p *Policy) runRegalLinter(filePath, content string) []error { inputModules, err := rules.InputFromText(filePath, content) if err != nil { return []error{err} @@ -239,7 +227,7 @@ func (p *Policy) runRegalLinter(filePath, content string, lineOffset int) []erro errors := make([]error, 0, len(report.Violations)) for _, v := range report.Violations { errors = append(errors, fmt.Errorf("%d: %s", - v.Location.Row+lineOffset, + v.Location.Row, v.Description, )) } @@ -247,12 +235,12 @@ func (p *Policy) runRegalLinter(filePath, content string, lineOffset int) []erro return errors } -func (p *Policy) validateAndFormatRego(content, file string, offset int) (string, []error) { +func (p *Policy) validateAndFormatRego(content, path string) (string, []error) { var errs []error // 1. Optionally format if p.Format { - formatted, err := p.applyOPAFmt(content, file) + formatted, err := p.applyOPAFmt(content, path) if err != nil { errs = append(errs, err) } else { @@ -261,10 +249,12 @@ func (p *Policy) validateAndFormatRego(content, file string, offset int) (string } // 2. Structural validation - errs = append(errs, checkResultStructure(content, file, []string{"skipped", "violations", "skip_reason"})...) + errs = append(errs, checkResultStructure(content, path, []string{"skipped", "violations", "skip_reason"})...) + + // 3. Run Regal linter + rawErrs := p.runRegalLinter(path, content) - // 3. Run Regal linter and remap OPA fmt lines - errs = append(errs, p.runLintWithOffset(content, file, offset)...) + errs = append(errs, p.remapOPAfmtErrors(rawErrs, path)...) return content, errs } @@ -304,15 +294,10 @@ func checkResultStructure(content, path string, keys []string) []error { return errs } -func (p *Policy) runLintWithOffset(content, path string, offset int) []error { - rawErrs := p.runRegalLinter(path, content, offset) - return p.remapOPAfmtErrors(rawErrs, path, offset) -} - -// Processes raw errors from OPA fmr ran by Regal and: +// Processes raw errors from OPA fmt ran by Regal and: // 1. Splits grouped errors into individual errors // 2. Adjusts line numbers for embedded rego scripts -func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string, offset int) []error { +func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string) []error { var errs []error // Regex matches file path, line number and error message like: /path/file:line: message errorRegex := regexp.MustCompile(`^` + regexp.QuoteMeta(path) + `:(\d+):\s*(.+)$`) @@ -336,7 +321,7 @@ func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string, offset int) []e // Try to match the standard error format if matches := errorRegex.FindStringSubmatch(line); len(matches) == 3 { if lineNum, convErr := strconv.Atoi(matches[1]); convErr == nil { - errs = append(errs, fmt.Errorf("%s:%d: %s", path, lineNum+offset, matches[2])) + errs = append(errs, fmt.Errorf("%s:%d: %s", path, lineNum, matches[2])) continue } } @@ -348,43 +333,3 @@ func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string, offset int) []e return errs } - -// Locates beginning line of embedded rego script -func findRegoLineInYAML(doc *yaml.Node, sectionIdx int) int { - if doc == nil || len(doc.Content) == 0 { - return 1 - } - - // Navigate through the YAML structure - root := doc.Content[0] - spec := findKey(root, "spec") - if spec == nil { - return 1 - } - - policies := findKey(spec, "policies") - if policies == nil || policies.Kind != yaml.SequenceNode || sectionIdx >= len(policies.Content) { - return 1 - } - - policy := policies.Content[sectionIdx] - rego := findKey(policy, "rego") - if rego == nil { - return 1 - } - - return rego.Line -} - -func findKey(node *yaml.Node, key string) *yaml.Node { - if node == nil || node.Kind != yaml.MappingNode { - return nil - } - - for i := 0; i < len(node.Content)-1; i += 2 { - if node.Content[i].Value == key { - return node.Content[i+1] - } - } - return nil -} From 04c3c6d90665bc3bfecfc822883645bcac88f119 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Wed, 16 Jul 2025 14:41:18 +0200 Subject: [PATCH 4/6] fix tests Signed-off-by: Sylwester Piskozub --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 13d2484ff..24e46ccaa 100644 --- a/go.mod +++ b/go.mod @@ -382,7 +382,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.1 + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.28.6 // indirect k8s.io/apimachinery v0.28.6 k8s.io/client-go v0.28.6 // indirect From 5a6fc8dfadd4be92a0d4397556bb7e8e99d5ef6b Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 18 Jul 2025 09:12:06 +0200 Subject: [PATCH 5/6] rename policy; add comments, change return type for linting functions Signed-off-by: Sylwester Piskozub --- .../internal/action/policy_develop_lint.go | 20 ++- app/cli/internal/policydevel/lint.go | 120 +++++++++++------- 2 files changed, 85 insertions(+), 55 deletions(-) diff --git a/app/cli/internal/action/policy_develop_lint.go b/app/cli/internal/action/policy_develop_lint.go index e076c6436..27befe8ac 100644 --- a/app/cli/internal/action/policy_develop_lint.go +++ b/app/cli/internal/action/policy_develop_lint.go @@ -17,6 +17,7 @@ package action import ( "context" + "errors" "fmt" "path/filepath" @@ -51,23 +52,30 @@ func (action *PolicyLint) Run(_ context.Context, opts *PolicyLintOpts) (*PolicyL } // Read policies - policy, err := policydevel.Read(absPath, opts.Format) + policy, err := policydevel.Lookup(absPath, opts.Format) if err != nil { return nil, fmt.Errorf("loading policy: %w", err) } // Run all validations - validationErrors := policy.Validate() + validationErr := policy.Validate() // Convert errors to strings - errorStrings := make([]string, 0, len(validationErrors)) - for _, err := range validationErrors { - errorStrings = append(errorStrings, err.Error()) + var errorStrings []string + if validationErr != nil { + var errs interface{ Unwrap() []error } + if errors.As(validationErr, &errs) { + for _, e := range errs.Unwrap() { + errorStrings = append(errorStrings, e.Error()) + } + } else { + errorStrings = append(errorStrings, validationErr.Error()) + } } // Prepare result result := &PolicyLintResult{ - Valid: len(validationErrors) == 0, + Valid: validationErr == nil, Errors: errorStrings, } diff --git a/app/cli/internal/policydevel/lint.go b/app/cli/internal/policydevel/lint.go index cfc852c23..f76aca7ab 100644 --- a/app/cli/internal/policydevel/lint.go +++ b/app/cli/internal/policydevel/lint.go @@ -17,6 +17,7 @@ package policydevel import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -32,7 +33,7 @@ import ( "github.com/styrainc/regal/pkg/rules" ) -type Policy struct { +type PolicyToLint struct { Path string YAMLFiles []*File RegoFiles []*File @@ -45,23 +46,26 @@ type File struct { } // Read policy files from the given directory or file -func Read(absPath string, format bool) (*Policy, error) { +func Lookup(absPath string, format bool) (*PolicyToLint, error) { fileInfo, err := os.Stat(absPath) - if os.IsNotExist(err) { - return nil, fmt.Errorf("path does not exist: %s", absPath) + if err != nil { + if os.IsNotExist(err) { + return nil, fmt.Errorf("path does not exist: %s", absPath) + } + return nil, fmt.Errorf("failed to stat path %q: %w", absPath, err) } - policy := &Policy{ + policy := &PolicyToLint{ Path: absPath, Format: format, } if fileInfo.IsDir() { - if err := readDirectory(policy, absPath); err != nil { + if err := scanDirectory(policy, absPath); err != nil { return nil, err } } else { - if err := readSingleFile(policy, absPath); err != nil { + if err := processFile(policy, absPath); err != nil { return nil, err } } @@ -74,7 +78,8 @@ func Read(absPath string, format bool) (*Policy, error) { return policy, nil } -func readDirectory(policy *Policy, dirPath string) error { +// Performs a one-level directory lookup to find .yaml/.yml or .rego files. +func scanDirectory(policy *PolicyToLint, dirPath string) error { files, err := os.ReadDir(dirPath) if err != nil { return fmt.Errorf("reading directory: %w", err) @@ -101,11 +106,7 @@ func readDirectory(policy *Policy, dirPath string) error { return nil } -func readSingleFile(policy *Policy, filePath string) error { - return processFile(policy, filePath) -} - -func processFile(policy *Policy, filePath string) error { +func processFile(policy *PolicyToLint, filePath string) error { content, err := os.ReadFile(filePath) if err != nil { return fmt.Errorf("reading %s: %w", filepath.Base(filePath), err) @@ -130,33 +131,39 @@ func processFile(policy *Policy, filePath string) error { return nil } -func (p *Policy) Validate() []error { - var allErrors []error +func (p *PolicyToLint) Validate() error { + var errs []error // Validate all YAML files (including their embedded policies) for _, yamlFile := range p.YAMLFiles { - if yamlErrs := p.validateYAMLFile(yamlFile); len(yamlErrs) > 0 { - allErrors = append(allErrors, yamlErrs...) + err := p.validateYAMLFile(yamlFile) + if err != nil { + errs = append(errs, err) } } // Validate standalone rego files for _, regoFile := range p.RegoFiles { - if regoErrs := p.validateRegoFile(regoFile); len(regoErrs) > 0 { - allErrors = append(allErrors, regoErrs...) + err := p.validateRegoFile(regoFile) + if err != nil { + errs = append(errs, err) } } - return allErrors + return errors.Join(errs...) } -func (p *Policy) validateYAMLFile(file *File) []error { +func (p *PolicyToLint) validateYAMLFile(file *File) error { var policy v1.Policy if err := unmarshal.FromRaw(file.Content, unmarshal.RawFormatYAML, &policy, true); err != nil { - return []error{fmt.Errorf("%s: failed to parse/validate: %w", file.Path, err)} + return fmt.Errorf("%s: failed to parse/validate: %w", file.Path, err) } - errs := p.processEmbeddedPolicies(&policy, file) + var errs []error + err := p.processEmbeddedPolicies(&policy, file) + if err != nil { + errs = append(errs, err) + } // Update policy file with formatted content if p.Format { @@ -170,19 +177,19 @@ func (p *Policy) validateYAMLFile(file *File) []error { } } - return errs + return errors.Join(errs...) } -func (p *Policy) processEmbeddedPolicies(pa *v1.Policy, file *File) []error { +func (p *PolicyToLint) processEmbeddedPolicies(pa *v1.Policy, file *File) error { var errs []error for idx, spec := range pa.Spec.Policies { if regoSrc := spec.GetEmbedded(); regoSrc != "" { - formatted, reErrs := p.validateAndFormatRego( + formatted, err := p.validateAndFormatRego( regoSrc, fmt.Sprintf("%s:(embedded #%d)", file.Path, idx+1), ) - errs = append(errs, reErrs...) + errs = append(errs, err) if p.Format && formatted != regoSrc { spec.Source = &v1.PolicySpecV2_Embedded{Embedded: formatted} @@ -190,52 +197,54 @@ func (p *Policy) processEmbeddedPolicies(pa *v1.Policy, file *File) []error { } } - return errs + return errors.Join(errs...) } -func (p *Policy) validateRegoFile(file *File) []error { - var errors []error +func (p *PolicyToLint) validateRegoFile(file *File) error { + var errs []error original := string(file.Content) - formatted, errs := p.validateAndFormatRego(original, file.Path) - errors = append(errors, errs...) + formatted, err := p.validateAndFormatRego(original, file.Path) + if err != nil { + errs = append(errs, err) + } if p.Format && formatted != original { if err := os.WriteFile(file.Path, []byte(formatted), 0600); err != nil { - errors = append(errors, fmt.Errorf("%s: failed to auto-format: %w", file.Path, err)) + errs = append(errs, fmt.Errorf("%s: failed to auto-format: %w", file.Path, err)) } else { file.Content = []byte(formatted) } } - return errors + return errors.Join(errs...) } // Runs the Regal linter on the given rego content and returns any violations as errors -func (p *Policy) runRegalLinter(filePath, content string) []error { +func (p *PolicyToLint) runRegalLinter(filePath, content string) error { inputModules, err := rules.InputFromText(filePath, content) if err != nil { - return []error{err} + return err } lntr := linter.NewLinter().WithInputModules(&inputModules) report, err := lntr.Lint(context.Background()) if err != nil { - return []error{err} + return err } - errors := make([]error, 0, len(report.Violations)) + errs := make([]error, 0, len(report.Violations)) for _, v := range report.Violations { - errors = append(errors, fmt.Errorf("%d: %s", + errs = append(errs, fmt.Errorf("%d: %s", v.Location.Row, v.Description, )) } - return errors + return errors.Join(errs...) } -func (p *Policy) validateAndFormatRego(content, path string) (string, []error) { +func (p *PolicyToLint) validateAndFormatRego(content, path string) (string, error) { var errs []error // 1. Optionally format @@ -252,14 +261,15 @@ func (p *Policy) validateAndFormatRego(content, path string) (string, []error) { errs = append(errs, checkResultStructure(content, path, []string{"skipped", "violations", "skip_reason"})...) // 3. Run Regal linter - rawErrs := p.runRegalLinter(path, content) - - errs = append(errs, p.remapOPAfmtErrors(rawErrs, path)...) + err := p.runRegalLinter(path, content) + if err != nil { + errs = append(errs, p.remapOPAfmtErrors(err, path)) + } - return content, errs + return content, errors.Join(errs...) } -func (p *Policy) applyOPAFmt(content, file string) (string, error) { +func (p *PolicyToLint) applyOPAFmt(content, file string) (string, error) { formatted, err := format.SourceWithOpts(file, []byte(content), format.Opts{}) if err != nil { // formatting failed, keep original @@ -297,12 +307,24 @@ func checkResultStructure(content, path string, keys []string) []error { // Processes raw errors from OPA fmt ran by Regal and: // 1. Splits grouped errors into individual errors // 2. Adjusts line numbers for embedded rego scripts -func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string) []error { +func (p *PolicyToLint) remapOPAfmtErrors(rawErr error, path string) error { + if rawErr == nil { + return nil + } + var errs []error // Regex matches file path, line number and error message like: /path/file:line: message errorRegex := regexp.MustCompile(`^` + regexp.QuoteMeta(path) + `:(\d+):\s*(.+)$`) - for _, err := range rawErrs { + // Unwrap errors if rawErr is a joined error or has multiple wrapped errors + var list []error + if errsList, ok := rawErr.(interface{ Unwrap() []error }); ok { + list = errsList.Unwrap() + } else { + list = []error{rawErr} + } + + for _, err := range list { errorStr := err.Error() // Split by newlines to handle both single and multi-line errors @@ -331,5 +353,5 @@ func (p *Policy) remapOPAfmtErrors(rawErrs []error, path string) []error { } } - return errs + return errors.Join(errs...) } From b905bcee1803d8339c6f256f5079640431ea0aa3 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 18 Jul 2025 09:59:59 +0200 Subject: [PATCH 6/6] refactor handling storage during linting process Signed-off-by: Sylwester Piskozub --- .../internal/action/policy_develop_lint.go | 25 +- app/cli/internal/policydevel/lint.go | 228 ++++++++---------- 2 files changed, 107 insertions(+), 146 deletions(-) diff --git a/app/cli/internal/action/policy_develop_lint.go b/app/cli/internal/action/policy_develop_lint.go index 27befe8ac..abc5475f8 100644 --- a/app/cli/internal/action/policy_develop_lint.go +++ b/app/cli/internal/action/policy_develop_lint.go @@ -17,7 +17,6 @@ package action import ( "context" - "errors" "fmt" "path/filepath" @@ -58,25 +57,17 @@ func (action *PolicyLint) Run(_ context.Context, opts *PolicyLintOpts) (*PolicyL } // Run all validations - validationErr := policy.Validate() - - // Convert errors to strings - var errorStrings []string - if validationErr != nil { - var errs interface{ Unwrap() []error } - if errors.As(validationErr, &errs) { - for _, e := range errs.Unwrap() { - errorStrings = append(errorStrings, e.Error()) - } - } else { - errorStrings = append(errorStrings, validationErr.Error()) - } - } + policy.Validate() // Prepare result result := &PolicyLintResult{ - Valid: validationErr == nil, - Errors: errorStrings, + Valid: !policy.HasErrors(), + Errors: make([]string, 0, len(policy.Errors)), + } + + // Convert validation errors to strings + for _, err := range policy.Errors { + result.Errors = append(result.Errors, err.Error()) } return result, nil diff --git a/app/cli/internal/policydevel/lint.go b/app/cli/internal/policydevel/lint.go index f76aca7ab..8faaee3d9 100644 --- a/app/cli/internal/policydevel/lint.go +++ b/app/cli/internal/policydevel/lint.go @@ -17,7 +17,6 @@ package policydevel import ( "context" - "errors" "fmt" "os" "path/filepath" @@ -38,6 +37,7 @@ type PolicyToLint struct { YAMLFiles []*File RegoFiles []*File Format bool + Errors []ValidationError } type File struct { @@ -45,6 +45,33 @@ type File struct { Content []byte } +type ValidationError struct { + Path string + Line int + Message string +} + +func (e ValidationError) Error() string { + if e.Line > 0 { + return fmt.Sprintf("%s:%d: %s", e.Path, e.Line, e.Message) + } + return fmt.Sprintf("%s: %s", e.Path, e.Message) +} + +// Returns true if any validation errors were found +func (p *PolicyToLint) HasErrors() bool { + return len(p.Errors) > 0 +} + +// Adds a new validation error +func (p *PolicyToLint) AddError(path, message string, line int) { + p.Errors = append(p.Errors, ValidationError{ + Path: path, + Message: message, + Line: line, + }) +} + // Read policy files from the given directory or file func Lookup(absPath string, format bool) (*PolicyToLint, error) { fileInfo, err := os.Stat(absPath) @@ -131,161 +158,100 @@ func processFile(policy *PolicyToLint, filePath string) error { return nil } -func (p *PolicyToLint) Validate() error { - var errs []error - +func (p *PolicyToLint) Validate() { // Validate all YAML files (including their embedded policies) for _, yamlFile := range p.YAMLFiles { - err := p.validateYAMLFile(yamlFile) - if err != nil { - errs = append(errs, err) - } + p.validateYAMLFile(yamlFile) } // Validate standalone rego files for _, regoFile := range p.RegoFiles { - err := p.validateRegoFile(regoFile) - if err != nil { - errs = append(errs, err) - } + p.validateRegoFile(regoFile) } - - return errors.Join(errs...) } -func (p *PolicyToLint) validateYAMLFile(file *File) error { +func (p *PolicyToLint) validateYAMLFile(file *File) { var policy v1.Policy if err := unmarshal.FromRaw(file.Content, unmarshal.RawFormatYAML, &policy, true); err != nil { - return fmt.Errorf("%s: failed to parse/validate: %w", file.Path, err) + p.AddError(file.Path, fmt.Sprintf("failed to parse/validate: %v", err), 0) + return } - var errs []error - err := p.processEmbeddedPolicies(&policy, file) - if err != nil { - errs = append(errs, err) - } + p.processEmbeddedPolicies(&policy, file) // Update policy file with formatted content if p.Format { outYAML, err := protoyaml.Marshal(&policy) if err != nil { - errs = append(errs, fmt.Errorf("%s: failed to marshal updated YAML: %w", file.Path, err)) + p.AddError(file.Path, fmt.Sprintf("failed to marshal updated YAML: %v", err), 0) } else if err := os.WriteFile(file.Path, outYAML, 0600); err != nil { - errs = append(errs, fmt.Errorf("%s: failed to save updated file: %w", file.Path, err)) + p.AddError(file.Path, fmt.Sprintf("failed to save updated file: %v", err), 0) } else { file.Content = outYAML } } - - return errors.Join(errs...) } -func (p *PolicyToLint) processEmbeddedPolicies(pa *v1.Policy, file *File) error { - var errs []error - +func (p *PolicyToLint) processEmbeddedPolicies(pa *v1.Policy, file *File) { for idx, spec := range pa.Spec.Policies { if regoSrc := spec.GetEmbedded(); regoSrc != "" { - formatted, err := p.validateAndFormatRego( + formatted := p.validateAndFormatRego( regoSrc, fmt.Sprintf("%s:(embedded #%d)", file.Path, idx+1), ) - errs = append(errs, err) if p.Format && formatted != regoSrc { spec.Source = &v1.PolicySpecV2_Embedded{Embedded: formatted} } } } - - return errors.Join(errs...) } -func (p *PolicyToLint) validateRegoFile(file *File) error { - var errs []error +func (p *PolicyToLint) validateRegoFile(file *File) { original := string(file.Content) - - formatted, err := p.validateAndFormatRego(original, file.Path) - if err != nil { - errs = append(errs, err) - } + formatted := p.validateAndFormatRego(original, file.Path) if p.Format && formatted != original { if err := os.WriteFile(file.Path, []byte(formatted), 0600); err != nil { - errs = append(errs, fmt.Errorf("%s: failed to auto-format: %w", file.Path, err)) + p.AddError(file.Path, fmt.Sprintf("failed to auto-format: %v", err), 0) } else { file.Content = []byte(formatted) } } - - return errors.Join(errs...) } -// Runs the Regal linter on the given rego content and returns any violations as errors -func (p *PolicyToLint) runRegalLinter(filePath, content string) error { - inputModules, err := rules.InputFromText(filePath, content) - if err != nil { - return err - } - - lntr := linter.NewLinter().WithInputModules(&inputModules) - report, err := lntr.Lint(context.Background()) - if err != nil { - return err - } - - errs := make([]error, 0, len(report.Violations)) - for _, v := range report.Violations { - errs = append(errs, fmt.Errorf("%d: %s", - v.Location.Row, - v.Description, - )) - } - - return errors.Join(errs...) -} - -func (p *PolicyToLint) validateAndFormatRego(content, path string) (string, error) { - var errs []error - +func (p *PolicyToLint) validateAndFormatRego(content, path string) string { // 1. Optionally format if p.Format { - formatted, err := p.applyOPAFmt(content, path) - if err != nil { - errs = append(errs, err) - } else { - content = formatted - } + formatted := p.applyOPAFmt(content, path) + content = formatted } // 2. Structural validation - errs = append(errs, checkResultStructure(content, path, []string{"skipped", "violations", "skip_reason"})...) + p.checkResultStructure(content, path, []string{"skipped", "violations", "skip_reason"}) // 3. Run Regal linter - err := p.runRegalLinter(path, content) - if err != nil { - errs = append(errs, p.remapOPAfmtErrors(err, path)) - } + p.runRegalLinter(path, content) - return content, errors.Join(errs...) + return content } -func (p *PolicyToLint) applyOPAFmt(content, file string) (string, error) { +func (p *PolicyToLint) applyOPAFmt(content, file string) string { formatted, err := format.SourceWithOpts(file, []byte(content), format.Opts{}) if err != nil { - // formatting failed, keep original - return content, fmt.Errorf("%s: Auto-formatting failed", file) + p.AddError(file, "Auto-formatting failed", 0) + return content } - return string(formatted), nil + return string(formatted) } -func checkResultStructure(content, path string, keys []string) []error { - var errs []error - +func (p *PolicyToLint) checkResultStructure(content, path string, keys []string) { // Regex to capture result := { ... } including multiline re := regexp.MustCompile(`(?s)result\s*:=\s*\{(.+?)\}`) match := re.FindStringSubmatch(content) if match == nil { - return append(errs, fmt.Errorf("%s: no result literal found", path)) + p.AddError(path, "no result literal found", 0) + return } body := match[1] @@ -298,60 +264,64 @@ func checkResultStructure(content, path string, keys []string) []error { for _, want := range keys { if !found[want] { - errs = append(errs, fmt.Errorf("%s: missing %q key in result", path, want)) + p.AddError(path, fmt.Sprintf("missing %q key in result", want), 0) } } - return errs } -// Processes raw errors from OPA fmt ran by Regal and: -// 1. Splits grouped errors into individual errors -// 2. Adjusts line numbers for embedded rego scripts -func (p *PolicyToLint) remapOPAfmtErrors(rawErr error, path string) error { +// Runs the Regal linter on the given rego content and records any violations +func (p *PolicyToLint) runRegalLinter(filePath, content string) { + inputModules, err := rules.InputFromText(filePath, content) + if err != nil { + p.AddError(filePath, fmt.Sprintf("failed to prepare for linting: %v", err), 0) + return + } + + lntr := linter.NewLinter().WithInputModules(&inputModules) + report, err := lntr.Lint(context.Background()) + if err != nil { + p.AddError(filePath, fmt.Sprintf("linting failed: %v", err), 0) + return + } + + // Handle Regal violations by formatting + for _, v := range report.Violations { + p.processRegalViolation(fmt.Errorf("%s:%d: %s", filePath, v.Location.Row, v.Description), filePath) + } +} + +// Splits grouped errors into individual errors +func (p *PolicyToLint) processRegalViolation(rawErr error, path string) { if rawErr == nil { - return nil + return } - var errs []error + errorStr := rawErr.Error() // Regex matches file path, line number and error message like: /path/file:line: message errorRegex := regexp.MustCompile(`^` + regexp.QuoteMeta(path) + `:(\d+):\s*(.+)$`) - // Unwrap errors if rawErr is a joined error or has multiple wrapped errors - var list []error - if errsList, ok := rawErr.(interface{ Unwrap() []error }); ok { - list = errsList.Unwrap() - } else { - list = []error{rawErr} - } - - for _, err := range list { - errorStr := err.Error() + // Split by newlines to handle both single and multi-line errors + lines := strings.Split(errorStr, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if line == "" { + continue + } - // Split by newlines to handle both single and multi-line errors - lines := strings.Split(errorStr, "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if line == "" { - continue - } + // Skip the "N errors occurred" header + if strings.Contains(line, "errors occurred:") { + continue + } - // Skip the "N errors occurred" header - if strings.Contains(line, "errors occurred:") { + // Try to match the standard error format + if matches := errorRegex.FindStringSubmatch(line); len(matches) == 3 { + if lineNum, convErr := strconv.Atoi(matches[1]); convErr == nil { + p.AddError(path, matches[2], lineNum) continue } - - // Try to match the standard error format - if matches := errorRegex.FindStringSubmatch(line); len(matches) == 3 { - if lineNum, convErr := strconv.Atoi(matches[1]); convErr == nil { - errs = append(errs, fmt.Errorf("%s:%d: %s", path, lineNum, matches[2])) - continue - } - } - - // If we didn't match the standard format, preserve the original error - errs = append(errs, fmt.Errorf("%s: %s", path, line)) } - } - return errors.Join(errs...) + // If we didn't match the standard format, preserve the original error + p.AddError(path, line, 0) + } }