Git Product home page Git Product logo

gosmee's Introduction

gosmee - A webhook forwarder/relayer and replayer

gosmee logo

Gosmee is a webhook relayer that can be easily run anywhere. It can act as well as a replayer using the GitHub API for GitHub Hooks.n

Description

Gosmee enables you to relay webhooks from either itself (as a server) or from https://smee.io to your local laptop or an infrastructure that is not accessible from the public internet.

Gosmee makes it easy to expose a service on your local network (such as a web service on localhost) or behind a VPN. This enables a public service, like GitHub, to push webhooks to your local environment.

Here's how it works:

  1. Configure your Webhook to direct events to a https://smee.io/ URL or to a URL where your Gosmee server is publicly listening acting as a relay server.
  2. Use the Gosmee client on your local machine to retrieve these events from the relay server and forward them to your local service.

This setup creates a bridge between the GitHub webhook and your local service on your workstation.

Alternatively, if you prefer not to use a relay server, you can use the GitHub API to replay the webhook deliveries directly.

Diagram

For the people who rather prefer to understand on how it works with a small diagram:

diagram

Blog Post

There is a blog post as well that explains it the background of this project and some of its features: https://blog.chmouel.com/posts/gosmee-webhook-forwarder-relayer

Screenshot

Screenshot

Install

Release

Go to the release page and choose your archive or package for your platform.

Homebrew

brew tap chmouel/gosmee https://github.com/chmouel/gosmee
brew install gosmee
yay -S gosmee-bin

Gosmee client with Docker

docker run ghcr.io/chmouel/gosmee:latest

Gosmee server with Docker

docker run -d -p 3026:3026 --restart always --name example.org ghcr.io/chmouel/gosmee:latest server --port 3026 --address 0.0.0.0 --public-url https://example.org

GO

go install -v github.com/chmouel/gosmee@latest

Git

Checkout the directory and use :

-$ make build
-$ ./bin/gosmee --help

Gosmee is available from nixpkgs.

nix-env -iA gosmee
nix run nixpkgs#gosmee -- --help # your args are here

System Services

System Service example file for macOS and Linux is available in the misc directory.

Kubernetes

You can expose an internal kubernetes deployment or service with gosmee by using this file.

Adjust the SMEE_URL in there to your endpoint and the http://deployment.name.namespace.name:PORT_OF_SERVICE URL is the Kubernetes internal URL of your deployment running on your cluster, for example:

http://service.namespace:8080

Shell completion

Shell completions is available for gosmee:

# BASH
source <(gosmee completion bash)

# ZSH
source <(gosmee completion zsh)

Usage

Client

If you intend to use https://smee.io, you might want to generate your own smee URL by visiting https://smee.io/new.

Once you have it, the basic usage is as follows:

gosmee client https://smee.io/aBcDeF https://localhost:8080

This command will relay all payloads received at the smee URL to a service running on http://localhost:8080.

Another option is to save all the relays as shell script that can be replayed without having to recreate the event:

gosmee client --saveDir /tmp/savedreplay https://smee.io/aBcDeF https://localhost:8080

This command will save the JSON data of new payloads received at your smee URL to /tmp/savedreplay/timestamp.json and create a shell script with cURL options to /tmp/savedreplay/timestamp.sh. You can replay the webhook effortlessly by repeatedly running the shell script.

You can ignore certain events (identified by GitLab/GitHub/Bitbucket) by adding one or more --ignore-event flags.

If you only want to save the payloads but not replay them, you can use --noReplay.

By default, you will have colored emoji output unless you specify --nocolor as an argument.

You can output the logs as json with the --output json which imply --nocolor

Server

With gosmee server you can use your own server rather than https://smee.io as relay. By default gosmee server will bind to localhost on port 3333 which is not very useful. You probably want to expose it to your public IP or behind a proxy with the flags --address and --port.

You really want to secure that endpoint, you can generate some letsencrypt certificate and use the --tls-cert and --tls-key flags to specify them.

There is a lot of other flags you can use to customize the server, you can see them with gosmee server --help.

To use it you go to your URL and a suffix with your random ID. For example:

https://myserverurl/RANDOM_ID

The random ID accepted to the server needs to be 12 characters (and you probably want to be it random).

With /new you can easily generate a random ID, ie:

% curl http://localhost:3333/new
http://localhost:3333/NqybHcEi

Caddy

Caddy is the best way to run gosmee server, you just need this:

https://webhook.mydomain {
    reverse_proxy http://127.0.0.1:3333
}

It will automatically configure a letsencrypt certificate for you

Nginx

Running gosmee server behind nginx may require some configuration to work properly. Here is a proxy_pass location to a locally running gosmee server on port localhost:3333:

    location / {
        proxy_pass         http://127.0.0.1:3333;
        proxy_set_header Connection '';
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
        proxy_read_timeout 372h;
    }

There is maybe some errors appearing some time with nginx with long running connections. Help is welcome to help debug this.

Replay webhook deliveries via the GitHub API

Alternatively if you don't want to use a relay server and use GitHub you can replay the hooks deliveries via the GitHub API. Compared to the relay server method this is more reliable and you don't have to worry about the relay server being down. The downside is that it only works with GitHub and you need to have a GitHub token. The scopes needed are:

  • For repository webhooks, the token must have the read:repo_hook or repo scope
  • For organizations webhooks, you must have the admin:org_hook scope.

It currently only supports replaying webhook installed on Repositories and Organizations but not supporting webhooks events from GitHub apps.

You will need to know the Hook ID of the webhook you want to replay, you can get it with the --hook-id command:

goplay replay --github-token=$GITHUB_TOKEN --list-hooks org/repo

This will list all the hooks for the repository and their ID.

If you want to list the hooks on an organization you can just specify the org name with no slash (same goes for the rest of this documentation, it behaves the same between org and repo):

goplay replay --github-token=$GITHUB_TOKEN --list-hooks org

When you grab the appropriate you can start to listen to the events and replay them on a local server:

goplay replay --github-token=$GITHUB_TOKEN org/repo HOOK_ID http://localhost:8080

This will listen to all new events and replay them on http://localhost:8080.

You can also replay all the events that have been previously received by the hook from a date time. The date is is in UTC and in the format of 2023-12-19T12:31:12 and it will replay all the events from that date to now:

goplay replay --time-since=2023-12-19T09:00:00 --github-token=$GITHUB_TOKEN org/repo HOOK_ID http://localhost:8080

To make it easier to know the date you can use the --list-deliveries command to list all the deliveries and their date:

goplay replay --github-token=$GITHUB_TOKEN --list-deliveries org/repo HOOK_ID

Note

gosmee replay does not support paging yet, and list only the last 100 deliveries. So if you specify a date that is older than the last 100 deliveries it will not work.

When the token gets rate limited, gosmee will be just failing and do not at the moment do anything to recover from this.

Beyond Webhook

gosmee will only works with webhooks, if you want an alternative solution you can try to looks the one you like from this list https://github.com/anderspitman/awesome-tunneling, my favourite would be go-http-tunnel or tailscale.

Thanks

  • Most of the works is done by the go-sse library.
  • Used previously pysmee but it seems that the underlying sse library is broken with chunked transfer.

Copyright

Apache-2.0

Authors

Chmouel Boudjnah

gosmee's People

Contributors

aamosljp avatar basavaraju-g avatar chmouel avatar dependabot[bot] avatar goreleaserbot avatar portante avatar vdemeester avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

gosmee's Issues

Error 400 when forwarding to Jenkins

Hi, I'm using gosmee to pass github webhooks to my jenkins server. I'm facing an HTTP code 400 when the message is passed to Jenkins directly, but when i save the payload and i replay it with the bash script autogenerated with --saveDir it works with HTTP code 200 and Jenkins triggers correctly.

Info:
I'm running gosmee from docker:
docker run -d --net host --name gosmee ghcr.io/chmouel/gosmee:latest client --saveDir /home/gosmee https://hook.pipelinesascode.com/<my_id> http://localhost:8080/github-webhook/
Result of docker logs gosmee:

Starting gosmee version: dev
Forwarding https://hook.pipelinesascode.com/<my_id> to http://localhost:8080/github-webhook/
/home/gosmee/push-20230322T15h49.sh and /home/gosmee/push-20230322T15h49.json has been saved
push event replayed to http://localhost:8080/github-webhook/, status: 400, error: 400 Bad Request

And when i execute /home/gosmee/push-20230322T15h49.sh jenkins is triggered and works fine. I'm doing something wrong?

Thank you,

Seeing 'ERROR no headers found in message' twice per minute when running in client mode

Probably Github is verifying that the webhook actually replies by senidng an empty message or opening/closing the socket.
I doubt it would be the Jenkins server - unless gosmee is polling Jenkins itself and receiving an empty reply?

It might be these are not seen in all situations.
This particular webhook is being used by both a Github Application and general organization wide gthub hook.

These are annoying since there is now a lot of unnecessary errors. Furthermore, ERROR looks really dangerous when in fact nothing has happened.

I can possibly get more debugging information if there is a flag to do that. FYI, I am running gosmee inside docker.

Can you fix this?

Gosmee pod reports such error "No help topic for ..."

Issue

When we deploy gosemee-client as a pod using the deployment definition as documented here: https://pipelinesascode.com/docs/install/installation/#proxy-service-for-pac-controller

k get -n pipelines-as-code deployment/gosmee-client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gosmee-client
  namespace: pipelines-as-code
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: gosmee-client
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: gosmee-client
    spec:
      containers:
      - args:
        - https://smee.io/upi-0.apps.mystone.lab.upshift.rdu2.redhat.com
        - $(SVC)
        env:
        - name: SVC
          value: https://pipelines-as-code-controller-pipelines-as-code.apps.mystone.lab.upshift.rdu2.redhat.com/
        image: ghcr.io/chmouel/gosmee:main
        imagePullPolicy: IfNotPresent
        name: gosmee-client
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

then the log reports

No help topic for 'https://smee.io/upi-0.apps.mystone.lab.upshift.rdu2.redhat.com'

Disabling Certificate verification

Issue

Is it possible to disable the Certificate verification with the client as I got this error ?

gosmee client https://smee.io/upi-0.apps.mystone.lab.upshift.rdu2.redhat.com https://pipelines-as-code-controller-pipelines-as-code.apps.mystone.lab.upshift.rdu2.redhat.com/
⇉ Starting gosmee version: 0.14.2
✓ Forwarding https://smee.io/upi-0.apps.mystone.lab.upshift.rdu2.redhat.com to https://pipelines-as-code-controller-pipelines-as-code.apps.mystone.lab.upshift.rdu2.redhat.com/
ERROR Forwarding Post "https://pipelines-as-code-controller-pipelines-as-code.apps.mystone.lab.upshift.rdu2.redhat.com/": x509: “ingress-operator@1676649058” certificate is not trusted

Note: Such a problem also exists if we run gosmee as a pod on k8s

Suggestion: Add to the log of the events the date

Suggestion

Add to the log of the events the date as currently it is very difficult to verify if the events coming from github can be matched with what the client reports locally (or using a pod).

check_run event replayed to http://pipelines-as-code-controller.pipelines-as-code.svc.cluster.local:8080, status: 200
check_suite event replayed to http://pipelines-as-code-controller.pipelines-as-code.svc.cluster.local:8080, status: 200

Ideally we should report

GithubApp ID or Webhook | Date | EventType | message

Connection reset when using server

OS: Windows 11 23H2
Docker version: Docker version 24.0.7

When running

docker run -p 3333:3333 ghcr.io/chmouel/gosmee:latest server

I'm getting:

Serving for webhooks on http://localhost:3333

But when trying to connect tho this URL I'm getting Connection reset error in browser, and while using curl empty response.
Screenshot 2024-04-03 114138

Are there any necessary steps missing to fully utilize this functionality or there is some bug?

Adding --insecure-skip-tls-verify still fails for client

When using the gosmee client to forward to a local dev process using https with a self-signed certificate, it fails with tls: failed to verify certificate: x509: certificate signed by unknown authority regardless of whether --insecure-skip-tls-verify is set or not.

Example command:

gosmee --insecure-skip-tls-verify client https://smee.io/abc https://localhost:8443/github/webhook

unexpected EOF after 15 minutes

@chmouel

When running gosmee in client mode after about 15 minutes the application crashes with error:

Wed, 10 Apr 2024 07:09:00 UTC INF Starting gosmee version: dev

Wed, 10 Apr 2024 07:09:01 UTC INF 2024-04-10T07.09.04.177 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:09:31 UTC INF 2024-04-10T07.09.04.826 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:10:02 UTC INF 2024-04-10T07.10.04.594 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:10:18 UTC INF 2024-04-10T07.10.04.009 pullrequest event replayed to https://another.example.org, status: 200
Wed, 10 Apr 2024 07:10:22 UTC INF 2024-04-10T07.10.04.294 pullrequest event replayed to https://another.example.org, status: 200
Wed, 10 Apr 2024 07:10:52 UTC INF 2024-04-10T07.10.04.711 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:11:24 UTC INF 2024-04-10T07.11.04.898 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:11:57 UTC INF 2024-04-10T07.11.04.808 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:12:32 UTC INF 2024-04-10T07.12.04.056 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:13:09 UTC INF 2024-04-10T07.13.04.668 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:13:49 UTC INF 2024-04-10T07.13.04.211 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:14:30 UTC INF 2024-04-10T07.14.04.993 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:15:16 UTC INF 2024-04-10T07.15.04.981 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:16:04 UTC INF 2024-04-10T07.16.04.320 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:17:32 UTC INF 2024-04-10T07.17.04.748 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:18:46 UTC INF 2024-04-10T07.18.04.419 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:20:25 UTC INF 2024-04-10T07.20.04.181 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:22:01 UTC INF 2024-04-10T07.22.04.048 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:23:18 UTC INF 2024-04-10T07.23.04.374 Forwarding https://example.org to https://another.example.org
Wed, 10 Apr 2024 07:24:49 UTC INF 2024-04-10T07.24.04.215 Forwarding https://example.org to https://another.example.org
2024/04/10 07:25:19 unexpected EOF

docker ghcr.io/chmouel/gosmee client https://example.org https://another.example.org

no supported Git provider error while testing Pipelines as Code on bitbucket server/cloud

I got below error while testing PAC on bitbucket server/cloud via gosmee. Its detecting the changes bit not triggering the pipeline-run
smee : https://smee.io/yg5wLgX7eIog2V0N

{"severity":"INFO","timestamp":"2022-11-16T06:45:48.806451127Z","logger":"pipelinesascode","caller":"metrics/prometheus_exporter.go:51","message":"Created Prometheus exporter with config: &{pipelinesascode.tekton.dev/controller controller prometheus 5000000000 <nil> false 9090 0.0.0.0}. Start the server for Prometheus exporter.","commit":"d1fe4c5"}
{"severity":"INFO","timestamp":"2022-11-16T06:45:48.806465127Z","logger":"pipelinesascode","caller":"metrics/metrics_worker.go:91","message":"Successfully updated the metrics exporter; old config: <nil>; new config &{pipelinesascode.tekton.dev/controller controller prometheus 5000000000 <nil> false 9090 0.0.0.0}","commit":"d1fe4c5"}
{"severity":"WARNING","timestamp":"2022-11-16T06:45:48.806486686Z","logger":"pipelinesascode","caller":"v2/config.go:185","message":"Tracing configuration is invalid, using the no-op default{error 26 0 empty json tracing config}","commit":"d1fe4c5"}
{"severity":"WARNING","timestamp":"2022-11-16T06:45:48.806500549Z","logger":"pipelinesascode","caller":"v2/config.go:178","message":"Sink timeout configuration is invalid, default to -1 (no timeout)","commit":"d1fe4c5"}
{"severity":"INFO","timestamp":"2022-11-16T06:45:48.806519263Z","logger":"pipelinesascode","caller":"adapter/adapter.go:67","message":"Starting Pipelines as Code version: nightly","commit":"d1fe4c5"}
{"severity":"ERROR","timestamp":"2022-11-16T06:47:39.32011764Z","logger":"pipelinesascode","caller":"adapter/adapter.go:175","message":"got error while processing : no supported Git provider has been detected","commit":"d1fe4c5","stacktrace":"github.com/openshift-pipelines/pipelines-as-code/pkg/adapter.listener.processRes\n\t/go/src/github.com/openshift-pipelines/pipelines-as-code/pkg/adapter/adapter.go:175\ngithub.com/openshift-pipelines/pipelines-as-code/pkg/adapter.listener.detectProvider\n\t/go/src/github.com/openshift-pipelines/pipelines-as-code/pkg/adapter/adapter.go:218\ngithub.com/openshift-pipelines/pipelines-as-code/pkg/adapter.listener.handleEvent.func1\n\t/go/src/github.com/openshift-pipelines/pipelines-as-code/pkg/adapter/adapter.go:136\nnet/http.HandlerFunc.ServeHTTP\n\t/usr/lib/golang/src/net/http/server.go:2047\nnet/http.(*ServeMux).ServeHTTP\n\t/usr/lib/golang/src/net/http/server.go:2425\nnet/http.(*timeoutHandler).ServeHTTP.func1\n\t/usr/lib/golang/src/net/http/server.go:3337"}
{"severity":"WARNING","timestamp":"2022-11-16T06:47:39.355283219Z","logger":"pipelinesascode","caller":"pipelineascode/match.go:33","message":"cannot set status since no token has been set","commit":"d1fe4c5","provider":"bitbucket-server","event-id":"0f6d54a5-354f-4032-943d-57cc17e0f1c9","event-sha":"17be391e3af2a104d0a0226bd72cbe1bdcf3e5bd","event-type":""}

Add possibility to control retry/reconnect settings in the client

Problem:
We are running the gosmee server on Azure App Services, and the Azure Loadbalancer in front serving these applications has a default non-changable connection-timeout of 230 seconds. This means with the SSE setup of gosmee, that we every ~4 minutes get a connection reset by peer on the gosmee client.

Currently it seems like the default is to retry the connection 5 or 4 times before gosmee exists. This in turn causes the container the gosmee client runs in to restart every 20 minutes, and until the container is back up, we can potentially loose events from in our case github.

Feature request:
Make it possible to control the retry settings to avoid the conainer restarts, or in some way handle these connection resets from Azure App service without exiting the gosmee binary.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.