Module: Legion::Extensions::Github::App::Runners::Webhooks
- Includes:
- Helpers::Client, Helpers::Lex
- Included in:
- Client
- Defined in:
- lib/legion/extensions/github/app/runners/webhooks.rb
Constant Summary collapse
- SCOPE_INVALIDATION_EVENTS =
%w[installation installation_repositories].freeze
Constants included from Helpers::Client
Helpers::Client::CREDENTIAL_RESOLVERS
Constants included from Helpers::TokenCache
Helpers::TokenCache::TOKEN_BUFFER_SECONDS
Instance Method Summary collapse
- #invalidate_all_scopes_for_owner(owner:) ⇒ Object
- #invalidate_scopes_for_event(event_type:, payload:) ⇒ Object
- #parse_event(payload:, event_type:, delivery_id:) ⇒ Object
- #receive_event(payload:, signature:, secret:, event_type:, delivery_id:) ⇒ Object
- #verify_signature(payload:, signature:, secret:) ⇒ Object
Methods included from Helpers::Client
#connection, #gh_cli_token_output, #max_fallback_retries, #on_rate_limit, #on_scope_authorized, #on_scope_denied, #resolve_broker_app, #resolve_credential, #resolve_env, #resolve_gh_cli, #resolve_next_credential, #resolve_settings_app, #resolve_settings_delegated, #resolve_settings_pat, #resolve_vault_app, #resolve_vault_delegated, #resolve_vault_pat
Methods included from Helpers::ScopeRegistry
#credential_fingerprint, #invalidate_scope, #mark_rate_limited, #rate_limited?, #register_scope, #scope_status
Methods included from Helpers::TokenCache
#fetch_token, #mark_rate_limited, #rate_limited?, #store_token
Instance Method Details
#invalidate_all_scopes_for_owner(owner:) ⇒ Object
54 55 56 57 58 59 |
# File 'lib/legion/extensions/github/app/runners/webhooks.rb', line 54 def invalidate_all_scopes_for_owner(owner:) known_fingerprints = resolve_known_fingerprints known_fingerprints.each do |fp| invalidate_scope(fingerprint: fp, owner: owner) end end |
#invalidate_scopes_for_event(event_type:, payload:) ⇒ Object
45 46 47 48 49 50 51 52 |
# File 'lib/legion/extensions/github/app/runners/webhooks.rb', line 45 def invalidate_scopes_for_event(event_type:, payload:, **) return unless SCOPE_INVALIDATION_EVENTS.include?(event_type.to_s) owner = payload&.dig('installation', 'account', 'login') return unless owner invalidate_all_scopes_for_owner(owner: owner) end |
#parse_event(payload:, event_type:, delivery_id:) ⇒ Object
26 27 28 29 |
# File 'lib/legion/extensions/github/app/runners/webhooks.rb', line 26 def parse_event(payload:, event_type:, delivery_id:, **) parsed = payload.is_a?(String) ? ::JSON.parse(payload) : payload { result: { event_type: event_type, delivery_id: delivery_id, payload: parsed } } end |
#receive_event(payload:, signature:, secret:, event_type:, delivery_id:) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/legion/extensions/github/app/runners/webhooks.rb', line 31 def receive_event(payload:, signature:, secret:, event_type:, delivery_id:, **) verified = verify_signature(payload: payload, signature: signature, secret: secret)[:result] unless verified return { result: { verified: false, event_type: event_type, delivery_id: delivery_id, payload: nil } } end parsed = parse_event(payload: payload, event_type: event_type, delivery_id: delivery_id)[:result] invalidate_scopes_for_event(event_type: event_type, payload: parsed[:payload]) { result: parsed.merge(verified: true) } end |
#verify_signature(payload:, signature:, secret:) ⇒ Object
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/legion/extensions/github/app/runners/webhooks.rb', line 15 def verify_signature(payload:, signature:, secret:, **) return { result: false } if signature.nil? || signature.empty? expected = "sha256=#{OpenSSL::HMAC.hexdigest('SHA256', secret, payload)}" # Use constant-time comparison to prevent timing side-channel attacks. # Pad to equal length so fixed_length_secure_compare can be used safely. result = expected.length == signature.length && OpenSSL.fixed_length_secure_compare(expected, signature) { result: result } end |