Skip to content

Commit

Permalink
Merge branch 'master' into pr_add_tuntap
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Jun 21, 2024
2 parents f433cb3 + be7223d commit ad4d64c
Show file tree
Hide file tree
Showing 81 changed files with 2,338 additions and 2,403 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[Unit]
Description=Generate issue file for Agama SSL certificate
Before=systemd-user-sessions.service

[Service]
Type=oneshot
Expand Down
27 changes: 27 additions & 0 deletions live/root/etc/systemd/system/agama-certificate-wait.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[Unit]
Description=Postpone login prompt after the SSL fingerprint issue is generated

After=agama-web-server.service

# copied from YaST2-Second-Stage.service
Before=getty@tty1.service
Before=getty@tty2.service
Before=getty@tty3.service
Before=getty@tty4.service
Before=getty@tty5.service
Before=getty@tty6.service
Before=serial-getty@hvc0.service
Before=serial-getty@sclp_line0.service
Before=serial-getty@ttyAMA0.service
Before=serial-getty@ttyS0.service
Before=serial-getty@ttyS1.service
Before=serial-getty@ttyS2.service
Before=serial-getty@ttysclp0.service

[Service]
Type=oneshot
# wait at most 15 seconds to not block
ExecStart=agama-issue-generator --wait-for-ssl 15

[Install]
WantedBy=default.target
19 changes: 13 additions & 6 deletions live/root/etc/systemd/system/live-password-dialog.service
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,28 @@ Before=serial-getty@ttyS1.service
Before=serial-getty@ttyS2.service
Before=serial-getty@ttysclp0.service

# start at the end to avoid overwriting the screen with systemd messages
After=agama.service
After=modprobe@drm.service

# kernel command line option
ConditionKernelCommandLine=live.password_dialog

[Service]
Type=oneshot
Environment=TERM=linux

# disable the kernel output on the console
ExecStartPre=dmesg --console-off
# disable the systemd status messages on the console
ExecStartPre=kill -SIGRTMIN+21 1

ExecStart=live-password --dialog

# reset the console state after closing the dialog otherwise the dialog
# content would stay on the screen
ExecStartPost=reset
# enable back the kernel output on the console
ExecStartPost=dmesg --console-on
TTYReset=yes
TTYVHangup=yes
# enable back the systemd status messages on the console
ExecStartPost=kill -SIGRTMIN+20 1

StandardInput=tty
RemainAfterExit=true
TimeoutSec=0
Expand Down
14 changes: 10 additions & 4 deletions live/root/etc/systemd/system/live-password-systemd.service
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,24 @@ Before=serial-getty@ttyS1.service
Before=serial-getty@ttyS2.service
Before=serial-getty@ttysclp0.service

# start at the end to avoid overwriting the screen with systemd messages
After=agama.service
After=modprobe@drm.service

# kernel command line option
ConditionKernelCommandLine=live.password_systemd

[Service]
Type=oneshot

# disable the kernel output on the console
ExecStartPre=dmesg --console-off
# disable the systemd status messages on the console
ExecStartPre=kill -SIGRTMIN+21 1

ExecStart=live-password --systemd

# enable back the kernel output on the console
ExecStartPost=dmesg --console-on
# enable back the systemd status messages on the console
ExecStartPost=kill -SIGRTMIN+20 1

StandardOutput=tty
RemainAfterExit=true
TimeoutSec=0
Expand Down
10 changes: 10 additions & 0 deletions live/root/usr/bin/agama-issue-generator
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ generate_network_url() {
fi
}

# wait until the SSL fingreprint issue is create, but at most 10 seconds
wait_for_ssl_issue() {
for i in $(seq 1 "$1"); do
[ -f "$CERT_ISSUE" ] && exit 0
sleep 1
done
}

# make sure the parent directory for the issues exists
mkdir -p /run/issue.d

Expand All @@ -159,6 +167,8 @@ elif [ "$1" = "--ssh" ]; then
generate_ssh_fingerprints
elif [ "$1" = "--ssl" ]; then
generate_certificate_fingerprints
elif [ "$1" = "--wait-for-ssl" ]; then
wait_for_ssl_issue "$2"
elif [ "$1" = "--network" ]; then
generate_network_url "$2" "$3"
elif [ "$1" = "--watch-avahi" ]; then
Expand Down
9 changes: 5 additions & 4 deletions live/root/usr/bin/live-password
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@ TITLE="Set Login Password"

# functions for entering the password in an interactive dialog
confirm_exit() {
if dialog --backtitle "$BTITLE" --defaultno --yesno "Are you sure you want to cancel?" 5 40; then
# --keep-tite is not a misspelling of "title"
if dialog --keep-tite --backtitle "$BTITLE" --defaultno --yesno "Are you sure you want to cancel?" 5 40; then
exit 1
fi
}

msg_box() {
dialog --backtitle "$BTITLE" --msgbox "$1" 6 30
dialog --keep-tite --backtitle "$BTITLE" --msgbox "$1" 6 30
}

ask_password() {
if ! PWD1=$(dialog --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Password:" 8 40); then
if ! PWD1=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Password:" 8 40); then
confirm_exit
ask_password
fi

if ! PWD2=$(dialog --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Verify Password:" 8 40); then
if ! PWD2=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Verify Password:" 8 40); then
confirm_exit
ask_password
fi
Expand Down
1 change: 1 addition & 0 deletions live/src/config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ systemctl enable agama-auto.service
systemctl enable agama-hostname.service
systemctl enable agama-proxy-setup.service
systemctl enable agama-certificate-issue.path
systemctl enable agama-certificate-wait.service
systemctl enable agama-welcome-issue.service
systemctl enable agama-avahi-issue.service
systemctl enable agama-ssh-issue.service
Expand Down
1 change: 1 addition & 0 deletions products.d/tumbleweed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,4 @@ storage:
- ext3
- ext4
- xfs
- vfat
97 changes: 76 additions & 21 deletions rust/agama-cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,47 @@
use std::io::{self, Read};

use crate::{
error::CliError,
printers::{print, Format},
use std::{
io::{self, Read},
path::PathBuf,
process::Command,
};

use crate::show_progress;
use agama_lib::{
auth::AuthToken, connection, install_settings::InstallSettings, Store as SettingsStore,
};
use anyhow::anyhow;
use clap::Subcommand;
use std::io::Write;
use tempfile::Builder;

const DEFAULT_EDITOR: &str = "/usr/bin/vi";

#[derive(Subcommand, Debug)]
pub enum ConfigCommands {
/// Generates an installation profile with the current settings.
/// Generate an installation profile with the current settings.
///
/// It is possible that many configuration settings do not have a value. Those settings
/// are not included in the output.
///
/// The output of command can be used as input for the "agama config load".
Show,

/// Reads and loads a profile from the standard input.
/// Read and load a profile from the standard input.
Load,
}

pub enum ConfigAction {
Show,
Load,
/// Edit and update installation option using an external editor.
///
/// The changes are not applied if the editor exits with an error code.
///
/// If an editor is not specified, it honors the EDITOR environment variable. It falls back to
/// `/usr/bin/vi` as a last resort.
Edit {
/// Editor command (including additional arguments if needed)
#[arg(short, long)]
editor: Option<String>,
},
}

pub async fn run(subcommand: ConfigCommands, format: Format) -> anyhow::Result<()> {
pub async fn run(subcommand: ConfigCommands) -> anyhow::Result<()> {
let Some(token) = AuthToken::find() else {
println!("You need to login for generating a valid token");
return Ok(());
Expand All @@ -37,26 +50,68 @@ pub async fn run(subcommand: ConfigCommands, format: Format) -> anyhow::Result<(
let client = agama_lib::http_client(token.as_str())?;
let store = SettingsStore::new(connection().await?, client).await?;

let command = parse_config_command(subcommand)?;
match command {
ConfigAction::Show => {
match subcommand {
ConfigCommands::Show => {
let model = store.load().await?;
print(model, std::io::stdout(), format)?;
let json = serde_json::to_string_pretty(&model)?;
println!("{}", json);
Ok(())
}
ConfigAction::Load => {
ConfigCommands::Load => {
let mut stdin = io::stdin();
let mut contents = String::new();
stdin.read_to_string(&mut contents)?;
let result: InstallSettings = serde_json::from_str(&contents)?;
Ok(store.store(&result).await?)
}
ConfigCommands::Edit { editor } => {
let model = store.load().await?;
let editor = editor
.or_else(|| std::env::var("EDITOR").ok())
.unwrap_or(DEFAULT_EDITOR.to_string());
let result = edit(&model, &editor)?;
tokio::spawn(async move {
show_progress().await.unwrap();
});
store.store(&result).await?;
Ok(())
}
}
}

fn parse_config_command(subcommand: ConfigCommands) -> Result<ConfigAction, CliError> {
match subcommand {
ConfigCommands::Show => Ok(ConfigAction::Show),
ConfigCommands::Load => Ok(ConfigAction::Load),
/// Edit the installation settings using an external editor.
///
/// If the editor does not return a successful error code, it returns an error.
///
/// * `model`: current installation settings.
/// * `editor`: editor command.
fn edit(model: &InstallSettings, editor: &str) -> anyhow::Result<InstallSettings> {
let content = serde_json::to_string_pretty(model)?;
let mut file = Builder::new().suffix(".json").tempfile()?;
let path = PathBuf::from(file.path());
write!(file, "{}", content)?;

let mut command = editor_command(&editor);
let status = command.arg(path.as_os_str()).status()?;
if status.success() {
return Ok(InstallSettings::from_file(path)?);
}

Err(anyhow!(
"Ignoring the changes becase the editor was closed with an error code."
))
}

/// Return the Command to run the editor.
///
/// Separate the program and the arguments and build a Command struct.
///
/// * `command`: command to run as editor.
fn editor_command(command: &str) -> Command {
let mut parts = command.split_whitespace();
let program = parts.next().unwrap_or(DEFAULT_EDITOR);

let mut command = Command::new(program);
command.args(parts.collect::<Vec<&str>>());
command
}
8 changes: 1 addition & 7 deletions rust/agama-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod commands;
mod config;
mod error;
mod logs;
mod printers;
mod profile;
mod progress;
mod questions;
Expand All @@ -18,7 +17,6 @@ use auth::run as run_auth_cmd;
use commands::Commands;
use config::run as run_config_cmd;
use logs::run as run_logs_cmd;
use printers::Format;
use profile::run as run_profile_cmd;
use progress::InstallerProgress;
use questions::run as run_questions_cmd;
Expand All @@ -39,10 +37,6 @@ use std::{
struct Cli {
#[command(subcommand)]
pub command: Commands,

/// Format output
#[arg(value_enum, short, long, default_value_t = Format::Json)]
pub format: Format,
}

async fn probe() -> anyhow::Result<()> {
Expand Down Expand Up @@ -129,7 +123,7 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> {
Commands::Config(subcommand) => {
let manager = build_manager().await?;
wait_for_services(&manager).await?;
run_config_cmd(subcommand, cli.format).await
run_config_cmd(subcommand).await
}
Commands::Probe => {
let manager = build_manager().await?;
Expand Down
Loading

0 comments on commit ad4d64c

Please sign in to comment.