6

Introducing ngrok-go: Ingress network straight from your app

 1 year ago
source link: https://blog.ngrok.com/posts/announcing-ngrok-go
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Introducing ngrok-go: Ingress network straight from your app

January 10, 2023
Cover Image for Introducing ngrok-go: Ingress network straight from your app

Today, we're excited to announce the General Availability of ngrok-go, our open-source and idiomatic package for embedding ngrok networking directly into Go apps.

ngrok-go allows developers to define network tunnels within their application source code and get secure ingress regardless of where their apps run. It reduces network complexity while improving application scalability and operations, saving developers time.

This post explains how ngrok-go works, how it compares to traditional networking and tunnels, and how to start using it in your apps.

We spend too much time provisioning networking

As an industry, we build and distribute more apps and APIs than ever. Much of this increase is due to advancements in programming languages, frameworks, how developers consume supporting services like infrastructure, auth, and monitoring as code, and how many more problems software is solving.

However, developers are still using the ‘assembly language’ of networking:

  • Ingress is environment specific — Each environment where the app is deployed — public and private clouds, on-premises, customers' networks — introduces network particularities, requiring bespoke configuration.
  • Networks are subject to changes — New ports, firewall rules, nodes, changes in DNS and certificates all introduce change in what was working previously.
  • Reliable access requires perfect coordination — To enable ingress to their apps, developers, IT, and security need to tape together chains of network proxies, firewalls, routing, gateways, middleware, and port forwarding configurations and execute perfectly every time for every change.
network_ingress_is_hard.png

Declarative network with ngrok-go

To overcome these challenges, ngrok began with creating an instant, secured ingress to development environments. Now, we’re bringing that same simplicity to your production apps and APIs.

With ngrok-go, developers declare the network ingress they want within their apps:

l, err := ngrok.StartTunnel(ctx, 
	config.HTTPEndpoint(
		config.WithDomain("www.my-awesome-app.com"),
		config.WithOAuth("google" ),
		config.WithAllowOAuthDomain("example.com"),
		config.WithAllowCIDRString("10.0.0.0/16"),
		config.WithWebhookVerification("twilio",webhookSecret),
		config.WithCircuitBreaker(0.8),
		config.WithCompression(),
		config.WithMutualTLSCA(x509Cert),
	), 
)

The access is delivered by the ngrok edge anywhere the app runs to:

  • Reduce additional network setup and coordination
  • Keep the contract between the network ingress and app in sync, reducing the risk of unavailability by network changes
  • Decouple the application ingress from the environment it runs in, making it portable

ngrok-go also works together with your current network stack. For example, you can use ngrok-go with your SIEM for observability and monitoring to meet your security requirements.

Ultimately, ngrok-go empowers developers to build, removing network pain without compromising on security.

ngrok-go in action: Getting ingress access in 6 lines

Tip: This tutorial assumes you have Go already installed.

Let's start by showing how ngrok-go is an easy drop-in to any existing go app. In this step, we will get a hello world app (using net.Listener), and replace that with an ngrok ingress:

  1. Launch a terminal and create a go app and file:

    mkdir hello-world
    cd hello-world
    go mod init hello-world
    touch main.go
    
  2. Edit the main.go file and add the hello world code — this code imports the net library (lines 3-9) to expose your app on localhost:8080 (line 12):

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "net"
        "net/http"
    )
    
    func run(ctx context.Context) error {
        l, err := net.Listen("tcp", ":8080")
        if err != nil {
            return err
        }
        fmt.Println("Listening at ", l.Addr())
        return http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, "Hello World!")
        }))
    }
    
    func main() {
        if err := run(context.Background()); err != nil {
            log.Fatal(err)
        }
    }
    
  3. Run the app

    run go main.go
    
  4. Your app is available on http://localhost:8080

With net, you're able to control which localhost port you want to show your app, but you cannot share that with the world. Let's drop in ngrok-go and change that:

  1. Sign up for a free ngrok account.

  2. In the ngrok Dashboard, copy your Authtoken

  3. Back to the terminal (in the hello-world folder), add the ngrok-go library:

    go get golang.ngrok.com/ngrok
    
  4. Update your main.go code to use ngrok-go — this code replaces net with ngrok libraries (lines 3-11) and changes from the net listen function (on 8080) to ngrok.Listen (lines 14-17). Listen will expose a HTTP endpoint using an ngrok token informed via environment variable:

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "net/http"
    
        "golang.ngrok.com/ngrok"
        "golang.ngrok.com/ngrok/config"
    )
    
    func run(ctx context.Context) error {
        l, err := ngrok.Listen(ctx, 
            config.HTTPEndpoint(),
            ngrok.WithAuthtokenFromEnv(),
        )
        if err != nil {
            return err
        }
        fmt.Println("Listening at ", l.Addr())
        return http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, "Hello World!")
        }))
    }
    
    func main() {
        if err := run(context.Background()); err != nil {
            log.Fatal(err)
        }
    }
    
  5. Run the app, replacing TOKEN with the authtoken you copied on step 2:

    | Tip: You can copy your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken

    NGROK_AUTHTOKEN="TOKEN" run go main.go
    
  6. Copy the address from the terminal (for example https://myapp.ngrok.io) and paste into your browser. Your app has a public ingress!

Adding OAuth security with one line

The ngrok-go library supports all of ngrok’s features, including OAuth. To add Google authentication to your app:

  1. On main.go, update config.HTTPEndpoint() with additional configs to add OAuth authentication with Google:

    l, err := ngrok.StartTunnel(ctx, 
        config.HTTPEndpoint(
            config.WithOAuth("google"),
        ),
        ngrok.WithAuthtokenFromEnv(),
    )
    
  2. Save main.go and repeat the same command replacing TOKEN to run the app:

    NGROK_AUTHTOKEN="TOKEN" run go main.go
    
  3. You should be able to access your app with OAuth from Google:

    ngrok-go-in-action.gif
  4. Optionally, change the Oauth provider from Google to other OAuth providers such as "github", "microsoft", or "twitch".

    Tip: ngrok-go also supports ngrok paid features — such as load balancing, circuit breaking, webhook validation. These features are accessible by the config function:

    ngrok-go-functions.png

    Examples:

    • To use a custom subdomain (i.e. my-awesome-app.ngrok-io), simply add config.WithDomain("my-awesome-app.ngrok.io"). ngrok also supports custom domains (such as www.my-awesome-app.com)
    • To restricting OAuth only for specific user emails or domains (config.WithAllowOAuthDomain())
    • To enable webhook validation, use config.WithWebhookVerification()
    • To restrict access to IPs, use config.WithAllowCIDR())

Using Edge configurations (without changing code!)

Note: to run this section, you need a ngrok Pro account. Reach us in our ngrok slack community for a free month of Pro to test ngrok-go.

ngrok-go works seamlessly with the ngrok Cloud Edge configurations. Using k8s-style label matching, you can change ingress configurations to your production apps in real-time and without restarting processes, changing, or redistributing your app.

Let's do this by moving all our configuration to the edge:

  1. Visit the ngrok Dashboard

  2. Click to expand Cloud Edge and then click New Edge

  3. Select HTTPS Edge and click Create HTTPS Edge

  4. Click OAuth and then Begin Setup.

  5. Select Google as Identity Provider and click Save

  6. Click Manage Endpoints and then click Attach Endpoints.

  7. Click New Domain

  8. Enter a domain for your app (i.e. my-awesome-go-app.ngrok.io) and follow the steps to complete the setup.

  9. Click Save.

  10. Under Overview, copy the edge label under Backend. It will be a long string starting with edghts

Now, let's change our code to use our label:

  1. On main.go, replace config.HTTPEndpoint() with config.LabelTunnel() :

    l, err := ngrok.Listen(ctx, 
        config.LabeledTunnel(
            config.WithLabel("edge","edghts_2INPeoAIS9Ki98EN4MX47ZKcMJFk"),
        ), 
        ngrok.WithAuthtokenFromEnv(),
    )
    
  2. Save main.go and repeat the same command replacing TOKEN to run the app:

    NGROK_AUTHTOKEN="TOKEN" run go main.go
    
  3. You should be able to get the same behavior as before, but now the config lives in the edge:

    ngrok-go-in-action.gif

Changing config in real-time:

  1. Return to your edge in the ngrok dashboard.

  2. Under OAuth, change the provider from Google to Github and click save.

  3. Return to the browser where your app is running and refresh the page.

Now you need to log in with a different provider.

(Bonus) Load balancing with ngrok-go & Cloud Edge

  1. Launch a new terminal, navigate to your app folder and copy main.go to a different file:

    cd hello-world
    go mod init hello-world
    cp main.go main-2.go
    
  2. Edit main-2.go and change the hello world message to hello word 2:

    fmt.Fprintln(w, "Hello World 2!")
    
  3. Save main.go and repeat the same command replacing TOKEN to run the app:

    NGROK_AUTHTOKEN="TOKEN" run go main-2.go
    
  4. Back to the ngrok dashboard, visit the overview page of your edge and click refresh. You will see the message:

    load_balancing.png
  5. Return to your app and make multiple calls. You should see the hello world messaging rotating, showing the load balancing distribution.

Conclusion

ngrok-go adds secure network ingress into apps as a native go library, allowing developers to define networking straight from their source code, and get secure ingress regardless of where their apps run.

ngrok-go reduces network setup and coordination, reduces the risk of downtime due to network changes, and decouples the application ingress from the network environment, making apps network portable without compromising on security.

Ultimately, ngrok-go empowers developers to build, removing network pain without compromising on security.

The ngrok-go library is generally available today on our free and paid plans. To get started, sign up for ngrok. If you have notes and questions or want to test some of the features available in paid plans, please reach us in our ngrok slack community.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK