Skip to content

Commit c28d686

Browse files
committed
reorg
1 parent 38d96c7 commit c28d686

File tree

3 files changed

+20
-257
lines changed

3 files changed

+20
-257
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ name = "sops-gitops-github-action"
33
version = "0.1.0"
44
edition = "2024"
55

6+
[[bin]]
7+
name = "sops-gitops-github-action"
8+
path = "src/main.rs"
9+
610
[dependencies]
711
serde = { version = "1.0", features = ["derive"] }
812
serde_yaml = "0.9"

src/bin/sops-gitops-github-action/main.rs

-42
This file was deleted.

src/main.rs

+16-215
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
use anyhow::{Context, Result, anyhow};
2-
use base64::Engine;
1+
use anyhow::Result;
32
use clap::Parser;
4-
use glob::glob;
5-
use serde_yaml::Value;
6-
use std::fs;
7-
use std::io::Write;
8-
use std::path::Path;
9-
use std::process::{Command, Stdio};
10-
11-
#[derive(Parser, Debug)]
12-
struct Args {
13-
/// Base64-encoded private GPG key
14-
#[clap(long)]
3+
use dotenv::dotenv;
4+
use sops_gitops_github_action::import_gpg_key;
5+
use sops_gitops_github_action::update_sops_config;
6+
7+
/// CLI arguments for the sops-gitops-github-action
8+
#[derive(Debug, Parser)]
9+
#[command(name = "sops-gitops-github-action1")]
10+
struct MyArgs {
11+
/// The base64-encoded private GPG key
12+
#[arg(long)]
1513
private_key: String,
16-
/// Comma-separated list of base64-encoded public GPG keys
17-
#[clap(long)]
14+
15+
/// A comma-separated list of base64-encoded public GPG keys
16+
#[arg(long)]
1817
public_keys: String,
1918
}
2019

2120
#[tokio::main]
2221
async fn main() -> Result<()> {
23-
let args = Args::parse();
22+
dotenv().ok();
23+
let args = MyArgs::parse();
2424

2525
// Step 1: Decode and import the private key
2626
println!("Importing private key...");
@@ -40,202 +40,3 @@ async fn main() -> Result<()> {
4040
println!("Action completed!");
4141
Ok(())
4242
}
43-
44-
fn import_gpg_key(encoded_key: &str) -> Result<(), anyhow::Error> {
45-
let decoded_key = base64::engine::general_purpose::STANDARD
46-
.decode(encoded_key)
47-
.context("Failed to decode base64 key")?;
48-
let mut process = Command::new("gpg")
49-
.args(["--import"])
50-
.stdin(Stdio::piped())
51-
.spawn()
52-
.context("Failed to spawn gpg process")?;
53-
54-
if let Some(stdin) = process.stdin.as_mut() {
55-
stdin.write_all(&decoded_key)?;
56-
}
57-
process.wait().context("Failed to wait for gpg process")?;
58-
Ok(())
59-
}
60-
61-
fn update_sops_config(public_keys: &str) -> Result<(), anyhow::Error> {
62-
let sops_config_path = "./.sops.yaml";
63-
let mut config: Value = if Path::new(sops_config_path).exists() {
64-
let content =
65-
fs::read_to_string(sops_config_path).context("Failed to read existing .sops.yaml")?;
66-
serde_yaml::from_str(&content).context("Failed to parse .sops.yaml")?
67-
} else {
68-
serde_yaml::from_str("creation_rules: []").unwrap()
69-
};
70-
71-
// Update the creation rules with public keys
72-
let creation_rules = config
73-
.get_mut("creation_rules")
74-
.and_then(Value::as_sequence_mut)
75-
.ok_or_else(|| anyhow!("Invalid .sops.yaml structure"))?;
76-
77-
for public_key in public_keys.split(',') {
78-
let fingerprint = get_key_fingerprint(public_key)?;
79-
let rule = serde_yaml::to_value(&serde_yaml::Mapping::from_iter([(
80-
Value::String("pgp".to_string()),
81-
Value::Sequence(vec![Value::String(fingerprint)]),
82-
)]))?;
83-
creation_rules.push(rule);
84-
}
85-
86-
// Write back the updated configuration
87-
let updated_config =
88-
serde_yaml::to_string(&config).context("Failed to serialize updated .sops.yaml")?;
89-
fs::write(sops_config_path, updated_config).context("Failed to write updated .sops.yaml")?;
90-
Ok(())
91-
}
92-
93-
fn get_key_fingerprint(encoded_key: &str) -> Result<String, anyhow::Error> {
94-
let _decoded_key = base64::engine::general_purpose::STANDARD
95-
.decode(encoded_key)
96-
.context("Failed to decode base64 key")?;
97-
let output = Command::new("gpg")
98-
.args([
99-
"--with-colons",
100-
"--import-options",
101-
"show-only",
102-
"--import",
103-
"--fingerprint",
104-
])
105-
.stdin(Stdio::piped())
106-
.stdout(Stdio::piped())
107-
.spawn()
108-
.context("Failed to spawn gpg process")?
109-
.wait_with_output()
110-
.context("Failed to wait for gpg process")?;
111-
112-
let output_str = String::from_utf8(output.stdout).context("Failed to parse gpg output")?;
113-
let fingerprint = output_str
114-
.lines()
115-
.find(|line| line.starts_with("fpr"))
116-
.and_then(|line| line.split(':').nth(9))
117-
.map(String::from)
118-
.context("Failed to extract fingerprint from gpg output")?;
119-
Ok(fingerprint)
120-
}
121-
122-
#[allow(unused)]
123-
fn setup_workspace() -> Result<(), anyhow::Error> {
124-
println!("Setting up workspace...");
125-
fs::copy("/generator/.", ".")?;
126-
Ok(())
127-
}
128-
129-
#[allow(unused)]
130-
fn debug_output() -> Result<(), anyhow::Error> {
131-
println!("Working dir: {}", std::env::current_dir()?.display());
132-
println!("================================================");
133-
for entry in fs::read_dir(".")? {
134-
let entry = entry?;
135-
println!("{:?}", entry.path());
136-
}
137-
println!("================================================");
138-
Ok(())
139-
}
140-
141-
#[allow(unused)]
142-
fn sops_config_file_exists() -> Result<bool, anyhow::Error> {
143-
let path = Path::new("actions/generator/workspace/.sops.yaml");
144-
Ok(path.exists())
145-
}
146-
147-
#[allow(unused)]
148-
fn create_default_sops_config_file() -> Result<(), anyhow::Error> {
149-
println!("Creating .sops.yaml...");
150-
let team_key_fpr = get_key_fingerprint("team_private_key")?;
151-
let content = format!(
152-
"creation_rules:\n- key_groups:\n - pgp:\n - {}",
153-
team_key_fpr
154-
);
155-
fs::write("actions/generator/workspace/.sops.yaml", content)?;
156-
Ok(())
157-
}
158-
159-
#[allow(unused)]
160-
fn public_keys_provided() -> Result<bool, anyhow::Error> {
161-
let public_keys_file = "actions/generator/public_keys.txt";
162-
let content = fs::read_to_string(public_keys_file).unwrap_or_default();
163-
let public_keys: Vec<&str> = content.lines().collect();
164-
Ok(!public_keys.is_empty())
165-
}
166-
167-
#[allow(unused)]
168-
fn update_sops_configuration_file() -> Result<(), anyhow::Error> {
169-
println!("Updating .sops.yaml file with public keys...");
170-
let public_keys_file = "actions/generator/public_keys.txt";
171-
let binding = fs::read_to_string(public_keys_file)?;
172-
let public_keys = binding.lines().collect::<Vec<_>>();
173-
174-
let mut config = fs::read_to_string("actions/generator/workspace/.sops.yaml")?;
175-
for key in public_keys {
176-
let key_fingerprint = get_key_fingerprint(key)?;
177-
config.push_str(&format!("\n - {}", key_fingerprint));
178-
}
179-
fs::write("actions/generator/workspace/.sops.yaml", config)?;
180-
Ok(())
181-
}
182-
183-
#[allow(unused)]
184-
fn find_secret_files(workspace: &str) -> Result<Vec<String>, anyhow::Error> {
185-
let mut secret_files = Vec::new();
186-
for entry in glob(&format!("{}/**/*.yaml", workspace))? {
187-
let path = entry?;
188-
let content = fs::read_to_string(&path)?;
189-
if content.contains("sops:") {
190-
secret_files.push(path.to_string_lossy().to_string());
191-
}
192-
}
193-
Ok(secret_files)
194-
}
195-
196-
#[allow(unused)]
197-
fn update_secret_file(file_path: &str) -> Result<(), anyhow::Error> {
198-
println!("Updating secret file: {}", file_path);
199-
if Path::new(file_path).exists() {
200-
println!("The secret file {} exists.", file_path);
201-
Command::new("sops")
202-
.args(["updatekeys", file_path, "--yes"])
203-
.stdout(Stdio::inherit())
204-
.stderr(Stdio::inherit())
205-
.output()
206-
.with_context(|| format!("Failed to re-encrypt secret file: {}", file_path))?;
207-
} else {
208-
println!("Creating secret file: {}", file_path);
209-
create_secret_file(file_path)?;
210-
}
211-
Ok(())
212-
}
213-
214-
#[allow(unused)]
215-
fn create_secret_file(file_path: &str) -> Result<(), anyhow::Error> {
216-
fs::create_dir_all(Path::new(file_path).parent().unwrap())?;
217-
let sops_config_path = "actions/generator/workspace/.sops.yaml";
218-
219-
let mut child = Command::new("sops")
220-
.args(["--config", sops_config_path, "-e", "/dev/stdin"])
221-
.stdin(Stdio::piped())
222-
.stdout(Stdio::from(fs::File::create(file_path)?))
223-
.spawn()
224-
.context("Failed to spawn sops process")?;
225-
226-
if let Some(stdin) = child.stdin.as_mut() {
227-
writeln!(stdin, "key: value").context("Failed to write to stdin")?;
228-
} else {
229-
return Err(anyhow::anyhow!("Failed to open stdin for sops process"));
230-
}
231-
232-
child.wait().context("Failed to wait for sops process")?;
233-
Ok(())
234-
}
235-
236-
#[allow(unused)]
237-
fn set_message() -> Result<(), anyhow::Error> {
238-
let message = "encrypt sops secrets and update sops.yaml";
239-
println!("message={}", message);
240-
Ok(())
241-
}

0 commit comments

Comments
 (0)