Skip to content

Commit

Permalink
fix: cache bug (#1885)
Browse files Browse the repository at this point in the history
## Description:
When I introduced the cache I didn't recognize that once the primary
user logs in it caches the instance config for _any other_ user to
re-use. With this we are scoping the api key and instance config to the
jwt token and removing failed login attempts.

## Is this change user facing?
YES

## References (if applicable):
<!-- Add relevant Github Issues, Discord threads, or other helpful
information. -->
  • Loading branch information
adschwartz authored Dec 1, 2023
1 parent 64084d8 commit 82e46e2
Showing 1 changed file with 20 additions and 14 deletions.
34 changes: 20 additions & 14 deletions enclave-manager/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ type WebServer struct {
engineServiceClient *kurtosis_engine_rpc_api_bindingsconnect.EngineServiceClient
enforceAuth bool
instanceConfig *kurtosis_backend_server_rpc_api_bindings.GetCloudInstanceConfigResponse
apiKey *string
instanceConfigMap map[string]*kurtosis_backend_server_rpc_api_bindings.GetCloudInstanceConfigResponse
apiKeyMap map[string]*string
}

func NewWebserver(enforceAuth bool) (*WebServer, error) {
Expand All @@ -57,6 +58,8 @@ func NewWebserver(enforceAuth bool) (*WebServer, error) {
enforceAuth: enforceAuth,
instanceConfigMutex: &sync.RWMutex{},
apiKeyMutex: &sync.RWMutex{},
apiKeyMap: map[string]*string{},
instanceConfigMap: map[string]*kurtosis_backend_server_rpc_api_bindings.GetCloudInstanceConfigResponse{},
}, nil
}

Expand Down Expand Up @@ -92,7 +95,7 @@ func (c *WebServer) ValidateRequestAuthorization(
return false, stacktrace.NewError("An internal error has occurred. An empty API key was found")
}

instanceConfig, err := c.GetCloudInstanceConfig(ctx, auth.ApiKey)
instanceConfig, err := c.GetCloudInstanceConfig(ctx, reqToken, auth.ApiKey)
if err != nil {
return false, stacktrace.Propagate(err, "Failed to retrieve the instance config")
}
Expand All @@ -103,7 +106,9 @@ func (c *WebServer) ValidateRequestAuthorization(
}
reqHost = splitHost[0]
if instanceConfig.LaunchResult.PublicDns != reqHost {
return false, stacktrace.NewError("Instance config public dns '%s' does not match the request host '%s'", instanceConfig.LaunchResult.PublicDns, reqHost)
delete(c.apiKeyMap, reqToken)
delete(c.instanceConfigMap, reqToken)
return false, stacktrace.NewError("either the requested instance does not exist or the user is not authorized to access the resource")
}

return true, nil
Expand Down Expand Up @@ -413,11 +418,12 @@ func (c *WebServer) createKurtosisCloudBackendClient(

func (c *WebServer) GetCloudInstanceConfig(
ctx context.Context,
jwtToken string,
apiKey string,
) (*kurtosis_backend_server_rpc_api_bindings.GetCloudInstanceConfigResponse, error) {
// Check if we have already fetched the instance config, if so return the cache
if c.instanceConfig != nil {
return c.instanceConfig, nil
if c.instanceConfigMap[jwtToken] != nil {
return c.instanceConfigMap[jwtToken], nil
}

// We have not yet fetched the instance configuration, so we write lock, make the external call and cache the result
Expand Down Expand Up @@ -452,7 +458,7 @@ func (c *WebServer) GetCloudInstanceConfig(
return nil, stacktrace.Propagate(err, "Failed to get the instance config")
}

c.instanceConfig = getInstanceConfigResponse.Msg
c.instanceConfigMap[jwtToken] = getInstanceConfigResponse.Msg

return getInstanceConfigResponse.Msg, nil
}
Expand All @@ -468,21 +474,21 @@ func (c *WebServer) ConvertJwtTokenToApiKey(
if err != nil {
return nil, stacktrace.Propagate(err, "Failed to create the Cloud backend client")
}
request := &connect.Request[kurtosis_backend_server_rpc_api_bindings.GetOrCreateApiKeyRequest]{
Msg: &kurtosis_backend_server_rpc_api_bindings.GetOrCreateApiKeyRequest{
AccessToken: jwtToken,
},
}

if c.apiKey != nil {
if c.apiKeyMap[jwtToken] != nil {
return &Authentication{
ApiKey: *c.apiKey,
ApiKey: *c.apiKeyMap[jwtToken],
JwtToken: jwtToken,
}, nil
} else {
c.apiKeyMutex.Lock()
defer c.apiKeyMutex.Unlock()

request := &connect.Request[kurtosis_backend_server_rpc_api_bindings.GetOrCreateApiKeyRequest]{
Msg: &kurtosis_backend_server_rpc_api_bindings.GetOrCreateApiKeyRequest{
AccessToken: jwtToken,
},
}
result, err := (*client).GetOrCreateApiKey(ctx, request)
if err != nil {
return nil, stacktrace.Propagate(err, "Failed to get the API key")
Expand All @@ -494,7 +500,7 @@ func (c *WebServer) ConvertJwtTokenToApiKey(
}

if len(result.Msg.ApiKey) > 0 {
c.apiKey = &result.Msg.ApiKey
c.apiKeyMap[jwtToken] = &result.Msg.ApiKey
return &Authentication{
ApiKey: result.Msg.ApiKey,
JwtToken: jwtToken,
Expand Down

0 comments on commit 82e46e2

Please sign in to comment.