From ec8b893f6a639addc856a7c37b43ef61878dfde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Christian=20Gr=C3=BCnhage?= Date: Mon, 20 Apr 2020 23:04:31 +0200 Subject: [PATCH] feat: migrate to api tokens Cloudflare's v4 API provides three ways of authenticating, with the API tokens being the new, standard conform, recommended way. This patch removes the use of the old auth_key + email combo and replaces it with API tokens. BREAKING CHANGE: auth keys can't be used anymore, switch to api tokens --- src/main.rs | 34 +++++++++++++--------------------- src/network.rs | 17 ++++++----------- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8a07845..b2f3d3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,7 @@ use anyhow::{Context, Result}; #[derive(Deserialize)] struct Config { - email: String, - auth_key: String, + api_token: String, zone: String, domain: String, } @@ -20,17 +19,13 @@ struct Config { #[derive(Debug, StructOpt)] /// Inform Cloudflare's DDNS service of the current IP address for your domain struct Cli { - /// Your TOML config file containing all the required options (email, auth_key, zone, domain) which you can use instead of passing the arguments to the command line + /// Your TOML config file containing all the required options (api_token, zone, domain) which you can use instead of passing the arguments to the command line #[structopt(long = "config", short = "f")] config: Option, - /// Your Cloudflare login email - #[structopt(long = "email", short = "e", required_unless = "config")] - email: Option, - - /// The auth key you need to generate in your Cloudflare profile - #[structopt(long = "key", short = "k", required_unless = "config")] - auth_key: Option, + /// The api token you need to generate in your Cloudflare profile + #[structopt(long = "token", short = "t", required_unless = "config")] + api_token: Option, /// The zone in which your domain is (usually that is your base domain name) #[structopt(long = "zone", short = "z", required_unless = "config")] @@ -76,21 +71,20 @@ fn main() -> Result<()> { write_file(&args.cache.unwrap(), ¤t_ip)?; } - let (email, auth_key, zone, domain) = match args.config { + let (api_token, zone, domain) = match args.config { Some(c) => { let config_str = read_file(&c)?; let config: Config = toml::from_str(&config_str)?; - (config.email, config.auth_key, config.zone, config.domain) + (config.api_token, config.zone, config.domain) } None => ( - args.email.expect("Email is not set"), - args.auth_key.expect("Auth key is not set"), + args.api_token.expect("API token is not set"), args.zone.expect("Zone is not set"), args.domain.expect("Domain is not set"), ), }; - update(¤t_ip, &email, &auth_key, &zone, &domain)?; + update(¤t_ip, &api_token, &zone, &domain)?; println!( "Successfully updated the A record for {} to {}", @@ -102,21 +96,19 @@ fn main() -> Result<()> { fn update( current_ip: &str, - email: &str, - auth_key: &str, + api_token: &str, zone: &str, domain: &str, ) -> Result<()> { - let zone_id = get_zone_identifier(&zone, &email, &auth_key).context("Error getting the zone identifier")?; - let record_id = get_dns_record_id(&zone_id, &domain, &email, &auth_key).context("Error getting the DNS record ID")?; + let zone_id = get_zone_identifier(&zone, &api_token).context("Error getting the zone identifier")?; + let record_id = get_dns_record_id(&zone_id, &domain, &api_token).context("Error getting the DNS record ID")?; update_ddns( ¤t_ip, &domain, &zone_id, &record_id, - &email, - &auth_key, + &api_token, ).context("Error updating the DNS record")?; Ok(()) diff --git a/src/network.rs b/src/network.rs index 8c1e333..958637f 100644 --- a/src/network.rs +++ b/src/network.rs @@ -28,14 +28,13 @@ struct UpdateIpData { content: String, } -pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> anyhow::Result { +pub fn get_zone_identifier(zone: &str, api_token: &str) -> anyhow::Result { let client = reqwest::blocking::Client::new(); let url = format!("https://api.cloudflare.com/client/v4/zones?name={}", zone); let response = client .get(&url) - .header("X-Auth-Email", email) - .header("X-Auth-Key", key) + .header("Authorization", format!("Bearer {}", api_token)) .header("Content-Type", "application/json") .send()?; @@ -68,8 +67,7 @@ pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> anyhow::Result pub fn get_dns_record_id( zone_id: &str, domain: &str, - email: &str, - key: &str, + api_token: &str, ) -> anyhow::Result { let client = reqwest::blocking::Client::new(); let url = format!( @@ -79,8 +77,7 @@ pub fn get_dns_record_id( let response = client .get(&url) - .header("X-Auth-Email", email) - .header("X-Auth-Key", key) + .header("Authorization", format!("Bearer {}", api_token)) .header("Content-Type", "application/json") .send()?; @@ -132,8 +129,7 @@ pub fn update_ddns( domain: &str, zone_id: &str, record_id: &str, - email: &str, - key: &str, + api_token: &str, ) -> anyhow::Result<()> { let client = reqwest::blocking::Client::new(); let url = format!( @@ -150,8 +146,7 @@ pub fn update_ddns( let response = client .put(&url) - .header("X-Auth-Email", email) - .header("X-Auth-Key", key) + .header("Authorization", format!("Bearer {}", api_token)) .header("Content-Type", "application/json") .json(&update_data) .send()?;