diff --git a/cmd/compare/compare.go b/cmd/compare/compare.go index 327e60341..416c604a0 100644 --- a/cmd/compare/compare.go +++ b/cmd/compare/compare.go @@ -26,15 +26,17 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/yaml" + "github.com/conforma/cli/internal/policy" "github.com/conforma/cli/internal/policy/equivalence" ) var ( - effectiveTime string - imageDigest string - imageRef string - imageURL string - outputFormat string + effectiveTime string + allowPastEffectiveTime bool + imageDigest string + imageRef string + imageURL string + outputFormat string ) var CompareCmd *cobra.Command @@ -74,6 +76,7 @@ Examples: } compareCmd.Flags().StringVar(&effectiveTime, "effective-time", "now", "Effective time for policy evaluation (RFC3339 format, 'now')") + compareCmd.Flags().BoolVar(&allowPastEffectiveTime, "allow-past-effective-time", false, "Allow setting --effective-time to a date in the past") compareCmd.Flags().StringVar(&imageDigest, "image-digest", "", "Image digest for volatile config matching") compareCmd.Flags().StringVar(&imageRef, "image-ref", "", "Image reference for volatile config matching") compareCmd.Flags().StringVar(&imageURL, "image-url", "", "Image URL for volatile config matching") @@ -84,20 +87,12 @@ Examples: func runCompare(cmd *cobra.Command, args []string) error { - // Parse effective time - var effectiveTimeValue time.Time - switch effectiveTime { - case "now": - effectiveTimeValue = time.Now().UTC() - case "attestation": - // For now, use current time as default for attestation time + effectiveTimeValue, err := policy.ParseEffectiveTime(effectiveTime, allowPastEffectiveTime) + if err != nil { + return err + } + if effectiveTimeValue.IsZero() { effectiveTimeValue = time.Now().UTC() - default: - var err error - effectiveTimeValue, err = time.Parse(time.RFC3339, effectiveTime) - if err != nil { - return fmt.Errorf("invalid effective time format: %w", err) - } } // Create image info if provided diff --git a/cmd/validate/image.go b/cmd/validate/image.go index 8fb17e8f2..816c39e00 100644 --- a/cmd/validate/image.go +++ b/cmd/validate/image.go @@ -202,7 +202,8 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { data.policyConfiguration = policyConfiguration policyOptions := policy.Options{ - EffectiveTime: data.effectiveTime, + EffectiveTime: data.effectiveTime, + AllowPastEffectiveTime: data.allowPastEffectiveTime, Identity: cosign.Identity{ Issuer: data.certificateOIDCIssuer, IssuerRegExp: data.certificateOIDCIssuerRegExp, @@ -547,6 +548,11 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { a RFC3339 formatted value, e.g. 2022-11-18T00:00:00Z. `)) + cmd.Flags().BoolVar(&data.allowPastEffectiveTime, "allow-past-effective-time", false, hd.Doc(` + Allow setting --effective-time to a date in the past. By default, dates + more than 5 minutes in the past are rejected. + `)) + cmd.Flags().StringSliceVar(&data.extraRuleData, "extra-rule-data", data.extraRuleData, hd.Doc(` Extra data to be provided to the Rego policy evaluator. Use format 'key=value'. May be used multiple times. `)) @@ -633,6 +639,7 @@ type imageData struct { certificateOIDCIssuer string certificateOIDCIssuerRegExp string effectiveTime string + allowPastEffectiveTime bool extraRuleData []string filePath string filterType string diff --git a/cmd/validate/image_test.go b/cmd/validate/image_test.go index 4ef655993..697d81c0d 100644 --- a/cmd/validate/image_test.go +++ b/cmd/validate/image_test.go @@ -598,6 +598,7 @@ spec: "/policy.yaml", "--effective-time", "1970-01-01", + "--allow-past-effective-time", }...) cmd.SetArgs(args) diff --git a/cmd/validate/input.go b/cmd/validate/input.go index 5d056bc66..89e1ea82a 100644 --- a/cmd/validate/input.go +++ b/cmd/validate/input.go @@ -43,20 +43,21 @@ type InputValidationFunc func(context.Context, string, policy.Policy, bool) (*ou func validateInputCmd(validate InputValidationFunc) *cobra.Command { data := struct { - effectiveTime string - filePaths []string - forceColor bool - info bool - namespaces []string - noColor bool - output []string - policy policy.Policy - policyConfiguration string - strict bool - workers int - serverMode bool - serverAddress string - serverPort int + effectiveTime string + allowPastEffectiveTime bool + filePaths []string + forceColor bool + info bool + namespaces []string + noColor bool + output []string + policy policy.Policy + policyConfiguration string + strict bool + workers int + serverMode bool + serverAddress string + serverPort int }{ strict: true, workers: 5, @@ -168,7 +169,7 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { } data.policyConfiguration = policyConfiguration - if p, err := policy.NewInputPolicy(cmd.Context(), data.policyConfiguration, data.effectiveTime); err != nil { + if p, err := policy.NewInputPolicy(cmd.Context(), data.policyConfiguration, data.effectiveTime, data.allowPastEffectiveTime); err != nil { allErrors = errors.Join(allErrors, err) } else { data.policy = p @@ -349,6 +350,10 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { effective dates in the future. The value can be "now" (default) - for current time, or a RFC3339 formatted value, e.g. 2022-11-18T00:00:00Z.`)) + cmd.Flags().BoolVar(&data.allowPastEffectiveTime, "allow-past-effective-time", false, hd.Doc(` + Allow setting --effective-time to a date in the past. By default, dates + more than 5 minutes in the past are rejected.`)) + cmd.Flags().BoolVar(&data.info, "info", data.info, hd.Doc(` Include additional information on the failures. For instance for policy violations, include the title and the description of the failed policy diff --git a/docs/modules/ROOT/pages/ec_compare.adoc b/docs/modules/ROOT/pages/ec_compare.adoc index ab77552d9..148c3c80e 100644 --- a/docs/modules/ROOT/pages/ec_compare.adoc +++ b/docs/modules/ROOT/pages/ec_compare.adoc @@ -33,6 +33,7 @@ ec compare [flags] ---- == Options +--allow-past-effective-time:: Allow setting --effective-time to a date in the past (Default: false) --effective-time:: Effective time for policy evaluation (RFC3339 format, 'now') (Default: now) -h, --help:: help for compare (Default: false) --image-digest:: Image digest for volatile config matching diff --git a/docs/modules/ROOT/pages/ec_validate_image.adoc b/docs/modules/ROOT/pages/ec_validate_image.adoc index c0f656352..77d08b08e 100644 --- a/docs/modules/ROOT/pages/ec_validate_image.adoc +++ b/docs/modules/ROOT/pages/ec_validate_image.adoc @@ -111,6 +111,9 @@ Use a regular expression to match certificate attributes. == Options +--allow-past-effective-time:: Allow setting --effective-time to a date in the past. By default, dates +more than 5 minutes in the past are rejected. + (Default: false) --attestation-format:: Attestation output format: dsse (signed envelope), predicate (raw JSON) (Default: dsse) --attestation-output-dir:: Directory for attestation output files. Defaults to a temp directory under /tmp. Must be under /tmp or the current working directory. --certificate-identity:: URL of the certificate identity for keyless verification diff --git a/docs/modules/ROOT/pages/ec_validate_input.adoc b/docs/modules/ROOT/pages/ec_validate_input.adoc index 68ef734c5..e3351582c 100644 --- a/docs/modules/ROOT/pages/ec_validate_input.adoc +++ b/docs/modules/ROOT/pages/ec_validate_input.adoc @@ -75,6 +75,8 @@ Start the server on a custom port: == Options +--allow-past-effective-time:: Allow setting --effective-time to a date in the past. By default, dates +more than 5 minutes in the past are rejected. (Default: false) --color:: Enable color when using text output even when the current terminal does not support it (Default: false) --effective-time:: Run policy checks with the provided time. Useful for testing rules with effective dates in the future. The value can be "now" (default) - for diff --git a/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc b/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc index dd90b8a28..437aaf3fe 100644 --- a/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc +++ b/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc @@ -57,6 +57,9 @@ paths can be provided by using the `:` separator. *EFFECTIVE_TIME* (`string`):: Run policy checks with the provided time. + *Default*: `now` +*ALLOW_PAST_EFFECTIVE_TIME* (`string`):: Allow setting EFFECTIVE_TIME to a date in the past. ++ +*Default*: `false` *EXTRA_RULE_DATA* (`string`):: Merge additional Rego variables into the policy data. Use syntax "key=value,key2=value2..." *POLICY_BUNDLE_DIGEST* (`string`):: Optional OCI digest to pin the release policy bundle. When provided, the policy configuration is resolved and the reference oci::quay.io/conforma/release-policy:konflux is replaced with oci::quay.io/conforma/release-policy@. Accepts a full digest (sha256:abc123...) or just the hex hash (abc123...). + diff --git a/docs/modules/ROOT/pages/verify-enterprise-contract.adoc b/docs/modules/ROOT/pages/verify-enterprise-contract.adoc index 339e27908..5523113ce 100644 --- a/docs/modules/ROOT/pages/verify-enterprise-contract.adoc +++ b/docs/modules/ROOT/pages/verify-enterprise-contract.adoc @@ -68,6 +68,9 @@ paths can be provided by using the `:` separator. *EFFECTIVE_TIME* (`string`):: Run policy checks with the provided time. + *Default*: `now` +*ALLOW_PAST_EFFECTIVE_TIME* (`string`):: Allow setting EFFECTIVE_TIME to a date in the past. ++ +*Default*: `false` *EXTRA_RULE_DATA* (`string`):: Merge additional Rego variables into the policy data. Use syntax "key=value,key2=value2..." *POLICY_BUNDLE_DIGEST* (`string`):: Optional OCI digest to pin the release policy bundle. When provided, the policy configuration is resolved and the reference oci::quay.io/conforma/release-policy:konflux is replaced with oci::quay.io/conforma/release-policy@. Accepts a full digest (sha256:abc123...) or just the hex hash (abc123...). + diff --git a/features/task_validate_image.feature b/features/task_validate_image.feature index 7b48083a1..66095fd16 100644 --- a/features/task_validate_image.feature +++ b/features/task_validate_image.feature @@ -356,10 +356,11 @@ Feature: Verify Enterprise Contract Tekton Tasks {"publicKey": ${known_PUBLIC_KEY}} ``` When version 0.1 of the task named "verify-enterprise-contract" is run with parameters: - | IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/effective-time"}]} | - | POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} | - | IGNORE_REKOR | true | - | EFFECTIVE_TIME | 2020-01-01T00:00:00Z | + | IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/effective-time"}]} | + | POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} | + | IGNORE_REKOR | true | + | EFFECTIVE_TIME | 2020-01-01T00:00:00Z | + | ALLOW_PAST_EFFECTIVE_TIME | true | Then the task should succeed And the task logs for step "show-config" should contain `"effective-time": "2020-01-01T00:00:00Z"` diff --git a/features/validate_image.feature b/features/validate_image.feature index c6c43d835..5b7c1f64f 100644 --- a/features/validate_image.feature +++ b/features/validate_image.feature @@ -851,7 +851,7 @@ Feature: evaluate enterprise contract ] } """ - When ec command is run with "validate image --image ${REGISTRY}/acceptance/image --policy acceptance/ec-policy --rekor-url ${REKOR} --public-key ${known_PUBLIC_KEY} --output=json --effective-time 2014-05-31 --show-successes" + When ec command is run with "validate image --image ${REGISTRY}/acceptance/image --policy acceptance/ec-policy --rekor-url ${REKOR} --public-key ${known_PUBLIC_KEY} --output=json --effective-time 2014-05-31 --allow-past-effective-time --show-successes" Then the exit status should be 0 And the output should match the snapshot diff --git a/internal/input/report_test.go b/internal/input/report_test.go index 1ac2ab454..32787fe1f 100644 --- a/internal/input/report_test.go +++ b/internal/input/report_test.go @@ -414,7 +414,7 @@ sources: exclude: [] ` - p, err := policy.NewInputPolicy(ctx, policyConfiguration, "now") + p, err := policy.NewInputPolicy(ctx, policyConfiguration, "now", false) assert.NoError(t, err) return p } diff --git a/internal/input/validate_test.go b/internal/input/validate_test.go index 5659640ff..5419ba423 100644 --- a/internal/input/validate_test.go +++ b/internal/input/validate_test.go @@ -146,7 +146,7 @@ func Test_ValidatePipeline(t *testing.T) { errFile := afero.WriteFile(appFS, validFile, []byte("data"), 0o777) assert.NoError(t, errFile) ctx := utils.WithFS(context.Background(), appFS) - policy, err := policy.NewInputPolicy(ctx, "", "2023-01-01T00:00:00.00Z") + policy, err := policy.NewInputPolicy(ctx, "", "2023-01-01T00:00:00.00Z", true) assert.NoError(t, err) for _, tt := range tests { diff --git a/internal/policy/policy.go b/internal/policy/policy.go index b76fbd260..9d9c1dad0 100644 --- a/internal/policy/policy.go +++ b/internal/policy/policy.go @@ -167,21 +167,22 @@ func (p *policy) SigstoreOpts() (SigstoreOpts, error) { } type Options struct { - EffectiveTime string - Identity cosign.Identity - IgnoreRekor bool - SkipImageSigCheck bool - SkipAttSigCheck bool - PolicyRef string - PublicKey string - RekorURL string + EffectiveTime string + AllowPastEffectiveTime bool + Identity cosign.Identity + IgnoreRekor bool + SkipImageSigCheck bool + SkipAttSigCheck bool + PolicyRef string + PublicKey string + RekorURL string } // NewOfflinePolicy construct and return a new instance of Policy that is used // in offline scenarios, i.e. without cluster or specific services access, and // no signature verification being performed. func NewOfflinePolicy(ctx context.Context, effectiveTime string) (Policy, error) { - if efn, err := parseEffectiveTime(effectiveTime); err == nil { + if efn, err := parseEffectiveTime(effectiveTime, true); err == nil { return &policy{ effectiveTime: efn, choosenTime: effectiveTime, @@ -219,8 +220,8 @@ func NewInertPolicy(ctx context.Context, policyRef string) (Policy, error) { // resource in Kubernetes using the format: [namespace/]name // // If policyRef is blank, an empty EnterpriseContractPolicySpec is used. -func NewInputPolicy(ctx context.Context, policyRef string, effectiveTime string) (Policy, error) { - if efn, err := parseEffectiveTime(effectiveTime); err == nil { +func NewInputPolicy(ctx context.Context, policyRef string, effectiveTime string, allowPastEffectiveTime bool) (Policy, error) { + if efn, err := parseEffectiveTime(effectiveTime, allowPastEffectiveTime); err == nil { p := policy{ choosenTime: effectiveTime, checkOpts: &cosign.CheckOpts{}, @@ -299,7 +300,7 @@ func NewPolicy(ctx context.Context, opts Options) (Policy, error) { } } - if efn, err := parseEffectiveTime(opts.EffectiveTime); err != nil { + if efn, err := parseEffectiveTime(opts.EffectiveTime, opts.AllowPastEffectiveTime); err != nil { return nil, err } else { p.effectiveTime = efn @@ -421,7 +422,28 @@ func isNow(choosenTime string) bool { return strings.EqualFold(choosenTime, Now) } -func parseEffectiveTime(choosenTime string) (*time.Time, error) { +// pastEffectiveTimeGracePeriod is the tolerance for clock skew when rejecting +// past effective-time values. Times within this window are accepted even +// without --allow-past-effective-time. +const pastEffectiveTimeGracePeriod = 5 * time.Minute + +// ParseEffectiveTime parses the effective-time string and returns the resolved +// time. It accepts "now", "attestation", RFC3339, or YYYY-MM-DD formats. When +// allowPast is false, times more than 5 minutes in the past are rejected. +// The "attestation" sentinel returns a zero time.Time — callers should handle +// that case separately. +func ParseEffectiveTime(choosenTime string, allowPast bool) (time.Time, error) { + t, err := parseEffectiveTime(choosenTime, allowPast) + if err != nil { + return time.Time{}, err + } + if t == nil { + return time.Time{}, nil + } + return *t, nil +} + +func parseEffectiveTime(choosenTime string, allowPast bool) (*time.Time, error) { switch { case isNow(choosenTime): now := now().UTC() @@ -435,6 +457,9 @@ func parseEffectiveTime(choosenTime string) (*time.Time, error) { if when, err := time.Parse(time.RFC3339, choosenTime); err == nil { log.Debugf("Using provided effective time %s", when.Format(time.RFC3339)) whenUTC := when.UTC() + if err := rejectPastTime(whenUTC, allowPast); err != nil { + return nil, err + } return &whenUTC, nil } @@ -444,6 +469,9 @@ func parseEffectiveTime(choosenTime string) (*time.Time, error) { if when, err := time.Parse(DateFormat, choosenTime); err == nil { log.Debugf("Using provided effective time %s", when.Format(time.RFC3339)) whenUTC := when.UTC() + if err := rejectPastTime(whenUTC, allowPast); err != nil { + return nil, err + } return &whenUTC, nil } log.Debugf("Unable to parse provided effective time string `%s` using %s format", choosenTime, DateFormat) @@ -453,6 +481,17 @@ func parseEffectiveTime(choosenTime string) (*time.Time, error) { } } +func rejectPastTime(when time.Time, allowPast bool) error { + if allowPast { + return nil + } + threshold := now().UTC().Add(-pastEffectiveTimeGracePeriod) + if when.Before(threshold) { + return fmt.Errorf("effective time %s is in the past; use --allow-past-effective-time to override", when.Format(time.RFC3339)) + } + return nil +} + // checkOpts returns an instance based on attributes of the Policy. func checkOpts(ctx context.Context, p *policy) (*cosign.CheckOpts, error) { var err error diff --git a/internal/policy/policy_test.go b/internal/policy/policy_test.go index c528ffb31..a292bc9df 100644 --- a/internal/policy/policy_test.go +++ b/internal/policy/policy_test.go @@ -245,10 +245,11 @@ func TestNewPolicy(t *testing.T) { utils.SetTestRekorPublicKey(t) got, err := NewPolicy(ctx, Options{ - PolicyRef: c.policyRef, - RekorURL: c.rekorUrl, - PublicKey: c.publicKey, - EffectiveTime: timeNowStr, + PolicyRef: c.policyRef, + RekorURL: c.rekorUrl, + PublicKey: c.publicKey, + EffectiveTime: timeNowStr, + AllowPastEffectiveTime: true, }) if c.expectErr { @@ -656,10 +657,10 @@ func TestIdentity(t *testing.T) { } func TestParseEffectiveTime(t *testing.T) { - _, err := parseEffectiveTime("") + _, err := parseEffectiveTime("", false) assert.ErrorContains(t, err, "invalid policy time argument") - effective, err := parseEffectiveTime(Now) + effective, err := parseEffectiveTime(Now, false) assert.NoError(t, err) assert.Equal(t, time.UTC, effective.Location()) @@ -671,22 +672,72 @@ func TestParseEffectiveTime(t *testing.T) { epoch := time.Unix(0, 0).UTC() now = func() time.Time { return epoch } - effective, err = parseEffectiveTime(Now) + effective, err = parseEffectiveTime(Now, false) assert.NoError(t, err) assert.NotNil(t, effective) assert.Equal(t, epoch, *effective) - effective, err = parseEffectiveTime("2001-02-03T04:05:06+07:00") + effective, err = parseEffectiveTime("2001-02-03T04:05:06+07:00", true) assert.NoError(t, err) assert.NotNil(t, effective) assert.Equal(t, time.Date(2001, 2, 2, 21, 5, 6, 0, time.UTC), *effective) - effective, err = parseEffectiveTime("2001-02-03") + effective, err = parseEffectiveTime("2001-02-03", true) assert.NoError(t, err) assert.NotNil(t, effective) assert.Equal(t, time.Date(2001, 2, 3, 0, 0, 0, 0, time.UTC), *effective) - effective, err = parseEffectiveTime("attestation") + effective, err = parseEffectiveTime("attestation", false) + assert.NoError(t, err) + assert.Nil(t, effective) +} + +func TestParseEffectiveTimePastRejection(t *testing.T) { + then := now + t.Cleanup(func() { + now = then + }) + + fixedNow := time.Date(2025, 7, 20, 12, 0, 0, 0, time.UTC) + now = func() time.Time { return fixedNow } + + // Past date (RFC3339) rejected by default + _, err := parseEffectiveTime("2025-01-01T00:00:00Z", false) + assert.ErrorContains(t, err, "is in the past") + assert.ErrorContains(t, err, "--allow-past-effective-time") + + // Past date (date-only) rejected by default + _, err = parseEffectiveTime("2025-01-01", false) + assert.ErrorContains(t, err, "is in the past") + + // Past date allowed with allowPast=true + effective, err := parseEffectiveTime("2025-01-01T00:00:00Z", true) + assert.NoError(t, err) + assert.NotNil(t, effective) + + // Time within 5-minute grace period is accepted + withinGrace := fixedNow.Add(-3 * time.Minute).Format(time.RFC3339) + effective, err = parseEffectiveTime(withinGrace, false) + assert.NoError(t, err) + assert.NotNil(t, effective) + + // Time just past the 5-minute grace period is rejected + pastGrace := fixedNow.Add(-6 * time.Minute).Format(time.RFC3339) + _, err = parseEffectiveTime(pastGrace, false) + assert.ErrorContains(t, err, "is in the past") + + // Future date is always accepted + effective, err = parseEffectiveTime("2030-01-01T00:00:00Z", false) + assert.NoError(t, err) + assert.NotNil(t, effective) + + // "now" is unaffected + effective, err = parseEffectiveTime(Now, false) + assert.NoError(t, err) + assert.NotNil(t, effective) + + // "attestation" is unaffected + effective, err = parseEffectiveTime("attestation", false) assert.NoError(t, err) assert.Nil(t, effective) } @@ -1152,7 +1203,7 @@ func TestNewInputPolicy(t *testing.T) { t.Run(c.name, func(t *testing.T) { ctx := context.Background() - policy, err := NewInputPolicy(ctx, c.policyRef, c.effectiveTime) + policy, err := NewInputPolicy(ctx, c.policyRef, c.effectiveTime, true) if c.expectErr { assert.Error(t, err, "Expected error for invalid input") @@ -1323,8 +1374,9 @@ func TestPreProcessPolicy(t *testing.T) { { name: "successful preprocessing with simple policy", policyOptions: Options{ - PolicyRef: fmt.Sprintf(`{"publicKey": %s}`, utils.TestPublicKeyJSON), - EffectiveTime: "2023-01-01T12:00:00Z", + PolicyRef: fmt.Sprintf(`{"publicKey": %s}`, utils.TestPublicKeyJSON), + EffectiveTime: "2023-01-01T12:00:00Z", + AllowPastEffectiveTime: true, }, expectErr: false, description: "Should successfully preprocess a simple policy without sources", @@ -1342,7 +1394,8 @@ func TestPreProcessPolicy(t *testing.T) { } ] }`, utils.TestPublicKeyJSON), - EffectiveTime: "2023-01-01T12:00:00Z", + EffectiveTime: "2023-01-01T12:00:00Z", + AllowPastEffectiveTime: true, }, mockDownload: func(ctx context.Context, dest, source string, showMsg bool) (metadata.Metadata, error) { // Mock successful download @@ -1367,7 +1420,8 @@ func TestPreProcessPolicy(t *testing.T) { } ] }`, utils.TestPublicKeyJSON), - EffectiveTime: "2023-01-01T12:00:00Z", + EffectiveTime: "2023-01-01T12:00:00Z", + AllowPastEffectiveTime: true, }, mockDownload: func(ctx context.Context, dest, source string, showMsg bool) (metadata.Metadata, error) { return nil, fmt.Errorf("network error: connection refused") @@ -1379,8 +1433,9 @@ func TestPreProcessPolicy(t *testing.T) { { name: "failed preprocessing with invalid policy reference", policyOptions: Options{ - PolicyRef: `{"invalid": "json""}`, - EffectiveTime: "2023-01-01T12:00:00Z", + PolicyRef: `{"invalid": "json""}`, + EffectiveTime: "2023-01-01T12:00:00Z", + AllowPastEffectiveTime: true, }, expectErr: true, errMsg: "unable to parse", diff --git a/tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml b/tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml index c4e68d677..0c6d62a33 100644 --- a/tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml +++ b/tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml @@ -152,6 +152,10 @@ spec: type: string description: Run policy checks with the provided time. default: "now" + - name: ALLOW_PAST_EFFECTIVE_TIME + type: string + description: Allow setting EFFECTIVE_TIME to a date in the past. + default: "false" - name: EXTRA_RULE_DATA type: string description: Merge additional Rego variables into the policy data. Use syntax "key=value,key2=value2..." @@ -431,6 +435,7 @@ spec: --show-successes=true --show-policy-docs-link=true --effective-time="${EFFECTIVE_TIME}" + --allow-past-effective-time="${ALLOW_PAST_EFFECTIVE_TIME}" --extra-rule-data="${EXTRA_RULE_DATA}" --retry-max-wait="${RETRY_MAX_WAIT}" --retry-max-retry="${RETRY_MAX_RETRY}" @@ -514,6 +519,8 @@ spec: value: "$(params.INFO)" - name: EFFECTIVE_TIME value: "$(params.EFFECTIVE_TIME)" + - name: ALLOW_PAST_EFFECTIVE_TIME + value: "$(params.ALLOW_PAST_EFFECTIVE_TIME)" - name: EXTRA_RULE_DATA value: "$(params.EXTRA_RULE_DATA)" - name: RETRY_MAX_WAIT diff --git a/tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml b/tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml index b5282ebe6..d62830505 100644 --- a/tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml +++ b/tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml @@ -159,6 +159,10 @@ spec: type: string description: Run policy checks with the provided time. default: "now" + - name: ALLOW_PAST_EFFECTIVE_TIME + type: string + description: Allow setting EFFECTIVE_TIME to a date in the past. + default: "false" - name: EXTRA_RULE_DATA type: string description: Merge additional Rego variables into the policy data. Use syntax "key=value,key2=value2..." @@ -379,6 +383,7 @@ spec: --show-successes=true --show-policy-docs-link=true --effective-time="${EFFECTIVE_TIME}" + --allow-past-effective-time="${ALLOW_PAST_EFFECTIVE_TIME}" --extra-rule-data="${EXTRA_RULE_DATA}" --retry-max-wait="${RETRY_MAX_WAIT}" --retry-max-retry="${RETRY_MAX_RETRY}" @@ -416,6 +421,8 @@ spec: value: "$(params.INFO)" - name: EFFECTIVE_TIME value: "$(params.EFFECTIVE_TIME)" + - name: ALLOW_PAST_EFFECTIVE_TIME + value: "$(params.ALLOW_PAST_EFFECTIVE_TIME)" - name: EXTRA_RULE_DATA value: "$(params.EXTRA_RULE_DATA)" - name: RETRY_MAX_WAIT