Skip to content

Commit 9557eeb

Browse files
committed
feat(certbot.rs): add validation for Cloudflare credentials to ensure valid input
feat(certbot.rs): implement detailed logging for credential handling and command execution fix(certbot.rs): set file permissions for credentials file to enhance security on Unix systems
1 parent 96e15fd commit 9557eeb

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

src/certbot.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,35 +68,69 @@ impl Certbot {
6868
args.push("-w".to_string());
6969
args.push(self.webroot.clone());
7070
},
71-
ChallengeType::Dns(ref plugin, ref credentials) => { // Added 'ref' here
71+
ChallengeType::Dns(ref plugin, ref credentials) => {
7272
if plugin == "cloudflare" {
7373
args.push("--dns-cloudflare".to_string());
7474

75-
// If credentials provided, set them up
7675
if let Some(creds) = credentials {
77-
// Create a temporary credentials file
7876
use std::fs::File;
7977
use std::io::Write;
8078
use std::path::PathBuf;
8179

80+
// Validate credentials
81+
if creds.api_token.is_empty() && (creds.email.is_none() || creds.api_key.is_none()) {
82+
return Err(io::Error::new(
83+
ErrorKind::InvalidInput,
84+
"No valid Cloudflare credentials provided"
85+
));
86+
}
87+
8288
let creds_dir = PathBuf::from(&self.config_dir).join("cloudflare");
8389
std::fs::create_dir_all(&creds_dir)?;
8490

8591
let creds_file = creds_dir.join("credentials.ini");
86-
let mut file = File::create(&creds_file)?;
8792

93+
// Create the credentials file content
8894
let creds_content = if !creds.api_token.is_empty() {
89-
format!("dns_cloudflare_api_token = {}", creds.api_token)
95+
println!("Using API token authentication");
96+
format!(
97+
"# Cloudflare API token credentials for Certbot\n\
98+
dns_cloudflare_api_token = {}\n",
99+
creds.api_token
100+
)
90101
} else if let (Some(ref email), Some(ref api_key)) = (creds.email.as_ref(), creds.api_key.as_ref()) {
91-
format!("dns_cloudflare_email = {}\ndns_cloudflare_api_key = {}", email, api_key)
102+
println!("Using email/API key authentication");
103+
format!(
104+
"# Cloudflare API credentials for Certbot\n\
105+
dns_cloudflare_email = {}\n\
106+
dns_cloudflare_api_key = {}\n",
107+
email, api_key
108+
)
92109
} else {
93110
return Err(io::Error::new(
94111
ErrorKind::InvalidInput,
95112
"Invalid Cloudflare credentials configuration"
96113
));
97114
};
98115

99-
file.write_all(creds_content.as_bytes())?;
116+
// Write the credentials file
117+
println!("Writing credentials to: {}", creds_file.display());
118+
std::fs::write(&creds_file, &creds_content)?;
119+
120+
// Set proper permissions
121+
#[cfg(unix)]
122+
{
123+
use std::os::unix::fs::PermissionsExt;
124+
let mut perms = std::fs::metadata(&creds_file)?.permissions();
125+
perms.set_mode(0o600);
126+
std::fs::set_permissions(&creds_file, perms)?;
127+
}
128+
129+
// Verify the file was created and contains the credentials
130+
match std::fs::read_to_string(&creds_file) {
131+
Ok(contents) => println!("Credentials file contents:\n{}", contents),
132+
Err(e) => println!("Failed to read credentials file: {}", e),
133+
}
100134

101135
args.push("--dns-cloudflare-credentials".to_string());
102136
args.push(creds_file.to_string_lossy().to_string());
@@ -124,12 +158,13 @@ impl Certbot {
124158
args.push("--no-eff-email".to_string());
125159
}
126160

127-
// Add propagation wait time for DNS challenges
128161
if matches!(challenge, ChallengeType::Dns(_, _)) {
129162
args.push("--dns-cloudflare-propagation-seconds".to_string());
130163
args.push("30".to_string());
131164
}
132165

166+
println!("Executing command: certbot {}", args.join(" "));
167+
133168
let output = command
134169
.args(&args)
135170
.stdout(std::process::Stdio::piped())

0 commit comments

Comments
 (0)