1+ require 'oj'
2+
13module VCAP ::CloudController
24 class SyslogDrainUrlsInternalController < RestController ::BaseController
35 # Endpoint uses mutual tls for auth, handled by nginx
@@ -55,32 +57,35 @@ def listv5
5557 join ( :apps , guid : :app_guid ) .
5658 join ( :spaces , guid : :apps__space_guid ) .
5759 join ( :organizations , id : :spaces__organization_id ) .
60+ join ( :service_instances , guid : :service_bindings__service_instance_guid ) .
5861 select (
5962 :service_bindings__syslog_drain_url ,
6063 :service_bindings__credentials ,
6164 :service_bindings__salt ,
6265 :service_bindings__encryption_key_label ,
6366 :service_bindings__encryption_iterations ,
6467 :service_bindings__app_guid ,
68+ :service_bindings__service_instance_guid ,
6569 :apps__name___app_name ,
6670 :spaces__name___space_name ,
67- :organizations__name___organization_name
71+ :organizations__name___organization_name ,
72+ :service_instances__is_gateway_service___is_managed_service
6873 ) .
6974 where ( service_bindings__syslog_drain_url : syslog_drain_urls_query ) .
7075
7176 each_with_object ( { } ) do |item , injected |
7277 syslog_drain_url = item [ :syslog_drain_url ]
73- credentials = item . credentials
74- cert = credentials &.fetch ( 'cert' , '' ) || ''
75- key = credentials &.fetch ( 'key' , '' ) || ''
76- ca = credentials &.fetch ( 'ca' , '' ) || ''
78+
7779 hostname = hostname_from_app_name ( item [ :organization_name ] , item [ :space_name ] , item [ :app_name ] )
7880 app_guid = item [ :app_guid ]
7981
82+ cert , key , ca = fetch_credentials_from_cache ( item )
83+
8084 injected_item = injected [ syslog_drain_url ] ||= {
8185 url : syslog_drain_url ,
8286 binding_data_map : { }
8387 }
88+
8489 cert_item = injected_item [ :binding_data_map ] [ [ key , cert , ca ] ] ||= {
8590 cert : cert ,
8691 key : key ,
@@ -99,11 +104,45 @@ def listv5
99104
100105 next_page_token = nil
101106 next_page_token = last_id + batch_size unless bindings . empty?
102- [ HTTP ::OK , MultiJson . dump ( { results : bindings , next_id : next_page_token } , pretty : true ) ]
107+ [ HTTP ::OK , Oj . dump ( { results : bindings , next_id : next_page_token } ) ]
103108 end
104109
105110 private
106111
112+ def upsi_service_instance_credential_cache
113+ @upsi_service_instance_credential_cache ||= { }
114+ end
115+
116+ # Service Binding credentials are stored as encrypted values in CCDB.
117+ # Decrypting them is computationally expensive and has caused performance
118+ # issues since this endpoint may decrypt credentials from thousands of service bindings.
119+ #
120+ # Since all user-provided service instance bindings share the same credentials
121+ # as their service instance we can safely cache the for a given service instance guid.
122+ def fetch_credentials_from_cache ( item )
123+ if item [ :is_managed_service ]
124+ credentials = item . credentials
125+ cert = credentials &.fetch ( 'cert' , '' ) || ''
126+ key = credentials &.fetch ( 'key' , '' ) || ''
127+ ca = credentials &.fetch ( 'ca' , '' ) || ''
128+ else # service is user-provided
129+ upsi_service_instance_credential_cache [ item . service_instance_guid ] ||= { }
130+
131+ if upsi_service_instance_credential_cache [ item . service_instance_guid ] . empty?
132+ credentials = item . credentials
133+ upsi_service_instance_credential_cache [ item . service_instance_guid ] [ 'cert' ] = credentials &.fetch ( 'cert' , '' ) || ''
134+ upsi_service_instance_credential_cache [ item . service_instance_guid ] [ 'key' ] = credentials &.fetch ( 'key' , '' ) || ''
135+ upsi_service_instance_credential_cache [ item . service_instance_guid ] [ 'ca' ] = credentials &.fetch ( 'ca' , '' ) || ''
136+ end
137+
138+ cert = upsi_service_instance_credential_cache [ item . service_instance_guid ] . fetch ( 'cert' , '' )
139+ key = upsi_service_instance_credential_cache [ item . service_instance_guid ] . fetch ( 'key' , '' )
140+ ca = upsi_service_instance_credential_cache [ item . service_instance_guid ] . fetch ( 'ca' , '' )
141+ end
142+
143+ [ cert , key , ca ]
144+ end
145+
107146 def syslog_drain_urls_query
108147 ServiceBinding .
109148 distinct .
0 commit comments