commit signing hell

This commit is contained in:
Ian Gulliver
2026-10-18 22:55:23 -07:00
parent 95389d0d92
commit 380e533ef4
8 changed files with 402 additions and 280 deletions
+35 -2
View File
@@ -14,6 +14,17 @@ private let maxMessage = 256 << 20
private let maxRead = 64 << 20
private let copyTimeoutMs = 10 * 60 * 1000
// The signature goes to a file, since a login shell's startup files can print to stdout.
private let signScript = """
format=$(git config gpg.format || echo openpgp)
case $format in
openpgp) program=$(git config gpg.openpgp.program || git config gpg.program || echo gpg) ;;
x509) program=$(git config gpg.x509.program || echo gpgsm) ;;
*) echo "byre can't sign with gpg.format $format" >&2; exit 1 ;;
esac
exec "$program" --status-fd=2 -bsau "$(git config user.signingkey || echo "$1")" >"$2"
"""
@MainActor
final class Remote {
let api: API
@@ -158,9 +169,31 @@ final class Remote {
case .hands:
let result = try await hands.call(req.tool ?? "", req.arguments?.additionalProperties ?? OpenAPIObjectContainer())
return ClientReply(id: req.id, result: .init(additionalProperties: result))
case .sign:
let (code, status, signature) = try await sign(Data(req.data?.data ?? []), as: req.ident ?? "", timeoutMs: req.timeoutMs ?? 120_000)
return ClientReply(id: req.id, exitCode: code, output: status, data: Base64EncodedData(signature))
}
}
private func sign(_ payload: Data, as ident: String, timeoutMs: Int) async throws -> (Int, String, Data) {
let fm = FileManager.default
let dir = fm.temporaryDirectory.appending(path: "byre-sign-\(UUID().uuidString)", directoryHint: .isDirectory)
try fm.createDirectory(at: dir, withIntermediateDirectories: false, attributes: [.posixPermissions: 0o700])
defer {
try? fm.removeItem(at: dir)
}
let input = dir.appending(path: "commit")
let output = dir.appending(path: "signature")
try payload.write(to: input)
let stdin = try FileHandle(forReadingFrom: input)
defer {
try? stdin.close()
}
let home = fm.homeDirectoryForCurrentUser.path
let (code, status) = try await spawn(["/bin/zsh", "-l", "-c", signScript, "byre-sign", ident, output.path], in: home, timeoutMs: timeoutMs, input: stdin)
return (code, status, (try? Data(contentsOf: output)) ?? Data())
}
private func download(_ path: String, transfer: String) async throws {
let source = expand(path)
let archive = FileManager.default.temporaryDirectory.appending(path: "byre-download-\(UUID().uuidString).tgz")
@@ -258,7 +291,7 @@ private func start(_ p: Process) throws -> AsyncStream<Void> {
return exit
}
private func spawn(_ argv: [String], in dir: String, timeoutMs: Int) async throws -> (Int, String) {
private func spawn(_ argv: [String], in dir: String, timeoutMs: Int, input: FileHandle = .nullDevice) async throws -> (Int, String) {
let fm = FileManager.default
let out = fm.temporaryDirectory.appending(path: "byre-\(UUID().uuidString).log")
defer {
@@ -274,7 +307,7 @@ private func spawn(_ argv: [String], in dir: String, timeoutMs: Int) async throw
p.executableURL = URL(filePath: argv[0])
p.arguments = Array(argv.dropFirst())
p.currentDirectoryURL = URL(filePath: dir)
p.standardInput = FileHandle.nullDevice
p.standardInput = input
p.standardOutput = sink
p.standardError = sink
let exit: AsyncStream<Void>