From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id E39C6757F9 for ; Tue, 13 Jul 2021 10:04:19 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id DA87D1D7CE for ; Tue, 13 Jul 2021 10:04:19 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 1F1131D77B for ; Tue, 13 Jul 2021 10:04:18 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id EBFE14033D for ; Tue, 13 Jul 2021 10:04:17 +0200 (CEST) From: Fabian Ebner To: pmg-devel@lists.proxmox.com Date: Tue, 13 Jul 2021 10:04:11 +0200 Message-Id: <20210713080413.26662-3-f.ebner@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210713080413.26662-1-f.ebner@proxmox.com> References: <20210713080413.26662-1-f.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.515 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [mod.rs, repositories.pm, csr.pm, lib.rs, repositories.rs, acme.pm] Subject: [pmg-devel] [PATCH pmg-rs 2/2] add bindings for proxmox-apt X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Jul 2021 08:04:19 -0000 Signed-off-by: Fabian Ebner --- Cargo.toml | 4 + Makefile | 7 ++ debian/control | 2 + src/apt/mod.rs | 1 + src/apt/repositories.rs | 159 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 6 files changed, 174 insertions(+) create mode 100644 src/apt/mod.rs create mode 100644 src/apt/repositories.rs diff --git a/Cargo.toml b/Cargo.toml index d942daa..553d5eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,9 @@ serde_json = "1.0" perlmod = { version = "0.5.2", features = [ "exporter" ] } #perlmod = { path = "../perlmod/perlmod", features = [ "exporter" ] } +proxmox = { version = "0.11.5", default-features = false } + proxmox-acme-rs = { version = "0.2.2", features = ["client"] } #proxmox-acme-rs = { path = "../proxmox-acme-rs", features = ["client"] } + +proxmox-apt = "0.4.0" diff --git a/Makefile b/Makefile index 9d475c7..67eeb15 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,12 @@ DEBS=$(MAIN_DEB) $(DBGSYM_DEB) DESTDIR= +PM_DIRS := \ + PMG/RS/APT + PM_FILES := \ PMG/RS/Acme.pm \ + PMG/RS/APT/Repositories.pm \ PMG/RS/CSR.pm ifeq ($(BUILD_MODE), release) @@ -40,6 +44,9 @@ install: target/release/libpmg_rs.so install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto install -m644 target/release/libpmg_rs.so $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto/libpmg_rs.so install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)/PMG/RS + for i in $(PM_DIRS); do \ + install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)/$$i; \ + done for i in $(PM_FILES); do \ install -m644 $$i $(DESTDIR)$(PERL_INSTALLVENDORLIB)/$$i; \ done diff --git a/debian/control b/debian/control index 677a28d..fe5dad6 100644 --- a/debian/control +++ b/debian/control @@ -5,6 +5,8 @@ Maintainer: Proxmox Support Team Build-Depends: debhelper (>= 12), librust-curl-dev, librust-proxmox-acme-rs+client-dev, + librust-proxmox-apt-dev, + librust-proxmox-dev, librust-perlmod-macro-dev, librust-anyhow-dev, librust-openssl-dev, diff --git a/src/apt/mod.rs b/src/apt/mod.rs new file mode 100644 index 0000000..574c1a7 --- /dev/null +++ b/src/apt/mod.rs @@ -0,0 +1 @@ +mod repositories; diff --git a/src/apt/repositories.rs b/src/apt/repositories.rs new file mode 100644 index 0000000..81552e3 --- /dev/null +++ b/src/apt/repositories.rs @@ -0,0 +1,159 @@ +#[perlmod::package(name = "PMG::RS::APT::Repositories", lib = "pmg_rs")] +mod export { + use std::convert::TryInto; + + use anyhow::{bail, Error}; + use serde::{Deserialize, Serialize}; + + use proxmox_apt::repositories::{ + APTRepositoryFile, APTRepositoryFileError, APTRepositoryHandle, APTRepositoryInfo, + APTStandardRepository, + }; + + #[derive(Deserialize, Serialize)] + #[serde(rename_all = "kebab-case")] + /// Result for the repositories() function + pub struct RepositoriesResult { + /// Successfully parsed files. + pub files: Vec, + + /// Errors for files that could not be parsed or read. + pub errors: Vec, + + /// Common digest for successfully parsed files. + pub digest: String, + + /// Additional information/warnings about repositories. + pub infos: Vec, + + /// Standard repositories and their configuration status. + pub standard_repos: Vec, + } + + #[derive(Deserialize, Serialize)] + #[serde(rename_all = "kebab-case")] + /// For changing an existing repository. + pub struct ChangeProperties { + /// Whether the repository should be enabled or not. + pub enabled: Option, + } + + /// Get information about configured and standard repositories. + #[export] + pub fn repositories() -> Result { + let (files, errors, digest) = proxmox_apt::repositories::repositories()?; + let digest = proxmox::tools::digest_to_hex(&digest); + + let infos = proxmox_apt::repositories::check_repositories(&files)?; + let standard_repos = proxmox_apt::repositories::standard_repositories("pmg", &files); + + Ok(RepositoriesResult { + files, + errors, + digest, + infos, + standard_repos, + }) + } + + /// Add the repository identified by the `handle`. + /// If the repository is already configured, it will be set to enabled. + /// + /// The `digest` parameter asserts that the configuration has not been modified. + #[export] + pub fn add_repository(handle: &str, digest: Option<&str>) -> Result<(), Error> { + let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?; + + let handle: APTRepositoryHandle = handle.try_into()?; + + if let Some(digest) = digest { + let expected_digest = proxmox::tools::hex_to_digest(digest)?; + if expected_digest != current_digest { + bail!("detected modified configuration - file changed by other user? Try again."); + } + } + + // check if it's already configured first + for file in files.iter_mut() { + for repo in file.repositories.iter_mut() { + if repo.is_referenced_repository(handle, "pmg") { + if repo.enabled { + return Ok(()); + } + + repo.set_enabled(true); + file.write()?; + + return Ok(()); + } + } + } + + let (repo, path) = proxmox_apt::repositories::get_standard_repository(handle, "pmg")?; + + if let Some(error) = errors.iter().find(|error| error.path == path) { + bail!( + "unable to parse existing file {} - {}", + error.path, + error.error, + ); + } + + if let Some(file) = files.iter_mut().find(|file| file.path == path) { + file.repositories.push(repo); + + file.write()?; + } else { + let mut file = match APTRepositoryFile::new(&path)? { + Some(file) => file, + None => bail!("invalid path - {}", path), + }; + + file.repositories.push(repo); + + file.write()?; + } + + Ok(()) + } + + /// Change the properties of the specified repository. + /// + /// The `digest` parameter asserts that the configuration has not been modified. + #[export] + pub fn change_repository( + path: &str, + index: usize, + options: ChangeProperties, + digest: Option<&str>, + ) -> Result<(), Error> { + let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?; + + if let Some(digest) = digest { + let expected_digest = proxmox::tools::hex_to_digest(digest)?; + if expected_digest != current_digest { + bail!("detected modified configuration - file changed by other user? Try again."); + } + } + + if let Some(error) = errors.iter().find(|error| error.path == path) { + bail!("unable to parse file {} - {}", error.path, error.error); + } + + if let Some(file) = files.iter_mut().find(|file| file.path == path) { + if let Some(repo) = file.repositories.get_mut(index) { + if let Some(enabled) = options.enabled { + repo.set_enabled(enabled); + } + + file.write()?; + } else { + bail!("invalid index - {}", index); + } + } else { + bail!("invalid path - {}", path); + } + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 9822106..47e61b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod acme; +pub mod apt; pub mod csr; -- 2.30.2