2626import time
2727import typing
2828
29+ from kmip .core import enums as kmip_enums # type: ignore[import]
2930from kmip .pie .client import ProxyKmipClient # type: ignore[import]
30- from kmip .pie .client import enums as kmip_enums
31+ from kmip .pie .exceptions import KmipOperationFailure # type: ignore[import]
3132
32- from sambacc .varlink .keybridge import EntryKind , ScopeInfo
33+ from sambacc .varlink .keybridge import (
34+ EntryKind ,
35+ EntryNotFoundError ,
36+ OpKind ,
37+ OperationFailed ,
38+ ScopeInfo ,
39+ )
3340
3441
3542_logger = logging .getLogger (__name__ )
@@ -142,6 +149,44 @@ def _prune(self) -> None:
142149 len (self ._kmip_cache ),
143150 )
144151
152+ @contextlib .contextmanager
153+ def _handle_kmip_error (
154+ self , op : OpKind , key : str
155+ ) -> typing .Iterator [None ]:
156+ """Catch exceptions from KMIP libs and turn them into something
157+ more reasonable for a keybridge client.
158+ """
159+ try :
160+ yield
161+ except OSError as err :
162+ _logger .warning ("KMIP connection failed: %s" , err )
163+ raise OperationFailed (
164+ op = op .value ,
165+ name = key ,
166+ scope = self .name (),
167+ status = "KMIP_CONNECTION_FAILED" ,
168+ reason = str (err ),
169+ )
170+ except KmipOperationFailure as kmip_err :
171+ _logger .debug ("KMIP operation failure: %s" , kmip_err )
172+ reason = getattr (kmip_err , "reason" , None )
173+ if (
174+ reason is kmip_enums .ResultReason .ITEM_NOT_FOUND
175+ or reason is kmip_enums .ResultReason .PERMISSION_DENIED
176+ ):
177+ raise EntryNotFoundError (
178+ name = key ,
179+ scope = self .name (),
180+ ) from kmip_err
181+ _logger .warning ("unexpected KMIP operation failure: %s" , kmip_err )
182+ raise OperationFailed (
183+ op = op .value ,
184+ name = key ,
185+ scope = self .name (),
186+ status = "KMIP_OPERATION_FAILED" ,
187+ reason = str (kmip_err ),
188+ ) from kmip_err
189+
145190 def get (self , key : str , kind : EntryKind ) -> str :
146191 """Get a value associated with the given key from the KMIP server or
147192 cache. If entry kind is B64 the (typically) binary data will be base64
@@ -153,9 +198,9 @@ def get(self, key: str, kind: EntryKind) -> str:
153198 if key in cache :
154199 _logger .debug ("KMIP cache hit: %r" , key )
155200 return _format (cache [key ].value , kind )
156-
157- with self ._client () as client :
158- result = client .get (key )
201+ with self . _handle_kmip_error ( OpKind . GET , key ):
202+ with self ._client () as client :
203+ result = client .get (key )
159204 _logger .debug ("KMIP result for: %r" , key )
160205 with self ._cache () as cache :
161206 cache [key ] = _Value (result .value , created = self ._timestamp ())
0 commit comments