Merge branch 'main' into oauth-testing
4
.github/workflows/ci-build.yml
vendored
@ -20,12 +20,12 @@ jobs:
|
||||
- name: setup-go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19.3
|
||||
go-version: 1.21.0
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 18.x
|
||||
|
||||
- run: npm install
|
||||
working-directory: ui
|
||||
|
3
.github/workflows/publish-docker-images.yml
vendored
@ -9,7 +9,8 @@ on:
|
||||
required: true
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- released # excludes "prereleased" which is included in "published" to
|
||||
# avoid prematurely releasing semver tagged container images
|
||||
|
||||
jobs:
|
||||
publish-docker-images:
|
||||
|
12
.github/workflows/release.yml
vendored
@ -24,12 +24,12 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.19.3'
|
||||
go-version: '>=1.21.0'
|
||||
cache: true
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 18.x
|
||||
|
||||
- run: npm install
|
||||
working-directory: ui
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.19.3'
|
||||
go-version: '>=1.21.0'
|
||||
cache: true
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
@ -108,7 +108,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.19.3'
|
||||
go-version: '>=1.21.0'
|
||||
cache: true
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
@ -157,7 +157,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.19.3'
|
||||
go-version: '>=1.21.0'
|
||||
cache: true
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
@ -201,7 +201,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.19.3'
|
||||
go-version: '>=1.21.0'
|
||||
cache: true
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
|
3
BUILD.md
@ -2,8 +2,7 @@
|
||||
|
||||
## zrok
|
||||
|
||||
At this time, building `zrok` is pretty straightforward. You will require `node` v16+ to be installed in order to complete
|
||||
the build as well as `go`.
|
||||
At this time, building `zrok` is pretty straightforward. You will require `node` v16+ to be installed in order to complete the build as well as `go`. Because `zrok` uses CGO, you will also need to have a working C compiler toolchain. [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) works great on Windows (just make sure it's in your PATH).
|
||||
|
||||
To build, follow these steps:
|
||||
* clone the repository
|
||||
|
32
CHANGELOG.md
@ -1,3 +1,33 @@
|
||||
# v0.4.6
|
||||
|
||||
FEATURE: New `--backend-mode caddy`, which pre-processes a `Caddyfile` allowing a `bind` statement to work like this: `bind {{ .ZrokBindAddress }}`. Allows development of complicated API gateways and multi-backend shares, while maintaining the simple, ephemeral sharing model provided by `zrok` (https://github.com/openziti/zrok/issues/391)
|
||||
|
||||
CHANGE: `--backend-mode web` has been refactored to utilize Caddy as the integrated web server. This provides for a much nicer web-based file browsing experience, while maintaining the existing web server facilities (https://github.com/openziti/zrok/issues/392)
|
||||
|
||||
CHANGE: Updated the golang version for release builds to `1.21.0` and the node version to `18.x`
|
||||
|
||||
CHANGE: Added `FrontendEndponts` to `sdk.Share`, returning selected frontend URLs to callers of `sdk.CreateShare`
|
||||
|
||||
CHANGE: Added a short alias `-b` for `--backend-mode` to improve CLI ergonomics (https://github.com/openziti/zrok/issues/397)
|
||||
|
||||
# v0.4.5
|
||||
|
||||
FEATURE: New health check endpoint (`/health`), which verifies that the underlying SQL store and metrics repository (InfluxDB, if configured) are operating correctly (https://github.com/openziti/zrok/issues/372)
|
||||
|
||||
CHANGE: Updated to golang v1.21.0 and node v18.x
|
||||
|
||||
FIX: `zrok admin bootstrap` and `zrok enable` both broken with latest OpenZiti releases (tested with `v0.30.0`); updated to latest OpenZiti golang SDK (https://github.com/openziti/zrok/issues/389)
|
||||
|
||||
# v0.4.4
|
||||
|
||||
FIX: `zrok status`, `zrok enable`, `zrok config`, etc. were all causing a panic when used on systems that had no previous `~/.zrok` directory (https://github.com/openziti/zrok/issues/383)
|
||||
|
||||
# v0.4.3
|
||||
|
||||
FEATURE: New `zrok overview` command, which returns all of the account details as a single JSON structure. See the OpenAPI spec at `specs/zrok.yml` for more details of the `/api/v1/overview` endpoint (https://github.com/openziti/zrok/issues/374)
|
||||
|
||||
FEATURE: New `zrok` SDK (https://github.com/openziti/zrok/issues/34). `pastebin` example illustrates basic SDK usage (see `sdk/examples/pastebin/README.md` for details) ((https://github.com/openziti/zrok/issues/379)
|
||||
|
||||
# v0.4.2
|
||||
|
||||
Some days are just like this. `v0.4.2` is a re-do of `v0.4.1`. Trying to get Homebrew working and had a bad release. Hopefully this is the one.
|
||||
@ -6,7 +36,7 @@ Some days are just like this. `v0.4.2` is a re-do of `v0.4.1`. Trying to get Hom
|
||||
|
||||
FEATURE: New `zrok console` command to open the currently configured web console in the local web browser (https://github.com/openziti/zrok/issues/170)
|
||||
|
||||
CHANGES: Further tweaks to the release process to automatically get the latest release into Homebrew (https://github.com/openziti/zrok/issues/264)
|
||||
CHANGE: Further tweaks to the release process to automatically get the latest release into Homebrew (https://github.com/openziti/zrok/issues/264)
|
||||
|
||||
# v0.4.0
|
||||
|
||||
|
60
README.md
@ -1,24 +1,20 @@
|
||||
![zrok](docs/images/zrok.png)
|
||||
![zrok](docs/images/zrok_cover.png)
|
||||
|
||||
`zrok` is a next-generation sharing platform built on top of [OpenZiti](https://docs.openziti.io/docs/learn/introduction/), a programmable zero-trust network overlay. `zrok` is a _Ziti Native Application_.
|
||||
`zrok` is a next-generation, peer-to-peer sharing platform built on top of [OpenZiti](https://docs.openziti.io/docs/learn/introduction/), a programmable zero-trust network overlay. `zrok` is a _Ziti Native Application_.
|
||||
|
||||
`zrok` facilitates sharing resources both publicly and privately, exposing them to an audience you can easily control.
|
||||
`zrok` facilitates sharing resources both publicly and privately. Public sharing allows you to share `zrok` resources with non-`zrok` users over the public internet. Private sharing allows you to directly share your resources peer-to-peer with other `zrok` users without changing your security or firewall settings.
|
||||
|
||||
Like other offerings in this space, `zrok` allows users to create ephemeral reverse proxies ("tunnels") for `http` resources. Additionally:
|
||||
Like other offerings in this space, `zrok` allows users to share tunnels for HTTP, TCP and UDP network resources. `zrok` additionally allows users to easily and rapidly share files, web content, and custom resources in a peer-to-peer manner.
|
||||
|
||||
* `zrok` allows users to _privately_ share resources with other `zrok` users; in _private_ usage scenarios, your private resources are not exposed to any public endpoints; all communication is securely and privately transported between `zrok` environments
|
||||
* `zrok` allows sharing other types of resources; rather than just proxying `http` endpoints, `zrok` allows users to easily and rapidly share files and web content
|
||||
* `zrok` is ready to be extended to easily support many kinds of decentralized resource sharing; `zrok` provides a framework that makes this kind of peer-to-peer resource sharing simple and secure
|
||||
`zrok` is an extensible platform for sharing. Initially we're targeting technical users. Super-simple sharing for end users is planned an in the backlog.
|
||||
|
||||
![zrok](docs/images/zrok_deployment.png)
|
||||
![zrok Web Console](docs/images/zrok_web_console.png)
|
||||
|
||||
## Frictionless
|
||||
|
||||
You can be up and sharing using the `zrok.io` service in minutes. Here is a synopsis of what's involved.
|
||||
You can be up and sharing using the `zrok.io` service in minutes. Here is a synopsis of what's involved:
|
||||
|
||||
### First-time Setup
|
||||
|
||||
* Download the binary for your platform [here](https://github.com/openziti/zrok/releases)
|
||||
* Download the binary for your platform [here](https://github.com/openziti/zrok/releases/latest)
|
||||
* `zrok invite` to create an account with the service
|
||||
* `zrok enable` to enable your shell environment for sharing with the service
|
||||
|
||||
@ -26,7 +22,43 @@ You can be up and sharing using the `zrok.io` service in minutes. Here is a syno
|
||||
|
||||
* `zrok share` to share resources immediately, simply and securely
|
||||
|
||||
See the [Concepts and Getting Started Guide](docs/getting-started.md) for a full overview.
|
||||
See the [Concepts and Getting Started Guide](https://docs.zrok.io/docs/getting-started) for a full overview.
|
||||
|
||||
## The `zrok` SDK
|
||||
|
||||
`zrok` includes an SDK that allows you to embed `zrok` sharing capabilities into your own applications. If you're familiar with a golang `net.Conn` and `net.Listener`, you'll be right at home with our SDK.
|
||||
|
||||
### A Simple `zrok` Sharing Service
|
||||
|
||||
```go
|
||||
// load enabled zrok environment
|
||||
root, err := environment.LoadRoot()
|
||||
|
||||
// request a share for your resource
|
||||
shr, err := sdk.CreateShare(root, &sdk.ShareRequest{
|
||||
BackendMode: sdk.TcpTunnelBackendMode,
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
// ...
|
||||
})
|
||||
|
||||
// accept requests for your resource
|
||||
listener, err := sdk.NewListener(shr.Token, root)
|
||||
```
|
||||
|
||||
### A Simple `zrok` Client
|
||||
|
||||
```go
|
||||
// load enabled zrok environment
|
||||
root, err := environment.LoadRoot()
|
||||
|
||||
// request access to a shared zrok resource
|
||||
acc, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: shrToken})
|
||||
|
||||
// establish a connection to the resource directly
|
||||
conn, err := sdk.NewDialer(shrToken, root)
|
||||
```
|
||||
|
||||
This [blog post](https://blog.openziti.io/the-zrok-sdk) provides more details for [getting started](https://blog.openziti.io/the-zrok-sdk) with the `zrok` SDK.
|
||||
|
||||
## Self-Hosting
|
||||
|
||||
@ -36,7 +68,7 @@ See the [Concepts and Getting Started Guide](docs/getting-started.md) for a full
|
||||
|
||||
The single `zrok` binary contains everything you need to operate `zrok` environments and also host your own service instances. Just add an OpenZiti network and you're up and running.
|
||||
|
||||
See the [Self-Hosting Guide](docs/guides/self-hosting/self_hosting_guide.md) for details on getting your own `zrok` service instance running. This builds on top of the [OpenZiti Quick Start](https://docs.openziti.io/docs/learn/quickstarts/network/) to have a running `zrok` service instance in minutes.
|
||||
See the [Self-Hosting Guide](https://docs.zrok.io/docs/guides/self-hosting/self_hosting_guide/) for details on getting your own `zrok` service instance running.
|
||||
|
||||
## Building
|
||||
|
||||
|
@ -8,11 +8,11 @@ import (
|
||||
"github.com/openziti/zrok/endpoints/proxy"
|
||||
"github.com/openziti/zrok/endpoints/tcpTunnel"
|
||||
"github.com/openziti/zrok/endpoints/udpTunnel"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"net/url"
|
||||
@ -48,16 +48,16 @@ func newAccessPrivateCommand() *accessPrivateCommand {
|
||||
func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
shrToken := args[0]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("error loading environment", err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !env.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
@ -65,11 +65,11 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", env.Environment().Token)
|
||||
req := share.NewAccessParams()
|
||||
req.Body = &rest_model_zrok.AccessRequest{
|
||||
ShrToken: shrToken,
|
||||
EnvZID: zrd.Env.ZId,
|
||||
EnvZID: env.Environment().ZitiIdentity,
|
||||
}
|
||||
accessResp, err := zrok.Share.Access(req, auth)
|
||||
if err != nil {
|
||||
@ -101,20 +101,20 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
case "tcpTunnel":
|
||||
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
|
||||
BindAddress: cmd.bindAddress,
|
||||
IdentityName: "backend",
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
})
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private frontend", err)
|
||||
tui.Error("unable to create private access", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error starting frontend", err)
|
||||
tui.Error("error starting access", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
@ -123,7 +123,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
case "udpTunnel":
|
||||
fe, err := udpTunnel.NewFrontend(&udpTunnel.FrontendConfig{
|
||||
BindAddress: cmd.bindAddress,
|
||||
IdentityName: "backend",
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
IdleTime: time.Minute,
|
||||
@ -144,7 +144,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}()
|
||||
|
||||
default:
|
||||
cfg := proxy.DefaultFrontendConfig("backend")
|
||||
cfg := proxy.DefaultFrontendConfig(env.EnvironmentIdentityName())
|
||||
cfg.ShrToken = shrToken
|
||||
cfg.Address = cmd.bindAddress
|
||||
cfg.RequestsChan = requests
|
||||
@ -168,7 +168,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, zrd.Env.ZId, shrToken, zrok, auth)
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
@ -203,7 +203,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
close(requests)
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, zrd.Env.ZId, shrToken, zrok, auth)
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ func init() {
|
||||
|
||||
type adminBootstrap struct {
|
||||
cmd *cobra.Command
|
||||
skipCtrl bool
|
||||
skipFrontend bool
|
||||
}
|
||||
|
||||
@ -26,7 +25,6 @@ func newAdminBootstrap() *adminBootstrap {
|
||||
}
|
||||
command := &adminBootstrap{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
cmd.Flags().BoolVar(&command.skipCtrl, "skip-ctrl", false, "Skip controller (ctrl) identity bootstrapping")
|
||||
cmd.Flags().BoolVar(&command.skipFrontend, "skip-frontend", false, "Skip frontend identity bootstrapping")
|
||||
return command
|
||||
}
|
||||
@ -38,7 +36,7 @@ func (cmd *adminBootstrap) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infof(cf.Dump(inCfg, cf.DefaultOptions()))
|
||||
if err := controller.Bootstrap(cmd.skipCtrl, cmd.skipFrontend, inCfg); err != nil {
|
||||
if err := controller.Bootstrap(cmd.skipFrontend, inCfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Info("bootstrap complete!")
|
||||
|
@ -1,14 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -35,12 +34,12 @@ func (cmd *adminCreateFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
publicName := args[1]
|
||||
urlTemplate := args[2]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
@ -32,7 +32,11 @@ func newAdminCreateIdentity() *adminCreateIdentity {
|
||||
func (cmd *adminCreateIdentity) run(_ *cobra.Command, args []string) {
|
||||
name := args[0]
|
||||
|
||||
zif, err := zrokdir.ZitiIdentityFile(name)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
zif, err := env.ZitiIdentityNamed(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -41,12 +45,7 @@ func (cmd *adminCreateIdentity) run(_ *cobra.Command, args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -59,7 +58,7 @@ func (cmd *adminCreateIdentity) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := zrokdir.SaveZitiIdentity(name, resp.Payload.Cfg); err != nil {
|
||||
if err := env.SaveZitiIdentityNamed(name, resp.Payload.Cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -30,12 +30,12 @@ func newAdminDeleteFrontendCommand() *adminDeleteFrontendCommand {
|
||||
func (cmd *adminDeleteFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
feToken := args[0]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -43,12 +43,12 @@ func (cmd *adminGenerateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
logrus.Error("error loading zrokdir", err)
|
||||
logrus.Error("error loading environment", err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
logrus.Error("error creating zrok api client", err)
|
||||
|
@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"time"
|
||||
@ -31,12 +31,12 @@ func newAdminListFrontendsCommand() *adminListFrontendsCommand {
|
||||
}
|
||||
|
||||
func (cmd *adminListFrontendsCommand) run(_ *cobra.Command, _ []string) {
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -38,12 +38,12 @@ func (cmd *adminUpdateFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
panic("must specify at least one of public name or url template")
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -28,15 +28,15 @@ func newConfigGetCommand() *configGetCommand {
|
||||
func (cmd *configGetCommand) run(_ *cobra.Command, args []string) {
|
||||
configName := args[0]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
switch configName {
|
||||
case "apiEndpoint":
|
||||
if zrd.Cfg != nil && zrd.Cfg.ApiEndpoint != "" {
|
||||
fmt.Printf("apiEndpoint = %v\n", zrd.Cfg.ApiEndpoint)
|
||||
if env.Config() != nil && env.Config().ApiEndpoint != "" {
|
||||
fmt.Printf("apiEndpoint = %v\n", env.Config().ApiEndpoint)
|
||||
} else {
|
||||
fmt.Println("apiEndpoint = <unset>")
|
||||
}
|
||||
|
@ -2,12 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -33,17 +33,13 @@ func (cmd *configSetCommand) run(_ *cobra.Command, args []string) {
|
||||
configName := args[0]
|
||||
value := args[1]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
modified := false
|
||||
switch configName {
|
||||
case "apiEndpoint":
|
||||
if zrd.Cfg == nil {
|
||||
zrd.Cfg = &zrokdir.Config{}
|
||||
}
|
||||
ok, err := isFullyValidUrl(value)
|
||||
if err != nil {
|
||||
tui.Error("unable to validate api endpoint", err)
|
||||
@ -51,25 +47,26 @@ func (cmd *configSetCommand) run(_ *cobra.Command, args []string) {
|
||||
if !ok {
|
||||
tui.Error("invalid apiEndpoint; please make sure URL starts with http:// or https://", nil)
|
||||
}
|
||||
zrd.Cfg.ApiEndpoint = value
|
||||
modified = true
|
||||
if env.Config() == nil {
|
||||
if err := env.SetConfig(&env_core.Config{ApiEndpoint: value}); err != nil {
|
||||
tui.Error("unable to save config", err)
|
||||
}
|
||||
} else {
|
||||
cfg := env.Config()
|
||||
cfg.ApiEndpoint = value
|
||||
if err := env.SetConfig(cfg); err != nil {
|
||||
tui.Error("unable to save config", err)
|
||||
}
|
||||
}
|
||||
fmt.Println("zrok configuration updated")
|
||||
if env.IsEnabled() {
|
||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||
}
|
||||
|
||||
default:
|
||||
fmt.Printf("unknown config name '%v'\n", configName)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if modified {
|
||||
if err := zrd.Save(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("zrok configuration updated")
|
||||
if zrd.Env != nil && configName == "apiEndpoint" {
|
||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||
}
|
||||
} else {
|
||||
fmt.Println("zrok configuration not changed")
|
||||
}
|
||||
}
|
||||
|
||||
func isFullyValidUrl(rawUrl string) (bool, error) {
|
||||
|
@ -2,8 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
@ -30,33 +31,23 @@ func newConfigUnsetCommand() *configUnsetCommand {
|
||||
func (cmd *configUnsetCommand) run(_ *cobra.Command, args []string) {
|
||||
configName := args[0]
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
modified := false
|
||||
switch configName {
|
||||
case "apiEndpoint":
|
||||
if zrd.Cfg != nil && zrd.Cfg.ApiEndpoint != "" {
|
||||
zrd.Cfg.ApiEndpoint = ""
|
||||
modified = true
|
||||
if err := env.SetConfig(&env_core.Config{}); err != nil {
|
||||
tui.Error("unable to save config", err)
|
||||
}
|
||||
fmt.Println("zrok configuration updated")
|
||||
if env.IsEnabled() {
|
||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||
}
|
||||
|
||||
default:
|
||||
fmt.Printf("unknown config name '%v'\n", configName)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if modified {
|
||||
if err := zrd.Save(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("zrok configuration updated")
|
||||
if zrd.Env != nil && configName == "apiEndpoint" {
|
||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||
}
|
||||
} else {
|
||||
fmt.Println("zrok configuration not changed")
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -27,12 +27,12 @@ func newConsoleCommand() *consoleCommand {
|
||||
}
|
||||
|
||||
func (cmd *consoleCommand) run(_ *cobra.Command, _ []string) {
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
|
||||
apiEndpoint, _ := zrd.ApiEndpoint()
|
||||
apiEndpoint, _ := env.ApiEndpoint()
|
||||
if err := openBrowser(apiEndpoint); err != nil {
|
||||
tui.Error(fmt.Sprintf("unable to open '%v'", apiEndpoint), err)
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/rest_client_zrok/environment"
|
||||
httpTransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/environment"
|
||||
restEnvironment "github.com/openziti/zrok/rest_client_zrok/environment"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -31,41 +31,41 @@ func newDisableCommand() *disableCommand {
|
||||
}
|
||||
|
||||
func (cmd *disableCommand) run(_ *cobra.Command, _ []string) {
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !env.IsEnabled() {
|
||||
tui.Error("no environment found; nothing to disable!", nil)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("could not create zrok client", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
req := environment.NewDisableParams()
|
||||
auth := httpTransport.APIKeyAuth("X-TOKEN", "header", env.Environment().Token)
|
||||
req := restEnvironment.NewDisableParams()
|
||||
req.Body = &rest_model_zrok.DisableRequest{
|
||||
Identity: zrd.Env.ZId,
|
||||
Identity: env.Environment().ZitiIdentity,
|
||||
}
|
||||
_, err = zrok.Environment.Disable(req, auth)
|
||||
if err != nil {
|
||||
logrus.Warnf("share cleanup failed (%v); will clean up local environment", err)
|
||||
}
|
||||
if err := zrokdir.DeleteEnvironment(); err != nil {
|
||||
if err := env.DeleteEnvironment(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error removing zrok environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
if err := zrokdir.DeleteZitiIdentity("backend"); err != nil {
|
||||
if err := env.DeleteZitiIdentityNamed(env.EnvironmentIdentityName()); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error removing zrok backend identity", err)
|
||||
}
|
||||
|
@ -2,20 +2,20 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
user2 "os/user"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/rest_client_zrok/environment"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
restEnvironment "github.com/openziti/zrok/rest_client_zrok/environment"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
user2 "os/user"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -42,13 +42,13 @@ func newEnableCommand() *enableCommand {
|
||||
}
|
||||
|
||||
func (cmd *enableCommand) run(_ *cobra.Command, args []string) {
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
token := args[0]
|
||||
|
||||
if zrd.Env != nil {
|
||||
if env.IsEnabled() {
|
||||
tui.Error(fmt.Sprintf("you already have an enabled environment, %v first before you %v", tui.Code.Render("zrok disable"), tui.Code.Render("zrok enable")), nil)
|
||||
}
|
||||
|
||||
@ -64,13 +64,13 @@ func (cmd *enableCommand) run(_ *cobra.Command, args []string) {
|
||||
if cmd.description == "<user>@<hostname>" {
|
||||
cmd.description = fmt.Sprintf("%v@%v", user.Username, hostName)
|
||||
}
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
cmd.endpointError(zrd.ApiEndpoint())
|
||||
cmd.endpointError(env.ApiEndpoint())
|
||||
tui.Error("error creating service client", err)
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", token)
|
||||
req := environment.NewEnableParams()
|
||||
req := restEnvironment.NewEnableParams()
|
||||
req.Body = &rest_model_zrok.EnableRequest{
|
||||
Description: cmd.description,
|
||||
Host: hostDetail,
|
||||
@ -110,15 +110,14 @@ func (cmd *enableCommand) run(_ *cobra.Command, args []string) {
|
||||
case <-done:
|
||||
case <-time.After(1 * time.Second):
|
||||
}
|
||||
cmd.endpointError(zrd.ApiEndpoint())
|
||||
cmd.endpointError(env.ApiEndpoint())
|
||||
os.Exit(1)
|
||||
}
|
||||
if err != nil {
|
||||
prg.Send("writing the environment details...")
|
||||
}
|
||||
apiEndpoint, _ := zrd.ApiEndpoint()
|
||||
zrd.Env = &zrokdir.Environment{Token: token, ZId: resp.Payload.Identity, ApiEndpoint: apiEndpoint}
|
||||
if err := zrd.Save(); err != nil {
|
||||
apiEndpoint, _ := env.ApiEndpoint()
|
||||
if err := env.SetEnvironment(&env_core.Environment{Token: token, ZitiIdentity: resp.Payload.Identity, ApiEndpoint: apiEndpoint}); err != nil {
|
||||
if !cmd.headless && prg != nil {
|
||||
prg.Send(fmt.Sprintf("there was an error saving the new environment: %v", err))
|
||||
prg.Quit()
|
||||
@ -131,7 +130,7 @@ func (cmd *enableCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := zrokdir.SaveZitiIdentity("backend", resp.Payload.Cfg); err != nil {
|
||||
if err := env.SaveZitiIdentityNamed(env.EnvironmentIdentityName(), resp.Payload.Cfg); err != nil {
|
||||
if !cmd.headless && prg != nil {
|
||||
prg.Send(fmt.Sprintf("there was an error writing the environment: %v", err))
|
||||
prg.Quit()
|
||||
|
@ -2,19 +2,18 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/account"
|
||||
"github.com/openziti/zrok/rest_client_zrok/metadata"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -42,15 +41,15 @@ func newInviteCommand() *inviteCommand {
|
||||
}
|
||||
|
||||
func (cmd *inviteCommand) run(_ *cobra.Command, _ []string) {
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
tui.Error("error loading environment", err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
cmd.endpointError(zrd.ApiEndpoint())
|
||||
cmd.endpointError(env.ApiEndpoint())
|
||||
tui.Error("error creating zrok api client", err)
|
||||
}
|
||||
panic(err)
|
||||
@ -63,7 +62,7 @@ func (cmd *inviteCommand) run(_ *cobra.Command, _ []string) {
|
||||
|
||||
if md != nil {
|
||||
if !md.GetPayload().InvitesOpen {
|
||||
apiEndpoint, _ := zrd.ApiEndpoint()
|
||||
apiEndpoint, _ := env.ApiEndpoint()
|
||||
tui.Error(fmt.Sprintf("'%v' is not currently accepting new users", apiEndpoint), nil)
|
||||
}
|
||||
cmd.tui.invitesOpen = md.GetPayload().InvitesOpen
|
||||
@ -86,7 +85,7 @@ func (cmd *inviteCommand) run(_ *cobra.Command, _ []string) {
|
||||
}
|
||||
_, err = zrok.Account.Invite(req)
|
||||
if err != nil {
|
||||
cmd.endpointError(zrd.ApiEndpoint())
|
||||
cmd.endpointError(env.ApiEndpoint())
|
||||
tui.Error("error creating invitation", err)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/openziti/transport/v2"
|
||||
"github.com/openziti/transport/v2/tcp"
|
||||
"github.com/openziti/transport/v2/udp"
|
||||
_ "github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
72
cmd/zrok/overview.go
Normal file
@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(newOverviewCommand().cmd)
|
||||
}
|
||||
|
||||
type overviewCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newOverviewCommand() *overviewCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "overview",
|
||||
Short: "Retrieve all of the zrok account details (environments, shares) as JSON",
|
||||
Args: cobra.ExactArgs(0),
|
||||
}
|
||||
command := &overviewCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *overviewCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
apiEndpoint, _ := root.ApiEndpoint()
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%v/api/v1/overview", apiEndpoint), nil)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error accessing overview", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
req.Header.Add("X-TOKEN", root.Environment().Token)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error requesting overview", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
json, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error reading body", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
|
||||
fmt.Println(string(json))
|
||||
}
|
@ -2,10 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -31,19 +31,19 @@ func newReleaseCommand() *releaseCommand {
|
||||
|
||||
func (cmd *releaseCommand) run(_ *cobra.Command, args []string) {
|
||||
shrToken := args[0]
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !env.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
@ -51,10 +51,10 @@ func (cmd *releaseCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", env.Environment().Token)
|
||||
req := share.NewUnshareParams()
|
||||
req.Body = &rest_model_zrok.UnshareRequest{
|
||||
EnvZID: zrd.Env.ZId,
|
||||
EnvZID: env.Environment().ZitiIdentity,
|
||||
ShrToken: shrToken,
|
||||
Reserved: true,
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -33,14 +29,14 @@ func newReserveCommand() *reserveCommand {
|
||||
command := &reserveCommand{cmd: cmd}
|
||||
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
|
||||
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
|
||||
cmd.Flags().StringVar(&command.backendMode, "backend-mode", "proxy", "The backend mode {proxy, web, <tcpTunnel, udpTunnel>}")
|
||||
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, <tcpTunnel, udpTunnel>, caddy}")
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
|
||||
shareMode := args[0]
|
||||
if shareMode != "public" && shareMode != "private" {
|
||||
shareMode := sdk.ShareMode(args[0])
|
||||
if shareMode != sdk.PublicShareMode && shareMode != sdk.PrivateShareMode {
|
||||
tui.Error("invalid sharing mode; expecting 'public' or 'private'", nil)
|
||||
}
|
||||
|
||||
@ -58,63 +54,51 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
|
||||
|
||||
case "web":
|
||||
target = args[1]
|
||||
|
||||
case "tcpTunnel":
|
||||
target = args[1]
|
||||
|
||||
case "udpTunnel":
|
||||
target = args[1]
|
||||
|
||||
case "caddy":
|
||||
target = args[1]
|
||||
|
||||
default:
|
||||
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel, udpTunnel, caddy}", cmd.backendMode), nil)
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
tui.Error("error loading environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !env.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
req := &sdk.ShareRequest{
|
||||
BackendMode: sdk.BackendMode(cmd.backendMode),
|
||||
ShareMode: shareMode,
|
||||
Auth: cmd.basicAuth,
|
||||
Target: target,
|
||||
}
|
||||
if shareMode == sdk.PublicShareMode {
|
||||
req.Frontends = cmd.frontendSelection
|
||||
}
|
||||
shr, err := sdk.CreateShare(env, req)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
req := share.NewShareParams()
|
||||
req.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: zrd.Env.ZId,
|
||||
ShareMode: shareMode,
|
||||
BackendMode: cmd.backendMode,
|
||||
BackendProxyEndpoint: target,
|
||||
AuthScheme: string(model.None),
|
||||
Reserved: true,
|
||||
}
|
||||
if shareMode == "public" {
|
||||
req.Body.FrontendSelection = cmd.frontendSelection
|
||||
}
|
||||
if len(cmd.basicAuth) > 0 {
|
||||
logrus.Infof("configuring basic auth")
|
||||
req.Body.AuthScheme = string(model.Basic)
|
||||
for _, pair := range cmd.basicAuth {
|
||||
tokens := strings.Split(pair, ":")
|
||||
if len(tokens) == 2 {
|
||||
req.Body.AuthUsers = append(req.Body.AuthUsers, &rest_model_zrok.AuthUser{Username: strings.TrimSpace(tokens[0]), Password: strings.TrimSpace(tokens[1])})
|
||||
} else {
|
||||
panic(errors.Errorf("invalid username:password pair '%v'", pair))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := zrok.Share.Share(req, auth)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create tunnel", err)
|
||||
tui.Error("unable to create share", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logrus.Infof("your reserved share token is '%v'", resp.Payload.ShrToken)
|
||||
for _, fpe := range resp.Payload.FrontendProxyEndpoints {
|
||||
logrus.Infof("your reserved share token is '%v'", shr.Token)
|
||||
for _, fpe := range shr.FrontendEndpoints {
|
||||
logrus.Infof("reserved frontend endpoint: %v", fpe)
|
||||
}
|
||||
}
|
||||
|
@ -3,24 +3,18 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/proxy"
|
||||
"github.com/openziti/zrok/endpoints/tcpTunnel"
|
||||
"github.com/openziti/zrok/endpoints/udpTunnel"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@ -44,7 +38,7 @@ func newSharePrivateCommand() *sharePrivateCommand {
|
||||
}
|
||||
command := &sharePrivateCommand{cmd: cmd}
|
||||
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...")
|
||||
cmd.Flags().StringVar(&command.backendMode, "backend-mode", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel}")
|
||||
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy}")
|
||||
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
|
||||
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
|
||||
cmd.Run = command.run
|
||||
@ -74,23 +68,27 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
case "udpTunnel":
|
||||
target = args[0]
|
||||
|
||||
case "caddy":
|
||||
target = args[0]
|
||||
cmd.headless = true
|
||||
|
||||
default:
|
||||
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel}", cmd.backendMode), nil)
|
||||
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel, udpTunnel, caddy}", cmd.backendMode), nil)
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zif, err := zrokdir.ZitiIdentityFile("backend")
|
||||
zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load ziti identity configuration", err)
|
||||
@ -98,36 +96,13 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
}
|
||||
panic(err)
|
||||
req := &sdk.ShareRequest{
|
||||
BackendMode: sdk.BackendMode(cmd.backendMode),
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
Auth: cmd.basicAuth,
|
||||
Target: target,
|
||||
}
|
||||
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
req := share.NewShareParams()
|
||||
req.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: zrd.Env.ZId,
|
||||
ShareMode: "private",
|
||||
BackendMode: cmd.backendMode,
|
||||
BackendProxyEndpoint: target,
|
||||
AuthScheme: string(model.None),
|
||||
}
|
||||
if len(cmd.basicAuth) > 0 {
|
||||
logrus.Infof("configuring basic auth")
|
||||
req.Body.AuthScheme = string(model.Basic)
|
||||
for _, pair := range cmd.basicAuth {
|
||||
tokens := strings.Split(pair, ":")
|
||||
if len(tokens) == 2 {
|
||||
req.Body.AuthUsers = append(req.Body.AuthUsers, &rest_model_zrok.AuthUser{Username: strings.TrimSpace(tokens[0]), Password: strings.TrimSpace(tokens[1])})
|
||||
} else {
|
||||
panic(errors.Errorf("invalid username:password pair '%v'", pair))
|
||||
}
|
||||
}
|
||||
}
|
||||
resp, err := zrok.Share.Share(req, auth)
|
||||
shr, err := sdk.CreateShare(root, req)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create share", err)
|
||||
@ -135,61 +110,84 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
shareDescription := fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", shr.Token)))
|
||||
mdl := newShareModel(shr.Token, []string{shareDescription}, sdk.PrivateShareMode, sdk.BackendMode(cmd.backendMode))
|
||||
if !cmd.headless {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.destroy(zrd.Env.ZId, resp.Payload.ShrToken, zrok, auth)
|
||||
cmd.shutdown(root, shr)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
requestsChan := make(chan *endpoints.Request, 1024)
|
||||
requests := make(chan *endpoints.Request, 1024)
|
||||
|
||||
switch cmd.backendMode {
|
||||
case "proxy":
|
||||
cfg := &proxy.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
ShrToken: shr.Token,
|
||||
Insecure: cmd.insecure,
|
||||
RequestsChan: requestsChan,
|
||||
Requests: requests,
|
||||
}
|
||||
_, err = cmd.proxyBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create proxy backend handler", err)
|
||||
tui.Error("error creating proxy backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "web":
|
||||
cfg := &proxy.WebBackendConfig{
|
||||
cfg := &proxy.CaddyWebBackendConfig{
|
||||
IdentityPath: zif,
|
||||
WebRoot: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
ShrToken: shr.Token,
|
||||
Requests: requests,
|
||||
}
|
||||
_, err = cmd.webBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewCaddyWebBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create web backend handler", err)
|
||||
tui.Error("error creating web backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "tcpTunnel":
|
||||
cfg := &tcpTunnel.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
ShrToken: shr.Token,
|
||||
RequestsChan: requests,
|
||||
}
|
||||
|
||||
be, err := tcpTunnel.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create tcpTunnel backend", err)
|
||||
tui.Error("error creating tcpTunnel backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running tcpTunnel backend: %v", err)
|
||||
@ -200,38 +198,60 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
cfg := &udpTunnel.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
ShrToken: shr.Token,
|
||||
RequestsChan: requests,
|
||||
}
|
||||
|
||||
be, err := udpTunnel.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create udpTunnel backend", err)
|
||||
tui.Error("error creating udpTunnel backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running udpTunnel backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "caddy":
|
||||
cfg := &proxy.CaddyfileBackendConfig{
|
||||
CaddyfilePath: target,
|
||||
Shr: shr,
|
||||
Requests: requests,
|
||||
}
|
||||
|
||||
be, err := proxy.NewCaddyfileBackend(cfg)
|
||||
if err != nil {
|
||||
cmd.shutdown(root, shr)
|
||||
if !panicInstead {
|
||||
tui.Error("error creating caddy backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running caddy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
default:
|
||||
tui.Error("invalid backend mode", nil)
|
||||
}
|
||||
|
||||
if cmd.headless {
|
||||
logrus.Infof("allow other to access your share with the following command:\nzrok access private %v", resp.Payload.ShrToken)
|
||||
logrus.Infof("allow other to access your share with the following command:\nzrok access private %v", shr.Token)
|
||||
for {
|
||||
select {
|
||||
case req := <-requestsChan:
|
||||
case req := <-requests:
|
||||
logrus.Infof("%v -> %v %v", req.RemoteAddr, req.Method, req.Path)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
shareDescription := fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", resp.Payload.ShrToken)))
|
||||
mdl := newShareModel(resp.Payload.ShrToken, []string{shareDescription}, "private", cmd.backendMode)
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
mdl.prg = prg
|
||||
@ -239,7 +259,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case req := <-requestsChan:
|
||||
case req := <-requests:
|
||||
prg.Send(req)
|
||||
}
|
||||
}
|
||||
@ -249,51 +269,15 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
tui.Error("An error occurred", err)
|
||||
}
|
||||
|
||||
close(requestsChan)
|
||||
cmd.destroy(zrd.Env.ZId, resp.Payload.ShrToken, zrok, auth)
|
||||
close(requests)
|
||||
cmd.shutdown(root, shr)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *sharePrivateCommand) proxyBackendMode(cfg *proxy.BackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http proxy backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePrivateCommand) webBackendMode(cfg *proxy.WebBackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewWebBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http web backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePrivateCommand) destroy(id string, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
|
||||
logrus.Debugf("shutting down '%v'", shrToken)
|
||||
req := share.NewUnshareParams()
|
||||
req.Body = &rest_model_zrok.UnshareRequest{
|
||||
EnvZID: id,
|
||||
ShrToken: shrToken,
|
||||
}
|
||||
if _, err := zrok.Share.Unshare(req, auth); err == nil {
|
||||
logrus.Debugf("shutdown complete")
|
||||
} else {
|
||||
logrus.Errorf("error shutting down: %v", err)
|
||||
func (cmd *sharePrivateCommand) shutdown(root env_core.Root, shr *sdk.Share) {
|
||||
logrus.Debugf("shutting down '%v'", shr.Token)
|
||||
if err := sdk.DeleteShare(root, shr); err != nil {
|
||||
logrus.Errorf("error shutting down '%v': %v", shr.Token, err)
|
||||
}
|
||||
logrus.Debugf("shutdown complete")
|
||||
}
|
||||
|
@ -9,17 +9,12 @@ import (
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/proxy"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -49,7 +44,7 @@ func newSharePublicCommand() *sharePublicCommand {
|
||||
command := &sharePublicCommand{cmd: cmd}
|
||||
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
|
||||
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
|
||||
cmd.Flags().StringVar(&command.backendMode, "backend-mode", "proxy", "The backend mode {proxy, web}")
|
||||
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, caddy}")
|
||||
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
|
||||
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
|
||||
|
||||
@ -79,67 +74,49 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
case "web":
|
||||
target = args[0]
|
||||
|
||||
case "caddy":
|
||||
target = args[0]
|
||||
cmd.headless = true
|
||||
|
||||
default:
|
||||
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web}", cmd.backendMode), nil)
|
||||
}
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zif, err := zrokdir.ZitiIdentityFile("backend")
|
||||
zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load ziti identity configuration", err)
|
||||
tui.Error("unable to access ziti identity file", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
}
|
||||
panic(err)
|
||||
req := &sdk.ShareRequest{
|
||||
BackendMode: sdk.BackendMode(cmd.backendMode),
|
||||
ShareMode: sdk.PublicShareMode,
|
||||
Frontends: cmd.frontendSelection,
|
||||
Auth: cmd.basicAuth,
|
||||
Target: target,
|
||||
}
|
||||
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
req := share.NewShareParams()
|
||||
req.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: zrd.Env.ZId,
|
||||
ShareMode: "public",
|
||||
FrontendSelection: cmd.frontendSelection,
|
||||
BackendMode: cmd.backendMode,
|
||||
BackendProxyEndpoint: target,
|
||||
AuthScheme: string(model.None),
|
||||
}
|
||||
if len(cmd.basicAuth) > 0 {
|
||||
logrus.Infof("configuring basic auth")
|
||||
req.Body.AuthScheme = string(model.Basic)
|
||||
for _, pair := range cmd.basicAuth {
|
||||
tokens := strings.Split(pair, ":")
|
||||
if len(tokens) == 2 {
|
||||
req.Body.AuthUsers = append(req.Body.AuthUsers, &rest_model_zrok.AuthUser{Username: strings.TrimSpace(tokens[0]), Password: strings.TrimSpace(tokens[1])})
|
||||
} else {
|
||||
panic(errors.Errorf("invalid username:password pair '%v'", pair))
|
||||
}
|
||||
}
|
||||
}
|
||||
if cmd.oauthProvider != "" {
|
||||
req.Body.AuthScheme = string(model.Oauth)
|
||||
req.Body.OauthProvider = cmd.oauthProvider
|
||||
req.Body.OauthEmailDomains = cmd.oauthEmailDomains
|
||||
req.Body.OauthAuthorizationCheckInterval = cmd.oauthCheckInterval.String()
|
||||
req.Auth = []string{}
|
||||
req.OauthProvider = cmd.oauthProvider
|
||||
req.OauthEmailDomains = cmd.oauthEmailDomains
|
||||
req.OauthAuthorizationCheckInterval = cmd.oauthCheckInterval
|
||||
}
|
||||
resp, err := zrok.Share.Share(req, auth)
|
||||
shr, err := sdk.CreateShare(root, req)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create share", err)
|
||||
@ -147,62 +124,103 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mdl := newShareModel(shr.Token, shr.FrontendEndpoints, sdk.PublicShareMode, sdk.BackendMode(cmd.backendMode))
|
||||
if !cmd.headless {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.destroy(zrd.Env.ZId, resp.Payload.ShrToken, zrok, auth)
|
||||
cmd.shutdown(root, shr)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
requestsChan := make(chan *endpoints.Request, 1024)
|
||||
requests := make(chan *endpoints.Request, 1024)
|
||||
|
||||
switch cmd.backendMode {
|
||||
case "proxy":
|
||||
cfg := &proxy.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
ShrToken: shr.Token,
|
||||
Insecure: cmd.insecure,
|
||||
RequestsChan: requestsChan,
|
||||
Requests: requests,
|
||||
}
|
||||
_, err = cmd.proxyBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create proxy backend handler", err)
|
||||
tui.Error("error creating proxy backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "web":
|
||||
cfg := &proxy.WebBackendConfig{
|
||||
cfg := &proxy.CaddyWebBackendConfig{
|
||||
IdentityPath: zif,
|
||||
WebRoot: target,
|
||||
ShrToken: resp.Payload.ShrToken,
|
||||
RequestsChan: requestsChan,
|
||||
ShrToken: shr.Token,
|
||||
Requests: requests,
|
||||
}
|
||||
_, err = cmd.webBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewCaddyWebBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create web backend handler", err)
|
||||
tui.Error("unable to create web backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "caddy":
|
||||
cfg := &proxy.CaddyfileBackendConfig{
|
||||
CaddyfilePath: target,
|
||||
Shr: shr,
|
||||
Requests: requests,
|
||||
}
|
||||
|
||||
be, err := proxy.NewCaddyfileBackend(cfg)
|
||||
if err != nil {
|
||||
cmd.shutdown(root, shr)
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create caddy backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running caddy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
default:
|
||||
tui.Error("invalid backend mode", nil)
|
||||
}
|
||||
|
||||
if cmd.headless {
|
||||
logrus.Infof("access your zrok share at the following endpoints:\n %v", strings.Join(resp.Payload.FrontendProxyEndpoints, "\n"))
|
||||
logrus.Infof("access your zrok share at the following endpoints:\n %v", strings.Join(shr.FrontendEndpoints, "\n"))
|
||||
for {
|
||||
select {
|
||||
case req := <-requestsChan:
|
||||
case req := <-requests:
|
||||
logrus.Infof("%v -> %v %v", req.RemoteAddr, req.Method, req.Path)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
mdl := newShareModel(resp.Payload.ShrToken, resp.Payload.FrontendProxyEndpoints, "public", cmd.backendMode)
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
mdl.prg = prg
|
||||
@ -210,7 +228,7 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case req := <-requestsChan:
|
||||
case req := <-requests:
|
||||
prg.Send(req)
|
||||
}
|
||||
}
|
||||
@ -220,51 +238,15 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
tui.Error("An error occurred", err)
|
||||
}
|
||||
|
||||
close(requestsChan)
|
||||
cmd.destroy(zrd.Env.ZId, resp.Payload.ShrToken, zrok, auth)
|
||||
close(requests)
|
||||
cmd.shutdown(root, shr)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *sharePublicCommand) proxyBackendMode(cfg *proxy.BackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http proxy backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePublicCommand) webBackendMode(cfg *proxy.WebBackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewWebBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http web backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *sharePublicCommand) destroy(id string, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
|
||||
logrus.Debugf("shutting down '%v'", shrToken)
|
||||
req := share.NewUnshareParams()
|
||||
req.Body = &rest_model_zrok.UnshareRequest{
|
||||
EnvZID: id,
|
||||
ShrToken: shrToken,
|
||||
}
|
||||
if _, err := zrok.Share.Unshare(req, auth); err == nil {
|
||||
logrus.Debugf("shutdown complete")
|
||||
} else {
|
||||
logrus.Errorf("error shutting down: %v", err)
|
||||
func (cmd *sharePublicCommand) shutdown(root env_core.Root, shr *sdk.Share) {
|
||||
logrus.Debugf("shutting down '%v'", shr.Token)
|
||||
if err := sdk.DeleteShare(root, shr); err != nil {
|
||||
logrus.Errorf("error shutting down '%v': %v", shr.Token, err)
|
||||
}
|
||||
logrus.Debugf("shutdown complete")
|
||||
}
|
||||
|
@ -6,12 +6,14 @@ import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/proxy"
|
||||
"github.com/openziti/zrok/endpoints/tcpTunnel"
|
||||
"github.com/openziti/zrok/endpoints/udpTunnel"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/metadata"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -44,26 +46,26 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
shrToken := args[0]
|
||||
var target string
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
tui.Error("error loading environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zrok, err := zrd.Client()
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
|
||||
req := metadata.NewGetShareDetailParams()
|
||||
req.ShrToken = shrToken
|
||||
resp, err := zrok.Metadata.GetShareDetail(req, auth)
|
||||
@ -77,8 +79,11 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
if target == "" {
|
||||
target = resp.Payload.BackendProxyEndpoint
|
||||
}
|
||||
if sdk.BackendMode(resp.Payload.BackendMode) == sdk.CaddyBackendMode {
|
||||
cmd.headless = true
|
||||
}
|
||||
|
||||
zif, err := zrokdir.ZitiIdentityFile("backend")
|
||||
zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load ziti identity configuration", err)
|
||||
@ -105,6 +110,19 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
logrus.Infof("using existing backend proxy endpoint: %v", target)
|
||||
}
|
||||
|
||||
var shareDescription string
|
||||
switch resp.Payload.ShareMode {
|
||||
case string(sdk.PublicShareMode):
|
||||
shareDescription = resp.Payload.FrontendEndpoint
|
||||
case string(sdk.PrivateShareMode):
|
||||
shareDescription = fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", shrToken)))
|
||||
}
|
||||
|
||||
mdl := newShareModel(shrToken, []string{shareDescription}, sdk.ShareMode(resp.Payload.ShareMode), sdk.BackendMode(resp.Payload.BackendMode))
|
||||
if !cmd.headless {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
requestsChan := make(chan *endpoints.Request, 1024)
|
||||
switch resp.Payload.BackendMode {
|
||||
case "proxy":
|
||||
@ -113,9 +131,10 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
EndpointAddress: target,
|
||||
ShrToken: shrToken,
|
||||
Insecure: cmd.insecure,
|
||||
RequestsChan: requestsChan,
|
||||
Requests: requestsChan,
|
||||
}
|
||||
_, err := cmd.proxyBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create proxy backend handler", err)
|
||||
@ -123,31 +142,109 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "web":
|
||||
cfg := &proxy.WebBackendConfig{
|
||||
cfg := &proxy.CaddyWebBackendConfig{
|
||||
IdentityPath: zif,
|
||||
WebRoot: target,
|
||||
ShrToken: shrToken,
|
||||
RequestsChan: requestsChan,
|
||||
Requests: requestsChan,
|
||||
}
|
||||
_, err := cmd.webBackendMode(cfg)
|
||||
|
||||
be, err := proxy.NewCaddyWebBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create web backend handler", err)
|
||||
tui.Error("error creating web backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "tcpTunnel":
|
||||
cfg := &tcpTunnel.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: shrToken,
|
||||
RequestsChan: requestsChan,
|
||||
}
|
||||
|
||||
be, err := tcpTunnel.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error creating tcpTunnel backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running tcpTunnel backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "udpTunnel":
|
||||
cfg := &udpTunnel.BackendConfig{
|
||||
IdentityPath: zif,
|
||||
EndpointAddress: target,
|
||||
ShrToken: shrToken,
|
||||
RequestsChan: requestsChan,
|
||||
}
|
||||
|
||||
be, err := udpTunnel.NewBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error creating udpTunnel backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running udpTunnel backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "caddy":
|
||||
cfg := &proxy.CaddyfileBackendConfig{
|
||||
CaddyfilePath: target,
|
||||
Shr: &sdk.Share{Token: shrToken, FrontendEndpoints: []string{resp.Payload.FrontendEndpoint}},
|
||||
Requests: requestsChan,
|
||||
}
|
||||
|
||||
be, err := proxy.NewCaddyfileBackend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error creating caddy backend", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running caddy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
default:
|
||||
tui.Error("invalid backend mode", nil)
|
||||
}
|
||||
|
||||
if cmd.headless {
|
||||
switch resp.Payload.ShareMode {
|
||||
case "public":
|
||||
case string(sdk.PublicShareMode):
|
||||
logrus.Infof("access your zrok share: %v", resp.Payload.FrontendEndpoint)
|
||||
|
||||
case "private":
|
||||
case string(sdk.PrivateShareMode):
|
||||
logrus.Infof("use this command to access your zrok share: 'zrok access private %v'", shrToken)
|
||||
}
|
||||
for {
|
||||
@ -157,15 +254,6 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var shareDescription string
|
||||
switch resp.Payload.ShareMode {
|
||||
case "public":
|
||||
shareDescription = resp.Payload.FrontendEndpoint
|
||||
case "private":
|
||||
shareDescription = fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", shrToken)))
|
||||
}
|
||||
|
||||
mdl := newShareModel(shrToken, []string{shareDescription}, resp.Payload.ShareMode, resp.Payload.BackendMode)
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
mdl.prg = prg
|
||||
@ -186,33 +274,3 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
close(requestsChan)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *shareReservedCommand) proxyBackendMode(cfg *proxy.BackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http proxy backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http proxy backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (cmd *shareReservedCommand) webBackendMode(cfg *proxy.WebBackendConfig) (endpoints.RequestHandler, error) {
|
||||
be, err := proxy.NewWebBackend(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating http web backend")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := be.Run(); err != nil {
|
||||
logrus.Errorf("error running http web backend: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return be, nil
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -19,8 +20,8 @@ var wordwrapBreakpoints = map[rune]bool{' ': true, '-': true}
|
||||
type shareModel struct {
|
||||
shrToken string
|
||||
frontendDescriptions []string
|
||||
shareMode string
|
||||
backendMode string
|
||||
shareMode sdk.ShareMode
|
||||
backendMode sdk.BackendMode
|
||||
requests []*endpoints.Request
|
||||
log []string
|
||||
showLog bool
|
||||
@ -32,7 +33,7 @@ type shareModel struct {
|
||||
|
||||
type shareLogLine string
|
||||
|
||||
func newShareModel(shrToken string, frontendEndpoints []string, shareMode, backendMode string) *shareModel {
|
||||
func newShareModel(shrToken string, frontendEndpoints []string, shareMode sdk.ShareMode, backendMode sdk.BackendMode) *shareModel {
|
||||
return &shareModel{
|
||||
shrToken: shrToken,
|
||||
frontendDescriptions: frontendEndpoints,
|
||||
@ -116,15 +117,15 @@ func (m *shareModel) adjustPaneHeights() {
|
||||
func (m *shareModel) renderConfig() string {
|
||||
out := "["
|
||||
if m.shareMode == "public" {
|
||||
out += shareModePublicStyle.Render(strings.ToUpper(m.shareMode))
|
||||
out += shareModePublicStyle.Render(strings.ToUpper(string(m.shareMode)))
|
||||
} else {
|
||||
out += shareModePrivateStyle.Render(strings.ToUpper(m.shareMode))
|
||||
out += shareModePrivateStyle.Render(strings.ToUpper(string(m.shareMode)))
|
||||
}
|
||||
out += "] ["
|
||||
if m.backendMode == "proxy" {
|
||||
out += backendModeProxyStyle.Render(strings.ToUpper(m.backendMode))
|
||||
out += backendModeProxyStyle.Render(strings.ToUpper(string(m.backendMode)))
|
||||
} else {
|
||||
out += backendModeWebStyle.Render(strings.ToUpper(m.backendMode))
|
||||
out += backendModeWebStyle.Render(strings.ToUpper(string(m.backendMode)))
|
||||
}
|
||||
out += "]"
|
||||
return out
|
||||
@ -217,6 +218,10 @@ func (m *shareModel) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (shareModel) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func wrap(lines []string, width int) []string {
|
||||
ret := make([]string, 0)
|
||||
for _, line := range lines {
|
||||
|
@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
@ -34,9 +34,13 @@ func newStatusCommand() *statusCommand {
|
||||
func (cmd *statusCommand) run(_ *cobra.Command, _ []string) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n")
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("unable to load zrokdir", err)
|
||||
tui.Error("error loading environment", err)
|
||||
}
|
||||
|
||||
if !environment.IsLatest(env) {
|
||||
tui.Warning(fmt.Sprintf("Your environment is out of date ('%v'), use '%v' to update (make a backup before updating!)\n", env.Metadata().V, tui.Code.Render("zrok update")))
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stdout, tui.Code.Render("Config")+":\n\n")
|
||||
@ -44,13 +48,12 @@ func (cmd *statusCommand) run(_ *cobra.Command, _ []string) {
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Config", "Value", "Source"})
|
||||
apiEndpoint, from := zrd.ApiEndpoint()
|
||||
apiEndpoint, from := env.ApiEndpoint()
|
||||
t.AppendRow(table.Row{"apiEndpoint", apiEndpoint, from})
|
||||
t.Render()
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n")
|
||||
|
||||
if zrd.Env == nil {
|
||||
tui.Warning("Unable to load your local environment!\n")
|
||||
if !env.IsEnabled() {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "To create a local environment use the %v command.\n", tui.Code.Render("zrok enable"))
|
||||
} else {
|
||||
_, _ = fmt.Fprintf(os.Stdout, tui.Code.Render("Environment")+":\n\n")
|
||||
@ -60,17 +63,17 @@ func (cmd *statusCommand) run(_ *cobra.Command, _ []string) {
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Property", "Value"})
|
||||
if cmd.secrets {
|
||||
t.AppendRow(table.Row{"Secret Token", zrd.Env.Token})
|
||||
t.AppendRow(table.Row{"Ziti Identity", zrd.Env.ZId})
|
||||
t.AppendRow(table.Row{"Secret Token", env.Environment().Token})
|
||||
t.AppendRow(table.Row{"Ziti Identity", env.Environment().ZitiIdentity})
|
||||
} else {
|
||||
secretToken := "<<SET>>"
|
||||
if zrd.Env.Token == "" {
|
||||
if env.Environment().Token == "" {
|
||||
secretToken = "<<UNSET>>"
|
||||
}
|
||||
t.AppendRow(table.Row{"Secret Token", secretToken})
|
||||
|
||||
zId := "<<SET>>"
|
||||
if zrd.Env.ZId == "" {
|
||||
if env.Environment().ZitiIdentity == "" {
|
||||
zId = "<<UNSET>>"
|
||||
}
|
||||
t.AppendRow(table.Row{"Ziti Identity", zId})
|
||||
|
@ -8,13 +8,14 @@ import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
@ -105,7 +106,7 @@ func (cmd *testLoopPublicCommand) run(_ *cobra.Command, _ []string) {
|
||||
type looper struct {
|
||||
id int
|
||||
cmd *testLoopPublicCommand
|
||||
env *zrokdir.Environment
|
||||
env *env_core.Environment
|
||||
done chan struct{}
|
||||
listener edge.Listener
|
||||
zif string
|
||||
@ -175,33 +176,33 @@ func (l *looper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
func (l *looper) startup() {
|
||||
logrus.Infof("starting #%d", l.id)
|
||||
|
||||
zrd, err := zrokdir.Load()
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if zrd.Env == nil {
|
||||
if !env.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
l.env = zrd.Env
|
||||
l.env = env.Environment()
|
||||
|
||||
l.zif, err = zrokdir.ZitiIdentityFile("backend")
|
||||
l.zif, err = env.ZitiIdentityNamed(env.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
l.zrok, err = zrd.Client()
|
||||
l.zrok, err = env.Client()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
l.auth = httptransport.APIKeyAuth("x-token", "header", l.env.Token)
|
||||
tunnelReq := share.NewShareParams()
|
||||
tunnelReq.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: l.env.ZId,
|
||||
ShareMode: "public",
|
||||
EnvZID: l.env.ZitiIdentity,
|
||||
ShareMode: string(sdk.PublicShareMode),
|
||||
FrontendSelection: l.cmd.frontendSelection,
|
||||
BackendMode: "proxy",
|
||||
BackendMode: string(sdk.ProxyBackendMode),
|
||||
BackendProxyEndpoint: fmt.Sprintf("looper#%d", l.id),
|
||||
AuthScheme: string(model.None),
|
||||
AuthScheme: string(sdk.None),
|
||||
}
|
||||
tunnelReq.SetTimeout(60 * time.Second)
|
||||
tunnelResp, err := l.zrok.Share.Share(tunnelReq, l.auth)
|
||||
@ -272,7 +273,7 @@ func (l *looper) shutdown() {
|
||||
|
||||
untunnelReq := share.NewUnshareParams()
|
||||
untunnelReq.Body = &rest_model_zrok.UnshareRequest{
|
||||
EnvZID: l.env.ZId,
|
||||
EnvZID: l.env.ZitiIdentity,
|
||||
ShrToken: l.shrToken,
|
||||
}
|
||||
if _, err := l.zrok.Share.Unshare(untunnelReq, l.auth); err != nil {
|
||||
|
52
cmd/zrok/update.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(newUpdateCommand().cmd)
|
||||
}
|
||||
|
||||
type updateCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newUpdateCommand() *updateCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update your environment to the latest version",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &updateCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *updateCommand) run(_ *cobra.Command, _ []string) {
|
||||
r, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if environment.IsLatest(r) {
|
||||
fmt.Printf("zrok environment is already the latest version at '%v'\n", r.Metadata().V)
|
||||
return
|
||||
}
|
||||
|
||||
newR, err := environment.UpdateRoot(r)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to update environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("environment updated to '%v'\n", newR.Metadata().V)
|
||||
}
|
@ -6,22 +6,23 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/config"
|
||||
restMgmtEdgeConfig "github.com/openziti/edge-api/rest_management_api_client/config"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/edge_router_policy"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/identity"
|
||||
rest_model_edge "github.com/openziti/edge-api/rest_model"
|
||||
restModelEdge "github.com/openziti/edge-api/rest_model"
|
||||
"github.com/openziti/edge-api/rest_util"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
zrok_config "github.com/openziti/zrok/controller/config"
|
||||
"github.com/openziti/zrok/controller/config"
|
||||
"github.com/openziti/zrok/controller/store"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Bootstrap(skipCtrl, skipFrontend bool, inCfg *zrok_config.Config) error {
|
||||
func Bootstrap(skipFrontend bool, inCfg *config.Config) error {
|
||||
cfg = inCfg
|
||||
|
||||
if v, err := store.Open(cfg.Store); err == nil {
|
||||
@ -36,34 +37,19 @@ func Bootstrap(skipCtrl, skipFrontend bool, inCfg *zrok_config.Config) error {
|
||||
return errors.Wrap(err, "error connecting to the ziti edge management api")
|
||||
}
|
||||
|
||||
var ctrlZId string
|
||||
if !skipCtrl {
|
||||
logrus.Info("creating identity for controller ziti access")
|
||||
|
||||
if ctrlZId, err = getIdentityId("ctrl"); err == nil {
|
||||
logrus.Infof("controller identity: %v", ctrlZId)
|
||||
} else {
|
||||
ctrlZId, err = bootstrapIdentity("ctrl", edge)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if err := assertIdentity(ctrlZId, edge); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := assertErpForIdentity("ctrl", ctrlZId, edge); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var frontendZId string
|
||||
if !skipFrontend {
|
||||
logrus.Info("creating identity for frontend ziti access")
|
||||
logrus.Info("creating identity for public frontend access")
|
||||
|
||||
if frontendZId, err = getIdentityId("frontend"); err == nil {
|
||||
if frontendZId, err = getIdentityId(env.PublicIdentityName()); err == nil {
|
||||
logrus.Infof("frontend identity: %v", frontendZId)
|
||||
} else {
|
||||
frontendZId, err = bootstrapIdentity("frontend", edge)
|
||||
frontendZId, err = bootstrapIdentity(env.PublicIdentityName(), edge)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -71,7 +57,7 @@ func Bootstrap(skipCtrl, skipFrontend bool, inCfg *zrok_config.Config) error {
|
||||
if err := assertIdentity(frontendZId, edge); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := assertErpForIdentity("frontend", frontendZId, edge); err != nil {
|
||||
if err := assertErpForIdentity(env.PublicIdentityName(), frontendZId, edge); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -100,10 +86,10 @@ func Bootstrap(skipCtrl, skipFrontend bool, inCfg *zrok_config.Config) error {
|
||||
}
|
||||
|
||||
func assertZrokProxyConfigType(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
filter := fmt.Sprintf("name=\"%v\"", model.ZrokProxyConfig)
|
||||
filter := fmt.Sprintf("name=\"%v\"", sdk.ZrokProxyConfig)
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &config.ListConfigTypesParams{
|
||||
listReq := &restMgmtEdgeConfig.ListConfigTypesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
@ -115,27 +101,31 @@ func assertZrokProxyConfigType(edge *rest_management_api_client.ZitiEdgeManageme
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
name := model.ZrokProxyConfig
|
||||
ct := &rest_model_edge.ConfigTypeCreate{Name: &name}
|
||||
createReq := &config.CreateConfigTypeParams{ConfigType: ct}
|
||||
name := sdk.ZrokProxyConfig
|
||||
ct := &restModelEdge.ConfigTypeCreate{Name: &name}
|
||||
createReq := &restMgmtEdgeConfig.CreateConfigTypeParams{ConfigType: ct}
|
||||
createReq.SetTimeout(30 * time.Second)
|
||||
createResp, err := edge.Config.CreateConfigType(createReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("created '%v' config type with id '%v'", model.ZrokProxyConfig, createResp.Payload.Data.ID)
|
||||
logrus.Infof("created '%v' config type with id '%v'", sdk.ZrokProxyConfig, createResp.Payload.Data.ID)
|
||||
} else if len(listResp.Payload.Data) > 1 {
|
||||
return errors.Errorf("found %d '%v' config types; expected 0 or 1", len(listResp.Payload.Data), model.ZrokProxyConfig)
|
||||
return errors.Errorf("found %d '%v' config types; expected 0 or 1", len(listResp.Payload.Data), sdk.ZrokProxyConfig)
|
||||
} else {
|
||||
logrus.Infof("found '%v' config type with id '%v'", model.ZrokProxyConfig, *(listResp.Payload.Data[0].ID))
|
||||
logrus.Infof("found '%v' config type with id '%v'", sdk.ZrokProxyConfig, *(listResp.Payload.Data[0].ID))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIdentityId(identityName string) (string, error) {
|
||||
zif, err := zrokdir.ZitiIdentityFile(identityName)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error opening identity '%v' from zrokdir", identityName)
|
||||
return "", errors.Wrap(err, "error opening environment root")
|
||||
}
|
||||
zif, err := env.ZitiIdentityNamed(identityName)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error opening identity '%v' from environment", identityName)
|
||||
}
|
||||
zcfg, err := ziti.NewConfigFromFile(zif)
|
||||
if err != nil {
|
||||
@ -177,15 +167,20 @@ func assertIdentity(zId string, edge *rest_management_api_client.ZitiEdgeManagem
|
||||
}
|
||||
|
||||
func bootstrapIdentity(name string, edge *rest_management_api_client.ZitiEdgeManagement) (string, error) {
|
||||
idc, err := zrokEdgeSdk.CreateIdentity(name, rest_model_edge.IdentityTypeDevice, nil, edge)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error creating '%v' identity", name)
|
||||
return "", errors.Wrap(err, "error loading environment root")
|
||||
}
|
||||
|
||||
idc, err := zrokEdgeSdk.CreateIdentity(name, restModelEdge.IdentityTypeDevice, nil, edge)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(rest_util.WrapErr(err), "error creating '%v' identity", name)
|
||||
}
|
||||
|
||||
zId := idc.Payload.Data.ID
|
||||
cfg, err := zrokEdgeSdk.EnrollIdentity(zId, edge)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error enrolling '%v' identity", name)
|
||||
return "", errors.Wrapf(rest_util.WrapErr(err), "error enrolling '%v' identity", name)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
@ -195,7 +190,7 @@ func bootstrapIdentity(name string, edge *rest_management_api_client.ZitiEdgeMan
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error encoding identity config '%v'", name)
|
||||
}
|
||||
if err := zrokdir.SaveZitiIdentity(name, out.String()); err != nil {
|
||||
if err := env.SaveZitiIdentityNamed(name, out.String()); err != nil {
|
||||
return "", errors.Wrapf(err, "error saving identity config '%v'", name)
|
||||
}
|
||||
return zId, nil
|
||||
|
@ -130,6 +130,7 @@ func Run(inCfg *config.Config) error {
|
||||
defer func() { _ = server.Shutdown() }()
|
||||
server.Host = cfg.Endpoint.Host
|
||||
server.Port = cfg.Endpoint.Port
|
||||
rest_server_zrok.HealthCheck = HealthCheckHTTP
|
||||
server.ConfigureAPI()
|
||||
if err := server.Serve(); err != nil {
|
||||
return errors.Wrap(err, "api server error")
|
||||
@ -137,3 +138,7 @@ func Run(inCfg *config.Config) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Store() *store.Store {
|
||||
return str
|
||||
}
|
||||
|
62
controller/health.go
Normal file
@ -0,0 +1,62 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func HealthCheckHTTP(w http.ResponseWriter, _ *http.Request) {
|
||||
if err := healthCheckStore(w); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if err := healthCheckMetrics(w); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Write([]byte("<html><body><h1>Healthy</h1></body></html>"))
|
||||
}
|
||||
|
||||
func healthCheckStore(w http.ResponseWriter) error {
|
||||
trx, err := str.Begin()
|
||||
if err != nil {
|
||||
http.Error(w, "error starting transaction", http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = trx.Rollback()
|
||||
}()
|
||||
count := -1
|
||||
if err := trx.QueryRowx("select count(0) from migrations").Scan(&count); err != nil {
|
||||
http.Error(w, "error selecting migration count", http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("%d migrations", count)
|
||||
return nil
|
||||
}
|
||||
|
||||
func healthCheckMetrics(w http.ResponseWriter) error {
|
||||
if cfg.Metrics != nil && cfg.Metrics.Influx != nil {
|
||||
queryApi := idb.QueryAPI(cfg.Metrics.Influx.Org)
|
||||
query := fmt.Sprintf("from(bucket: \"%v\")\n", cfg.Metrics.Influx.Bucket) +
|
||||
fmt.Sprintf("|> range(start: -5s)\n") +
|
||||
"|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" +
|
||||
"|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" +
|
||||
"|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" +
|
||||
"|> sum()"
|
||||
result, err := queryApi.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
http.Error(w, "error querying influx", http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
results := 0
|
||||
for result.Next() {
|
||||
results++
|
||||
}
|
||||
logrus.Debugf("%d results", results)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/openziti/zrok/controller/store"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -38,11 +39,11 @@ func (a *accountRelaxAction) HandleAccount(acct *store.Account, _, _ int64, _ *B
|
||||
|
||||
for _, shr := range shrs {
|
||||
switch shr.ShareMode {
|
||||
case "public":
|
||||
case string(sdk.PublicShareMode):
|
||||
if err := relaxPublicShare(a.str, edge, shr, trx); err != nil {
|
||||
return errors.Wrap(err, "error relaxing public share")
|
||||
}
|
||||
case "private":
|
||||
case string(sdk.PrivateShareMode):
|
||||
if err := relaxPrivateShare(a.str, edge, shr, trx); err != nil {
|
||||
return errors.Wrap(err, "error relaxing private share")
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/openziti/zrok/controller/store"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -33,11 +34,11 @@ func (a *environmentRelaxAction) HandleEnvironment(env *store.Environment, rxByt
|
||||
for _, shr := range shrs {
|
||||
if !shr.Deleted {
|
||||
switch shr.ShareMode {
|
||||
case "public":
|
||||
case string(sdk.PublicShareMode):
|
||||
if err := relaxPublicShare(a.str, edge, shr, trx); err != nil {
|
||||
return err
|
||||
}
|
||||
case "private":
|
||||
case string(sdk.PrivateShareMode):
|
||||
if err := relaxPrivateShare(a.str, edge, shr, trx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/zrok/controller/store"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -28,11 +29,11 @@ func (a *shareRelaxAction) HandleShare(shr *store.Share, _, _ int64, _ *Bandwidt
|
||||
}
|
||||
|
||||
switch shr.ShareMode {
|
||||
case "public":
|
||||
case string(sdk.PublicShareMode):
|
||||
if err := relaxPublicShare(a.str, edge, shr, trx); err != nil {
|
||||
return err
|
||||
}
|
||||
case "private":
|
||||
case string(sdk.PrivateShareMode):
|
||||
if err := relaxPrivateShare(a.str, edge, shr, trx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ func (h *registerHandler) Handle(params account.RegisterParams) middleware.Respo
|
||||
return account.NewRegisterInternalServerError()
|
||||
}
|
||||
|
||||
logrus.Infof("created account '%v' with token '%v'", a.Email, a.Token)
|
||||
logrus.Infof("created account '%v'", a.Email)
|
||||
|
||||
return account.NewRegisterOK().WithPayload(&rest_model_zrok.RegisterResponse{Token: a.Token})
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/rest_server_zrok/operations/share"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -68,7 +69,7 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
|
||||
var shrZId string
|
||||
var frontendEndpoints []string
|
||||
switch params.Body.ShareMode {
|
||||
case "public":
|
||||
case string(sdk.PublicShareMode):
|
||||
if len(params.Body.FrontendSelection) < 1 {
|
||||
logrus.Info("no frontend selection provided")
|
||||
return share.NewShareNotFound()
|
||||
@ -94,7 +95,7 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
|
||||
return share.NewShareInternalServerError()
|
||||
}
|
||||
|
||||
case "private":
|
||||
case string(sdk.PrivateShareMode):
|
||||
logrus.Info("doing private")
|
||||
shrZId, frontendEndpoints, err = newPrivateResourceAllocator().allocate(envZId, shrToken, params, edge)
|
||||
if err != nil {
|
||||
@ -123,7 +124,7 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
|
||||
}
|
||||
if len(frontendEndpoints) > 0 {
|
||||
sshr.FrontendEndpoint = &frontendEndpoints[0]
|
||||
} else if sshr.ShareMode == "private" {
|
||||
} else if sshr.ShareMode == string(sdk.PrivateShareMode) {
|
||||
sshr.FrontendEndpoint = &sshr.ShareMode
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package controller
|
||||
import (
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/rest_server_zrok/operations/share"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
)
|
||||
|
||||
type privateResourceAllocator struct{}
|
||||
@ -14,9 +14,9 @@ func newPrivateResourceAllocator() *privateResourceAllocator {
|
||||
}
|
||||
|
||||
func (a *privateResourceAllocator) allocate(envZId, shrToken string, params share.ShareParams, edge *rest_management_api_client.ZitiEdgeManagement) (shrZId string, frontendEndpoints []string, err error) {
|
||||
var authUsers []*model.AuthUser
|
||||
var authUsers []*sdk.AuthUser
|
||||
for _, authUser := range params.Body.AuthUsers {
|
||||
authUsers = append(authUsers, &model.AuthUser{authUser.Username, authUser.Password})
|
||||
authUsers = append(authUsers, &sdk.AuthUser{authUser.Username, authUser.Password})
|
||||
}
|
||||
cfgZId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, params.Body.OauthProvider, params.Body.OauthEmailDomains, edge)
|
||||
if err != nil {
|
||||
|
@ -3,8 +3,8 @@ package controller
|
||||
import (
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/rest_server_zrok/operations/share"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
)
|
||||
|
||||
type publicResourceAllocator struct{}
|
||||
@ -14,9 +14,9 @@ func newPublicResourceAllocator() *publicResourceAllocator {
|
||||
}
|
||||
|
||||
func (a *publicResourceAllocator) allocate(envZId, shrToken string, frontendZIds, frontendTemplates []string, params share.ShareParams, edge *rest_management_api_client.ZitiEdgeManagement) (shrZId string, frontendEndpoints []string, err error) {
|
||||
var authUsers []*model.AuthUser
|
||||
var authUsers []*sdk.AuthUser
|
||||
for _, authUser := range params.Body.AuthUsers {
|
||||
authUsers = append(authUsers, &model.AuthUser{authUser.Username, authUser.Password})
|
||||
authUsers = append(authUsers, &sdk.AuthUser{authUser.Username, authUser.Password})
|
||||
}
|
||||
cfgId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, params.Body.OauthProvider, params.Body.OauthEmailDomains, edge)
|
||||
if err != nil {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/config"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"time"
|
||||
@ -36,7 +36,7 @@ func inspectZiti() error {
|
||||
}
|
||||
|
||||
func findZrokProxyConfigType(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
filter := fmt.Sprintf("name=\"%v\"", model.ZrokProxyConfig)
|
||||
filter := fmt.Sprintf("name=\"%v\"", sdk.ZrokProxyConfig)
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &config.ListConfigTypesParams{
|
||||
@ -53,7 +53,7 @@ func findZrokProxyConfigType(edge *rest_management_api_client.ZitiEdgeManagement
|
||||
if len(listResp.Payload.Data) != 1 {
|
||||
return errors.Errorf("expected 1 zrok proxy config type, found %d", len(listResp.Payload.Data))
|
||||
}
|
||||
logrus.Infof("found '%v' config type with id '%v'", model.ZrokProxyConfig, *(listResp.Payload.Data[0].ID))
|
||||
logrus.Infof("found '%v' config type with id '%v'", sdk.ZrokProxyConfig, *(listResp.Payload.Data[0].ID))
|
||||
zrokProxyConfigId = *(listResp.Payload.Data[0].ID)
|
||||
|
||||
return nil
|
||||
|
@ -0,0 +1,3 @@
|
||||
-- +migrate Up
|
||||
|
||||
alter type backend_mode add value 'caddy';
|
@ -0,0 +1,54 @@
|
||||
-- +migrate Up
|
||||
|
||||
alter table shares rename to shares_old;
|
||||
create table shares (
|
||||
id integer primary key,
|
||||
environment_id integer constraint fk_environments_shares references environments on delete cascade,
|
||||
z_id string not null unique,
|
||||
token string not null unique,
|
||||
share_mode string not null,
|
||||
backend_mode string not null,
|
||||
frontend_selection string,
|
||||
frontend_endpoint string,
|
||||
backend_proxy_endpoint string,
|
||||
reserved boolean not null default(false),
|
||||
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
||||
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), deleted boolean not null default(false),
|
||||
|
||||
constraint chk_z_id check (z_id <> ''),
|
||||
constraint chk_token check (token <> ''),
|
||||
constraint chk_share_mode check (share_mode == 'public' or share_mode == 'private'),
|
||||
constraint chk_backend_mode check (backend_mode == 'proxy' or backend_mode == 'web' or backend_mode == 'tcpTunnel' or backend_mode == 'udpTunnel' or backend_mode == 'caddy')
|
||||
);
|
||||
insert into shares select * from shares_old;
|
||||
drop table shares_old;
|
||||
|
||||
alter table frontends rename to frontends_old;
|
||||
create table frontends (
|
||||
id integer primary key,
|
||||
environment_id integer references environments(id),
|
||||
token varchar(32) not null unique,
|
||||
z_id varchar(32) not null,
|
||||
public_name varchar(64) unique,
|
||||
url_template varchar(1024),
|
||||
reserved boolean not null default(false),
|
||||
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
||||
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
||||
deleted boolean not null default(false),
|
||||
private_share_id integer references shares(id)
|
||||
);
|
||||
insert into frontends select * from frontends_old;
|
||||
drop table frontends_old;
|
||||
|
||||
alter table share_limit_journal rename to share_limit_journal_old;
|
||||
create table share_limit_journal (
|
||||
id integer primary key,
|
||||
share_id integer references shares(id),
|
||||
rx_bytes bigint not null,
|
||||
tx_bytes bigint not null,
|
||||
action limit_action_type not null,
|
||||
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
|
||||
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now'))
|
||||
);
|
||||
insert into share_limit_journal select * from share_limit_journal_old;
|
||||
drop table share_limit_journal_old;
|
@ -6,24 +6,23 @@ import (
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/config"
|
||||
"github.com/openziti/edge-api/rest_model"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO: Create options struct
|
||||
func CreateConfig(cfgTypeZId, envZId, shrToken string, authSchemeStr string, authUsers []*model.AuthUser, oauthProvider string, oauthEmailDomains []string, edge *rest_management_api_client.ZitiEdgeManagement) (cfgZId string, err error) {
|
||||
authScheme, err := model.ParseAuthScheme(authSchemeStr)
|
||||
func CreateConfig(cfgTypeZId, envZId, shrToken string, authSchemeStr string, authUsers []*sdk.AuthUser, oauthProvider string, oauthEmailDomains []string, edge *rest_management_api_client.ZitiEdgeManagement) (cfgZId string, err error) {
|
||||
authScheme, err := sdk.ParseAuthScheme(authSchemeStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cfg := &model.ProxyConfig{
|
||||
cfg := &sdk.ProxyConfig{
|
||||
AuthScheme: authScheme,
|
||||
}
|
||||
if cfg.AuthScheme == model.Basic {
|
||||
cfg.BasicAuth = &model.BasicAuth{}
|
||||
if cfg.AuthScheme == sdk.Basic {
|
||||
cfg.BasicAuth = &sdk.BasicAuth{}
|
||||
for _, authUser := range authUsers {
|
||||
cfg.BasicAuth.Users = append(cfg.BasicAuth.Users, &model.AuthUser{Username: authUser.Username, Password: authUser.Password})
|
||||
cfg.BasicAuth.Users = append(cfg.BasicAuth.Users, &sdk.AuthUser{Username: authUser.Username, Password: authUser.Password})
|
||||
}
|
||||
}
|
||||
if cfg.AuthScheme == model.Oauth {
|
||||
|
@ -56,15 +56,15 @@ When the user runs `zrok enable` from their shell, here's what happens:
|
||||
2. The `zrok` controller creates a new OpenZiti identity for the environment and enrolls it.
|
||||
3. The `zrok` controller creates an edge router policy associating the new OpenZiti identity with `#all` edge routers.
|
||||
4. The `zrok` controller returns the entire SDK configuration back to the `zrok enable` client.
|
||||
5. The `zrok enable` client then stores the OpenZiti identity along with a few other housekeeping details in the user's `~/.zrok` folder (we refer to this as `zrokdir`, conceptually in the code).
|
||||
6. With the OpenZiti identity and configuration details stored in the user's `zrokdir`, the user is then able to create any number of binding endpoints using the `zrok http` command.
|
||||
5. The `zrok enable` client then stores the OpenZiti identity along with a few other housekeeping details in the user's `~/.zrok` folder.
|
||||
6. With the OpenZiti identity and configuration details stored in the user's `environment`, the user is then able to create any number of binding endpoints using the `zrok http` command.
|
||||
|
||||
|
||||
### The `zrok http` Flow
|
||||
|
||||
When a `zrok` user issues a `zrok http` command for an endpoint, here's what happens:
|
||||
|
||||
1. The `zrok http` client gathers the necessary identity details from the `zrokdir` (this was all staged during `zrok enable`).
|
||||
1. The `zrok http` client gathers the necessary identity details from the `environment` (this was all staged during `zrok enable`).
|
||||
2. The `zrok http` client reaches out to the `zrok` controller with an authenticated `tunnel` request, asking to have a new endpoint binding created.
|
||||
3. The `zrok` controller allocates a new "service name" for the binding.
|
||||
4. The `zrok` controller creates a `zrok.proxy.v1` configuration describing the user's requested authentication details (currently: `none` or `basic`).
|
||||
|
@ -20,12 +20,7 @@ Let's take a look at how to get started with `zrok`.
|
||||
|
||||
:::note `zrok` moves fast!
|
||||
|
||||
`zrok` is currently in a closed-beta phase and requires an invitation token. If you would like to try `zrok` and provide
|
||||
feedback, please send an email to invite@zrok.io. `zrok` is an open source project and is in its early development
|
||||
phases. We're doing our development publicly. See the [roadmap](https://github.com/orgs/openziti/projects/16) for details
|
||||
about the project. We are highly interested in feedback as we continue to iterate quickly. Please provide feedback in
|
||||
[Discourse](https://openziti.discourse.group/), raise [GitHub Issues](https://github.com/openziti/zrok/issues), or reach
|
||||
out directly.
|
||||
`zrok` is an open source project and is in its early development phases. We're doing our development publicly. See the [roadmap](https://github.com/orgs/openziti/projects/16) for details about the project. We are highly interested in feedback as we continue to iterate quickly. Please provide feedback in [Discourse](https://openziti.discourse.group/), raise [GitHub Issues](https://github.com/openziti/zrok/issues), or reach out directly.
|
||||
|
||||
:::
|
||||
|
||||
@ -107,13 +102,13 @@ The `zrok` executable defaults to using the `zrok` service instance at `api.zrok
|
||||
|
||||
```
|
||||
$ zrok config set apiEndpoint https://zrok.mydomain.com
|
||||
[WARNING]: unable to open zrokdir metadata; ignoring
|
||||
[WARNING]: unable to open environment metadata; ignoring
|
||||
|
||||
zrok configuration updated
|
||||
```
|
||||
|
||||
:::note
|
||||
The `WARNING` about `zrokdir metadata` is ignorable. Running the `zrok config set` command writes a small piece of metadata into a `.zrok` folder inside your home directory. This allows `zrok` to identify the version of its settings, providing a mechanism to upgrade your installation as new versions are released. This `WARNING` is letting you know that your current environment has not been initialized by `zrok`.
|
||||
The `WARNING` about `environment metadata` is ignorable. Running the `zrok config set` command writes a small piece of metadata into a `.zrok` folder inside your home directory. This allows `zrok` to identify the version of its settings, providing a mechanism to upgrade your installation as new versions are released. This `WARNING` is letting you know that your current environment has not been initialized by `zrok`.
|
||||
:::
|
||||
|
||||
You can use the `zrok status` command to inspect the state of your local _environment_. `zrok` refers to each shell where you install and `enable` a copy of `zrok` as as an _environment_.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"label": "Metrics and Limits",
|
||||
"position": 40,
|
||||
"position": 60,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
---
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
# Configuring Limits
|
||||
|
||||
> If you have not yet configured [metrics](configuring-metrics.md), please visit the [metrics guide](configuring-metrics.md) first before working through the limits configuration.
|
@ -1,3 +1,7 @@
|
||||
---
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
# Configuring Metrics
|
||||
|
||||
A fully configured, production-scale `zrok` service instance looks like this:
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
@ -85,7 +85,7 @@ The `ziti` section defines how the `zrok` controller should communicate with you
|
||||
|
||||
Be sure to see the [reference configuration at `etc/ctrl.yml`](../../../etc/ctrl.yml) for the complete documentation of the current configuration file format for the `zrok` controller and service instance components.
|
||||
|
||||
See the separate guides on [configuring metrics](../metrics-and-limits/configuring-metrics.md) and [configuring limits](../metrics-and-limits/configuring-limits.md) for details about both of these specialized areas of service instance configuration.
|
||||
See the separate guides on [configuring metrics](./metrics-and-limits/configuring-metrics.md) and [configuring limits](./metrics-and-limits/configuring-limits.md) for details about both of these specialized areas of service instance configuration.
|
||||
|
||||
:::
|
||||
|
||||
|
BIN
docs/images/zrok_cover.png
Executable file
After Width: | Height: | Size: 90 KiB |
BIN
docs/images/zrok_web_console.png
Executable file
After Width: | Height: | Size: 96 KiB |
80
endpoints/caddyListener.go
Normal file
@ -0,0 +1,80 @@
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
_ "github.com/caddyserver/caddy/v2/modules/standard"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterNetwork("zrok", NewZrokListener)
|
||||
}
|
||||
|
||||
type ZrokListener struct {
|
||||
zctx ziti.Context
|
||||
share string
|
||||
l edge.Listener
|
||||
}
|
||||
|
||||
func (l *ZrokListener) String() string {
|
||||
return fmt.Sprintf("zrok/%s", l.share)
|
||||
}
|
||||
|
||||
func (l *ZrokListener) Network() string {
|
||||
return "zrok"
|
||||
}
|
||||
|
||||
func (l *ZrokListener) Accept() (net.Conn, error) {
|
||||
return l.l.Accept()
|
||||
}
|
||||
|
||||
func (l *ZrokListener) Close() error {
|
||||
_ = l.l.Close()
|
||||
l.zctx.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ZrokListener) Addr() net.Addr {
|
||||
return l
|
||||
}
|
||||
|
||||
func NewZrokListener(_ context.Context, _ string, addr string, _ net.ListenConfig) (any, error) {
|
||||
shrToken := strings.Split(addr, ":")[0]
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !env.IsEnabled() {
|
||||
return nil, errors.New("environment not enabled")
|
||||
}
|
||||
zif, err := env.ZitiIdentityNamed(env.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zctx, err := ziti.NewContextFromFile(zif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err := zctx.Listen(shrToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := &ZrokListener{
|
||||
zctx: zctx,
|
||||
share: shrToken,
|
||||
l: conn,
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ net.Addr = (*ZrokListener)(nil)
|
||||
_ net.Listener = (*ZrokListener)(nil)
|
||||
)
|
@ -20,7 +20,7 @@ type BackendConfig struct {
|
||||
EndpointAddress string
|
||||
ShrToken string
|
||||
Insecure bool
|
||||
RequestsChan chan *endpoints.Request
|
||||
Requests chan *endpoints.Request
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
@ -88,8 +88,8 @@ func newReverseProxy(cfg *BackendConfig) (*httputil.ReverseProxy, error) {
|
||||
proxy.Transport = tpt
|
||||
director := proxy.Director
|
||||
proxy.Director = func(req *http.Request) {
|
||||
if cfg.RequestsChan != nil {
|
||||
cfg.RequestsChan <- &endpoints.Request{
|
||||
if cfg.Requests != nil {
|
||||
cfg.Requests <- &endpoints.Request{
|
||||
Stamp: time.Now(),
|
||||
RemoteAddr: fmt.Sprintf("%v", req.Header["X-Real-Ip"]),
|
||||
Method: req.Method,
|
||||
|
1217
endpoints/proxy/browse.html
Executable file
52
endpoints/proxy/caddyLogger.go
Normal file
@ -0,0 +1,52 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterModule(CaddyLogWriter{})
|
||||
}
|
||||
|
||||
func SetCaddyLoggingWriter(w io.WriteCloser) {
|
||||
loggingRequests = w
|
||||
}
|
||||
|
||||
var loggingRequests io.WriteCloser
|
||||
|
||||
type CaddyLogWriter struct{}
|
||||
|
||||
func (CaddyLogWriter) CaddyModule() caddy.ModuleInfo {
|
||||
return caddy.ModuleInfo{
|
||||
ID: "caddy.logging.writers.zrok_tui",
|
||||
New: func() caddy.Module { return new(CaddyLogWriter) },
|
||||
}
|
||||
}
|
||||
|
||||
func (w *CaddyLogWriter) Provision(_ caddy.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (CaddyLogWriter) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (CaddyLogWriter) WriterKey() string {
|
||||
return "zrok_tui"
|
||||
}
|
||||
|
||||
func (CaddyLogWriter) OpenWriter() (io.WriteCloser, error) {
|
||||
return loggingRequests, nil
|
||||
}
|
||||
|
||||
func (*CaddyLogWriter) UnmarshalCaddyfile(_ *caddyfile.Dispenser) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ caddy.Provisioner = (*CaddyLogWriter)(nil)
|
||||
_ caddy.WriterOpener = (*CaddyLogWriter)(nil)
|
||||
_ caddyfile.Unmarshaler = (*CaddyLogWriter)(nil)
|
||||
)
|
73
endpoints/proxy/caddyRequestsMiddleware.go
Normal file
@ -0,0 +1,73 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
||||
)
|
||||
|
||||
var middlewareRequests chan *endpoints.Request
|
||||
|
||||
func init() {
|
||||
caddy.RegisterModule(ZrokRequestsMiddleware{})
|
||||
httpcaddyfile.RegisterHandlerDirective("zrok_requests", parseCaddyfile)
|
||||
}
|
||||
|
||||
type ZrokRequestsMiddleware struct{}
|
||||
|
||||
// CaddyModule returns the Caddy module information.
|
||||
func (ZrokRequestsMiddleware) CaddyModule() caddy.ModuleInfo {
|
||||
return caddy.ModuleInfo{
|
||||
ID: "http.handlers.zrok_requests",
|
||||
New: func() caddy.Module { return new(ZrokRequestsMiddleware) },
|
||||
}
|
||||
}
|
||||
|
||||
// Provision implements caddy.Provisioner.
|
||||
func (m *ZrokRequestsMiddleware) Provision(ctx caddy.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate implements caddy.Validator.
|
||||
func (m ZrokRequestsMiddleware) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeHTTP implements caddyhttp.MiddlewareHandler.
|
||||
func (m ZrokRequestsMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
|
||||
if middlewareRequests != nil {
|
||||
middlewareRequests <- &endpoints.Request{
|
||||
Stamp: time.Now(),
|
||||
RemoteAddr: fmt.Sprintf("%v", r.Header["X-Real-Ip"]),
|
||||
Method: r.Method,
|
||||
Path: r.URL.String(),
|
||||
}
|
||||
}
|
||||
return next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
|
||||
func (m *ZrokRequestsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseCaddyfile unmarshals tokens from h into a new ZrokRequestsMiddleware.
|
||||
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
|
||||
var m ZrokRequestsMiddleware
|
||||
err := m.UnmarshalCaddyfile(h.Dispenser)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// Interface guards
|
||||
var (
|
||||
_ caddy.Provisioner = (*ZrokRequestsMiddleware)(nil)
|
||||
_ caddy.Validator = (*ZrokRequestsMiddleware)(nil)
|
||||
_ caddyhttp.MiddlewareHandler = (*ZrokRequestsMiddleware)(nil)
|
||||
_ caddyfile.Unmarshaler = (*ZrokRequestsMiddleware)(nil)
|
||||
)
|
86
endpoints/proxy/caddyWebBackend.go
Normal file
@ -0,0 +1,86 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp/fileserver"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CaddyWebBackendConfig struct {
|
||||
IdentityPath string
|
||||
WebRoot string
|
||||
ShrToken string
|
||||
Requests chan *endpoints.Request
|
||||
}
|
||||
|
||||
type CaddyWebBackend struct {
|
||||
cfg *CaddyWebBackendConfig
|
||||
caddyCfg *caddy.Config
|
||||
}
|
||||
|
||||
func NewCaddyWebBackend(cfg *CaddyWebBackendConfig) (*CaddyWebBackend, error) {
|
||||
handler := fileserver.FileServer{Root: cfg.WebRoot}
|
||||
handler.Browse = new(fileserver.Browse)
|
||||
|
||||
var handlers []json.RawMessage
|
||||
middlewareRequests = cfg.Requests
|
||||
handlers = append(handlers, caddyconfig.JSONModuleObject(&ZrokRequestsMiddleware{}, "handler", "zrok_requests", nil))
|
||||
handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "file_server", nil))
|
||||
|
||||
route := caddyhttp.Route{HandlersRaw: handlers}
|
||||
|
||||
server := &caddyhttp.Server{
|
||||
ReadHeaderTimeout: caddy.Duration(10 * time.Second),
|
||||
IdleTimeout: caddy.Duration(30 * time.Second),
|
||||
MaxHeaderBytes: 1024 * 10,
|
||||
Routes: caddyhttp.RouteList{route},
|
||||
}
|
||||
server.Listen = []string{fmt.Sprintf("zrok/%s", cfg.ShrToken)}
|
||||
|
||||
httpApp := caddyhttp.App{
|
||||
Servers: map[string]*caddyhttp.Server{"static": server},
|
||||
}
|
||||
|
||||
var false bool
|
||||
caddyCfg := &caddy.Config{
|
||||
Admin: &caddy.AdminConfig{
|
||||
Disabled: true,
|
||||
Config: &caddy.ConfigSettings{
|
||||
Persist: &false,
|
||||
},
|
||||
},
|
||||
AppsRaw: caddy.ModuleMap{
|
||||
"http": caddyconfig.JSON(httpApp, nil),
|
||||
},
|
||||
Logging: &caddy.Logging{
|
||||
Logs: map[string]*caddy.CustomLog{
|
||||
"default": {
|
||||
BaseLog: caddy.BaseLog{
|
||||
Level: zap.ErrorLevel.CapitalString(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if loggingRequests != nil {
|
||||
caddyLog := caddyCfg.Logging.Logs["default"]
|
||||
caddyLog.WriterRaw = caddyconfig.JSONModuleObject(&CaddyLogWriter{}, "output", "zrok_tui", nil)
|
||||
caddyCfg.Logging.Logs["default"] = caddyLog
|
||||
}
|
||||
|
||||
return &CaddyWebBackend{cfg: cfg, caddyCfg: caddyCfg}, nil
|
||||
}
|
||||
|
||||
func (c *CaddyWebBackend) Run() error {
|
||||
return caddy.Run(c.caddyCfg)
|
||||
}
|
||||
|
||||
func (c *CaddyWebBackend) Requests() func() int32 {
|
||||
return func() int32 { return 0 }
|
||||
}
|
81
endpoints/proxy/caddyfileBackend.go
Normal file
@ -0,0 +1,81 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp/fileserver"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
//go:embed browse.html
|
||||
var browseHtml string
|
||||
|
||||
func init() {
|
||||
fileserver.BrowseTemplate = browseHtml
|
||||
}
|
||||
|
||||
type CaddyfileBackendConfig struct {
|
||||
CaddyfilePath string
|
||||
Shr *sdk.Share
|
||||
Requests chan *endpoints.Request
|
||||
}
|
||||
|
||||
type CaddyfileBackend struct {
|
||||
cfg []byte
|
||||
}
|
||||
|
||||
func NewCaddyfileBackend(cfg *CaddyfileBackendConfig) (*CaddyfileBackend, error) {
|
||||
cdyf, err := preprocessCaddyfile(cfg.CaddyfilePath, cfg.Shr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var adapter caddyfile.Adapter
|
||||
adapter.ServerType = httpcaddyfile.ServerType{}
|
||||
caddyCfg, warnings, err := adapter.Adapt([]byte(cdyf), map[string]interface{}{"filename": cfg.CaddyfilePath})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, warning := range warnings {
|
||||
logrus.Warnf("%v [%d] (%v): %v", cfg.CaddyfilePath, warning.Line, warning.Directive, warning.Message)
|
||||
}
|
||||
return &CaddyfileBackend{cfg: caddyCfg}, nil
|
||||
}
|
||||
|
||||
func (b *CaddyfileBackend) Run() error {
|
||||
if err := caddy.Load(b.cfg, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *CaddyfileBackend) Requests() func() int32 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func preprocessCaddyfile(inF string, shr *sdk.Share) (string, error) {
|
||||
input, err := os.ReadFile(inF)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tmpl, err := template.New(inF).Parse(string(input))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output := new(strings.Builder)
|
||||
if err := tmpl.Execute(output, &caddyfileData{ZrokBindAddress: fmt.Sprintf("zrok/%s", shr.Token)}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return output.String(), nil
|
||||
}
|
||||
|
||||
type caddyfileData struct {
|
||||
ZrokBindAddress string
|
||||
}
|
@ -6,9 +6,9 @@ import (
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/notFoundUi"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
@ -40,15 +40,19 @@ type Frontend struct {
|
||||
}
|
||||
|
||||
func NewFrontend(cfg *FrontendConfig) (*Frontend, error) {
|
||||
zCfgPath, err := zrokdir.ZitiIdentityFile(cfg.IdentityName)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from zrokdir", cfg.IdentityName)
|
||||
return nil, errors.Wrap(err, "error loading environment root")
|
||||
}
|
||||
zCfgPath, err := env.ZitiIdentityNamed(cfg.IdentityName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.IdentityName)
|
||||
}
|
||||
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config")
|
||||
}
|
||||
zCfg.ConfigTypes = []string{model.ZrokProxyConfig}
|
||||
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
|
||||
zCtx, err := ziti.NewContext(zCfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti context")
|
||||
@ -117,7 +121,7 @@ func serviceTargetProxy(cfg *FrontendConfig, ctx ziti.Context) *httputil.Reverse
|
||||
director := func(req *http.Request) {
|
||||
targetShrToken := cfg.ShrToken
|
||||
if svc, found := endpoints.GetRefreshedService(targetShrToken, ctx); found {
|
||||
if cfg, found := svc.Config[model.ZrokProxyConfig]; found {
|
||||
if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found {
|
||||
logrus.Debugf("auth model: %v", cfg)
|
||||
} else {
|
||||
logrus.Warn("no config!")
|
||||
@ -149,15 +153,15 @@ func serviceTargetProxy(cfg *FrontendConfig, ctx ziti.Context) *httputil.Reverse
|
||||
func authHandler(shrToken string, handler http.Handler, realm string, cfg *FrontendConfig, ctx ziti.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found {
|
||||
if cfg, found := svc.Config[model.ZrokProxyConfig]; found {
|
||||
if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found {
|
||||
if scheme, found := cfg["auth_scheme"]; found {
|
||||
switch scheme {
|
||||
case string(model.None):
|
||||
case string(sdk.None):
|
||||
logrus.Debugf("auth scheme none '%v'", shrToken)
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
|
||||
case string(model.Basic):
|
||||
case string(sdk.Basic):
|
||||
logrus.Debugf("auth scheme basic '%v", shrToken)
|
||||
inUser, inPass, ok := r.BasicAuth()
|
||||
if !ok {
|
||||
|
@ -1,82 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/pkg/errors"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WebBackendConfig struct {
|
||||
IdentityPath string
|
||||
WebRoot string
|
||||
ShrToken string
|
||||
RequestsChan chan *endpoints.Request
|
||||
}
|
||||
|
||||
type WebBackend struct {
|
||||
cfg *WebBackendConfig
|
||||
listener edge.Listener
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func NewWebBackend(cfg *WebBackendConfig) (*WebBackend, error) {
|
||||
options := ziti.ListenOptions{
|
||||
ConnectTimeout: 5 * time.Minute,
|
||||
MaxConnections: 64,
|
||||
}
|
||||
zcfg, err := ziti.NewConfigFromFile(cfg.IdentityPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config")
|
||||
}
|
||||
zctx, err := ziti.NewContext(zcfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti context")
|
||||
}
|
||||
listener, err := zctx.ListenWithOptions(cfg.ShrToken, &options)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error listening")
|
||||
}
|
||||
|
||||
be := &WebBackend{
|
||||
cfg: cfg,
|
||||
listener: listener,
|
||||
}
|
||||
if cfg.RequestsChan != nil {
|
||||
be.handler = &requestGrabber{requests: cfg.RequestsChan, handler: http.FileServer(http.Dir(cfg.WebRoot))}
|
||||
} else {
|
||||
be.handler = http.FileServer(http.Dir(cfg.WebRoot))
|
||||
}
|
||||
return be, nil
|
||||
}
|
||||
|
||||
func (self *WebBackend) Run() error {
|
||||
if err := http.Serve(self.listener, self.handler); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *WebBackend) Requests() func() int32 {
|
||||
return func() int32 { return 0 }
|
||||
}
|
||||
|
||||
type requestGrabber struct {
|
||||
requests chan *endpoints.Request
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func (rl *requestGrabber) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
if rl.requests != nil {
|
||||
rl.requests <- &endpoints.Request{
|
||||
Stamp: time.Now(),
|
||||
RemoteAddr: fmt.Sprintf("%v", req.Header["X-Real-Ip"]),
|
||||
Method: req.Method,
|
||||
Path: req.URL.String(),
|
||||
}
|
||||
}
|
||||
rl.handler.ServeHTTP(resp, req)
|
||||
}
|
@ -36,7 +36,7 @@ type OauthProviderSecrets struct {
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Identity: "frontend",
|
||||
Identity: "public",
|
||||
Address: "0.0.0.0:8080",
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,15 @@ package publicProxy
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/healthUi"
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/notFoundUi"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
@ -16,9 +25,7 @@ import (
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/healthUi"
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/notFoundUi"
|
||||
"github.com/openziti/zrok/endpoints/publicProxy/unauthorizedUi"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
zhttp "github.com/zitadel/oidc/v2/pkg/http"
|
||||
@ -31,15 +38,19 @@ type httpFrontend struct {
|
||||
}
|
||||
|
||||
func NewHTTP(cfg *Config) (*httpFrontend, error) {
|
||||
zCfgPath, err := zrokdir.ZitiIdentityFile(cfg.Identity)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from zrokdir", cfg.Identity)
|
||||
return nil, errors.Wrap(err, "error loading environment root")
|
||||
}
|
||||
zCfgPath, err := env.ZitiIdentityNamed(cfg.Identity)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.Identity)
|
||||
}
|
||||
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config")
|
||||
}
|
||||
zCfg.ConfigTypes = []string{model.ZrokProxyConfig}
|
||||
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
|
||||
zCtx, err := ziti.NewContext(zCfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti context")
|
||||
@ -102,7 +113,7 @@ func hostTargetReverseProxy(cfg *Config, ctx ziti.Context) *httputil.ReverseProx
|
||||
director := func(req *http.Request) {
|
||||
targetShrToken := resolveService(cfg.HostMatch, req.Host)
|
||||
if svc, found := endpoints.GetRefreshedService(targetShrToken, ctx); found {
|
||||
if cfg, found := svc.Config[model.ZrokProxyConfig]; found {
|
||||
if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found {
|
||||
logrus.Debugf("auth model: %v", cfg)
|
||||
} else {
|
||||
logrus.Warn("no config!")
|
||||
@ -136,15 +147,15 @@ func authHandler(handler http.Handler, realm string, pcfg *Config, ctx ziti.Cont
|
||||
shrToken := resolveService(pcfg.HostMatch, r.Host)
|
||||
if shrToken != "" {
|
||||
if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found {
|
||||
if cfg, found := svc.Config[model.ZrokProxyConfig]; found {
|
||||
if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found {
|
||||
if scheme, found := cfg["auth_scheme"]; found {
|
||||
switch scheme {
|
||||
case string(model.None):
|
||||
case string(sdk.None):
|
||||
logrus.Debugf("auth scheme none '%v'", shrToken)
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
|
||||
case string(model.Basic):
|
||||
case string(sdk.Basic):
|
||||
logrus.Debugf("auth scheme basic '%v", shrToken)
|
||||
inUser, inPass, ok := r.BasicAuth()
|
||||
if !ok {
|
||||
@ -188,7 +199,7 @@ func authHandler(handler http.Handler, realm string, pcfg *Config, ctx ziti.Cont
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
|
||||
case string(model.Oauth):
|
||||
case string(sdk.Oauth):
|
||||
if oauthCfg, found := cfg["oauth"]; found {
|
||||
if provider, found := oauthCfg.(map[string]interface{})["provider"]; found {
|
||||
cookie, err := r.Cookie("zrok-access")
|
||||
|
@ -3,8 +3,8 @@ package tcpTunnel
|
||||
import (
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
@ -29,15 +29,19 @@ func NewFrontend(cfg *FrontendConfig) (*Frontend, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error resolving tcp address '%v'", cfg.BindAddress)
|
||||
}
|
||||
zCfgPath, err := zrokdir.ZitiIdentityFile(cfg.IdentityName)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from zrokdir", cfg.IdentityName)
|
||||
return nil, errors.Wrap(err, "error loading environment root")
|
||||
}
|
||||
zCfgPath, err := env.ZitiIdentityNamed(cfg.IdentityName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.IdentityName)
|
||||
}
|
||||
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config")
|
||||
}
|
||||
zCfg.ConfigTypes = []string{model.ZrokProxyConfig}
|
||||
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
|
||||
zCtx, err := ziti.NewContext(zCfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti context")
|
||||
|
@ -3,8 +3,8 @@ package udpTunnel
|
||||
import (
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/model"
|
||||
"github.com/openziti/zrok/zrokdir"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
@ -99,15 +99,19 @@ func NewFrontend(cfg *FrontendConfig) (*Frontend, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error resolving udp address '%v'", cfg.BindAddress)
|
||||
}
|
||||
zCfgPath, err := zrokdir.ZitiIdentityFile(cfg.IdentityName)
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from zrokdir", cfg.IdentityName)
|
||||
return nil, errors.Wrap(err, "error loading environment root")
|
||||
}
|
||||
zCfgPath, err := env.ZitiIdentityNamed(cfg.IdentityName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.IdentityName)
|
||||
}
|
||||
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config")
|
||||
}
|
||||
zCfg.ConfigTypes = []string{model.ZrokProxyConfig}
|
||||
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
|
||||
zCtx, err := ziti.NewContext(zCfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti context")
|
||||
|
39
environment/api.go
Normal file
@ -0,0 +1,39 @@
|
||||
package environment
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/environment/env_v0_3"
|
||||
"github.com/openziti/zrok/environment/env_v0_4"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func LoadRoot() (env_core.Root, error) {
|
||||
if assert, err := env_v0_4.Assert(); assert && err == nil {
|
||||
return env_v0_4.Load()
|
||||
} else if assert, err := env_v0_3.Assert(); assert && err == nil {
|
||||
return env_v0_3.Load()
|
||||
} else {
|
||||
return env_v0_4.Default()
|
||||
}
|
||||
}
|
||||
|
||||
func IsLatest(r env_core.Root) bool {
|
||||
if r == nil {
|
||||
return false
|
||||
}
|
||||
if r.Metadata() == nil {
|
||||
return false
|
||||
}
|
||||
if r.Metadata().V == env_v0_4.V {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func UpdateRoot(r env_core.Root) (env_core.Root, error) {
|
||||
newR, err := env_v0_4.Update(r)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to update environment")
|
||||
}
|
||||
return newR, nil
|
||||
}
|
43
environment/env_core/model.go
Normal file
@ -0,0 +1,43 @@
|
||||
package env_core
|
||||
|
||||
import "github.com/openziti/zrok/rest_client_zrok"
|
||||
|
||||
// Root is the primary interface encapsulating the on-disk environment data.
|
||||
type Root interface {
|
||||
Metadata() *Metadata
|
||||
Obliterate() error
|
||||
|
||||
HasConfig() (bool, error)
|
||||
Config() *Config
|
||||
SetConfig(cfg *Config) error
|
||||
|
||||
Client() (*rest_client_zrok.Zrok, error)
|
||||
ApiEndpoint() (string, string)
|
||||
|
||||
IsEnabled() bool
|
||||
Environment() *Environment
|
||||
SetEnvironment(env *Environment) error
|
||||
DeleteEnvironment() error
|
||||
|
||||
PublicIdentityName() string
|
||||
EnvironmentIdentityName() string
|
||||
|
||||
ZitiIdentityNamed(name string) (string, error)
|
||||
SaveZitiIdentityNamed(name, data string) error
|
||||
DeleteZitiIdentityNamed(name string) error
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
Token string
|
||||
ZitiIdentity string
|
||||
ApiEndpoint string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ApiEndpoint string
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
V string
|
||||
RootPath string
|
||||
}
|
168
environment/env_v0_3/api.go
Normal file
@ -0,0 +1,168 @@
|
||||
package env_v0_3
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/openziti/zrok/build"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/pkg/errors"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (r *Root) Metadata() *env_core.Metadata {
|
||||
return r.meta
|
||||
}
|
||||
|
||||
func (r *Root) HasConfig() (bool, error) {
|
||||
return r.cfg != nil, nil
|
||||
}
|
||||
|
||||
func (r *Root) Config() *env_core.Config {
|
||||
return r.cfg
|
||||
}
|
||||
|
||||
func (r *Root) SetConfig(cfg *env_core.Config) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := saveConfig(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
r.cfg = cfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) Client() (*rest_client_zrok.Zrok, error) {
|
||||
apiEndpoint, _ := r.ApiEndpoint()
|
||||
apiUrl, err := url.Parse(apiEndpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing api endpoint '%v'", r)
|
||||
}
|
||||
transport := httptransport.New(apiUrl.Host, "/api/v1", []string{apiUrl.Scheme})
|
||||
transport.Producers["application/zrok.v1+json"] = runtime.JSONProducer()
|
||||
transport.Consumers["application/zrok.v1+json"] = runtime.JSONConsumer()
|
||||
|
||||
zrok := rest_client_zrok.New(transport, strfmt.Default)
|
||||
v, err := zrok.Metadata.Version(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting version from api endpoint '%v': %v", apiEndpoint, err)
|
||||
}
|
||||
// allow reported version string to be optionally prefixed with
|
||||
// "refs/heads/" or "refs/tags/"
|
||||
re := regexp.MustCompile(`^(refs/(heads|tags)/)?` + build.Series)
|
||||
if !re.MatchString(string(v.Payload)) {
|
||||
return nil, errors.Errorf("expected a '%v' version, received: '%v'", build.Series, v.Payload)
|
||||
}
|
||||
|
||||
return zrok, nil
|
||||
}
|
||||
|
||||
func (r *Root) ApiEndpoint() (string, string) {
|
||||
apiEndpoint := "https://api.zrok.io"
|
||||
from := "binary"
|
||||
|
||||
if r.Config() != nil && r.Config().ApiEndpoint != "" {
|
||||
apiEndpoint = r.Config().ApiEndpoint
|
||||
from = "config"
|
||||
}
|
||||
|
||||
env := os.Getenv("ZROK_API_ENDPOINT")
|
||||
if env != "" {
|
||||
apiEndpoint = env
|
||||
from = "ZROK_API_ENDPOINT"
|
||||
}
|
||||
|
||||
if r.IsEnabled() {
|
||||
apiEndpoint = r.Environment().ApiEndpoint
|
||||
from = "env"
|
||||
}
|
||||
|
||||
return apiEndpoint, from
|
||||
}
|
||||
|
||||
func (r *Root) Environment() *env_core.Environment {
|
||||
return r.env
|
||||
}
|
||||
|
||||
func (r *Root) SetEnvironment(env *env_core.Environment) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := saveEnvironment(env); err != nil {
|
||||
return err
|
||||
}
|
||||
r.env = env
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) DeleteEnvironment() error {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.Remove(ef); err != nil {
|
||||
return errors.Wrap(err, "error removing environment file")
|
||||
}
|
||||
r.env = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) IsEnabled() bool {
|
||||
return r.env != nil
|
||||
}
|
||||
|
||||
func (r *Root) PublicIdentityName() string {
|
||||
return "frontend"
|
||||
}
|
||||
|
||||
func (r *Root) EnvironmentIdentityName() string {
|
||||
return "backend"
|
||||
}
|
||||
|
||||
func (r *Root) ZitiIdentityNamed(name string) (string, error) {
|
||||
return identityFile(name)
|
||||
}
|
||||
|
||||
func (r *Root) SaveZitiIdentityNamed(name, data string) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
zif, err := r.ZitiIdentityNamed(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(zif), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(zif))
|
||||
}
|
||||
if err := os.WriteFile(zif, []byte(data), os.FileMode(0600)); err != nil {
|
||||
return errors.Wrapf(err, "error writing ziti identity file '%v'", zif)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) DeleteZitiIdentityNamed(name string) error {
|
||||
zif, err := r.ZitiIdentityNamed(name)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting ziti identity file path for '%v'", name)
|
||||
}
|
||||
if err := os.Remove(zif); err != nil {
|
||||
return errors.Wrapf(err, "error removing ziti identity file '%v'", zif)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) Obliterate() error {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.RemoveAll(zrd); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
55
environment/env_v0_3/dirs.go
Normal file
@ -0,0 +1,55 @@
|
||||
package env_v0_3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func rootDir() (string, error) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(home, ".zrok"), nil
|
||||
}
|
||||
|
||||
func metadataFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "metadata.json"), nil
|
||||
}
|
||||
|
||||
func configFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "config.json"), nil
|
||||
}
|
||||
|
||||
func environmentFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "environment.json"), nil
|
||||
}
|
||||
|
||||
func identitiesDir() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "identities"), nil
|
||||
}
|
||||
|
||||
func identityFile(name string) (string, error) {
|
||||
idd, err := identitiesDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(idd, fmt.Sprintf("%v.json", name)), nil
|
||||
}
|
262
environment/env_v0_3/root.go
Normal file
@ -0,0 +1,262 @@
|
||||
package env_v0_3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const V = "v0.3"
|
||||
|
||||
type Root struct {
|
||||
meta *env_core.Metadata
|
||||
cfg *env_core.Config
|
||||
env *env_core.Environment
|
||||
}
|
||||
|
||||
func Assert() (bool, error) {
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if exists {
|
||||
meta, err := loadMetadata()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return meta.V == V, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func Load() (*Root, error) {
|
||||
r := &Root{}
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
if meta, err := loadMetadata(); err == nil {
|
||||
r.meta = meta
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg, err := loadConfig(); err == nil {
|
||||
r.cfg = cfg
|
||||
}
|
||||
|
||||
if env, err := loadEnvironment(); err == nil {
|
||||
r.env = env
|
||||
}
|
||||
|
||||
} else {
|
||||
root, err := rootDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.meta = &env_core.Metadata{
|
||||
V: V,
|
||||
RootPath: root,
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func rootExists() (bool, error) {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, err = os.Stat(mf)
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func assertMetadata() error {
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
if err := writeMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadMetadata() (*env_core.Metadata, error) {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := os.ReadFile(mf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := &metadata{}
|
||||
if err := json.Unmarshal(data, m); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling metadata file '%v'", mf)
|
||||
}
|
||||
if m.V != V {
|
||||
return nil, errors.Errorf("got metadata version '%v', expected '%v'", m.V, V)
|
||||
}
|
||||
rf, err := rootDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := &env_core.Metadata{
|
||||
V: m.V,
|
||||
RootPath: rf,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func writeMetadata() error {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.Marshal(&metadata{V: V})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(mf), os.FileMode(0700)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(mf, data, os.FileMode(0600)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadConfig() (*env_core.Config, error) {
|
||||
cf, err := configFile()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting config file path")
|
||||
}
|
||||
data, err := os.ReadFile(cf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading config file '%v'", cf)
|
||||
}
|
||||
cfg := &config{}
|
||||
if err := json.Unmarshal(data, cfg); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling config file '%v'", cf)
|
||||
}
|
||||
out := &env_core.Config{
|
||||
ApiEndpoint: cfg.ApiEndpoint,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func saveConfig(cfg *env_core.Config) error {
|
||||
in := &config{ApiEndpoint: cfg.ApiEndpoint}
|
||||
data, err := json.MarshalIndent(in, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error marshaling config")
|
||||
}
|
||||
cf, err := configFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting config file path")
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(cf), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(cf))
|
||||
}
|
||||
if err := os.WriteFile(cf, data, os.FileMode(0600)); err != nil {
|
||||
return errors.Wrap(err, "error saving config file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isEnabled() (bool, error) {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error getting environment file path")
|
||||
}
|
||||
_, err = os.Stat(ef)
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "error stat-ing environment file '%v'", ef)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func loadEnvironment() (*env_core.Environment, error) {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
data, err := os.ReadFile(ef)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading environment file '%v'", ef)
|
||||
}
|
||||
env := &environment{}
|
||||
if err := json.Unmarshal(data, env); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling environment file '%v'", ef)
|
||||
}
|
||||
out := &env_core.Environment{
|
||||
Token: env.Token,
|
||||
ZitiIdentity: env.ZId,
|
||||
ApiEndpoint: env.ApiEndpoint,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func saveEnvironment(env *env_core.Environment) error {
|
||||
in := &environment{
|
||||
Token: env.Token,
|
||||
ZId: env.ZitiIdentity,
|
||||
ApiEndpoint: env.ApiEndpoint,
|
||||
}
|
||||
data, err := json.MarshalIndent(in, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error marshaling environment")
|
||||
}
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(ef), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(ef))
|
||||
}
|
||||
if err := os.WriteFile(ef, data, os.FileMode(0600)); err != nil {
|
||||
return errors.Wrap(err, "error saving environment file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteEnvironment() error {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.Remove(ef); err != nil {
|
||||
return errors.Wrap(err, "error removing environment file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type metadata struct {
|
||||
V string `json:"v"`
|
||||
}
|
||||
|
||||
type config struct {
|
||||
ApiEndpoint string `json:"api_endpoint"`
|
||||
}
|
||||
|
||||
type environment struct {
|
||||
Token string `json:"zrok_token"`
|
||||
ZId string `json:"ziti_identity"`
|
||||
ApiEndpoint string `json:"api_endpoint"`
|
||||
}
|
168
environment/env_v0_4/api.go
Normal file
@ -0,0 +1,168 @@
|
||||
package env_v0_4
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/openziti/zrok/build"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/pkg/errors"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (r *Root) Metadata() *env_core.Metadata {
|
||||
return r.meta
|
||||
}
|
||||
|
||||
func (r *Root) HasConfig() (bool, error) {
|
||||
return r.cfg != nil, nil
|
||||
}
|
||||
|
||||
func (r *Root) Config() *env_core.Config {
|
||||
return r.cfg
|
||||
}
|
||||
|
||||
func (r *Root) SetConfig(cfg *env_core.Config) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := saveConfig(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
r.cfg = cfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) Client() (*rest_client_zrok.Zrok, error) {
|
||||
apiEndpoint, _ := r.ApiEndpoint()
|
||||
apiUrl, err := url.Parse(apiEndpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing api endpoint '%v'", r)
|
||||
}
|
||||
transport := httptransport.New(apiUrl.Host, "/api/v1", []string{apiUrl.Scheme})
|
||||
transport.Producers["application/zrok.v1+json"] = runtime.JSONProducer()
|
||||
transport.Consumers["application/zrok.v1+json"] = runtime.JSONConsumer()
|
||||
|
||||
zrok := rest_client_zrok.New(transport, strfmt.Default)
|
||||
v, err := zrok.Metadata.Version(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting version from api endpoint '%v': %v", apiEndpoint, err)
|
||||
}
|
||||
// allow reported version string to be optionally prefixed with
|
||||
// "refs/heads/" or "refs/tags/"
|
||||
re := regexp.MustCompile(`^(refs/(heads|tags)/)?` + build.Series)
|
||||
if !re.MatchString(string(v.Payload)) {
|
||||
return nil, errors.Errorf("expected a '%v' version, received: '%v'", build.Series, v.Payload)
|
||||
}
|
||||
|
||||
return zrok, nil
|
||||
}
|
||||
|
||||
func (r *Root) ApiEndpoint() (string, string) {
|
||||
apiEndpoint := "https://api.zrok.io"
|
||||
from := "binary"
|
||||
|
||||
if r.Config() != nil && r.Config().ApiEndpoint != "" {
|
||||
apiEndpoint = r.Config().ApiEndpoint
|
||||
from = "config"
|
||||
}
|
||||
|
||||
env := os.Getenv("ZROK_API_ENDPOINT")
|
||||
if env != "" {
|
||||
apiEndpoint = env
|
||||
from = "ZROK_API_ENDPOINT"
|
||||
}
|
||||
|
||||
if r.IsEnabled() {
|
||||
apiEndpoint = r.Environment().ApiEndpoint
|
||||
from = "env"
|
||||
}
|
||||
|
||||
return apiEndpoint, from
|
||||
}
|
||||
|
||||
func (r *Root) Environment() *env_core.Environment {
|
||||
return r.env
|
||||
}
|
||||
|
||||
func (r *Root) SetEnvironment(env *env_core.Environment) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := saveEnvironment(env); err != nil {
|
||||
return err
|
||||
}
|
||||
r.env = env
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) DeleteEnvironment() error {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.Remove(ef); err != nil {
|
||||
return errors.Wrap(err, "error removing environment file")
|
||||
}
|
||||
r.env = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) IsEnabled() bool {
|
||||
return r.env != nil
|
||||
}
|
||||
|
||||
func (r *Root) PublicIdentityName() string {
|
||||
return "public"
|
||||
}
|
||||
|
||||
func (r *Root) EnvironmentIdentityName() string {
|
||||
return "environment"
|
||||
}
|
||||
|
||||
func (r *Root) ZitiIdentityNamed(name string) (string, error) {
|
||||
return identityFile(name)
|
||||
}
|
||||
|
||||
func (r *Root) SaveZitiIdentityNamed(name, data string) error {
|
||||
if err := assertMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
zif, err := r.ZitiIdentityNamed(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(zif), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(zif))
|
||||
}
|
||||
if err := os.WriteFile(zif, []byte(data), os.FileMode(0600)); err != nil {
|
||||
return errors.Wrapf(err, "error writing ziti identity file '%v'", zif)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) DeleteZitiIdentityNamed(name string) error {
|
||||
zif, err := r.ZitiIdentityNamed(name)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting ziti identity file path for '%v'", name)
|
||||
}
|
||||
if err := os.Remove(zif); err != nil {
|
||||
return errors.Wrapf(err, "error removing ziti identity file '%v'", zif)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) Obliterate() error {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.RemoveAll(zrd); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
55
environment/env_v0_4/dirs.go
Normal file
@ -0,0 +1,55 @@
|
||||
package env_v0_4
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func rootDir() (string, error) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(home, ".zrok"), nil
|
||||
}
|
||||
|
||||
func metadataFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "metadata.json"), nil
|
||||
}
|
||||
|
||||
func configFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "config.json"), nil
|
||||
}
|
||||
|
||||
func environmentFile() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "environment.json"), nil
|
||||
}
|
||||
|
||||
func identitiesDir() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "identities"), nil
|
||||
}
|
||||
|
||||
func identityFile(name string) (string, error) {
|
||||
idd, err := identitiesDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(idd, fmt.Sprintf("%v.json", name)), nil
|
||||
}
|
333
environment/env_v0_4/root.go
Normal file
@ -0,0 +1,333 @@
|
||||
package env_v0_4
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/environment/env_v0_3"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const V = "v0.4"
|
||||
|
||||
type Root struct {
|
||||
meta *env_core.Metadata
|
||||
cfg *env_core.Config
|
||||
env *env_core.Environment
|
||||
}
|
||||
|
||||
func Default() (*Root, error) {
|
||||
r := &Root{}
|
||||
root, err := rootDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.meta = &env_core.Metadata{
|
||||
V: V,
|
||||
RootPath: root,
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func Assert() (bool, error) {
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if exists {
|
||||
meta, err := loadMetadata()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return meta.V == V, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func Load() (*Root, error) {
|
||||
r := &Root{}
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
if meta, err := loadMetadata(); err == nil {
|
||||
r.meta = meta
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg, err := loadConfig(); err == nil {
|
||||
r.cfg = cfg
|
||||
}
|
||||
|
||||
if env, err := loadEnvironment(); err == nil {
|
||||
r.env = env
|
||||
}
|
||||
|
||||
} else {
|
||||
root, err := Default()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r = root
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func Update(r env_core.Root) (env_core.Root, error) {
|
||||
if r == nil || r.Metadata() == nil {
|
||||
return nil, errors.Errorf("nil root")
|
||||
}
|
||||
if r.Metadata().V != env_v0_3.V {
|
||||
return nil, errors.Errorf("expecting version '%v'", env_v0_3.V)
|
||||
}
|
||||
|
||||
newR := &Root{meta: r.Metadata(), cfg: r.Config(), env: r.Environment()}
|
||||
|
||||
oldAccessF, err := r.ZitiIdentityNamed(r.PublicIdentityName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = os.Stat(oldAccessF)
|
||||
if err == nil {
|
||||
newAccessF, err := newR.ZitiIdentityNamed(newR.PublicIdentityName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.Rename(oldAccessF, newAccessF); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("renamed '%v' -> '%v'\n", oldAccessF, newAccessF)
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldShareF, err := r.ZitiIdentityNamed(r.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = os.Stat(oldShareF)
|
||||
if err == nil {
|
||||
newShareF, err := newR.ZitiIdentityNamed(newR.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.Rename(oldShareF, newShareF); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("renamed '%v' -> '%v'\n", oldShareF, newShareF)
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := writeMetadata(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
meta, err := loadMetadata()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newR.meta = meta
|
||||
|
||||
return newR, nil
|
||||
}
|
||||
|
||||
func rootExists() (bool, error) {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, err = os.Stat(mf)
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func assertMetadata() error {
|
||||
exists, err := rootExists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
if err := writeMetadata(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadMetadata() (*env_core.Metadata, error) {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := os.ReadFile(mf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := &metadata{}
|
||||
if err := json.Unmarshal(data, m); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling metadata file '%v'", mf)
|
||||
}
|
||||
if m.V != V {
|
||||
return nil, errors.Errorf("got metadata version '%v', expected '%v'", m.V, V)
|
||||
}
|
||||
rf, err := rootDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := &env_core.Metadata{
|
||||
V: m.V,
|
||||
RootPath: rf,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func writeMetadata() error {
|
||||
mf, err := metadataFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.Marshal(&metadata{V: V})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(mf), os.FileMode(0700)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(mf, data, os.FileMode(0600)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadConfig() (*env_core.Config, error) {
|
||||
cf, err := configFile()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting config file path")
|
||||
}
|
||||
data, err := os.ReadFile(cf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading config file '%v'", cf)
|
||||
}
|
||||
cfg := &config{}
|
||||
if err := json.Unmarshal(data, cfg); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling config file '%v'", cf)
|
||||
}
|
||||
out := &env_core.Config{
|
||||
ApiEndpoint: cfg.ApiEndpoint,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func saveConfig(cfg *env_core.Config) error {
|
||||
in := &config{ApiEndpoint: cfg.ApiEndpoint}
|
||||
data, err := json.MarshalIndent(in, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error marshaling config")
|
||||
}
|
||||
cf, err := configFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting config file path")
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(cf), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(cf))
|
||||
}
|
||||
if err := os.WriteFile(cf, data, os.FileMode(0600)); err != nil {
|
||||
return errors.Wrap(err, "error saving config file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isEnabled() (bool, error) {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error getting environment file path")
|
||||
}
|
||||
_, err = os.Stat(ef)
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "error stat-ing environment file '%v'", ef)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func loadEnvironment() (*env_core.Environment, error) {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
data, err := os.ReadFile(ef)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading environment file '%v'", ef)
|
||||
}
|
||||
env := &environment{}
|
||||
if err := json.Unmarshal(data, env); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling environment file '%v'", ef)
|
||||
}
|
||||
out := &env_core.Environment{
|
||||
Token: env.Token,
|
||||
ZitiIdentity: env.ZId,
|
||||
ApiEndpoint: env.ApiEndpoint,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func saveEnvironment(env *env_core.Environment) error {
|
||||
in := &environment{
|
||||
Token: env.Token,
|
||||
ZId: env.ZitiIdentity,
|
||||
ApiEndpoint: env.ApiEndpoint,
|
||||
}
|
||||
data, err := json.MarshalIndent(in, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error marshaling environment")
|
||||
}
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(ef), os.FileMode(0700)); err != nil {
|
||||
return errors.Wrapf(err, "error creating environment path '%v'", filepath.Dir(ef))
|
||||
}
|
||||
if err := os.WriteFile(ef, data, os.FileMode(0600)); err != nil {
|
||||
return errors.Wrap(err, "error saving environment file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteEnvironment() error {
|
||||
ef, err := environmentFile()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting environment file")
|
||||
}
|
||||
if err := os.Remove(ef); err != nil {
|
||||
return errors.Wrap(err, "error removing environment file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type metadata struct {
|
||||
V string `json:"v"`
|
||||
}
|
||||
|
||||
type config struct {
|
||||
ApiEndpoint string `json:"api_endpoint"`
|
||||
}
|
||||
|
||||
type environment struct {
|
||||
Token string `json:"zrok_token"`
|
||||
ZId string `json:"ziti_identity"`
|
||||
ApiEndpoint string `json:"api_endpoint"`
|
||||
}
|
7
etc/caddy/multiple_upstream.Caddyfile
Normal file
@ -0,0 +1,7 @@
|
||||
http:// {
|
||||
bind {{ .ZrokBindAddress }}
|
||||
reverse_proxy /zrok/* https://zrok.io
|
||||
reverse_proxy /* 127.0.0.1:3000 {
|
||||
header_up Host localhost:3000
|
||||
}
|
||||
}
|
4
etc/caddy/simple_reverse_proxy.Caddyfile
Normal file
@ -0,0 +1,4 @@
|
||||
http:// {
|
||||
bind {{ .ZrokBindAddress }}
|
||||
reverse_proxy 127.0.0.1:3000
|
||||
}
|
165
go.mod
@ -3,8 +3,7 @@ module github.com/openziti/zrok
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.13
|
||||
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.22.2
|
||||
github.com/caddyserver/caddy/v2 v2.7.5-0.20230829153420-ed8bb13c5df7
|
||||
github.com/charmbracelet/bubbles v0.14.0
|
||||
github.com/charmbracelet/bubbletea v0.23.1
|
||||
github.com/charmbracelet/lipgloss v0.6.0
|
||||
@ -15,6 +14,7 @@ require (
|
||||
github.com/go-openapi/strfmt v0.21.7
|
||||
github.com/go-openapi/swag v0.22.4
|
||||
github.com/go-openapi/validate v0.22.1
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/iancoleman/strcase v0.2.0
|
||||
@ -23,29 +23,30 @@ require (
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.3
|
||||
github.com/jessevdk/go-flags v1.5.0
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/lib/pq v1.10.0
|
||||
github.com/mattn/go-sqlite3 v1.14.14
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/mattn/go-sqlite3 v1.14.15
|
||||
github.com/michaelquigley/cf v0.0.13
|
||||
github.com/michaelquigley/pfxlog v0.6.10
|
||||
github.com/muesli/reflow v0.3.0
|
||||
github.com/nxadm/tail v1.4.8
|
||||
github.com/openziti/channel/v2 v2.0.81
|
||||
github.com/openziti/edge-api v0.25.29
|
||||
github.com/openziti/channel/v2 v2.0.91
|
||||
github.com/openziti/edge-api v0.25.33
|
||||
github.com/openziti/fabric v0.23.26
|
||||
github.com/openziti/identity v1.0.57
|
||||
github.com/openziti/sdk-golang v0.20.67
|
||||
github.com/openziti/transport/v2 v2.0.91
|
||||
github.com/openziti/identity v1.0.60
|
||||
github.com/openziti/sdk-golang v0.20.92
|
||||
github.com/openziti/transport/v2 v2.0.99
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rabbitmq/amqp091-go v1.8.1
|
||||
github.com/rubenv/sql-migrate v1.1.2
|
||||
github.com/shirou/gopsutil/v3 v3.23.5
|
||||
github.com/shirou/gopsutil/v3 v3.23.7
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/wneessen/go-mail v0.2.7
|
||||
github.com/zitadel/oidc/v2 v2.7.0
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/net v0.12.0
|
||||
go.uber.org/zap v1.25.0
|
||||
golang.org/x/crypto v0.12.0
|
||||
golang.org/x/net v0.14.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/time v0.3.0
|
||||
nhooyr.io/websocket v1.8.7
|
||||
@ -54,97 +55,189 @@ require (
|
||||
require (
|
||||
cloud.google.com/go/compute v1.20.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/Jeffail/gabs v1.4.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.7.0 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211106181442-e4c1a74c66bd // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect
|
||||
github.com/caddyserver/certmagic v0.19.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/dgraph-io/badger v1.6.2 // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.0.2 // indirect
|
||||
github.com/go-kit/kit v0.10.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/glog v1.1.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/cel-go v0.15.1 // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.4 // indirect
|
||||
github.com/google/go-tpm v0.3.3 // indirect
|
||||
github.com/google/go-tspi v0.3.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/schema v1.2.0 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kataras/go-events v0.0.3 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/klauspost/compress v1.16.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mastercactapus/proxyprotocol v0.0.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mholt/acmez v1.2.0 // indirect
|
||||
github.com/micromdm/scep/v2 v2.1.0 // indirect
|
||||
github.com/miekg/dns v1.1.55 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.13.0 // indirect
|
||||
github.com/muhlemmer/gu v0.3.1 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/openziti/foundation/v2 v2.0.26 // indirect
|
||||
github.com/openziti/metrics v1.2.27 // indirect
|
||||
github.com/openziti/secretstream v0.1.9 // indirect
|
||||
github.com/openziti/foundation/v2 v2.0.29 // indirect
|
||||
github.com/openziti/metrics v1.2.31 // indirect
|
||||
github.com/openziti/secretstream v0.1.10 // indirect
|
||||
github.com/openziti/storage v0.2.6 // indirect
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
|
||||
github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.2 // indirect
|
||||
github.com/quic-go/quic-go v0.38.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/slackhq/nebula v1.6.1 // indirect
|
||||
github.com/smallstep/certificates v0.24.3-rc.5 // indirect
|
||||
github.com/smallstep/go-attestation v0.4.4-0.20230509120429-e17291421738 // indirect
|
||||
github.com/smallstep/nosql v0.6.0 // indirect
|
||||
github.com/smallstep/truststore v0.12.1 // indirect
|
||||
github.com/speps/go-hashids v2.0.0+incompatible // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stoewer/go-strcase v1.2.0 // indirect
|
||||
github.com/tailscale/tscert v0.0.0-20230509043813-4e9cb4f2b4ad // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/urfave/cli v1.22.14 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yuin/goldmark v1.5.5 // indirect
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.mongodb.org/mongo-driver v1.11.7 // indirect
|
||||
go.mongodb.org/mongo-driver v1.12.1 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.42.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.17.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.17.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.17.0 // indirect
|
||||
go.opentelemetry.io/otel v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.16.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
||||
go.step.sm/cli-utils v0.8.0 // indirect
|
||||
go.step.sm/crypto v0.33.0 // indirect
|
||||
go.step.sm/linkedca v0.20.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/term v0.10.0 // indirect
|
||||
golang.org/x/text v0.11.0 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/term v0.11.0 // indirect
|
||||
golang.org/x/text v0.12.0 // indirect
|
||||
golang.org/x/tools v0.10.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/grpc v1.56.2 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
)
|
||||
|
@ -1,12 +0,0 @@
|
||||
package model
|
||||
|
||||
type Metrics struct {
|
||||
Namespace string
|
||||
Sessions map[string]SessionMetrics
|
||||
}
|
||||
|
||||
type SessionMetrics struct {
|
||||
BytesRead int64
|
||||
BytesWritten int64
|
||||
LastUpdate int64
|
||||
}
|
@ -28,7 +28,7 @@ type ShareRequest struct {
|
||||
AuthUsers []*AuthUser `json:"authUsers"`
|
||||
|
||||
// backend mode
|
||||
// Enum: [proxy web tcpTunnel udpTunnel]
|
||||
// Enum: [proxy web tcpTunnel udpTunnel caddy]
|
||||
BackendMode string `json:"backendMode,omitempty"`
|
||||
|
||||
// backend proxy endpoint
|
||||
@ -114,7 +114,7 @@ var shareRequestTypeBackendModePropEnum []interface{}
|
||||
|
||||
func init() {
|
||||
var res []string
|
||||
if err := json.Unmarshal([]byte(`["proxy","web","tcpTunnel","udpTunnel"]`), &res); err != nil {
|
||||
if err := json.Unmarshal([]byte(`["proxy","web","tcpTunnel","udpTunnel","caddy"]`), &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, v := range res {
|
||||
@ -135,6 +135,9 @@ const (
|
||||
|
||||
// ShareRequestBackendModeUDPTunnel captures enum value "udpTunnel"
|
||||
ShareRequestBackendModeUDPTunnel string = "udpTunnel"
|
||||
|
||||
// ShareRequestBackendModeCaddy captures enum value "caddy"
|
||||
ShareRequestBackendModeCaddy string = "caddy"
|
||||
)
|
||||
|
||||
// prop value enum
|
||||
|
@ -13,6 +13,8 @@ import (
|
||||
"github.com/openziti/zrok/rest_server_zrok/operations"
|
||||
)
|
||||
|
||||
var HealthCheck func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
//go:generate swagger generate server --target ../../zrok --name Zrok --spec ../specs/zrok.yml --model-package rest_model_zrok --server-package rest_server_zrok --principal interface{} --exclude-main
|
||||
|
||||
func configureFlags(api *operations.ZrokAPI) {
|
||||
@ -53,6 +55,5 @@ func setupMiddlewares(handler http.Handler) http.Handler {
|
||||
// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
|
||||
// So this is a good place to plug in a panic handling middleware, logging and metrics.
|
||||
func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
logrus.Infof("configuring")
|
||||
return ui.StaticBuilder(handler)
|
||||
return ui.Middleware(handler, HealthCheck)
|
||||
}
|
||||
|
@ -1509,7 +1509,8 @@ func init() {
|
||||
"proxy",
|
||||
"web",
|
||||
"tcpTunnel",
|
||||
"udpTunnel"
|
||||
"udpTunnel",
|
||||
"caddy"
|
||||
]
|
||||
},
|
||||
"backendProxyEndpoint": {
|
||||
@ -3162,7 +3163,8 @@ func init() {
|
||||
"proxy",
|
||||
"web",
|
||||
"tcpTunnel",
|
||||
"udpTunnel"
|
||||
"udpTunnel",
|
||||
"caddy"
|
||||
]
|
||||
},
|
||||
"backendProxyEndpoint": {
|
||||
|
56
sdk/access.go
Normal file
@ -0,0 +1,56 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func CreateAccess(root env_core.Root, request *AccessRequest) (*Access, error) {
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("environment is not enabled; enable with 'zrok enable' first!")
|
||||
}
|
||||
|
||||
out := share.NewAccessParams()
|
||||
out.Body = &rest_model_zrok.AccessRequest{
|
||||
ShrToken: request.ShareToken,
|
||||
EnvZID: root.Environment().ZitiIdentity,
|
||||
}
|
||||
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
|
||||
|
||||
in, err := zrok.Share.Access(out, auth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to create access")
|
||||
}
|
||||
|
||||
return &Access{Token: in.Payload.FrontendToken, ShareToken: request.ShareToken, BackendMode: BackendMode(in.Payload.BackendMode)}, nil
|
||||
}
|
||||
|
||||
func DeleteAccess(root env_core.Root, acc *Access) error {
|
||||
out := share.NewUnaccessParams()
|
||||
out.Body = &rest_model_zrok.UnaccessRequest{
|
||||
FrontendToken: acc.Token,
|
||||
ShrToken: acc.ShareToken,
|
||||
EnvZID: root.Environment().ZitiIdentity,
|
||||
}
|
||||
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
|
||||
|
||||
_, err = zrok.Share.Unaccess(out, auth)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error deleting access")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,17 +1,9 @@
|
||||
package model
|
||||
package sdk
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
const ZrokProxyConfig = "zrok.proxy.v1"
|
||||
|
||||
type AuthScheme string
|
||||
|
||||
const (
|
||||
None AuthScheme = "none"
|
||||
Basic AuthScheme = "basic"
|
||||
Oauth AuthScheme = "oauth"
|
||||
)
|
||||
|
||||
type ProxyConfig struct {
|
||||
AuthScheme AuthScheme `json:"auth_scheme"`
|
||||
BasicAuth *BasicAuth `json:"basic_auth"`
|
32
sdk/dialer.go
Normal file
@ -0,0 +1,32 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewDialer(shrToken string, root env_core.Root) (edge.Conn, error) {
|
||||
zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting ziti identity path")
|
||||
}
|
||||
|
||||
zcfg, err := ziti.NewConfigFromFile(zif)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti identity")
|
||||
}
|
||||
|
||||
zctx, err := ziti.NewContext(zcfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting ziti context")
|
||||
}
|
||||
|
||||
conn, err := zctx.Dial(shrToken)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error dialing '%v'", shrToken)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
117
sdk/examples/pastebin/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
# "pastebin" SDK Example
|
||||
|
||||
This `pastebin` example is a minimal `zrok` SDK application that implements a wormhole that makes redirecting file contents between multiple `zrok` environments very easy.
|
||||
|
||||
The `pastebin` example is split into two separate commands. The `copyto` command takes a copy buffer from standard input. You can use it like this:
|
||||
|
||||
```
|
||||
$ echo "this is a pastebin test" | copyto
|
||||
access your pastebin using 'pastefrom b46p9j82z81f'
|
||||
```
|
||||
|
||||
And then using another terminal window, you can access your pastebin data like this:
|
||||
|
||||
```
|
||||
$ pastefrom b46p9j82z81f
|
||||
this is a pastebin test
|
||||
```
|
||||
|
||||
## The `copyto` Implementation
|
||||
|
||||
The `copyto` utility is an illustration of how to implement an application that creates a share and exposes it to the `zrok` network. Let's look at each section of the implementation:
|
||||
|
||||
```go
|
||||
data, err := loadData()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
This first block of code is responsible for calling the `loadData` function, which loads the pastebin with data from `os.Stdin`.
|
||||
|
||||
All SDK applications need to load the user's "root" from the `environment` package, like this:
|
||||
|
||||
```go
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
The `root` is a structure that contains all of the user's environment detail and allows the SDK application to access the `zrok` service instance and the underlying OpenZiti network.
|
||||
|
||||
Next, `copyto` will create a `zrok` share:
|
||||
|
||||
```go
|
||||
shr, err := sdk.CreateShare(root, &sdk.ShareRequest{
|
||||
BackendMode: sdk.TcpTunnelBackendMode,
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
Target: "pastebin",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("access your pastebin using 'pastefrom %v'\n", shr.Token)
|
||||
```
|
||||
|
||||
The `sdk.CreateShare` call uses the loaded `environment` root along with the details of the share request (`sdk.ShareRequest`) to create the share that will be used to access the `pastebin`.
|
||||
|
||||
For the `pastebin` application, we're using a `sdk.TcpTunnelBackendMode` backend mode (we're just using a single network connection that implements a reliable byte stream, so TCP works great). Tunnel backends only work with `private` shares as of `zrok` `v0.4`, so we're using `sdk.PrivateShareMode`.
|
||||
|
||||
We'll set the `Target` to be `pastebin`, as that's just metadata describing the application.
|
||||
|
||||
Finally, we emit the share token so the user can access the `pastebin` using the `pastefrom` command.
|
||||
|
||||
Next, we'll use the SDK to create a listener for this share:
|
||||
|
||||
```go
|
||||
listener, err := sdk.NewListener(shr.Token, root)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
The `sdk.NewListener` establishes a network listener for the newly created share. This listener works just like a `net.Listener`.
|
||||
|
||||
Next, we're going to add a shutdown hook so that `copyto` will delete the share when the application is terminated using `^C`:
|
||||
|
||||
```go
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
if err := sdk.DeleteShare(root, shr); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = listener.Close()
|
||||
os.Exit(0)
|
||||
}()
|
||||
```
|
||||
|
||||
This anonymous function runs waiting for a signal to exit. When that is received, it runs the `sdk.DeleteShare` function to remove the share that was created. This is how ephemeral shares work for the `zrok share` commands as well.
|
||||
|
||||
And finally, we run in an infinite loop waiting for requests for the `pastebin` data from the network:
|
||||
|
||||
```go
|
||||
for {
|
||||
if conn, err := listener.Accept(); err == nil {
|
||||
go handle(conn, data)
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## The "pastefrom" Implementation
|
||||
|
||||
The `pastefrom` application works very similarly to `copyto`. The primary difference is that it "dials" the share through the SDK using `sdk.NewDialer`, which returns a `net.Conn`:
|
||||
|
||||
```go
|
||||
conn, err := sdk.NewDialer(shrToken, root)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
When this `sdk.NewDialer` function returns without an error, a bidirectional `net.Conn` has been established between the `copyto` "server" and the `pastefrom` "client". `pastefrom` then just reads the available data from the `net.Conn` and emits it to `os.Stdout`.
|
86
sdk/examples/pastebin/cmd/copyto/main.go
Normal file
@ -0,0 +1,86 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
pfxlog.GlobalInit(logrus.WarnLevel, pfxlog.DefaultOptions())
|
||||
}
|
||||
|
||||
func main() {
|
||||
data, err := loadData()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
shr, err := sdk.CreateShare(root, &sdk.ShareRequest{
|
||||
BackendMode: sdk.TcpTunnelBackendMode,
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
Target: "pastebin",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("access your pastebin using 'pastefrom %v'\n", shr.Token)
|
||||
|
||||
listener, err := sdk.NewListener(shr.Token, root)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
if err := sdk.DeleteShare(root, shr); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = listener.Close()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
for {
|
||||
if conn, err := listener.Accept(); err == nil {
|
||||
go handle(conn, data)
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadData() ([]byte, error) {
|
||||
stat, _ := os.Stdin.Stat()
|
||||
if stat.Mode()&os.ModeCharDevice == 0 {
|
||||
data, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
} else {
|
||||
return nil, errors.New("'copyto' requires input from stdin; direct your paste buffer into stdin")
|
||||
}
|
||||
}
|
||||
|
||||
func handle(conn net.Conn, data []byte) {
|
||||
_, err := conn.Write(data)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
}
|
||||
}
|
48
sdk/examples/pastebin/cmd/pastefrom/main.go
Normal file
@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk"
|
||||
"os"
|
||||
)
|
||||
|
||||
const MAX_PASTE_SIZE = 64 * 1024
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
panic("usage: pastefrom <shrToken>")
|
||||
}
|
||||
shrToken := os.Args[1]
|
||||
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
acc, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: shrToken})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := sdk.DeleteAccess(root, acc); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := sdk.NewDialer(shrToken, root)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = conn.Close()
|
||||
}()
|
||||
|
||||
buf := make([]byte, MAX_PASTE_SIZE)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf(string(buf[:n]))
|
||||
}
|
37
sdk/listener.go
Normal file
@ -0,0 +1,37 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/pkg/errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewListener(shrToken string, root env_core.Root) (edge.Listener, error) {
|
||||
return NewListenerWithOptions(shrToken, root, &ziti.ListenOptions{ConnectTimeout: 30 * time.Second, MaxConnections: 64})
|
||||
}
|
||||
|
||||
func NewListenerWithOptions(shrToken string, root env_core.Root, opts *ziti.ListenOptions) (edge.Listener, error) {
|
||||
zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting ziti identity path")
|
||||
}
|
||||
|
||||
zcfg, err := ziti.NewConfigFromFile(zif)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error loading ziti identity")
|
||||
}
|
||||
|
||||
zctx, err := ziti.NewContext(zcfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting ziti context")
|
||||
}
|
||||
|
||||
listener, err := zctx.ListenWithOptions(shrToken, opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating listener")
|
||||
}
|
||||
|
||||
return listener, nil
|
||||
}
|
65
sdk/model.go
Normal file
@ -0,0 +1,65 @@
|
||||
package sdk
|
||||
|
||||
import "time"
|
||||
|
||||
type BackendMode string
|
||||
|
||||
const (
|
||||
ProxyBackendMode BackendMode = "proxy"
|
||||
WebBackendMode BackendMode = "web"
|
||||
TcpTunnelBackendMode BackendMode = "tcpTunnel"
|
||||
UdpTunnelBackendMode BackendMode = "udpTunnel"
|
||||
CaddyBackendMode BackendMode = "caddy"
|
||||
)
|
||||
|
||||
type ShareMode string
|
||||
|
||||
const (
|
||||
PrivateShareMode ShareMode = "private"
|
||||
PublicShareMode ShareMode = "public"
|
||||
)
|
||||
|
||||
type ShareRequest struct {
|
||||
BackendMode BackendMode
|
||||
ShareMode ShareMode
|
||||
Frontends []string
|
||||
Auth []string
|
||||
Target string
|
||||
OauthProvider string
|
||||
OauthEmailDomains []string
|
||||
OauthAuthorizationCheckInterval time.Duration
|
||||
}
|
||||
|
||||
type Share struct {
|
||||
Token string
|
||||
FrontendEndpoints []string
|
||||
}
|
||||
|
||||
type AccessRequest struct {
|
||||
ShareToken string
|
||||
}
|
||||
|
||||
type Access struct {
|
||||
Token string
|
||||
ShareToken string
|
||||
BackendMode BackendMode
|
||||
}
|
||||
|
||||
type Metrics struct {
|
||||
Namespace string
|
||||
Sessions map[string]SessionMetrics
|
||||
}
|
||||
|
||||
type SessionMetrics struct {
|
||||
BytesRead int64
|
||||
BytesWritten int64
|
||||
LastUpdate int64
|
||||
}
|
||||
|
||||
type AuthScheme string
|
||||
|
||||
const (
|
||||
None AuthScheme = "none"
|
||||
Basic AuthScheme = "basic"
|
||||
Oauth AuthScheme = "oauth"
|
||||
)
|
102
sdk/share.go
Normal file
@ -0,0 +1,102 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CreateShare(root env_core.Root, request *ShareRequest) (*Share, error) {
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("environment is not enabled; enable with 'zrok enable' first!")
|
||||
}
|
||||
|
||||
var err error
|
||||
var out *share.ShareParams
|
||||
|
||||
switch request.ShareMode {
|
||||
case PrivateShareMode:
|
||||
out = newPrivateShare(root, request)
|
||||
case PublicShareMode:
|
||||
out = newPublicShare(root, request)
|
||||
default:
|
||||
return nil, errors.Errorf("unknown share mode '%v'", request.ShareMode)
|
||||
}
|
||||
|
||||
if len(request.Auth) > 0 {
|
||||
out.Body.AuthScheme = string(Basic)
|
||||
for _, pair := range request.Auth {
|
||||
tokens := strings.Split(pair, ":")
|
||||
if len(tokens) == 2 {
|
||||
out.Body.AuthUsers = append(out.Body.AuthUsers, &rest_model_zrok.AuthUser{Username: strings.TrimSpace(tokens[0]), Password: strings.TrimSpace(tokens[1])})
|
||||
} else {
|
||||
return nil, errors.Errorf("invalid username:password pair '%v'", pair)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
|
||||
|
||||
in, err := zrok.Share.Share(out, auth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to create share")
|
||||
}
|
||||
|
||||
return &Share{
|
||||
Token: in.Payload.ShrToken,
|
||||
FrontendEndpoints: in.Payload.FrontendProxyEndpoints,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newPrivateShare(root env_core.Root, request *ShareRequest) *share.ShareParams {
|
||||
req := share.NewShareParams()
|
||||
req.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: root.Environment().ZitiIdentity,
|
||||
ShareMode: string(request.ShareMode),
|
||||
BackendMode: string(request.BackendMode),
|
||||
BackendProxyEndpoint: request.Target,
|
||||
AuthScheme: string(None),
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func newPublicShare(root env_core.Root, request *ShareRequest) *share.ShareParams {
|
||||
req := share.NewShareParams()
|
||||
req.Body = &rest_model_zrok.ShareRequest{
|
||||
EnvZID: root.Environment().ZitiIdentity,
|
||||
ShareMode: string(request.ShareMode),
|
||||
FrontendSelection: request.Frontends,
|
||||
BackendMode: string(request.BackendMode),
|
||||
BackendProxyEndpoint: request.Target,
|
||||
AuthScheme: string(None),
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func DeleteShare(root env_core.Root, shr *Share) error {
|
||||
req := share.NewUnshareParams()
|
||||
req.Body = &rest_model_zrok.UnshareRequest{
|
||||
EnvZID: root.Environment().ZitiIdentity,
|
||||
ShrToken: shr.Token,
|
||||
}
|
||||
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
|
||||
|
||||
_, err = zrok.Share.Unshare(req, auth)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error deleting share")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -971,7 +971,7 @@ definitions:
|
||||
type: string
|
||||
backendMode:
|
||||
type: string
|
||||
enum: ["proxy", "web", "tcpTunnel", "udpTunnel"]
|
||||
enum: ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy"]
|
||||
backendProxyEndpoint:
|
||||
type: string
|
||||
authScheme:
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func StaticBuilder(handler http.Handler) http.Handler {
|
||||
func Middleware(handler http.Handler, healthCheck func(w http.ResponseWriter, r *http.Request)) http.Handler {
|
||||
logrus.Infof("building")
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/api/v1") {
|
||||
@ -17,6 +17,10 @@ func StaticBuilder(handler http.Handler) http.Handler {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.URL.Path, "/health") {
|
||||
healthCheck(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Debugf("directing '%v' to static handler", r.URL.Path)
|
||||
|
16
ui/package-lock.json
generated
@ -6196,9 +6196,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001450",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz",
|
||||
"integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==",
|
||||
"version": "1.0.30001519",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -6207,6 +6207,10 @@
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -24270,9 +24274,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001450",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz",
|
||||
"integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew=="
|
||||
"version": "1.0.30001519",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg=="
|
||||
},
|
||||
"canvas-color-tracker": {
|
||||
"version": "1.1.6",
|
||||
|