Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
"homepage": "https://github.com/php/pie/graphs/contributors"
}
],
"repositories": {
"attestation": {
"type": "vcs",
"url": "https://github.com/asgrim/attestation.git"
}
},
"require": {
"php": "8.1.*||8.2.*||8.3.*||8.4.*||8.5.*",
"composer/composer": "^2.8.11",
Expand All @@ -37,6 +43,7 @@
"symfony/console": "^6.4.25",
"symfony/event-dispatcher": "^6.4.24",
"symfony/process": "^6.4.25",
"thephpf/attestation": "dev-port-pie-initial-implementation",
"webmozart/assert": "^1.11"
},
"require-dev": {
Expand Down
61 changes: 59 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Command/SelfUpdateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
$httpDownloader = new HttpDownloader($this->io, $composer->getConfig());
$authHelper = new AuthHelper($this->io, $composer->getConfig());
$fetchLatestPieRelease = new FetchPieReleaseFromGitHub($this->githubApiBaseUrl, $httpDownloader, $authHelper);
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory($this->githubApiBaseUrl, $httpDownloader, $authHelper);
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory();

if ($input->hasOption(self::OPTION_NIGHTLY_UPDATE) && $input->getOption(self::OPTION_NIGHTLY_UPDATE)) {
$latestRelease = new ReleaseMetadata(
Expand Down
26 changes: 3 additions & 23 deletions src/Command/SelfVerifyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@

namespace Php\Pie\Command;

use Composer\Util\AuthHelper;
use Composer\Util\HttpDownloader;
use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Php\Pie\ComposerIntegration\QuieterConsoleIO;
use Php\Pie\File\BinaryFile;
use Php\Pie\File\FullPathToSelf;
use Php\Pie\SelfManage\Update\ReleaseMetadata;
use Php\Pie\SelfManage\Verify\FailedToVerifyRelease;
use Php\Pie\SelfManage\Verify\VerifyPieReleaseUsingAttestation;
use Php\Pie\Util\Emoji;
use Php\Pie\Util\PieVersion;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -30,11 +24,7 @@
)]
final class SelfVerifyCommand extends Command
{
/** @param non-empty-string $githubApiBaseUrl */
public function __construct(
private readonly string $githubApiBaseUrl,
private readonly QuieterConsoleIO $io,
private readonly ContainerInterface $container,
private readonly FullPathToSelf $fullPathToSelf,
) {
parent::__construct();
Expand All @@ -55,19 +45,9 @@ public function execute(InputInterface $input, OutputInterface $output): int
return Command::FAILURE;
}

$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $output);
$composer = PieComposerFactory::createPieComposer(
$this->container,
PieComposerRequest::noOperation(
$output,
$targetPlatform,
),
);
$httpDownloader = new HttpDownloader($this->io, $composer->getConfig());
$authHelper = new AuthHelper($this->io, $composer->getConfig());
$latestRelease = new ReleaseMetadata(PieVersion::get(), 'blah');
$pharFilename = BinaryFile::fromFileWithSha256Checksum(($this->fullPathToSelf)());
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory($this->githubApiBaseUrl, $httpDownloader, $authHelper);
$latestRelease = new ReleaseMetadata(PieVersion::get(), 'blah');
$pharFilename = BinaryFile::fromFileWithSha256Checksum(($this->fullPathToSelf)());
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory();

try {
$verifyPiePhar->verify($latestRelease, $pharFilename, $output);
Expand Down
65 changes: 3 additions & 62 deletions src/SelfManage/Verify/FailedToVerifyRelease.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,19 @@

namespace Php\Pie\SelfManage\Verify;

use Php\Pie\File\BinaryFile;
use Php\Pie\SelfManage\Update\ReleaseMetadata;
use RuntimeException;
use Symfony\Component\Process\Exception\ProcessFailedException;
use ThePhpFoundation\Attestation\Verification\Exception\FailedToVerifyArtifact;

use function implode;
use function is_array;
use function sprintf;
use function strlen;
use function trim;

class FailedToVerifyRelease extends RuntimeException
{
public static function fromInvalidSubjectDefinition(): self
public static function fromAttestationException(FailedToVerifyArtifact $failedToVerifyArtifact): self
{
return new self('Unable to extract subject digest from the dsseEnvelope in the attestation.');
}

public static function fromMissingAttestation(ReleaseMetadata $releaseMetadata, BinaryFile $file): self
{
return new self(sprintf(
'Attestation for %s (sha256:%s) was not found',
$releaseMetadata->tag,
$file->checksum,
));
}

public static function fromSignatureVerificationFailed(int $attestationIndex, ReleaseMetadata $releaseMetadata): self
{
return new self(sprintf(
'Failed to verify DSSE Envelope payload signature for attestation %d for %s',
$attestationIndex,
$releaseMetadata->tag,
));
}

/** @param array<string,string>|string $issuer */
public static function fromIssuerCertificateVerificationFailed(array|string $issuer): self
{
return new self(sprintf(
'Failed to verify the attestation certificate was issued by trusted root %s',
is_array($issuer) ? implode(',', $issuer) : $issuer,
));
}

/** @param array<string,string>|string $issuer */
public static function fromNoIssuerCertificateInTrustedRoot(array|string $issuer): self
{
return new self(sprintf(
'Could not find a trusted root certificate for issuer %s',
is_array($issuer) ? implode(',', $issuer) : $issuer,
));
}

public static function fromInvalidDerEncodedStringLength(string $derEncodedString, int $expectedLength): self
{
return new self(sprintf(
'DER encoded string length of "%s" was wrong; expected %d characters, was actually %d characters',
$derEncodedString,
$expectedLength,
strlen($derEncodedString),
));
}

public static function fromMismatchingExtensionValues(string $extension, string $expected, string $actual): self
{
return new self(sprintf(
'Attestation certificate extension %s mismatch; expected "%s", was "%s"',
$extension,
$expected,
$actual,
));
return new self($failedToVerifyArtifact->getMessage(), 0, $failedToVerifyArtifact);
}

public static function fromNoOpenssl(): self
Expand Down
Loading
Loading