Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[implant] Add code quality tools #34

Open
wants to merge 23 commits into
base: release/1.11.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ jobs:
- run: sudo apt-get -y install curl musl-tools
- run: curl https://sh.rustup.rs -sSf | sh -s -- -y
- run: . "$HOME/.cargo/env"; rustup target add x86_64-unknown-linux-musl
# Install quality tools
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Can we add the fact of putting the build in error if we have warnings during compilation?

- run: |
rustup component add clippy
rustup component add rustfmt
cargo install cargo-audit
# Run checks
- run: cargo check
- run: cargo clippy -- -D warnings
- run: cargo fmt -- --check
- run: cargo audit
- run: cargo test --release
- run: . "$HOME/.cargo/env"; cargo build --target=x86_64-unknown-linux-musl --release
- run: strip ./target/x86_64-unknown-linux-musl/release/openbas-implant
- save_cache:
Expand Down Expand Up @@ -150,6 +161,17 @@ jobs:
- run: sudo apt-get -y install curl musl-tools
- run: curl https://sh.rustup.rs -sSf | sh -s -- -y
- run: . "$HOME/.cargo/env"; rustup target add aarch64-unknown-linux-musl
# Install quality tools
- run: |
rustup component add clippy
rustup component add rustfmt
cargo install cargo-audit
# Run checks
- run: cargo check
- run: cargo clippy -- -D warnings
- run: cargo fmt -- --check
- run: cargo audit
- run: cargo test --release
- run: . "$HOME/.cargo/env"; cargo build --target=aarch64-unknown-linux-musl --release
- run: strip ./target/aarch64-unknown-linux-musl/release/openbas-implant
- save_cache:
Expand Down Expand Up @@ -192,6 +214,17 @@ jobs:
- cargo-{{ arch }}-{{ checksum "Cargo.toml" }}
- cargo-{{ arch }}
- run: curl https://sh.rustup.rs -sSf | sh -s -- -y
# Install quality tools
- run: |
rustup component add clippy
rustup component add rustfmt
cargo install cargo-audit
# Run checks
- run: cargo check
- run: cargo clippy -- -D warnings
- run: cargo fmt -- --check
- run: cargo audit
- run: cargo test --release
- run: . "$HOME/.cargo/env"; cargo build --release
- run: strip ./target/release/openbas-implant
- save_cache:
Expand Down Expand Up @@ -230,6 +263,17 @@ jobs:
- cargo-{{ arch }}-{{ checksum "Cargo.toml" }}
- cargo-{{ arch }}
- run: curl https://sh.rustup.rs -sSf | sh -s -- -y
# Install quality tools
- run: |
rustup component add clippy
rustup component add rustfmt
cargo install cargo-audit
# Run checks
- run: cargo check
- run: cargo clippy -- -D warnings
- run: cargo fmt -- --check
- run: cargo audit
- run: cargo test --release
- run: . "$HOME/.cargo/env"; cargo build --release
- run: strip ./target/release/openbas-implant
- save_cache:
Expand Down
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ assignees: ''

---

## Context

<!--
- Why is this solution needed?
- What value or benefits will the end-users gain from this change?
- Is this change a technical improvement? just for internal use, or does it impact users as well?
-->

## Use case

<!-- Please describe the use case for which you need a solution -->
Expand Down
52 changes: 52 additions & 0 deletions CODE_QUALITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Code Quality Guidelines

This document outlines the tools and standards used to maintain code quality in this project. Please follow these guidelines to ensure the codebase remains clean, efficient, and secure.

## Quality Tools

### Clippy

Clippy is a Rust linter that provides a collection of lints to catch common mistakes and improve code quality.

- **How to Run Clippy Locally:**
To run Clippy, execute the following command:
```bash
cargo clippy -- -D warnings

This will cause the build to fail if there are any warnings or errors.

Clippy on CI: Clippy is run automatically on CI as part of the build process. Ensure that no warnings or errors are present before pushing your changes.

### Rustfmt

Rustfmt automatically formats Rust code to conform to style guidelines.

- **How to Run Rustfmt Locally:**
To check if your code is formatted properly, run:
```bash
cargo fmt -- --check

This will not modify any files but will indicate if formatting is required.

Rustfmt on CI: Rustfmt is run as part of the CI pipeline, and the build will fail if there are formatting issues.

### Cargo Audit

Cargo Audit checks for known vulnerabilities in the dependencies of your project.

- **How to Run Cargo Audit Locally:**
To check for security vulnerabilities, run:
```bash
cargo audit

If any vulnerabilities are found, please resolve them before submitting your code.

### Running Tests

Unit tests and integration tests are run automatically on CI using the following command:

- **How to Test Locally:**
```bash
cargo test

Make sure your code passes all tests before pushing.
33 changes: 19 additions & 14 deletions src/api/manage_inject.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{env, fs};
use std::fs::File;
use std::io::{BufWriter, Write};
use std::{env, fs};

use mailparse::{parse_content_disposition, parse_header};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -68,15 +68,20 @@ pub struct UpdateInput {
}

impl Client {

pub fn get_executable_payload(&self, inject_id: String) -> Result<InjectorContractPayload, Error> {
return match self.get(&format!("/api/injects/{}/executable-payload", inject_id)).call() {
pub fn get_executable_payload(
&self,
inject_id: String,
) -> Result<InjectorContractPayload, Error> {
match self
.get(&format!("/api/injects/{}/executable-payload", inject_id))
.call()
{
Ok(response) => Ok(response.into_json()?),
Err(ureq::Error::Status(_, response)) => {
Err(Error::Api(response.into_string().unwrap()))
}
Err(err) => Err(Error::Internal(err.to_string())),
};
}
}

pub fn update_status(
Expand All @@ -85,7 +90,7 @@ impl Client {
input: UpdateInput,
) -> Result<UpdateInjectResponse, Error> {
let post_data = ureq::json!(input);
return match self
match self
.post(&format!("/api/injects/execution/callback/{}", inject_id))
.send_json(post_data)
{
Expand All @@ -94,11 +99,11 @@ impl Client {
Err(Error::Api(response.into_string().unwrap()))
}
Err(err) => Err(Error::Internal(err.to_string())),
};
}
}

pub fn download_file(&self, document_id: &String, in_memory: bool) -> Result<String, Error> {
return match self
match self
.get(&format!("/api/documents/{}/file", document_id))
.call()
{
Expand All @@ -111,26 +116,26 @@ impl Client {
let executable_path = current_exe_patch.parent().unwrap();
let name = dis.params.get("filename").unwrap();
let file_directory = executable_path.join(name);
return if in_memory {
if in_memory {
let buf = BufWriter::new(Vec::new());
let _ = write_response(buf, response);
Ok(String::from(name))
} else {
let output_file = File::create(file_directory.clone()).unwrap();
let file_write = write_response(output_file, response);
return match file_write {
match file_write {
Ok(_) => Ok(String::from(name)),
Err(err) => {
let _ = fs::remove_file(file_directory.clone());
return Err(Error::Io(err));
Err(Error::Io(err))
}
};
};
}
}
}
Err(ureq::Error::Status(_, response)) => {
Err(Error::Api(response.into_string().unwrap()))
}
Err(err) => Err(Error::Internal(err.to_string())),
};
}
}
}
6 changes: 3 additions & 3 deletions src/api/manage_reporting.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::Client;
use crate::api::manage_inject::UpdateInput;
use crate::api::Client;
use crate::handle::ExecutionOutput;

pub fn report_success(
Expand All @@ -12,7 +12,7 @@ pub fn report_success(
) {
let message = ExecutionOutput {
action: String::from(semantic),
stderr: stderr.unwrap_or(String::new()),
stderr: stderr.unwrap_or_default(),
stdout,
exit_code: -1,
};
Expand All @@ -37,7 +37,7 @@ pub fn report_error(
) {
let message = ExecutionOutput {
action: String::from(semantic),
stdout: stdout.unwrap_or(String::new()),
stdout: stdout.unwrap_or_default(),
stderr,
exit_code: -1,
};
Expand Down
32 changes: 22 additions & 10 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use rustls::ClientConfig;
use rustls_platform_verifier::BuilderVerifierExt;
use std::sync::Arc;
use std::time::Duration;
use ureq::{Agent, Request};
Expand All @@ -15,16 +17,24 @@ pub struct Client {
}

impl Client {
pub fn new(server_url: String, token: String, unsecured_certificate: bool, with_proxy: bool) -> Client {
pub fn new(
server_url: String,
token: String,
unsecured_certificate: bool,
with_proxy: bool,
) -> Client {
let mut http_client = ureq::AgentBuilder::new()
.timeout_connect(Duration::from_secs(2))
.timeout(Duration::from_secs(5))
.user_agent(format!("openbas-implant/{}", VERSION).as_str())
.try_proxy_from_env(with_proxy);
if unsecured_certificate {
let arc_crypto_provider = Arc::new(rustls::crypto::ring::default_provider());
let config = rustls_platform_verifier::tls_config_with_provider(arc_crypto_provider)
.expect("Failed to create TLS config with crypto provider");
let config = ClientConfig::builder_with_provider(arc_crypto_provider)
.with_safe_default_protocol_versions()
.unwrap()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Can we keep the expect here ?

.expect("Failed to create TLS config with crypto provider")

.with_platform_verifier()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Why adding this line ?

.with_no_client_auth();
http_client = http_client.tls_config(Arc::new(config));
}
// Remove trailing slash
Expand All @@ -42,15 +52,17 @@ impl Client {

pub fn post(&self, route: &str) -> Request {
let api_route = format!("{}{}", self.server_url, route);
let request = self.http_client.post(&api_route)
.set("Authorization", &format!("Bearer {}", self.token));
return request;

self.http_client
.post(&api_route)
.set("Authorization", &format!("Bearer {}", self.token))
}

pub fn get(&self, route: &str) -> Request {
let api_route = format!("{}{}", self.server_url, route);
let request = self.http_client.get(&api_route)
.set("Authorization", &format!("Bearer {}", self.token));
return request;

self.http_client
.get(&api_route)
.set("Authorization", &format!("Bearer {}", self.token))
}
}
}
2 changes: 1 addition & 1 deletion src/common/error_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl fmt::Display for Error {
match self {
Error::Internal(message) => write!(f, "{}", message),
Error::Api(api_message) => write!(f, "{}", api_message),
Error::Io(io) => write!(f, "{}", io.to_string()),
Error::Io(io) => write!(f, "{}", io),
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/handle/handle_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@ use std::time::Instant;

use log::info;

use crate::api::manage_inject::InjectorContractPayload;
use crate::api::Client;
use crate::api::manage_inject::{InjectorContractPayload};
use crate::handle::handle_execution::handle_execution_result;
use crate::process::command_exec::command_execution;

fn compute_working_dir() -> PathBuf {
let current_exe_patch = env::current_exe().unwrap();
return current_exe_patch.parent().unwrap().to_path_buf();
current_exe_patch.parent().unwrap().to_path_buf()
}

pub fn compute_command(command: &String) -> String {
let executable_command = command.clone();
pub fn compute_command(command: &str) -> String {
let executable_command = command;
let working_dir = compute_working_dir();
return executable_command.replace("#{location}", working_dir.to_str().unwrap());
executable_command.replace("#{location}", working_dir.to_str().unwrap())
}

pub fn handle_execution_command(
semantic: &str,
api: &Client,
inject_id: String,
command: &String,
executor: &String,
executor: &str,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Why changing executor type and not command as well ?

pre_check: bool,
) -> i32 {
let now = Instant::now();
info!("{} execution: {:?}", semantic, command);
let command_result = command_execution(command.as_str(), executor.as_str(), pre_check);
let command_result = command_execution(command.as_str(), executor, pre_check);
let elapsed = now.elapsed().as_millis();
return handle_execution_result(semantic, api, inject_id, command_result, elapsed);
handle_execution_result(semantic, api, inject_id, command_result, elapsed)
}

pub fn handle_command(inject_id: String, api: &Client, contract_payload: &InjectorContractPayload) {
Expand All @@ -41,7 +41,7 @@ pub fn handle_command(inject_id: String, api: &Client, contract_payload: &Inject
let executable_command = compute_command(&command);
let _ = handle_execution_command(
"implant execution",
&api,
api,
inject_id.clone(),
&executable_command,
&executor,
Expand Down
Loading