Documentation ¶
Overview ¶
Package img contains the required interfaces and logic to validate that an image has been issued by Teleport and can be trusted.
There are multiple image signature mechanisms competing, the Docker Content Trust (DCT) stores signatures in the manifest index itself. This approach is more constraining because the signed object and the original object end up having different Digests. Signatures cannot be added or modified a posteriori.
Cosign is another emerging signature standard, its signature specification is described here: https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md Cosign signatures are stored as images in the artifact registry, alongside the signed image. As signatures are stored separately, an object can be signed multiple times and this does not affect its digest. At the time of writing, cosign supports both static key signing and "keyless" (short-lived certificates) signing through the Fulcio CA. Keyless singing is still experimental and we don't use it yet, support might be added in the future.
The Cosign validator delegates all validation logic to the upstream cosign implementation. This is a good thing as we benefit from all the bug fixes and security audits they make. However, we still to test against a wide range of valid and invalid signatures to make sure we invoke cosign properly and validate all fields and claims. As there are no tools to craft broken and invalid signatures, we needed to write out own fixture generator. Fixture generation is done by `teleport/integrations/kube-agent-updater/hack/cosign-fixtures.go`. The executable generates a go file declaring all blobs and manifests to be loaded in the test registry.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NamedTaggedToDigest ¶
func NamedTaggedToDigest(image reference.NamedTagged) (name.Digest, error)
NamedTaggedToDigest resolves the digest of a reference.NamedTagged image and returns a name.Digest image corresponding to the resolved image.
Types ¶
type ImageNotValidatedError ¶
type ImageNotValidatedError struct {
// contains filtered or unexported fields
}
ImageNotValidatedError indicates that the validator did not validate the image. It wraps the original error and implements trace.ErrorWrapper.
func NotValidatedError ¶
func NotValidatedError(name string, image reference.NamedTagged, err error) *ImageNotValidatedError
NotValidatedError returns an ImageNotValidatedError if the error is not nil.
func (*ImageNotValidatedError) Error ¶
func (e *ImageNotValidatedError) Error() string
Error returns log friendly description of an error.
func (*ImageNotValidatedError) OrigError ¶
func (e *ImageNotValidatedError) OrigError() error
OrigError return the original error.
func (*ImageNotValidatedError) Unwrap ¶
func (e *ImageNotValidatedError) Unwrap() error
Unwrap unwraps the error and return the original error.
type NamedTaggedDigested ¶
NamedTaggedDigested is an object with a full name, a tag and a digest. A name and a digest are sufficient to canonically identify a layer, however the tag carries the version information. controller.VersionUpdater relies on the tag to detect what is the current version. The tag also allows users to determine which version is running by looking at the image reference. The digest ensures the container runtime will run the exact same image than the one currently treated.
func NewImageRef ¶
func NewImageRef(domain, path, tag string, imageDigest digest.Digest) NamedTaggedDigested
NewImageRef returns an image reference that is both Named, Tagged and Digested. In this setup the tag is typically superfluous, but in our case the tag carries the version information and makes the images friendlier for human operators.
type Validator ¶
type Validator interface { Name() string ValidateAndResolveDigest(ctx context.Context, image reference.NamedTagged) (NamedTaggedDigested, error) }
Validator validates that an image reference can be safely deployed. This typically involves validating that the image manifest has been signed by a trusted third party. The Validator also returns the image NamedTaggedDigested, this ensures the nodes cannot run something that has not been validated.
func NewCosignSingleKeyValidator ¶
NewCosignSingleKeyValidator takes a PEM-encoded public key and returns an img.Validator that checks the image was signed with cosign by the corresponding private key.
func NewImageValidatorMock ¶
func NewImageValidatorMock(name string, valid bool, image NamedTaggedDigested) Validator
NewImageValidatorMock creates a ValidatorMock
func NewInsecureValidator ¶
NewInsecureValidator returns an img.Validator that only resolves the image but does not check its signature. This must not be confused with NewNopValidator that returns a validator that always validate without resolving.
func NewNopValidator ¶
NewNopValidator returns an img.Validator that only resolves the image but does not check its signature.
type ValidatorMock ¶
type ValidatorMock struct {
// contains filtered or unexported fields
}
ValidatorMock is a fake validator that return a static answer. This is used for testing purposes and is inherently insecure.
func (ValidatorMock) Name ¶
func (i ValidatorMock) Name() string
Name returns the ValidatorMock name.
func (ValidatorMock) ValidateAndResolveDigest ¶
func (i ValidatorMock) ValidateAndResolveDigest(_ context.Context, _ reference.NamedTagged) (NamedTaggedDigested, error)
ValidateAndResolveDigest returns the statically defined image validation result.
type Validators ¶
type Validators []Validator
Validators is a list of Validator. They are OR-ed: if at least a Validator returns true, the image is validated.
func (Validators) Validate ¶
func (v Validators) Validate(ctx context.Context, image reference.NamedTagged) (NamedTaggedDigested, error)
Validate evaluates all Validators against an image reference until one Validator validates the image. If no Validator validates the image, it returns an error aggregate containing all Validator errors.