diff --git a/CHANGELOG.md b/CHANGELOG.md index 177c42fe..16b1e2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) +## 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 CHANGE: the Docker instance will wait for the ziti container healthy status (contribution from Ben Wong @bwong365 - https://github.com/openziti/zrok/pull/790) diff --git a/docs/myzrok/_category_.json b/docs/myzrok/_category_.json new file mode 100644 index 00000000..13e637eb --- /dev/null +++ b/docs/myzrok/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "myzrok", + "position": 50, + "link": { + "type": "generated-index" + } +} diff --git a/docs/myzrok/custom-domains/_category_.json b/docs/myzrok/custom-domains/_category_.json new file mode 100644 index 00000000..ea8a8f1c --- /dev/null +++ b/docs/myzrok/custom-domains/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Custom Domains", + "position": 120, + "link": { + "type": "doc", + "id": "myzrok/custom-domains/index" + } +} diff --git a/docs/myzrok/custom-domains/images/myzrok_add_a_record.png b/docs/myzrok/custom-domains/images/myzrok_add_a_record.png new file mode 100644 index 00000000..751fe3b1 Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_add_a_record.png differ diff --git a/docs/myzrok/custom-domains/images/myzrok_add_cname.png b/docs/myzrok/custom-domains/images/myzrok_add_cname.png new file mode 100644 index 00000000..d079c2a1 Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_add_cname.png differ diff --git a/docs/myzrok/custom-domains/images/myzrok_add_domain.png b/docs/myzrok/custom-domains/images/myzrok_add_domain.png new file mode 100644 index 00000000..ab06b844 Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_add_domain.png differ diff --git a/docs/myzrok/custom-domains/images/myzrok_domains_page.png b/docs/myzrok/custom-domains/images/myzrok_domains_page.png new file mode 100644 index 00000000..170e6a8e Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_domains_page.png differ diff --git a/docs/myzrok/custom-domains/images/myzrok_finalize.png b/docs/myzrok/custom-domains/images/myzrok_finalize.png new file mode 100644 index 00000000..09008be5 Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_finalize.png differ diff --git a/docs/myzrok/custom-domains/images/myzrok_verify_dns.png b/docs/myzrok/custom-domains/images/myzrok_verify_dns.png new file mode 100644 index 00000000..bb689c9d Binary files /dev/null and b/docs/myzrok/custom-domains/images/myzrok_verify_dns.png differ diff --git a/docs/myzrok/custom-domains/images/zrok_status.png b/docs/myzrok/custom-domains/images/zrok_status.png new file mode 100644 index 00000000..d562d5dc Binary files /dev/null and b/docs/myzrok/custom-domains/images/zrok_status.png differ diff --git a/docs/myzrok/custom-domains/index.mdx b/docs/myzrok/custom-domains/index.mdx new file mode 100644 index 00000000..e6057e32 --- /dev/null +++ b/docs/myzrok/custom-domains/index.mdx @@ -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. + +![myzrok_domains_page](images/myzrok_domains_page.png) + + +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. + +![myzrok_add_domain](images/myzrok_add_domain.png) + +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. + +![myzrok_add_cname](images/myzrok_add_cname.png) + +Next, create an A record to direct all DNS requests for your domain to a set of static IPs that are hosted by zrok. + +![myzrok_add_a_record](images/myzrok_add_a_record.png) + +After you’ve created your records, you can verify that they are configured properly using the instructions provided in the form. + +![myzrok_verify_dns](images/myzrok_verify_dns.png) + +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. + +![myzrok_finalize](images/myzrok_finalize.png) + +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: + +![zrok_status](images/zrok_status.png) diff --git a/sdk/python/sdk/zrok/zrok/environment/root.py b/sdk/python/sdk/zrok/zrok/environment/root.py new file mode 100644 index 00000000..ad7ae6ef --- /dev/null +++ b/sdk/python/sdk/zrok/zrok/environment/root.py @@ -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"])