Skip to content

Commit fc5c0f1

Browse files
authored
feat: add basic auth (#101)
1 parent a43f81d commit fc5c0f1

File tree

11 files changed

+145
-9
lines changed

11 files changed

+145
-9
lines changed

pyroscope_cli/src/cli/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ enum Commands {
6464
help = "Authentication token used when uploading profiling data"
6565
)]
6666
auth_token: Option<String>,
67+
#[clap(
68+
name = "basic_auth_username",
69+
long = "basic-auth-username",
70+
value_name = "BASIC_AUTH_USERNAME",
71+
help = "HTTP Basic Authentication username used when uploading profiling data"
72+
)]
73+
basic_auth_username: Option<String>,
74+
#[clap(
75+
name = "basic_auth_password",
76+
long = "basic-auth-password",
77+
value_name = "BASIC_AUTH_PASSWORD",
78+
help = "HTTP Basic Authentication password used when uploading profiling data"
79+
)]
80+
basic_auth_password: Option<String>,
6781
#[clap(
6882
name = "scope_org_id",
6983
long = "scope_org_id",
@@ -197,6 +211,20 @@ enum Commands {
197211
help = "Authentication token used when uploading profiling data"
198212
)]
199213
auth_token: Option<String>,
214+
#[clap(
215+
name = "basic_auth_username",
216+
long = "basic-auth-username",
217+
value_name = "BASIC_AUTH_USERNAME",
218+
help = "HTTP Basic Authentication username used when uploading profiling data"
219+
)]
220+
basic_auth_username: Option<String>,
221+
#[clap(
222+
name = "basic_auth_password",
223+
long = "basic-auth-password",
224+
value_name = "BASIC_AUTH_PASSWORD",
225+
help = "HTTP Basic Authentication password used when uploading profiling data"
226+
)]
227+
basic_auth_password: Option<String>,
200228
#[clap(
201229
name = "scope_org_id",
202230
long = "scope_org_id",

pyroscope_cli/src/core/profiler.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ impl Profiler {
2525
let app_name: String = AppConfig::get::<String>("application_name")?;
2626

2727
let auth_token: String = AppConfig::get::<String>("auth_token")?;
28+
let basic_auth_username: String = AppConfig::get::<String>("basic_auth_username")?;
29+
let basic_auth_password: String = AppConfig::get::<String>("basic_auth_password")?;
2830

2931
let scope_org_id: String = AppConfig::get::<String>("scope_org_id").unwrap_or("".to_string());
3032

@@ -70,6 +72,8 @@ impl Profiler {
7072
// There must be a better way to do this, hopefully as clap supports Option<String>
7173
if auth_token.len() > 0 {
7274
builder = builder.auth_token(auth_token);
75+
} else if basic_auth_username != "" && basic_auth_password != "" {
76+
builder = builder.basic_auth(basic_auth_username, basic_auth_password);
7377
}
7478

7579
builder.backend(backend).tags(tags).build()?

pyroscope_cli/src/resources/default_config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ pyspy_native = false
88
sample_rate = 100
99
server_address = "http://localhost:4040"
1010
auth_token = ""
11+
basic_auth_username = ""
12+
basic_auth_password = ""
1113
debug = false

pyroscope_cli/src/utils/app_config.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub struct AppConfig {
2121
pub spy_name: Spy,
2222
pub application_name: Option<String>,
2323
pub auth_token: Option<String>,
24+
pub basic_auth_username: Option<String>,
25+
pub basic_auth_password: Option<String>,
2426
pub detect_subprocesses: Option<bool>,
2527
pub no_logging: Option<bool>,
2628
pub log_level: LogLevel,
@@ -119,6 +121,16 @@ impl AppConfig {
119121
AppConfig::set("auth_token", auth_token)?;
120122
}
121123
}
124+
if sub_connect.is_present("basic_auth_username") {
125+
if let Some(basic_auth_username) = sub_connect.value_of("basic_auth_username") {
126+
AppConfig::set("basic_auth_username", basic_auth_username)?;
127+
}
128+
}
129+
if sub_connect.is_present("basic_auth_password") {
130+
if let Some(basic_auth_password) = sub_connect.value_of("basic_auth_password") {
131+
AppConfig::set("basic_auth_password", basic_auth_password)?;
132+
}
133+
}
122134
if sub_connect.is_present("scope_org_id") {
123135
if let Some(scope_org_id) = sub_connect.value_of("scope_org_id") {
124136
AppConfig::set("scope_org_id", scope_org_id)?;
@@ -210,6 +222,16 @@ impl AppConfig {
210222
AppConfig::set("auth_token", auth_token)?;
211223
}
212224
}
225+
if sub_exec.is_present("basic_auth_username") {
226+
if let Some(basic_auth_username) = sub_exec.value_of("basic_auth_username") {
227+
AppConfig::set("basic_auth_username", basic_auth_username)?;
228+
}
229+
}
230+
if sub_exec.is_present("basic_auth_password") {
231+
if let Some(basic_auth_password) = sub_exec.value_of("basic_auth_password") {
232+
AppConfig::set("basic_auth_password", basic_auth_password)?;
233+
}
234+
}
213235
if sub_exec.is_present("scope_org_id") {
214236
if let Some(scope_org_id) = sub_exec.value_of("scope_org_id") {
215237
AppConfig::set("scope_org_id", scope_org_id)?;

pyroscope_ffi/python/lib/include/pyroscope_ffi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ bool initialize_logging(uint32_t logging_level);
1717
bool initialize_agent(const char *application_name,
1818
const char *server_address,
1919
const char *auth_token,
20+
const char *basic_auth_username,
21+
const char *basic_auth_password,
2022
uint32_t sample_rate,
2123
bool detect_subprocesses,
2224
bool oncpu,

pyroscope_ffi/python/lib/src/lib.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,20 @@ pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
4040

4141
#[no_mangle]
4242
pub extern "C" fn initialize_agent(
43-
application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
44-
sample_rate: u32, detect_subprocesses: bool, oncpu: bool, native: bool, gil_only: bool,
45-
report_pid: bool, report_thread_id: bool, report_thread_name: bool, tags: *const c_char,
43+
application_name: *const c_char,
44+
server_address: *const c_char,
45+
auth_token: *const c_char,
46+
basic_auth_username: *const c_char,
47+
basic_auth_password: *const c_char,
48+
sample_rate: u32,
49+
detect_subprocesses: bool,
50+
oncpu: bool,
51+
native: bool,
52+
gil_only: bool,
53+
report_pid: bool,
54+
report_thread_id: bool,
55+
report_thread_name: bool,
56+
tags: *const c_char,
4657
scope_org_id: *const c_char,
4758
http_headers_json: *const c_char,
4859
) -> bool {
@@ -61,12 +72,21 @@ pub extern "C" fn initialize_agent(
6172
.unwrap()
6273
.to_string();
6374

64-
// auth_token
6575
let auth_token = unsafe { CStr::from_ptr(auth_token) }
6676
.to_str()
6777
.unwrap()
6878
.to_string();
6979

80+
let basic_auth_username = unsafe { CStr::from_ptr(basic_auth_username) }
81+
.to_str()
82+
.unwrap()
83+
.to_string();
84+
85+
let basic_auth_password = unsafe { CStr::from_ptr(basic_auth_password) }
86+
.to_str()
87+
.unwrap()
88+
.to_string();
89+
7090
// tags
7191
let tags_string = unsafe { CStr::from_ptr(tags) }
7292
.to_str()
@@ -124,6 +144,8 @@ pub extern "C" fn initialize_agent(
124144
// Add the auth token if it is not empty.
125145
if auth_token != "" {
126146
agent_builder = agent_builder.auth_token(auth_token);
147+
} else if basic_auth_username != "" && basic_auth_password != "" {
148+
agent_builder = agent_builder.basic_auth(basic_auth_username, basic_auth_password);
127149
}
128150
if scope_org_id != "" {
129151
agent_builder = agent_builder.scope_org_id(scope_org_id);

pyroscope_ffi/python/pyroscope/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ def configure(
1212
application_name=None,
1313
server_address="http://localhost:4040",
1414
auth_token="",
15+
basic_auth_username="",
16+
basic_auth_password="",
1517
enable_logging=False,
1618
sample_rate=100,
1719
detect_subprocesses=False,
@@ -39,6 +41,8 @@ def configure(
3941
application_name.encode("UTF-8"),
4042
server_address.encode("UTF-8"),
4143
auth_token.encode("UTF-8"),
44+
basic_auth_username.encode("UTF-8"),
45+
basic_auth_password.encode("UTF-8"),
4246
sample_rate,
4347
detect_subprocesses,
4448
oncpu,

pyroscope_ffi/ruby/ext/rbspy/src/lib.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,18 @@ pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
110110

111111
#[no_mangle]
112112
pub extern "C" fn initialize_agent(
113-
application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
114-
sample_rate: u32, detect_subprocesses: bool, oncpu: bool, report_pid: bool,
115-
report_thread_id: bool, tags: *const c_char, compression: *const c_char,
113+
application_name: *const c_char,
114+
server_address: *const c_char,
115+
auth_token: *const c_char,
116+
basic_auth_user: *const c_char,
117+
basic_auth_password: *const c_char,
118+
sample_rate: u32,
119+
detect_subprocesses: bool,
120+
oncpu: bool,
121+
report_pid: bool,
122+
report_thread_id: bool,
123+
tags: *const c_char,
124+
compression: *const c_char,
116125
report_encoding: *const c_char,
117126
scope_org_id: *const c_char,
118127
http_headers_json: *const c_char,
@@ -135,6 +144,16 @@ pub extern "C" fn initialize_agent(
135144
.unwrap()
136145
.to_string();
137146

147+
let basic_auth_user = unsafe { CStr::from_ptr(basic_auth_user) }
148+
.to_str()
149+
.unwrap()
150+
.to_string();
151+
152+
let basic_auth_password = unsafe { CStr::from_ptr(basic_auth_password) }
153+
.to_str()
154+
.unwrap()
155+
.to_string();
156+
138157
let tags_string = unsafe { CStr::from_ptr(tags) }
139158
.to_str()
140159
.unwrap()
@@ -186,6 +205,8 @@ pub extern "C" fn initialize_agent(
186205

187206
if auth_token != "" {
188207
agent_builder = agent_builder.auth_token(auth_token);
208+
} else if basic_auth_user != "" && basic_auth_password != "" {
209+
agent_builder = agent_builder.basic_auth(basic_auth_user, basic_auth_password);
189210
}
190211

191212
if scope_org_id != "" {

pyroscope_ffi/ruby/lib/pyroscope.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module Rust
99
extend FFI::Library
1010
ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
1111
attach_function :initialize_logging, [:int], :bool
12-
attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string, :string, :string, :string, :string], :bool
12+
attach_function :initialize_agent, [:string, :string, :string, :string, :string, :int, :bool, :bool, :bool, :bool, :string, :string, :string, :string, :string], :bool
1313
attach_function :add_thread_tag, [:uint64, :string, :string], :bool
1414
attach_function :remove_thread_tag, [:uint64, :string, :string], :bool
1515
attach_function :add_global_tag, [:string, :string], :bool
@@ -38,6 +38,8 @@ class Engine < ::Rails::Engine
3838
:app_name,
3939
:server_address,
4040
:auth_token,
41+
:basic_auth_username,
42+
:basic_auth_password,
4143
:log_level,
4244
:sample_rate,
4345
:detect_subprocesses,
@@ -57,6 +59,8 @@ def initialize(*)
5759
self.application_name = ''
5860
self.server_address = 'http://localhost:4040'
5961
self.auth_token = ''
62+
self.basic_auth_username = ''
63+
self.basic_auth_password = ''
6064
self.sample_rate = 100
6165
self.detect_subprocesses = false
6266
self.oncpu = true
@@ -106,6 +110,8 @@ def configure
106110
@config.app_name || @config.application_name || "",
107111
@config.server_address || "",
108112
@config.auth_token || "",
113+
@config.basic_auth_username || "",
114+
@config.basic_auth_password || "",
109115
@config.sample_rate || 100,
110116
@config.detect_subprocesses || false,
111117
@config.oncpu || false,

src/pyroscope.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct PyroscopeConfig {
4747
pub spy_name: String,
4848
/// Authentication Token
4949
pub auth_token: Option<String>,
50+
pub basic_auth: Option<BasicAuth>,
5051
/// Function to apply
5152
pub func: Option<fn(Report) -> Report>,
5253
/// Pyroscope http request body compression
@@ -56,6 +57,12 @@ pub struct PyroscopeConfig {
5657
pub http_headers: HashMap<String, String>,
5758
}
5859

60+
#[derive(Clone, Debug)]
61+
pub struct BasicAuth {
62+
pub username: String,
63+
pub password: String,
64+
}
65+
5966
impl Default for PyroscopeConfig {
6067
fn default() -> Self {
6168
Self {
@@ -68,6 +75,7 @@ impl Default for PyroscopeConfig {
6875
sample_rate: 100u32,
6976
spy_name: "undefined".to_string(),
7077
auth_token: None,
78+
basic_auth: None,
7179
func: None,
7280
compression: None,
7381
report_encoding: ReportEncoding::FOLDED,
@@ -93,6 +101,7 @@ impl PyroscopeConfig {
93101
sample_rate: 100u32, // Default sample rate
94102
spy_name: String::from("undefined"), // Spy Name should be set by the backend
95103
auth_token: None, // No authentication token
104+
basic_auth: None,
96105
func: None, // No function
97106
compression: None,
98107
report_encoding: ReportEncoding::FOLDED,
@@ -130,14 +139,21 @@ impl PyroscopeConfig {
130139
Self { spy_name, ..self }
131140
}
132141

133-
/// Set the Authentication Token.
142+
134143
pub fn auth_token(self, auth_token: String) -> Self {
135144
Self {
136145
auth_token: Some(auth_token),
137146
..self
138147
}
139148
}
140149

150+
pub fn basic_auth(self, username: String, password: String) -> Self {
151+
Self {
152+
basic_auth: Some(BasicAuth { username, password }),
153+
..self
154+
}
155+
}
156+
141157
/// Set the Function.
142158
pub fn func(self, func: fn(Report) -> Report) -> Self {
143159
Self {
@@ -310,6 +326,13 @@ impl PyroscopeAgentBuilder {
310326
}
311327
}
312328

329+
pub fn basic_auth(self, username: impl AsRef<str>, password: impl AsRef<str>) -> Self {
330+
Self {
331+
config: self.config.basic_auth(username.as_ref().to_owned(), password.as_ref().to_owned()),
332+
..self
333+
}
334+
}
335+
313336
/// Set the Function.
314337
/// This is optional. If not set, the agent will not apply any function.
315338
/// #Example

0 commit comments

Comments
 (0)