secrets-manager icon indicating copy to clipboard operation
secrets-manager copied to clipboard

python - KSMCache doesn't use cache on server HTTP errors

Open barnesda opened this issue 9 months ago • 1 comments

My org uses Keeper Secrets in python, configured to use the KSMCache for added resiliency. This works great when there's momentary connection issues, but more recently we've occasionally had chunks of time where a connection is established but we get errors back from the server:

image

image

HTTP500 An unexpected server error occurred (unable to validate app client: XXXXXXXXXXXXXXX). Please reboot your device and if the issue persists, contact your Keeper Support Team. HTTP503 Service Unavailable: Back-end server is at capacity

I'd expect for these to fall back to the checking the cache, but instead it was raising an error which was causing scheduled production scripts to fail. As a workaround, we made a new function to wrap KSMCache.caching_post_function, and we use that as the custom_post_function after setting up our cache instead. So far (about a month), it seems to be working with no production issues since.

def improved_caching_post_function(  # type: ignore  
    url, transmission_key, encrypted_payload_and_signature, verify_ssl_certs=True  
):  
    """Wrapper for KSMCache's ``caching_post_function`` to handle HTTP errors while fetching secrets.  
  
    KSMCache uses the cache if there's no connection at all, but raises for HTTP errors with isn't ideal.    
    """    
    ksm_rs = KSMCache.caching_post_function(  
        url, transmission_key, encrypted_payload_and_signature, verify_ssl_certs  
    )  
  
    if ksm_rs.status_code < 400:
        return ksm_rs
  
    # Try to log any error info we got back.  
    # Very loosely based on KSM's SecretsManager.handler_http_error()  
    info = {  
        "status_code": ksm_rs.status_code,  
        "reason": ksm_rs.http_response.reason,  
    }  
    try:  
        info["body"] = ksm_rs.http_response.json()  
    except JSONDecodeError:  
        info["body"] = ksm_rs.http_response.text  
  
    info = {k: v for k, v in info.items() if v not in (None, "")}  
    logger.warning("Handling KSM Error", **info)  
  
    # Cache access, code copied from KSMCache.caching_post_function()  
    cached_data = KSMCache.get_cached_data()  
    cached_transmission_key = cached_data[:32]  
    transmission_key.key = cached_transmission_key  
    data = cached_data[32 : len(cached_data)]  
  
    new_rs = KSMHttpResponse(HTTPStatus.OK, data, None)  
    return new_rs

barnesda avatar May 09 '24 21:05 barnesda

Great information! The original cache function that we have developed was more like an example for the developers to use as a template to develop their own catching mechanism.

I'll also talk to the team to see if we should update our default caching function using your work around.

Thank you,

Max

maksimu avatar May 09 '24 21:05 maksimu

The original cache function that we have developed was more like an example for the developers to use as a template to develop their own catching mechanism.

"Keeper Secrets Manager benefits from the existing Keeper platform architecture in addition to an optional offline caching mechanism in all Secrets Manager SDK endpoints."

talk to the team

results?

our default caching function

The optional one mentioned in the link above? Where can i find information about that in product papers? What are the use cases of this default implementation? Is there a detailed explanation how to use it for mixed use cases ksm cli ( for ansible-vault key/password files ) and keeper_ansible ( for ansible playbooks) ?

flybyray avatar Oct 21 '24 07:10 flybyray