<?php
namespace Tuf\Metadata;
use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\Count;
use Symfony\Component\Validator\Constraints\EqualTo;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\IdenticalTo;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Validation;
use Tuf\Exception\MetadataException;
/**
* Trait with methods to provide common constraints.
*/
trait ConstraintsTrait
{
/**
* Validates the structure of the metadata.
*
* @param array $data
* The data to validate.
* @param \Symfony\Component\Validator\Constraints\Collection $constraints
* Th constraints collection for validation.
*
* @return void
*
* @throws \Tuf\Exception\MetadataException
* Thrown if validation fails.
*/
protected static function validate(array $data, Collection $constraints): void
{
$validator = Validation::createValidator();
$violations = $validator->validate($data, $constraints);
if (count($violations)) {
$exceptionMessages = [];
foreach ($violations as $violation) {
$exceptionMessages[] = (string) $violation;
}
throw new MetadataException(implode(", \n", $exceptionMessages));
}
}
/**
* Gets the common hash constraints.
*
* @return \Symfony\Component\Validator\Constraint[][]
* The hash constraints.
*/
protected static function getHashesConstraints(): array
{
return [
'hashes' => [
new Count(['min' => 1]),
new Type('array'),
// The keys for 'hashes is not know but they all must be strings.
new All([
new Type('string'),
new NotBlank(),
]),
],
];
}
/**
* Gets the common version constraints.
*
* @return \Symfony\Component\Validator\Constraint[][]
* The version constraints.
*/
protected static function getVersionConstraints(): array
{
return [
'version' => [
new Type('integer'),
new GreaterThanOrEqual(1),
],
];
}
/**
* Gets the common threshold constraints.
*
* @return \Symfony\Component\Validator\Constraint[][]
* The threshold constraints.
*/
protected static function getThresholdConstraints(): array
{
return [
'threshold' => [
new Type('integer'),
new GreaterThanOrEqual(1),
],
];
}
/**
* Gets the common keyids constraints.
*
* @return \Symfony\Component\Validator\Constraint[][]
* The keysids constraints.
*/
protected static function getKeyidsConstraints(): array
{
return [
'keyids' => [
new Count(['min' => 1]),
new Type('array'),
// The keys for 'hashes is not know but they all must be strings.
new All([
new Type('string'),
new NotBlank(),
]),
],
];
}
/**
* Gets the common key Collection constraints.
*
* @return Collection
* The 'key' Collection constraint.
*/
protected static function getKeyConstraints(): Collection
{
return new Collection([
// This field is not part of the TUF specification and is being
// removed from the Python TUF reference implementation in
// https://github.com/theupdateframework/tuf/issues/848.
// If it is provided though we only support the default value which
// is passed on from a setting in the Python `securesystemslib`
// library.
'keyid_hash_algorithms' => new Optional([
new EqualTo(['value' => ["sha256", "sha512"]]),
]),
'keytype' => [
new Type('string'),
new IdenticalTo('ed25519'),
],
'keyval' => [
new Type('array'),
new Collection([
'public' => [
new Type('string'),
new NotBlank(),
],
]),
],
'scheme' => [
new Type('string'),
new NotBlank(),
],
]);
}
/**
* Gets the role constraints.
*
* @return \Symfony\Component\Validator\Constraints\Collection
* The role constraints collection.
*/
protected static function getRoleConstraints(): Collection
{
return new Collection(
static::getKeyidsConstraints() +
static::getThresholdConstraints()
);
}
}