appengine-ruby icon indicating copy to clipboard operation
appengine-ruby copied to clipboard

Cannot execute remote tasks when Identity Aware Proxy is on

Open leandrogoe opened this issue 5 years ago • 0 comments

Currently there is no way to execute remote tasks when the identity aware proxy is on. The task will simply fail when trying to poll the status over the newly deployed app engine version.

As a workaround, I've monkey patched the code in order to be able to supply a service account key file and a client id:

class AppEngine::Exec

  # PATCH - Memoize authorizer that will be used when polling the status
  def authorizer
    authorizer ||= begin
      key_path = ENV['GAE_SERVICE_ACCOUNT_KEY_PATH']
      client_id = ENV['GAE_IAM_CLIENT_ID']

      if client && key_path
        puts "Using IAM authorizer with GAE_SERVICE_ACCOUNT_KEY_PATH: #{key_path} and GAE_IAM_CLIENT_ID: #{client_id}"
        Google::Auth::ServiceAccountCredentials.make_creds(
          json_key_io: File.open(key_path),
          target_audience: client_id
        )
      end
    end
  end

  def track_status temp_version, secret
    host = "#{temp_version}.#{@service}.#{@project}.appspot.com"
    ::Net::HTTP.start host do |http|
      outpos = errpos = 0
      delay = 0.0
      loop do
        sleep delay
        uri = URI("http://#{host}/#{secret}")
        uri.query = ::URI.encode_www_form outpos: outpos, errpos: errpos

        # BEGIN PATCH - Adding authorizer while polling the status
        req = Net::HTTP::Get.new(uri)
        authorizer&.apply!(req)
        response = http.request(req)
        # END PATCH - Adding authorizer while polling the status

        data = ::JSON.parse response.body
        data["outlines"].each { |line| puts "[STDOUT] #{line}" }
        data["errlines"].each { |line| puts "[STDERR] #{line}" }
        outpos = data["outpos"]
        errpos = data["errpos"]
        return data["status"] if data["status"]
        if data["time"] > @timeout_seconds

          # BEGIN PATCH - Adding authorizer while polling the status
          req = Net::HTTP::Post.new("/#{secret}/kill")
          authorizer&.apply!(req)
          http.request(req)
          # END PATCH - Adding authorizer while polling the status

          return "timeout"
        end
        if data["outlines"].empty? && data["errlines"].empty?
          delay += 0.1
          delay = 1.0 if delay > 1.0
        else
          delay = 0.0
        end
      end
    end
  end
end

leandrogoe avatar Dec 29 '20 21:12 leandrogoe