From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <f.gleumes@proxmox.com>
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 2FC879A056
 for <pmg-devel@lists.proxmox.com>; Tue, 14 Nov 2023 15:14:35 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id 1942D1CD8F
 for <pmg-devel@lists.proxmox.com>; Tue, 14 Nov 2023 15:14:35 +0100 (CET)
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
 for <pmg-devel@lists.proxmox.com>; Tue, 14 Nov 2023 15:14:33 +0100 (CET)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 4BF0F42A04
 for <pmg-devel@lists.proxmox.com>; Tue, 14 Nov 2023 15:14:33 +0100 (CET)
From: Folke Gleumes <f.gleumes@proxmox.com>
To: pmg-devel@lists.proxmox.com
Date: Tue, 14 Nov 2023 15:14:04 +0100
Message-Id: <20231114141408.228705-6-f.gleumes@proxmox.com>
X-Mailer: git-send-email 2.39.2
In-Reply-To: <20231114141408.228705-1-f.gleumes@proxmox.com>
References: <20231114141408.228705-1-f.gleumes@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.020 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 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
 T_SCC_BODY_TEXT_LINE    -0.01 -
Subject: [pmg-devel] [PATCH backup 4/8] cli: acme: add possibility to set
 eab via the cli
X-BeenThere: pmg-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Mail Gateway development discussion
 <pmg-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pmg-devel>, 
 <mailto:pmg-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pmg-devel/>
List-Post: <mailto:pmg-devel@lists.proxmox.com>
List-Help: <mailto:pmg-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel>, 
 <mailto:pmg-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Tue, 14 Nov 2023 14:14:35 -0000

If the ca demands external account binding credentials, the user will be
asked for them. If a custom directory is used, the user will be asked if
eab should be used.

Signed-off-by: Folke Gleumes <f.gleumes@proxmox.com>
---
 src/acme/client.rs                     |  2 +-
 src/bin/proxmox_backup_manager/acme.rs | 51 +++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/src/acme/client.rs b/src/acme/client.rs
index 1396eb2c..6130748b 100644
--- a/src/acme/client.rs
+++ b/src/acme/client.rs
@@ -577,7 +577,7 @@ impl AcmeClient {
         Self::execute(&mut self.http_client, request, &mut self.nonce).await
     }
 
-    async fn directory(&mut self) -> Result<&Directory, Error> {
+    pub async fn directory(&mut self) -> Result<&Directory, Error> {
         Ok(Self::get_directory(
             &mut self.http_client,
             &self.directory_url,
diff --git a/src/bin/proxmox_backup_manager/acme.rs b/src/bin/proxmox_backup_manager/acme.rs
index 17ca5958..f3e62115 100644
--- a/src/bin/proxmox_backup_manager/acme.rs
+++ b/src/bin/proxmox_backup_manager/acme.rs
@@ -103,8 +103,8 @@ async fn register_account(
     contact: String,
     directory: Option<String>,
 ) -> Result<(), Error> {
-    let directory = match directory {
-        Some(directory) => directory,
+    let (directory_url, custom_directory) = match directory {
+        Some(directory) => (directory, true),
         None => {
             println!("Directory endpoints:");
             for (i, dir) in KNOWN_ACME_DIRECTORIES.iter().enumerate() {
@@ -122,12 +122,12 @@ async fn register_account(
 
                 match input.trim().parse::<usize>() {
                     Ok(n) if n < KNOWN_ACME_DIRECTORIES.len() => {
-                        break KNOWN_ACME_DIRECTORIES[n].url.to_owned();
+                        break (KNOWN_ACME_DIRECTORIES[n].url.to_owned(), false);
                     }
                     Ok(n) if n == KNOWN_ACME_DIRECTORIES.len() => {
                         input.clear();
                         std::io::stdin().read_line(&mut input)?;
-                        break input.trim().to_owned();
+                        break (input.trim().to_owned(), true);
                     }
                     _ => eprintln!("Invalid selection."),
                 }
@@ -140,9 +140,13 @@ async fn register_account(
         }
     };
 
-    println!("Attempting to fetch Terms of Service from {:?}", directory);
-    let mut client = AcmeClient::new(directory.clone());
-    let tos_agreed = if let Some(tos_url) = client.terms_of_service_url().await? {
+    println!(
+        "Attempting to fetch Terms of Service from {:?}",
+        directory_url
+    );
+    let mut client = AcmeClient::new(directory_url.clone());
+    let directory = client.directory().await?;
+    let tos_agreed = if let Some(tos_url) = directory.terms_of_service_url() {
         println!("Terms of Service: {}", tos_url);
         print!("Do you agree to the above terms? [y|N]: ");
         std::io::stdout().flush()?;
@@ -154,7 +158,36 @@ async fn register_account(
         true
     };
 
-    println!("Attempting to register account with {:?}...", directory);
+    let mut eab_enabled = directory.external_account_binding_required();
+    if !eab_enabled && custom_directory {
+        print!("Do you want to use external account binding? [y|N]: ");
+        std::io::stdout().flush()?;
+        let mut input = String::new();
+        std::io::stdin().read_line(&mut input)?;
+        eab_enabled = input.trim().eq_ignore_ascii_case("y");
+    } else if eab_enabled {
+        println!("The CA requires external account binding.");
+    }
+
+    let eab_creds = if eab_enabled {
+        println!("You should have received a key id and a key from your CA.");
+
+        print!("Enter EAB key id: ");
+        std::io::stdout().flush()?;
+        let mut eab_kid = String::new();
+        std::io::stdin().read_line(&mut eab_kid)?;
+
+        print!("Enter EAB key: ");
+        std::io::stdout().flush()?;
+        let mut eab_hmac_key = String::new();
+        std::io::stdin().read_line(&mut eab_hmac_key)?;
+
+        Some((eab_kid.trim().to_owned(), eab_hmac_key.trim().to_owned()))
+    } else {
+        None
+    };
+
+    println!("Attempting to register account with {:?}...", directory_url);
 
     let account = api2::config::acme::do_register_account(
         &mut client,
@@ -162,7 +195,7 @@ async fn register_account(
         tos_agreed,
         contact,
         None,
-        None,
+        eab_creds,
     )
     .await?;
 
-- 
2.39.2