# README
go-http
This project provides examples of how to use different mechanisms within the GoLang HTTP standard libraries to intercept network socket creation to route HTTP client and server traffic over alternative networks.
Specifically, the OpenZiti overlay network GoLang SDK is used to create net.Conn
implementations that can be used innet.Listener
use cases (servers) and http.Client
.
Why?
Taking over socket level connections make it easy to integrate alternative networking into GoLang based applications. This enables OSI level 3 API Security for software developers. Normally layer 3 concerns are delegated to network engineers as physical hardware or cloud resources are invovled.
Additionally, this approach is orthogonal to the development of the application logic. Meaning it can
be added or removed at any time. Old applications can be converted as the main interfaces net.Conn
and
net.Listner
are used. The client/servers are unaware of any networking change. This also means that other GoLang
libraries easily fit this model too - not just HTTP.
Consider the following diagram where existing HTTP API Clients and HTTP API Server is secured using one alternative networking solution: OpenZiti. The Application Server (e.g. HTTP API Server) does not open any ports for listening. Instead, the SDK calls out to an overlay network that verifies it. In this scenario, the Application Server cannot be scanned by normal means on the internet or an internal network unless the overlay network is compromised first.
Examples
The examples are all runnable executables under the cmd
directory.
Servers
Clients
The Main Magic
GoLang's built-in HTTP facilitates provide excellent methods for hooking into them. With the use of the OpenZiti SDK, it essentially boils down to the following patterns that work for the standard GoLang HTTP client and server. These can then be adjusted to fit into any framework/library that uses the GoLang HTTP packages.
The OpenZiti GoLang SDK provides
ZitiTransport
, which can be used as an
http.Transport
/http.RoundTripper
, and edge.Listener
that can be used as a net.Listener
. ZitiTransport
can be used to create
http.Client
instances and edge.Listener
can be used to with http.Serve(listener,...)
calls. The rest of the
GoLang HTTP machinery handles all the HTTP interactions unknowingly over an OpenZiti network.
This same pattern can be used to inject any custom networking you wish!
If you want to deep dive, the ZitiTransport
definition can be found here
and edge.Listen()
can be found here.
Client
Before:
client := http.DefaultClient
resp, err := client.Get("http://" + args.ServiceName)
After:
client := sdk_golang.NewHttpClient(ctx, nil)
resp, err := client.Get("http://" + args.ServiceName)
Server
Before:
if err := http.Serve(listener, http.HandlerFunc(handler)); err != nil {
log.Fatalf("serving failed: %v", err)
}
After:
listener, err = ctx.Listen(args.ServiceName)
if err := http.Serve(listener, http.HandlerFunc(handler)); err != nil {
log.Fatalf("https serving failed: %v", err)
}
Example CLI Arguments
Each example uses the same command line argument processing. This processing takes in two or four arguments that specify the Ziti Identity configuration file and OpenZiti service name. The two additional arguments are paths to a x509 certificate and key in PEM format. If specified for a server, the server will be hosted as an HTTPS service using the provided certificate and key files for the server's identity. For a client, the x509 certificate and key will be used as the client certificate and key used to initiate the TLS connection over the OpenZiti network.
ziti-server-gin <serviceName> <identityConfig> [<certificate> <key>]
However, HTTPS when working with OpenZiti is not necessary. See the next section!
A Note on HTTPS
Hosting an HTTPS server over OpenZiti means that a TLS handshake will occur. A TLS handshake requires that the server presents a certificate with a SAN IP or a SAN DNS entry that matches the address the client used to access the service. For OpenZiti, this means that a SAN DNS that matches the OpenZiti service name must be present.
If the service will only be hosted over OpenZiti, HTTPS is an extra layer of security that can safely be omitted. OpenZiti connections are inherently end-to-end encrypted and the data plane across an OpenZiti network is additionally encrypted on each leg of transit. Further, the controller has already verified all clients and hosts before they "dial" (connect) or "bind" (host).
Building The Examples
git clone https://github.com/openziti-test-kitchen/go-http.git
cd go-http
go install ./...
~/go/bin/ziti-server-go ...
or$GOBIN/ziti-server-go ...
if you have a customGOBIN
environment variable
After building the examples, see the next section on setting up a network.
Setting Up The Examples
To run these examples an OpenZiti network must be up and running. This includes a controller and router. A service, service host, and client will need to be created. The host and client identities will require policies to access and host the service. To set up an OpenZiti network, please see the quickstart guides.
You will need the Ziti CLI from the main Ziti repository installed and on your path.
- Login
ziti edge login "https://localhost:1280/edge/management/v1" -c $controllerCa -u $user -p $password
- Create the Service
ziti create service myHttpService -a httpService
- Create the identities
ziti create identity service httpServer -a httpServer -o server.jwt
> createsserver.jwt
ziti create identity user httpClient -a httpClient -o client.jwt
> createsclient.jwt
- Create policies
ziti create service-policy httpServers Bind --identity-roles #httpServer --service-roles #httpService
ziti create service-policy httpClients Dial --identity-roles #httpClient --service-roles #httpService
- Enroll your identities
ziti edge enroll server.jwt
> createsserver.json
ziti edge enroll client.jwt
> createsclient.json
- Start an example
ziti-server-go myHttpService server.json
ziti-client-resty myHttpService client.json