Merge branch 'main' into v1_0_0
@ -18,6 +18,10 @@ CHANGE: Refactored API implementation. Cleanup, lint removal, additional data el
|
|||||||
|
|
||||||
CHANGE: Deprecated the `passwords` configuration stanza. The zrok controller and API console now use a hard-coded set of (what we believe to be) reasonable assumptions about password quality (https://github.com/openziti/zrok/issues/834)
|
CHANGE: Deprecated the `passwords` configuration stanza. The zrok controller and API console now use a hard-coded set of (what we believe to be) reasonable assumptions about password quality (https://github.com/openziti/zrok/issues/834)
|
||||||
|
|
||||||
|
## v0.4.48
|
||||||
|
|
||||||
|
FIX: the Python SDK erroneously assumed the enabled zrok environment contained a config.json file, and was changed to only load it if the file was present (https://github.com/openziti/zrok/pull/853/).
|
||||||
|
|
||||||
## v0.4.47
|
## v0.4.47
|
||||||
|
|
||||||
CHANGE: the Docker instance will wait for the ziti container healthy status (contribution from Ben Wong @bwong365 - https://github.com/openziti/zrok/pull/790)
|
CHANGE: the Docker instance will wait for the ziti container healthy status (contribution from Ben Wong @bwong365 - https://github.com/openziti/zrok/pull/790)
|
||||||
|
7
docs/myzrok/_category_.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"label": "myzrok",
|
||||||
|
"position": 50,
|
||||||
|
"link": {
|
||||||
|
"type": "generated-index"
|
||||||
|
}
|
||||||
|
}
|
8
docs/myzrok/custom-domains/_category_.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"label": "Custom Domains",
|
||||||
|
"position": 120,
|
||||||
|
"link": {
|
||||||
|
"type": "doc",
|
||||||
|
"id": "myzrok/custom-domains/index"
|
||||||
|
}
|
||||||
|
}
|
BIN
docs/myzrok/custom-domains/images/myzrok_add_a_record.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
docs/myzrok/custom-domains/images/myzrok_add_cname.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
docs/myzrok/custom-domains/images/myzrok_add_domain.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
docs/myzrok/custom-domains/images/myzrok_domains_page.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
docs/myzrok/custom-domains/images/myzrok_finalize.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
docs/myzrok/custom-domains/images/myzrok_verify_dns.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
docs/myzrok/custom-domains/images/zrok_status.png
Normal file
After Width: | Height: | Size: 17 KiB |
110
docs/myzrok/custom-domains/index.mdx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
---
|
||||||
|
title: Custom Domains
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
[myzrok.io](https://myzrok.io) is a hosted zrok-as-a-service offering that provides a way for you bring a custom DNS name for zrok shares.
|
||||||
|
For example, let's say you own the domain `foo.example.io`, you can leverage zrok custom domains to
|
||||||
|
create ephemeral shares such as: `https://vw8jbg4ijz5g.foo.example.io`
|
||||||
|
or [reserved shares](/concepts/sharing-reserved.md) such as `https://myshare.foo.example.io`.
|
||||||
|
|
||||||
|
Custom domains require a Pro subscription with [myzrok.io](https://myzrok.io).
|
||||||
|
If you don't already have an account, you can sign up for one [here](https://myzrok.io).
|
||||||
|
|
||||||
|
[myzrok.io](https://myzrok.io) provides a guided setup with just a few easy steps!
|
||||||
|
|
||||||
|
1. Bring your own custom domain name
|
||||||
|
2. Create DNS records for certificate validation and traffic routing
|
||||||
|
3. Wait for zrok to validate your records and finalize configuration
|
||||||
|
4. Start sharing!
|
||||||
|
|
||||||
|
Detailed setup instructions are documented below.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
:::note
|
||||||
|
In order to create a custom domain in zrok, **you must already own the domain you want to use.**
|
||||||
|
:::
|
||||||
|
|
||||||
|
During the setup process you will need to create DNS records to validate ownership and to allow a certificate to be issued
|
||||||
|
on behalf of your domain. Once you have your domain registered, you can begin the process of setting up your custom
|
||||||
|
domain with zrok.
|
||||||
|
|
||||||
|
### Create Your Custom Domain
|
||||||
|
|
||||||
|
Log into the myzrok console and access the domains page by clicking on the globe icon in the left navigation menu.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
Click the CREATE button on the top right of the page to get started.
|
||||||
|
When you click the create button you’ll be presented with a form to allow you to enable your custom domain.
|
||||||
|
Enter your domain into the form field and click CREATE. This will begin the process for setting up your custom domain.
|
||||||
|
A new managed TLS certificate will be created to host traffic on your domain's behalf.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This may take a few minutes.
|
||||||
|
You may close the form at this time and come back when your domain is *pending validation.*
|
||||||
|
Once your certificate is ready, you’ll be presented with instructions on how to set up your DNS records.
|
||||||
|
|
||||||
|
### Creating DNS Records
|
||||||
|
|
||||||
|
zrok will host and manage a TLS certificate for the custom domain on your behalf.
|
||||||
|
This process requires a DNS validation record to be created in order to prove ownership of the domain.
|
||||||
|
Follow the prompts in the UI to create a CNAME DNS record with the name and value specified in the UI.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Next, create an A record to direct all DNS requests for your domain to a set of static IPs that are hosted by zrok.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
After you’ve created your records, you can verify that they are configured properly using the instructions provided in the form.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
If the `nslookup` command returns the IP addresses supplied for the A-record entry, then DNS for your domain is resolving properly.
|
||||||
|
|
||||||
|
```
|
||||||
|
nslookup test.foo.example.io
|
||||||
|
Server: 192.168.86.194
|
||||||
|
Address: 192.168.86.194#53
|
||||||
|
|
||||||
|
Non-authoritative answer:
|
||||||
|
Name: test.foo.example.io
|
||||||
|
Address: 99.83.220.186
|
||||||
|
Name: test.foo.example.io
|
||||||
|
Address: 52.223.6.108
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you have created your DNS records, it will take zrok a few minutes to validate that they exist.
|
||||||
|
You can safely close the form until your certificate has been issued.
|
||||||
|
|
||||||
|
### Finalizing Your Custom Domain
|
||||||
|
|
||||||
|
After your records have been validated and your certificate has been issued, click the FINALIZE button within 72 hours to complete your custom domain setup.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
From here, myzrok.io will complete the last few steps of creating your custom domain.
|
||||||
|
This should only take a minute, but if you need to close the form you can find the instructions on how to share your frontend when you return.
|
||||||
|
|
||||||
|
### Start Sharing!
|
||||||
|
Once the Finalize stage has completed, you can start sharing with your custom DNS.
|
||||||
|
|
||||||
|
In order to create shares that utilize your custom DNS, you will need to specify the `--frontend` flag when creating a share,
|
||||||
|
or update your environment configuration to use this new frontend by default.
|
||||||
|
|
||||||
|
```
|
||||||
|
zrok share public --frontend foo-example--goPIhgtJtz
|
||||||
|
```
|
||||||
|
|
||||||
|
You can set the custom frontend as the environment default by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
zrok config set defaultFrontend foo-example--goPIhgtJtz
|
||||||
|
```
|
||||||
|
|
||||||
|
To validate which frontend is being used, use the `zrok status` command, which will identify the default frontend being used:
|
||||||
|
|
||||||
|

|
162
sdk/python/sdk/zrok/zrok/environment/root.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import NamedTuple
|
||||||
|
from .dirs import identityFile, rootDir, configFile, environmentFile, metadataFile
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import zrok_api as zrok
|
||||||
|
from zrok_api.configuration import Configuration
|
||||||
|
import re
|
||||||
|
|
||||||
|
V = "v0.4"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Metadata:
|
||||||
|
V: str = ""
|
||||||
|
RootPath: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Config:
|
||||||
|
ApiEndpoint: str = ""
|
||||||
|
DefaultFrontend: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Environment:
|
||||||
|
Token: str = ""
|
||||||
|
ZitiIdentity: str = ""
|
||||||
|
ApiEndpoint: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ApiEndpoint(NamedTuple):
|
||||||
|
endpoint: str
|
||||||
|
frm: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Root:
|
||||||
|
meta: Metadata = field(default_factory=Metadata)
|
||||||
|
cfg: Config = field(default_factory=Config)
|
||||||
|
env: Environment = field(default_factory=Environment)
|
||||||
|
|
||||||
|
def HasConfig(self) -> bool:
|
||||||
|
return self.cfg != Config()
|
||||||
|
|
||||||
|
def Client(self) -> zrok.ApiClient:
|
||||||
|
apiEndpoint = self.ApiEndpoint()
|
||||||
|
|
||||||
|
cfg = Configuration()
|
||||||
|
cfg.host = apiEndpoint[0] + "/api/v1"
|
||||||
|
cfg.api_key["x-token"] = self.env.Token
|
||||||
|
cfg.api_key_prefix['Authorization'] = 'Bearer'
|
||||||
|
|
||||||
|
zrock_client = zrok.ApiClient(configuration=cfg)
|
||||||
|
v = zrok.MetadataApi(zrock_client).version()
|
||||||
|
# allow reported version string to be optionally prefixed with
|
||||||
|
# "refs/heads/" or "refs/tags/"
|
||||||
|
rxp = re.compile("^(refs/(heads|tags)/)?" + V)
|
||||||
|
if not rxp.match(v):
|
||||||
|
raise Exception("expected a '" + V + "' version, received: '" + v + "'")
|
||||||
|
return zrock_client
|
||||||
|
|
||||||
|
def ApiEndpoint(self) -> ApiEndpoint:
|
||||||
|
apiEndpoint = "https://api.zrok.io"
|
||||||
|
frm = "binary"
|
||||||
|
|
||||||
|
if self.cfg.ApiEndpoint != "":
|
||||||
|
apiEndpoint = self.cfg.ApiEndpoint
|
||||||
|
frm = "config"
|
||||||
|
|
||||||
|
env = os.getenv("ZROK_API_ENDPOINT")
|
||||||
|
if env != "":
|
||||||
|
apiEndpoint = env
|
||||||
|
frm = "ZROK_API_ENDPOINT"
|
||||||
|
|
||||||
|
if self.IsEnabled():
|
||||||
|
apiEndpoint = self.env.ApiEndpoint
|
||||||
|
frm = "env"
|
||||||
|
|
||||||
|
return ApiEndpoint(apiEndpoint.rstrip("/"), frm)
|
||||||
|
|
||||||
|
def IsEnabled(self) -> bool:
|
||||||
|
return self.env != Environment()
|
||||||
|
|
||||||
|
def PublicIdentityName(self) -> str:
|
||||||
|
return "public"
|
||||||
|
|
||||||
|
def EnvironmentIdentityName(self) -> str:
|
||||||
|
return "environment"
|
||||||
|
|
||||||
|
def ZitiIdentityNamed(self, name: str) -> str:
|
||||||
|
return identityFile(name)
|
||||||
|
|
||||||
|
|
||||||
|
def Default() -> Root:
|
||||||
|
r = Root()
|
||||||
|
root = rootDir()
|
||||||
|
r.meta = Metadata(V=V, RootPath=root)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def Assert() -> bool:
|
||||||
|
exists = __rootExists()
|
||||||
|
if exists:
|
||||||
|
meta = __loadMetadata()
|
||||||
|
return meta.V == V
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def Load() -> Root:
|
||||||
|
r = Root()
|
||||||
|
if __rootExists():
|
||||||
|
r.meta = __loadMetadata()
|
||||||
|
r.cfg = __loadConfig()
|
||||||
|
r.env = __loadEnvironment()
|
||||||
|
else:
|
||||||
|
r = Default()
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def __rootExists() -> bool:
|
||||||
|
mf = metadataFile()
|
||||||
|
return os.path.isfile(mf)
|
||||||
|
|
||||||
|
|
||||||
|
def __assertMetadata():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def __loadMetadata() -> Metadata:
|
||||||
|
mf = metadataFile()
|
||||||
|
with open(mf) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return Metadata(V=data["v"])
|
||||||
|
|
||||||
|
|
||||||
|
def __loadConfig() -> Config:
|
||||||
|
cf = configFile()
|
||||||
|
try:
|
||||||
|
with open(cf) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return Config(
|
||||||
|
ApiEndpoint=data.get("api_endpoint", ""),
|
||||||
|
DefaultFrontend=data.get("default_frontend", "")
|
||||||
|
)
|
||||||
|
except (FileNotFoundError, json.JSONDecodeError):
|
||||||
|
return Config(ApiEndpoint="", DefaultFrontend="")
|
||||||
|
|
||||||
|
|
||||||
|
def isEnabled() -> bool:
|
||||||
|
ef = environmentFile()
|
||||||
|
return os.path.isfile(ef)
|
||||||
|
|
||||||
|
|
||||||
|
def __loadEnvironment() -> Environment:
|
||||||
|
ef = environmentFile()
|
||||||
|
with open(ef) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return Environment(
|
||||||
|
Token=data["zrok_token"],
|
||||||
|
ZitiIdentity=data["ziti_identity"],
|
||||||
|
ApiEndpoint=data["api_endpoint"])
|