mirror of
https://github.com/hashicorp/packer.git
synced 2026-09-26 01:34:00 -04:00
* feat(provenance): add SLSA provenance and attestation signing libraries Add internal/provenance for deriving in-toto subjects from Packer artifacts, building SLSA Provenance v1 predicates, wrapping in-toto statements, and best-effort git/CI source detection. Add internal/attestation for DSSE envelope handling and a pluggable Signer/Verifier backend supporting key (local PEM), kms (aws/gcp/ azure/hashivault), and keyless (Sigstore Fulcio) modes, plus Sigstore bundle handling and DSSE/policy verification. Add the supporting module dependencies in go.mod/go.sum. * feat(provenance): add provenance post-processor Add the opt-in "provenance" post-processor that runs after a build, derives subjects from the artifact, emits DSSE-wrapped SLSA provenance (and optional SBOM) attestations, signs them via the configured signing backend, and writes sidecar files (including *.sigstore.json bundles in keyless mode). Register it in the core post-processor set. The provenance enable flag is a tri-state so an unset value stays enabled through HCL2 decoding instead of being silently disabled. * feat(provenance): add verify-attestation command Add "packer verify-attestation" to verify signed DSSE attestations against key, KMS, and keyless policy inputs, including optional Sigstore bundle checks for Rekor and timestamp evidence. Register the command in the CLI. * docs(provenance): add reference CI workflows and changelog Add reference GitHub Actions workflows under examples/ci for SLSA L2 keyless signing and L3-compatible delegated signing * fix: lint and tests * Added docs for Provenance PostProcessor
99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
// Copyright IBM Corp. 2024, 2025
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package hcl2template
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/gohcl"
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
)
|
|
|
|
// ProvisionerBlock references a detected but unparsed post processor
|
|
type PostProcessorBlock struct {
|
|
PType string
|
|
PName string
|
|
OnlyExcept OnlyExcept
|
|
KeepInputArtifact *bool
|
|
|
|
HCL2Ref
|
|
}
|
|
|
|
func (p *PostProcessorBlock) String() string {
|
|
return fmt.Sprintf(buildPostProcessorLabel+"-block %q %q", p.PType, p.PName)
|
|
}
|
|
|
|
func (p *Parser) decodePostProcessor(block *hcl.Block, ectx *hcl.EvalContext) (*PostProcessorBlock, hcl.Diagnostics) {
|
|
var b struct {
|
|
Name string `hcl:"name,optional"`
|
|
Only []string `hcl:"only,optional"`
|
|
Except []string `hcl:"except,optional"`
|
|
KeepInputArtifact *bool `hcl:"keep_input_artifact,optional"`
|
|
Rest hcl.Body `hcl:",remain"`
|
|
}
|
|
|
|
diags := gohcl.DecodeBody(block.Body, ectx, &b)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
postProcessor := &PostProcessorBlock{
|
|
PType: block.Labels[0],
|
|
PName: b.Name,
|
|
OnlyExcept: OnlyExcept{Only: b.Only, Except: b.Except},
|
|
HCL2Ref: newHCL2Ref(block, b.Rest),
|
|
KeepInputArtifact: b.KeepInputArtifact,
|
|
}
|
|
|
|
diags = diags.Extend(postProcessor.OnlyExcept.Validate())
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
return postProcessor, diags
|
|
}
|
|
|
|
func (cfg *PackerConfig) startPostProcessor(source SourceUseBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext) (packersdk.PostProcessor, hcl.Diagnostics) {
|
|
// ProvisionerBlock represents a detected but unparsed provisioner
|
|
var diags hcl.Diagnostics
|
|
|
|
postProcessor, err := cfg.parser.PluginConfig.PostProcessors.Start(pp.PType)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("Failed loading %s", pp.PType),
|
|
Subject: pp.DefRange.Ptr(),
|
|
Detail: err.Error(),
|
|
})
|
|
return nil, diags
|
|
}
|
|
|
|
builderVars := source.builderVariables()
|
|
builderVars["packer_core_version"] = cfg.CorePackerVersionString
|
|
builderVars["packer_debug"] = strconv.FormatBool(cfg.debug)
|
|
builderVars["packer_force"] = strconv.FormatBool(cfg.force)
|
|
builderVars["packer_on_error"] = cfg.onError
|
|
builderVars["packer_sensitive_variables"] = cfg.sensitiveInputVariableKeys()
|
|
|
|
hclPostProcessor := &HCL2PostProcessor{
|
|
PostProcessor: postProcessor,
|
|
postProcessorBlock: pp,
|
|
evalContext: ectx,
|
|
builderVariables: builderVars,
|
|
}
|
|
err = hclPostProcessor.HCL2Prepare(nil)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("Failed preparing %s", pp),
|
|
Detail: err.Error(),
|
|
Subject: pp.DefRange.Ptr(),
|
|
})
|
|
return nil, diags
|
|
}
|
|
return hclPostProcessor, diags
|
|
}
|