Created
January 9, 2024 23:50
Revisions
-
tcaddy created this gist
Jan 9, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,3 @@ source "https://rubygems.org" gem "functions_framework", "~> 1.4" This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,21 @@ GEM remote: https://rubygems.org/ specs: cloud_events (0.7.1) functions_framework (1.4.1) cloud_events (>= 0.7.0, < 2.a) puma (>= 4.3.0, < 7.a) rack (>= 2.1, < 4.a) nio4r (2.5.9) puma (6.4.0) nio4r (~> 2.0) rack (3.0.8) PLATFORMS ruby DEPENDENCIES functions_framework (~> 1.4) BUNDLED WITH 2.4.10 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ This is a proof-of-concept for validation Webhooks from https://getport.io. This is the source for a GCP Cloud Function for Ruby 3.2. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,93 @@ require 'functions_framework' require 'base64' require 'openssl' FunctionsFramework.http "entrypoint" do |request| # The request parameter is a Rack::Request object. # See https://www.rubydoc.info/gems/rack/Rack/Request WebhookProcessor.new(request: request).call end class WebhookProcessor # See: https://docs.getport.io/create-self-service-experiences/security/ GET_PORT_IP_ADDRESSES = [ '44.221.30.248', '44.193.148.179', '34.197.132.205', '3.251.12.205', ].freeze HEADERS = { get_port: { signature: 'X_PORT_SIGNATURE', timestamp: 'X_PORT_TIMESTAMP' } }.freeze def call return four_zero_four unless valid_signature? process response end private def initialize(request:) @request = request @response = {} end def response # response can be: # * a string # * a Ruby Hash (which will be converted to a JSON-encoded string) # * an instance of `Rack::Response` # * A Rack response array @response end def four_zero_four Rack::Response.new('not authorized', 401) end def process puts "TODO: do stuff here to handle webhook" @response[:msg] = "OK" end def request_originated_from_get_port? (GET_PORT_IP_ADDRESSES & @request.forwarded_for).any? end def expected_signature case when request_originated_from_get_port? then @request.get_header("HTTP_#{HEADERS[:get_port][:signature]}").split(',')[1] else nil end end def computed_signature case when request_originated_from_get_port? then Base64.strict_encode64( OpenSSL::HMAC.digest( 'sha256', ENV['GET_PORT_CLIENT_SECRET'], [ @request.get_header("HTTP_#{HEADERS[:get_port][:timestamp]}"), @request.body.string ].join('.') ) ) else nil end end def valid_signature? case when request_originated_from_get_port? then Rack::Utils.secure_compare(computed_signature, expected_signature) else false end end end