Skip to content

Commit

Permalink
feat: rbac changes (openobserve#2634)
Browse files Browse the repository at this point in the history
Co-authored-by: omkark06 <omkar@zinclabs.io>
  • Loading branch information
oasisk and omkarK06 authored Feb 1, 2024
1 parent 092e037 commit 56f8cb1
Show file tree
Hide file tree
Showing 18 changed files with 1,245 additions and 366 deletions.
12 changes: 11 additions & 1 deletion src/common/meta/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ pub enum UserRole {
#[cfg(feature = "enterprise")]
#[serde(rename = "viewer")]
Viewer,
#[cfg(feature = "enterprise")]
#[serde(rename = "user")]
User,
}

impl fmt::Display for UserRole {
Expand All @@ -207,6 +210,8 @@ impl fmt::Display for UserRole {
UserRole::Root => write!(f, "root"),
#[cfg(feature = "enterprise")]
UserRole::Viewer => write!(f, "viewer"),
#[cfg(feature = "enterprise")]
UserRole::User => write!(f, "user"),
}
}
}
Expand All @@ -222,7 +227,12 @@ impl FromStr for UserRole {
"root" => Ok(UserRole::Root),
#[cfg(feature = "enterprise")]
"viewer" => Ok(UserRole::Viewer),
_ => Err(()),
#[cfg(feature = "enterprise")]
"user" => Ok(UserRole::User),
#[cfg(feature = "enterprise")]
_ => Ok(UserRole::User),
#[cfg(not(feature = "enterprise"))]
_ => Ok(UserRole::Admin),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/utils/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl FromRequest for AuthExtractor {

if let Some(auth_header) = req.headers().get("Authorization") {
if let Ok(auth_str) = auth_header.to_str() {
if (method.eq("POST") && path_columns[1].eq("_search"))
if (method.eq("POST") && path_columns[1].starts_with("_search"))
|| path.contains("/prometheus/api/v1/query")
|| path.contains("/resources")
{
Expand Down
9 changes: 7 additions & 2 deletions src/handler/http/auth/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub async fn process_token(
Option<TokenData<HashMap<String, Value>>>,
),
) {
use std::str::FromStr;

use config::CONFIG;
use o2_enterprise::enterprise::openfga::{
authorizer::{
Expand All @@ -42,6 +44,8 @@ pub async fn process_token(
meta::mapping::{NON_OWNING_ORG, OFGA_MODELS},
};

use crate::common::meta::user::UserRole;

let dec_token = res.1.unwrap();

let groups = match dec_token.claims.get("groups") {
Expand All @@ -60,7 +64,7 @@ pub async fn process_token(
let mut tuples_to_add = HashMap::new();
if groups.is_empty() {
source_orgs.push(UserOrg {
role: crate::common::meta::user::UserRole::Viewer,
role: UserRole::from_str(&O2_CONFIG.dex.default_role).unwrap(),
name: O2_CONFIG.dex.default_org.clone(),
..UserOrg::default()
});
Expand Down Expand Up @@ -90,7 +94,6 @@ pub async fn process_token(
&org.role.to_string(),
&mut tuples,
);

get_org_creation_tuples(
&org.name,
&mut tuples,
Expand All @@ -101,10 +104,12 @@ pub async fn process_token(
NON_OWNING_ORG.to_vec(),
)
.await;

if index == 0 {
// this is to allow user call organization api with org
tuples.push(get_user_org_tuple(&user_email, &user_email));
}

tuples_to_add.insert(org.name.to_owned(), tuples);
}
}
Expand Down
40 changes: 31 additions & 9 deletions src/handler/http/request/authz/fga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::io::Error;

use actix_web::{get, post, put, web, HttpResponse};
#[cfg(feature = "enterprise")]
use o2_enterprise::enterprise::dex::meta::auth::RolePermissionRequest;
use o2_enterprise::enterprise::dex::meta::auth::RoleRequest;

use crate::common::meta::user::{UserGroup, UserGroupRequest, UserRoleRequest};

Expand Down Expand Up @@ -62,16 +62,20 @@ pub async fn get_roles(_org_id: web::Path<String>) -> Result<HttpResponse, Error
}

#[cfg(feature = "enterprise")]
#[put("/{org_id}/roles/{role_id}/permissions")]
pub async fn update_role_permissions(
#[put("/{org_id}/roles/{role_id}")]
pub async fn update_role(
path: web::Path<(String, String)>,
permissions: web::Json<RolePermissionRequest>,
update_role: web::Json<RoleRequest>,
) -> Result<HttpResponse, Error> {
let (_org_id, role_id) = path.into_inner();
let permissions = permissions.into_inner();
match o2_enterprise::enterprise::openfga::authorizer::add_permissions_to_role(
let update_role = update_role.into_inner();

match o2_enterprise::enterprise::openfga::authorizer::update_role(
&role_id,
permissions,
update_role.add,
update_role.remove,
update_role.add_users,
update_role.remove_users,
)
.await
{
Expand All @@ -81,8 +85,8 @@ pub async fn update_role_permissions(
}

#[cfg(not(feature = "enterprise"))]
#[post("/{org_id}/roles/{role_id}/permissions")]
pub async fn update_role_permissions(
#[post("/{org_id}/roles/{role_id}")]
pub async fn update_role(
_path: web::Path<(String, String)>,
_permissions: web::Json<String>,
) -> Result<HttpResponse, actix_web::Error> {
Expand Down Expand Up @@ -113,6 +117,24 @@ pub async fn get_role_permissions(
Ok(HttpResponse::Forbidden().json("Not Supported"))
}

#[cfg(feature = "enterprise")]
#[get("/{org_id}/roles/{role_id}/users")]
pub async fn get_users_with_role(path: web::Path<(String, String)>) -> Result<HttpResponse, Error> {
let (org_id, role_id) = path.into_inner();
match o2_enterprise::enterprise::openfga::authorizer::get_users_with_role(&org_id, &role_id)
.await
{
Ok(res) => Ok(HttpResponse::Ok().json(res)),
Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string())),
}
}

#[cfg(not(feature = "enterprise"))]
#[get("/{org_id}/roles/{role_id}/users")]
pub async fn get_users_with_role(_org_id: web::Path<String>) -> Result<HttpResponse, Error> {
Ok(HttpResponse::Forbidden().json("Not Supported"))
}

#[cfg(feature = "enterprise")]
#[post("/{org_id}/groups")]
pub async fn create_group(
Expand Down
5 changes: 3 additions & 2 deletions src/handler/http/router/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,14 @@ pub fn get_service_routes(cfg: &mut web::ServiceConfig) {
.service(organization::org::create_org)
.service(authz::fga::create_role)
.service(authz::fga::get_roles)
.service(authz::fga::update_role_permissions)
.service(authz::fga::update_role)
.service(authz::fga::get_role_permissions)
.service(authz::fga::create_group)
.service(authz::fga::update_group)
.service(authz::fga::get_groups)
.service(authz::fga::get_group_details)
.service(authz::fga::get_resources),
.service(authz::fga::get_resources)
.service(authz::fga::get_users_with_role),
);
}

Expand Down
25 changes: 18 additions & 7 deletions src/job/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

use config::{cluster, ider, utils::file::clean_empty_dirs, CONFIG, INSTANCE_ID};
use infra::file_list as infra_file_list;
#[cfg(feature = "enterprise")]
use o2_enterprise::enterprise::common::infra::config::O2_CONFIG;
use regex::Regex;

use crate::{
Expand Down Expand Up @@ -192,13 +194,22 @@ pub async fn init() -> Result<(), anyhow::Error> {
o2_enterprise::enterprise::openfga::authorizer::init_open_fga().await;

// RBAC model
// #[cfg(feature = "enterprise")]
// let existing_meta = match db::get_ofga_model().await {
// Ok(Some(model)) => Some(model),
// Ok(None) | Err(_) => None,
// };
// #[cfg(feature = "enterprise")]
// let _ = db::set_ofga_model(existing_meta).await;
#[cfg(feature = "enterprise")]
if O2_CONFIG.openfga.enabled {
let existing_meta = match db::get_ofga_model().await {
Ok(Some(model)) => Some(model),
Ok(None) | Err(_) => None,
};
match db::set_ofga_model(existing_meta).await {
Ok(store_id) => {
o2_enterprise::enterprise::common::infra::config::OFGA_STORE_ID
.insert("store_id".to_owned(), store_id);
}
Err(e) => {
log::error!("Error setting OFGA model: {:?}", e);
}
}
}

// Shouldn't serve request until initialization finishes
log::info!("Job initialization complete");
Expand Down
32 changes: 21 additions & 11 deletions src/service/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,35 +59,40 @@ pub async fn set_instance(id: &str) -> Result<(), anyhow::Error> {
}

#[cfg(feature = "enterprise")]
pub async fn set_ofga_model(existing_meta: Option<OFGAModel>) -> Result<(), anyhow::Error> {
pub async fn set_ofga_model(existing_meta: Option<OFGAModel>) -> Result<String, anyhow::Error> {
use o2_enterprise::enterprise::openfga::model::{
create_open_fga_store, read_ofga_model, write_auth_models,
};

let meta = read_ofga_model().await;
if let Some(existig_model) = existing_meta {
if meta.version == existig_model.version {
Ok(())
if let Some(existing_model) = existing_meta {
if meta.version == existing_model.version {
log::info!("OFGA model already exists & no changes required");
Ok(meta.store_id)
} else {
let store_id = if existig_model.store_id.is_empty() {
let store_id = if existing_model.store_id.is_empty() {
create_open_fga_store().await.unwrap()
} else {
existig_model.store_id
existing_model.store_id
};

match write_auth_models(&meta, &store_id).await {
Ok(_) => {
let db = infra_db::get_db().await;
let key = "/ofga/model";

let mut loc_meta = meta.clone();
loc_meta.store_id = store_id;
loc_meta.model = None;

match db
.put(
key,
json::to_vec(&meta).unwrap().into(),
json::to_vec(&loc_meta).unwrap().into(),
infra_db::NO_NEED_WATCH,
)
.await
{
Ok(_) => Ok(()),
Ok(_) => Ok(loc_meta.store_id),
Err(e) => Err(anyhow::anyhow!(e)),
}
}
Expand All @@ -100,15 +105,20 @@ pub async fn set_ofga_model(existing_meta: Option<OFGAModel>) -> Result<(), anyh
Ok(_) => {
let db = infra_db::get_db().await;
let key = "/ofga/model";

let mut loc_meta = meta.clone();
loc_meta.store_id = store_id;
loc_meta.model = None;

match db
.put(
key,
json::to_vec(&meta).unwrap().into(),
json::to_vec(&loc_meta).unwrap().into(),
infra_db::NO_NEED_WATCH,
)
.await
{
Ok(_) => Ok(()),
Ok(_) => Ok(loc_meta.store_id),
Err(e) => Err(anyhow::anyhow!(e)),
}
}
Expand Down
8 changes: 4 additions & 4 deletions web/src/components/iam/groups/EditGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ const addedRoles = ref(new Set());
const removedRoles = ref(new Set());
const tabs = [
{
value: "users",
label: "Users",
},
{
value: "roles",
label: "Roles",
},
{
value: "users",
label: "Users",
},
];
const getGroupDetails = () => {
Expand Down
Loading

0 comments on commit 56f8cb1

Please sign in to comment.