Skip to content

Commit

Permalink
Add initial implementation of auth service
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Cattermole <[email protected]>
  • Loading branch information
adam-cattermole committed Aug 16, 2024
1 parent b5b3b1b commit c752365
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 1 deletion.
1 change: 0 additions & 1 deletion src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ impl Attribute for DateTime<FixedOffset> {
}
}

#[allow(dead_code)]
pub fn get_attribute<T>(attr: &str) -> Result<T, String>

Check warning on line 106 in src/attribute.rs

View workflow job for this annotation

GitHub Actions / Test Suite

function `get_attribute` is never used

Check warning on line 106 in src/attribute.rs

View workflow job for this annotation

GitHub Actions / Test Suite

function `get_attribute` is never used

Check warning on line 106 in src/attribute.rs

View workflow job for this annotation

GitHub Actions / Check

function `get_attribute` is never used

Check warning on line 106 in src/attribute.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

function `get_attribute` is never used

Check failure on line 106 in src/attribute.rs

View workflow job for this annotation

GitHub Actions / Clippy

function `get_attribute` is never used
where
T: Attribute,
Expand Down
7 changes: 7 additions & 0 deletions src/envoy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ mod token_bucket;
mod value;

pub use {
address::{Address, SocketAddress},
attribute_context::{
AttributeContext, AttributeContext_HttpRequest, AttributeContext_Peer,
AttributeContext_Request,
},
base::Metadata,
external_auth::{CheckRequest, CheckResponse, CheckResponse_oneof_http_response},

Check warning on line 40 in src/envoy/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused imports: `CheckResponse_oneof_http_response` and `CheckResponse`

Check warning on line 40 in src/envoy/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused imports: `CheckResponse_oneof_http_response` and `CheckResponse`

Check warning on line 40 in src/envoy/mod.rs

View workflow job for this annotation

GitHub Actions / Check

unused imports: `CheckResponse_oneof_http_response` and `CheckResponse`

Check warning on line 40 in src/envoy/mod.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unused imports: `CheckResponse_oneof_http_response` and `CheckResponse`

Check failure on line 40 in src/envoy/mod.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused imports: `CheckResponse_oneof_http_response` and `CheckResponse`
ratelimit::{RateLimitDescriptor, RateLimitDescriptor_Entry},
rls::{RateLimitRequest, RateLimitResponse, RateLimitResponse_Code},
};
Expand Down
1 change: 1 addition & 0 deletions src/service.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod auth;
pub(crate) mod rate_limit;

use protobuf::Message;
Expand Down
122 changes: 122 additions & 0 deletions src/service/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use crate::attribute::get_attribute;
use crate::envoy::{
Address, AttributeContext, AttributeContext_HttpRequest, AttributeContext_Peer,
AttributeContext_Request, CheckRequest, Metadata, SocketAddress,
};
use crate::service::Service;
use chrono::{DateTime, FixedOffset, Timelike};
use protobuf::well_known_types::Timestamp;
use protobuf::Message;
use proxy_wasm::hostcalls;
use proxy_wasm::hostcalls::dispatch_grpc_call;
use proxy_wasm::types::{MapType, Status};
use std::collections::HashMap;
use std::time::Duration;

const AUTH_SERVICE_NAME: &str = "envoy.service.auth.v3.Authorization";
const AUTH_METHOD_NAME: &str = "Check";

pub struct AuthService {
endpoint: String,
metadata: Vec<(String, Vec<u8>)>,
}

impl AuthService {
pub fn new(endpoint: &str, metadata: Vec<(&str, &[u8])>) -> Self {

Check warning on line 25 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Test Suite

associated functions `new`, `message`, `build_check_req`, `build_request`, and `build_peer` are never used

Check warning on line 25 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Test Suite

associated functions `new`, `message`, `build_check_req`, `build_request`, and `build_peer` are never used

Check warning on line 25 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Check

associated functions `new`, `message`, `build_check_req`, `build_request`, and `build_peer` are never used

Check warning on line 25 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

associated functions `new`, `message`, `build_check_req`, `build_request`, and `build_peer` are never used

Check failure on line 25 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Clippy

associated functions `new`, `message`, `build_check_req`, `build_request`, and `build_peer` are never used
let m = metadata
.into_iter()
.map(|(header, value)| (header.to_owned(), value.to_owned()))
.collect();
Self {
endpoint: endpoint.to_owned(),
metadata: m,
}
}

pub fn message() -> CheckRequest {
AuthService::build_check_req()
}

fn build_check_req() -> CheckRequest {
let mut auth_req = CheckRequest::default();
let mut attr = AttributeContext::default();
attr.set_request(AuthService::build_request());
attr.set_destination(AuthService::build_peer(
get_attribute::<String>("destination.address").unwrap_or_default(),
get_attribute::<i64>("destination.port").unwrap_or_default() as u32,
));
attr.set_source(AuthService::build_peer(
get_attribute::<String>("source.address").unwrap_or_default(),
get_attribute::<i64>("source.port").unwrap_or_default() as u32,
));
// todo(adam-cattermole): for now we set the context_extensions to the request host
// but this should take other info into account
let context_extensions = HashMap::from([(
"host".to_string(),
attr.get_request().get_http().host.to_owned(),
)]);
attr.set_context_extensions(context_extensions);
attr.set_metadata_context(Metadata::default());
auth_req.set_attributes(attr);
auth_req
}

fn build_request() -> AttributeContext_Request {
let mut request = AttributeContext_Request::default();
let mut http = AttributeContext_HttpRequest::default();
let headers: HashMap<String, String> = hostcalls::get_map(MapType::HttpRequestHeaders)
.unwrap()
.into_iter()
.collect();

http.set_host(get_attribute::<String>("request.host").unwrap_or_default());
http.set_method(get_attribute::<String>("request.method").unwrap_or_default());
http.set_scheme(get_attribute::<String>("request.scheme").unwrap_or_default());
http.set_path(get_attribute::<String>("request.path").unwrap_or_default());
http.set_protocol(get_attribute::<String>("request.protocol").unwrap_or_default());

http.set_headers(headers);
request.set_time(get_attribute("request.time").map_or(
Timestamp::new(),
|date_time: DateTime<FixedOffset>| Timestamp {
nanos: date_time.nanosecond() as i32,
seconds: date_time.second() as i64,
unknown_fields: Default::default(),
cached_size: Default::default(),
},
));
request.set_http(http);
request
}

fn build_peer(host: String, port: u32) -> AttributeContext_Peer {
let mut peer = AttributeContext_Peer::default();
let mut address = Address::default();
let mut socket_address = SocketAddress::default();
socket_address.set_address(host);
socket_address.set_port_value(port);
address.set_socket_address(socket_address);
peer.set_address(address);
peer
}
}

impl Service<CheckRequest> for AuthService {
fn send(&self, message: CheckRequest) -> Result<u32, Status> {
let msg = Message::write_to_bytes(&message).unwrap(); // TODO(adam-cattermole): Error Handling
let metadata = self
.metadata
.iter()
.map(|(header, value)| (header.as_str(), value.as_slice()))
.collect();

dispatch_grpc_call(
self.endpoint.as_str(),
AUTH_SERVICE_NAME,
AUTH_METHOD_NAME,
metadata,
Some(&msg),
Duration::from_secs(5),
)
}
}

0 comments on commit c752365

Please sign in to comment.