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