Repository: bottlerocket-os/bottlerocket
File: sources/logdog/src/log_request.rs (Rust)

Code before:
                    .entry(part.to_string())
                    .or_insert(serde_json::Value::Object(serde_json::Map::new()));
            }
        }
        *current = v;
    }
    Ok(result)
}

/// Requests settings from the API, filters them, and writes the output to `tempdir`
async fn handle_settings_request<P>(request: &LogRequest<'_>, tempdir: P) -> Result<()>
where
    P: AsRef<Path>,
{
    let settings = get_settings().await?;
    let mut settings_map = HashMap::new();
    normalize(&settings, String::default(), &mut settings_map)?;

    // Filter all settings that match any of the "sensitive" patterns
    for pattern in SENSITIVE_SETTINGS_PATTERNS {
        let pattern =
            Pattern::new(pattern).context(error::ParseGlobPatternSnafu { pattern: *pattern })?;
        settings_map.retain(|k, _| !pattern.matches(k.as_str()))
    }

    // Serialize the map back to a `Settings` to remove the escaping so it writes nicely to file
    let settings = serde_json::to_value(denormalize(
        settings_map
            .iter()
            .map(|(k, v)| (k.to_string(), v.clone()))
            .collect(),
    )?)
    .context(error::SerializeSettingsSnafu)?;
    let outpath = tempdir.as_ref().join(request.filename);
    let outfile = File::create(&outpath).context(error::FileCreateSnafu { path: &outpath })?;
    serde_json::to_writer_pretty(&outfile, &settings)
        .context(error::FileWriteSnafu { path: &outpath })?;
    Ok(())
}

/// Uses `apiclient` to request all settings from the apiserver and deserializes into a `Settings`
async fn get_settings() -> Result<serde_json::Value> {
    let result = Command::new("/usr/bin/apiclient")
        .arg("get")
        .output()
        .context(error::ApiCommandFailureSnafu)?;

    ensure!(
        result.status.success(),
        error::ApiExecutionFailureSnafu {
            reason: String::from_utf8_lossy(&result.stderr)

Review comment (suggestion):
```suggestion
    // Serialize the map back to a `json::Value` to remove the escaping so it writes nicely to file
```

Code after:
    }
    strip_user_data(&mut settings);

    let outpath = tempdir.as_ref().join(request.filename);
    let outfile = File::create(&outpath).context(error::FileCreateSnafu { path: &outpath })?;
    serde_json::to_writer_pretty(&outfile, &settings)
        .context(error::FileWriteSnafu { path: &outpath })?;
    Ok(())
}

/// Uses `apiclient` to request all settings from the apiserver and deserializes into a `json::Value`
async fn get_settings() -> Result<serde_json::Value> {
    let result = Command::new("/usr/bin/apiclient")
        .arg("get")
        .output()
        .context(error::ApiCommandFailureSnafu)?;

    ensure!(
        result.status.success(),
        error::ApiExecutionFailureSnafu {
            reason: String::from_utf8_lossy(&result.stderr)
        }
    );

    serde_json::from_slice(result.stdout.as_slice()).context(error::SettingsJsonSnafu)
}

/// Runs an `exec` `LogRequest`'s `instructions` and writes its output to to `tempdir`.
fn handle_exec_request<P>(request: &LogRequest<'_>, tempdir: P) -> Result<()>
where
    P: AsRef<Path>,
{
    let split =
        shell_words::split(request.instructions).with_context(|_| error::CommandParseSnafu {
            command: request.to_string(),
        })?;
    let (command, args) = split
        .split_first()
        .with_context(|| error::CommandMissingSnafu {
            request: request.to_string(),
        })?;
    let outpath = tempdir.as_ref().join(request.filename);
    let ofile = File::create(&outpath).context(error::CommandOutputFileSnafu { path: &outpath })?;
    let stderr_file = ofile
        .try_clone()
        .context(error::CommandErrFileSnafu { path: &outpath })?;
    Command::new(command)
        .args(args)
        .stdout(Stdio::from(ofile))
        .stderr(Stdio::from(stderr_file))
        .spawn()