Skip to content

Commit d6d69c3

Browse files
authored
fix: remove old signatures on update (#18)
* fix: remove old signatures on update, correct signing references * fix: prune orphan signatures on startup * fix: don't log missing repository directory
1 parent 267c4c5 commit d6d69c3

File tree

6 files changed

+59
-11
lines changed

6 files changed

+59
-11
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Many more commands are found on the documentation for the CLI:
3939
**[<kbd>&ensp;<br>&ensp;CLI Documentation&ensp;<br>&ensp;</kbd>](./cli/README.md)**
4040

4141
## State
42-
This project is still in its early stages, but already usable on a daily basis. There are also a couple of improvements and optimizations that still need to be implemented.
42+
This project is still in its early stages, but already usable on a daily basis. There are also a couple of improvements and optimizations that still need to be implemented.
4343
Big, recently implemented features include:
4444
- [X] Entirely custom PKGBUILDs without a git repository
4545
- [X] Package signing
@@ -51,8 +51,8 @@ Refer to the [TODO File](TODO.md) for more features, tasks and enhancements and
5151
Installing serene involves two things, deploying the server, and installing a local CLI to conveniently interact with the server.
5252

5353
### Deploying
54-
Here is a quick overview of hosting a serene server, based on the main branch. The server is just a single docker container, making it straightforward:
55-
1. First, **create an empty file** called `authorized_secrets` in your directory.
54+
Here is a quick overview of hosting a serene server, based on the main branch. The server is just a single docker container, making it straightforward:
55+
1. First, **create an empty file** called `authorized_secrets` in your directory.
5656
2. Set up a reverse proxy for docker (e.g. traefik) to use SSL/TLS.
5757
3. Add the following service to your docker compose in the same directory:
5858
```yaml
@@ -94,7 +94,7 @@ If you want to use the repository without instructions from the cli, also quite
9494
SigLevel = Optional TrustAll
9595
Server = https://your-host/x86_64
9696
```
97-
*Signatures are not validated, as this is not yet supported. This shouldn't be an issue as we're using https and don't have any mirrors.*
97+
*The SigLevel should only be set to `Optional TrustAll` when [package signing](./server/README.md#package-signing) is disabled for the repository*
9898

9999
## Architecture
100100
Here's a *very* quick word about the architecture of *serene*:
@@ -103,7 +103,7 @@ Here's a *very* quick word about the architecture of *serene*:
103103
- **Local CLI:** Interacts with said API to add and manipulate added packages. Requires authentication via secret.
104104

105105
## Disclaimer
106-
When hosting a repository with this project, this repository is **your** responsibility!
106+
When hosting a repository with this project, this repository is **your** responsibility!
107107

108108
This means that it is your job to check `PKGBUILDs` before adding a package to the repository, as building the packages on an isolated environment does **in no way protect you from malware** if you install the package on your system. So make sure you trust the **software and AUR package maintainers** before adding it into the repository. This is especially important as the server will **automatically build new versions** without any actions from your side.
109109

cli/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl Config {
8989
println!();
9090
println!("3. To now use the repository with your pacman, add the following to your pacman configuration:");
9191
println!("[serene] # or something else if you've changed that");
92-
println!("SigLevel = Optional TrustAll # signatures are not yet supported");
92+
println!("SigLevel = Optional TrustAll # needed when package signing is disabled");
9393
println!("Server = {}/{}", &config.url, env::consts::ARCH);
9494

9595
println!();

server/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ async fn main() -> anyhow::Result<()> {
7575
error!("failed apply heuristics to migrate to built_state: {e:#}")
7676
}
7777

78+
repository::remove_orphan_signature().await;
79+
7880
// schedule packages (which are enabled)
7981
for package in Package::find_all(&db).await?.iter().filter(|p| p.enabled) {
8082
schedule

server/src/package/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub mod source;
2525

2626
const SOURCE_FOLDER: &str = "sources";
2727

28-
const PACKAGE_EXTENSION: &str = ".pkg.tar.zst"; // see /etc/makepkg.conf
28+
pub(crate) const PACKAGE_EXTENSION: &str = ".pkg.tar.zst"; // see /etc/makepkg.conf
2929

3030
pub async fn add_source(
3131
db: &Database,

server/src/repository/manage.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn db_file(name: &str) -> String {
88
format!("{name}.db.tar.gz")
99
}
1010

11-
fn sig_path(path: &Path) -> PathBuf {
11+
pub(crate) fn sig_path(path: &Path) -> PathBuf {
1212
path.with_file_name(format!(
1313
"{}.sig",
1414
path.file_name().unwrap_or_default().to_str().unwrap_or_default()

server/src/repository/mod.rs

+49-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use crate::config::CONFIG;
2-
use crate::package::Package;
2+
use crate::package::{Package, PACKAGE_EXTENSION};
33
use crate::runner::archive;
44
use actix_files::Files;
55
use anyhow::{anyhow, Context};
66
use async_tar::Entries;
77
use futures_util::AsyncRead;
88
use hyper::body::HttpBody;
9-
use log::warn;
9+
use log::{info, warn};
1010
use serde::{Deserialize, Serialize};
1111
use std::collections::HashMap;
1212
use std::path::Path;
@@ -20,6 +20,41 @@ const REPO_SERENE: &str = "bases.json";
2020
const KEY_FILE: &str = "sign_key.asc";
2121
const GPG_AGENT_SOCKET: &str = "S.gpg-agent";
2222

23+
/// see https://github.com/VirtCode/serene-aur/pull/18
24+
pub async fn remove_orphan_signature() {
25+
let Ok(dir) = std::fs::read_dir(REPO_DIR) else {
26+
// repository directory does not yet exist -> no orphan signatures can exist
27+
return;
28+
};
29+
30+
let mut deleted = 0;
31+
32+
dir.into_iter()
33+
.filter_map(|e| e.ok())
34+
.filter(|e| {
35+
e.path().is_file()
36+
&& e.path().to_string_lossy().ends_with(format!("{PACKAGE_EXTENSION}.sig").as_str())
37+
})
38+
.for_each(|entry| {
39+
if let Some(path) = entry.path().file_stem() {
40+
if !Path::new(REPO_DIR).join(path).exists() {
41+
if let Err(e) = std::fs::remove_file(entry.path()) {
42+
warn!(
43+
"failed to delete orphan signature file from repository ({e}): {}",
44+
entry.path().to_string_lossy()
45+
);
46+
} else {
47+
deleted += 1;
48+
}
49+
}
50+
}
51+
});
52+
53+
if deleted > 0 {
54+
info!("pruned {deleted} orphan signature file(s) from repository");
55+
}
56+
}
57+
2358
/// returns the webservice which exposes the repository
2459
pub fn webservice() -> Files {
2560
Files::new(&CONFIG.architecture, REPO_DIR).show_files_listing()
@@ -102,9 +137,20 @@ impl PackageRepository {
102137

103138
// delete package files
104139
for entry in entries {
105-
if let Err(e) = fs::remove_file(Path::new(REPO_DIR).join(&entry.file)).await {
140+
let package_path = Path::new(REPO_DIR).join(&entry.file);
141+
if let Err(e) = fs::remove_file(&package_path).await {
106142
warn!("failed to delete file from repository ({e}): {}", entry.file);
107143
}
144+
145+
let signature_path = manage::sig_path(&package_path);
146+
if signature_path.exists() {
147+
if let Err(e) = fs::remove_file(&signature_path).await {
148+
warn!(
149+
"failed to delete signature file from repository ({e}): {}.sig",
150+
entry.file
151+
);
152+
}
153+
}
108154
}
109155
}
110156

0 commit comments

Comments
 (0)