1515
1616from  __future__ import  absolute_import 
1717
18+ from  oslo_config  import  cfg 
19+ 
1820from  st2common  import  log  as  logging 
1921
2022from  st2common .constants .keyvalue  import  DATASTORE_PARENT_SCOPE 
2123from  st2common .constants .keyvalue  import  SYSTEM_SCOPE , FULL_SYSTEM_SCOPE 
2224from  st2common .constants .keyvalue  import  USER_SCOPE , FULL_USER_SCOPE 
2325from  st2common .constants .keyvalue  import  ALLOWED_SCOPES 
2426from  st2common .constants .keyvalue  import  DATASTORE_KEY_SEPARATOR , USER_SEPARATOR 
27+ from  st2common .constants .types  import  ResourceType 
2528from  st2common .exceptions .db  import  StackStormDBObjectNotFoundError 
2629from  st2common .exceptions .keyvalue  import  InvalidScopeException , InvalidUserException 
30+ from  st2common .models .db .auth  import  UserDB 
2731from  st2common .models .system .keyvalue  import  UserKeyReference 
2832from  st2common .persistence .keyvalue  import  KeyValuePair 
2933from  st2common .persistence .rbac  import  UserRoleAssignment 
3034from  st2common .persistence .rbac  import  Role 
3135from  st2common .persistence .rbac  import  PermissionGrant 
32- from  st2common .constants .types  import  ResourceType 
36+ from  st2common .rbac .backends  import  get_rbac_backend 
37+ from  st2common .rbac .types  import  PermissionType 
3338
3439__all__  =  [
3540    "get_kvp_for_name" ,
@@ -103,7 +108,12 @@ class KeyValueLookup(BaseKeyValueLookup):
103108    scope  =  SYSTEM_SCOPE 
104109
105110    def  __init__ (
106-         self , prefix = None , key_prefix = None , cache = None , scope = FULL_SYSTEM_SCOPE 
111+         self ,
112+         prefix = None ,
113+         key_prefix = None ,
114+         cache = None ,
115+         scope = FULL_SYSTEM_SCOPE ,
116+         context = None ,
107117    ):
108118        if  not  scope :
109119            scope  =  FULL_SYSTEM_SCOPE 
@@ -116,6 +126,18 @@ def __init__(
116126        self ._value_cache  =  cache  or  {}
117127        self ._scope  =  scope 
118128
129+         self ._context  =  context  if  context  else  dict ()
130+         self ._user  =  (
131+             context ["user" ]
132+             if  context  and  "user"  in  context  and  context ["user" ]
133+             else  cfg .CONF .system_user .user 
134+         )
135+         self ._user  =  (
136+             context ["api_user" ]
137+             if  context  and  "api_user"  in  context  and  context ["api_user" ]
138+             else  self ._user 
139+         )
140+ 
119141    def  __str__ (self ):
120142        return  self ._value_cache [self ._key_prefix ]
121143
@@ -154,6 +176,7 @@ def _get(self, name):
154176            key_prefix = key ,
155177            cache = self ._value_cache ,
156178            scope = self ._scope ,
179+             context = self ._context ,
157180        )
158181
159182    def  _get_kv (self , key ):
@@ -167,6 +190,19 @@ def _get_kv(self, key):
167190
168191        if  kvp :
169192            LOG .debug ("Got value %s from datastore." , kvp .value )
193+ 
194+         # Check that user has permission to the key value pair. 
195+         # If RBAC is enabled, this check will verify if user has system role with all access. 
196+         # If RBAC is enabled, this check guards against a user accessing another user's kvp. 
197+         # If RBAC is enabled, user needs to be explicitly granted permission to view a system kvp. 
198+         # The check is sufficient to allow decryption of the system kvp. 
199+         rbac_utils  =  get_rbac_backend ().get_utils_class ()
200+         rbac_utils .assert_user_has_resource_db_permission (
201+             user_db = UserDB (name = self ._user ),
202+             resource_db = kvp ,
203+             permission_type = PermissionType .KEY_VALUE_PAIR_VIEW ,
204+         )
205+ 
170206        return  kvp .value  if  kvp  else  "" 
171207
172208
@@ -175,7 +211,13 @@ class UserKeyValueLookup(BaseKeyValueLookup):
175211    scope  =  USER_SCOPE 
176212
177213    def  __init__ (
178-         self , user , prefix = None , key_prefix = None , cache = None , scope = FULL_USER_SCOPE 
214+         self ,
215+         user ,
216+         prefix = None ,
217+         key_prefix = None ,
218+         cache = None ,
219+         scope = FULL_USER_SCOPE ,
220+         context = None ,
179221    ):
180222        if  not  scope :
181223            scope  =  FULL_USER_SCOPE 
@@ -188,6 +230,7 @@ def __init__(
188230        self ._value_cache  =  cache  or  {}
189231        self ._user  =  user 
190232        self ._scope  =  scope 
233+         self ._context  =  context  if  context  else  dict ()
191234
192235    def  __str__ (self ):
193236        return  self ._value_cache [self ._key_prefix ]
0 commit comments