hadoop_common/security/user_group_information.rs
1use super::User;
2use std::{collections::HashMap, env, sync::Mutex};
3
4const HADOOP_PROXY_USER: &str = "HADOOP_PROXY_USER";
5
6/// Information about the logged in user.
7static LOGIN_USER_REF: Mutex<Option<UserGroupInformation>> = Mutex::new(None);
8
9/// User and group information for Hadoop.
10/// This class provides methods to determine the
11/// user's username and groups. It supports both the Windows, Unix and Kerberos
12/// login modules.
13#[derive(Clone, Copy)]
14pub struct UserGroupInformation {
15 user: User,
16}
17
18impl UserGroupInformation {
19 /// A method to initialize the fields that depend on a configuration.
20 /// Must be called before useKerberos or groups is used.
21 fn ensure_initialized() {
22 // TODO
23 }
24
25 /// Return the current user, including any doAs in the current stack.
26 pub fn get_current_user() -> anyhow::Result<Self> {
27 Self::ensure_initialized();
28 // TODO: use context user if any
29 Self::get_login_user()
30 }
31
32 /// Get the currently logged in user. If no explicit login has occurred,
33 /// the user will automatically be logged in with either kerberos credentials
34 /// if available, or as the local OS user, based on security settings.
35 pub fn get_login_user() -> anyhow::Result<Self> {
36 Self::ensure_initialized();
37 // TODO: confirm whether to use Atomic or Mutex for LOGIN_USER_REF
38 if let Some(login_user) = *LOGIN_USER_REF.lock().unwrap() {
39 return Ok(login_user);
40 }
41 let new_login_user = Self::create_login_user(None)?;
42 let login_user = *LOGIN_USER_REF.lock().unwrap().get_or_insert_with(|| {
43 new_login_user.spawn_auto_renewal_thread_for_user_creds(false);
44 new_login_user
45 });
46 Ok(login_user)
47 }
48
49 fn create_login_user(subject: Option<&str>) -> anyhow::Result<Self> {
50 let real_user = Self::do_subject_login(subject, None)?;
51
52 // If the HADOOP_PROXY_USER environment variable
53 // is specified, create a proxy user as the logged in user.
54 let proxy_user = env::var(HADOOP_PROXY_USER).ok().filter(|p| !p.is_empty());
55 let login_user = proxy_user.map_or(real_user, |p| Self::create_proxy_user(&p, &real_user));
56
57 // TODO: load tokens from files and base64 encoding
58
59 Ok(login_user)
60 }
61
62 /// Spawn a thread to do periodic renewals of kerberos credentials. NEVER
63 /// directly call this method. This method should only be used for ticket cache
64 /// based kerberos credentials.
65 fn spawn_auto_renewal_thread_for_user_creds(&self, _force: bool) {
66 // TODO
67 }
68
69 /// Create a proxy user using username of the effective user and the ugi of the
70 /// real user.
71 pub fn create_proxy_user(_user: &str, real_user: &Self) -> Self {
72 // TODO
73 real_user.to_owned()
74 }
75
76 /// Get the user's login name.
77 pub fn get_short_user_name(&self) -> String {
78 self.user.get_short_name()
79 }
80
81 /// Get the user's full principal name.
82 pub fn get_user_name(&self) -> String {
83 self.user.get_name()
84 }
85
86 /// Login a subject with the given parameters. If the subject is null,
87 /// the login context used to create the subject will be attached.
88 fn do_subject_login(
89 _subject: Option<&str>,
90 _params: Option<HashMap<String, String>>,
91 ) -> anyhow::Result<Self> {
92 // TODO
93 Ok(Self { user: User {} })
94 }
95}